@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
@@ -17289,7 +17289,7 @@
17289
17289
  return {
17290
17290
  FUEL_CORE: "0.43.1",
17291
17291
  FORC: "0.68.7",
17292
- FUELS: "0.101.2"
17292
+ FUELS: "0.101.3"
17293
17293
  };
17294
17294
  }
17295
17295
  __name(getBuiltinVersions, "getBuiltinVersions");
@@ -17402,6 +17402,7 @@ This unreleased fuel-core build may include features and updates not yet support
17402
17402
  ErrorCode2["CONNECTION_REFUSED"] = "connection-refused";
17403
17403
  ErrorCode2["INVALID_URL"] = "invalid-url";
17404
17404
  ErrorCode2["UNSUPPORTED_FEATURE"] = "unsupported-feature";
17405
+ ErrorCode2["RESPONSE_BODY_EMPTY"] = "response-body-empty";
17405
17406
  ErrorCode2["INVALID_PUBLIC_KEY"] = "invalid-public-key";
17406
17407
  ErrorCode2["WALLET_MANAGER_ERROR"] = "wallet-manager-error";
17407
17408
  ErrorCode2["HD_WALLET_ERROR"] = "hd-wallet-error";
@@ -17420,6 +17421,8 @@ This unreleased fuel-core build may include features and updates not yet support
17420
17421
  ErrorCode2["INVALID_REQUEST"] = "invalid-request";
17421
17422
  ErrorCode2["INVALID_TRANSFER_AMOUNT"] = "invalid-transfer-amount";
17422
17423
  ErrorCode2["INSUFFICIENT_FUNDS_OR_MAX_COINS"] = "not-enough-funds-or-max-coins-reached";
17424
+ ErrorCode2["INSUFFICIENT_FUNDS"] = "not-enough-funds";
17425
+ ErrorCode2["MAX_COINS_REACHED"] = "max-coins-reached";
17423
17426
  ErrorCode2["INVALID_CREDENTIALS"] = "invalid-credentials";
17424
17427
  ErrorCode2["HASHER_LOCKED"] = "hasher-locked";
17425
17428
  ErrorCode2["GAS_PRICE_TOO_LOW"] = "gas-price-too-low";
@@ -17453,6 +17456,7 @@ This unreleased fuel-core build may include features and updates not yet support
17453
17456
  ErrorCode2["INVALID_PASSWORD"] = "invalid-password";
17454
17457
  ErrorCode2["ACCOUNT_REQUIRED"] = "account-required";
17455
17458
  ErrorCode2["UNLOCKED_WALLET_REQUIRED"] = "unlocked-wallet-required";
17459
+ ErrorCode2["UNABLE_TO_CONSOLIDATE_COINS"] = "unable-to-consolidate-coins";
17456
17460
  ErrorCode2["NO_COINS_TO_CONSOLIDATE"] = "no-coins-to-consolidate";
17457
17461
  ErrorCode2["COINS_ASSET_ID_MISMATCH"] = "coins-asset-id-mismatch";
17458
17462
  ErrorCode2["ASSET_NOT_FOUND"] = "asset-not-found";
@@ -17494,7 +17498,7 @@ This unreleased fuel-core build may include features and updates not yet support
17494
17498
  `Unknown error code: ${error2.code}. Accepted codes: ${enumValues.join(", ")}.`
17495
17499
  );
17496
17500
  }
17497
- return new _FuelError(error2.code, error2.message);
17501
+ return new _FuelError(error2.code, error2.message, error2.metadata, error2.rawError);
17498
17502
  }
17499
17503
  code;
17500
17504
  constructor(code, message, metadata = {}, rawError = null) {
@@ -23343,8 +23347,9 @@ If you are attempting to transform a hex value, please make sure it is being pas
23343
23347
  "--consensus-key",
23344
23348
  "--db-type",
23345
23349
  "--poa-instant",
23350
+ "--native-executor-version",
23346
23351
  "--min-gas-price",
23347
- "--native-executor-version"
23352
+ "--starting-gas-price"
23348
23353
  ]);
23349
23354
  const snapshotDir = getFlagValueFromArgs(args, "--snapshot");
23350
23355
  const consensusKey = getFlagValueFromArgs(args, "--consensus-key") || defaultConsensusKey;
@@ -23568,6 +23573,11 @@ If you are attempting to transform a hex value, please make sure it is being pas
23568
23573
  }
23569
23574
  __name(_curry3, "_curry3");
23570
23575
 
23576
+ // ../../node_modules/.pnpm/ramda@0.30.1/node_modules/ramda/es/internal/_isArray.js
23577
+ var isArray_default = Array.isArray || /* @__PURE__ */ __name(function _isArray(val) {
23578
+ return val != null && val.length >= 0 && Object.prototype.toString.call(val) === "[object Array]";
23579
+ }, "_isArray");
23580
+
23571
23581
  // ../../node_modules/.pnpm/ramda@0.30.1/node_modules/ramda/es/internal/_has.js
23572
23582
  function _has(prop, obj) {
23573
23583
  return Object.prototype.hasOwnProperty.call(obj, prop);
@@ -23698,6 +23708,25 @@ If you are attempting to transform a hex value, please make sure it is being pas
23698
23708
  }, "clone"));
23699
23709
  var clone_default = clone;
23700
23710
 
