UNPKG

nomadex-client

Version:

Client library to programmatically interact with https://voi.nomadex.app

236 lines (235 loc) 9.92 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MyPool = exports.TokenType = void 0; const algosdk_1 = require("algosdk"); const PoolClient_1 = require("./PoolClient"); const MySmartAsset_1 = require("./MySmartAsset"); const SmartAssetClient_1 = require("./SmartAssetClient"); const constants_1 = require("../constants"); const algokit_utils_1 = require("@algorandfoundation/algokit-utils"); var TokenType; (function (TokenType) { TokenType[TokenType["ALGO"] = 0] = "ALGO"; TokenType[TokenType["ASA"] = 1] = "ASA"; TokenType[TokenType["SMART"] = 2] = "SMART"; })(TokenType || (exports.TokenType = TokenType = {})); class MyPool extends MySmartAsset_1.MySmartAsset { constructor(id, network, nodeClient, signer) { super(id, nodeClient, signer); this.id = id; this.poolClient = new PoolClient_1.PoolClient({ id: id, resolveBy: 'id', sender: signer ?? { addr: 'DYX2V5XF4IKOHE55Z63XAHVBJTMYM723HK5WJZ72BDZ5AFEFKJ5YP4DOQQ', signer: (0, algosdk_1.makeEmptyTransactionSigner)(), }, }, nodeClient); this.network = network; this.algod = nodeClient; this.signer = signer; } async buildDepositTxn(token, amount) { if (token.type === 0) { return (0, algosdk_1.makePaymentTxnWithSuggestedParamsFromObject)({ from: this.signer.addr, to: (0, algosdk_1.getApplicationAddress)(this.id), amount: amount, suggestedParams: await this.algod.getTransactionParams().do(), }); } else if (token.type === 1) { return (0, algosdk_1.makeAssetTransferTxnWithSuggestedParamsFromObject)({ assetIndex: token.id, from: this.signer.addr, to: (0, algosdk_1.getApplicationAddress)(this.id), amount: amount, suggestedParams: await this.algod.getTransactionParams().do(), }); } else if (token.type === 2) { const smartAssetClient = new SmartAssetClient_1.SmartAssetClient({ id: token.id, resolveBy: 'id', sender: this.signer, }, this.algod); const { transaction } = await smartAssetClient.arc200Transfer({ to: (0, algosdk_1.getApplicationAddress)(this.id), value: amount, }, { sendParams: { populateAppCallResources: true, skipSending: true, }, }); return transaction; } throw Error(''); } async makeOptinTxns(token) { const params = await this.algod.getTransactionParams().do(); const txns = []; if (token.type === TokenType.ASA) { let isOptedIn = false; try { const info = await this.algod.accountAssetInformation(this.signer.addr, token.id).do(); if (typeof info?.['asset-holding']?.amount !== 'undefined') isOptedIn = true; } catch (e) { if (e) { // } } if (!isOptedIn) { txns.push((0, algosdk_1.makeAssetTransferTxnWithSuggestedParamsFromObject)({ assetIndex: token.id, from: this.signer.addr, to: this.signer.addr, amount: 0, suggestedParams: params, })); } } else if (token.type === TokenType.SMART) { const factoryAddress = (0, algosdk_1.getApplicationAddress)(constants_1.contracts[this.network].poolFcatory); const factoryBalance = await MySmartAsset_1.MySmartAsset.from(token.id, this.algod).arc200BalanceOf(factoryAddress); const userBalance = await MySmartAsset_1.MySmartAsset.from(token.id, this.algod).arc200BalanceOf(this.signer.addr); const getTxns = async (address) => { const client = new SmartAssetClient_1.SmartAssetClient({ id: token.id, resolveBy: 'id', sender: { addr: this.signer.addr, signer: (0, algosdk_1.makeEmptyTransactionSigner)(), }, }, this.algod); return [ (0, algosdk_1.makePaymentTxnWithSuggestedParamsFromObject)({ from: this.signer.addr, to: (0, algosdk_1.getApplicationAddress)(token.id), amount: 28500, suggestedParams: params, note: crypto.getRandomValues(new Uint8Array(4)) }), (await client.arc200Transfer({ to: address, value: 0 }, { sendParams: { skipSending: true } })) .transaction, ]; }; if (factoryBalance < 1n) { txns.push(...(await getTxns(factoryAddress))); } if (userBalance < 1n) { txns.push(...(await getTxns(this.signer.addr))); } } return txns; } async addLiquidityHandler(tokenA, tokenB, assetAAmount, assetBAmount, send, populate) { const opts = { id: this.id, resolveBy: 'id', sender: { ...this.signer }, }; const alphaTxn = await this.buildDepositTxn(tokenA, assetAAmount); const betaTxn = await this.buildDepositTxn(tokenB, assetBAmount); const args = { alphaTxn, betaTxn }; const callOpts = { sendParams: { populateAppCallResources: populate, skipSending: !send, }, }; if (!send) opts.sender.signer = (0, algosdk_1.makeEmptyTransactionSigner)(); const poolClient = new PoolClient_1.PoolClient(opts, this.algod); const resp = await poolClient.addLiquidity(args, callOpts); return resp; } async addLiquidity(tokenA, tokenB, assetAAmount, assetBAmount) { const result = await this.addLiquidityHandler(tokenA, tokenB, assetAAmount, assetBAmount, true, true); return result.return; } async buildAddLiquidityTxns(tokenA, tokenB, assetAAmount, assetBAmount, populate) { const result = await this.addLiquidityHandler(tokenA, tokenB, assetAAmount, assetBAmount, false, populate); return result.transactions; } async removeLiquidityHandler(lptAmount, send, populate) { const opts = { id: this.id, resolveBy: 'id', sender: { ...this.signer }, }; const args = { lptAmount: lptAmount }; const callOpts = { sendParams: { populateAppCallResources: true, skipSending: !send }, }; if (!send) opts.sender.signer = (0, algosdk_1.makeEmptyTransactionSigner)(); const poolClient = new PoolClient_1.PoolClient(opts, this.algod); const resp = await poolClient.removeLiquidity(args, callOpts); return resp; } async removeLiquidity(lptAmount) { const result = await this.removeLiquidityHandler(lptAmount, true, true); return result.return; } async buildRemoveLiquidityTxns(lptAmount, populate) { const result = await this.removeLiquidityHandler(lptAmount, false, populate); return result.transactions; } async swap(fromToken, toToken, fromAmount, toAmountMin, isDirectionAlphaToBeta) { const finalTxns = await this.buildSwapTxns(fromToken, toToken, fromAmount, toAmountMin, isDirectionAlphaToBeta, true); const signed = await this.signer.signer(finalTxns, []); await this.algod.sendRawTransaction(signed).do(); const result = await (0, algosdk_1.waitForConfirmation)(this.algod, finalTxns.at(-1)?.txID() ?? '', 3); const log = result.logs.find((log) => log.length === 36); if (log) { return algosdk_1.ABIType.from('uint256').decode(log.slice(4)); } } async buildSwapTxns(fromToken, toToken, fromAmount, toAmountMin, isDirectionAlphaToBeta, populate) { const poolClient = new PoolClient_1.PoolClient({ id: this.id, resolveBy: 'id', sender: this.signer, }, this.algod); const args = { txn: await this.buildDepositTxn(fromToken, fromAmount), minAmount: toAmountMin, }; const txns = []; const optinTxns = await this.makeOptinTxns(toToken); txns.push(...optinTxns); if (isDirectionAlphaToBeta) { const { transactions } = await poolClient.swapAlphaToBeta({ alphaTxn: args.txn, minBetaAmount: args.minAmount, }, { sendParams: { skipSending: true }, }); txns.push(...transactions); } else { const { transactions } = await poolClient.swapBetaToAlpha({ betaTxn: args.txn, minAlphaAmount: args.minAmount, }, { sendParams: { skipSending: true }, }); txns.push(...transactions); } let atc = new algosdk_1.AtomicTransactionComposer(); const mpt = (0, algosdk_1.makeEmptyTransactionSigner)(); for (const txn of txns) { txn.group = undefined; atc.addTransaction({ txn: txn, signer: mpt }); } atc.buildGroup(); if (populate) { atc = await (0, algokit_utils_1.populateAppCallResources)(atc, this.algod); } return atc.buildGroup().map(({ txn }) => txn); } } exports.MyPool = MyPool;