reach-sh / humble-sdk

A Javascript library for interacting with the HumbleSwap DEx
https://app.humble.sh
10 stars 1 forks source link

how can i get 'swap txns' #43

Closed nnnggel closed 2 years ago

nnnggel commented 2 years ago

hi, we want to integrate humble swapping into our project, how can i get:

  1. pool info (input = asa_1_id + asa_2_id)
  2. txns (input = pool info + asa_1_amount) // txns will be sent to frontend user for signing with wallet.

i can do swapping with sdk, but only need the txns(no need to send): https://github.com/reach-sh/humble-sdk/blob/7368e1ebd0223b7c2511260f9169b8fd0b8e45f1/src/api/Trader.Swap.ts#L17

nnnggel commented 2 years ago

or where can i find the docs for native txns assembling( txn + paramater)

MrJackdaw commented 2 years ago

Hey @nnnggel; you don't need to send transactions directly to the user's wallet. The SDK uses the same account abstraction object that you get from @reach-sh/stdlib.

Getting an Account object

When using reach stdlib with Algorand, you can usually use WalletConnect or MyAlgoWallet. Here's how you initialize the SDK with wallet options.

WalletConnect

Using this looks almost exactly the same as MyAlgoWallet, except the wallet fallback object will be { WalletConnect }.\ You will need to install @reach-sh/stdlib@0.1.10-rc.6 separately if you want to use WalletConnect. There's a section here that shows how you could import the WalletConnect object from reach stdlib; just supply it as a wallet fallback as shown above. If you want both WC and MAW as options, consider doing this to get both imports. If you want only MyAlgoWallet, read on.

MyAlgo

You can install and use the MyAlgoConnect package from randlabs when initializing HumbleSDK.

import  { createReachAPI, initHumbleSDK } from "@reach-sh/humble-sdk";
import MyAlgoConnect from "@randlabs/myalgo-connect"; // get this from npm 

initHumbleSDK({
  // include your usual options here (e.g. network), then add this for the wallet:  
  walletFallback: { MyAlgoConnect }
});

const stdlib = createReachAPI()

// Connect the wallet: you should only need to do this once. Store and use this 
// reference wherever the SDK asks for a "ReachAccount" 
const account = await stdlib.getDefaultAccount()

Mnemonic

This is another way to get an account if e.g. you are using a command-line or other windowless environment.

import  { createReachAPI, initHumbleSDK } from "@reach-sh/humble-sdk";

// Initialize SDK WITHOUT wallet options (i.e. what you were doing before)
initHumbleSDK({ ... });

const stdlib = createReachAPI();

// Connect an account using a mnemonic phrase. You can get this from
// e.g. a command-line input or an environment variable
const mnemonic = process.env.MY_MNEMONIC; // string
const account = await stdlib.newAccountFromMnemonic( mnemonic );

Any one of these should allow you to use any part of the SDK.

Using the Account abstraction

Fetching pools

Most operations require pool and/or token data. We recommend using the subscribeToPoolStream function here, though instead of using stdlib.createAccount(), you should supply the account from one of the examples above.

subscribeToPoolStream( account, { ... } )

That function will emit objects that look like this for each pool: you can see both the condensed pool data, as well as the metadata for the tokens in the pool. You will need to store a list of these objects so they can be referenced later.

{
    "pool": {
        "poolAddress": 94291765,
        "poolTokenId": 94291788,
        "mintedLiquidityTokens": 34884660669,
        "n2nn": false,
        "tokenABalance": "3488466.30159452",
        "tokenAFees": "0",
        "tokenAId": 94110718,
        "tokenADecimals": 8,
        "tokenBBalance": "3488467",
        "tokenBFees": "0",
        "tokenBId": 94288609,
        "tokenBDecimals": 0
    },
    "tradeable": true,
    "tokens": [
        {
            "id": 94110718,
            "name": "Hubles",
            "symbol": "HBL",
            "url": "",
            "supply": "50000000",
            "decimals": 8
        },
        {
            "id": 94288609,
            "name": "Kornflakes",
            "symbol": "KORN",
            "url": "",
            "supply": "50000000",
            "decimals": 0
        }
    ]
}

You can now use this object as the pool const shown in the swap examples here. Hope this helps!