23711
+ // ../../node_modules/.pnpm/ramda@0.30.1/node_modules/ramda/es/internal/_checkForMethod.js
23712
+ function _checkForMethod(methodname, fn) {
23713
+ return function() {
23714
+ var length = arguments.length;
23715
+ if (length === 0) {
23716
+ return fn();
23717
+ }
23718
+ var obj = arguments[length - 1];
23719
+ return isArray_default(obj) || typeof obj[methodname] !== "function" ? fn.apply(this, arguments) : obj[methodname].apply(obj, Array.prototype.slice.call(arguments, 0, length - 1));
23720
+ };
23721
+ }
23722
+ __name(_checkForMethod, "_checkForMethod");
23723
+
23724
+ // ../../node_modules/.pnpm/ramda@0.30.1/node_modules/ramda/es/slice.js
23725
+ var slice = /* @__PURE__ */ _curry3(/* @__PURE__ */ _checkForMethod("slice", /* @__PURE__ */ __name(function slice2(fromIndex, toIndex, list) {
23726
+ return Array.prototype.slice.call(list, fromIndex, toIndex);
23727
+ }, "slice")));
23728
+ var slice_default = slice;
23729
+
23701
23730
  // ../../node_modules/.pnpm/ramda@0.30.1/node_modules/ramda/es/mergeWithKey.js
23702
23731
  var mergeWithKey = /* @__PURE__ */ _curry3(/* @__PURE__ */ __name(function mergeWithKey2(fn, l, r) {
23703
23732
  var result = {};
@@ -23738,6 +23767,20 @@ If you are attempting to transform a hex value, please make sure it is being pas
23738
23767
  }, "mergeDeepRight"));
23739
23768
  var mergeDeepRight_default = mergeDeepRight;
23740
23769
 
23770
+ // ../../node_modules/.pnpm/ramda@0.30.1/node_modules/ramda/es/splitEvery.js
23771
+ var splitEvery = /* @__PURE__ */ _curry2(/* @__PURE__ */ __name(function splitEvery2(n, list) {
23772
+ if (n <= 0) {
23773
+ throw new Error("First argument to splitEvery must be a positive integer");
23774
+ }
23775
+ var result = [];
23776
+ var idx = 0;
23777
+ while (idx < list.length) {
23778
+ result.push(slice_default(idx, idx += n, list));
23779
+ }
23780
+ return result;
23781
+ }, "splitEvery"));
23782
+ var splitEvery_default = splitEvery;
23783
+
23741
23784
  // src/providers/coin-quantity.ts
23742
23785
  var coinQuantityfy = /* @__PURE__ */ __name((coinQuantityLike) => {
23743
23786
  let assetId;
@@ -30394,8 +30437,11 @@ ${DryRunSuccessAssembleTxFragmentDoc}`;
30394
30437
  }, "setAndValidateGasAndFeeForAssembledTx");
30395
30438
 
30396
30439
  // src/providers/utils/handle-gql-error-message.ts
30440
+ var ASSET_ID_REGEX = /[0-9a-fA-F]{32,64}/g;
30397
30441
  var gqlErrorMessage = {
30398
30442
  RPC_CONSISTENCY: /The required fuel block height is higher than the current block height. Required: \d+, Current: \d+/,
30443
+ INSUFFICIENT_FUNDS: /the target cannot be met due to insufficient coins available for [0-9a-fA-F]{32,64}. Collected: \d+/,
30444
+ MAX_COINS_REACHED: /the target for [0-9a-fA-F]{32,64} cannot be met due to exceeding the \d+ coin limit. Collected: \d+./,
30399
30445
  NOT_ENOUGH_COINS_MAX_COINS: /the target cannot be met due to no coins available or exceeding the \d+ coin limit./,
30400
30446
  ASSET_NOT_FOUND: /resource was not found in table/,
30401
30447
  MULTIPLE_CHANGE_POLICIES: /The asset ([a-fA-F0-9]{64}) has multiple change policies/,
@@ -30411,6 +30457,46 @@ ${DryRunSuccessAssembleTxFragmentDoc}`;
30411
30457
  error2
30412
30458
  );
30413
30459
  }
30460
+ if (gqlErrorMessage.MAX_COINS_REACHED.test(error2.message)) {
30461
+ const matches = error2.message.match(ASSET_ID_REGEX);
30462
+ const assetId = matches ? `0x${matches[0]}` : null;
30463
+ const owner = matches ? `0x${matches[1]}` : null;
30464
+ let suffix = "";
30465
+ if (assetId) {
30466
+ suffix += `
30467
+ Asset ID: '${assetId}'.`;
30468
+ }
30469
+ if (owner) {
30470
+ suffix += `
30471
+ Owner: '${owner}'.`;
30472
+ }
30473
+ return new FuelError(
30474
+ ErrorCode.MAX_COINS_REACHED,
30475
+ `You have too many small value coins - consider combining UTXOs.${suffix}`,
30476
+ { assetId, owner },
30477
+ error2
30478
+ );
30479
+ }
30480
+ if (gqlErrorMessage.INSUFFICIENT_FUNDS.test(error2.message)) {
30481
+ const matches = error2.message.match(ASSET_ID_REGEX);
30482
+ const assetId = matches ? `0x${matches[0]}` : null;
30483
+ const owner = matches ? `0x${matches[1]}` : null;
30484
+ let suffix = "";
30485
+ if (assetId) {
30486
+ suffix += `
30487
+ Asset ID: '${assetId}'.`;
30488
+ }
30489
+ if (owner) {
30490
+ suffix += `
30491
+ Owner: '${owner}'.`;
30492
+ }
30493
+ return new FuelError(
30494
+ ErrorCode.INSUFFICIENT_FUNDS,
30495
+ `Insufficient funds.${suffix}`,
30496
+ { assetId, owner },
30497
+ error2
30498
+ );
30499
+ }
30414
30500
  if (gqlErrorMessage.MULTIPLE_CHANGE_POLICIES.test(error2.message)) {
30415
30501
  const match = error2.message.match(/asset ([a-fA-F0-9]{64})/);
30416
30502
  const assetId = match?.[1] || "";
@@ -31539,6 +31625,7 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
31539
31625
  }
