@fuel-ts/account 0.101.2 → 0.101.3

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.
Files changed (36) hide show
  1. package/dist/account.d.ts +45 -14
  2. package/dist/account.d.ts.map +1 -1
  3. package/dist/connectors/fuel-connector.d.ts +8 -0
  4. package/dist/connectors/fuel-connector.d.ts.map +1 -1
  5. package/dist/connectors/types/connector-types.d.ts +4 -2
  6. package/dist/connectors/types/connector-types.d.ts.map +1 -1
  7. package/dist/connectors/types/events.d.ts +6 -1
  8. package/dist/connectors/types/events.d.ts.map +1 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.global.js +538 -101
  12. package/dist/index.global.js.map +1 -1
  13. package/dist/index.js +598 -250
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +583 -238
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/providers/provider.d.ts.map +1 -1
  18. package/dist/providers/transaction-request/script-transaction-request.d.ts +2 -1
  19. package/dist/providers/transaction-request/script-transaction-request.d.ts.map +1 -1
  20. package/dist/providers/transaction-response/transaction-response.d.ts +23 -4
  21. package/dist/providers/transaction-response/transaction-response.d.ts.map +1 -1
  22. package/dist/providers/utils/extract-tx-error.d.ts.map +1 -1
  23. package/dist/providers/utils/handle-gql-error-message.d.ts.map +1 -1
  24. package/dist/providers/utils/transaction-response-serialization.d.ts.map +1 -1
  25. package/dist/test-utils/launchNode.d.ts.map +1 -1
  26. package/dist/test-utils.global.js +465 -101
  27. package/dist/test-utils.global.js.map +1 -1
  28. package/dist/test-utils.js +525 -198
  29. package/dist/test-utils.js.map +1 -1
  30. package/dist/test-utils.mjs +515 -188
  31. package/dist/test-utils.mjs.map +1 -1
  32. package/dist/types.d.ts +1 -1
  33. package/dist/types.d.ts.map +1 -1
  34. package/dist/utils/consolidate-coins.d.ts +43 -0
  35. package/dist/utils/consolidate-coins.d.ts.map +1 -0
  36. package/package.json +14 -14
@@ -217,8 +217,9 @@ var launchNode = /* @__PURE__ */ __name(async ({
217
217
  "--consensus-key",
218
218
  "--db-type",
219
219
  "--poa-instant",
220
+ "--native-executor-version",
220
221
  "--min-gas-price",
221
- "--native-executor-version"
222
+ "--starting-gas-price"
222
223
  ]);
223
224
  const snapshotDir = getFlagValueFromArgs(args, "--snapshot");
224
225
  const consensusKey = getFlagValueFromArgs(args, "--consensus-key") || defaultConsensusKey;
@@ -1809,8 +1810,11 @@ import { print } from "graphql";
1809
1810
 
1810
1811
  // src/providers/utils/handle-gql-error-message.ts
1811
1812
  import { ErrorCode as ErrorCode2, FuelError as FuelError3 } from "@fuel-ts/errors";
1813
+ var ASSET_ID_REGEX = /[0-9a-fA-F]{32,64}/g;
1812
1814
  var gqlErrorMessage = {
1813
1815
  RPC_CONSISTENCY: /The required fuel block height is higher than the current block height. Required: \d+, Current: \d+/,
1816
+ INSUFFICIENT_FUNDS: /the target cannot be met due to insufficient coins available for [0-9a-fA-F]{32,64}. Collected: \d+/,
1817
+ MAX_COINS_REACHED: /the target for [0-9a-fA-F]{32,64} cannot be met due to exceeding the \d+ coin limit. Collected: \d+./,
1814
1818
  NOT_ENOUGH_COINS_MAX_COINS: /the target cannot be met due to no coins available or exceeding the \d+ coin limit./,
1815
1819
  ASSET_NOT_FOUND: /resource was not found in table/,
1816
1820
  MULTIPLE_CHANGE_POLICIES: /The asset ([a-fA-F0-9]{64}) has multiple change policies/,
@@ -1826,6 +1830,46 @@ var mapGqlErrorMessage = /* @__PURE__ */ __name((error) => {
1826
1830
  error
1827
1831
  );
1828
1832
  }
1833
+ if (gqlErrorMessage.MAX_COINS_REACHED.test(error.message)) {
1834
+ const matches = error.message.match(ASSET_ID_REGEX);
1835
+ const assetId = matches ? `0x${matches[0]}` : null;
1836
+ const owner = matches ? `0x${matches[1]}` : null;
1837
+ let suffix = "";
1838
+ if (assetId) {
1839
+ suffix += `
1840
+ Asset ID: '${assetId}'.`;
1841
+ }
1842
+ if (owner) {
1843
+ suffix += `
1844
+ Owner: '${owner}'.`;
1845
+ }
1846
+ return new FuelError3(
1847
+ ErrorCode2.MAX_COINS_REACHED,
1848
+ `You have too many small value coins - consider combining UTXOs.${suffix}`,
1849
+ { assetId, owner },
1850
+ error
1851
+ );
1852
+ }
1853
+ if (gqlErrorMessage.INSUFFICIENT_FUNDS.test(error.message)) {
1854
+ const matches = error.message.match(ASSET_ID_REGEX);
1855
+ const assetId = matches ? `0x${matches[0]}` : null;
1856
+ const owner = matches ? `0x${matches[1]}` : null;
1857
+ let suffix = "";
1858
+ if (assetId) {
1859
+ suffix += `
1860
+ Asset ID: '${assetId}'.`;
1861
+ }
1862
+ if (owner) {
1863
+ suffix += `
1864
+ Owner: '${owner}'.`;
1865
+ }
1866
+ return new FuelError3(
1867
+ ErrorCode2.INSUFFICIENT_FUNDS,
1868
+ `Insufficient funds.${suffix}`,
1869
+ { assetId, owner },
1870
+ error
1871
+ );
1872
+ }
1829
1873
  if (gqlErrorMessage.MULTIPLE_CHANGE_POLICIES.test(error.message)) {
1830
1874
  const match = error.message.match(/asset ([a-fA-F0-9]{64})/);
1831
1875
  const assetId = match?.[1] || "";
@@ -2929,6 +2973,7 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
2929
2973
  }
2930
2974
  return new FuelError9(ErrorCode8.SCRIPT_REVERTED, errorMessage, {
2931
2975
  ...metadata,
2976
+ abiError,
2932
2977
  reason
2933
2978
  });
2934
2979
  }
@@ -3951,11 +3996,15 @@ var ScriptTransactionRequest = class extends BaseTransactionRequest {
3951
3996
  * @deprecated Use `provider.assembleTx` instead.
3952
3997
  * Check the migration guide https://docs.fuel.network/guide/assembling-transactions/migration-guide.html for more information.
3953
3998
  */
3954
- async estimateAndFund(account, { signatureCallback, quantities = [] } = {}) {
3999
+ async estimateAndFund(account, {
4000
+ signatureCallback,
4001
+ quantities = [],
4002
+ skipAutoConsolidation
4003
+ } = {}) {
3955
4004
  const txCost = await account.getTransactionCost(this, { signatureCallback, quantities });
3956
4005
  this.maxFee = txCost.maxFee;
3957
4006
  this.gasLimit = txCost.gasUsed;
3958
- await account.fund(this, txCost);
4007
+ await account.fund(this, txCost, { skipAutoConsolidation });
3959
4008
  return this;
3960
4009
  }
3961
4010
  /**
@@ -5522,25 +5571,6 @@ __name(getAllDecodedLogs, "getAllDecodedLogs");
5522
5571
 
5523
5572
  // src/providers/transaction-response/transaction-response.ts
5524
5573
  var TransactionResponse = class _TransactionResponse {
5525
- /**
5526
- * Constructor for `TransactionResponse`.
5527
- *
5528
- * @param tx - The transaction ID or TransactionRequest.
5529
- * @param provider - The provider.
5530
- */
5531
- constructor(tx, provider, chainId, abis, submitTxSubscription) {
5532
- this.submitTxSubscription = submitTxSubscription;
5533
- if (typeof tx === "string") {
5534
- this.id = tx;
5535
- } else {
5536
- this.id = tx.getTransactionId(chainId);
5537
- this.request = tx;
5538
- }
5539
- this.provider = provider;
5540
- this.abis = abis;
5541
- this.waitForResult = this.waitForResult.bind(this);
5542
- this.waitForPreConfirmation = this.waitForPreConfirmation.bind(this);
5543
- }
5544
5574
  static {
5545
5575
  __name(this, "TransactionResponse");
5546
5576
  }
@@ -5555,9 +5585,42 @@ var TransactionResponse = class _TransactionResponse {
5555
5585
  request;
5556
5586
  status;
5557
5587
  abis;
5588
+ submitTxSubscription;
5558
5589
  preConfirmationStatus;
5559
5590
  waitingForStreamData = false;
5560
5591
  statusResolvers = /* @__PURE__ */ new Map();
5592
+ /**
5593
+ * Constructor for `TransactionResponse`.
5594
+ */
5595
+ constructor(constructorParams, provider, chainId, abis, submitTxSubscription) {
5596
+ let tx;
5597
+ let _provider;
5598
+ let _chainId;
5599
+ let _abis;
5600
+ if (typeof constructorParams === "object" && "provider" in constructorParams && arguments.length === 1) {
5601
+ tx = constructorParams.transactionRequestOrId;
5602
+ _provider = constructorParams.provider;
5603
+ _chainId = constructorParams.chainId;
5604
+ _abis = constructorParams.abis;
5605
+ this.submitTxSubscription = constructorParams.submitAndAwaitSubscription;
5606
+ } else {
5607
+ tx = constructorParams;
5608
+ _provider = provider;
5609
+ _chainId = chainId;
5610
+ _abis = abis;
5611
+ this.submitTxSubscription = submitTxSubscription;
5612
+ }
5613
+ if (typeof tx === "string") {
5614
+ this.id = tx;
5615
+ } else {
5616
+ this.id = tx.getTransactionId(_chainId);
5617
+ this.request = tx;
5618
+ }
5619
+ this.provider = _provider;
5620
+ this.abis = _abis;
5621
+ this.waitForResult = this.waitForResult.bind(this);
5622
+ this.waitForPreConfirmation = this.waitForPreConfirmation.bind(this);
5623
+ }
5561
5624
  /**
5562
5625
  * Async constructor for `TransactionResponse`. This method can be used to create
5563
5626
  * an instance of `TransactionResponse` and wait for the transaction to be fetched
@@ -6074,7 +6137,15 @@ var Provider = class _Provider {
6074
6137
  if (_Provider.ENABLE_RPC_CONSISTENCY && _Provider.hasWriteOperationHappened(url)) {
6075
6138
  _Provider.applyBlockHeight(fullRequest, url);
6076
6139
  }
6077
- return _Provider.fetchAndProcessBlockHeight(url, fullRequest, options);
6140
+ const response = await _Provider.fetchAndProcessBlockHeight(url, fullRequest, options);
6141
+ if (response.body === null) {
6142
+ throw new FuelError20(
6143
+ ErrorCode17.RESPONSE_BODY_EMPTY,
6144
+ "The response from the server is missing the body",
6145
+ { timestamp: (/* @__PURE__ */ new Date()).toISOString(), request, response }
6146
+ );
6147
+ }
6148
+ return response;
6078
6149
  }, retryOptions);
