UNPKG

@ledgerhq/coin-canton

Version:
136 lines (121 loc) 4.45 kB
import { encodeTokenAccountId, emptyHistoryCache, } from "@ledgerhq/ledger-wallet-framework/account/index"; import { mergeOps } from "@ledgerhq/ledger-wallet-framework/bridge/jsHelpers"; import { encodeOperationId } from "@ledgerhq/ledger-wallet-framework/operation"; import { TokenCurrency } from "@ledgerhq/ledger-wallet-framework/types"; import type { TokenAccount } from "@ledgerhq/types-live"; import { Operation } from "@ledgerhq/types-live"; import BigNumber from "bignumber.js"; import { type TransferProposal } from "../network/gateway"; export type CantonTokenAccount = TokenAccount & { cantonResources: { pendingTransferProposals: TransferProposal[] }; }; export function buildSubAccounts({ accountId, tokenBalances, existingSubAccounts, allOperations, pendingTransferProposals, calTokens, }: { accountId: string; calTokens: Map<string, string>; tokenBalances: Array<{ adminId: string; totalBalance: bigint; spendableBalance: bigint; token: TokenCurrency; }>; existingSubAccounts: TokenAccount[]; allOperations: Operation[]; pendingTransferProposals: TransferProposal[]; }): CantonTokenAccount[] { if (tokenBalances.length === 0) return []; const tokenAccounts: CantonTokenAccount[] = []; const existingAccountByTicker: { [ticker: string]: TokenAccount } = {}; const existingAccountTickers: string[] = []; for (const existingSubAccount of existingSubAccounts) { if (existingSubAccount.type === "TokenAccount") { const { ticker } = existingSubAccount.token; existingAccountTickers.push(ticker); existingAccountByTicker[ticker] = existingSubAccount; } } for (const { totalBalance, spendableBalance, token, adminId } of tokenBalances) { const initialTokenAccount = existingAccountByTicker[token.ticker]; const instrumentId = calTokens.get(token.id) || token.name; // Filter operations for this specific instrument (both id and admin must match) const tokenOperations = allOperations.filter(op => { const extra = op.extra as { instrumentId?: string; instrumentAdmin?: string }; return extra?.instrumentId === instrumentId && extra?.instrumentAdmin === adminId; }); // Filter pending transfer proposals for this specific instrument const tokenPendingTransferProposals = pendingTransferProposals.filter( proposal => proposal.instrument_id === instrumentId && proposal.instrument_admin === adminId, ); const tokenAccount = buildSubAccount({ totalBalance: new BigNumber(totalBalance.toString()), spendableBalance: new BigNumber(spendableBalance.toString()), accountId, initialTokenAccount, parentAccountId: accountId, token, operations: tokenOperations, pendingTransferProposals: tokenPendingTransferProposals, }); if (tokenAccount) tokenAccounts.push(tokenAccount); } return tokenAccounts; } function buildSubAccount({ totalBalance, spendableBalance, accountId, initialTokenAccount, parentAccountId, token, operations, pendingTransferProposals, }: { totalBalance: BigNumber; spendableBalance: BigNumber; accountId: string; initialTokenAccount: TokenAccount | undefined; parentAccountId: string; token: TokenCurrency; operations: Operation[]; pendingTransferProposals: TransferProposal[]; }): CantonTokenAccount { const subAccountId = encodeTokenAccountId(accountId, token); // Merge old operations with new ones and update accountId for sub-account const oldOperations = initialTokenAccount?.operations || []; const newOperations = operations.map(op => ({ ...op, id: encodeOperationId(subAccountId, op.hash, op.type), accountId: subAccountId, })); const mergedOperations = mergeOps(oldOperations, newOperations); const creationDate = mergedOperations.length > 0 ? new Date(Math.min(...mergedOperations.map(op => op.date.getTime()))) : new Date(); return { type: "TokenAccount" as const, id: subAccountId, parentId: parentAccountId, token, balance: totalBalance, spendableBalance, operationsCount: mergedOperations.length, operations: mergedOperations, creationDate, pendingOperations: initialTokenAccount?.pendingOperations || [], balanceHistoryCache: initialTokenAccount?.balanceHistoryCache || emptyHistoryCache, swapHistory: [], cantonResources: { pendingTransferProposals, }, }; }