31540
31626
  return new FuelError(ErrorCode.SCRIPT_REVERTED, errorMessage, {
31541
31627
  ...metadata,
31628
+ abiError,
31542
31629
  reason
31543
31630
  });
31544
31631
  }
@@ -32529,11 +32616,15 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
32529
32616
  * @deprecated Use `provider.assembleTx` instead.
32530
32617
  * Check the migration guide https://docs.fuel.network/guide/assembling-transactions/migration-guide.html for more information.
32531
32618
  */
32532
- async estimateAndFund(account, { signatureCallback, quantities = [] } = {}) {
32619
+ async estimateAndFund(account, {
32620
+ signatureCallback,
32621
+ quantities = [],
32622
+ skipAutoConsolidation
32623
+ } = {}) {
32533
32624
  const txCost = await account.getTransactionCost(this, { signatureCallback, quantities });
32534
32625
  this.maxFee = txCost.maxFee;
32535
32626
  this.gasLimit = txCost.gasUsed;
32536
- await account.fund(this, txCost);
32627
+ await account.fund(this, txCost, { skipAutoConsolidation });
32537
32628
  return this;
32538
32629
  }
32539
32630
  /**
@@ -34053,25 +34144,6 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
34053
34144
 
34054
34145
  // src/providers/transaction-response/transaction-response.ts
34055
34146
  var TransactionResponse = class _TransactionResponse {
34056
- /**
34057
- * Constructor for `TransactionResponse`.
34058
- *
34059
- * @param tx - The transaction ID or TransactionRequest.
34060
- * @param provider - The provider.
34061
- */
34062
- constructor(tx, provider, chainId, abis, submitTxSubscription) {
34063
- this.submitTxSubscription = submitTxSubscription;
34064
- if (typeof tx === "string") {
34065
- this.id = tx;
34066
- } else {
34067
- this.id = tx.getTransactionId(chainId);
34068
- this.request = tx;
34069
- }
34070
- this.provider = provider;
34071
- this.abis = abis;
34072
- this.waitForResult = this.waitForResult.bind(this);
34073
- this.waitForPreConfirmation = this.waitForPreConfirmation.bind(this);
34074
- }
34075
34147
  static {
34076
34148
  __name(this, "TransactionResponse");
34077
34149
  }
@@ -34086,9 +34158,42 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
34086
34158
  request;
34087
34159
  status;
34088
34160
  abis;
34161
+ submitTxSubscription;
34089
34162
  preConfirmationStatus;
34090
34163
  waitingForStreamData = false;
34091
34164
  statusResolvers = /* @__PURE__ */ new Map();
34165
+ /**
34166
+ * Constructor for `TransactionResponse`.
34167
+ */
34168
+ constructor(constructorParams, provider, chainId, abis, submitTxSubscription) {
34169
+ let tx;
34170
+ let _provider;
34171
+ let _chainId;
34172
+ let _abis;
34173
+ if (typeof constructorParams === "object" && "provider" in constructorParams && arguments.length === 1) {
34174
+ tx = constructorParams.transactionRequestOrId;
34175
+ _provider = constructorParams.provider;
34176
+ _chainId = constructorParams.chainId;
34177
+ _abis = constructorParams.abis;
34178
+ this.submitTxSubscription = constructorParams.submitAndAwaitSubscription;
34179
+ } else {
34180
+ tx = constructorParams;
34181
+ _provider = provider;
34182
+ _chainId = chainId;
34183
+ _abis = abis;
34184
+ this.submitTxSubscription = submitTxSubscription;
34185
+ }
34186
+ if (typeof tx === "string") {
34187
+ this.id = tx;
34188
+ } else {
34189
+ this.id = tx.getTransactionId(_chainId);
34190
+ this.request = tx;
34191
+ }
34192
+ this.provider = _provider;
34193
+ this.abis = _abis;
34194
+ this.waitForResult = this.waitForResult.bind(this);
34195
+ this.waitForPreConfirmation = this.waitForPreConfirmation.bind(this);
34196
+ }
34092
34197
  /**
34093
34198
  * Async constructor for `TransactionResponse`. This method can be used to create
34094
34199
  * an instance of `TransactionResponse` and wait for the transaction to be fetched
@@ -34598,7 +34703,15 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
34598
34703
  if (_Provider.ENABLE_RPC_CONSISTENCY && _Provider.hasWriteOperationHappened(url)) {
34599
34704
  _Provider.applyBlockHeight(fullRequest, url);
34600
34705
  }
34601
- return _Provider.fetchAndProcessBlockHeight(url, fullRequest, options);
34706
+ const response = await _Provider.fetchAndProcessBlockHeight(url, fullRequest, options);
34707
+ if (response.body === null) {
34708
+ throw new FuelError(
34709
+ ErrorCode.RESPONSE_BODY_EMPTY,
34710
+ "The response from the server is missing the body",
34711
+ { timestamp: (/* @__PURE__ */ new Date()).toISOString(), request, response }
34712
+ );
34713
+ }
34714
+ return response;
34602
34715
  }, retryOptions);
34603
34716
  }
34604
34717
  static applyBlockHeight(request, url) {
@@ -34621,13 +34734,15 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
34621
34734
  baseDelay: 500
34622
34735
  };
