@xchainjs/xchain-dash 2.0.10 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AssetInfo, FeeRate, TxHistoryParams } from '@xchainjs/xchain-client';
2
2
  import { Address } from '@xchainjs/xchain-util';
3
- import { Balance, Client as UTXOClient, Tx, TxParams, TxsPage, UTXO, UtxoClientParams } from '@xchainjs/xchain-utxo';
3
+ import { Balance, Client as UTXOClient, PreparedTx, Tx, TxParams, TxsPage, UTXO, UtxoClientParams, UtxoSelectionPreferences } from '@xchainjs/xchain-utxo';
4
4
  import { DashPreparedTx, NodeAuth, NodeUrls } from './types';
5
5
  /**
6
6
  * Default parameters for the DASH client.
@@ -59,6 +59,7 @@ declare abstract class Client extends UTXOClient {
59
59
  private insightTxToXChainTx;
60
60
  /**
61
61
  * Asynchronously prepares a transaction for sending assets.
62
+ * @deprecated Use `prepareTxEnhanced` instead for better UTXO selection and error handling.
62
63
  * @param {TxParams&Address&FeeRate} params - Parameters for the transaction preparation.
63
64
  * @returns {string} A promise resolving to the prepared transaction data.
64
65
  */
@@ -80,5 +81,29 @@ declare abstract class Client extends UTXOClient {
80
81
  * @returns {number} The calculated transaction fee amount.
81
82
  */
82
83
  protected getFeeFromUtxos(inputs: UTXO[], feeRate: FeeRate, data?: Buffer | null): number;
84
+ /**
85
+ * Prepare transaction with enhanced UTXO selection.
86
+ * Uses base class UTXO selection logic with dashcore-lib transaction building.
87
+ */
88
+ prepareTxEnhanced({ sender, memo, amount, recipient, feeRate, spendPendingUTXO, utxoSelectionPreferences, }: TxParams & {
89
+ sender: Address;
90
+ feeRate: FeeRate;
91
+ spendPendingUTXO?: boolean;
92
+ utxoSelectionPreferences?: UtxoSelectionPreferences;
93
+ }): Promise<PreparedTx>;
94
+ /**
95
+ * Prepare max send transaction
96
+ */
97
+ prepareMaxTx({ sender, recipient, memo, feeRate, spendPendingUTXO, utxoSelectionPreferences, }: {
98
+ sender: Address;
99
+ recipient: Address;
100
+ memo?: string;
101
+ feeRate: FeeRate;
102
+ spendPendingUTXO?: boolean;
103
+ utxoSelectionPreferences?: UtxoSelectionPreferences;
104
+ }): Promise<PreparedTx & {
105
+ maxAmount: number;
106
+ fee: number;
107
+ }>;
83
108
  }
84
109
  export { Client };
@@ -1,6 +1,6 @@
1
1
  import { FeeRate, TxHash } from '@xchainjs/xchain-client';
2
2
  import { Address } from '@xchainjs/xchain-util';
3
- import { TxParams } from '@xchainjs/xchain-utxo';
3
+ import { TxParams, UtxoSelectionPreferences } from '@xchainjs/xchain-utxo';
4
4
  import { ECPairInterface } from 'ecpair';
5
5
  import { Client } from './client';
