nomadex-client
Version:
Client library to programmatically interact with https://voi.nomadex.app
236 lines (235 loc) • 9.92 kB
JavaScript
"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;