diff --git a/src/api/main/transactions.ts b/src/api/main/transactions.ts index ad3040f..afcfb1c 100644 --- a/src/api/main/transactions.ts +++ b/src/api/main/transactions.ts @@ -15,6 +15,7 @@ import { Token } from './meta.js' import { EvmTransaction, SuiTransaction, + XrplTransaction, StarknetTransaction, } from './txs/index.js' @@ -23,6 +24,7 @@ export { GenericTransactionType, SwapExplorerUrl, SuiTransaction, + XrplTransaction, ReportTransactionRequest, TransactionStatus, CheckApprovalResponse, @@ -133,6 +135,7 @@ export type Transaction = | StarknetTransaction | TonTransaction | SuiTransaction + | XrplTransaction | Transfer /** diff --git a/src/api/main/txs/index.ts b/src/api/main/txs/index.ts index d723702..483e5c9 100644 --- a/src/api/main/txs/index.ts +++ b/src/api/main/txs/index.ts @@ -6,3 +6,4 @@ export * from './tron.js' export * from './starknet.js' export * from './ton.js' export * from './sui.js' +export * from './xrpl.js' diff --git a/src/api/main/txs/xrpl.ts b/src/api/main/txs/xrpl.ts new file mode 100644 index 0000000..fa2ee61 --- /dev/null +++ b/src/api/main/txs/xrpl.ts @@ -0,0 +1,8 @@ +export { + isXrplTransaction, + XrplTransaction, + XrplTrustSetTransactionData, + XrplPaymentTransactionData, + XrplTransactionDataIssuedCurrencyAmount, + XrplTransactionDataMPTAmount, +} from '../../shared/txs/xrpl.js' diff --git a/src/api/shared/meta.ts b/src/api/shared/meta.ts index 9c81079..96e446f 100644 --- a/src/api/shared/meta.ts +++ b/src/api/shared/meta.ts @@ -9,6 +9,7 @@ export type MetaInfoType = | 'SolanaMetaInfo' | 'TransferMetaInfo' | 'SuiMetaInfo' + | 'XRPLMetaInfo' /** * ChainInfoBase @@ -97,15 +98,25 @@ export interface TransferChainInfo extends ChainInfoBase { } /** - * Move Chain Info + * Sui Chain Info * - * @property {MetaInfoType} infoType - equals to SuiMetaInfo for move based blockchains + * @property {MetaInfoType} infoType - equals to SuiMetaInfo for Sui * */ export interface SuiChainInfo extends ChainInfoBase { infoType: 'SuiMetaInfo' } +/** + * Xrpl Chain Info + * + * @property {MetaInfoType} infoType - equals to XrplMetaInfo for XRPL + * + */ +export interface XrplChainInfo extends ChainInfoBase { + infoType: 'XRPLMetaInfo' +} + /** * Cosmos Chain Info - Used for adding experimental chains to keplr if needed * @@ -223,6 +234,7 @@ export type ChainInfo = | SolanaChainInfo | TransferChainInfo | SuiChainInfo + | XrplChainInfo /** * Blockchain Meta Information @@ -307,6 +319,12 @@ export interface SuiBlockchainMeta extends BlockchainMetaBase { info: SuiChainInfo } +export interface XrplBlockchainMeta extends BlockchainMetaBase { + type: TransactionType.XRPL + chainId: string + info: XrplChainInfo +} + export type BlockchainMeta = | EvmBlockchainMeta | CosmosBlockchainMeta @@ -316,6 +334,7 @@ export type BlockchainMeta = | TronBlockchainMeta | TonBlockchainMeta | SuiBlockchainMeta + | XrplBlockchainMeta /** * MessagingProtocol diff --git a/src/api/shared/transactions.ts b/src/api/shared/transactions.ts index 66296fa..6df8b9b 100644 --- a/src/api/shared/transactions.ts +++ b/src/api/shared/transactions.ts @@ -10,6 +10,7 @@ export enum TransactionType { STARKNET = 'STARKNET', TON = 'TON', SUI = 'SUI', + XRPL = 'XRPL', } /** diff --git a/src/api/shared/txs/index.ts b/src/api/shared/txs/index.ts index 0b3fae7..d879696 100644 --- a/src/api/shared/txs/index.ts +++ b/src/api/shared/txs/index.ts @@ -5,3 +5,4 @@ export * from './transfer.js' export * from './starknet.js' export * from './tron.js' export * from './ton.js' +export * from './xrpl.js' diff --git a/src/api/shared/txs/xrpl.ts b/src/api/shared/txs/xrpl.ts new file mode 100644 index 0000000..c157c89 --- /dev/null +++ b/src/api/shared/txs/xrpl.ts @@ -0,0 +1,270 @@ +import { + BaseTransaction as RangoBaseTransaction, + TransactionType, +} from '../../shared/index.js' +export interface XrplTransaction extends RangoBaseTransaction { + type: TransactionType.XRPL + data: Payment | TrustSet +} + +export const isXrplTransaction = (transaction: { + type: TransactionType +}): transaction is XrplTransaction => transaction.type === TransactionType.XRPL + +export type XrplPaymentTransactionData = Payment +export type XrplTrustSetTransactionData = TrustSet +export type XrplTransactionDataIssuedCurrencyAmount = IssuedCurrencyAmount +export type XrplTransactionDataMPTAmount = MPTAmount + +// --------------------------- These types come from xrpl.js directly ------------------------------------------- +// @see https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/models/transactions/payment.ts + +// eslint-disable-next-line @typescript-eslint/no-empty-interface -- no global flags right now, so this is fine +interface GlobalFlags {} + +/** + * Must be a valid account address + */ +type Account = string + +interface Memo { + Memo: { + MemoData?: string + MemoType?: string + MemoFormat?: string + } +} + +interface Signer { + Signer: { + Account: string + TxnSignature: string + SigningPubKey: string + } +} + +/** + * Every transaction has the same set of common fields. + */ +interface BaseTransaction { + /** The unique address of the transaction sender. */ + Account: Account + /** + * The type of transaction. Valid types include: `Payment`, `OfferCreate`, + * `TrustSet`, and many others. + */ + TransactionType: string + /** + * Integer amount of XRP, in drops, to be destroyed as a cost for + * distributing this transaction to the network. Some transaction types have + * different minimum requirements. + */ + Fee?: string + /** + * The sequence number of the account sending the transaction. A transaction + * is only valid if the Sequence number is exactly 1 greater than the previous + * transaction from the same account. The special case 0 means the transaction + * is using a Ticket instead. + */ + Sequence?: number + /** + * Hash value identifying another transaction. If provided, this transaction + * is only valid if the sending account's previously-sent transaction matches + * the provided hash. + */ + AccountTxnID?: string + /** Set of bit-flags for this transaction. */ + Flags?: number | GlobalFlags + /** + * Highest ledger index this transaction can appear in. Specifying this field + * places a strict upper limit on how long the transaction can wait to be + * validated or rejected. + */ + LastLedgerSequence?: number + /** + * Additional arbitrary information used to identify this transaction. + */ + Memos?: Memo[] + /** + * Array of objects that represent a multi-signature which authorizes this + * transaction. + */ + Signers?: Signer[] + /** + * Arbitrary integer used to identify the reason for this payment, or a sender + * on whose behalf this transaction is made. Conventionally, a refund should + * specify the initial payment's SourceTag as the refund payment's + * DestinationTag. + */ + SourceTag?: number + /** + * Hex representation of the public key that corresponds to the private key + * used to sign this transaction. If an empty string, indicates a + * multi-signature is present in the Signers field instead. + */ + SigningPubKey?: string + /** + * The sequence number of the ticket to use in place of a Sequence number. If + * this is provided, Sequence must be 0. Cannot be used with AccountTxnID. + */ + TicketSequence?: number + /** + * The signature that verifies this transaction as originating from the + * account it says it is from. + */ + TxnSignature?: string + /** + * The network id of the transaction. + */ + NetworkID?: number +} + +interface IssuedCurrency { + currency: string + issuer: string +} + +interface IssuedCurrencyAmount extends IssuedCurrency { + value: string +} + +interface MPTAmount { + mpt_issuance_id: string + value: string +} + +type Amount = IssuedCurrencyAmount | string + +interface PathStep { + account?: string + currency?: string + issuer?: string +} + +type Path = PathStep[] + +interface PaymentFlagsInterface extends GlobalFlags { + /** + * Do not use the default path; only use paths included in the Paths field. + * This is intended to force the transaction to take arbitrage opportunities. + * Most clients do not need this. + */ + tfNoRippleDirect?: boolean + /** + * If the specified Amount cannot be sent without spending more than SendMax, + * reduce the received amount instead of failing outright. See Partial. + * Payments for more details. + */ + tfPartialPayment?: boolean + /** + * Only take paths where all the conversions have an input:output ratio that + * is equal or better than the ratio of Amount:SendMax. See Limit Quality for + * details. + */ + tfLimitQuality?: boolean +} + +interface TrustSetFlagsInterface { + /** + * Authorize the other party to hold currency issued by this account. (No + * effect unless using the asfRequireAuth AccountSet flag.) Cannot be unset. + */ + tfSetfAuth?: boolean + /** + * Enable the No Ripple flag, which blocks rippling between two trust lines + * of the same currency if this flag is enabled on both. + */ + tfSetNoRipple?: boolean + /** Disable the No Ripple flag, allowing rippling on this trust line. */ + tfClearNoRipple?: boolean + /** Freeze the trust line. */ + tfSetFreeze?: boolean + /** Unfreeze the trust line. */ + tfClearFreeze?: boolean + /** Deep-Freeze the trustline -- disallow sending and receiving the said IssuedCurrency */ + /** Allowed only if the trustline is already regularly frozen, or if tfSetFreeze is set in the same transaction. */ + tfSetDeepFreeze?: boolean + /** Clear a Deep-Frozen trust line */ + tfClearDeepFreeze?: boolean +} + +/** + * Create or modify a trust line linking two accounts. + * + * @category Transaction Models + */ +interface TrustSet extends BaseTransaction { + TransactionType: 'TrustSet' + /** + * Object defining the trust line to create or modify, in the format of a + * Currency Amount. + */ + LimitAmount: IssuedCurrencyAmount + /** + * Value incoming balances on this trust line at the ratio of this number per + * 1,000,000,000 units. A value of 0 is shorthand for treating balances at + * face value. + */ + QualityIn?: number + /** + * Value outgoing balances on this trust line at the ratio of this number per + * 1,000,000,000 units. A value of 0 is shorthand for treating balances at + * face value. + */ + QualityOut?: number + Flags?: number | TrustSetFlagsInterface +} + +/* + * A Payment transaction represents a transfer of value from one account to + * another. + * + * @category Transaction Models + */ +interface Payment extends BaseTransaction { + TransactionType: 'Payment' + /** + * The amount of currency to deliver. For non-XRP amounts, the nested field + * names MUST be lower-case. If the tfPartialPayment flag is set, deliver up + * to this amount instead. + */ + Amount: Amount | MPTAmount + /** The unique address of the account receiving the payment. */ + Destination: Account + /** + * Arbitrary tag that identifies the reason for the payment to the + * destination, or a hosted recipient to pay. + */ + DestinationTag?: number + /** + * Arbitrary 256-bit hash representing a specific reason or identifier for + * this payment. + */ + InvoiceID?: string + /** + * Array of payment paths to be used for this transaction. Must be omitted + * for XRP-to-XRP transactions. + */ + Paths?: Path[] + /** + * Highest amount of source currency this transaction is allowed to cost, + * including transfer fees, exchange rates, and slippage . Does not include + * the XRP destroyed as a cost for submitting the transaction. For non-XRP + * amounts, the nested field names MUST be lower-case. Must be supplied for + * cross-currency/cross-issue payments. Must be omitted for XRP-to-XRP + * Payments. + */ + SendMax?: Amount | MPTAmount + /** + * Minimum amount of destination currency this transaction should deliver. + * Only valid if this is a partial payment. For non-XRP amounts, the nested + * field names are lower-case. + */ + DeliverMin?: Amount | MPTAmount + /** + * Credentials associated with the sender of this transaction. + * The credentials included must not be expired. + */ + CredentialIDs?: string[] + Flags?: number | PaymentFlagsInterface +} diff --git a/src/execution/index.ts b/src/execution/index.ts index d387da8..4040142 100644 --- a/src/execution/index.ts +++ b/src/execution/index.ts @@ -7,6 +7,7 @@ import { StarknetTransaction, SwapperStatusStep, Transfer as TransferTransaction, + XrplTransaction, } from '../api/main/index.js' import { AmountRestrictionType, @@ -73,6 +74,7 @@ export type SwapStepTransaction = { starknetTransaction: StarknetTransaction | null tonTransaction: TonTransaction | null suiTransaction: SuiTransaction | null + xrplTransaction: XrplTransaction | null } export type SwapStepStatus = {