34623
34736
  for (let retriesLeft = retryOptions.maxRetries; retriesLeft > 0; --retriesLeft) {
34624
- const { extensions } = await parseGraphqlResponse({
34625
- response,
34626
- isSubscription: url.endsWith("-sub")
34627
- });
34628
- _Provider.setCurrentBlockHeight(url, extensions?.current_fuel_block_height);
34629
- if (!extensions?.fuel_block_height_precondition_failed) {
34630
- break;
34737
+ if (response.body) {
34738
+ const { extensions } = await parseGraphqlResponse({
34739
+ response,
34740
+ isSubscription: url.endsWith("-sub")
34741
+ });
34742
+ _Provider.setCurrentBlockHeight(url, extensions?.current_fuel_block_height);
34743
+ if (!extensions?.fuel_block_height_precondition_failed) {
34744
+ break;
34745
+ }
34631
34746
  }
34632
34747
  const retryAttempt = retryOptions.maxRetries - retriesLeft + 1;
34633
34748
  const sleepTime = getWaitDelay(retryOptions, retryAttempt);
@@ -35050,7 +35165,13 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
35050
35165
  transactionRequest.getTransactionId(await this.getChainId())
35051
35166
  );
35052
35167
  const chainId = await this.getChainId();
35053
- return new TransactionResponse(transactionRequest, this, chainId, abis, subscription);
35168
+ return new TransactionResponse({
35169
+ transactionRequestOrId: transactionRequest,
35170
+ provider: this,
35171
+ chainId,
35172
+ abis,
35173
+ submitAndAwaitSubscription: subscription
35174
+ });
35054
35175
  }
35055
35176
  /**
35056
35177
  * Executes a transaction without actually submitting it to the chain.
@@ -36145,7 +36266,11 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36145
36266
  */
36146
36267
  async getTransactionResponse(transactionId) {
36147
36268
  const chainId = await this.getChainId();
36148
- return new TransactionResponse(transactionId, this, chainId);
36269
+ return new TransactionResponse({
36270
+ transactionRequestOrId: transactionId,
36271
+ provider: this,
36272
+ chainId
36273
+ });
36149
36274
  }
36150
36275
  /**
36151
36276
  * Returns Message for given nonce.
@@ -36308,6 +36433,149 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36308
36433
  }
36309
36434
  };
36310
36435
 
36436
+ // src/utils/consolidate-coins.ts
36437
+ var CONSOLIDATABLE_ERROR_CODES = [ErrorCode.MAX_COINS_REACHED];
36438
+ var consolidateCoinsIfRequired = /* @__PURE__ */ __name(async (opts) => {
36439
+ const { error: errorUnknown, account, skipAutoConsolidation = false } = opts;
36440
+ if (skipAutoConsolidation) {
36441
+ return false;
36442
+ }
36443
+ const error2 = FuelError.parse(errorUnknown);
36444
+ if (CONSOLIDATABLE_ERROR_CODES.includes(error2.code)) {
36445
+ const { assetId, owner } = error2.metadata;
36446
+ return account.startConsolidation({
36447
+ owner,
36448
+ assetId
36449
+ });
36450
+ }
36451
+ return false;
36452
+ }, "consolidateCoinsIfRequired");
36453
+ var getAllCoins = /* @__PURE__ */ __name(async (account, assetId) => {
36454
+ const all = [];
36455
+ let hasNextPage = true;
36456
+ let after;
36457
+ while (hasNextPage) {
36458
+ const { coins, pageInfo } = await account.getCoins(assetId, { after });
36459
+ all.push(...coins);
36460
+ after = coins.pop()?.id;
36461
+ hasNextPage = pageInfo.hasNextPage;
36462
+ }
36463
+ return { coins: all };
36464
+ }, "getAllCoins");
36465
+ var sortCoins = /* @__PURE__ */ __name(({ coins }) => coins.sort((a, b) => b.amount.cmp(a.amount)), "sortCoins");
36466
+ var createOuputCoin = /* @__PURE__ */ __name((opts) => {
36467
+ const { transactionId, outputs, baseAssetId } = opts;
36468
+ const outputChangeIndex = outputs.findIndex(
36469
+ (output) => output.type === OutputType.Change && output.assetId === baseAssetId
36470
+ );
36471
+ if (outputChangeIndex === -1) {
36472
+ throw new FuelError(ErrorCode.UNKNOWN, "No change output found");
36473
+ }
36474
+ const outputCoin = outputs[outputChangeIndex];
36475
+ const outputIndexPadded = Number(outputChangeIndex).toString().padStart(4, "0");
36476
+ return {
36477
+ id: `${transactionId}${outputIndexPadded}`,
36478
+ assetId: outputCoin.assetId,
36479
+ amount: outputCoin.amount,
36480
+ owner: new Address(outputCoin.to),
36481
+ blockCreated: bn(0),
36482
+ txCreatedIdx: bn(0)
36483
+ };
36484
+ }, "createOuputCoin");
36485
+ var consolidateCoins = /* @__PURE__ */ __name(async ({
36486
+ account,
36487
+ assetId
36488
+ }) => {
36489
+ const chainInfo = await account.provider.getChain();
36490
+ const chainId = chainInfo.consensusParameters.chainId.toNumber();
36491
+ const gasPrice = await account.provider.estimateGasPrice(10);
36492
+ const maxInputs = chainInfo.consensusParameters.txParameters.maxInputs.toNumber();
36493
+ const baseAssetId = await account.provider.getBaseAssetId();
36494
+ const isBaseAsset = assetId === baseAssetId;
36495
+ const batchSize = maxInputs;
36496
+ const numberOfFundingCoins = maxInputs;
36497
+ let funding = [];
36498
+ let dust = [];
36499
+ if (isBaseAsset) {
36500
+ const coins = await getAllCoins(account, baseAssetId).then(sortCoins);
36501
+ funding = coins.slice(0, numberOfFundingCoins);
36502
+ dust = coins.slice(numberOfFundingCoins);
36503
+ } else {
36504
+ funding = await getAllCoins(account, baseAssetId).then(sortCoins).then((coins) => coins.slice(0, numberOfFundingCoins));
36505
+ dust = await getAllCoins(account, assetId).then(({ coins }) => coins);
36506
+ }
36507
+ if (funding.length === 0) {
36508
+ throw new FuelError(
36509
+ ErrorCode.INSUFFICIENT_FUNDS,
36510
+ `Insufficient funds to consolidate.
36511
+ Asset ID: ${baseAssetId}
36512
+ Owner: ${account.address.toB256()}`
36513
+ );
36514
+ }
36515
+ const batches = [
36516
+ ...splitEvery_default(batchSize, funding),
36517
+ // We leave one coin for the funding coin
36518
+ ...splitEvery_default(batchSize - 1, dust)
36519
+ ];
36520
+ const txs = batches.map((batch) => {
36521
+ const request = new ScriptTransactionRequest({
36522
+ scriptData: "0x"
36523
+ });
36524
+ request.addResources(batch);
36525
+ return request;
36526
+ });
36527
+ const submitAll = /* @__PURE__ */ __name(async (opts = {}) => {
36528
+ const txResponses = [];
36529
+ let previousTx;
36530
+ for (let i = 0; i < txs.length; i++) {
36531
+ let currentTx = txs[i];
36532
+ const step = i + 1;
36533
+ if (previousTx) {
36534
+ const coin = createOuputCoin({
36535
+ transactionId: previousTx.transactionId,
36536
+ outputs: previousTx.outputs,
36537
+ baseAssetId
36538
+ });
36539
+ currentTx.addResource(coin);
36540
+ }
36541
+ if ("populateTransactionPredicateData" in account && typeof account.populateTransactionPredicateData === "function") {
36542
+ currentTx = account.populateTransactionPredicateData(currentTx);
36543
+ currentTx = await account.provider.estimatePredicates(currentTx);
36544
+ }
36545
+ const fee = calculateGasFee({
36546
+ gasPrice,
36547
+ gas: currentTx.calculateMinGas(chainInfo),
36548
+ priceFactor: chainInfo.consensusParameters.feeParameters.gasPriceFactor,
36549
+ tip: currentTx.tip
36550
+ });
36551
+ currentTx.maxFee = fee;
36552
+ currentTx.gasLimit = bn(1e3);
36553
+ opts.onTransactionStart?.({
36554
+ tx: currentTx,
36555
+ step,
36556
+ assetId,
36557
+ transactionId: currentTx.getTransactionId(chainId)
36558
+ });
36559
+ const response = await account.sendTransaction(currentTx);
36560
+ const result = await response.waitForResult();
36561
+ txResponses.push(result);
36562
+ previousTx = {
36563
+ transactionId: response.id,
36564
+ outputs: result.transaction.outputs
36565
+ };
36566
+ }
36567
+ return {
36568
+ txResponses,
36569
+ errors: []
36570
+ };
36571
+ }, "submitAll");
36572
+ return {
36573
+ txs,
36574
+ totalFeeCost: txs.reduce((acc, request) => acc.add(request.maxFee), bn(0)),
36575
+ submitAll
36576
+ };
36577
+ }, "consolidateCoins");
36578
+
36311
36579
  // src/utils/formatTransferToContractScriptData.ts
