@fuel-ts/account 0.90.0 → 0.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @fuel-ts/account might be problematic. Click here for more details.

@@ -510,6 +510,12 @@ var GasCostsFragmentDoc = gql`
510
510
  alocDependentCost {
511
511
  ...DependentCostFragment
512
512
  }
513
+ cfe {
514
+ ...DependentCostFragment
515
+ }
516
+ cfeiDependentCost {
517
+ ...DependentCostFragment
518
+ }
513
519
  call {
514
520
  ...DependentCostFragment
515
521
  }
@@ -750,6 +756,9 @@ ${TransactionFragmentDoc}`;
750
756
  var GetBlocksDocument = gql`
751
757
  query getBlocks($after: String, $before: String, $first: Int, $last: Int) {
752
758
  blocks(after: $after, before: $before, first: $first, last: $last) {
759
+ pageInfo {
760
+ ...pageInfoFragment
761
+ }
753
762
  edges {
754
763
  node {
755
764
  ...blockFragment
@@ -757,7 +766,8 @@ var GetBlocksDocument = gql`
757
766
  }
758
767
  }
759
768
  }
760
- ${BlockFragmentDoc}`;
769
+ ${PageInfoFragmentDoc}
770
+ ${BlockFragmentDoc}`;
761
771
  var GetCoinDocument = gql`
762
772
  query getCoin($coinId: UtxoId!) {
763
773
  coin(utxoId: $coinId) {
@@ -774,6 +784,9 @@ var GetCoinsDocument = gql`
774
784
  first: $first
775
785
  last: $last
