UNPKG

@ledgerhq/coin-cardano

Version:
117 lines 5.39 kB
import { decodeTokenAccountId, emptyHistoryCache, encodeTokenAccountId, } from "@ledgerhq/coin-framework/account/index"; import keyBy from "lodash/keyBy"; import groupBy from "lodash/groupBy"; import BigNumber from "bignumber.js"; import { findTokenById } from "@ledgerhq/cryptoassets"; import { utils as TyphonUtils } from "@stricahq/typhonjs"; import { mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers"; import { encodeOperationId } from "@ledgerhq/coin-framework/operation"; import { getAccountChange, getMemoFromTx, isHexString } from "./logic"; export const getTokenAssetId = ({ policyId, assetName, }) => `${policyId}${assetName}`; export const decodeTokenAssetId = (id) => { const policyId = id.slice(0, 56); const assetName = id.slice(56); return { policyId, assetName }; }; const encodeTokenCurrencyId = (parentCurrency, assetId) => `${parentCurrency.id}/native/${assetId}`; export const decodeTokenCurrencyId = (id) => { const [parentCurrencyId, type, assetId] = id.split("/"); return { parentCurrencyId, type, assetId, }; }; /** * @returns operations of tokens that are defined in ledgerjs cryptoassets */ const mapTxToTokenAccountOperation = ({ parentAccountId, parentCurrency, newTransactions, accountCredentialsMap, }) => { const operations = []; newTransactions.forEach(tx => { const accountChange = getAccountChange(tx, accountCredentialsMap); accountChange.tokens.forEach(token => { const assetId = getTokenAssetId({ policyId: token.policyId, assetName: token.assetName, }); const tokenCurrencyId = encodeTokenCurrencyId(parentCurrency, assetId); const tokenCurrency = findTokenById(tokenCurrencyId); // skip the unsupported tokens by ledger-live if (tokenCurrency === null || tokenCurrency === undefined) { return; } const tokenAccountId = encodeTokenAccountId(parentAccountId, tokenCurrency); const tokenOperationType = token.amount.lt(0) ? "OUT" : "IN"; const memo = getMemoFromTx(tx); const extra = {}; if (memo) { extra.memo = memo; } const operation = { accountId: tokenAccountId, id: encodeOperationId(tokenAccountId, tx.hash, tokenOperationType), hash: tx.hash, type: tokenOperationType, fee: new BigNumber(tx.fees), value: token.amount.absoluteValue(), senders: tx.inputs.map(i => isHexString(i.address) ? TyphonUtils.getAddressFromHex(Buffer.from(i.address, "hex")).getBech32() : i.address), recipients: tx.outputs.map(o => isHexString(o.address) ? TyphonUtils.getAddressFromHex(Buffer.from(o.address, "hex")).getBech32() : o.address), blockHeight: tx.blockHeight, date: new Date(tx.timestamp), extra, blockHash: undefined, }; operations.push(operation); }); }); return operations; }; export function buildSubAccounts({ initialAccount, parentAccountId, parentCurrency, newTransactions, tokens, accountCredentialsMap, }) { const tokenAccountsById = {}; if (initialAccount && initialAccount.subAccounts) { for (const existingAccount of initialAccount.subAccounts) { if (existingAccount.type === "TokenAccount") { tokenAccountsById[existingAccount.id] = existingAccount; } } } const tokenOperations = mapTxToTokenAccountOperation({ parentAccountId, parentCurrency, newTransactions: newTransactions, accountCredentialsMap, }); const tokenOperationsByAccId = groupBy(tokenOperations, o => o.accountId); const tokensBalanceByAssetId = keyBy(tokens, t => getTokenAssetId(t)); for (const tokenAccountId in tokenOperationsByAccId) { const initialTokenAccount = tokenAccountsById[tokenAccountId]; const oldOperations = initialTokenAccount?.operations || []; const newOperations = tokenOperationsByAccId[tokenAccountId] || []; const operations = mergeOps(oldOperations, newOperations); const { token: tokenCurrency } = decodeTokenAccountId(tokenAccountId); if (tokenCurrency) { const accountBalance = tokensBalanceByAssetId[tokenCurrency.contractAddress]?.amount || new BigNumber(0); const tokenAccount = { type: "TokenAccount", id: tokenAccountId, parentId: parentAccountId, token: tokenCurrency, balance: accountBalance, spendableBalance: accountBalance, creationDate: operations.length > 0 ? operations[operations.length - 1].date : new Date(), operationsCount: operations.length, operations, pendingOperations: [], balanceHistoryCache: emptyHistoryCache, swapHistory: [], }; tokenAccountsById[tokenAccountId] = tokenAccount; } } return Object.values(tokenAccountsById); } //# sourceMappingURL=buildSubAccounts.js.map