minswap / sdk

Query Minswap data and build transactions
MIT License
51 stars 20 forks source link

getAmountOut does not return the same amount as the UI (May not be deducting fees) #9

Closed ItsDaveB closed 1 year ago

ItsDaveB commented 1 year ago

I've been testing this adapter, it works really well so far, great work guys, it's extremely valuable. I've been tested this in conjunction with Wingriders Adapter, this actually returns the correct amount and this is mimicked in the UI.

But with this implementation, the getAmountOut function, is returning a quantity much higher than what I am getting in the UI. I assume this amount is excluding any fees, whereas the UI indicates the quantity after fees are taken.

This may be by design so may need some guidance here, @longngn, but without knowing the correct quantity or fee deduction it is difficult for me to estimate a valid swaps quantity output, because of the large difference here, I could potentially offset this with a function to minus of the fees, but I think it would be extremely valuable to indicate its intention either way in documentation or if this function is returning the incorrect value and it should be the amount after fees or something else even better, as this is preventing me from calculating amounts and submitting transactions. Or if I am missing something completely, which could also be the case.

Details. 500 ADA Swap amount, to SUNDAE returns 10613 SUNDAE from this function, however the UI returns 10329 SUNDAE.

image

const amountOfTokenReceived = pool?.getAmountOut(adaAssetId, BigInt(amountToSwap)); image

Happy to provide further details if it helps at all! :)

ItsDaveB commented 1 year ago

I have produced a replication example based on the current example implementation in the readme below. I was doing this slightly differently by storing the pools in json after the initial response, so wanted to test it again without that additional logic. As below.

for (let i = 1; ; i++) { const pools = await this.api.getPools({ page: i }); if (pools.length === 0) { // last page break; } const sundaePool = pools.find((p) => p.assetA === 'lovelace' && p.assetB === '9a9693a9a37912a5097918f97918d15240c92ab729a0b7c4aa144d7753554e444145'); if (sundaePool) { const [a, b] = await this.api.getPoolPrice({ pool: sundaePool }); var amounts = sundaePool.getAmountOut('lovelace', BigInt(500)); // amounts.amoutOut is 10613n console.log(ADA/SUNDAE price: ${a.toString()}; SUNDAE/ADA price: ${b.toString()}); // we can later use this ID to call getPoolById console.log(ADA/MIN pool ID: ${sundaePool.id}); break; } }

ItsDaveB commented 1 year ago

This could also be related to the above, doing a SWAP from ADA to AGIX, again 500 ADA Quantity, the getAmountOut function is actually returning the same amount as the UI interestingly, however as it returns as a bigint without precision like 71874n when formatting using the tokens precision, AGIX being 6 decimals. I receive an incorrect value, I think there it should be 2 decimals to match the UI's figure of 71.87 precision, but not sure if this is 2 decimals across all tokens?

ItsDaveB commented 1 year ago

I have managed to resolve this issue last night, it is actually a non issue after I investigated further and more down to how I was formatting and passing in the amounts, especially when each token varied with its precision but the ADA input amount also needed its 6 decimal precision but represented as a bigint, without this the value returned was completely different, especially tokens with larger precision which also needed converting back, I will add my findings below with an example in hope it helps others when using this package.

ItsDaveB commented 1 year ago

// ADA / TOKEN var amountWithPrecision = ethers.parseUnits(amountToSwap?.toString(), 6); const amountOfTokenReceived = pool?.getAmountOut(adaAssetId, amountWithPrecision); const amountOfTokenReceivedWithPrecision = ethers.formatUnits(amountOfTokenReceived?.amountOut ?? 0, tokenIdToFetch.decimals);

// TOKEN / ADA var amountWithPrecision = ethers.parseUnits(amountToSwap?.toString(), tokenIdToFetch?.decimals); const amountOfAdaReceived = pool?.getAmountOut(tokenIdToFetch?.assetSubject ?? '', amountWithPrecision); const amountOfAdaReceivedWithPrecision = ethers.formatUnits(amountOfAdaReceived?.amountOut ?? '', 6);