UNPKG

@ledgerhq/coin-algorand

Version:
171 lines (158 loc) 4.88 kB
import network from "@ledgerhq/live-network"; import { getEnv } from "@ledgerhq/live-env"; import { BigNumber } from "bignumber.js"; import { AlgoAssetTransferInfo, AlgoPaymentInfo, AlgoTransaction, AlgoTransactionDetails, } from "./indexer.types"; const LIMIT = 100; // Max nb of transactions per request const BASE_URL = getEnv("API_ALGORAND_BLOCKCHAIN_EXPLORER_API_ENDPOINT"); const INDEXER_URL = `${BASE_URL}/idx2/v2`; const fullUrl = (route: string): string => `${INDEXER_URL}${route}?limit=${LIMIT}`; type ExplorerTransactions = { "current-round": number; "next-token": string; transactions: ExplorerTransaction[]; }; type ExplorerTransaction = { "application-transaction"?: { accounts: string[]; "application-args": string[]; "application-id": number; "foreign-apps": unknown[]; "foreign-assets": number[]; "global-state-schema": { "num-byte-slice": number; "num-uint": number; }; "local-state-schema": { "num-byte-slice": number; "num-uint": number; }; "on-completion": string; }; "asset-transfer-transaction"?: { amount: number; "asset-id": number; "close-amount": number; "close-to"?: string; receiver: string; }; "close-rewards": number; "closing-amount": number; "confirmed-round": number; fee: number; "first-valid": number; "genesis-hash": string; "genesis-id": string; "global-state-delta": { key: string; value: { action: number; uint: number; bytes?: string; }; }[]; id: string; "intra-round-offset": number; "last-valid": number; "local-state-delta": { address: string; delta: { key: string; value: { action: number; uint: number; }; }[]; }[]; note: string; "payment-transaction"?: { amount: number; "close-amount": number; "close-remainder-to"?: string; receiver: string; }; "receiver-rewards": number; "round-time": number; sender: string; "sender-rewards": number; signature: { sig: string; }; "tx-type": string; }; export const getAccountTransactions = async ( address: string, startAt?: number, ): Promise<AlgoTransaction[]> => { const url = fullUrl(`/accounts/${address}/transactions`); let nextToken: string | undefined; let newRawTxs: any[] = []; const mergedTxs: AlgoTransaction[] = []; do { let nextUrl: string = url; if (startAt) { nextUrl = nextUrl.concat(`&min-round=${startAt}`); } if (nextToken) { nextUrl = nextUrl.concat(`&next=${nextToken}`); } const { data }: { data: { transactions: any[] } } = await network<ExplorerTransactions>({ url: nextUrl, }); // FIXME: what is the correct type? Properly type response from api above (data) // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore nextToken = data["next-token"]; newRawTxs = data.transactions; newRawTxs.map(parseRawTransaction).forEach(tx => mergedTxs.push(tx)); } while (newRawTxs.length >= LIMIT); return mergedTxs; }; const parseRawTransaction = (tx: ExplorerTransaction): AlgoTransaction => { let details: AlgoTransactionDetails | undefined = undefined; if (tx["tx-type"] === "pay") { // If "tx-type" is "pay", we know we received a "payment-transaction" const info = tx["payment-transaction"]!; const paymentInfo: AlgoPaymentInfo = { amount: new BigNumber(info.amount), recipientAddress: info.receiver, closeAmount: info["close-amount"] === undefined ? undefined : new BigNumber(info["close-amount"]), closeToAddress: info["close-remainder-to"], }; details = paymentInfo; } else if (tx["tx-type"] === "axfer") { // If "tx-type" is "axfer", we know we received a "asset-transfer-transaction" const info = tx["asset-transfer-transaction"]!; const assetTransferInfo: AlgoAssetTransferInfo = { assetAmount: new BigNumber(info.amount), assetId: info["asset-id"].toString(), assetRecipientAddress: info.receiver, assetSenderAddress: tx.sender, assetCloseAmount: info["close-amount"] === undefined ? undefined : new BigNumber(info["close-amount"]), assetCloseToAddress: info["close-to"], }; details = assetTransferInfo; } return { id: tx.id, timestamp: tx["round-time"].toString(), round: tx["confirmed-round"], senderAddress: tx.sender, senderRewards: new BigNumber(tx["sender-rewards"]), recipientRewards: new BigNumber(tx["receiver-rewards"]), closeRewards: tx["close-rewards"] === undefined ? undefined : new BigNumber(tx["close-rewards"]), closeAmount: tx["closing-amount"] === undefined ? undefined : new BigNumber(tx["closing-amount"]), fee: new BigNumber(tx.fee), note: tx.note, type: tx["tx-type"], details, }; };