6
6
  export declare class ClientKeystore extends Client {
@@ -30,10 +30,34 @@ export declare class ClientKeystore extends Client {
30
30
  getDashKeys(phrase: string, index?: number): ECPairInterface;
31
31
  /**
32
32
  * Asynchronously transfers assets between addresses.
33
- * @param {TxParams & { feeRate?: FeeRate }} params - Parameters for the transfer.
33
+ * @param {TxParams & { feeRate?: FeeRate; utxoSelectionPreferences?: UtxoSelectionPreferences }} params - Parameters for the transfer.
34
34
  * @returns {Promise<TxHash>} A promise resolving to the transaction hash.
35
35
  */
36
36
  transfer(params: TxParams & {
37
37
  feeRate?: FeeRate;
38
+ utxoSelectionPreferences?: UtxoSelectionPreferences;
38
39
  }): Promise<TxHash>;
40
+ /**
41
+ * Transfer the maximum amount of DASH (sweep).
42
+ *
43
+ * Calculates the maximum sendable amount after fees, signs, and broadcasts the transaction.
44
+ * @param {Object} params The transfer parameters.
45
+ * @param {string} params.recipient The recipient address.
46
+ * @param {string} [params.memo] Optional memo for the transaction.
47
+ * @param {FeeRate} [params.feeRate] Optional fee rate. Defaults to 'average' rate.
48
+ * @param {number} [params.walletIndex] Optional wallet index. Defaults to 0.
49
+ * @param {UtxoSelectionPreferences} [params.utxoSelectionPreferences] Optional UTXO selection preferences.
50
+ * @returns {Promise<{ hash: TxHash; maxAmount: number; fee: number }>} The transaction hash, amount sent, and fee.
51
+ */
52
+ transferMax(params: {
53
+ recipient: Address;
54
+ memo?: string;
55
+ feeRate?: FeeRate;
56
+ walletIndex?: number;
57
+ utxoSelectionPreferences?: UtxoSelectionPreferences;
58
+ }): Promise<{
59
+ hash: TxHash;
60
+ maxAmount: number;
61
+ fee: number;
62
+ }>;
39
63
  }
package/lib/index.esm.js CHANGED
@@ -2,7 +2,7 @@ import { ExplorerProvider, Network, TxType, FeeOption, checkFeeBounds } from '@x
2
2
  import { AssetType, baseAmount, assetToBase, assetAmount } from '@xchainjs/xchain-util';
3
3
  import { BlockcypherProvider, BlockcypherNetwork, BitgoProvider } from '@xchainjs/xchain-utxo-providers';
4
4
  import dashcore from '@dashevo/dashcore-lib';
5
- import { toBitcoinJS, Client as Client$1 } from '@xchainjs/xchain-utxo';
5
+ import { toBitcoinJS, Client as Client$1, UtxoError } from '@xchainjs/xchain-utxo';
6
6
  import * as Dash from 'bitcoinjs-lib';
7
7
  import accumulative from 'coinselect/accumulative.js';
8
8
  import * as ecc from '@bitcoin-js/tiny-secp256k1-asmjs';
@@ -4449,6 +4449,7 @@ class Client extends Client$1 {
4449
4449
  }
4450
4450
  /**
4451
4451
  * Asynchronously prepares a transaction for sending assets.
4452
+ * @deprecated Use `prepareTxEnhanced` instead for better UTXO selection and error handling.
4452
4453
  * @param {TxParams&Address&FeeRate} params - Parameters for the transaction preparation.
4453
4454
  * @returns {string} A promise resolving to the prepared transaction data.
4454
4455
  */
@@ -4515,6 +4516,123 @@ class Client extends Client$1 {
4515
4516
  // Ensure fee meets minimum requirement
4516
4517
  return fee > TX_MIN_FEE ? fee : TX_MIN_FEE;
4517
4518
  }
4519
+ // ==================== Enhanced Transaction Methods ====================
4520
+ /**
4521
+ * Prepare transaction with enhanced UTXO selection.
4522
+ * Uses base class UTXO selection logic with dashcore-lib transaction building.
4523
+ */
4524
+ prepareTxEnhanced(_a) {
4525
+ return __awaiter(this, arguments, void 0, function* ({ sender, memo, amount, recipient, feeRate, spendPendingUTXO = true, utxoSelectionPreferences, }) {
4526
+ try {
4527
+ // Validate inputs using base class method
4528
+ this.validateTransactionInputs({
4529
+ amount,
4530
+ recipient,
4531
+ memo,
4532
+ sender,
4533
+ feeRate,
4534
+ });
4535
+ // Get validated UTXOs using base class method
4536
+ const confirmedOnly = !spendPendingUTXO;
4537
+ const utxos = yield this.getValidatedUtxos(sender, confirmedOnly);
4538
+ const compiledMemo = memo ? this.compileMemo(memo) : null;
4539
+ const targetValue = amount.amount().toNumber();
4540
+ const extraOutputs = 1 + (compiledMemo ? 1 : 0);
4541
+ // Use base class UTXO selection
4542
+ const selectionResult = this.selectUtxosForTransaction(utxos, targetValue, Math.ceil(feeRate), extraOutputs, utxoSelectionPreferences);
4543
+ // Build transaction using dashcore-lib
4544
+ const tx = new dashcore.Transaction().to(recipient, targetValue);
4545
+ // Add selected inputs
4546
+ for (const utxo of selectionResult.inputs) {
4547
+ const scriptBuffer = Buffer.from(utxo.scriptPubKey || '', 'hex');
4548
+ const script = new dashcore.Script(scriptBuffer);
4549
+ const input = new dashcore.Transaction.Input.PublicKeyHash({
4550
+ prevTxId: Buffer.from(utxo.hash, 'hex'),
4551
+ outputIndex: utxo.index,
4552
+ script: '',
4553
+ output: new dashcore.Transaction.Output({
4554
+ satoshis: utxo.value,
4555
+ script,
4556
+ }),
4557
+ });
4558
+ tx.uncheckedAddInput(input);
4559
+ }
4560
+ // Set change address
4561
+ const senderAddress = dashcore.Address.fromString(sender, this.network);
4562
+ tx.change(senderAddress);
4563
+ // Add memo if provided
4564
+ if (memo) {
4565
+ tx.addData(memo);
4566
+ }
4567
+ // ESLint disabled: Dash transaction has proper toString() method that returns hex string
4568
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
4569
+ return { rawUnsignedTx: tx.toString(), utxos, inputs: selectionResult.inputs };
4570
+ }
4571
+ catch (error) {
4572
+ if (UtxoError.isUtxoError(error)) {
4573
+ throw error;
4574
+ }
4575
+ throw UtxoError.fromUnknown(error, 'prepareTxEnhanced');
4576
+ }
4577
+ });
4578
+ }
4579
+ /**
4580
+ * Prepare max send transaction
4581
+ */
4582
+ prepareMaxTx(_a) {
4583
+ return __awaiter(this, arguments, void 0, function* ({ sender, recipient, memo, feeRate, spendPendingUTXO = true, utxoSelectionPreferences, }) {
4584
+ try {
4585
+ // Validate addresses
4586
+ if (!this.validateAddress(recipient)) {
4587
+ throw UtxoError.invalidAddress(recipient, this.network);
4588
+ }
4589
+ if (!this.validateAddress(sender)) {
4590
+ throw UtxoError.invalidAddress(sender, this.network);
4591
+ }
4592
+ // Get validated UTXOs
4593
+ const confirmedOnly = !spendPendingUTXO;
4594
+ const utxos = yield this.getValidatedUtxos(sender, confirmedOnly);
4595
+ // Calculate max using base class method
4596
+ const maxCalc = this.calculateMaxSendableAmount(utxos, Math.ceil(feeRate), !!memo, utxoSelectionPreferences);
4597
+ // Build transaction using dashcore-lib
4598
+ const tx = new dashcore.Transaction().to(recipient, maxCalc.amount);
4599
+ // Add inputs
4600
+ for (const utxo of maxCalc.inputs) {
4601
+ const scriptBuffer = Buffer.from(utxo.scriptPubKey || '', 'hex');
4602
+ const script = new dashcore.Script(scriptBuffer);
4603
+ const input = new dashcore.Transaction.Input.PublicKeyHash({
4604
+ prevTxId: Buffer.from(utxo.hash, 'hex'),
4605
+ outputIndex: utxo.index,
4606
+ script: '',
4607
+ output: new dashcore.Transaction.Output({
4608
+ satoshis: utxo.value,
4609
+ script,
4610
+ }),
4611
+ });
4612
+ tx.uncheckedAddInput(input);
4613
+ }
4614
+ // Add memo if provided
4615
+ if (memo) {
4616
+ tx.addData(memo);
4617
+ }
4618
+ // ESLint disabled: Dash transaction has proper toString() method that returns hex string
4619
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
4620
+ return {
4621
+ rawUnsignedTx: tx.toString(),
4622
+ utxos,
4623
+ inputs: maxCalc.inputs,
4624
+ maxAmount: maxCalc.amount,
4625
+ fee: maxCalc.fee,
4626
+ };
4627
+ }
4628
+ catch (error) {
4629
+ if (UtxoError.isUtxoError(error)) {
4630
+ throw error;
4631
+ }
4632
+ throw UtxoError.fromUnknown(error, 'prepareMaxTx');
4633
+ }
4634
+ });
4635
+ }
4518
4636
  }