6079
6150
  }
6080
6151
  static applyBlockHeight(request, url) {
@@ -6097,13 +6168,15 @@ var Provider = class _Provider {
6097
6168
  baseDelay: 500
6098
6169
  };
6099
6170
  for (let retriesLeft = retryOptions.maxRetries; retriesLeft > 0; --retriesLeft) {
6100
- const { extensions } = await parseGraphqlResponse({
6101
- response,
6102
- isSubscription: url.endsWith("-sub")
6103
- });
6104
- _Provider.setCurrentBlockHeight(url, extensions?.current_fuel_block_height);
6105
- if (!extensions?.fuel_block_height_precondition_failed) {
6106
- break;
6171
+ if (response.body) {
6172
+ const { extensions } = await parseGraphqlResponse({
6173
+ response,
6174
+ isSubscription: url.endsWith("-sub")
6175
+ });
6176
+ _Provider.setCurrentBlockHeight(url, extensions?.current_fuel_block_height);
6177
+ if (!extensions?.fuel_block_height_precondition_failed) {
6178
+ break;
6179
+ }
6107
6180
  }
6108
6181
  const retryAttempt = retryOptions.maxRetries - retriesLeft + 1;
6109
6182
  const sleepTime = getWaitDelay(retryOptions, retryAttempt);
@@ -6526,7 +6599,13 @@ var Provider = class _Provider {
6526
6599
  transactionRequest.getTransactionId(await this.getChainId())
6527
6600
  );
6528
6601
  const chainId = await this.getChainId();
6529
- return new TransactionResponse(transactionRequest, this, chainId, abis, subscription);
6602
+ return new TransactionResponse({
6603
+ transactionRequestOrId: transactionRequest,
6604
+ provider: this,
6605
+ chainId,
6606
+ abis,
6607
+ submitAndAwaitSubscription: subscription
6608
+ });
6530
6609
  }
6531
6610
  /**
6532
6611
  * Executes a transaction without actually submitting it to the chain.
@@ -7621,7 +7700,11 @@ var Provider = class _Provider {
7621
7700
  */
7622
7701
  async getTransactionResponse(transactionId) {
7623
7702
  const chainId = await this.getChainId();
7624
- return new TransactionResponse(transactionId, this, chainId);
7703
+ return new TransactionResponse({
7704
+ transactionRequestOrId: transactionId,
7705
+ provider: this,
7706
+ chainId
7707
+ });
7625
7708
  }
7626
7709
  /**
7627
7710
  * Returns Message for given nonce.
@@ -7792,8 +7875,8 @@ var TestAssetId = class _TestAssetId {
7792
7875
 
7793
7876
  // src/test-utils/wallet-config.ts
7794
7877
  import { randomBytes as randomBytes8 } from "@fuel-ts/crypto";
7795
- import { FuelError as FuelError27 } from "@fuel-ts/errors";
7796
- import { bn as bn23 } from "@fuel-ts/math";
7878
+ import { FuelError as FuelError28 } from "@fuel-ts/errors";
7879
+ import { bn as bn24 } from "@fuel-ts/math";
7797
7880
  import { defaultSnapshotConfigs as defaultSnapshotConfigs2, hexlify as hexlify26 } from "@fuel-ts/utils";
7798
7881
 
7799
7882
  // src/wallet/base-wallet-unlocked.ts
@@ -7802,11 +7885,11 @@ import { hexlify as hexlify23 } from "@fuel-ts/utils";
7802
7885
 
7803
7886
  // src/account.ts
7804
7887
  import { UTXO_ID_LEN as UTXO_ID_LEN3 } from "@fuel-ts/abi-coder";
7805
- import { Address as Address5 } from "@fuel-ts/address";
7888
+ import { Address as Address6 } from "@fuel-ts/address";
7806
7889
  import { randomBytes as randomBytes5 } from "@fuel-ts/crypto";
7807
- import { ErrorCode as ErrorCode19, FuelError as FuelError22 } from "@fuel-ts/errors";
7808
- import { bn as bn21 } from "@fuel-ts/math";
7809
- import { InputType as InputType8, OutputType as OutputType9 } from "@fuel-ts/transactions";
7890
+ import { ErrorCode as ErrorCode20, FuelError as FuelError23 } from "@fuel-ts/errors";
7891
+ import { bn as bn22 } from "@fuel-ts/math";
7892
+ import { InputType as InputType8, OutputType as OutputType10 } from "@fuel-ts/transactions";
7810
7893
  import { arrayify as arrayify18, hexlify as hexlify21, isDefined as isDefined4 } from "@fuel-ts/utils";
7811
7894
  import { clone as clone9 } from "ramda";
7812
7895
 
@@ -7817,9 +7900,157 @@ var AbstractAccount = class {
7817
7900
  }
7818
7901
  };
7819
7902
 
7903
+ // src/utils/consolidate-coins.ts
7904
+ import { Address as Address4 } from "@fuel-ts/address";
7905
+ import { ErrorCode as ErrorCode19, FuelError as FuelError22 } from "@fuel-ts/errors";
7906
+ import { bn as bn21 } from "@fuel-ts/math";
7907
+ import { OutputType as OutputType9 } from "@fuel-ts/transactions";
7908
+ import { splitEvery } from "ramda";
7909
+ var CONSOLIDATABLE_ERROR_CODES = [ErrorCode19.MAX_COINS_REACHED];
7910
+ var consolidateCoinsIfRequired = /* @__PURE__ */ __name(async (opts) => {
7911
+ const { error: errorUnknown, account, skipAutoConsolidation = false } = opts;
7912
+ if (skipAutoConsolidation) {
7913
+ return false;
7914
+ }
7915
+ const error = FuelError22.parse(errorUnknown);
7916
+ if (CONSOLIDATABLE_ERROR_CODES.includes(error.code)) {
7917
+ const { assetId, owner } = error.metadata;
7918
+ return account.startConsolidation({
7919
+ owner,
7920
+ assetId
7921
+ });
7922
+ }
7923
+ return false;
7924
+ }, "consolidateCoinsIfRequired");
7925
+ var getAllCoins = /* @__PURE__ */ __name(async (account, assetId) => {
7926
+ const all = [];
7927
+ let hasNextPage = true;
7928
+ let after;
7929
+ while (hasNextPage) {
7930
+ const { coins, pageInfo } = await account.getCoins(assetId, { after });
7931
+ all.push(...coins);
7932
+ after = coins.pop()?.id;
7933
+ hasNextPage = pageInfo.hasNextPage;
7934
+ }
7935
+ return { coins: all };
7936
+ }, "getAllCoins");
7937
+ var sortCoins = /* @__PURE__ */ __name(({ coins }) => coins.sort((a, b) => b.amount.cmp(a.amount)), "sortCoins");
7938
+ var createOuputCoin = /* @__PURE__ */ __name((opts) => {
7939
+ const { transactionId, outputs, baseAssetId } = opts;
7940
+ const outputChangeIndex = outputs.findIndex(
7941
+ (output) => output.type === OutputType9.Change && output.assetId === baseAssetId
7942
+ );
7943
+ if (outputChangeIndex === -1) {
7944
+ throw new FuelError22(ErrorCode19.UNKNOWN, "No change output found");
7945
+ }
7946
+ const outputCoin = outputs[outputChangeIndex];
7947
+ const outputIndexPadded = Number(outputChangeIndex).toString().padStart(4, "0");
7948
+ return {
7949
+ id: `${transactionId}${outputIndexPadded}`,
7950
+ assetId: outputCoin.assetId,
7951
+ amount: outputCoin.amount,
7952
+ owner: new Address4(outputCoin.to),
7953
+ blockCreated: bn21(0),
7954
+ txCreatedIdx: bn21(0)
7955
+ };
7956
+ }, "createOuputCoin");
7957
+ var consolidateCoins = /* @__PURE__ */ __name(async ({
7958
+ account,
7959
+ assetId
7960
+ }) => {
7961
+ const chainInfo = await account.provider.getChain();
7962
+ const chainId = chainInfo.consensusParameters.chainId.toNumber();
7963
+ const gasPrice = await account.provider.estimateGasPrice(10);
7964
+ const maxInputs = chainInfo.consensusParameters.txParameters.maxInputs.toNumber();
7965
+ const baseAssetId = await account.provider.getBaseAssetId();
7966
+ const isBaseAsset = assetId === baseAssetId;
7967
+ const batchSize = maxInputs;
7968
+ const numberOfFundingCoins = maxInputs;
7969
+ let funding = [];
7970
+ let dust = [];
7971
+ if (isBaseAsset) {
7972
+ const coins = await getAllCoins(account, baseAssetId).then(sortCoins);
7973
+ funding = coins.slice(0, numberOfFundingCoins);
7974
+ dust = coins.slice(numberOfFundingCoins);
7975
+ } else {
7976
+ funding = await getAllCoins(account, baseAssetId).then(sortCoins).then((coins) => coins.slice(0, numberOfFundingCoins));
7977
+ dust = await getAllCoins(account, assetId).then(({ coins }) => coins);
7978
+ }
7979
+ if (funding.length === 0) {
7980
+ throw new FuelError22(
7981
+ ErrorCode19.INSUFFICIENT_FUNDS,
7982
+ `Insufficient funds to consolidate.
7983
+ Asset ID: ${baseAssetId}
7984
+ Owner: ${account.address.toB256()}`
7985
+ );
7986
+ }
7987
+ const batches = [
7988
+ ...splitEvery(batchSize, funding),
7989
+ // We leave one coin for the funding coin
7990
+ ...splitEvery(batchSize - 1, dust)
7991
+ ];
7992
+ const txs = batches.map((batch) => {
7993
+ const request = new ScriptTransactionRequest({
7994
+ scriptData: "0x"
7995
+ });
7996
+ request.addResources(batch);
7997
+ return request;
7998
+ });
7999
+ const submitAll = /* @__PURE__ */ __name(async (opts = {}) => {
8000
+ const txResponses = [];
8001
+ let previousTx;
8002
+ for (let i = 0; i < txs.length; i++) {
8003
+ let currentTx = txs[i];
8004
+ const step = i + 1;
8005
+ if (previousTx) {
8006
+ const coin = createOuputCoin({
8007
+ transactionId: previousTx.transactionId,
8008
+ outputs: previousTx.outputs,
8009
+ baseAssetId
8010
+ });
8011
+ currentTx.addResource(coin);
8012
+ }
8013
+ if ("populateTransactionPredicateData" in account && typeof account.populateTransactionPredicateData === "function") {
8014
+ currentTx = account.populateTransactionPredicateData(currentTx);
8015
+ currentTx = await account.provider.estimatePredicates(currentTx);
8016
+ }
8017
+ const fee = calculateGasFee({
8018
+ gasPrice,
8019
+ gas: currentTx.calculateMinGas(chainInfo),
8020
+ priceFactor: chainInfo.consensusParameters.feeParameters.gasPriceFactor,
8021
+ tip: currentTx.tip
8022
+ });
8023
+ currentTx.maxFee = fee;
8024
+ currentTx.gasLimit = bn21(1e3);
8025
+ opts.onTransactionStart?.({
8026
+ tx: currentTx,
8027
+ step,
8028
+ assetId,
8029
+ transactionId: currentTx.getTransactionId(chainId)
8030
+ });
8031
+ const response = await account.sendTransaction(currentTx);
8032
+ const result = await response.waitForResult();
8033
+ txResponses.push(result);
8034
+ previousTx = {
8035
+ transactionId: response.id,
8036
+ outputs: result.transaction.outputs
8037
+ };
8038
+ }
8039
+ return {
8040
+ txResponses,
8041
+ errors: []
8042
+ };
8043
+ }, "submitAll");
8044
+ return {
8045
+ txs,
8046
+ totalFeeCost: txs.reduce((acc, request) => acc.add(request.maxFee), bn21(0)),
8047
+ submitAll
8048
+ };
8049
+ }, "consolidateCoins");
8050
+
7820
8051
  // src/utils/formatTransferToContractScriptData.ts
7821
8052
  import { ASSET_ID_LEN, BigNumberCoder as BigNumberCoder3, CONTRACT_ID_LEN, WORD_SIZE } from "@fuel-ts/abi-coder";
7822
- import { Address as Address4 } from "@fuel-ts/address";
8053
+ import { Address as Address5 } from "@fuel-ts/address";
7823
8054
  import { arrayify as arrayify17, concat as concat5 } from "@fuel-ts/utils";
7824
8055
  import * as asm from "@fuels/vm-asm";
7825
8056
  var formatTransferToContractScriptData = /* @__PURE__ */ __name((transferParams) => {
@@ -7827,7 +8058,7 @@ var formatTransferToContractScriptData = /* @__PURE__ */ __name((transferParams)
7827
8058
  return transferParams.reduce((acc, transferParam) => {
7828
8059
  const { assetId, amount, contractId } = transferParam;
7829
8060
  const encoded = numberCoder.encode(amount);
7830
- const scriptData = concat5([new Address4(contractId).toBytes(), encoded, arrayify17(assetId)]);
8061
+ const scriptData = concat5([new Address5(contractId).toBytes(), encoded, arrayify17(assetId)]);
7831
8062
  return concat5([acc, scriptData]);
7832
8063
  }, new Uint8Array());
7833
8064
  }, "formatTransferToContractScriptData");
@@ -7898,7 +8129,7 @@ var Account = class extends AbstractAccount {
7898
8129
  super();
7899
8130
  this._provider = provider;
7900
8131
  this._connector = connector;
7901
- this.address = new Address5(address);
8132
+ this.address = new Address6(address);
7902
8133
  }
7903
8134
  /**
7904
8135
  * The provider used to interact with the network.
@@ -7909,7 +8140,7 @@ var Account = class extends AbstractAccount {
7909
8140
  */
7910
8141
  get provider() {
7911
8142
  if (!this._provider) {
7912
- throw new FuelError22(ErrorCode19.MISSING_PROVIDER, "Provider not set");
8143
+ throw new FuelError23(ErrorCode20.MISSING_PROVIDER, "Provider not set");
7913
8144
  }
7914
8145
  return this._provider;
7915
8146
  }
@@ -7936,10 +8167,24 @@ var Account = class extends AbstractAccount {
7936
8167
  *
7937
8168
  * @param quantities - Quantities of resources to be obtained.
7938
8169
  * @param resourcesIdsToIgnore - IDs of resources to be excluded from the query (optional).
8170
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
7939
8171
  * @returns A promise that resolves to an array of Resources.
7940
8172
  */
7941
- async getResourcesToSpend(quantities, resourcesIdsToIgnore) {
7942
- return this.provider.getResourcesToSpend(this.address, quantities, resourcesIdsToIgnore);
8173
+ async getResourcesToSpend(quantities, resourcesIdsToIgnore, { skipAutoConsolidation } = {}) {
8174
+ const getResourcesToSpend = /* @__PURE__ */ __name(() => this.provider.getResourcesToSpend(this.address, quantities, resourcesIdsToIgnore), "getResourcesToSpend");
8175
+ try {
8176
+ return await getResourcesToSpend();
8177
+ } catch (error) {
8178
+ const shouldRetry = await consolidateCoinsIfRequired({
8179
+ error,
8180
+ account: this,
8181
+ skipAutoConsolidation
8182
+ });
8183
+ if (!shouldRetry) {
8184
+ throw error;
8185
+ }
8186
+ return await getResourcesToSpend();
8187
+ }
7943
8188
  }
7944
8189
  /**
7945
8190
  * Retrieves coins owned by the account.
@@ -7988,7 +8233,7 @@ var Account = class extends AbstractAccount {
7988
8233
  * @deprecated Use provider.assembleTx instead
7989
8234
  * Check the migration guide https://docs.fuel.network/docs/fuels-ts/transactions/assemble-tx-migration-guide/ for more information.
7990
8235
  */
7991
- async fund(request, params) {
8236
+ async fund(request, params, { skipAutoConsolidation } = {}) {
7992
8237
  const {
7993
8238
  addedSignatures,
7994
8239
  estimatedPredicates,
@@ -8000,9 +8245,9 @@ var Account = class extends AbstractAccount {
8000
8245
  const chainId = await this.provider.getChainId();
8001
8246
  const fee = request.maxFee;
8002
8247
  const baseAssetId = await this.provider.getBaseAssetId();
8003
- const requiredInBaseAsset = requiredQuantities.find((quantity) => quantity.assetId === baseAssetId)?.amount || bn21(0);
8248
+ const requiredInBaseAsset = requiredQuantities.find((quantity) => quantity.assetId === baseAssetId)?.amount || bn22(0);
8004
8249
  const requiredQuantitiesWithFee = addAmountToCoinQuantities({
8005
- amount: bn21(fee),
8250
+ amount: bn22(fee),
8006
8251
  assetId: baseAssetId,
8007
8252
  coinQuantities: requiredQuantities
8008
8253
  });
@@ -8010,7 +8255,7 @@ var Account = class extends AbstractAccount {
8010
8255
  requiredQuantitiesWithFee.forEach(({ amount, assetId }) => {
8011
8256
  quantitiesDict[assetId] = {
8012
8257
  required: amount,
8013
- owned: bn21(0)
8258
+ owned: bn22(0)
8014
8259
  };
8015
8260
  });
8016
8261
  request.inputs.filter(isRequestInputResource).forEach((input) => {
@@ -8034,7 +8279,8 @@ var Account = class extends AbstractAccount {
8034
8279
  while (needsToBeFunded && fundingAttempts < MAX_FUNDING_ATTEMPTS) {
8035
8280
  const resources = await this.getResourcesToSpend(
8036
8281
  missingQuantities,
8037
- cacheRequestInputsResourcesFromOwner(request.inputs, this.address)
8282
+ cacheRequestInputsResourcesFromOwner(request.inputs, this.address),
8283
+ { skipAutoConsolidation }
8038
8284
  );
8039
8285
  request.addResources(resources);
8040
8286
  request.updatePredicateGasUsed(estimatedPredicates);
@@ -8071,8 +8317,8 @@ var Account = class extends AbstractAccount {
8071
8317
  fundingAttempts += 1;
8072
8318
  }
8073
8319
  if (needsToBeFunded) {
8074
- throw new FuelError22(
8075
- ErrorCode19.INSUFFICIENT_FUNDS_OR_MAX_COINS,
8320
+ throw new FuelError23(
8321
+ ErrorCode20.INSUFFICIENT_FUNDS,
8076
8322
  `The account ${this.address} does not have enough base asset funds to cover the transaction execution.`
8077
8323
  );
8078
8324
  }
@@ -8100,16 +8346,20 @@ var Account = class extends AbstractAccount {
8100
8346
  * @param amount - The amount of coins to transfer.
8101
8347
  * @param assetId - The asset ID of the coins to transfer (optional).
8102
8348
  * @param txParams - The transaction parameters (optional).
8349
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
8103
8350
  * @returns A promise that resolves to the prepared transaction request.
8104
8351
  */
8105
- async createTransfer(destination, amount, assetId, txParams = {}) {
8352
+ async createTransfer(destination, amount, assetId, txParams = {}, { skipAutoConsolidation } = {}) {
8106
8353
  let request = new ScriptTransactionRequest(txParams);
8107
8354
  request = this.addTransfer(request, {
8108
8355
  destination,
8109
8356
  amount,
8110
8357
  assetId: assetId || await this.provider.getBaseAssetId()
8111
8358
  });
8112
- const { gasPrice, transactionRequest } = await this.assembleTx(request);
8359
+ const { gasPrice, transactionRequest } = await this.assembleTx({
8360
+ transactionRequest: request,
8361
+ skipAutoConsolidation
8362
+ });
8113
8363
  request = await setAndValidateGasAndFeeForAssembledTx({
8114
8364
  gasPrice,
8115
8365
  provider: this.provider,
@@ -8126,10 +8376,13 @@ var Account = class extends AbstractAccount {
8126
8376
  * @param amount - The amount of coins to transfer.
8127
8377
  * @param assetId - The asset ID of the coins to transfer (optional).
8128
8378
  * @param txParams - The transaction parameters (optional).
8379
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
8129
8380
  * @returns A promise that resolves to the transaction response.
8130
8381
  */
8131
- async transfer(destination, amount, assetId, txParams = {}) {
8132
- const request = await this.createTransfer(destination, amount, assetId, txParams);
8382
+ async transfer(destination, amount, assetId, txParams = {}, { skipAutoConsolidation } = {}) {
8383
+ const request = await this.createTransfer(destination, amount, assetId, txParams, {
8384
+ skipAutoConsolidation
8385
+ });
8133
8386
  return this.sendTransaction(request, { estimateTxDependencies: false });
8134
8387
  }
8135
8388
  /**
@@ -8137,12 +8390,16 @@ var Account = class extends AbstractAccount {
8137
8390
  *
8138
8391
  * @param transferParams - An array of `TransferParams` objects representing the transfers to be made.
8139
8392
  * @param txParams - Optional transaction parameters.
8393
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
8140
8394
  * @returns A promise that resolves to a `TransactionResponse` object representing the transaction result.
8141
8395
  */
8142
- async batchTransfer(transferParams, txParams = {}) {
8396
+ async batchTransfer(transferParams, txParams = {}, { skipAutoConsolidation } = {}) {
8143
8397
  let request = new ScriptTransactionRequest(txParams);
8144
8398
  request = this.addBatchTransfer(request, transferParams);
8145
- const { gasPrice, transactionRequest } = await this.assembleTx(request);
8399
+ const { gasPrice, transactionRequest } = await this.assembleTx({
8400
+ transactionRequest: request,
8401
+ skipAutoConsolidation
8402
+ });
8146
8403
  request = await setAndValidateGasAndFeeForAssembledTx({
8147
8404
  gasPrice,
8148
8405
  provider: this.provider,
@@ -8162,7 +8419,7 @@ var Account = class extends AbstractAccount {
8162
8419
  addTransfer(request, transferParams) {
8163
8420
  const { destination, amount, assetId } = transferParams;
8164
8421
  this.validateTransferAmount(amount);
8165
- request.addCoinOutput(new Address5(destination), amount, assetId);
8422
+ request.addCoinOutput(new Address6(destination), amount, assetId);
8166
8423
  return request;
8167
8424
  }
8168
8425
  /**
@@ -8189,24 +8446,27 @@ var Account = class extends AbstractAccount {
8189
8446
  * @param amount - The amount of coins to transfer.
8190
8447
  * @param assetId - The asset ID of the coins to transfer (optional).
8191
8448
  * @param txParams - The transaction parameters (optional).
8449
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
8192
8450
  * @returns A promise that resolves to the transaction response.
8193
8451
  */
8194
- async transferToContract(contractId, amount, assetId, txParams = {}) {
8195
- return this.batchTransferToContracts([{ amount, assetId, contractId }], txParams);
8452
+ async transferToContract(contractId, amount, assetId, txParams = {}, { skipAutoConsolidation } = {}) {
8453
+ return this.batchTransferToContracts([{ amount, assetId, contractId }], txParams, {
8454
+ skipAutoConsolidation
8455
+ });
8196
8456
  }
8197
- async batchTransferToContracts(contractTransferParams, txParams = {}) {
8457
+ async batchTransferToContracts(contractTransferParams, txParams = {}, { skipAutoConsolidation } = {}) {
8198
8458
  let request = new ScriptTransactionRequest({
8199
8459
  ...txParams
8200
8460
  });
8201
8461
  const quantities = [];
8202
8462
  const defaultAssetId = await this.provider.getBaseAssetId();
8203
8463
  const transferParams = contractTransferParams.map((transferParam) => {
8204
- const amount = bn21(transferParam.amount);
8205
- const contractAddress = new Address5(transferParam.contractId);
8464
+ const amount = bn22(transferParam.amount);
8465
+ const contractAddress = new Address6(transferParam.contractId);
8206
8466
  const assetId = transferParam.assetId ? hexlify21(transferParam.assetId) : defaultAssetId;
8207
8467
  if (amount.lte(0)) {
8208
- throw new FuelError22(
8209
- ErrorCode19.INVALID_TRANSFER_AMOUNT,
8468
+ throw new FuelError23(
8469
+ ErrorCode20.INVALID_TRANSFER_AMOUNT,
8210
8470
  "Transfer amount must be a positive number."
8211
8471
  );
8212
8472
  }
@@ -8221,7 +8481,11 @@ var Account = class extends AbstractAccount {
8221
8481
  const { script, scriptData } = await assembleTransferToContractScript(transferParams);
8222
8482
  request.script = script;
8223
8483
  request.scriptData = scriptData;
8224
- const { gasPrice, transactionRequest } = await this.assembleTx(request, quantities);
8484
+ const { gasPrice, transactionRequest } = await this.assembleTx({
8485
+ transactionRequest: request,
8486
+ quantities,
8487
+ skipAutoConsolidation
8488
+ });
8225
8489
  request = await setAndValidateGasAndFeeForAssembledTx({
8226
8490
  gasPrice,
8227
8491
  provider: this.provider,
@@ -8237,15 +8501,16 @@ var Account = class extends AbstractAccount {
8237
8501
  * @param recipient - Address of the recipient on the base chain.
8238
8502
  * @param amount - Amount of base asset.
8239
8503
  * @param txParams - The transaction parameters (optional).
8504
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
8240
8505
  * @returns A promise that resolves to the transaction response.
8241
8506
  */
8242
- async withdrawToBaseLayer(recipient, amount, txParams = {}) {
8243
- const recipientAddress = new Address5(recipient);
8507
+ async withdrawToBaseLayer(recipient, amount, txParams = {}, { skipAutoConsolidation } = {}) {
8508
+ const recipientAddress = new Address6(recipient);
8244
8509
  const recipientDataArray = arrayify18(
8245
8510
  "0x".concat(recipientAddress.toHexString().substring(2).padStart(64, "0"))
8246
8511
  );
8247
8512
  const amountDataArray = arrayify18(
8248
- "0x".concat(bn21(amount).toHex().substring(2).padStart(16, "0"))
8513
+ "0x".concat(bn22(amount).toHex().substring(2).padStart(16, "0"))
8249
8514
  );
8250
8515
  const script = new Uint8Array([
8251
8516
  ...arrayify18(withdrawScript.bytes),
@@ -8255,8 +8520,12 @@ var Account = class extends AbstractAccount {
8255
8520
  const params = { script, ...txParams };
8256
8521
  const baseAssetId = await this.provider.getBaseAssetId();
8257
8522
  let request = new ScriptTransactionRequest(params);
8258
- const quantities = [{ amount: bn21(amount), assetId: baseAssetId }];
8259
- const { gasPrice, transactionRequest } = await this.assembleTx(request, quantities);
8523
+ const quantities = [{ amount: bn22(amount), assetId: baseAssetId }];
8524
+ const { gasPrice, transactionRequest } = await this.assembleTx({
8525
+ transactionRequest: request,
8526
+ quantities,
8527
+ skipAutoConsolidation
8528
+ });
8260
8529
  request = await setAndValidateGasAndFeeForAssembledTx({
8261
8530
  gasPrice,
8262
8531
  provider: this.provider,
@@ -8266,6 +8535,25 @@ var Account = class extends AbstractAccount {
8266
8535
  });
8267
8536
  return this.sendTransaction(request);
8268
8537
  }
8538
+ /**
8539
+ * Start the consolidation process
8540
+ *
8541
+ * @param owner - The B256 address of the owner.
8542
+ * @param assetId - The asset ID that requires consolidation.
8543
+ */
8544
+ async startConsolidation(opts) {
8545
+ if (this._connector) {
8546
+ await this._connector.startConsolidation(opts);
8547
+ return false;
8548
+ }
8549
+ const { owner, assetId } = opts;
8550
+ if (owner !== this.address.toB256()) {
8551
+ return false;
8552
+ }
8553
+ const { submitAll } = await consolidateCoins({ account: this, assetId });
8554
+ await submitAll();
8555
+ return true;
8556
+ }
8269
8557
  /**
8270
8558
  * Consolidates base asset UTXOs into fewer, larger ones.
8271
8559
  *
@@ -8285,6 +8573,7 @@ var Account = class extends AbstractAccount {
8285
8573
  const isBaseAsset = baseAssetId === assetId;
8286
8574
  let submitAll;
8287
8575
  const consolidationParams = {
8576
+ assetId,
8288
8577
  coins,
8289
8578
  mode: params.mode,
8290
8579
  outputNum: params.outputNum
@@ -8292,10 +8581,7 @@ var Account = class extends AbstractAccount {
8292
8581
  if (isBaseAsset) {
8293
8582
  ({ submitAll } = await this.assembleBaseAssetConsolidationTxs(consolidationParams));
8294
8583
  } else {
8295
- throw new FuelError22(
8296
- ErrorCode19.UNSUPPORTED_FEATURE,
8297
- "Consolidation for non-base assets is not supported yet."
8298
- );
8584
+ ({ submitAll } = await this.assembleNonBaseAssetConsolidationTxs(consolidationParams));
8299
8585
  }
8300
8586
  return submitAll();
8301
8587
  }
@@ -8316,7 +8602,7 @@ var Account = class extends AbstractAccount {
8316
8602
  this.validateConsolidationTxsCoins(coins, baseAssetId);
8317
8603
  const chainInfo = await this.provider.getChain();
8318
8604
  const maxInputsNumber = chainInfo.consensusParameters.txParameters.maxInputs.toNumber();
8319
- let totalFeeCost = bn21(0);
8605
+ let totalFeeCost = bn22(0);
8320
8606
  const txs = [];
8321
8607
  const coinsBatches = splitCoinsIntoBatches(coins, maxInputsNumber);
8322
8608
  const gasPrice = await this.provider.estimateGasPrice(10);
@@ -8340,10 +8626,10 @@ var Account = class extends AbstractAccount {
8340
8626
  });
8341
8627
  request.maxFee = fee;
8342
8628
  if (consolidateMoreThanOneCoin) {
8343
- const total = request.inputs.filter(isRequestInputCoin).reduce((acc, input) => acc.add(input.amount), bn21(0));
8629
+ const total = request.inputs.filter(isRequestInputCoin).reduce((acc, input) => acc.add(input.amount), bn22(0));
8344
8630
  const amountPerNewUtxo = total.div(outputNum + 1);
8345
8631
  request.outputs.forEach((output) => {
8346
- if (output.type === OutputType9.Coin) {
8632
+ if (output.type === OutputType10.Coin) {
8347
8633
  output.amount = amountPerNewUtxo;
8348
8634
  }
8349
8635
  });
@@ -8354,6 +8640,70 @@ var Account = class extends AbstractAccount {
8354
8640
  const submitAll = this.prepareSubmitAll({ txs, mode });
8355
8641
  return { txs, totalFeeCost, submitAll };
8356
8642
  }
8643
+ async assembleNonBaseAssetConsolidationTxs(params) {
8644
+ const { assetId, coins, mode = "parallel", outputNum = 1 } = params;
8645
+ this.validateConsolidationTxsCoins(coins, assetId);
8646
+ const chainInfo = await this.provider.getChain();
8647
+ const maxInputsNumber = chainInfo.consensusParameters.txParameters.maxInputs.toNumber();
8648
+ const baseAssetId = chainInfo.consensusParameters.baseAssetId;
8649
+ const { coins: baseAssetCoins } = await this.provider.getCoins(this.address, baseAssetId);
8650
+ let totalFeeCost = bn22(0);
8651
+ const txs = [];
8652
+ const gasPrice = await this.provider.estimateGasPrice(10);
8653
+ const consolidateMoreThanOneCoin = outputNum > 1;
8654
+ const assetCoinBatches = splitCoinsIntoBatches(coins, maxInputsNumber);
8655
+ assetCoinBatches.filter((batch) => batch.length > 1).forEach((coinBatch) => {
8656
+ const request = new ScriptTransactionRequest({
8657
+ script: "0x"
8658
+ });
8659
+ request.addResources(coinBatch);
8660
+ if (consolidateMoreThanOneCoin) {
8661
+ Array.from({ length: outputNum - 1 }).forEach(() => {
8662
+ request.addCoinOutput(this.address, 0, assetId);
8663
+ });
8664
+ }
8665
+ const minGas = request.calculateMinGas(chainInfo);
8666
+ const fee = calculateGasFee({
8667
+ gasPrice,
8668
+ gas: minGas,
8669
+ priceFactor: chainInfo.consensusParameters.feeParameters.gasPriceFactor,
8670
+ tip: request.tip
8671
+ });
8672
+ request.maxFee = fee;
8673
+ if (consolidateMoreThanOneCoin) {
8674
+ const total = request.inputs.filter(isRequestInputCoin).reduce((acc, input) => acc.add(input.amount), bn22(0));
8675
+ const amountPerNewUtxo = total.div(outputNum + 1);
8676
+ request.outputs.forEach((output) => {
8677
+ if (output.type === OutputType10.Coin) {
8678
+ output.amount = amountPerNewUtxo;
8679
+ }
8680
+ });
8681
+ }
8682
+ totalFeeCost = totalFeeCost.add(fee);
8683
+ const baseAssetResources = [];
8684
+ let fundingFeeTotal = bn22(0);
8685
+ while (fundingFeeTotal.lt(fee)) {
8686
+ const baseAssetCoin = baseAssetCoins.pop();
8687
+ if (!baseAssetCoin) {
8688
+ break;
8689
+ }
8690
+ baseAssetResources.push(baseAssetCoin);
8691
+ fundingFeeTotal = fundingFeeTotal.add(baseAssetCoin.amount);
8692
+ }
8693
+ const { inputs } = request;
8694
+ request.inputs = inputs.slice(0, maxInputsNumber - baseAssetResources.length);
8695
+ const removedCoins = coinBatch.slice(maxInputsNumber - baseAssetResources.length);
8696
+ request.addResources(baseAssetResources);
8697
+ const lastCoinBatch = assetCoinBatches[assetCoinBatches.length - 1];
8698
+ lastCoinBatch.push(...removedCoins);
8699
+ if (lastCoinBatch.length > maxInputsNumber) {
8700
+ assetCoinBatches.push(lastCoinBatch.slice(maxInputsNumber));
8701
+ }
8702
+ txs.push(request);
8703
+ });
8704
+ const submitAll = this.prepareSubmitAll({ txs, mode });
8705
+ return { txs, totalFeeCost, submitAll };
8706
+ }
8357
8707
  /**
8358
8708
  * Prepares a function to submit all transactions either sequentially or in parallel.
8359
8709
  *
@@ -8412,7 +8762,7 @@ var Account = class extends AbstractAccount {
8412
8762
  const baseAssetId = await this.provider.getBaseAssetId();
8413
8763
  const coinOutputsQuantities = txRequestClone.getCoinOutputsQuantities();
8414
8764
  const requiredQuantities = mergeQuantities(coinOutputsQuantities, quantities);
8415
- const transactionFeeForDryRun = [{ assetId: baseAssetId, amount: bn21("100000000000000000") }];
8765
+ const transactionFeeForDryRun = [{ assetId: baseAssetId, amount: bn22("100000000000000000") }];
8416
8766
  const findAssetInput = /* @__PURE__ */ __name((assetId) => txRequestClone.inputs.find((input) => {
8417
8767
  if (input.type === InputType8.Coin) {
8418
8768
  return input.assetId === assetId;
@@ -8460,7 +8810,7 @@ var Account = class extends AbstractAccount {
8460
8810
  */
8461
8811
  async signMessage(message) {
8462
8812
  if (!this._connector) {
8463
- throw new FuelError22(ErrorCode19.MISSING_CONNECTOR, "A connector is required to sign messages.");
8813
+ throw new FuelError23(ErrorCode20.MISSING_CONNECTOR, "A connector is required to sign messages.");
8464
8814
  }
8465
8815
  return this._connector.signMessage(this.address.toString(), message);
8466
8816
  }
@@ -8472,8 +8822,8 @@ var Account = class extends AbstractAccount {
8472
8822
  */
8473
8823
  async signTransaction(transactionRequestLike, connectorOptions = {}) {
8474
8824
  if (!this._connector) {
8475
- throw new FuelError22(
8476
- ErrorCode19.MISSING_CONNECTOR,
8825
+ throw new FuelError23(
8826
+ ErrorCode20.MISSING_CONNECTOR,
8477
8827
  "A connector is required to sign transactions."
8478
8828
  );
8479
8829
  }
@@ -8540,8 +8890,8 @@ var Account = class extends AbstractAccount {
8540
8890
  return coins.map((coin) => ({
8541
8891
  id: hexlify21(randomBytes5(UTXO_ID_LEN3)),
8542
8892
  owner: this.address,
8543
- blockCreated: bn21(1),
8544
- txCreatedIdx: bn21(1),
8893
+ blockCreated: bn22(1),
8894
+ txCreatedIdx: bn22(1),
8545
8895
  ...coin
8546
8896
  }));
8547
8897
  }
@@ -8568,73 +8918,50 @@ var Account = class extends AbstractAccount {
8568
8918
  } : void 0;
8569
8919
  }
8570
8920
  /** @hidden * */
8571
- async assembleTx(transactionRequest, quantities = []) {
8572
- const outputQuantities = transactionRequest.outputs.filter((o) => o.type === OutputType9.Coin).map(({ amount, assetId }) => ({ assetId: String(assetId), amount: bn21(amount) }));
8573
- transactionRequest.gasLimit = bn21(0);
8574
- transactionRequest.maxFee = bn21(0);
8575
- const { assembledRequest, gasPrice } = await this.provider.assembleTx({
8576
- request: transactionRequest,
8577
- accountCoinQuantities: mergeQuantities(outputQuantities, quantities),
8578
- feePayerAccount: this
8579
- });
8580
- return { transactionRequest: assembledRequest, gasPrice };
8921
+ async assembleTx(opts) {
8922
+ const { transactionRequest, quantities = [], skipAutoConsolidation } = opts;
8923
+ const outputQuantities = transactionRequest.outputs.filter((o) => o.type === OutputType10.Coin).map(({ amount, assetId }) => ({ assetId: String(assetId), amount: bn22(amount) }));
8924
+ transactionRequest.gasLimit = bn22(0);
8925
+ transactionRequest.maxFee = bn22(0);
8926
+ const assembleTx = /* @__PURE__ */ __name(async () => {
8927
+ const { assembledRequest, gasPrice } = await this.provider.assembleTx({
8928
+ request: transactionRequest,
8929
+ accountCoinQuantities: mergeQuantities(outputQuantities, quantities),
8930
+ feePayerAccount: this
8931
+ });
8932
+ return { transactionRequest: assembledRequest, gasPrice };
8933
+ }, "assembleTx");
8934
+ try {
8935
+ return await assembleTx();
8936
+ } catch (error) {
8937
+ const shouldRetry = await consolidateCoinsIfRequired({
8938
+ error,
8939
+ account: this,
8940
+ skipAutoConsolidation
8941
+ });
8942
+ if (!shouldRetry) {
8943
+ throw error;
8944
+ }
8945
+ return await assembleTx();
8946
+ }
8581
8947
  }
8582
8948
  /** @hidden * */
8583
8949
  validateTransferAmount(amount) {
8584
- if (bn21(amount).lte(0)) {
8585
- throw new FuelError22(
8586
- ErrorCode19.INVALID_TRANSFER_AMOUNT,
8950
+ if (bn22(amount).lte(0)) {
8951
+ throw new FuelError23(
8952
+ ErrorCode20.INVALID_TRANSFER_AMOUNT,
8587
8953
  "Transfer amount must be a positive number."
8588
8954
  );
8589
8955
  }
8590
8956
  }
8591
8957
  /** @hidden * */
8592
- async estimateAndFundTransaction(transactionRequest, txParams, costParams) {
8593
- let request = transactionRequest;
8594
- const txCost = await this.getTransactionCost(request, costParams);
8595
- request = this.validateGasLimitAndMaxFee({
8596
- transactionRequest: request,
8597
- gasUsed: txCost.gasUsed,
8598
- maxFee: txCost.maxFee,
8599
- txParams
8600
- });
8601
- request = await this.fund(request, txCost);
8602
- return request;
8603
- }
8604
- /** @hidden * */
8605
- validateGasLimitAndMaxFee({
8606
- gasUsed,
8607
- maxFee,
8608
- transactionRequest,
8609
- txParams: { gasLimit: setGasLimit, maxFee: setMaxFee }
8610
- }) {
8611
- const request = transactionRequestify(transactionRequest);
8612
- if (!isDefined4(setGasLimit)) {
8613
- request.gasLimit = gasUsed;
8614
- } else if (gasUsed.gt(setGasLimit)) {
8615
- throw new FuelError22(
8616
- ErrorCode19.GAS_LIMIT_TOO_LOW,
8617
- `Gas limit '${setGasLimit}' is lower than the required: '${gasUsed}'.`
8618
- );
8619
- }
8620
- if (!isDefined4(setMaxFee)) {
8621
- request.maxFee = maxFee;
8622
- } else if (maxFee.gt(setMaxFee)) {
8623
- throw new FuelError22(
8624
- ErrorCode19.MAX_FEE_TOO_LOW,
8625
- `Max fee '${setMaxFee}' is lower than the required: '${maxFee}'.`
8626
- );
8627
- }
8628
- return request;
8629
- }
8630
- /** @hidden * */
8631
8958
  validateConsolidationTxsCoins(coins, assetId) {
8632
8959
  if (coins.length <= 1) {
8633
- throw new FuelError22(ErrorCode19.NO_COINS_TO_CONSOLIDATE, "No coins to consolidate.");
8960
+ throw new FuelError23(ErrorCode20.NO_COINS_TO_CONSOLIDATE, "No coins to consolidate.");
8634
8961
  }
8635
8962
  if (!coins.every((c) => c.assetId === assetId)) {
8636
- throw new FuelError22(
8637
- ErrorCode19.COINS_ASSET_ID_MISMATCH,
8963
+ throw new FuelError23(
8964
+ ErrorCode20.COINS_ASSET_ID_MISMATCH,
8638
8965
  "All coins to consolidate must be from the same asset id."
8639
8966
  );
8640
8967
  }
@@ -8659,7 +8986,7 @@ var Account = class extends AbstractAccount {
8659
8986
  };
8660
8987
 
8661
8988
  // src/wallet/keystore-wallet.ts
8662
- import { Address as Address6 } from "@fuel-ts/address";
8989
+ import { Address as Address7 } from "@fuel-ts/address";
8663
8990
  import {
8664
8991
  bufferFromString,
8665
8992
  keccak256,
@@ -8670,7 +8997,7 @@ import {
8670
8997
  encryptJsonWalletData,
8671
8998
  randomUUID as randomUUID2
8672
8999
  } from "@fuel-ts/crypto";
8673
- import { ErrorCode as ErrorCode20, FuelError as FuelError23 } from "@fuel-ts/errors";
9000
+ import { ErrorCode as ErrorCode21, FuelError as FuelError24 } from "@fuel-ts/errors";
8674
9001
  import { hexlify as hexlify22 } from "@fuel-ts/utils";
8675
9002
  var DEFAULT_KDF_PARAMS_LOG_N = 13;
8676
9003
  var DEFAULT_KDF_PARAMS_R = 8;
@@ -8685,7 +9012,7 @@ var removeHexPrefix = /* @__PURE__ */ __name((hexString) => {
8685
9012
  }, "removeHexPrefix");
8686
9013
  async function encryptKeystoreWallet(privateKey, address, password) {
8687
9014
  const privateKeyBuffer = bufferFromString(removeHexPrefix(privateKey), "hex");
8688
- const ownerAddress = new Address6(address);
9015
+ const ownerAddress = new Address7(address);
8689
9016
  const salt = randomBytes6(DEFAULT_KEY_SIZE);
8690
9017
  const key = scrypt({
8691
9018
  password: bufferFromString(password),
@@ -8748,8 +9075,8 @@ async function decryptKeystoreWallet(jsonWallet, password) {
8748
9075
  const macHashUint8Array = keccak256(data);
8749
9076
  const macHash = stringFromBuffer(macHashUint8Array, "hex");
8750
9077
  if (mac !== macHash) {
8751
- throw new FuelError23(
8752
- ErrorCode20.INVALID_PASSWORD,
9078
+ throw new FuelError24(
9079
+ ErrorCode21.INVALID_PASSWORD,
8753
9080
  "Failed to decrypt the keystore wallet, the provided password is incorrect."
8754
9081
  );
8755
9082
  }
@@ -8888,14 +9215,14 @@ var BaseWalletUnlocked = class extends Account {
8888
9215
 
8889
9216
  // src/hdwallet/hdwallet.ts
8890
9217
  import { computeHmac as computeHmac2, ripemd160 } from "@fuel-ts/crypto";
8891
- import { ErrorCode as ErrorCode23, FuelError as FuelError26 } from "@fuel-ts/errors";
9218
+ import { ErrorCode as ErrorCode24, FuelError as FuelError27 } from "@fuel-ts/errors";
8892
9219
  import { sha256 as sha2564 } from "@fuel-ts/hasher";
8893
- import { bn as bn22, toBytes as toBytes3, toHex } from "@fuel-ts/math";
9220
+ import { bn as bn23, toBytes as toBytes3, toHex } from "@fuel-ts/math";
8894
9221
  import { arrayify as arrayify21, hexlify as hexlify25, concat as concat7, dataSlice as dataSlice2, encodeBase58 as encodeBase582, decodeBase58 } from "@fuel-ts/utils";
8895
9222
 
8896
9223
  // src/mnemonic/mnemonic.ts
8897
9224
  import { randomBytes as randomBytes7, pbkdf2, computeHmac } from "@fuel-ts/crypto";
8898
- import { ErrorCode as ErrorCode22, FuelError as FuelError25 } from "@fuel-ts/errors";
9225
+ import { ErrorCode as ErrorCode23, FuelError as FuelError26 } from "@fuel-ts/errors";
8899
9226
  import { sha256 as sha2563 } from "@fuel-ts/hasher";
8900
9227
  import { arrayify as arrayify20, hexlify as hexlify24, concat as concat6, dataSlice, encodeBase58, toUtf8Bytes } from "@fuel-ts/utils";
8901
9228
 
@@ -10952,7 +11279,7 @@ var english = [
10952
11279
  ];
10953
11280
 
10954
11281
  // src/mnemonic/utils.ts
10955
- import { ErrorCode as ErrorCode21, FuelError as FuelError24 } from "@fuel-ts/errors";
11282
+ import { ErrorCode as ErrorCode22, FuelError as FuelError25 } from "@fuel-ts/errors";
10956
11283
  import { sha256 as sha2562 } from "@fuel-ts/hasher";
10957
11284
  import { arrayify as arrayify19 } from "@fuel-ts/utils";
10958
11285
  function getLowerMask(bits) {
@@ -11006,8 +11333,8 @@ function mnemonicWordsToEntropy(words, wordlist) {
11006
11333
  for (let i = 0; i < words.length; i += 1) {
11007
11334
  const index = wordlist.indexOf(words[i].normalize("NFKD"));
11008
11335
  if (index === -1) {
11009
- throw new FuelError24(
11010
- ErrorCode21.INVALID_MNEMONIC,
11336
+ throw new FuelError25(
11337
+ ErrorCode22.INVALID_MNEMONIC,
11011
11338
  `Invalid mnemonic: the word '${words[i]}' is not found in the provided wordlist.`
11012
11339
  );
11013
11340
  }
@@ -11023,8 +11350,8 @@ function mnemonicWordsToEntropy(words, wordlist) {
11023
11350
  const checksumMask = getUpperMask(checksumBits);
11024
11351
  const checksum = arrayify19(sha2562(entropy.slice(0, entropyBits / 8)))[0] & checksumMask;
11025
11352
  if (checksum !== (entropy[entropy.length - 1] & checksumMask)) {
11026
- throw new FuelError24(
11027
- ErrorCode21.INVALID_CHECKSUM,
11353
+ throw new FuelError25(
11354
+ ErrorCode22.INVALID_CHECKSUM,
11028
11355
  "Checksum validation failed for the provided mnemonic."
11029
11356
  );
11030
11357
  }
@@ -11039,8 +11366,8 @@ var TestnetPRV = "0x04358394";
11039
11366
  var MNEMONIC_SIZES = [12, 15, 18, 21, 24];
11040
11367
  function assertWordList(wordlist) {
11041
11368
  if (wordlist.length !== 2048) {
11042
- throw new FuelError25(
11043
- ErrorCode22.INVALID_WORD_LIST,
11369
+ throw new FuelError26(
11370
+ ErrorCode23.INVALID_WORD_LIST,
11044
11371
  `Expected word list length of 2048, but got ${wordlist.length}.`
11045
11372
  );
11046
11373
  }
@@ -11048,8 +11375,8 @@ function assertWordList(wordlist) {
11048
11375
  __name(assertWordList, "assertWordList");
11049
11376
  function assertEntropy(entropy) {
11050
11377
  if (entropy.length % 4 !== 0 || entropy.length < 16 || entropy.length > 32) {
11051
- throw new FuelError25(
11052
- ErrorCode22.INVALID_ENTROPY,
11378
+ throw new FuelError26(
11379
+ ErrorCode23.INVALID_ENTROPY,
11053
11380
  `Entropy should be between 16 and 32 bytes and a multiple of 4, but got ${entropy.length} bytes.`
11054
11381
  );
11055
11382
  }
@@ -11060,7 +11387,7 @@ function assertMnemonic(words) {
11060
11387
  const errorMsg = `Invalid mnemonic size. Expected one of [${MNEMONIC_SIZES.join(
11061
11388
  ", "
11062
11389
  )}] words, but got ${words.length}.`;
11063
- throw new FuelError25(ErrorCode22.INVALID_MNEMONIC, errorMsg);
11390
+ throw new FuelError26(ErrorCode23.INVALID_MNEMONIC, errorMsg);
11064
11391
  }
11065
11392
  }
11066
11393
  __name(assertMnemonic, "assertMnemonic");
@@ -11182,8 +11509,8 @@ var Mnemonic = class _Mnemonic {
11182
11509
  static masterKeysFromSeed(seed) {
11183
11510
  const seedArray = arrayify20(seed);
11184
11511
  if (seedArray.length < 16 || seedArray.length > 64) {
11185
- throw new FuelError25(
11186
- ErrorCode22.INVALID_SEED,
11512
+ throw new FuelError26(
11513
+ ErrorCode23.INVALID_SEED,
11187
11514
  `Seed length should be between 16 and 64 bytes, but received ${seedArray.length} bytes.`
11188
11515
  );
11189
11516
  }
@@ -11264,7 +11591,7 @@ __name(isValidExtendedKey, "isValidExtendedKey");
11264
11591
  function parsePath(path2, depth = 0) {
11265
11592
  const components = path2.split("/");
11266
11593
  if (components.length === 0 || components[0] === "m" && depth !== 0) {
11267
- throw new FuelError26(ErrorCode23.HD_WALLET_ERROR, `invalid path - ${path2}`);
11594
+ throw new FuelError27(ErrorCode24.HD_WALLET_ERROR, `invalid path - ${path2}`);
11268
11595
  }
11269
11596
  if (components[0] === "m") {
11270
11597
  components.shift();
@@ -11297,8 +11624,8 @@ var HDWallet = class _HDWallet {
11297
11624
  this.privateKey = hexlify25(config.privateKey);
11298
11625
  } else {
11299
11626
  if (!config.publicKey) {
11300
- throw new FuelError26(
11301
- ErrorCode23.HD_WALLET_ERROR,
11627
+ throw new FuelError27(
11628
+ ErrorCode24.HD_WALLET_ERROR,
11302
11629
  "Both public and private Key cannot be missing. At least one should be provided."
11303
11630
  );
11304
11631
  }
@@ -11327,8 +11654,8 @@ var HDWallet = class _HDWallet {
11327
11654
  const data = new Uint8Array(37);
11328
11655
  if (index & HARDENED_INDEX) {
11329
11656
  if (!privateKey) {
11330
- throw new FuelError26(
11331
- ErrorCode23.HD_WALLET_ERROR,
11657
+ throw new FuelError27(
11658
+ ErrorCode24.HD_WALLET_ERROR,
11332
11659
  "Cannot derive a hardened index without a private Key."
11333
11660
  );
11334
11661
  }
@@ -11342,7 +11669,7 @@ var HDWallet = class _HDWallet {
11342
11669
  const IR = bytes.slice(32);
11343
11670
  if (privateKey) {
11344
11671
  const N = "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141";
11345
- const ki = bn22(IL).add(privateKey).mod(N).toBytes(32);
11672
+ const ki = bn23(IL).add(privateKey).mod(N).toBytes(32);
11346
11673
  return new _HDWallet({
11347
11674
  privateKey: ki,
11348
11675
  chainCode: IR,
@@ -11380,8 +11707,8 @@ var HDWallet = class _HDWallet {
11380
11707
  */
11381
11708
  toExtendedKey(isPublic = false, testnet = false) {
11382
11709
  if (this.depth >= 256) {
11383
- throw new FuelError26(
11384
- ErrorCode23.HD_WALLET_ERROR,
11710
+ throw new FuelError27(
11711
+ ErrorCode24.HD_WALLET_ERROR,
11385
11712
  `Exceeded max depth of 255. Current depth: ${this.depth}.`
11386
11713
  );
11387
11714
  }
@@ -11412,10 +11739,10 @@ var HDWallet = class _HDWallet {
11412
11739
  const bytes = arrayify21(decoded);
11413
11740
  const validChecksum = base58check(bytes.slice(0, 78)) === extendedKey;
11414
11741
  if (bytes.length !== 82 || !isValidExtendedKey(bytes)) {
11415
- throw new FuelError26(ErrorCode23.HD_WALLET_ERROR, "Provided key is not a valid extended key.");
11742
+ throw new FuelError27(ErrorCode24.HD_WALLET_ERROR, "Provided key is not a valid extended key.");
11416
11743
  }
11417
11744
  if (!validChecksum) {
11418
- throw new FuelError26(ErrorCode23.HD_WALLET_ERROR, "Provided key has an invalid checksum.");
11745
+ throw new FuelError27(ErrorCode24.HD_WALLET_ERROR, "Provided key has an invalid checksum.");
11419
11746
  }
11420
11747
  const depth = bytes[4];
11421
11748
  const parentFingerprint = hexlify25(bytes.slice(5, 9));
@@ -11423,14 +11750,14 @@ var HDWallet = class _HDWallet {
11423
11750
  const chainCode = hexlify25(bytes.slice(13, 45));
11424
11751
  const key = bytes.slice(45, 78);
11425
11752
  if (depth === 0 && parentFingerprint !== "0x00000000" || depth === 0 && index !== 0) {
11426
- throw new FuelError26(
11427
- ErrorCode23.HD_WALLET_ERROR,
11753
+ throw new FuelError27(
11754
+ ErrorCode24.HD_WALLET_ERROR,
11428
11755
  "Inconsistency detected: Depth is zero but fingerprint/index is non-zero."
11429
11756
  );
11430
11757
  }
11431
11758
  if (isPublicExtendedKey(bytes)) {
11432
11759
  if (key[0] !== 3) {
11433
- throw new FuelError26(ErrorCode23.HD_WALLET_ERROR, "Invalid public extended key.");
11760
+ throw new FuelError27(ErrorCode24.HD_WALLET_ERROR, "Invalid public extended key.");
11434
11761
  }
11435
11762
  return new _HDWallet({
11436
11763
  publicKey: key,
@@ -11441,7 +11768,7 @@ var HDWallet = class _HDWallet {
11441
11768
  });
11442
11769
  }
11443
11770
  if (key[0] !== 0) {
11444
- throw new FuelError26(ErrorCode23.HD_WALLET_ERROR, "Invalid private extended key.");
11771
+ throw new FuelError27(ErrorCode24.HD_WALLET_ERROR, "Invalid private extended key.");
11445
11772
  }
11446
11773
  return new _HDWallet({
11447
11774
  privateKey: key.slice(1),
@@ -11677,7 +12004,7 @@ var WalletsConfig = class _WalletsConfig {
11677
12004
  assetIds.forEach((assetId) => {
11678
12005
  for (let index = 0; index < coinsPerAsset; index++) {
11679
12006
  coins.push({
11680
- amount: bn23(amountPerCoin).toString(),
12007
+ amount: bn24(amountPerCoin).toString(),
11681
12008
  asset_id: assetId,
11682
12009
  owner: walletAddress,
11683
12010
  tx_pointer_block_height: 0,
@@ -11697,26 +12024,26 @@ var WalletsConfig = class _WalletsConfig {
11697
12024
  amountPerCoin
11698
12025
  }) {
11699
12026
  if (Array.isArray(wallets) && wallets.length === 0 || typeof wallets === "number" && wallets <= 0) {
11700
- throw new FuelError27(
11701
- FuelError27.CODES.INVALID_INPUT_PARAMETERS,
12027
+ throw new FuelError28(
12028
+ FuelError28.CODES.INVALID_INPUT_PARAMETERS,
11702
12029
  "Number of wallets must be greater than zero."
11703
12030
  );
11704
12031
  }
11705
12032
  if (Array.isArray(assets) && assets.length === 0 || typeof assets === "number" && assets <= 0) {
11706
- throw new FuelError27(
11707
- FuelError27.CODES.INVALID_INPUT_PARAMETERS,
12033
+ throw new FuelError28(
12034
+ FuelError28.CODES.INVALID_INPUT_PARAMETERS,
11708
12035
  "Number of assets per wallet must be greater than zero."
11709
12036
  );
11710
12037
  }
11711
12038
  if (coinsPerAsset <= 0) {
11712
- throw new FuelError27(
11713
- FuelError27.CODES.INVALID_INPUT_PARAMETERS,
12039
+ throw new FuelError28(
12040
+ FuelError28.CODES.INVALID_INPUT_PARAMETERS,
11714
12041
  "Number of coins per asset must be greater than zero."
11715
12042
  );
11716
12043
  }
11717
- if (bn23(amountPerCoin).lt(0)) {
11718
- throw new FuelError27(
11719
- FuelError27.CODES.INVALID_INPUT_PARAMETERS,
12044
+ if (bn24(amountPerCoin).lt(0)) {
12045
+ throw new FuelError28(
12046
+ FuelError28.CODES.INVALID_INPUT_PARAMETERS,
11720
12047
  "Amount per coin must be greater than or equal to zero."
11721
12048
  );
11722
12049
  }
@@ -11792,9 +12119,9 @@ async function setupTestProviderAndWallets({
11792
12119
  __name(setupTestProviderAndWallets, "setupTestProviderAndWallets");
11793
12120
 
11794
12121
  // src/test-utils/test-message.ts
11795
- import { Address as Address7 } from "@fuel-ts/address";
12122
+ import { Address as Address8 } from "@fuel-ts/address";
11796
12123
  import { randomBytes as randomBytes9 } from "@fuel-ts/crypto";
11797
- import { bn as bn24 } from "@fuel-ts/math";
12124
+ import { bn as bn25 } from "@fuel-ts/math";
11798
12125
  import { hexlify as hexlify27 } from "@fuel-ts/utils";
11799
12126
  var TestMessage = class {
11800
12127
  static {
@@ -11813,8 +12140,8 @@ var TestMessage = class {
11813
12140
  * It can also be used standalone and passed into the initial state of a chain via the `.toChainMessage` method.
11814
12141
  */
11815
12142
  constructor({
11816
- sender = Address7.fromRandom(),
11817
- recipient = Address7.fromRandom(),
12143
+ sender = Address8.fromRandom(),
12144
+ recipient = Address8.fromRandom(),
11818
12145
  nonce = hexlify27(randomBytes9(32)),
11819
12146
  amount = 1e6,
11820
12147
  data = "",
@@ -11834,7 +12161,7 @@ var TestMessage = class {
11834
12161
  sender: this.sender.toB256(),
11835
12162
  recipient: recipient?.toB256() ?? this.recipient.toB256(),
11836
12163
  nonce: this.nonce,
11837
- amount: bn24(this.amount).toNumber(),
12164
+ amount: bn25(this.amount).toNumber(),
11838
12165
  data,
11839
12166
  da_height: this.da_height
11840
12167
  };