diff --git a/modules/sdk-coin-xrp/src/lib/iface.ts b/modules/sdk-coin-xrp/src/lib/iface.ts index 6162942f31..4a5dc607a8 100644 --- a/modules/sdk-coin-xrp/src/lib/iface.ts +++ b/modules/sdk-coin-xrp/src/lib/iface.ts @@ -5,7 +5,7 @@ import { VerifyAddressOptions as BaseVerifyAddressOptions, TransactionPrebuild, } from '@bitgo/sdk-core'; -import { AccountSet, Payment, Signer, SignerEntry, SignerListSet, Amount } from 'xrpl'; +import { AccountSet, Payment, Signer, SignerEntry, SignerListSet, Amount, TrustSet } from 'xrpl'; export enum XrpTransactionType { AccountSet = 'AccountSet', @@ -15,7 +15,7 @@ export enum XrpTransactionType { TokenPayment = 'TokenPayment', } -export type XrpTransaction = Payment | AccountSet | SignerListSet; +export type XrpTransaction = Payment | AccountSet | SignerListSet | TrustSet; export interface Address { address: string; diff --git a/modules/sdk-coin-xrp/src/lib/index.ts b/modules/sdk-coin-xrp/src/lib/index.ts index b37b1a20be..7727ab648c 100644 --- a/modules/sdk-coin-xrp/src/lib/index.ts +++ b/modules/sdk-coin-xrp/src/lib/index.ts @@ -9,5 +9,6 @@ export { TransactionBuilder } from './transactionBuilder'; export { TransactionBuilderFactory } from './transactionBuilderFactory'; export { TransferBuilder } from './transferBuilder'; export { TokenTransferBuilder } from './tokenTransferBuilder'; +export { TrustSetBuilder } from './trustsetBuilder'; export { WalletInitializationBuilder } from './walletInitializationBuilder'; export { Utils }; diff --git a/modules/sdk-coin-xrp/src/lib/transaction.ts b/modules/sdk-coin-xrp/src/lib/transaction.ts index 4fed1413c1..ca8aa60803 100644 --- a/modules/sdk-coin-xrp/src/lib/transaction.ts +++ b/modules/sdk-coin-xrp/src/lib/transaction.ts @@ -110,6 +110,9 @@ export class Transaction extends BaseTransaction { txData.signerEntries = this._xrpTransaction.SignerEntries; return txData; + case XrpTransactionType.TrustSet: + return txData; + default: throw new InvalidTransactionError('Invalid transaction type'); } @@ -299,6 +302,8 @@ export class Transaction extends BaseTransaction { return XrpTransactionType.AccountSet; case XrpTransactionType.SignerListSet: return XrpTransactionType.SignerListSet; + case XrpTransactionType.TrustSet: + return XrpTransactionType.TrustSet; default: throw new InvalidTransactionError(`Invalid TransactionType: ${xrpTransaction.TransactionType}`); } @@ -351,6 +356,9 @@ export class Transaction extends BaseTransaction { case XrpTransactionType.TokenPayment: this.setTransactionType(TransactionType.SendToken); break; + case XrpTransactionType.TrustSet: + this.setTransactionType(TransactionType.TrustLine); + break; } this.loadInputsAndOutputs(); } diff --git a/modules/sdk-coin-xrp/src/lib/transactionBuilderFactory.ts b/modules/sdk-coin-xrp/src/lib/transactionBuilderFactory.ts index 217bb45f48..b4f3417e61 100644 --- a/modules/sdk-coin-xrp/src/lib/transactionBuilderFactory.ts +++ b/modules/sdk-coin-xrp/src/lib/transactionBuilderFactory.ts @@ -8,6 +8,7 @@ import { TransferBuilder } from './transferBuilder'; import utils from './utils'; import { WalletInitializationBuilder } from './walletInitializationBuilder'; import { TokenTransferBuilder } from './tokenTransferBuilder'; +import { TrustSetBuilder } from './trustsetBuilder'; export class TransactionBuilderFactory extends BaseTransactionBuilderFactory { constructor(_coinConfig: Readonly) { @@ -35,6 +36,8 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory { return this.getWalletInitializationBuilder(tx); case TransactionType.SendToken: return this.getTokenTransferBuilder(tx); + case TransactionType.TrustLine: + return this.getTrustSetBuilder(tx); default: throw new InvalidTransactionError('Invalid transaction'); } @@ -63,6 +66,11 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory { return this.initializeBuilder(tx, new TokenTransferBuilder(this._coinConfig)); } + /** @inheritdoc */ + public getTrustSetBuilder(tx?: Transaction): TrustSetBuilder { + return this.initializeBuilder(tx, new TrustSetBuilder(this._coinConfig)); + } + /** * Initialize the builder with the given transaction * diff --git a/modules/sdk-coin-xrp/src/lib/trustsetBuilder.ts b/modules/sdk-coin-xrp/src/lib/trustsetBuilder.ts new file mode 100644 index 0000000000..cfe269e0d1 --- /dev/null +++ b/modules/sdk-coin-xrp/src/lib/trustsetBuilder.ts @@ -0,0 +1,77 @@ +import { TransactionBuilder } from './transactionBuilder'; +import { BaseCoin as CoinConfig } from '@bitgo/statics'; +import { BuildTransactionError, TransactionType } from '@bitgo/sdk-core'; +import { XrpTransactionType } from './iface'; +import { Amount, IssuedCurrencyAmount, TrustSet } from 'xrpl'; +import { Transaction } from './transaction'; +import _ from 'lodash'; + +export class TrustSetBuilder extends TransactionBuilder { + private _amount: IssuedCurrencyAmount; + + constructor(_coinConfig: Readonly) { + super(_coinConfig); + } + + protected get transactionType(): TransactionType { + return TransactionType.TrustLine; + } + + protected get xrpTransactionType(): XrpTransactionType.TrustSet { + return XrpTransactionType.TrustSet; + } + + initBuilder(tx: Transaction): void { + super.initBuilder(tx); + + const { destination, amount } = tx.toJson(); + if (!destination) { + throw new BuildTransactionError('Missing destination'); + } + if (!amount) { + throw new BuildTransactionError('Missing amount'); + } + + this.amount(amount); + } + + /** + * Set the amount to send + * @param {string} amount - the amount sent + * @returns {TransactionBuilder} This transaction builder + */ + amount(amount: Amount): TransactionBuilder { + function isIssuedCurrencyAmount(amount: Amount): amount is IssuedCurrencyAmount { + return ( + !_.isString(amount) && + _.isObjectLike(amount) && + _.isString(amount.currency) && + _.isString(amount.issuer) && + _.isString(amount.value) + ); + } + + if (!isIssuedCurrencyAmount(amount)) { + throw new Error(`amount type ${typeof amount} must be a IssuedCurrencyAmount type`); + } + this._amount = amount; + return this; + } + + /** @inheritdoc */ + protected async buildImplementation(): Promise { + if (!this._sender) { + throw new BuildTransactionError('Sender must be set before building the transaction'); + } + + const transferFields: TrustSet = { + TransactionType: this.xrpTransactionType, + Account: this._sender, + LimitAmount: this._amount, + }; + + this._specificFields = transferFields; + + return await super.buildImplementation(); + } +} diff --git a/modules/sdk-core/src/account-lib/baseCoin/enum.ts b/modules/sdk-core/src/account-lib/baseCoin/enum.ts index fae95feeaa..7f92275ce3 100644 --- a/modules/sdk-core/src/account-lib/baseCoin/enum.ts +++ b/modules/sdk-core/src/account-lib/baseCoin/enum.ts @@ -71,6 +71,7 @@ export enum TransactionType { CloseAssociatedTokenAccount, SingleNominatorWithdraw, SendToken, + TrustLine, } /** diff --git a/package.json b/package.json index 210583be2b..65370ddcb9 100644 --- a/package.json +++ b/package.json @@ -120,5 +120,6 @@ }, "dependencies": { "terser": "^5.14.2" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" }