776
786
  ) {
787
+ pageInfo {
788
+ ...pageInfoFragment
789
+ }
777
790
  edges {
778
791
  node {
779
792
  ...coinFragment
@@ -781,7 +794,8 @@ var GetCoinsDocument = gql`
781
794
  }
782
795
  }
783
796
  }
784
- ${CoinFragmentDoc}`;
797
+ ${PageInfoFragmentDoc}
798
+ ${CoinFragmentDoc}`;
785
799
  var GetCoinsToSpendDocument = gql`
786
800
  query getCoinsToSpend($owner: Address!, $queryPerAsset: [SpendQueryElementInput!]!, $excludedIds: ExcludeInput) {
787
801
  coinsToSpend(
@@ -840,6 +854,9 @@ var GetBalancesDocument = gql`
840
854
  first: $first
841
855
  last: $last
842
856
  ) {
857
+ pageInfo {
858
+ ...pageInfoFragment
859
+ }
843
860
  edges {
844
861
  node {
845
862
  ...balanceFragment
@@ -847,7 +864,8 @@ var GetBalancesDocument = gql`
847
864
  }
848
865
  }
849
866
  }
850
- ${BalanceFragmentDoc}`;
867
+ ${PageInfoFragmentDoc}
868
+ ${BalanceFragmentDoc}`;
851
869
  var GetMessagesDocument = gql`
852
870
  query getMessages($owner: Address!, $after: String, $before: String, $first: Int, $last: Int) {
853
871
  messages(
@@ -857,6 +875,9 @@ var GetMessagesDocument = gql`
857
875
  first: $first
858
876
  last: $last
859
877
  ) {
878
+ pageInfo {
879
+ ...pageInfoFragment
880
+ }
860
881
  edges {
861
882
  node {
862
883
  ...messageFragment
@@ -864,7 +885,8 @@ var GetMessagesDocument = gql`
864
885
  }
865
886
  }
866
887
  }
867
- ${MessageFragmentDoc}`;
888
+ ${PageInfoFragmentDoc}
889
+ ${MessageFragmentDoc}`;
868
890
  var GetMessageProofDocument = gql`
869
891
  query getMessageProof($transactionId: TransactionId!, $nonce: Nonce!, $commitBlockId: BlockId, $commitBlockHeight: U32) {
870
892
  messageProof(
@@ -1675,7 +1697,7 @@ import {
1675
1697
  PANIC_REASONS,
1676
1698
  PANIC_DOC_URL
1677
1699
  } from "@fuel-ts/transactions/configs";
1678
- var assemblePanicError = (statusReason) => {
1700
+ var assemblePanicError = (statusReason, metadata) => {
1679
1701
  let errorMessage = `The transaction reverted with reason: "${statusReason}".`;
1680
1702
  if (PANIC_REASONS.includes(statusReason)) {
1681
1703
  errorMessage = `${errorMessage}
@@ -1684,10 +1706,13 @@ You can read more about this error at:
1684
1706
 
1685
1707
  ${PANIC_DOC_URL}#variant.${statusReason}`;
1686
1708
  }
1687
- return { errorMessage, reason: statusReason };
1709
+ return new FuelError7(ErrorCode7.SCRIPT_REVERTED, errorMessage, {
1710
+ ...metadata,
1711
+ reason: statusReason
1712
+ });
1688
1713
  };
1689
1714
  var stringify = (obj) => JSON.stringify(obj, null, 2);
1690
- var assembleRevertError = (receipts, logs) => {
1715
+ var assembleRevertError = (receipts, logs, metadata) => {
1691
1716
  let errorMessage = "The transaction reverted with an unknown reason.";
1692
1717
  const revertReceipt = receipts.find(({ type }) => type === ReceiptType3.Revert);
1693
1718
  let reason = "";
@@ -1720,25 +1745,36 @@ var assembleRevertError = (receipts, logs) => {
1720
1745
  errorMessage = `The transaction reverted because it's missing an "OutputChange".`;
1721
1746
  break;
1722
1747
  default:
1723
- reason = "unknown";
1724
- errorMessage = `The transaction reverted with an unknown reason: ${revertReceipt.val}`;
1748
+ throw new FuelError7(
1749
+ ErrorCode7.UNKNOWN,
1750
+ `The transaction reverted with an unknown reason: ${revertReceipt.val}`,
1751
+ {
1752
+ ...metadata,
1753
+ reason: "unknown"
1754
+ }
1755
+ );
1725
1756
  }
1726
1757
  }
1727
- return { errorMessage, reason };
1758
+ return new FuelError7(ErrorCode7.SCRIPT_REVERTED, errorMessage, {
1759
+ ...metadata,
1760
+ reason
1761
+ });
1728
1762
  };
1729
1763
  var extractTxError = (params) => {
1730
1764
  const { receipts, statusReason, logs } = params;
1731
1765
  const isPanic = receipts.some(({ type }) => type === ReceiptType3.Panic);
1732
1766
  const isRevert = receipts.some(({ type }) => type === ReceiptType3.Revert);
1733
- const { errorMessage, reason } = isPanic ? assemblePanicError(statusReason) : assembleRevertError(receipts, logs);
1734
1767
  const metadata = {
1735
1768
  logs,
1736
1769
  receipts,
1737
1770
  panic: isPanic,
1738
1771
  revert: isRevert,
1739
- reason
1772
+ reason: ""
1740
1773
  };
1741
- return new FuelError7(ErrorCode7.SCRIPT_REVERTED, errorMessage, metadata);
1774
+ if (isPanic) {
1775
+ return assemblePanicError(statusReason, metadata);
1776
+ }
1777
+ return assembleRevertError(receipts, logs, metadata);
1742
1778
  };
1743
1779
 
1744
1780
  // src/providers/transaction-request/errors.ts
@@ -3574,12 +3610,18 @@ var TransactionResponse = class {
3574
3610
  await this.fetch();
3575
3611
  }
3576
3612
  /**
3577
- * Waits for transaction to complete and returns the result.
3613
+ * Assembles the result of a transaction by retrieving the transaction summary,
3614
+ * decoding logs (if available), and handling transaction failure.
3578
3615
  *
3579
- * @returns The completed transaction result
3616
+ * This method can be used to obtain the result of a transaction that has just
3617
+ * been submitted or one that has already been processed.
3618
+ *
3619
+ * @template TTransactionType - The type of the transaction.
3620
+ * @param contractsAbiMap - The map of contract ABIs.
3621
+ * @returns - The assembled transaction result.
3622
+ * @throws If the transaction status is a failure.
3580
3623
  */
3581
- async waitForResult(contractsAbiMap) {
3582
- await this.waitForStatusChange();
3624
+ async assembleResult(contractsAbiMap) {
3583
3625
  const transactionSummary = await this.getTransactionSummary(contractsAbiMap);
3584
3626
  const transactionResult = {
3585
3627
  gqlTransaction: this.gqlTransaction,
@@ -3605,6 +3647,15 @@ var TransactionResponse = class {
3605
3647
  }
3606
3648
  return transactionResult;
3607
3649
  }
3650
+ /**
3651
+ * Waits for transaction to complete and returns the result.
3652
+ *
3653
+ * @returns The completed transaction result
3654
+ */
3655
+ async waitForResult(contractsAbiMap) {
3656
+ await this.waitForStatusChange();
3657
+ return this.assembleResult(contractsAbiMap);
3658
+ }
3608
3659
  /**
3609
3660
  * Waits for transaction to complete and returns the result.
3610
3661
  *
@@ -3668,6 +3719,8 @@ var mergeQuantities = (...coinQuantities) => {
3668
3719
 
3669
3720
  // src/providers/provider.ts
3670
3721
  var MAX_RETRIES = 10;
3722
+ var RESOURCES_PAGE_SIZE_LIMIT = 512;
3723
+ var BLOCKS_PAGE_SIZE_LIMIT = 5;
3671
3724
  var processGqlChain = (chain) => {
3672
3725
  const { name, daHeight, consensusParameters, latestBlock } = chain;
3673
3726
  const {
@@ -4311,7 +4364,7 @@ Supported fuel-core version: ${supportedVersion}.`
4311
4364
  /**
4312
4365
  * Returns a transaction cost to enable user
4313
4366
  * to set gasLimit and also reserve balance amounts
4314
- * on the the transaction.
4367
+ * on the transaction.
4315
4368
  *
4316
4369
  * @param transactionRequestLike - The transaction request object.
4317
4370
  * @param transactionCostParams - The transaction cost parameters (optional).
@@ -4422,20 +4475,27 @@ Supported fuel-core version: ${supportedVersion}.`
4422
4475
  */
4423
4476
  async getCoins(owner, assetId, paginationArgs) {
4424
4477
  const ownerAddress = Address2.fromAddressOrString(owner);
4425
- const result = await this.operations.getCoins({
4426
- first: 10,
4427
- ...paginationArgs,
4478
+ const {
4479
+ coins: { edges, pageInfo }
4480
+ } = await this.operations.getCoins({
4481
+ ...this.validatePaginationArgs({
4482
+ paginationLimit: RESOURCES_PAGE_SIZE_LIMIT,
4483
+ inputArgs: paginationArgs
4484
+ }),
4428
4485
  filter: { owner: ownerAddress.toB256(), assetId: assetId && hexlify12(assetId) }
4429
4486
  });
4430
- const coins = result.coins.edges.map((edge) => edge.node);
4431
- return coins.map((coin) => ({
4432
- id: coin.utxoId,
4433
- assetId: coin.assetId,
4434
- amount: bn17(coin.amount),
4435
- owner: Address2.fromAddressOrString(coin.owner),
4436
- blockCreated: bn17(coin.blockCreated),
4437
- txCreatedIdx: bn17(coin.txCreatedIdx)
4487
+ const coins = edges.map(({ node }) => ({
4488
+ id: node.utxoId,
4489
+ assetId: node.assetId,
4490
+ amount: bn17(node.amount),
4491
+ owner: Address2.fromAddressOrString(node.owner),
4492
+ blockCreated: bn17(node.blockCreated),
4493
+ txCreatedIdx: bn17(node.txCreatedIdx)
4438
4494
  }));
4495
+ return {
4496
+ coins,
4497
+ pageInfo
4498
+ };
4439
4499
  }
4440
4500
  /**
4441
4501
  * Returns resources for the given owner satisfying the spend query.
@@ -4528,14 +4588,21 @@ Supported fuel-core version: ${supportedVersion}.`
4528
4588
  * @returns A promise that resolves to the blocks.
4529
4589
  */
4530
4590
  async getBlocks(params) {
4531
- const { blocks: fetchedData } = await this.operations.getBlocks(params);
4532
- const blocks = fetchedData.edges.map(({ node: block }) => ({
4591
+ const {
4592
+ blocks: { edges, pageInfo }
4593
+ } = await this.operations.getBlocks({
4594
+ ...this.validatePaginationArgs({
4595
+ paginationLimit: BLOCKS_PAGE_SIZE_LIMIT,
4596
+ inputArgs: params
4597
+ })
4598
+ });
4599
+ const blocks = edges.map(({ node: block }) => ({
4533
4600
  id: block.id,
4534
4601
  height: bn17(block.height),
4535
4602
  time: block.header.time,
4536
4603
  transactionIds: block.transactions.map((tx) => tx.id)
4537
4604
  }));
4538
- return blocks;
4605
+ return { blocks, pageInfo };
4539
4606
  }
4540
4607
  /**
4541
4608
  * Returns block matching the given ID or type, including transaction data.
@@ -4645,17 +4712,22 @@ Supported fuel-core version: ${supportedVersion}.`
4645
4712
  * @param paginationArgs - Pagination arguments (optional).
4646
4713
  * @returns A promise that resolves to the balances.
4647
4714
  */
4648
- async getBalances(owner, paginationArgs) {
4649
- const result = await this.operations.getBalances({
4650
- first: 10,
4651
- ...paginationArgs,
4715
+ async getBalances(owner) {
4716
+ const {
4717
+ balances: { edges }
4718
+ } = await this.operations.getBalances({
4719
+ /**
4720
+ * The query parameters for this method were designed to support pagination,
4721
+ * but the current Fuel-Core implementation does not support pagination yet.
4722
+ */
4723
+ first: 1e4,
4652
4724
  filter: { owner: Address2.fromAddressOrString(owner).toB256() }
4653
4725
  });
4654
- const balances = result.balances.edges.map((edge) => edge.node);
4655
- return balances.map((balance) => ({
4656
- assetId: balance.assetId,
4657
- amount: bn17(balance.amount)
4726
+ const balances = edges.map(({ node }) => ({
4727
+ assetId: node.assetId,
4728
+ amount: bn17(node.amount)
4658
4729
  }));
4730
+ return { balances };
4659
4731
  }
4660
4732
  /**
4661
4733
  * Returns message for the given address.
@@ -4665,27 +4737,34 @@ Supported fuel-core version: ${supportedVersion}.`
4665
4737
  * @returns A promise that resolves to the messages.
4666
4738
  */
4667
4739
  async getMessages(address, paginationArgs) {
4668
- const result = await this.operations.getMessages({
4669
- first: 10,
4670
- ...paginationArgs,
4740
+ const {
4741
+ messages: { edges, pageInfo }
4742
+ } = await this.operations.getMessages({
4743
+ ...this.validatePaginationArgs({
4744
+ inputArgs: paginationArgs,
4745
+ paginationLimit: RESOURCES_PAGE_SIZE_LIMIT
4746
+ }),
4671
4747
  owner: Address2.fromAddressOrString(address).toB256()
4672
4748
  });
4673
- const messages = result.messages.edges.map((edge) => edge.node);
4674
- return messages.map((message) => ({
4749
+ const messages = edges.map(({ node }) => ({
4675
4750
  messageId: InputMessageCoder.getMessageId({
4676
- sender: message.sender,
4677
- recipient: message.recipient,
4678
- nonce: message.nonce,
4679
- amount: bn17(message.amount),
4680
- data: message.data
4751
+ sender: node.sender,
4752
+ recipient: node.recipient,
4753
+ nonce: node.nonce,
4754
+ amount: bn17(node.amount),
4755
+ data: node.data
4681
4756
  }),
4682
- sender: Address2.fromAddressOrString(message.sender),
4683
- recipient: Address2.fromAddressOrString(message.recipient),
4684
- nonce: message.nonce,
4685
- amount: bn17(message.amount),
4686
- data: InputMessageCoder.decodeData(message.data),
4687
- daHeight: bn17(message.daHeight)
4757
+ sender: Address2.fromAddressOrString(node.sender),
4758
+ recipient: Address2.fromAddressOrString(node.recipient),
4759
+ nonce: node.nonce,
4760
+ amount: bn17(node.amount),
4761
+ data: InputMessageCoder.decodeData(node.data),
4762
+ daHeight: bn17(node.daHeight)
4688
4763
  }));
4764
+ return {
4765
+ messages,
4766
+ pageInfo
4767
+ };
4689
4768
  }
4690
4769
  /**
4691
4770
  * Returns Message Proof for given transaction id and the message id from MessageOut receipt.
@@ -4864,6 +4943,41 @@ Supported fuel-core version: ${supportedVersion}.`
4864
4943
  }
4865
4944
  return relayedTransactionStatus;
4866
4945
  }
4946
+ /**
4947
+ * @hidden
4948
+ */
4949
+ validatePaginationArgs(params) {
4950
+ const { paginationLimit, inputArgs = {} } = params;
4951
+ const { first, last, after, before } = inputArgs;
4952
+ if (after && before) {
4953
+ throw new FuelError13(
4954
+ ErrorCode13.INVALID_INPUT_PARAMETERS,
4955
+ 'Pagination arguments "after" and "before" cannot be used together'
4956
+ );
4957
+ }
4958
+ if ((first || 0) > paginationLimit || (last || 0) > paginationLimit) {
4959
+ throw new FuelError13(
4960
+ ErrorCode13.INVALID_INPUT_PARAMETERS,
4961
+ `Pagination limit for this query cannot exceed ${paginationLimit} items`
4962
+ );
4963
+ }
4964
+ if (first && before) {
4965
+ throw new FuelError13(
4966
+ ErrorCode13.INVALID_INPUT_PARAMETERS,
4967
+ 'The use of pagination argument "first" with "before" is not supported'
4968
+ );
4969
+ }
4970
+ if (last && after) {
4971
+ throw new FuelError13(
4972
+ ErrorCode13.INVALID_INPUT_PARAMETERS,
4973
+ 'The use of pagination argument "last" with "after" is not supported'
4974
+ );
4975
+ }
4976
+ if (!first && !last) {
4977
+ inputArgs.first = paginationLimit;
4978
+ }
4979
+ return inputArgs;
4980
+ }
4867
4981
  /**
4868
4982
  * @hidden
4869
4983
  */
@@ -5089,52 +5203,16 @@ var Account = class extends AbstractAccount {
5089
5203
  * @param assetId - The asset ID of the coins to retrieve (optional).
5090
5204
  * @returns A promise that resolves to an array of Coins.
5091
5205
  */
5092
- async getCoins(assetId) {
5093
- const coins = [];
5094
- const pageSize = 9999;
5095
- let cursor;
5096
- for (; ; ) {
5097
- const pageCoins = await this.provider.getCoins(this.address, assetId, {
5098
- first: pageSize,
5099
- after: cursor
5100
- });
5101
- coins.push(...pageCoins);
5102
- const hasNextPage = pageCoins.length >= pageSize;
5103
- if (!hasNextPage) {
5104
- break;
5105
- }
5106
- throw new FuelError15(
5107
- ErrorCode15.NOT_SUPPORTED,
5108
- `Wallets containing more than ${pageSize} coins exceed the current supported limit.`
5109
- );
5110
- }
5111
- return coins;
5206
+ async getCoins(assetId, paginationArgs) {
5207
+ return this.provider.getCoins(this.address, assetId, paginationArgs);
5112
5208
  }
5113
5209
  /**
5114
5210
  * Retrieves messages owned by the account.
5115
5211
  *
5116
5212
  * @returns A promise that resolves to an array of Messages.
5117
5213
  */
5118
- async getMessages() {
5119
- const messages = [];
5120
- const pageSize = 9999;
5121
- let cursor;
5122
- for (; ; ) {
5123
- const pageMessages = await this.provider.getMessages(this.address, {
5124
- first: pageSize,
5125
- after: cursor
5126
- });
5127
- messages.push(...pageMessages);
5128
- const hasNextPage = pageMessages.length >= pageSize;
5129
- if (!hasNextPage) {
5130
- break;
5131
- }
5132
- throw new FuelError15(
5133
- ErrorCode15.NOT_SUPPORTED,
5134
- `Wallets containing more than ${pageSize} messages exceed the current supported limit.`
5135
- );
5136
- }
5137
- return messages;
5214
+ async getMessages(paginationArgs) {
5215
+ return this.provider.getMessages(this.address, paginationArgs);
5138
5216
  }
5139
5217
  /**
5140
5218
  * Retrieves the balance of the account for the given asset.
@@ -5153,25 +5231,7 @@ var Account = class extends AbstractAccount {
5153
5231
  * @returns A promise that resolves to an array of Coins and their quantities.
5154
5232
  */
5155
5233
  async getBalances() {
5156
- const balances = [];
5157
- const pageSize = 9999;
5158
- let cursor;
5159
- for (; ; ) {
5160
- const pageBalances = await this.provider.getBalances(this.address, {
5161
- first: pageSize,
5162
- after: cursor
5163
- });
5164
- balances.push(...pageBalances);
5165
- const hasNextPage = pageBalances.length >= pageSize;
5166
- if (!hasNextPage) {
5167
- break;
5168
- }
5169
- throw new FuelError15(
5170
- ErrorCode15.NOT_SUPPORTED,
5171
- `Wallets containing more than ${pageSize} balances exceed the current supported limit.`
5172
- );
5173
- }
5174
- return balances;
5234
+ return this.provider.getBalances(this.address);
5175
5235
  }
5176
5236
  /**
5177
5237
  * Funds a transaction request by adding the necessary resources.
@@ -8613,14 +8673,13 @@ var generateTestWallet = async (provider, quantities) => {
8613
8673
  // src/test-utils/launchNode.ts
8614
8674
  import { BYTES_32 as BYTES_322 } from "@fuel-ts/abi-coder";
8615
8675
  import { randomBytes as randomBytes7 } from "@fuel-ts/crypto";
8676
+ import { FuelError as FuelError20 } from "@fuel-ts/errors";
8616
8677
  import { defaultConsensusKey, hexlify as hexlify19, defaultSnapshotConfigs } from "@fuel-ts/utils";
8617
- import { spawn } from "child_process";
8618
8678
  import { randomUUID } from "crypto";
8619
8679
  import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs";
8620
8680
  import os from "os";
8621
8681
  import path from "path";
8622
8682
  import { getPortPromise } from "portfinder";
8623
- import treeKill from "tree-kill";
8624
8683
  var getFlagValueFromArgs = (args, flag) => {
8625
8684
  const flagIndex = args.indexOf(flag);
8626
8685
  if (flagIndex === -1) {
@@ -8638,20 +8697,6 @@ var extractRemainingArgs = (args, flagsToRemove) => {
8638
8697
  });
8639
8698
  return newArgs;
8640
8699
  };
8641
- var killNode = (params) => {
8642
- const { child, configPath, state, killFn } = params;
8643
- if (!state.isDead) {
8644
- if (child.pid) {
8645
- state.isDead = true;
8646
- killFn(Number(child.pid));
8647
- }
8648
- child.stdout.removeAllListeners();
8649
- child.stderr.removeAllListeners();
8650
- if (existsSync(configPath)) {
8651
- rmSync(configPath, { recursive: true });
8652
- }
8653
- }
8654
- };
8655
8700
  function getFinalStateConfigJSON({ stateConfig, chainConfig }) {
8656
8701
  const defaultCoins = defaultSnapshotConfigs.stateConfig.coins.map((coin) => ({
8657
8702
  ...coin,
@@ -8690,12 +8735,11 @@ var launchNode = async ({
8690
8735
  ip,
8691
8736
  port,
8692
8737
  args = [],
8693
- fuelCorePath = process.env.FUEL_CORE_PATH ?? void 0,
8738
+ fuelCorePath = process.env.FUEL_CORE_PATH || void 0,
8694
8739
  loggingEnabled = true,
8695
- debugEnabled = false,
8696
8740
  basePath,
8697
8741
  snapshotConfig = defaultSnapshotConfigs
8698
- }) => (
8742
+ } = {}) => (
8699
8743
  // eslint-disable-next-line no-async-promise-executor
8700
8744
  new Promise(async (resolve, reject) => {
8701
8745
  const remainingArgs = extractRemainingArgs(args, [
@@ -8712,7 +8756,7 @@ var launchNode = async ({
8712
8756
  const poaInstant = poaInstantFlagValue === "true" || poaInstantFlagValue === void 0;
8713
8757
  const nativeExecutorVersion = getFlagValueFromArgs(args, "--native-executor-version") || "0";
8714
8758
  const graphQLStartSubstring = "Binding GraphQL provider to";
8715
- const command = fuelCorePath ?? "fuel-core";
8759
+ const command = fuelCorePath || "fuel-core";
8716
8760
  const ipToUse = ip || "0.0.0.0";
8717
8761
  const portToUse = port || (await getPortPromise({
8718
8762
  port: 4e3,
@@ -8741,6 +8785,7 @@ var launchNode = async ({
8741
8785
  writeFileSync(stateTransitionPath, JSON.stringify(""));
8742
8786
  snapshotDirToUse = tempDir;
8743
8787
  }
8788
+ const { spawn } = await import("child_process");
8744
8789
  const child = spawn(
8745
8790
  command,
8746
8791
  [
@@ -8758,22 +8803,45 @@ var launchNode = async ({
8758
8803
  "--debug",
8759
8804
  ...remainingArgs
8760
8805
  ].flat(),
8761
- {
8762
- stdio: "pipe"
8763
- }
8806
+ { stdio: "pipe", detached: true }
8764
8807
  );
8765
8808
  if (loggingEnabled) {
8766
- child.stderr.pipe(process.stderr);
8767
- }
8768
- if (debugEnabled) {
8769
- child.stdout.pipe(process.stdout);
8809
+ child.stderr.on("data", (chunk) => {
8810
+ console.log(chunk.toString());
8811
+ });
8770
8812
  }
8771
- const cleanupConfig = {
8772
- child,
8773
- configPath: tempDir,
8774
- killFn: treeKill,
8775
- state: {
8776
- isDead: false
8813
+ const removeSideffects = () => {
8814
+ child.stderr.removeAllListeners();
8815
+ if (existsSync(tempDir)) {
8816
+ rmSync(tempDir, { recursive: true });
8817
+ }
8818
+ };
8819
+ child.on("error", removeSideffects);
8820
+ child.on("exit", removeSideffects);
8821
+ const childState = {
8822
+ isDead: false
8823
+ };
8824
+ const cleanup = () => {
8825
+ if (childState.isDead) {
8826
+ return;
8827
+ }
8828
+ childState.isDead = true;
8829
+ removeSideffects();
8830
+ if (child.pid !== void 0) {
8831
+ try {
8832
+ process.kill(-child.pid);
8833
+ } catch (e) {
8834
+ const error = e;
8835
+ if (error.code === "ESRCH") {
8836
+ console.log(
8837
+ `fuel-core node under pid ${child.pid} does not exist. The node might have been killed before cleanup was called. Exiting cleanly.`
8838
+ );
8839
+ } else {
8840
+ throw e;
8841
+ }
8842
+ }
8843
+ } else {
8844
+ console.error("No PID available for the child process, unable to kill launched node");
8777
8845
  }
8778
8846
  };
8779
8847
  child.stderr.on("data", (chunk) => {
@@ -8783,23 +8851,25 @@ var launchNode = async ({
8783
8851
  const rowWithUrl = rows.find((row) => row.indexOf(graphQLStartSubstring) !== -1);
8784
8852
  const [realIp, realPort] = rowWithUrl.split(" ").at(-1).trim().split(":");
8785
8853
  resolve({
8786
- cleanup: () => killNode(cleanupConfig),
8854
+ cleanup,
8787
8855
  ip: realIp,
8788
8856
  port: realPort,
8789
8857
  url: `http://${realIp}:${realPort}/v1/graphql`,
8790
- snapshotDir: snapshotDirToUse
8858
+ snapshotDir: snapshotDirToUse,
8859
+ pid: child.pid
8791
8860
  });
8792
8861
  }
8793
8862
  if (/error/i.test(text)) {
8794
- reject(text.toString());
8863
+ console.log(text);
8864
+ reject(new FuelError20(FuelError20.CODES.NODE_LAUNCH_FAILED, text));
8795
8865
  }
8796
8866
  });
8797
- process.on("exit", () => killNode(cleanupConfig));
8798
- process.on("SIGINT", () => killNode(cleanupConfig));
8799
- process.on("SIGUSR1", () => killNode(cleanupConfig));
8800
- process.on("SIGUSR2", () => killNode(cleanupConfig));
8801
- process.on("beforeExit", () => killNode(cleanupConfig));
8802
- process.on("uncaughtException", () => killNode(cleanupConfig));
8867
+ process.on("exit", cleanup);
8868
+ process.on("SIGINT", cleanup);
8869
+ process.on("SIGUSR1", cleanup);
8870
+ process.on("SIGUSR2", cleanup);
8871
+ process.on("beforeExit", cleanup);
8872
+ process.on("uncaughtException", cleanup);
8803
8873
  child.on("error", reject);
8804
8874
  })
8805
8875
  );
@@ -8854,7 +8924,7 @@ __publicField(AssetId, "B", new _AssetId(
8854
8924
 
8855
8925
  // src/test-utils/wallet-config.ts
8856
8926
  import { randomBytes as randomBytes9 } from "@fuel-ts/crypto";
8857
- import { FuelError as FuelError20 } from "@fuel-ts/errors";
8927
+ import { FuelError as FuelError21 } from "@fuel-ts/errors";
8858
8928
  import { defaultSnapshotConfigs as defaultSnapshotConfigs2, hexlify as hexlify21 } from "@fuel-ts/utils";
8859
8929
  var WalletsConfig = class {
8860
8930
  initialState;
@@ -8934,26 +9004,26 @@ var WalletsConfig = class {
8934
9004
  amountPerCoin
8935
9005
  }) {
8936
9006
  if (Array.isArray(wallets) && wallets.length === 0 || typeof wallets === "number" && wallets <= 0) {
8937
- throw new FuelError20(
8938
- FuelError20.CODES.INVALID_INPUT_PARAMETERS,
9007
+ throw new FuelError21(
9008
+ FuelError21.CODES.INVALID_INPUT_PARAMETERS,
8939
9009
  "Number of wallets must be greater than zero."
8940
9010
  );
8941
9011
  }
8942
9012
  if (Array.isArray(assets2) && assets2.length === 0 || typeof assets2 === "number" && assets2 <= 0) {
8943
- throw new FuelError20(
8944
- FuelError20.CODES.INVALID_INPUT_PARAMETERS,
9013
+ throw new FuelError21(
9014
+ FuelError21.CODES.INVALID_INPUT_PARAMETERS,
8945
9015
  "Number of assets per wallet must be greater than zero."
8946
9016
  );
8947
9017
  }
8948
9018
  if (coinsPerAsset <= 0) {
8949
- throw new FuelError20(
8950
- FuelError20.CODES.INVALID_INPUT_PARAMETERS,
9019
+ throw new FuelError21(
9020
+ FuelError21.CODES.INVALID_INPUT_PARAMETERS,
8951
9021
  "Number of coins per asset must be greater than zero."
8952
9022
  );
8953
9023
  }
8954
9024
  if (amountPerCoin <= 0) {
8955
- throw new FuelError20(
8956
- FuelError20.CODES.INVALID_INPUT_PARAMETERS,
9025
+ throw new FuelError21(
9026
+ FuelError21.CODES.INVALID_INPUT_PARAMETERS,
8957
9027
  "Amount per coin must be greater than zero."
8958
9028
  );
8959
9029
  }
@@ -8971,7 +9041,8 @@ var defaultWalletConfigOptions = {
8971
9041
  async function setupTestProviderAndWallets({
8972
9042
  walletsConfig: walletsConfigOptions = {},
8973
9043
  providerOptions,
8974
- nodeOptions = {}
9044
+ nodeOptions = {},
9045
+ launchNodeServerPort = process.env.LAUNCH_NODE_SERVER_PORT || void 0
8975
9046
  } = {}) {
8976
9047
  Symbol.dispose ??= Symbol("Symbol.dispose");
8977
9048
  const walletsConfig = new WalletsConfig(
@@ -8981,7 +9052,7 @@ async function setupTestProviderAndWallets({
8981
9052
  ...walletsConfigOptions
8982
9053
  }
8983
9054
  );
8984
- const { cleanup, url } = await launchNode({
9055
+ const launchNodeOptions = {
8985
9056
  loggingEnabled: false,
8986
9057
  ...nodeOptions,
8987
9058
  snapshotConfig: mergeDeepRight(
@@ -8989,7 +9060,20 @@ async function setupTestProviderAndWallets({
8989
9060
  walletsConfig.apply(nodeOptions?.snapshotConfig)
8990
9061
  ),
8991
9062
  port: "0"
8992
- });
9063
+ };
9064
+ let cleanup;
9065
+ let url;
9066
+ if (launchNodeServerPort) {
9067
+ const serverUrl = `http://localhost:${launchNodeServerPort}`;
9068
+ url = await (await fetch(serverUrl, { method: "POST", body: JSON.stringify(launchNodeOptions) })).text();
9069
+ cleanup = () => {
9070
+ fetch(`${serverUrl}/cleanup/${url}`);
9071
+ };
9072
+ } else {
9073
+ const settings = await launchNode(launchNodeOptions);
9074
+ url = settings.url;
9075
+ cleanup = settings.cleanup;
9076
+ }
8993
9077
  let provider;
8994
9078
  try {
8995
9079
  provider = await Provider.create(url, providerOptions);
@@ -9058,7 +9142,6 @@ export {
9058
9142
  TestMessage,
9059
9143
  WalletsConfig,
9060
9144
  generateTestWallet,
9061
- killNode,
9062
9145
  launchNode,
9063
9146
  launchNodeAndGetWallets,
9064
9147
  seedTestWallet,