4519
4637
 
4520
4638
  /**
@@ -4605,7 +4723,7 @@ class ClientKeystore extends Client {
4605
4723
  }
4606
4724
  /**
4607
4725
  * Asynchronously transfers assets between addresses.
4608
- * @param {TxParams & { feeRate?: FeeRate }} params - Parameters for the transfer.
4726
+ * @param {TxParams & { feeRate?: FeeRate; utxoSelectionPreferences?: UtxoSelectionPreferences }} params - Parameters for the transfer.
4609
4727
  * @returns {Promise<TxHash>} A promise resolving to the transaction hash.
4610
4728
  */
4611
4729
  transfer(params) {
@@ -4614,7 +4732,9 @@ class ClientKeystore extends Client {
4614
4732
  const feeRate = params.feeRate || (yield this.getFeeRates())[FeeOption.Average];
4615
4733
  checkFeeBounds(this.feeBounds, feeRate);
4616
4734
  const fromAddressIndex = params.walletIndex || 0;
4617
- const { rawUnsignedTx, utxos } = yield this.prepareTx(Object.assign(Object.assign({}, params), { feeRate, sender: yield this.getAddressAsync(fromAddressIndex) }));
4735
+ // Merge default preferences
4736
+ const mergedPreferences = Object.assign({ minimizeFee: true, avoidDust: true, minimizeInputs: false }, params.utxoSelectionPreferences);
4737
+ const { rawUnsignedTx, utxos } = yield this.prepareTxEnhanced(Object.assign(Object.assign({}, params), { feeRate, sender: yield this.getAddressAsync(fromAddressIndex), utxoSelectionPreferences: mergedPreferences }));
4618
4738
  const tx = new dashcore.Transaction(rawUnsignedTx);
4619
4739
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4620
4740
  tx.inputs.forEach((input, index) => {
@@ -4646,6 +4766,64 @@ class ClientKeystore extends Client {
4646
4766
  });
4647
4767
  });
4648
4768
  }
