diff --git a/.changeset/stupid-jokes-exist.md b/.changeset/stupid-jokes-exist.md new file mode 100644 index 00000000000..68546268dd7 --- /dev/null +++ b/.changeset/stupid-jokes-exist.md @@ -0,0 +1,4 @@ +--- +--- + +chore: add script for network testing diff --git a/.env.example b/.env.example index d848920a46b..e3a6565e3c5 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ DEVNET_WALLET_PVT_KEY= TESTNET_WALLET_PVT_KEY= -PUBLISHED_NPM_TAG= \ No newline at end of file +PUBLISHED_NPM_TAG= +NETWORK_TEST_URL= +NETWORK_TEST_PVT_KEY= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6b12eeed677..b7d90e864f5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -361,6 +361,40 @@ We'd follow the same approach as explained in the [Patching old releases](#patch - have the versions of packages on `master` match the `latest` released package versions, - have the released functionality on `master` as well +# Network Testing + +The network test suite is designed to run locally against a specified network for validation purposes. + +You can find the test suite at: `packages/fuel-gauge/src/network.test.ts`. + +### Setup Instructions + +Before running the tests, you need to configure the `.env` file: + +1. Copy the `.env.example` file: + +```sh +cp .env.example .env +``` + +2. Set the values for the following environment variables in the `.env` file: + +```env +NETWORK_TEST_URL=https://testnet.fuel.network/v1/graphql +NETWORK_TEST_PVT_KEY=0x... +``` + +- `NETWORK_TEST_URL`: The URL of which network the test should run (e.g., Fuel Testnet endpoint). +- `NETWORK_TEST_PVT_KEY`: Your private key for the network. + +### Running the Test Suite + +Once the environment is set up, run the network tests using the following command: + +```sh +pnpm test:network +``` + # FAQ ### Why is the prefix `fuels` and not `fuel`? diff --git a/package.json b/package.json index 028d7a99608..d9009eec20d 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "test:browser:filter": "vitest --run --coverage false --config vitest.browser.config.mts", "test:e2e": "vitest --run --config vitest.node.config.mts $(scripts/tests-find.sh --e2e)", "test:integration": "vitest --run --config vitest.node.config.mts $(scripts/tests-find.sh --integration)", + "test:network": "vitest --run --config vitest.node.config.mts $(scripts/tests-find.sh --network)", "lint": "run-s type:check-tests lint:check prettier:check type:check", "lint:check": "eslint . --ext .ts --max-warnings 0", "lint:fix": "pnpm lint:check --fix", diff --git a/packages/fuel-gauge/src/network.test.ts b/packages/fuel-gauge/src/network.test.ts new file mode 100644 index 00000000000..f38becdb9ee --- /dev/null +++ b/packages/fuel-gauge/src/network.test.ts @@ -0,0 +1,151 @@ +import type { BaseWalletUnlocked, ContractTransferParams, ReceiptTransfer } from 'fuels'; +import { Provider, ReceiptType, Wallet } from 'fuels'; + +import { + CoverageContract, + CoverageContractFactory, + PredicateWithConfigurable, + ScriptMainArgs, + StorageTestContract, + StorageTestContractFactory, +} from '../test/typegen'; + +/** + * @group network + */ +describe('network', () => { + const timeout = 1000 * 50; // 50 seconds + + let contractId1: string; + let contractId2: string; + let provider: Provider; + let wallet: BaseWalletUnlocked; + let baseAssetId: string; + + beforeAll(async () => { + if (!process.env.NETWORK_TEST_URL || !process.env.NETWORK_TEST_PVT_KEY) { + throw new Error('Please provide NETWORK_TEST_URL and NETWORK_TEST_PVT_KEY in the .env file'); + } + + provider = new Provider(process.env.NETWORK_TEST_URL); + wallet = Wallet.fromPrivateKey(process.env.NETWORK_TEST_PVT_KEY, provider); + baseAssetId = await provider.getBaseAssetId(); + }); + + it('should deploy contracts just fine', { timeout }, async () => { + const { waitForResult } = await StorageTestContractFactory.deploy(wallet); + const { contract: contract1, transactionResult: transactionResult1 } = await waitForResult(); + + const { waitForResult: waitForResult2 } = await CoverageContractFactory.deploy(wallet); + const { contract: contract2, transactionResult: transactionResult2 } = await waitForResult2(); + + expect(transactionResult1.isStatusSuccess).toBeTruthy(); + expect(transactionResult2.isStatusSuccess).toBeTruthy(); + + contractId1 = contract1.id.toB256(); + contractId2 = contract2.id.toB256(); + }); + + it('should transfer to contracts just fine', { timeout }, async () => { + const contractTransferParams: ContractTransferParams[] = [ + { + contractId: contractId1, + amount: 1, + assetId: baseAssetId, + }, + { + contractId: contractId2, + amount: 3, + assetId: baseAssetId, + }, + { + contractId: contractId1, + amount: 2, + assetId: baseAssetId, + }, + ]; + + const submit = await wallet.batchTransferToContracts(contractTransferParams); + const { receipts } = await submit.waitForResult(); + + const transferReceipts = receipts.filter( + ({ type }) => type === ReceiptType.Transfer + ) as ReceiptTransfer[]; + + expect(transferReceipts.length).toBe(contractTransferParams.length); + + contractTransferParams.forEach(({ amount, contractId, assetId = baseAssetId }) => { + const foundReceipt = transferReceipts.find( + (r) => r.amount.eq(amount) && r.to === contractId && r.assetId === assetId + ); + + expect(foundReceipt).toBeDefined(); + }); + }); + + it('should execute contract call just fine', { timeout }, async () => { + const contract = new StorageTestContract(contractId1, wallet); + + const call = await contract.functions.initialize_counter(1).call(); + const { transactionResult } = await call.waitForResult(); + + expect(transactionResult.isStatusSuccess).toBeTruthy(); + }); + + it('should execute contract multi-call just fine', { timeout }, async () => { + const contract1 = new StorageTestContract(contractId1, wallet); + const contract2 = new CoverageContract(contractId2, wallet); + + const call = await contract1 + .multiCall([ + contract1.functions.increment_counter(2), + contract1.functions.counter(), + contract2.functions.echo_bool(true), + ]) + .call(); + + const { transactionResult } = await call.waitForResult(); + + expect(transactionResult.isStatusSuccess).toBeTruthy(); + }); + + it('should deploy contract as blob and execute it just fine', { timeout }, async () => { + const factory = new StorageTestContractFactory(wallet); + const { waitForResult } = await factory.deployAsBlobTx(); + const { contract } = await waitForResult(); + + const call = await contract.functions.initialize_counter(1).call(); + const { transactionResult } = await call.waitForResult(); + + expect(transactionResult.isStatusSuccess).toBeTruthy(); + }); + + it('should deploy script as blob and execute it just fine', { timeout }, async () => { + const script = new ScriptMainArgs(wallet); + const { waitForResult } = await script.deploy(wallet); + const scriptAsBlob = await waitForResult(); + + const call = await scriptAsBlob.functions.main(100).call(); + + const { transactionResult } = await call.waitForResult(); + expect(transactionResult.isStatusSuccess).toBeTruthy(); + }); + + it('should deploy predicate as blob and use it just fine', { timeout }, async () => { + const predicate = new PredicateWithConfigurable({ + provider, + configurableConstants: { FEE: 10, ADDRESS: wallet.address.toB256() }, + data: [10, wallet.address.toB256()], + }); + const { waitForResult } = await predicate.deploy(wallet); + const predicateAsBlob = await waitForResult(); + + const transfer = await wallet.transfer(predicateAsBlob.address, 800, baseAssetId); + await transfer.waitForResult(); + + const transfer2 = await predicateAsBlob.transfer(wallet.address, 100, baseAssetId); + const { isStatusSuccess } = await transfer2.waitForResult(); + + expect(isStatusSuccess).toBeTruthy(); + }); +}); diff --git a/scripts/tests-find.sh b/scripts/tests-find.sh index b6a808a4162..fe360babdec 100755 --- a/scripts/tests-find.sh +++ b/scripts/tests-find.sh @@ -14,4 +14,6 @@ elif [[ $* == *--e2e* ]]; then grep -lE "\*\s+@group\s+e2e" $FILES elif [[ $* == *--integration* ]]; then grep -lE "\*\s+@group\s+integration" $FILES +elif [[ $* == *--network* ]]; then + grep -lE "\*\s+@group\s+network" $FILES fi diff --git a/scripts/tests-validate.sh b/scripts/tests-validate.sh index 59da48b12e9..eec27cfdf6a 100755 --- a/scripts/tests-validate.sh +++ b/scripts/tests-validate.sh @@ -5,10 +5,10 @@ ROOT=$(cd "$(dirname "$0")/.."; pwd) # ignore files in apps/create-fuels-counter-guide/test/ FILES=$(find $ROOT/{apps,packages,internal} -name '*.test.ts' | grep -v "apps/create-fuels-counter-guide/test/") -INVALID_FILES=$(grep -LE "@group\s+(node|browser|e2e|integration)" $FILES) +INVALID_FILES=$(grep -LE "@group\s+(node|browser|e2e|integration|network)" $FILES) if [ ! -z "$INVALID_FILES" ]; then echo -e "Test files don't contain a test environment configuration:" echo -e $INVALID_FILES exit 1 -fi \ No newline at end of file +fi