36312
36580
  var asm = __toESM(require_node());
36313
36581
  var formatTransferToContractScriptData = /* @__PURE__ */ __name((transferParams) => {
@@ -36424,10 +36692,24 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36424
36692
  *
36425
36693
  * @param quantities - Quantities of resources to be obtained.
36426
36694
  * @param resourcesIdsToIgnore - IDs of resources to be excluded from the query (optional).
36695
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
36427
36696
  * @returns A promise that resolves to an array of Resources.
36428
36697
  */
36429
- async getResourcesToSpend(quantities, resourcesIdsToIgnore) {
36430
- return this.provider.getResourcesToSpend(this.address, quantities, resourcesIdsToIgnore);
36698
+ async getResourcesToSpend(quantities, resourcesIdsToIgnore, { skipAutoConsolidation } = {}) {
36699
+ const getResourcesToSpend = /* @__PURE__ */ __name(() => this.provider.getResourcesToSpend(this.address, quantities, resourcesIdsToIgnore), "getResourcesToSpend");
36700
+ try {
36701
+ return await getResourcesToSpend();
36702
+ } catch (error2) {
36703
+ const shouldRetry = await consolidateCoinsIfRequired({
36704
+ error: error2,
36705
+ account: this,
36706
+ skipAutoConsolidation
36707
+ });
36708
+ if (!shouldRetry) {
36709
+ throw error2;
36710
+ }
36711
+ return await getResourcesToSpend();
36712
+ }
36431
36713
  }
36432
36714
  /**
36433
36715
  * Retrieves coins owned by the account.
@@ -36476,7 +36758,7 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36476
36758
  * @deprecated Use provider.assembleTx instead
36477
36759
  * Check the migration guide https://docs.fuel.network/docs/fuels-ts/transactions/assemble-tx-migration-guide/ for more information.
36478
36760
  */
36479
- async fund(request, params) {
36761
+ async fund(request, params, { skipAutoConsolidation } = {}) {
36480
36762
  const {
36481
36763
  addedSignatures,
36482
36764
  estimatedPredicates,
@@ -36522,7 +36804,8 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36522
36804
  while (needsToBeFunded && fundingAttempts < MAX_FUNDING_ATTEMPTS) {
36523
36805
  const resources = await this.getResourcesToSpend(
36524
36806
  missingQuantities,
36525
- cacheRequestInputsResourcesFromOwner(request.inputs, this.address)
36807
+ cacheRequestInputsResourcesFromOwner(request.inputs, this.address),
36808
+ { skipAutoConsolidation }
36526
36809
  );
36527
36810
  request.addResources(resources);
36528
36811
  request.updatePredicateGasUsed(estimatedPredicates);
@@ -36560,7 +36843,7 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36560
36843
  }
36561
36844
  if (needsToBeFunded) {
36562
36845
  throw new FuelError(
36563
- ErrorCode.INSUFFICIENT_FUNDS_OR_MAX_COINS,
36846
+ ErrorCode.INSUFFICIENT_FUNDS,
36564
36847
  `The account ${this.address} does not have enough base asset funds to cover the transaction execution.`
36565
36848
  );
36566
36849
  }
@@ -36588,16 +36871,20 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36588
36871
  * @param amount - The amount of coins to transfer.
36589
36872
  * @param assetId - The asset ID of the coins to transfer (optional).
36590
36873
  * @param txParams - The transaction parameters (optional).
36874
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
36591
36875
  * @returns A promise that resolves to the prepared transaction request.
36592
36876
  */
36593
- async createTransfer(destination, amount, assetId, txParams = {}) {
36877
+ async createTransfer(destination, amount, assetId, txParams = {}, { skipAutoConsolidation } = {}) {
36594
36878
  let request = new ScriptTransactionRequest(txParams);
36595
36879
  request = this.addTransfer(request, {
36596
36880
  destination,
36597
36881
  amount,
36598
36882
  assetId: assetId || await this.provider.getBaseAssetId()
36599
36883
  });
36600
- const { gasPrice, transactionRequest } = await this.assembleTx(request);
36884
+ const { gasPrice, transactionRequest } = await this.assembleTx({
36885
+ transactionRequest: request,
36886
+ skipAutoConsolidation
36887
+ });
36601
36888
  request = await setAndValidateGasAndFeeForAssembledTx({
36602
36889
  gasPrice,
36603
36890
  provider: this.provider,
@@ -36614,10 +36901,13 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36614
36901
  * @param amount - The amount of coins to transfer.
36615
36902
  * @param assetId - The asset ID of the coins to transfer (optional).
36616
36903
  * @param txParams - The transaction parameters (optional).
36904
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
36617
36905
  * @returns A promise that resolves to the transaction response.
36618
36906
  */
36619
- async transfer(destination, amount, assetId, txParams = {}) {
36620
- const request = await this.createTransfer(destination, amount, assetId, txParams);
36907
+ async transfer(destination, amount, assetId, txParams = {}, { skipAutoConsolidation } = {}) {
36908
+ const request = await this.createTransfer(destination, amount, assetId, txParams, {
36909
+ skipAutoConsolidation
36910
+ });
36621
36911
  return this.sendTransaction(request, { estimateTxDependencies: false });
36622
36912
  }
36623
36913
  /**
@@ -36625,12 +36915,16 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36625
36915
  *
36626
36916
  * @param transferParams - An array of `TransferParams` objects representing the transfers to be made.
36627
36917
  * @param txParams - Optional transaction parameters.
36918
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
36628
36919
  * @returns A promise that resolves to a `TransactionResponse` object representing the transaction result.
36629
36920
  */
36630
- async batchTransfer(transferParams, txParams = {}) {
36921
+ async batchTransfer(transferParams, txParams = {}, { skipAutoConsolidation } = {}) {
36631
36922
  let request = new ScriptTransactionRequest(txParams);
36632
36923
  request = this.addBatchTransfer(request, transferParams);
36633
- const { gasPrice, transactionRequest } = await this.assembleTx(request);
36924
+ const { gasPrice, transactionRequest } = await this.assembleTx({
36925
+ transactionRequest: request,
36926
+ skipAutoConsolidation
36927
+ });
36634
36928
  request = await setAndValidateGasAndFeeForAssembledTx({
36635
36929
  gasPrice,
36636
36930
  provider: this.provider,
@@ -36677,12 +36971,15 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36677
36971
  * @param amount - The amount of coins to transfer.
36678
36972
  * @param assetId - The asset ID of the coins to transfer (optional).
36679
36973
  * @param txParams - The transaction parameters (optional).
36974
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
36680
36975
  * @returns A promise that resolves to the transaction response.
36681
36976
  */
36682
- async transferToContract(contractId, amount, assetId, txParams = {}) {
36683
- return this.batchTransferToContracts([{ amount, assetId, contractId }], txParams);
36977
+ async transferToContract(contractId, amount, assetId, txParams = {}, { skipAutoConsolidation } = {}) {
36978
+ return this.batchTransferToContracts([{ amount, assetId, contractId }], txParams, {
36979
+ skipAutoConsolidation
36980
+ });
36684
36981
  }
36685
- async batchTransferToContracts(contractTransferParams, txParams = {}) {
36982
+ async batchTransferToContracts(contractTransferParams, txParams = {}, { skipAutoConsolidation } = {}) {
36686
36983
  let request = new ScriptTransactionRequest({
36687
36984
  ...txParams
36688
36985
  });
@@ -36709,7 +37006,11 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36709
37006
  const { script, scriptData } = await assembleTransferToContractScript(transferParams);
36710
37007
  request.script = script;
36711
37008
  request.scriptData = scriptData;
36712
- const { gasPrice, transactionRequest } = await this.assembleTx(request, quantities);
37009
+ const { gasPrice, transactionRequest } = await this.assembleTx({
37010
+ transactionRequest: request,
37011
+ quantities,
37012
+ skipAutoConsolidation
37013
+ });
36713
37014
  request = await setAndValidateGasAndFeeForAssembledTx({
36714
37015
  gasPrice,
36715
37016
  provider: this.provider,
@@ -36725,9 +37026,10 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36725
37026
  * @param recipient - Address of the recipient on the base chain.
36726
37027
  * @param amount - Amount of base asset.
36727
37028
  * @param txParams - The transaction parameters (optional).
37029
+ * @param skipAutoConsolidation - Whether to skip the automatic consolidatation of coins process (optional).
36728
37030
  * @returns A promise that resolves to the transaction response.
36729
37031
  */
36730
- async withdrawToBaseLayer(recipient, amount, txParams = {}) {
37032
+ async withdrawToBaseLayer(recipient, amount, txParams = {}, { skipAutoConsolidation } = {}) {
36731
37033
  const recipientAddress = new Address(recipient);
36732
37034
  const recipientDataArray = arrayify(
36733
37035
  "0x".concat(recipientAddress.toHexString().substring(2).padStart(64, "0"))
@@ -36744,7 +37046,11 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36744
37046
  const baseAssetId = await this.provider.getBaseAssetId();
36745
37047
  let request = new ScriptTransactionRequest(params);
36746
37048
  const quantities = [{ amount: bn(amount), assetId: baseAssetId }];
36747
- const { gasPrice, transactionRequest } = await this.assembleTx(request, quantities);
37049
+ const { gasPrice, transactionRequest } = await this.assembleTx({
37050
+ transactionRequest: request,
37051
+ quantities,
37052
+ skipAutoConsolidation
37053
+ });
36748
37054
  request = await setAndValidateGasAndFeeForAssembledTx({
36749
37055
  gasPrice,
36750
37056
  provider: this.provider,
@@ -36754,6 +37060,25 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36754
37060
  });
36755
37061
  return this.sendTransaction(request);
36756
37062
  }
37063
+ /**
37064
+ * Start the consolidation process
37065
+ *
37066
+ * @param owner - The B256 address of the owner.
37067
+ * @param assetId - The asset ID that requires consolidation.
37068
+ */
37069
+ async startConsolidation(opts) {
37070
+ if (this._connector) {
37071
+ await this._connector.startConsolidation(opts);
37072
+ return false;
37073
+ }
37074
+ const { owner, assetId } = opts;
37075
+ if (owner !== this.address.toB256()) {
37076
+ return false;
37077
+ }
37078
+ const { submitAll } = await consolidateCoins({ account: this, assetId });
37079
+ await submitAll();
37080
+ return true;
37081
+ }
36757
37082
  /**
36758
37083
  * Consolidates base asset UTXOs into fewer, larger ones.
36759
37084
  *
@@ -36773,6 +37098,7 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36773
37098
  const isBaseAsset = baseAssetId === assetId;
36774
37099
  let submitAll;
36775
37100
  const consolidationParams = {
37101
+ assetId,
36776
37102
  coins,
36777
37103
  mode: params.mode,
36778
37104
  outputNum: params.outputNum
@@ -36780,10 +37106,7 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36780
37106
  if (isBaseAsset) {
36781
37107
  ({ submitAll } = await this.assembleBaseAssetConsolidationTxs(consolidationParams));
36782
37108
  } else {
36783
- throw new FuelError(
36784
- ErrorCode.UNSUPPORTED_FEATURE,
36785
- "Consolidation for non-base assets is not supported yet."
36786
- );
37109
+ ({ submitAll } = await this.assembleNonBaseAssetConsolidationTxs(consolidationParams));
36787
37110
  }
36788
37111
  return submitAll();
36789
37112
  }
@@ -36842,6 +37165,70 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
36842
37165
  const submitAll = this.prepareSubmitAll({ txs, mode });
36843
37166
  return { txs, totalFeeCost, submitAll };
36844
37167
  }
37168
+ async assembleNonBaseAssetConsolidationTxs(params) {
37169
+ const { assetId, coins, mode = "parallel", outputNum = 1 } = params;
37170
+ this.validateConsolidationTxsCoins(coins, assetId);
37171
+ const chainInfo = await this.provider.getChain();
37172
+ const maxInputsNumber = chainInfo.consensusParameters.txParameters.maxInputs.toNumber();
37173
+ const baseAssetId = chainInfo.consensusParameters.baseAssetId;
37174
+ const { coins: baseAssetCoins } = await this.provider.getCoins(this.address, baseAssetId);
37175
+ let totalFeeCost = bn(0);
37176
+ const txs = [];
37177
+ const gasPrice = await this.provider.estimateGasPrice(10);
37178
+ const consolidateMoreThanOneCoin = outputNum > 1;
37179
+ const assetCoinBatches = splitCoinsIntoBatches(coins, maxInputsNumber);
37180
+ assetCoinBatches.filter((batch) => batch.length > 1).forEach((coinBatch) => {
37181
+ const request = new ScriptTransactionRequest({
37182
+ script: "0x"
37183
+ });
37184
+ request.addResources(coinBatch);
37185
+ if (consolidateMoreThanOneCoin) {
37186
+ Array.from({ length: outputNum - 1 }).forEach(() => {
37187
+ request.addCoinOutput(this.address, 0, assetId);
37188
+ });
37189
+ }
37190
+ const minGas = request.calculateMinGas(chainInfo);
37191
+ const fee = calculateGasFee({
37192
+ gasPrice,
37193
+ gas: minGas,
37194
+ priceFactor: chainInfo.consensusParameters.feeParameters.gasPriceFactor,
37195
+ tip: request.tip
37196
+ });
37197
+ request.maxFee = fee;
37198
+ if (consolidateMoreThanOneCoin) {
37199
+ const total = request.inputs.filter(isRequestInputCoin).reduce((acc, input) => acc.add(input.amount), bn(0));
37200
+ const amountPerNewUtxo = total.div(outputNum + 1);
37201
+ request.outputs.forEach((output) => {
37202
+ if (output.type === OutputType.Coin) {
37203
+ output.amount = amountPerNewUtxo;
37204
+ }
37205
+ });
37206
+ }
37207
+ totalFeeCost = totalFeeCost.add(fee);
37208
+ const baseAssetResources = [];
37209
+ let fundingFeeTotal = bn(0);
37210
+ while (fundingFeeTotal.lt(fee)) {
37211
+ const baseAssetCoin = baseAssetCoins.pop();
37212
+ if (!baseAssetCoin) {
37213
+ break;
37214
+ }
37215
+ baseAssetResources.push(baseAssetCoin);
37216
+ fundingFeeTotal = fundingFeeTotal.add(baseAssetCoin.amount);
37217
+ }
37218
+ const { inputs } = request;
37219
+ request.inputs = inputs.slice(0, maxInputsNumber - baseAssetResources.length);
37220
+ const removedCoins = coinBatch.slice(maxInputsNumber - baseAssetResources.length);
37221
+ request.addResources(baseAssetResources);
37222
+ const lastCoinBatch = assetCoinBatches[assetCoinBatches.length - 1];
37223
+ lastCoinBatch.push(...removedCoins);
37224
+ if (lastCoinBatch.length > maxInputsNumber) {
37225
+ assetCoinBatches.push(lastCoinBatch.slice(maxInputsNumber));
37226
+ }
37227
+ txs.push(request);
37228
+ });
37229
+ const submitAll = this.prepareSubmitAll({ txs, mode });
37230
+ return { txs, totalFeeCost, submitAll };
37231
+ }
36845
37232
  /**
36846
37233
  * Prepares a function to submit all transactions either sequentially or in parallel.
36847
37234
  *
@@ -37056,16 +37443,32 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
37056
37443
  } : void 0;
37057
37444
  }
37058
37445
  /** @hidden * */
37059
- async assembleTx(transactionRequest, quantities = []) {
37446
+ async assembleTx(opts) {
37447
+ const { transactionRequest, quantities = [], skipAutoConsolidation } = opts;
37060
37448
  const outputQuantities = transactionRequest.outputs.filter((o) => o.type === OutputType.Coin).map(({ amount, assetId }) => ({ assetId: String(assetId), amount: bn(amount) }));
37061
37449
  transactionRequest.gasLimit = bn(0);
37062
37450
  transactionRequest.maxFee = bn(0);
37063
- const { assembledRequest, gasPrice } = await this.provider.assembleTx({
37064
- request: transactionRequest,
37065
- accountCoinQuantities: mergeQuantities(outputQuantities, quantities),
37066
- feePayerAccount: this
37067
- });
37068
- return { transactionRequest: assembledRequest, gasPrice };
37451
+ const assembleTx = /* @__PURE__ */ __name(async () => {
37452
+ const { assembledRequest, gasPrice } = await this.provider.assembleTx({
37453
+ request: transactionRequest,
37454
+ accountCoinQuantities: mergeQuantities(outputQuantities, quantities),
37455
+ feePayerAccount: this
37456
+ });
37457
+ return { transactionRequest: assembledRequest, gasPrice };
37458
+ }, "assembleTx");
37459
+ try {
37460
+ return await assembleTx();
37461
+ } catch (error2) {
37462
+ const shouldRetry = await consolidateCoinsIfRequired({
37463
+ error: error2,
37464
+ account: this,
37465
+ skipAutoConsolidation
37466
+ });
37467
+ if (!shouldRetry) {
37468
+ throw error2;
37469
+ }
37470
+ return await assembleTx();
37471
+ }
37069
37472
  }
37070
37473
  /** @hidden * */
37071
37474
  validateTransferAmount(amount) {
@@ -37077,45 +37480,6 @@ This error originated at ${JSON.stringify(pos, null, 2)}` : "";
37077
37480
  }
37078
37481
  }
37079
37482
  /** @hidden * */
37080
- async estimateAndFundTransaction(transactionRequest, txParams, costParams) {
37081
- let request = transactionRequest;
37082
- const txCost = await this.getTransactionCost(request, costParams);
37083
- request = this.validateGasLimitAndMaxFee({
37084
- transactionRequest: request,
37085
- gasUsed: txCost.gasUsed,
37086
- maxFee: txCost.maxFee,
37087
- txParams
37088
- });
37089
- request = await this.fund(request, txCost);
37090
- return request;
37091
- }
37092
- /** @hidden * */
37093
- validateGasLimitAndMaxFee({
37094
- gasUsed,
37095
- maxFee,
37096
- transactionRequest,
37097
- txParams: { gasLimit: setGasLimit, maxFee: setMaxFee }
37098
- }) {
37099
- const request = transactionRequestify(transactionRequest);
37100
- if (!isDefined(setGasLimit)) {
37101
- request.gasLimit = gasUsed;
37102
- } else if (gasUsed.gt(setGasLimit)) {
37103
- throw new FuelError(
37104
- ErrorCode.GAS_LIMIT_TOO_LOW,
37105
- `Gas limit '${setGasLimit}' is lower than the required: '${gasUsed}'.`
37106
- );
37107
- }
37108
- if (!isDefined(setMaxFee)) {
37109
- request.maxFee = maxFee;
37110
- } else if (maxFee.gt(setMaxFee)) {
37111
- throw new FuelError(
37112
- ErrorCode.MAX_FEE_TOO_LOW,
37113
- `Max fee '${setMaxFee}' is lower than the required: '${maxFee}'.`
37114
- );
37115
- }
37116
- return request;
37117
- }
37118
- /** @hidden * */
37119
37483
  validateConsolidationTxsCoins(coins, assetId) {
37120
37484
  if (coins.length <= 1) {
37121
37485
  throw new FuelError(ErrorCode.NO_COINS_TO_CONSOLIDATE, "No coins to consolidate.");