nnnggel commented 2 years ago

@MrJackdaw Thank you for your fast reply.

I'm dev of althena(althena.io, a dex aggregator).

Althena consists of two parts: frontend - UI backend - calculation (distribute the proportion of transactions according to the depth of multiple dex)

The process of althena is as follow:

  1. frontend pass asa_1_id/asa_2_id/asa_1_amount to backend
  2. backend get pool infos of multiple dexes -> calculate -> assign different proportions(e.g. 80% in humble + 20% in pact) -> assemble txns of swapping(e.g. 2 humble's + 2 pact's) -> return to frontend
  3. user sign txns which return by above step with wallet(myalgo/algosigner/...)

we will assign part of the amount in humble if it's composable. we will assign all amount in humble if it's not composable. ** we are not using reach.

We're stuck getting humble(swapping) txns, it will be appreciate if you help us resolve the problem.

nnnggel commented 2 years ago

I don't know if it is possible that obtaining txns through humble-sdk exporting (current 'swapTokens' includes assembling txns + sending). or maybe some API ways?

MrJackdaw commented 2 years ago

@nnnggel Sadly, HumbleSwap also doesn't have any backend or API (besides the Algorand blockchain), so the SDK is the only way to access the data. (The front-end DEX also uses HumbleSDK). There also is no way to access the transactions [that need wallet-signing] because they are automatically constructed for us by stdlib from the smart contracts.

Keep in mind that HumbleSDK is bundled with stdlib, so you don't need to separately install the latter. But if you need to build unique transaction groups, I'm not sure that can be done through the SDK 😕

nnnggel commented 2 years ago

get it, thank you.

nnnggel commented 2 years ago

one more question, are swapping transactions of humbleswap composable? e.g. insert an algo transfer transaction befor/after swapping transactions (still in one group)

jeapostrophe commented 2 years ago

That's not what "composable" means. We are composable, because we are ABI-compliant and allow swapping on-chain using the ABI. We do not allow extra transactions in the group.

nnnggel commented 2 years ago

Different perspectives have different understandings of composability. For an aggregator, it's "uncomposable" when it cannot be packaged with other dexes transactions in a group (atomicity transaction).

jeapostrophe commented 2 years ago

If your goal is to do some atomically, then interacting with ABI compliant programs is the most powerful and flexible system. Suppose that X needs 9 txns and Y needs 9 txns, because an atomic group can only contain 16 txns, you will never be able to put these two calls into one atomic group. However, if they are ABI compliant, then you can write a new program, Z, which calls X and then Y. Since you can generate up to 256 txns during the evaluation of a program, you will able to call X and Y atomically by issuing a single call to Z.

jeapostrophe commented 2 years ago

That is the definition of "composability" in all other blockchains and in all other software systems --- https://en.wikipedia.org/wiki/Function_composition and https://en.wikipedia.org/wiki/Function_composition_(computer_science)

MrJackdaw commented 2 years ago

@nnnggel Sorry about the belated response. @jeapostrophe is correct; the best way to interact with the contract directly would be to use the ABI. We will update the SDK docs to reflect this in the future.

In the mean time, these are the contract function signatures for swaps:

"sigs": [
        "Trader_swapAForB(uint64,uint64)(uint64,uint64)",
        "Trader_swapBForA(uint64,uint64)(uint64,uint64)"
    ]

Given a pool A/B, you would call

Both functions expect the same thing:

If the result of the swap is smaller than the second argument you pass in, the transaction will not go through. Does this get you closer to your goal? Please let me know.

nnnggel commented 2 years ago

Thank you both, I have some clues now, atomic composer can combine ABI well.

I noticed that there are two txns in one group when swapping(algo->usdc): the first tx is for transfering algo from user to pool (type=transfer), the second tx is for transfering usdc from pool to user (type=application call).

can you explain the application args in the second tx?

AA== Aw== AAAAAAAAAAA= AwAAAAAAAYagAAAAAAAAcFMAAAAAAAA

https://algoexplorer.io/tx/MVIY2RD4S3EWP4ZBFX7OI32ZRPDEL3CFO6ZWPBO2CINNQ6BGH7CA

jeapostrophe commented 2 years ago

That call didn't use the ABI. You should use the ABI instead