import type { Balance, Block, BlockInfo, ListOperationsOptions, Operation, FeeEstimation, TransactionIntent, TransactionValidation, AssetInfo, Page, Stake, Reward, Cursor, CraftedTransaction, Validator, AlpacaApi, } from "@ledgerhq/coin-module-framework/api/index"; import { BridgeApi } from "@ledgerhq/ledger-wallet-framework/api/types"; import network from "@ledgerhq/live-network"; function adaptOp(backendOp: Operation): Operation { const { date } = backendOp.tx; const newDate = new Date(date); return { ...backendOp, value: BigInt(backendOp.value), tx: { ...backendOp.tx, fees: BigInt(backendOp.tx.fees), date: newDate }, }; } const ALPACA_URL = "http://0.0.0.0:3000"; const buildBroadcast = networkFamily => async function broadcast(signedOperation: string): Promise { const { data } = await network< { transactionIdentifier: string; }, { rawTransaction: string; } >({ method: "POST", url: `${ALPACA_URL}/${networkFamily}/transaction/broadcast`, data: { rawTransaction: signedOperation, }, }); return data.transactionIdentifier; }; const buildCombine = networkFamily => async function combine(tx: string, signature: string, pubKey?: string): Promise { const { data } = await network< { signedTransaction: string; }, unknown >({ method: "POST", url: `${ALPACA_URL}/${networkFamily}/transaction/combine`, data: { raw_transaction: tx, signature: signature, pubkey: pubKey, }, }); return data.signedTransaction; }; const buildEstimateFees = networkFamily => async function estimateFees(intent: TransactionIntent): Promise { const { data } = await network<{ fee: string }, unknown>({ method: "POST", url: `${ALPACA_URL}/${networkFamily}/transaction/estimate`, data: { intent: { ...intent, amount: intent.amount.toString(10), }, }, }); return { value: BigInt(data.fee), }; }; const buildValidateIntent = networkFamily => async function validateIntent(transaction: TransactionIntent): Promise { const { data } = await network< { errors: Record; warnings: Record; estimatedFees: bigint; amount: bigint; totalSpent: bigint; }, unknown >({ method: "POST", url: `${ALPACA_URL}/${networkFamily}/transaction/validate`, data: { transaction, }, }); return data; }; const buildGetBalance = (networkFamily: string) => async function getBalance(address: string): Promise { const { data } = await network({ method: "GET", url: `${ALPACA_URL}/${networkFamily}/account/${address}/balance`, }); return [ { value: BigInt(data.value), asset: data.asset, locked: BigInt(data?.locked ?? "0"), }, ]; }; const buildGetNextSequence = (networkFamily: string) => async function getNextSequence(address: string): Promise { const { data } = await network({ method: "GET", url: `${ALPACA_URL}/${networkFamily}/account/${address}/info`, }); return data; }; const buildListOperations = networkFamily => async function listOperations( address: string, { minHeight = 0 }: ListOperationsOptions, ): Promise>> { const { data } = await network<{ operations: Operation[] }, unknown>({ method: "GET", url: `${ALPACA_URL}/${networkFamily}/account/${address}/operations`, data: { from: minHeight, }, }); return { items: data.operations.map(op => adaptOp(op)), next: undefined }; }; const buildLastBlock = networkFamily => async function lastBlock(): Promise { const { data } = await network({ method: "GET", url: `${ALPACA_URL}/${networkFamily}/lastblock`, }); return { height: data.height, time: new Date(data.time), hash: data.hash, }; }; const buildCraftTransaction = networkFamily => async function craftTransaction(intent: TransactionIntent): Promise { const { data } = await network({ method: "POST", url: `${ALPACA_URL}/${networkFamily}/transaction/encode`, data: { intent: { ...intent, amount: intent.amount.toString(10), }, }, }); return data; }; export const getNetworkAlpacaApi = (networkFamily: string) => ({ broadcast: buildBroadcast(networkFamily), combine: buildCombine(networkFamily), validateIntent: buildValidateIntent(networkFamily), estimateFees: buildEstimateFees(networkFamily), getBalance: buildGetBalance(networkFamily), getNextSequence: buildGetNextSequence(networkFamily), listOperations: buildListOperations(networkFamily), lastBlock: buildLastBlock(networkFamily), craftTransaction: buildCraftTransaction(networkFamily), craftRawTransaction: ( _transaction: string, _sender: string, _publicKey: string, _sequence: bigint, ): Promise => { throw new Error("craftRawTransaction is not supported"); }, getBlock(_height): Promise { throw new Error("getBlock is not supported"); }, getBlockInfo(_height: number): Promise { throw new Error("getBlockInfo is not supported"); }, getStakes(_address: string, _cursor?: Cursor): Promise> { throw new Error("getStakes is not supported"); }, getRewards(_address: string, _cursor?: Cursor): Promise> { throw new Error("getRewards is not supported"); }, getValidators(_cursor?: Cursor): Promise> { throw new Error("getValidators is not supported"); }, validateAddress(_address: string): Promise { throw new Error("validateAddress is not supported"); }, }) satisfies AlpacaApi & BridgeApi;