From 685f1d174a85a19877f90f8bf50d89243df23795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Prudent?= Date: Fri, 31 Jan 2025 14:09:09 +0100 Subject: [PATCH] feat(xrp): add memos and destinationTag to xrp crafts --- libs/coin-framework/src/api/types.ts | 9 +--- .../coin-xrp/src/bridge/signOperation.ts | 2 +- .../coin-xrp/src/logic/craftTransaction.ts | 44 ++++++++++++++++--- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/libs/coin-framework/src/api/types.ts b/libs/coin-framework/src/api/types.ts index b9b7b896c0c1..a03104e44f76 100644 --- a/libs/coin-framework/src/api/types.ts +++ b/libs/coin-framework/src/api/types.ts @@ -24,14 +24,9 @@ export type Transaction = { recipient: string; amount: bigint; fee: bigint; - supplement?: unknown; -}; +} & Record; // Field containing dedicated value for each blockchain -// TODO rename start to minHeight -// and add a `token: string` field to the pagination if we really need to support pagination -// (which is not the case for now) -// for now start is used as a minHeight from which we want to fetch ALL operations -// limit is unused for now +// TODO add a `token: string` field to the pagination if we really need to support pagination (which is not the case for now) // see design document at https://ledgerhq.atlassian.net/wiki/spaces/BE/pages/5446205788/coin-modules+lama-adapter+APIs+refinements export type Pagination = { minHeight: number }; export type Api = { diff --git a/libs/coin-modules/coin-xrp/src/bridge/signOperation.ts b/libs/coin-modules/coin-xrp/src/bridge/signOperation.ts index 16b7c8f5e4df..72c37458a8c2 100644 --- a/libs/coin-modules/coin-xrp/src/bridge/signOperation.ts +++ b/libs/coin-modules/coin-xrp/src/bridge/signOperation.ts @@ -37,7 +37,7 @@ export const buildSignOperation = recipient: transaction.recipient, amount: BigInt(transaction.amount.toString()), fee: BigInt(fee.toString()), - tag: transaction.tag, + destinationTag: transaction.tag, }, publicKey, ); diff --git a/libs/coin-modules/coin-xrp/src/logic/craftTransaction.ts b/libs/coin-modules/coin-xrp/src/logic/craftTransaction.ts index ed36d844ac9e..faa0c8dc6bea 100644 --- a/libs/coin-modules/coin-xrp/src/logic/craftTransaction.ts +++ b/libs/coin-modules/coin-xrp/src/logic/craftTransaction.ts @@ -8,20 +8,34 @@ import { UINT32_MAX, validateTag } from "./utils"; const LEDGER_OFFSET = 20; const { TRANSACTION_TYPES } = XrplDefinitions; +type Memo = { + MemoData?: string; + MemoFormat?: string; + MemoType?: string; +}; +type MemoWrapper = { + Memo: Memo; +}; type XrplTransaction = { TransactionType: keyof typeof TRANSACTION_TYPES; Flags: number; Account: string; Amount: string; Destination: string; - DestinationTag: number | undefined; + DestinationTag?: number; Fee: string; Sequence: number; LastLedgerSequence: number; SigningPubKey?: string; TxnSignature?: string; + Memos?: MemoWrapper[]; }; +type MemoInput = { + data?: string; + format?: string; + type?: string; +}; export async function craftTransaction( account: { address: string; @@ -31,31 +45,49 @@ export async function craftTransaction( recipient: string; amount: bigint; fee: bigint; - tag?: number | null | undefined; + destinationTag?: number | null | undefined; + memos?: MemoInput[]; }, publicKey?: string, ): Promise<{ xrplTransaction: XrplTransaction; serializedTransaction: string; }> { - const tag = transaction.tag ? transaction.tag : undefined; const xrplTransaction: XrplTransaction = { TransactionType: "Payment", Account: account.address, Amount: transaction.amount.toString(), Destination: transaction.recipient, - DestinationTag: tag, Fee: transaction.fee.toString(), Flags: 2147483648, Sequence: account.nextSequenceNumber, LastLedgerSequence: (await getLedgerIndex()) + LEDGER_OFFSET, }; - if (tag) { + function memoMapper(memoInput: MemoInput): MemoWrapper { + const memo: Memo = {}; + if (memoInput.data) { + memo.MemoData = memoInput.data; + } + if (memoInput.format) { + memo.MemoFormat = memoInput.format; + } + if (memoInput.type) { + memo.MemoType = memoInput.type; + } + return { Memo: memo }; + } + + if (transaction.memos) { + xrplTransaction.Memos = transaction.memos.map(memoMapper); + } + + if (transaction.destinationTag) { invariant( - validateTag(new BigNumber(tag)), + validateTag(new BigNumber(transaction.destinationTag)), `tag is set but is not in a valid format, should be between [0 - ${UINT32_MAX.toString()}]`, ); + xrplTransaction.DestinationTag = transaction.destinationTag; } const serializedTransaction = publicKey