4769
+ /**
4770
+ * Transfer the maximum amount of DASH (sweep).
4771
+ *
4772
+ * Calculates the maximum sendable amount after fees, signs, and broadcasts the transaction.
4773
+ * @param {Object} params The transfer parameters.
4774
+ * @param {string} params.recipient The recipient address.
4775
+ * @param {string} [params.memo] Optional memo for the transaction.
4776
+ * @param {FeeRate} [params.feeRate] Optional fee rate. Defaults to 'average' rate.
4777
+ * @param {number} [params.walletIndex] Optional wallet index. Defaults to 0.
4778
+ * @param {UtxoSelectionPreferences} [params.utxoSelectionPreferences] Optional UTXO selection preferences.
4779
+ * @returns {Promise<{ hash: TxHash; maxAmount: number; fee: number }>} The transaction hash, amount sent, and fee.
4780
+ */
4781
+ transferMax(params) {
4782
+ return __awaiter(this, void 0, void 0, function* () {
4783
+ var _a;
4784
+ const feeRate = params.feeRate || (yield this.getFeeRates())[FeeOption.Average];
4785
+ checkFeeBounds(this.feeBounds, feeRate);
4786
+ const fromAddressIndex = params.walletIndex || 0;
4787
+ const sender = yield this.getAddressAsync(fromAddressIndex);
4788
+ const { rawUnsignedTx, utxos, maxAmount, fee } = yield this.prepareMaxTx({
4789
+ sender,
4790
+ recipient: params.recipient,
4791
+ memo: params.memo,
4792
+ feeRate,
4793
+ utxoSelectionPreferences: params.utxoSelectionPreferences,
4794
+ });
4795
+ const tx = new dashcore.Transaction(rawUnsignedTx);
4796
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4797
+ tx.inputs.forEach((input, index) => {
4798
+ const insightUtxo = utxos.find((utxo) => {
4799
+ return utxo.hash === input.prevTxId.toString('hex') && utxo.index == input.outputIndex;
4800
+ });
4801
+ if (!insightUtxo) {
4802
+ throw new Error('Unable to match accumulative inputs with insight utxos');
4803
+ }
4804
+ const scriptBuffer = Buffer.from(insightUtxo.scriptPubKey || '', 'hex');
4805
+ const script = new dashcore.Script(scriptBuffer);
4806
+ tx.inputs[index] = new dashcore.Transaction.Input.PublicKeyHash({
4807
+ prevTxId: Buffer.from(insightUtxo.hash, 'hex'),
4808
+ outputIndex: insightUtxo.index,
4809
+ script: '',
4810
+ output: new dashcore.Transaction.Output({
4811
+ satoshis: insightUtxo.value,
4812
+ script,
4813
+ }),
4814
+ });
4815
+ });
4816
+ const dashKeys = this.getDashKeys(this.phrase, fromAddressIndex);
4817
+ tx.sign(`${(_a = dashKeys.privateKey) === null || _a === void 0 ? void 0 : _a.toString('hex')}`);
4818
+ const txHex = tx.checkedSerialize({});
4819
+ const hash = yield broadcastTx({
4820
+ txHex,
4821
+ nodeUrl: this.nodeUrls[this.network],
4822
+ auth: this.nodeAuth,
4823
+ });
4824
+ return { hash, maxAmount, fee };
4825
+ });
4826
+ }
4649
4827
  }
