@ledgerhq/coin-multiversx
Version:
Ledger MultiversX Coin integration
112 lines • 5.24 kB
JavaScript
import { findTokenById, listTokensForCryptoCurrency } from "@ledgerhq/cryptoassets";
import BigNumber from "bignumber.js";
import { emptyHistoryCache, encodeTokenAccountId } from "@ledgerhq/coin-framework/account/index";
import { mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
import { getESDTOperations, getAccountESDTTokens } from "./api";
import { addPrefixToken, extractTokenId } from "./logic";
async function buildMultiversXESDTTokenAccount({ parentAccountId, accountAddress, token, balance, }) {
const tokenAccountId = encodeTokenAccountId(parentAccountId, token);
const tokenIdentifierHex = extractTokenId(token.id);
const tokenIdentifier = Buffer.from(tokenIdentifierHex, "hex").toString();
const operations = await getESDTOperations(tokenAccountId, accountAddress, tokenIdentifier, 0);
const tokenAccount = {
type: "TokenAccount",
id: tokenAccountId,
parentId: parentAccountId,
token,
operationsCount: operations.length,
operations,
pendingOperations: [],
balance,
spendableBalance: balance,
swapHistory: [],
creationDate: operations.length > 0 ? operations[operations.length - 1].date : new Date(),
balanceHistoryCache: emptyHistoryCache, // calculated in the jsHelpers
};
return tokenAccount;
}
async function syncESDTTokenAccountOperations(tokenAccount, address) {
const oldOperations = tokenAccount?.operations || [];
// Needed for incremental synchronisation
const startAt = oldOperations.length ? Math.floor(oldOperations[0].date.valueOf() / 1000) : 0;
const tokenIdentifierHex = extractTokenId(tokenAccount.token.id);
const tokenIdentifier = Buffer.from(tokenIdentifierHex, "hex").toString();
// Merge new operations with the previously synced ones
const newOperations = await getESDTOperations(tokenAccount.id, address, tokenIdentifier, startAt);
const operations = mergeOps(oldOperations, newOperations);
if (operations === oldOperations)
return tokenAccount;
const copy = { ...tokenAccount };
copy.operations = operations;
copy.operationsCount = operations.length;
return copy;
}
async function MultiversXBuildESDTTokenAccounts({ currency, accountId, accountAddress, existingAccount, syncConfig, }) {
const { blacklistedTokenIds = [] } = syncConfig;
if (listTokensForCryptoCurrency(currency).length === 0) {
return undefined;
}
const tokenAccounts = [];
const existingAccountByTicker = {}; // used for fast lookup
const existingAccountTickers = []; // used to keep track of ordering
if (existingAccount && existingAccount.subAccounts) {
for (const existingSubAccount of existingAccount.subAccounts) {
if (existingSubAccount.type === "TokenAccount") {
const { ticker, id } = existingSubAccount.token;
if (!blacklistedTokenIds.includes(id)) {
existingAccountTickers.push(ticker);
existingAccountByTicker[ticker] = existingSubAccount;
}
}
}
}
const accountESDTs = await getAccountESDTTokens(accountAddress);
for (const esdt of accountESDTs) {
const esdtIdentifierHex = Buffer.from(esdt.identifier).toString("hex");
const token = findTokenById(addPrefixToken(esdtIdentifierHex));
if (token && !blacklistedTokenIds.includes(token.id)) {
let tokenAccount = existingAccountByTicker[token.ticker];
if (!tokenAccount) {
tokenAccount = await buildMultiversXESDTTokenAccount({
parentAccountId: accountId,
accountAddress,
token,
balance: new BigNumber(esdt.balance),
});
}
else {
const inputTokenAccount = tokenAccount;
tokenAccount = await syncESDTTokenAccountOperations(inputTokenAccount, accountAddress);
const balance = new BigNumber(esdt.balance);
if (!balance.eq(tokenAccount.balance)) {
// only recreate the object if balance changed
if (inputTokenAccount === tokenAccount) {
tokenAccount = { ...tokenAccount };
}
tokenAccount.balance = balance;
tokenAccount.spendableBalance = balance;
}
}
if (tokenAccount) {
tokenAccounts.push(tokenAccount);
existingAccountTickers.push(token.ticker);
existingAccountByTicker[token.ticker] = tokenAccount;
}
}
}
// Preserve order of tokenAccounts from the existing token accounts
tokenAccounts.sort((a, b) => {
const i = existingAccountTickers.indexOf(a.token.ticker);
const j = existingAccountTickers.indexOf(b.token.ticker);
if (i === j)
return 0;
if (i < 0)
return 1;
if (j < 0)
return -1;
return i - j;
});
return tokenAccounts;
}
export default MultiversXBuildESDTTokenAccounts;
//# sourceMappingURL=buildSubAccounts.js.map