4650
4828
 
4651
4829
  /**
package/lib/index.js CHANGED
@@ -4477,6 +4477,7 @@ class Client extends xchainUtxo.Client {
4477
4477
  }
4478
4478
  /**
4479
4479
  * Asynchronously prepares a transaction for sending assets.
4480
+ * @deprecated Use `prepareTxEnhanced` instead for better UTXO selection and error handling.
4480
4481
  * @param {TxParams&Address&FeeRate} params - Parameters for the transaction preparation.
4481
4482
  * @returns {string} A promise resolving to the prepared transaction data.
4482
4483
  */
@@ -4543,6 +4544,123 @@ class Client extends xchainUtxo.Client {
4543
4544
  // Ensure fee meets minimum requirement
4544
4545
  return fee > TX_MIN_FEE ? fee : TX_MIN_FEE;
4545
4546
  }
4547
+ // ==================== Enhanced Transaction Methods ====================
4548
+ /**
4549
+ * Prepare transaction with enhanced UTXO selection.
4550
+ * Uses base class UTXO selection logic with dashcore-lib transaction building.
4551
+ */
4552
+ prepareTxEnhanced(_a) {
4553
+ return __awaiter(this, arguments, void 0, function* ({ sender, memo, amount, recipient, feeRate, spendPendingUTXO = true, utxoSelectionPreferences, }) {
4554
+ try {
4555
+ // Validate inputs using base class method
4556
+ this.validateTransactionInputs({
4557
+ amount,
4558
+ recipient,
4559
+ memo,
4560
+ sender,
4561
+ feeRate,
4562
+ });
4563
+ // Get validated UTXOs using base class method
4564
+ const confirmedOnly = !spendPendingUTXO;
4565
+ const utxos = yield this.getValidatedUtxos(sender, confirmedOnly);
4566
+ const compiledMemo = memo ? this.compileMemo(memo) : null;
4567
+ const targetValue = amount.amount().toNumber();
4568
+ const extraOutputs = 1 + (compiledMemo ? 1 : 0);
4569
+ // Use base class UTXO selection
4570
+ const selectionResult = this.selectUtxosForTransaction(utxos, targetValue, Math.ceil(feeRate), extraOutputs, utxoSelectionPreferences);
4571
+ // Build transaction using dashcore-lib
4572
+ const tx = new dashcore__default.default.Transaction().to(recipient, targetValue);
4573
+ // Add selected inputs
4574
+ for (const utxo of selectionResult.inputs) {
4575
+ const scriptBuffer = Buffer.from(utxo.scriptPubKey || '', 'hex');
4576
+ const script = new dashcore__default.default.Script(scriptBuffer);
4577
+ const input = new dashcore__default.default.Transaction.Input.PublicKeyHash({
4578
+ prevTxId: Buffer.from(utxo.hash, 'hex'),
4579
+ outputIndex: utxo.index,
4580
+ script: '',
4581
+ output: new dashcore__default.default.Transaction.Output({
4582
+ satoshis: utxo.value,
4583
+ script,
4584
+ }),
4585
+ });
4586
+ tx.uncheckedAddInput(input);
4587
+ }
4588
+ // Set change address
4589
+ const senderAddress = dashcore__default.default.Address.fromString(sender, this.network);
4590
+ tx.change(senderAddress);
4591
+ // Add memo if provided
4592
+ if (memo) {
4593
+ tx.addData(memo);
4594
+ }
4595
+ // ESLint disabled: Dash transaction has proper toString() method that returns hex string
4596
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
4597
+ return { rawUnsignedTx: tx.toString(), utxos, inputs: selectionResult.inputs };
4598
+ }
4599
+ catch (error) {
4600
+ if (xchainUtxo.UtxoError.isUtxoError(error)) {
4601
+ throw error;
4602
+ }
4603
+ throw xchainUtxo.UtxoError.fromUnknown(error, 'prepareTxEnhanced');
4604
+ }
4605
+ });
4606
+ }
4607
+ /**
4608
+ * Prepare max send transaction
4609
+ */
4610
+ prepareMaxTx(_a) {
4611
+ return __awaiter(this, arguments, void 0, function* ({ sender, recipient, memo, feeRate, spendPendingUTXO = true, utxoSelectionPreferences, }) {
4612
+ try {
4613
+ // Validate addresses
4614
+ if (!this.validateAddress(recipient)) {
4615
+ throw xchainUtxo.UtxoError.invalidAddress(recipient, this.network);
4616
+ }
4617
+ if (!this.validateAddress(sender)) {
4618
+ throw xchainUtxo.UtxoError.invalidAddress(sender, this.network);
4619
+ }
4620
+ // Get validated UTXOs
4621
+ const confirmedOnly = !spendPendingUTXO;
4622
+ const utxos = yield this.getValidatedUtxos(sender, confirmedOnly);
4623
+ // Calculate max using base class method
4624
+ const maxCalc = this.calculateMaxSendableAmount(utxos, Math.ceil(feeRate), !!memo, utxoSelectionPreferences);
4625
+ // Build transaction using dashcore-lib
4626
+ const tx = new dashcore__default.default.Transaction().to(recipient, maxCalc.amount);
4627
+ // Add inputs
4628
+ for (const utxo of maxCalc.inputs) {
4629
+ const scriptBuffer = Buffer.from(utxo.scriptPubKey || '', 'hex');
4630
+ const script = new dashcore__default.default.Script(scriptBuffer);
4631
+ const input = new dashcore__default.default.Transaction.Input.PublicKeyHash({
4632
+ prevTxId: Buffer.from(utxo.hash, 'hex'),
4633
+ outputIndex: utxo.index,
4634
+ script: '',
4635
+ output: new dashcore__default.default.Transaction.Output({
4636
+ satoshis: utxo.value,
4637
+ script,
4638
+ }),
4639
+ });
4640
+ tx.uncheckedAddInput(input);
4641
+ }
4642
+ // Add memo if provided
4643
+ if (memo) {
4644
+ tx.addData(memo);
4645
+ }
4646
+ // ESLint disabled: Dash transaction has proper toString() method that returns hex string
4647
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
4648
+ return {
4649
+ rawUnsignedTx: tx.toString(),
4650
+ utxos,
4651
+ inputs: maxCalc.inputs,
4652
+ maxAmount: maxCalc.amount,
4653
+ fee: maxCalc.fee,
4654
+ };
4655
+ }
4656
+ catch (error) {
4657
+ if (xchainUtxo.UtxoError.isUtxoError(error)) {
4658
+ throw error;
4659
+ }
4660
+ throw xchainUtxo.UtxoError.fromUnknown(error, 'prepareMaxTx');
4661
+ }
4662
+ });
4663
+ }
4546
4664
  }
4547
4665
 
4548
4666
  /**
@@ -4633,7 +4751,7 @@ class ClientKeystore extends Client {
4633
4751
  }
4634
4752
  /**
4635
4753
  * Asynchronously transfers assets between addresses.
4636
- * @param {TxParams & { feeRate?: FeeRate }} params - Parameters for the transfer.
4754
+ * @param {TxParams & { feeRate?: FeeRate; utxoSelectionPreferences?: UtxoSelectionPreferences }} params - Parameters for the transfer.
4637
4755
  * @returns {Promise<TxHash>} A promise resolving to the transaction hash.
4638
4756
  */
4639
4757
  transfer(params) {
@@ -4642,7 +4760,9 @@ class ClientKeystore extends Client {
4642
4760
  const feeRate = params.feeRate || (yield this.getFeeRates())[xchainClient.FeeOption.Average];
4643
4761
  xchainClient.checkFeeBounds(this.feeBounds, feeRate);
4644
4762
  const fromAddressIndex = params.walletIndex || 0;
4645
- const { rawUnsignedTx, utxos } = yield this.prepareTx(Object.assign(Object.assign({}, params), { feeRate, sender: yield this.getAddressAsync(fromAddressIndex) }));
4763
+ // Merge default preferences
4764
+ const mergedPreferences = Object.assign({ minimizeFee: true, avoidDust: true, minimizeInputs: false }, params.utxoSelectionPreferences);
4765
+ const { rawUnsignedTx, utxos } = yield this.prepareTxEnhanced(Object.assign(Object.assign({}, params), { feeRate, sender: yield this.getAddressAsync(fromAddressIndex), utxoSelectionPreferences: mergedPreferences }));
4646
4766
  const tx = new dashcore__default.default.Transaction(rawUnsignedTx);
4647
4767
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4648
4768
  tx.inputs.forEach((input, index) => {
@@ -4674,6 +4794,64 @@ class ClientKeystore extends Client {
4674
4794
  });
4675
4795
  });
4676
4796
  }
4797
+ /**
4798
+ * Transfer the maximum amount of DASH (sweep).
4799
+ *
4800
+ * Calculates the maximum sendable amount after fees, signs, and broadcasts the transaction.
4801
+ * @param {Object} params The transfer parameters.
4802
+ * @param {string} params.recipient The recipient address.
4803
+ * @param {string} [params.memo] Optional memo for the transaction.
4804
+ * @param {FeeRate} [params.feeRate] Optional fee rate. Defaults to 'average' rate.
4805
+ * @param {number} [params.walletIndex] Optional wallet index. Defaults to 0.
4806
+ * @param {UtxoSelectionPreferences} [params.utxoSelectionPreferences] Optional UTXO selection preferences.
4807
+ * @returns {Promise<{ hash: TxHash; maxAmount: number; fee: number }>} The transaction hash, amount sent, and fee.
4808
+ */
4809
+ transferMax(params) {
4810
+ return __awaiter(this, void 0, void 0, function* () {
4811
+ var _a;
4812
+ const feeRate = params.feeRate || (yield this.getFeeRates())[xchainClient.FeeOption.Average];
4813
+ xchainClient.checkFeeBounds(this.feeBounds, feeRate);
4814
+ const fromAddressIndex = params.walletIndex || 0;
4815
+ const sender = yield this.getAddressAsync(fromAddressIndex);
4816
+ const { rawUnsignedTx, utxos, maxAmount, fee } = yield this.prepareMaxTx({
4817
+ sender,
4818
+ recipient: params.recipient,
4819
+ memo: params.memo,
4820
+ feeRate,
4821
+ utxoSelectionPreferences: params.utxoSelectionPreferences,
4822
+ });
4823
+ const tx = new dashcore__default.default.Transaction(rawUnsignedTx);
4824
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4825
+ tx.inputs.forEach((input, index) => {
4826
+ const insightUtxo = utxos.find((utxo) => {
4827
+ return utxo.hash === input.prevTxId.toString('hex') && utxo.index == input.outputIndex;
4828
+ });
4829
+ if (!insightUtxo) {
4830
+ throw new Error('Unable to match accumulative inputs with insight utxos');
4831
+ }
4832
+ const scriptBuffer = Buffer.from(insightUtxo.scriptPubKey || '', 'hex');
4833
+ const script = new dashcore__default.default.Script(scriptBuffer);
4834
+ tx.inputs[index] = new dashcore__default.default.Transaction.Input.PublicKeyHash({
4835
+ prevTxId: Buffer.from(insightUtxo.hash, 'hex'),
4836
+ outputIndex: insightUtxo.index,
4837
+ script: '',
4838
+ output: new dashcore__default.default.Transaction.Output({
4839
+ satoshis: insightUtxo.value,
4840
+ script,
4841
+ }),
4842
+ });
4843
+ });
4844
+ const dashKeys = this.getDashKeys(this.phrase, fromAddressIndex);
4845
+ tx.sign(`${(_a = dashKeys.privateKey) === null || _a === void 0 ? void 0 : _a.toString('hex')}`);
4846
+ const txHex = tx.checkedSerialize({});
4847
+ const hash = yield broadcastTx({
4848
+ txHex,
4849
+ nodeUrl: this.nodeUrls[this.network],
4850
+ auth: this.nodeAuth,
4851
+ });
4852
+ return { hash, maxAmount, fee };
4853
+ });
4854
+ }
4677
4855
  }
4678
4856
 
4679
4857
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xchainjs/xchain-dash",
3
- "version": "2.0.10",
3
+ "version": "2.1.0",
4
4
  "description": "Custom Dash client and utilities used by XChainJS clients",
5
5
  "keywords": [
6
6
  "XChain",
@@ -40,7 +40,7 @@
40
40
  "@xchainjs/xchain-client": "2.0.10",
41
41
  "@xchainjs/xchain-crypto": "1.0.6",
42
42
  "@xchainjs/xchain-util": "2.0.5",
43
- "@xchainjs/xchain-utxo": "2.0.10",
43
+ "@xchainjs/xchain-utxo": "2.1.0",
44
44
  "@xchainjs/xchain-utxo-providers": "2.0.10",
45
45
  "bitcoinjs-lib": "^6.1.7",
46
46
  "coinselect": "3.1.12",