diff --git a/.changeset/lazy-years-share.md b/.changeset/lazy-years-share.md new file mode 100644 index 00000000000..4f7bbb87e72 --- /dev/null +++ b/.changeset/lazy-years-share.md @@ -0,0 +1,5 @@ +--- +"fuels": patch +--- + +docs: add further snippets with new infrastructure diff --git a/.eslintignore b/.eslintignore index 2f9746e2918..ff5b676d8a4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -13,6 +13,7 @@ apps/demo-react-cra apps/demo-react-vite apps/create-fuels-counter-guide apps/docs-snippets2/src/typegend +apps/docs-snippets2/src/**/*.test.ts packages/fuels/src/cli/commands/deploy/proxy packages/fuels/test/fixtures/project diff --git a/.prettierignore b/.prettierignore index 5576b6cd7fc..4285e9462f6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -14,6 +14,8 @@ apps/demo-typegen/src/script-types apps/demo-typegen/src/predicate-types apps/docs/.vitepress/cache/ apps/create-fuels-counter-guide +apps/docs-snippets/.fuels +apps/docs-snippets2/.fuels packages/fuels/src/cli/commands/deploy/proxy packages/fuels/test/fixtures/project diff --git a/apps/docs-snippets/.gitignore b/apps/docs-snippets/.gitignore new file mode 100644 index 00000000000..e4943ddb2d1 --- /dev/null +++ b/apps/docs-snippets/.gitignore @@ -0,0 +1 @@ +.fuels/ \ No newline at end of file diff --git a/apps/docs-snippets/scripts/pretest.sh b/apps/docs-snippets/scripts/pretest.sh index e4e41106e97..25f1121e8e3 100755 --- a/apps/docs-snippets/scripts/pretest.sh +++ b/apps/docs-snippets/scripts/pretest.sh @@ -1,8 +1,8 @@ -# Kill anything running on port 4000 -lsof -t -i:4000 | xargs -r kill - -# Runs a node at port 4000 -pnpm fuels node > /dev/null 2>&1 & +# Check if node is already running at port 4000, if not start it +# TODO: This is a temporary solution to avoid conflicts with the test node in docs-snippets2 +if ! lsof -t -i:4000 > /dev/null; then + pnpm fuels node > /dev/null 2>&1 & +fi # Builds projects pnpm fuels build @@ -10,8 +10,5 @@ pnpm fuels build # Deploys projects (needed for loader bytecode) pnpm fuels deploy -# Kills the node -lsof -t -i:4000 | xargs -r kill - # Checks for type errors pnpm tsc --noEmit \ No newline at end of file diff --git a/apps/docs-snippets/src/guide/create-fuels/decrement_counter.test.ts b/apps/docs-snippets/src/guide/create-fuels/decrement_counter.test.ts deleted file mode 100644 index 90b255b1f0a..00000000000 --- a/apps/docs-snippets/src/guide/create-fuels/decrement_counter.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { launchTestNode } from 'fuels/test-utils'; -import { describe, test, expect } from 'vitest'; - -import { CounterFactory } from '../../../test/typegen'; - -/** - * @group node - * @group browser - */ -describe('Counter Contract', () => { - // #region decrement-counter - // #context import { Counter } from './sway-programs-api'; - - test('calls the decrement_counter function', async () => { - // First, we'll launch a test node, passing the contract factory and bytecode. This will deploy the contract - // to our test node so we can test against it. - using launched = await launchTestNode({ - // The test node will be killed automatically once the `launched` variable goes out of scope, - // because we are instantiating it with the `using` keyword. - contractsConfigs: [ - { - factory: CounterFactory, - }, - ], - }); - - // We can now destructure the contract from the launched object. - const { - contracts: [contract], - } = launched; - - // Lets setup some values to use in the test. - const initialCount = 0; - const incrementedValue = 5; - const decrementedValue = 2; - - // We can now call the contract functions and test the results. Lets assert the initial value of the counter. - const { waitForResult: initWaitForResult } = await contract.functions.get_count().call(); - const { value: initValue } = await initWaitForResult(); - expect(initValue.toNumber()).toBe(initialCount); - - // Next we'll increment the counter, so that we can decrement it. - const { waitForResult: incWaitForResult } = await contract.functions - .increment_counter(5) - .call(); - const { value: incValue } = await incWaitForResult(); - expect(incValue.toNumber()).toBe(incrementedValue); - - // Next, we'll decrement the counter by 3 and assert the new value. - const { waitForResult: decWaitForResult } = await contract.functions - .decrement_counter(3) - .call(); - const { value: decValue } = await decWaitForResult(); - expect(decValue.toNumber()).toBe(decrementedValue); - - // Finally, we'll test the get count function again to ensure parity. - const { waitForResult: finalWaitForResult } = await contract.functions.get_count().call(); - const { value: finalValue } = await finalWaitForResult(); - expect(finalValue.toNumber()).toBe(decrementedValue); - }); - // #endregion decrement-counter -}); diff --git a/apps/docs-snippets/src/guide/encoding/encode-and-decode.test.ts b/apps/docs-snippets/src/guide/encoding/encode-and-decode.test.ts deleted file mode 100644 index 3e9595453e4..00000000000 --- a/apps/docs-snippets/src/guide/encoding/encode-and-decode.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -import type { JsonAbi, TransactionResultReturnDataReceipt } from 'fuels'; -import { buildFunctionResult, ReceiptType, arrayify, Script, Interface } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore JSONC extension requires mapping but behaves fine -import abiSnippet from '../../../test/fixtures/abi/encode-and-decode.jsonc'; -import { SumScript as factory } from '../../../test/typegen/scripts/SumScript'; - -/** - * @group node - * @group browser - */ -describe('encode and decode', () => { - it('generates valid ABI', () => { - expect(abiSnippet).toEqual(factory.abi); - }); - - it('encodes and decodes', async () => { - using launched = await launchTestNode(); - const { - wallets: [wallet], - } = launched; - - // #region encode-and-decode-3 - // #import { JsonAbi, Script }; - // #context import { factory } from './sway-programs-api'; - - // First we need to build out the transaction via the script that we want to encode. - // For that we'll need the ABI and the bytecode of the script - const abi: JsonAbi = factory.abi; - const bytecode = factory.bytecode; - - // Create the invocation scope for the script call, passing the initial - // value for the configurable constant - const script = new Script(bytecode, abi, wallet); - const initialValue = 10; - script.setConfigurableConstants({ AMOUNT: initialValue }); - const invocationScope = script.functions.main(0); - - // Create the transaction request, this can be picked off the invocation - // scope so the script bytecode is preset on the transaction - const request = await invocationScope.getTransactionRequest(); - // #endregion encode-and-decode-3 - - // #region encode-and-decode-4 - // #import { Interface }; - - // Now we can encode the argument we want to pass to the function. The argument is required - // as a function parameter for all abi functions and we can extract it from the ABI itself - const argument = abi.functions - .find((f) => f.name === 'main') - ?.inputs.find((i) => i.name === 'inputted_amount')?.concreteTypeId as string; - - // The `Interface` class is the entry point for encoding and decoding all things abi-related. - // We will use its `encodeType` method and create the encoding required for - // a u32 which takes 4 bytes up of property space. - - const abiInterface = new Interface(abi); - const argumentToAdd = 10; - const encodedArguments = abiInterface.encodeType(argument, [argumentToAdd]); - // Therefore the value of 10 will be encoded to: - // Uint8Array([0, 0, 0, 10] - - // The encoded value can now be set on the transaction via the script data property - request.scriptData = encodedArguments; - - // Now we can build out the rest of the transaction and then fund it - const txCost = await wallet.getTransactionCost(request); - request.maxFee = txCost.maxFee; - request.gasLimit = txCost.gasUsed; - await wallet.fund(request, txCost); - - // Finally, submit the built transaction - const response = await wallet.sendTransaction(request); - await response.waitForResult(); - // #endregion encode-and-decode-4 - - // #region encode-and-decode-5 - // #import { ReceiptType, TransactionResultReturnDataReceipt, arrayify, buildFunctionResult }; - - // Get result of the transaction, including the contract call result. For this we'll need - // the previously created invocation scope, the transaction response and the script - const invocationResult = await buildFunctionResult({ - funcScope: invocationScope, - isMultiCall: false, - program: script, - transactionResponse: response, - }); - - // The decoded value can be destructured from the `FunctionInvocationResult` - const { value } = invocationResult; - - // Or we can decode the returned bytes ourselves, by retrieving the return data - // receipt that contains the returned bytes. We can get this by filtering on - // the returned receipt types - const returnDataReceipt = invocationResult.transactionResult.receipts.find( - (r) => r.type === ReceiptType.ReturnData - ) as TransactionResultReturnDataReceipt; - - // The data is in hex format so it makes sense to use arrayify so that the data - // is more human readable - const returnData = arrayify(returnDataReceipt.data); - // returnData = new Uint8Array([0, 0, 0, 20] - - // And now we can decode the returned bytes in a similar fashion to how they were - // encoded, via the `Interface` - const [decodedReturnData] = abiInterface.decodeType(argument, returnData); - // 20 - // #endregion encode-and-decode-5 - - const totalValue = argumentToAdd + initialValue; - expect(value).toBe(totalValue); - expect(decodedReturnData).toBe(totalValue); - expect(encodedArguments).toStrictEqual(new Uint8Array([0, 0, 0, 10])); - expect(returnData).toStrictEqual(new Uint8Array([0, 0, 0, 20])); - }); -}); diff --git a/apps/docs-snippets/src/guide/encoding/working-with-bytes.test.ts b/apps/docs-snippets/src/guide/encoding/working-with-bytes.test.ts deleted file mode 100644 index dbec9691cd3..00000000000 --- a/apps/docs-snippets/src/guide/encoding/working-with-bytes.test.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { randomBytes } from 'crypto'; -import { - ArrayCoder, - B256Coder, - B512Coder, - BigNumberCoder, - BooleanCoder, - EnumCoder, - NumberCoder, - RawSliceCoder, - StdStringCoder, - StringCoder, - StructCoder, - TupleCoder, - VecCoder, - hexlify, -} from 'fuels'; - -/** - * @group node - */ -describe('working with bytes', () => { - it('integers', () => { - // #region working-with-bytes-1 - // #import { NumberCoder, BigNumberCoder }; - - const u8Coder = new NumberCoder('u8'); - const encodedU8 = u8Coder.encode(255); - // encodedU8 = new Uint8Array([255]); - - const u16Coder = new NumberCoder('u16'); - const encodedU16 = u16Coder.encode(255); - // encodedU16 = new Uint8Array([0, 255]); - - const u32Coder = new NumberCoder('u32'); - const encodedU32 = u32Coder.encode(255); - // encodedU32 = new Uint8Array([0, 0, 0, 255]); - - const u64Coder = new BigNumberCoder('u64'); - const encodedU64 = u64Coder.encode(255); - // encodedU64 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 255]); - - const u256Coder = new BigNumberCoder('u256'); - const encodedU256 = u256Coder.encode(255); - // encodedU256 = new Uint8Array([ - // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 - // ]); - // #endregion working-with-bytes-1 - - expect(encodedU8).toEqual(new Uint8Array([255])); - expect(encodedU16).toEqual(new Uint8Array([0, 255])); - expect(encodedU32).toEqual(new Uint8Array([0, 0, 0, 255])); - expect(encodedU64).toEqual(new Uint8Array([0, 0, 0, 0, 0, 0, 0, 255])); - expect(encodedU256).toEqual( - new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 255, - ]) - ); - }); - - it('boolean', () => { - // #region working-with-bytes-2 - // #import { BooleanCoder }; - - const booleanCoder = new BooleanCoder(); - const encodedTrue = booleanCoder.encode(true); - // encodedTrue = new Uint8Array([1]); - - const encodedFalse = booleanCoder.encode(false); - // encodedFalse = new Uint8Array([0]); - // #endregion working-with-bytes-2 - - expect(encodedTrue).toEqual(new Uint8Array([1])); - expect(encodedFalse).toEqual(new Uint8Array([0])); - }); - - it('fixed len strings', () => { - // #region working-with-bytes-3 - // #import { StringCoder }; - - const stringCoder = new StringCoder(5); - const encoded = stringCoder.encode('hello'); - // encoded = new Uint8Array([104, 101, 108, 108, 111]); - // #endregion working-with-bytes-3 - - expect(encoded).toEqual(new Uint8Array([104, 101, 108, 108, 111])); - }); - - it('b256 / b512', () => { - // #region working-with-bytes-4 - // #import { B256Coder, B512Coder, hexlify, randomBytes }; - - const b256Coder = new B256Coder(); - const encodedB256 = b256Coder.encode(hexlify(randomBytes(32))); - // encodedB256 = new Uint8Array(32); - - const b512Coder = new B512Coder(); - const encodedB512 = b512Coder.encode(hexlify(randomBytes(64))); - // encodedB512 = new Uint8Array(64); - // #endregion working-with-bytes-4 - - expect(encodedB256).toHaveLength(32); - expect(encodedB512).toHaveLength(64); - }); - - it('automatically encoded types', () => { - // #region working-with-bytes-5 - // #import { TupleCoder, StructCoder, ArrayCoder, EnumCoder }; - - const tupleCoder = new TupleCoder([new NumberCoder('u8'), new NumberCoder('u16')]); - const encodedTuple = tupleCoder.encode([255, 255]); - // encodedTuple = new Uint8Array([255, 0, 255]); - - const structCoder = new StructCoder('struct', { - a: new NumberCoder('u8'), - b: new NumberCoder('u16'), - }); - const encodedStruct = structCoder.encode({ a: 255, b: 255 }); - // encodedStruct = new Uint8Array([255, 0, 255]); - - const arrayCoder = new ArrayCoder(new NumberCoder('u8'), 4); - const encodedArray = arrayCoder.encode([255, 0, 255, 0]); - // encodedArray = new Uint8Array([255, 0, 255, 0]); - - const enumCoder = new EnumCoder('enum', { a: new NumberCoder('u32') }); - const encodedEnum = enumCoder.encode({ a: 255 }); - // encodedEnum = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255]); - // #endregion working-with-bytes-5 - - expect(encodedTuple).toEqual(new Uint8Array([255, 0, 255])); - expect(encodedStruct).toEqual(new Uint8Array([255, 0, 255])); - expect(encodedArray).toEqual(new Uint8Array([255, 0, 255, 0])); - expect(encodedEnum).toEqual(new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255])); - }); - - it('heap types', () => { - // #region working-with-bytes-6 - // #import { VecCoder, StdStringCoder, RawSliceCoder }; - - const vecCoder = new VecCoder(new NumberCoder('u8')); - const encodedVec = vecCoder.encode([255, 0, 255]); - // encodedVec = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 3, 255, 0, 255]); - - const stdStringCoder = new StdStringCoder(); - const encodedStdString = stdStringCoder.encode('hello'); - // encodedStdString = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 5, 104, 101, 108, 108, 111]); - - const rawSliceCoder = new RawSliceCoder(); - const encodedRawSlice = rawSliceCoder.encode([1, 2, 3, 4]); - // encodedRawSlice = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 4, 1, 2, 3, 4]); - // #endregion working-with-bytes-6 - - expect(encodedVec).toEqual(new Uint8Array([0, 0, 0, 0, 0, 0, 0, 3, 255, 0, 255])); - expect(encodedStdString).toEqual( - new Uint8Array([0, 0, 0, 0, 0, 0, 0, 5, 104, 101, 108, 108, 111]) - ); - expect(encodedRawSlice).toEqual(new Uint8Array([0, 0, 0, 0, 0, 0, 0, 4, 1, 2, 3, 4])); - }); -}); diff --git a/apps/docs-snippets/src/guide/scripts/deploying-scripts.test.ts b/apps/docs-snippets/src/guide/scripts/deploying-scripts.test.ts deleted file mode 100644 index 5990ef108f7..00000000000 --- a/apps/docs-snippets/src/guide/scripts/deploying-scripts.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ContractFactory, Provider, Wallet, hexlify } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -import { - SumScript as TypegenScript, - SumScriptLoader as TypegenScriptLoader, -} from '../../../test/typegen'; - -/** - * @group browser - * @group node - */ -describe('Deploying Scripts', () => { - it('deploys a script via loader and calls', async () => { - using launched = await launchTestNode(); - - const { - provider: testProvider, - wallets: [testWallet], - } = launched; - - const providerUrl = testProvider.url; - const WALLET_PVT_KEY = hexlify(testWallet.privateKey); - - const factory = new ContractFactory(TypegenScript.bytecode, TypegenScript.abi, testWallet); - const { waitForResult: waitForDeploy } = await factory.deployAsBlobTxForScript(); - await waitForDeploy(); - - // #region deploying-scripts - // #import { Provider, Wallet }; - // #context import { WALLET_PVT_KEY } from 'path/to/my/env/file'; - // #context import { TypegenScriptLoader } from 'path/to/typegen/outputs'; - - const provider = await Provider.create(providerUrl); - const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); - - // First, we will need to instantiate the script via it's loader bytecode. This can be imported from the typegen outputs - // that were created on `fuels deploy` - const script = new TypegenScriptLoader(wallet); - - // Now we are free to interact with the script as we would normally, such as overriding the configurables - const configurable = { - AMOUNT: 20, - }; - script.setConfigurableConstants(configurable); - - const { waitForResult } = await script.functions.main(10).call(); - const { value, gasUsed } = await waitForResult(); - // value: 10 - // #endregion deploying-scripts - - const scriptWithoutLoader = new TypegenScript(wallet); - scriptWithoutLoader.setConfigurableConstants(configurable); - const { waitForResult: waitForAnotherResult } = await script.functions.main(10).call(); - const { value: anotherValue, gasUsed: anotherGasUsed } = await waitForAnotherResult(); - - expect(value).toBe(30); - expect(anotherValue).toBe(30); - expect(gasUsed.toNumber()).toBeLessThanOrEqual(anotherGasUsed.toNumber()); - }); -}); diff --git a/apps/docs-snippets/src/guide/scripts/script-custom-transaction.test.ts b/apps/docs-snippets/src/guide/scripts/script-custom-transaction.test.ts deleted file mode 100644 index f7a1eda4adf..00000000000 --- a/apps/docs-snippets/src/guide/scripts/script-custom-transaction.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { BN, ScriptTransactionRequest, coinQuantityfy } from 'fuels'; -import { ASSET_A, ASSET_B, launchTestNode } from 'fuels/test-utils'; - -import { EchoValuesFactory, ScriptTransferToContract } from '../../../test/typegen'; - -/** - * @group node - * @group browser - */ -describe('Script Custom Transaction', () => { - it('transfer multiple assets to a contract', async () => { - using launched = await launchTestNode({ - contractsConfigs: [{ factory: EchoValuesFactory }], - }); - const { - contracts: [contract], - wallets: [wallet], - } = launched; - - const contractInitialBalanceAssetA = await contract.getBalance(ASSET_A); - const contractInitialBalanceAssetB = await contract.getBalance(ASSET_B); - - expect(contractInitialBalanceAssetA).toStrictEqual(new BN(0)); - expect(contractInitialBalanceAssetB).toStrictEqual(new BN(0)); - - const defaultTxParams = { - gasLimit: 10000, - }; - - // #region custom-transactions-2 - // #import { BN, ScriptTransactionRequest }; - - // 1. Create a script transaction using the script binary - const request = new ScriptTransactionRequest({ - ...defaultTxParams, - gasLimit: 3_000_000, - script: ScriptTransferToContract.bytecode, - }); - - // 2. Instantiate the script main arguments - const scriptArguments = [ - contract.id.toB256(), - { bits: ASSET_A }, - new BN(1000), - { bits: ASSET_B }, - new BN(500), - ]; - - // 3. Populate the script data and add the contract input and output - request - .setData(ScriptTransferToContract.abi, scriptArguments) - .addContractInputAndOutput(contract.id); - - // 4. Get the transaction resources - const quantities = [coinQuantityfy([1000, ASSET_A]), coinQuantityfy([500, ASSET_B])]; - - // 5. Calculate the transaction fee - const txCost = await wallet.getTransactionCost(request, { quantities }); - - request.gasLimit = txCost.gasUsed; - request.maxFee = txCost.maxFee; - - await wallet.fund(request, txCost); - - // 6. Send the transaction - const tx = await wallet.sendTransaction(request); - await tx.waitForResult(); - - // #endregion custom-transactions-2 - const contractFinalBalanceAssetA = await contract.getBalance(ASSET_A); - const contractFinalBalanceAssetB = await contract.getBalance(ASSET_B); - - expect(contractFinalBalanceAssetA).toStrictEqual(new BN(1000)); - expect(contractFinalBalanceAssetB).toStrictEqual(new BN(500)); - }); -}); diff --git a/apps/docs-snippets/src/guide/scripts/script-with-configurable.test.ts b/apps/docs-snippets/src/guide/scripts/script-with-configurable.test.ts deleted file mode 100644 index ec3dbc689ca..00000000000 --- a/apps/docs-snippets/src/guide/scripts/script-with-configurable.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Script, BN } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -import { SumScript } from '../../../test/typegen'; - -/** - * @group node - * @group browser - */ -describe('Script With Configurable', () => { - it('should successfully sum set configurable constants with inputted value', async () => { - using launched = await launchTestNode(); - const { - wallets: [wallet], - } = launched; - - // #region script-with-configurable-contants-2 - const script = new Script(SumScript.bytecode, SumScript.abi, wallet); - - const configurableConstants = { - AMOUNT: 81, - }; - - script.setConfigurableConstants(configurableConstants); - - const inputtedValue = 10; - - const { waitForResult } = await script.functions.main(inputtedValue).call(); - const { value } = await waitForResult(); - - const expectedTotal = inputtedValue + configurableConstants.AMOUNT; - - expect(new BN(value as number).toNumber()).toEqual(expectedTotal); - // #endregion script-with-configurable-contants-2 - }); - - it('prepares a script and retrieves the id before submission', async () => { - using launched = await launchTestNode(); - const { - wallets: [wallet], - } = launched; - - const argument = 10; - const expected = 20; - - // #region preparing-scripts - const script = new Script(SumScript.bytecode, SumScript.abi, wallet); - - const tx = script.functions.main(argument); - - // Set the call parameters - tx.callParams({ gasLimit: 1700 }); - - // Get the entire transaction request prior to - const txRequest = await tx.getTransactionRequest(); - - // Get the transaction ID - const txId = await tx.getTransactionId(); - - // Retrieve the value of the call and the actual gas used - const { waitForResult } = await tx.call(); - const { value, gasUsed } = await waitForResult(); - // #endregion preparing-scripts - expect(txRequest).toBeDefined(); - expect(txId).toBeDefined(); - expect(new BN(value as number).toNumber()).toEqual(expected); - expect(new BN(gasUsed).toNumber()).toBeGreaterThan(0); - }); -}); diff --git a/apps/docs-snippets/src/guide/testing/launching-a-test-node.test.ts b/apps/docs-snippets/src/guide/testing/launching-a-test-node.test.ts deleted file mode 100644 index 3557da4f374..00000000000 --- a/apps/docs-snippets/src/guide/testing/launching-a-test-node.test.ts +++ /dev/null @@ -1,247 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { WalletUnlocked } from 'fuels'; -import { TestAssetId, TestMessage, launchTestNode } from 'fuels/test-utils'; -import { join } from 'path'; - -import { Counter, CounterFactory } from '../../../test/typegen/contracts'; - -/** - * @group node - */ -describe('launching a test node', () => { - test(`instantiating test nodes - automatic cleanup`, async () => { - // #region automatic-cleanup - // #import { launchTestNode }; - - using launched = await launchTestNode(); - - /* - The method `launched.cleanup()` will be automatically - called when the variable `launched` goes out of block scope. - */ - - // #endregion automatic-cleanup - }); - - test('instantiating test nodes - manual cleanup', async () => { - // #region manual-cleanup - // #import { launchTestNode }; - - const launched = await launchTestNode(); - - /* - Do your things, run your tests, and then call - `launched.cleanup()` to dispose of everything. - */ - - launched.cleanup(); - // #endregion manual-cleanup - }); - - test('options', async () => { - // #region options - // #import { launchTestNode }; - - using launched = await launchTestNode(/* options */); - // #endregion options - }); - - test('simple contract deployment', async () => { - // #region basic-example - // #import { launchTestNode }; - - // #context import { CounterFactory } from 'path/to/typegen/output'; - - using launched = await launchTestNode({ - contractsConfigs: [{ factory: CounterFactory }], - }); - - const { - contracts: [contract], - provider, - wallets, - } = launched; - - const { waitForResult } = await contract.functions.get_count().call(); - const response = await waitForResult(); - // #endregion basic-example - expect(response.value.toNumber()).toBe(0); - expect(provider).toBeDefined(); - expect(wallets).toBeDefined(); - }); - - test('multiple contracts and wallets', async () => { - // #region advanced-example - // #import { launchTestNode, TestAssetId, TestMessage }; - - // #context import { CounterFactory } from 'path/to/typegen/output'; - - const assets = TestAssetId.random(2); - const message = new TestMessage({ amount: 1000 }); - - using launched = await launchTestNode({ - walletsConfig: { - count: 4, - assets, - coinsPerAsset: 2, - amountPerCoin: 1_000_000, - messages: [message], - }, - contractsConfigs: [ - { - factory: CounterFactory, - walletIndex: 3, - options: { storageSlots: [] }, - }, - ], - }); - - const { - contracts: [contract], - wallets: [wallet1, wallet2, wallet3, wallet4], - } = launched; - // #endregion advanced-example - - expect(contract).toBeDefined(); - expect(wallet1).toBeDefined(); - expect(wallet2).toBeDefined(); - expect(wallet3).toBeDefined(); - expect(wallet4).toBeDefined(); - }); - - test('configuring custom fuel-core args', async () => { - // #region custom-fuel-core-args - // #import { launchTestNode }; - - process.env.DEFAULT_FUEL_CORE_ARGS = `--tx-max-depth 20`; - - // `nodeOptions.args` will override the above values if provided. - - using launched = await launchTestNode(); - // #endregion custom-fuel-core-args - - const { provider } = launched; - - expect(provider.getNode().maxDepth.toNumber()).toEqual(20); - process.env.DEFAULT_FUEL_CORE_ARGS = ''; - }); - - test('configuring a base chain config', async () => { - const snapshotDirPath = join(__dirname, '../../../../../', '.fuel-core', 'configs'); - - // #region custom-chain-config - // #import { launchTestNode }; - - process.env.DEFAULT_CHAIN_SNAPSHOT_DIR = snapshotDirPath; - - using launched = await launchTestNode(); - // #endregion custom-chain-config - - const { provider } = launched; - - const { name } = await provider.fetchChain(); - - expect(name).toEqual('local_testnet'); - }); - - test('customizing node options', async () => { - // #region custom-node-options - // #import { launchTestNode, TestAssetId }; - - const [baseAssetId] = TestAssetId.random(); - - using launched = await launchTestNode({ - nodeOptions: { - snapshotConfig: { - chainConfig: { - consensus_parameters: { - V1: { - base_asset_id: baseAssetId.value, - }, - }, - }, - }, - }, - }); - // #endregion custom-node-options - }); - - test('using TestAssetId', async () => { - // #region asset-ids - // #import { launchTestNode, TestAssetId }; - - const assets = TestAssetId.random(); - - using launched = await launchTestNode({ - walletsConfig: { - assets, - }, - }); - - const { - wallets: [wallet], - } = launched; - - const { coins } = await wallet.getCoins(assets[0].value); - // #endregion asset-ids - expect(coins[0].assetId).toEqual(assets[0].value); - }); - - test('generating test messages', async () => { - // #region test-messages - // #import { launchTestNode, TestMessage }; - - const testMessage = new TestMessage({ amount: 1000 }); - - using launched = await launchTestNode({ - walletsConfig: { - messages: [testMessage], - }, - }); - - const { - wallets: [wallet], - } = launched; - - const { - messages: [message], - } = await wallet.getMessages(); - // message.nonce === testMessage.nonce - // #endregion test-messages - - expect(message.nonce).toEqual(testMessage.nonce); - }); - - test('generating test messages directly on chain', async () => { - // #region test-messages-chain - // #import { launchTestNode, TestMessage, WalletUnlocked }; - - const recipient = WalletUnlocked.generate(); - const testMessage = new TestMessage({ - amount: 1000, - recipient: recipient.address, - }); - - using launched = await launchTestNode({ - nodeOptions: { - snapshotConfig: { - stateConfig: { - messages: [testMessage.toChainMessage()], - }, - }, - }, - }); - - const { provider } = launched; - - recipient.provider = provider; - - const { - messages: [message], - } = await recipient.getMessages(); - // message.nonce === testMessage.nonce - // #endregion test-messages-chain - - expect(message.nonce).toEqual(testMessage.nonce); - }); -}); diff --git a/apps/docs-snippets/src/guide/testing/tweaking-the-blockchain.test.ts b/apps/docs-snippets/src/guide/testing/tweaking-the-blockchain.test.ts deleted file mode 100644 index d8d348155b5..00000000000 --- a/apps/docs-snippets/src/guide/testing/tweaking-the-blockchain.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { DateTime } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -/** - * @group node - * @group browser - */ -describe('tweaking the blockchain', () => { - test('produceBlocks', async () => { - // #region produce-blocks - using launched = await launchTestNode(); - const { provider } = launched; - const block = await provider.getBlock('latest'); - if (!block) { - throw new Error('No latest block'); - } - const { time: timeLastBlockProduced } = block; - - const producedBlockHeight = await provider.produceBlocks(3); - - const producedBlock = await provider.getBlock(producedBlockHeight.toNumber()); - - const oldest = DateTime.fromTai64(timeLastBlockProduced); - const newest = DateTime.fromTai64(producedBlock!.time); - // newest >= oldest - // #endregion produce-blocks - expect(producedBlock).toBeDefined(); - expect(newest >= oldest).toBeTruthy(); - }); - - test('produceBlocks with custom timestamp docs snippet', async () => { - // #region produceBlocks-custom-timestamp - using launched = await launchTestNode(); - const { provider } = launched; - - const latestBlock = await provider.getBlock('latest'); - if (!latestBlock) { - throw new Error('No latest block'); - } - const latestBlockTimestamp = DateTime.fromTai64(latestBlock.time).toUnixMilliseconds(); - const newBlockHeight = await provider.produceBlocks(3, latestBlockTimestamp + 1000); - // #endregion produceBlocks-custom-timestamp - expect(newBlockHeight.toHex()).toBe(latestBlock.height.add(3).toHex()); - }); -}); diff --git a/apps/docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts b/apps/docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts deleted file mode 100644 index e19ffce9e8b..00000000000 --- a/apps/docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { WalletManager } from '@fuel-ts/account'; -import { Wallet } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -/** - * @group node - * @group browser - */ -describe('Getting started with wallet manager', () => { - it('instantiates the WalletManager', async () => { - using launched = await launchTestNode(); - const { provider } = launched; - - // #region getting-started-with-wallet-manager-1 - const walletManager = new WalletManager(); - // #endregion getting-started-with-wallet-manager-1 - - // #region getting-started-with-wallet-manager-2 - const password = 'my-password'; - - await walletManager.unlock(password); - // #endregion getting-started-with-wallet-manager-2 - - // #region getting-started-with-wallet-manager-3 - const myWallet = Wallet.generate({ - provider, - }); - - const privateKey = myWallet.privateKey; - - await walletManager.addVault({ - type: 'privateKey', - secret: privateKey, - title: 'My first private key vault', - }); - // #endregion getting-started-with-wallet-manager-3 - - // #region getting-started-with-wallet-manager-4 - await walletManager.addVault({ - type: 'privateKey', - secret: privateKey, - title: 'My second private key vault', - }); - // #endregion getting-started-with-wallet-manager-4 - - // #region getting-started-with-wallet-manager-5 - const vaults = walletManager.getVaults(); - - // #context console.log(vaults); - // #endregion getting-started-with-wallet-manager-5 - - // #region getting-started-with-wallet-manager-6 - // #context [ - // #context { - // #context title: 'My first private key vault', - // #context type: 'privateKey', - // #context vaultId: 0 - // #context }, - // #context { - // #context title: 'My second private key vault', - // #context type: 'privateKey', - // #context vaultId: 1 - // #context } - // #context ] - // #endregion getting-started-with-wallet-manager-6 - - expect(vaults).toStrictEqual([ - { - title: 'My first private key vault', - type: 'privateKey', - vaultId: 0, - }, - { - title: 'My second private key vault', - type: 'privateKey', - vaultId: 1, - }, - ]); - - // #region getting-started-with-wallet-manager-7 - const retrievedWallet = walletManager.getWallet(myWallet.address); - // #endregion getting-started-with-wallet-manager-7 - - expect(retrievedWallet.address.equals(myWallet.address)).toBeTruthy(); - expect(vaults.length).toBeGreaterThan(0); - }); -}); diff --git a/apps/docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts b/apps/docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts deleted file mode 100644 index 5e3395b3f00..00000000000 --- a/apps/docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { WalletManager } from '@fuel-ts/account'; - -/** - * @group node - */ -describe(__filename, () => { - it('should', async () => { - const password = '0b540281-f87b-49ca-be37-2264c7f260f7'; - // #region locking-and-unlocking-wallet-manager-1 - const walletManager = new WalletManager(); - - // #context const password = 'my-password'; - - await walletManager.unlock(password); - // #endregion locking-and-unlocking-wallet-manager-1 - - const privateKey = '0xc7079e195cca2495e47b056115f850a8be1f2c4ffe2a806922accb36d2ff0dde'; - - await walletManager.addVault({ - type: 'privateKey', - secret: privateKey, - }); - - // #region locking-and-unlocking-wallet-manager-2 - await walletManager.lock(); - // #endregion locking-and-unlocking-wallet-manager-2 - - // #region locking-and-unlocking-wallet-manager-3 - await walletManager.unlock(password); - // #endregion locking-and-unlocking-wallet-manager-3 - - // #region locking-and-unlocking-wallet-manager-4 - const isLocked = walletManager.isLocked; - - // #context console.log(isLocked); // Outputs true if locked, false if unlocked - // #endregion locking-and-unlocking-wallet-manager-4 - - expect(isLocked).toBeFalsy(); - - // #region locking-and-unlocking-wallet-manager-5 - const newPassword = 'my-new-password'; - - await walletManager.updatePassphrase(password, newPassword); - // #endregion locking-and-unlocking-wallet-manager-5 - - // #region locking-and-unlocking-wallet-manager-6 - await walletManager.unlock(newPassword); - - // perform your tasks... - - walletManager.lock(); // Always lock your WalletManager when you're done - // #endregion locking-and-unlocking-wallet-manager-6 - - expect(walletManager).toBeTruthy(); - expect(isLocked).toBeFalsy(); - }); -}); diff --git a/apps/docs-snippets2/.gitignore b/apps/docs-snippets2/.gitignore index e2327c8eaed..303199f6582 100644 --- a/apps/docs-snippets2/.gitignore +++ b/apps/docs-snippets2/.gitignore @@ -1,2 +1,3 @@ src/typegend src/**/*.test.ts +.fuels/ \ No newline at end of file diff --git a/apps/docs-snippets2/README.md b/apps/docs-snippets2/README.md new file mode 100644 index 00000000000..5ee3b6e13a0 --- /dev/null +++ b/apps/docs-snippets2/README.md @@ -0,0 +1,28 @@ +# `docs-snippets` + +**docs-snippets** is a private package for generating snippets for the Fuel documentation site. + + +# Table of contents + +- [`docs-snippets`](#docs-snippets) +- [Table of contents](#table-of-contents) + - [Building](#building) + - [Testing](#testing) +## Building + +This builds the snippets into testable scripts from the `src` folder and generates the Typegen `types` in the `typegend` folder. All test scripts end with a `.test.ts` suffix. + +```sh +pnpm build +``` + +## Testing + +This will build the snippets and run the generated tests. To test a specific environment (`node` or `browser`), the snippet should be named as `{name}.{environment}.test.ts`. e.g. `deploy-contract.node.test.ts` + +If no environment is specified, it will run in the browser and node environments by default. + +```sh +pnpm test +``` diff --git a/apps/docs-snippets2/package.json b/apps/docs-snippets2/package.json index e5c056a8fd0..f3541d4d330 100644 --- a/apps/docs-snippets2/package.json +++ b/apps/docs-snippets2/package.json @@ -7,7 +7,7 @@ "build": "run-s wrap:snippets build:forc", "build:forc": "pnpm fuels build", "wrap:snippets": "tsx scripts/wrap-snippets.ts", - "pretest": "pnpm build", + "pretest": "./scripts/pretest.sh", "test": "cd ../.. && pnpm run test:filter apps/docs-snippets2" }, "dependencies": { diff --git a/apps/docs-snippets2/scripts/pretest.sh b/apps/docs-snippets2/scripts/pretest.sh new file mode 100755 index 00000000000..3843d22753c --- /dev/null +++ b/apps/docs-snippets2/scripts/pretest.sh @@ -0,0 +1,14 @@ +# Check if node is already running at port 4000, if not start it +# TODO: This is a temporary solution to avoid conflicts with the test node in docs-snippets +if ! lsof -t -i:4000 > /dev/null; then + pnpm fuels node > /dev/null 2>&1 & +fi + +# Builds projects +pnpm fuels build + +# Deploys projects (needed for loader bytecode) +pnpm fuels deploy + +# Checks for type errors +pnpm tsc --noEmit \ No newline at end of file diff --git a/apps/docs-snippets2/scripts/test-template.ts b/apps/docs-snippets2/scripts/test-template.ts index b4d542f747f..636956f16a3 100644 --- a/apps/docs-snippets2/scripts/test-template.ts +++ b/apps/docs-snippets2/scripts/test-template.ts @@ -10,10 +10,7 @@ afterAll(() => { console = { ...consoleBkp }; }); -/** - * @group node - * @group browser - */ +// %TEST_ENVIRONMENT% test('%NAME%', async () => { // TEST NODE LAUNCHER ———>>> // %NODE_LAUNCHER% diff --git a/apps/docs-snippets2/scripts/wrap-snippets.ts b/apps/docs-snippets2/scripts/wrap-snippets.ts index b01c4f7b6d9..a3fe5a1cc5b 100644 --- a/apps/docs-snippets2/scripts/wrap-snippets.ts +++ b/apps/docs-snippets2/scripts/wrap-snippets.ts @@ -12,6 +12,24 @@ const wrapperFnContents = readFileSync(wrapperFnFilepath, 'utf-8'); export const wrapSnippet = (filepath: string) => { const snippetContents = readFileSync(filepath, 'utf8'); + /** + * Test environment + */ + let testEnvironments = ''; + + // Check if the file contains 'node' or 'browser' groups at the top of the file + const fileContents = readFileSync(filepath, 'utf8'); + const hasNodeComment = fileContents.includes('@group node'); + const hasBrowserComment = fileContents.includes('@group browser'); + + if (hasNodeComment && !hasBrowserComment) { + testEnvironments = '/**\n * @group node\n */'; + } else if (hasBrowserComment && !hasNodeComment) { + testEnvironments = '/**\n * @group browser\n */'; + } else { + testEnvironments = '/**\n * @group node\n * @group browser\n */'; + } + /* Filter all imports from file. */ @@ -74,6 +92,7 @@ export const wrapSnippet = (filepath: string) => { const wrappedSnippet = // eslintDisableRule + wrapperFnContents + .replace('// %TEST_ENVIRONMENT%', testEnvironments) .replace('// %IMPORTS%', imports) .replace('%NAME%', basename(filepath)) .replace('// %SNIPPET%', indented) diff --git a/apps/docs-snippets2/src/create-fuels/decrement-counter.ts b/apps/docs-snippets2/src/create-fuels/decrement-counter.ts new file mode 100644 index 00000000000..2d229410208 --- /dev/null +++ b/apps/docs-snippets2/src/create-fuels/decrement-counter.ts @@ -0,0 +1,53 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +// #region full +import { Wallet, Provider } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../env'; +import { CounterFactory } from '../typegend/contracts'; + +// Let's create our provider from the network URL. +const provider = await Provider.create(LOCAL_NETWORK_URL); +// Let's create our wallet from the private key. +const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); + +// Then we can deploy the contract. +const { waitForResult } = await CounterFactory.deploy(wallet); +const { contract } = await waitForResult(); + +// Lets setup some values to use in our example. +const initialCount = 0; +const incrementedValue = 5; +const decrementedValue = 2; + +// We can now call the contract functions and test the results. Lets assert the initial value of the counter. +const { waitForResult: getCountWaitForResult } = await contract.functions + .get_count() + .call(); +const { value: initialGetCountValue } = await getCountWaitForResult(); + +console.log('Initial value', initialGetCountValue); + +// Next we'll increment the counter, so that we can decrement it. +const { waitForResult: incWaitForResult } = await contract.functions + .increment_count(5) + .call(); +const { value: incValue } = await incWaitForResult(); + +console.log('Incremented value', incValue); + +// Next, we'll decrement the counter by 3 and assert the new value. +const { waitForResult: decWaitForResult } = await contract.functions + .decrement_count(3) + .call(); +const { value: decValue } = await decWaitForResult(); + +console.log('Decremented value', decValue); + +// Finally, we'll test the get count function again to ensure parity. +const { waitForResult: finalWaitForResult } = await contract.functions + .get_count() + .call(); +const { value: finalValue } = await finalWaitForResult(); + +console.log('Final value', finalValue); +// #endregion full diff --git a/apps/docs-snippets2/src/encoding/encode-and-decode.ts b/apps/docs-snippets2/src/encoding/encode-and-decode.ts new file mode 100644 index 00000000000..276e34706d8 --- /dev/null +++ b/apps/docs-snippets2/src/encoding/encode-and-decode.ts @@ -0,0 +1,103 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +// #region full +import type { JsonAbi, TransactionResultReturnDataReceipt } from 'fuels'; +import { + buildFunctionResult, + ReceiptType, + arrayify, + Script, + Interface, + Provider, + Wallet, +} from 'fuels'; + +// #region encode-and-decode-3 +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../env'; +import { ScriptSum } from '../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); + +// First we need to build out the transaction via the script that we want to encode. +// For that we'll need the ABI and the bytecode of the script +const abi: JsonAbi = ScriptSum.abi; +const bytecode = ScriptSum.bytecode; + +// Create the invocation scope for the script call, passing the initial +// value for the configurable constant +const script = new Script(bytecode, abi, wallet); +const initialValue = 10; +script.setConfigurableConstants({ AMOUNT: initialValue }); +const invocationScope = script.functions.main(0); + +// Create the transaction request, this can be picked off the invocation +// scope so the script bytecode is preset on the transaction +const request = await invocationScope.getTransactionRequest(); +// #endregion encode-and-decode-3 + +// #region encode-and-decode-4 + +// Now we can encode the argument we want to pass to the function. The argument is required +// as a function parameter for all abi functions and we can extract it from the ABI itself +const argument = abi.functions + .find((f) => f.name === 'main') + ?.inputs.find((i) => i.name === 'inputted_amount')?.concreteTypeId as string; + +// The `Interface` class (imported from `fuels`) is the entry point for encoding and decoding all things abi-related. +// We will use its `encodeType` method and create the encoding required for +// a u32 which takes 4 bytes up of property space. + +const abiInterface = new Interface(abi); +const argumentToAdd = 10; +const encodedArguments = abiInterface.encodeType(argument, [argumentToAdd]); +// Therefore the value of 10 will be encoded to: +// Uint8Array([0, 0, 0, 10] + +// The encoded value can now be set on the transaction via the script data property +request.scriptData = encodedArguments; + +// Now we can build out the rest of the transaction and then fund it +const txCost = await wallet.getTransactionCost(request); +request.maxFee = txCost.maxFee; +request.gasLimit = txCost.gasUsed; +await wallet.fund(request, txCost); + +// Finally, submit the built transaction +const response = await wallet.sendTransaction(request); +await response.waitForResult(); +// #endregion encode-and-decode-4 + +// #region encode-and-decode-5 + +// Get result of the transaction, including the contract call result. For this we'll need +// the previously created invocation scope, the transaction response and the script +const invocationResult = await buildFunctionResult({ + funcScope: invocationScope, + isMultiCall: false, + program: script, + transactionResponse: response, +}); + +// The decoded value can be destructured from the `FunctionInvocationResult` +const { value } = invocationResult; + +// Or we can decode the returned bytes ourselves, by retrieving the return data +// receipt that contains the returned bytes. We can get this by filtering on +// the returned receipt types +const returnDataReceipt = invocationResult.transactionResult.receipts.find( + (r) => r.type === ReceiptType.ReturnData +) as TransactionResultReturnDataReceipt; + +// The data is in hex format so it makes sense to use arrayify so that the data +// is more human readable +const returnData = arrayify(returnDataReceipt.data); +// returnData = new Uint8Array([0, 0, 0, 20] + +// And now we can decode the returned bytes in a similar fashion to how they were +// encoded, via the `Interface` +const [decodedReturnData] = abiInterface.decodeType(argument, returnData); +// 20 + +const totalValue = argumentToAdd + initialValue; +// #endregion encode-and-decode-5 +// #endregion full diff --git a/apps/docs-snippets2/src/encoding/working-with-bytes.ts b/apps/docs-snippets2/src/encoding/working-with-bytes.ts new file mode 100644 index 00000000000..1dc89c369dd --- /dev/null +++ b/apps/docs-snippets2/src/encoding/working-with-bytes.ts @@ -0,0 +1,88 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +// #region full +import { randomBytes } from 'crypto'; +import { + ArrayCoder, + B256Coder, + B512Coder, + BigNumberCoder, + BooleanCoder, + EnumCoder, + NumberCoder, + RawSliceCoder, + StdStringCoder, + StringCoder, + StructCoder, + TupleCoder, + VecCoder, + hexlify, +} from 'fuels'; + +// #region working-with-bytes-1 +const u8Coder = new NumberCoder('u8'); +const encodedU8 = u8Coder.encode(255); + +const u16Coder = new NumberCoder('u16'); +const encodedU16 = u16Coder.encode(255); + +const u32Coder = new NumberCoder('u32'); +const encodedU32 = u32Coder.encode(255); + +const u64Coder = new BigNumberCoder('u64'); +const encodedU64 = u64Coder.encode(255); + +const u256Coder = new BigNumberCoder('u256'); +const encodedU256 = u256Coder.encode(255); +// #endregion working-with-bytes-1 + +// #region working-with-bytes-2 +const booleanCoder = new BooleanCoder(); +const encodedTrue = booleanCoder.encode(true); + +const encodedFalse = booleanCoder.encode(false); + +// #endregion working-with-bytes-2 + +// #region working-with-bytes-3 +const stringCoder = new StringCoder(5); +const encoded = stringCoder.encode('hello'); +// #endregion working-with-bytes-3 + +// #region working-with-bytes-4 +const b256Coder = new B256Coder(); +const encodedB256 = b256Coder.encode(hexlify(randomBytes(32))); +const b512Coder = new B512Coder(); +const encodedB512 = b512Coder.encode(hexlify(randomBytes(64))); +// #endregion working-with-bytes-4 + +// #region working-with-bytes-5 +const tupleCoder = new TupleCoder([ + new NumberCoder('u8'), + new NumberCoder('u16'), +]); +const encodedTuple = tupleCoder.encode([255, 255]); + +const structCoder = new StructCoder('struct', { + a: new NumberCoder('u8'), + b: new NumberCoder('u16'), +}); +const encodedStruct = structCoder.encode({ a: 255, b: 255 }); + +const arrayCoder = new ArrayCoder(new NumberCoder('u8'), 4); +const encodedArray = arrayCoder.encode([255, 0, 255, 0]); + +const enumCoder = new EnumCoder('enum', { a: new NumberCoder('u32') }); +const encodedEnum = enumCoder.encode({ a: 255 }); +// #endregion working-with-bytes-5 + +// #region working-with-bytes-6 +const vecCoder = new VecCoder(new NumberCoder('u8')); +const encodedVec = vecCoder.encode([255, 0, 255]); + +const stdStringCoder = new StdStringCoder(); +const encodedStdString = stdStringCoder.encode('hello'); + +const rawSliceCoder = new RawSliceCoder(); +const encodedRawSlice = rawSliceCoder.encode([1, 2, 3, 4]); +// #endregion working-with-bytes-6 +// #endregion full diff --git a/apps/docs-snippets2/src/scripts/deploying-scripts.ts b/apps/docs-snippets2/src/scripts/deploying-scripts.ts new file mode 100644 index 00000000000..4e123965baa --- /dev/null +++ b/apps/docs-snippets2/src/scripts/deploying-scripts.ts @@ -0,0 +1,57 @@ +import { ContractFactory, Provider, Wallet, hexlify } from 'fuels'; +import { launchTestNode } from 'fuels/test-utils'; + +import { + ScriptSum as TypegenScript, + ScriptSumLoader as TypegenScriptLoader, +} from '../typegend/scripts'; + +using launched = await launchTestNode(); + +const { + provider: testProvider, + wallets: [testWallet], +} = launched; + +const providerUrl = testProvider.url; +const WALLET_PVT_KEY = hexlify(testWallet.privateKey); + +const factory = new ContractFactory( + TypegenScript.bytecode, + TypegenScript.abi, + testWallet +); +const { waitForResult: waitForDeploy } = + await factory.deployAsBlobTxForScript(); +await waitForDeploy(); + +// #region deploying-scripts +const provider = await Provider.create(providerUrl); +const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); + +// First, we will need to instantiate the script via it's loader bytecode. This can be imported from the typegen outputs +// that were created on `fuels deploy` +const script = new TypegenScriptLoader(wallet); + +// Now we are free to interact with the script as we would normally, such as overriding the configurables +const configurable = { + AMOUNT: 20, +}; +script.setConfigurableConstants(configurable); + +const { waitForResult } = await script.functions.main(10).call(); +const { value, gasUsed } = await waitForResult(); +console.log('value', value); +// #endregion deploying-scripts + +const scriptWithoutLoader = new TypegenScript(wallet); +scriptWithoutLoader.setConfigurableConstants(configurable); +const { waitForResult: waitForAnotherResult } = await script.functions + .main(10) + .call(); +const { value: anotherValue, gasUsed: anotherGasUsed } = + await waitForAnotherResult(); + +console.log('anotherValue', anotherValue); +console.log('gasUsed', gasUsed.toNumber()); +console.log('anotherGasUsed', anotherGasUsed.toNumber()); diff --git a/apps/docs-snippets2/src/scripts/script-custom-transaction.ts b/apps/docs-snippets2/src/scripts/script-custom-transaction.ts new file mode 100644 index 00000000000..d229b093fee --- /dev/null +++ b/apps/docs-snippets2/src/scripts/script-custom-transaction.ts @@ -0,0 +1,66 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +// #region full +import { BN, ScriptTransactionRequest, coinQuantityfy } from 'fuels'; +import { ASSET_A, ASSET_B, launchTestNode } from 'fuels/test-utils'; + +import { EchoValuesFactory } from '../typegend/contracts/EchoValuesFactory'; +import { ScriptTransferToContract } from '../typegend/scripts/ScriptTransferToContract'; + +using launched = await launchTestNode({ + contractsConfigs: [{ factory: EchoValuesFactory }], +}); +const { + contracts: [contract], + wallets: [wallet], +} = launched; + +const defaultTxParams = { + gasLimit: 10000, +}; + +// #region custom-transactions-2 + +// 1. Create a script transaction using the script binary +const request = new ScriptTransactionRequest({ + ...defaultTxParams, + gasLimit: 3_000_000, + script: ScriptTransferToContract.bytecode, +}); + +// 2. Instantiate the script main arguments +const scriptArguments = [ + contract.id.toB256(), + { bits: ASSET_A }, + new BN(1000), + { bits: ASSET_B }, + new BN(500), +]; + +// 3. Populate the script data and add the contract input and output +request + .setData(ScriptTransferToContract.abi, scriptArguments) + .addContractInputAndOutput(contract.id); + +// 4. Get the transaction resources +const quantities = [ + coinQuantityfy([1000, ASSET_A]), + coinQuantityfy([500, ASSET_B]), +]; + +// 5. Calculate the transaction fee +const txCost = await wallet.getTransactionCost(request, { quantities }); + +request.gasLimit = txCost.gasUsed; +request.maxFee = txCost.maxFee; + +await wallet.fund(request, txCost); + +// 6. Send the transaction +const tx = await wallet.sendTransaction(request); +await tx.waitForResult(); + +const contractFinalBalanceAssetA = await contract.getBalance(ASSET_A); +const contractFinalBalanceAssetB = await contract.getBalance(ASSET_B); +// #endregion custom-transactions-2 + +// #endregion full diff --git a/apps/docs-snippets2/src/scripts/script-with-configurable.ts b/apps/docs-snippets2/src/scripts/script-with-configurable.ts new file mode 100644 index 00000000000..aa7c104a296 --- /dev/null +++ b/apps/docs-snippets2/src/scripts/script-with-configurable.ts @@ -0,0 +1,51 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +// #region full +import { Script, BN, Wallet, Provider } from 'fuels'; + +import { WALLET_PVT_KEY, LOCAL_NETWORK_URL } from '../env'; +import { ScriptSum } from '../typegend/scripts/ScriptSum'; + +// #region script-with-configurable-contants-2 +const provider = await Provider.create(LOCAL_NETWORK_URL); +const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); +const script = new Script(ScriptSum.bytecode, ScriptSum.abi, wallet); + +const configurableConstants = { + AMOUNT: 81, +}; + +script.setConfigurableConstants(configurableConstants); + +const inputtedValue = 10; + +const { waitForResult } = await script.functions.main(inputtedValue).call(); +const { value } = await waitForResult(); + +const expectedTotal = inputtedValue + configurableConstants.AMOUNT; + +// #endregion script-with-configurable-contants-2 + +const argument = 10; +const expected = 20; + +// #region preparing-scripts +const myMainScript = new Script(ScriptSum.bytecode, ScriptSum.abi, wallet); + +const tx = myMainScript.functions.main(argument); + +// Set the call parameters +tx.callParams({ gasLimit: 7500 }); + +// Get the entire transaction request prior to +const txRequest = await tx.getTransactionRequest(); + +// Get the transaction ID +const txId = await tx.getTransactionId(); + +// Retrieve the value of the call and the actual gas used +const { waitForResult: waitForActualGasUsed } = await tx.call(); +const { value: valueOfActualGasUsed, gasUsed: gasUsedOfActualGasUsed } = + await waitForActualGasUsed(); +// #endregion preparing-scripts + +// #endregion full diff --git a/apps/docs-snippets2/src/testing/launching-a-test-node.ts b/apps/docs-snippets2/src/testing/launching-a-test-node.ts new file mode 100644 index 00000000000..ac89dcb517b --- /dev/null +++ b/apps/docs-snippets2/src/testing/launching-a-test-node.ts @@ -0,0 +1,202 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable import/first */ +import { WalletUnlocked, Provider } from 'fuels'; +import { launchTestNode, TestAssetId, TestMessage } from 'fuels/test-utils'; +import { join } from 'path'; + +/** + * @group node + */ + +// #region automatic-cleanup +using launched = await launchTestNode(); + +/* + * The method `launched.cleanup()` will be automatically + * called when the variable `launched` goes out of block scope. + */ + +// #endregion automatic-cleanup + +// #region manual-cleanup +const launchedTestNode = await launchTestNode(); + +/* + Do your things, run your tests, and then call + `launchedTestNode.cleanup()` to dispose of everything. +*/ + +launchedTestNode.cleanup(); +// #endregion manual-cleanup + +// #region options +const customLaunchTestNode = await launchTestNode(/* options */); +// #endregion options + +customLaunchTestNode.cleanup(); +// #region basic-example +import { CounterFactory } from '../typegend/contracts/CounterFactory'; + +using launchedContractNode = await launchTestNode({ + contractsConfigs: [{ factory: CounterFactory }], +}); + +const { + contracts: [contract], + provider, + wallets, +} = launchedContractNode; + +const { waitForResult } = await contract.functions.get_count().call(); +const response = await waitForResult(); + +// #endregion basic-example + +// #region advanced-example +const assets = TestAssetId.random(2); +const message = new TestMessage({ amount: 1000 }); + +using counterContractNode = await launchTestNode({ + walletsConfig: { + count: 4, + assets, + coinsPerAsset: 2, + amountPerCoin: 1_000_000, + messages: [message], + }, + contractsConfigs: [ + { + factory: CounterFactory, + walletIndex: 3, + options: { storageSlots: [] }, + }, + ], +}); + +const { + contracts: [counterContract], + wallets: [wallet1, wallet2, wallet3, wallet4], +} = counterContractNode; + +// #endregion advanced-example + +// #region custom-fuel-core-args +process.env.DEFAULT_FUEL_CORE_ARGS = `--tx-max-depth 20`; + +// `nodeOptions.args` will override the above values if provided. + +const nodeWithCustomArgs = await launchTestNode(); +const { provider: providerWithCustomArgs } = nodeWithCustomArgs; + +process.env.DEFAULT_FUEL_CORE_ARGS = ''; +// #endregion custom-fuel-core-args + +nodeWithCustomArgs.cleanup(); + +const mySnapshotDirPath = join( + __dirname, + '../../../../', + '.fuel-core', + 'configs' +); + +// #region custom-chain-config +process.env.DEFAULT_CHAIN_SNAPSHOT_DIR = mySnapshotDirPath; + +const launchedWithCustomChainConfig = await launchTestNode(); + +const { provider: providerWithCustomChainConfig } = + launchedWithCustomChainConfig; + +const { name } = await providerWithCustomChainConfig.fetchChain(); + +// #endregion custom-chain-config + +launchedWithCustomChainConfig.cleanup(); +// #region custom-node-options +const [baseAssetId] = TestAssetId.random(); + +const nodeWithCustomBaseAssetId = await launchTestNode({ + nodeOptions: { + snapshotConfig: { + chainConfig: { + consensus_parameters: { + V1: { + base_asset_id: baseAssetId.value, + }, + }, + }, + }, + }, +}); +// #endregion custom-node-options + +nodeWithCustomBaseAssetId.cleanup(); + +// #region asset-ids +const randomAssetIds = TestAssetId.random(); + +const nodeWithCustomAssetIds = await launchTestNode({ + walletsConfig: { + assets: randomAssetIds, + }, +}); + +const { + wallets: [walletWithCustomAssetIds], +} = nodeWithCustomAssetIds; + +const { coins } = await walletWithCustomAssetIds.getCoins( + randomAssetIds[0].value +); +// #endregion asset-ids + +nodeWithCustomAssetIds.cleanup(); + +// #region test-messages +const testMessage = new TestMessage({ amount: 1000 }); + +const nodeWithTestMessages = await launchTestNode({ + walletsConfig: { + messages: [testMessage], + }, +}); + +const { + wallets: [walletWithTestMessages], +} = nodeWithTestMessages; + +const { + messages: [messageWithTestMessages], +} = await walletWithTestMessages.getMessages(); + +// #endregion test-messages + +nodeWithTestMessages.cleanup(); + +// #region test-messages-chain +const recipient = WalletUnlocked.generate(); +const testMessageOnChain = new TestMessage({ + amount: 1000, + recipient: recipient.address, +}); + +using launchedWithTestMessagesOnChain = await launchTestNode({ + nodeOptions: { + snapshotConfig: { + stateConfig: { + messages: [testMessageOnChain.toChainMessage()], + }, + }, + }, +}); + +const { provider: providerWithTestMessagesOnChain } = + launchedWithTestMessagesOnChain; + +recipient.provider = providerWithTestMessagesOnChain; + +const { + messages: [messageOnChain], +} = await recipient.getMessages(); +// #endregion test-messages-chain diff --git a/apps/docs-snippets2/src/testing/tweaking-the-blockchain.ts b/apps/docs-snippets2/src/testing/tweaking-the-blockchain.ts new file mode 100644 index 00000000000..59450cd4531 --- /dev/null +++ b/apps/docs-snippets2/src/testing/tweaking-the-blockchain.ts @@ -0,0 +1,42 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +// #region full +// #region produce-blocks +import { DateTime } from 'fuels'; +import { launchTestNode } from 'fuels/test-utils'; + +using launched = await launchTestNode(); +const { provider } = launched; +const block = await provider.getBlock('latest'); +if (!block) { + throw new Error('No latest block'); +} +const { time: timeLastBlockProduced } = block; + +const producedBlockHeight = await provider.produceBlocks(3); + +const producedBlock = await provider.getBlock(producedBlockHeight.toNumber()); + +const oldest = DateTime.fromTai64(timeLastBlockProduced); +const newest = DateTime.fromTai64(producedBlock!.time); +// newest >= oldest +// #endregion produce-blocks + +// #region produceBlocks-custom-timestamp +using launchedWithCustomTimestamp = await launchTestNode(); +const { provider: providerWithCustomTimestamp } = launchedWithCustomTimestamp; + +const latestBlock = await providerWithCustomTimestamp.getBlock('latest'); +if (!latestBlock) { + throw new Error('No latest block'); +} +const latestBlockTimestamp = DateTime.fromTai64( + latestBlock.time +).toUnixMilliseconds(); +const newBlockHeight = await providerWithCustomTimestamp.produceBlocks( + 3, + latestBlockTimestamp + 1000 +); + +// #endregion produceBlocks-custom-timestamp +// #endregion full diff --git a/apps/docs-snippets2/src/types/enums/using-an-invalid-enum-value.ts b/apps/docs-snippets2/src/types/enums/using-an-invalid-enum-value.ts index b183811e44a..ae1b8adb46a 100644 --- a/apps/docs-snippets2/src/types/enums/using-an-invalid-enum-value.ts +++ b/apps/docs-snippets2/src/types/enums/using-an-invalid-enum-value.ts @@ -1,10 +1,10 @@ // #region snippet-1 // Valid values: 'Void', 'Pending', 'Completed' -const emumParam = 'NotStateEnumValue'; +const invalidEnumValue = 'NotStateEnumValue'; try { // @ts-expect-error NotStateEnumValue is not a valid value - await contract.functions.echo_state_error_enum(emumParam).get(); + await contract.functions.echo_state_error_enum(invalidEnumValue).get(); } catch (error) { console.log('error', error); } diff --git a/apps/docs-snippets2/src/utilities/unit-conversion.ts b/apps/docs-snippets2/src/utilities/unit-conversion.ts new file mode 100644 index 00000000000..6622df70563 --- /dev/null +++ b/apps/docs-snippets2/src/utilities/unit-conversion.ts @@ -0,0 +1,103 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +// #region full +import { BN, DECIMAL_GWEI, DECIMAL_KWEI, bn, Provider, Wallet } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../env'; +import { EchoValuesFactory } from '../typegend/contracts/EchoValuesFactory'; + +// #region instantiation-1 +const myBigNumberOne = '100000000'; + +const resultOne = new BN('100000000').toString(); + +// #endregion instantiation-1 + +const myBigNumberTwo = '100000000'; + +// #region instantiation-2 + +const resultTwo = bn('100000000').toString(); +// #endregion instantiation-2 + +// #region contract-calls-1 + +// Let's deploy a contract that has a function that takes a u64 as input +const provider = await Provider.create(LOCAL_NETWORK_URL); + +const wallet = await Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); + +const deployedContract = await new EchoValuesFactory(wallet).deploy(); +const { contract } = await deployedContract.waitForResult(); + +const MAX_U64 = bn('18446744073709551615'); + +const { waitForResult } = await contract.functions.echo_u64(MAX_U64).call(); +const { value } = await waitForResult(); + +// #endregion contract-calls-1 + +const myBigNumberThree = '1'; + +// #region parse-units-1 +const resultThree = bn.parseUnits('0.000000001').toString(); +// #endregion parse-units-1 + +// #endregion parse-units-1 + +// #region parse-units-2 +const myBigNumberFour = '100100000000000'; +const resultFour = bn.parseUnits('100100').toString(); +// #endregion parse-units-2 + +// #endregion parse-units-3 + +// #region parse-units-3 +const myBigNumberFive = '100100000200001'; + +const resultFive = bn.parseUnits('100,100.000200001').toString(); +// #endregion parse-units-3 + +// #endregion parse-units-4 + +// #region parse-units-4 +const myBigNumberSix = '1000000000'; + +const resultSix = bn.parseUnits('1', DECIMAL_GWEI).toString(); +// #endregion parse-units-4 + +// #region format-1 +const myBigNumberSeven = '1.000'; +const oneGwei = bn('1000000000'); + +const resultSeven = oneGwei.format(); +// #endregion format-1 + +// #region format-2 +const myBigNumberEight = '2.000'; + +const twoGwei = bn('2000000000'); + +const resultEight = twoGwei.format({ units: DECIMAL_GWEI }); +// #endregion format-2 + +// #region format-3 +const oneDecimalGwei = '1.0'; + +const formattedGwei = oneGwei.format({ precision: 1 }); +// #endregion format-3 + +// #region format-units-1 +const myFormattedGwei = '1.000000000'; + +const formattedUnitsGwei = oneGwei.formatUnits(); +// #endregion format-units-1 + +// #region format-units-2 +const myFormattedKwei = '1.000000000000000'; + +const oneKwei = bn('1000000000000000'); + +const formattedUnitsKwei = oneKwei.formatUnits(DECIMAL_KWEI); +// #endregion format-units-2 + +// #endregion full diff --git a/apps/docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts b/apps/docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts new file mode 100644 index 00000000000..f567bca06ac --- /dev/null +++ b/apps/docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts @@ -0,0 +1,66 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +// #region full +import { WalletManager, Wallet, Provider } from 'fuels'; + +import { LOCAL_NETWORK_URL } from '../env'; + +// #region getting-started-with-wallet-manager-1 + +// Initialize a WalletManager +const walletManager = new WalletManager(); +// #endregion getting-started-with-wallet-manager-1 + +// #region getting-started-with-wallet-manager-2 +const password = 'my-password'; + +await walletManager.unlock(password); +// #endregion getting-started-with-wallet-manager-2 + +// #region getting-started-with-wallet-manager-3 +// Initialize a Provider +const provider = await Provider.create(LOCAL_NETWORK_URL); +const myWallet = Wallet.generate({ + provider, +}); + +const privateKey = myWallet.privateKey; + +await walletManager.addVault({ + type: 'privateKey', + secret: privateKey, + title: 'My first private key vault', +}); +// #endregion getting-started-with-wallet-manager-3 + +// #region getting-started-with-wallet-manager-4 +await walletManager.addVault({ + type: 'privateKey', + secret: privateKey, + title: 'My second private key vault', +}); +// #endregion getting-started-with-wallet-manager-4 + +// #region getting-started-with-wallet-manager-5 +const vaults = walletManager.getVaults(); +// #endregion getting-started-with-wallet-manager-5 + +// #region getting-started-with-wallet-manager-6 +// [ +// { +// title: 'My first private key vault', +// type: 'privateKey', +// vaultId: 0 +// }, +// { +// title: 'My second private key vault', +// type: 'privateKey', +// vaultId: 1 +// } +// ] +// #endregion getting-started-with-wallet-manager-6 + +// #region getting-started-with-wallet-manager-7 +const retrievedWallet = walletManager.getWallet(myWallet.address); +// #endregion getting-started-with-wallet-manager-7 + +// #endregion full diff --git a/apps/docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts b/apps/docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts new file mode 100644 index 00000000000..b1264c3f599 --- /dev/null +++ b/apps/docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts @@ -0,0 +1,47 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +// #region full +import { WalletManager } from 'fuels'; + +// #region locking-and-unlocking-wallet-manager-1 +const password = '0b540281-f87b-49ca-be37-2264c7f260f7'; + +const walletManager = new WalletManager(); + +await walletManager.unlock(password); +// #endregion locking-and-unlocking-wallet-manager-1 + +const privateKey = + '0xc7079e195cca2495e47b056115f850a8be1f2c4ffe2a806922accb36d2ff0dde'; + +await walletManager.addVault({ + type: 'privateKey', + secret: privateKey, +}); + +// #region locking-and-unlocking-wallet-manager-2 +await walletManager.lock(); +// #endregion locking-and-unlocking-wallet-manager-2 + +// #region locking-and-unlocking-wallet-manager-3 +await walletManager.unlock(password); +// #endregion locking-and-unlocking-wallet-manager-3 + +// #region locking-and-unlocking-wallet-manager-4 +const isLocked = walletManager.isLocked; + +// #endregion locking-and-unlocking-wallet-manager-4 + +// #region locking-and-unlocking-wallet-manager-5 +const newPassword = 'my-new-password'; + +await walletManager.updatePassphrase(password, newPassword); +// #endregion locking-and-unlocking-wallet-manager-5 + +// #region locking-and-unlocking-wallet-manager-6 +await walletManager.unlock(newPassword); + +// perform your tasks... + +walletManager.lock(); // Always lock your WalletManager when you're done +// #endregion locking-and-unlocking-wallet-manager-6 +// #endregion full diff --git a/apps/docs-snippets2/sway/Forc.toml b/apps/docs-snippets2/sway/Forc.toml index 32cda926a6d..14d655d41ca 100644 --- a/apps/docs-snippets2/sway/Forc.toml +++ b/apps/docs-snippets2/sway/Forc.toml @@ -2,6 +2,8 @@ members = [ "bytecode-input", "counter", + "echo-values", + "script-transfer-to-contract", "echo-asset-id", "echo-bytes", "echo-employee-data-vector", @@ -9,7 +11,6 @@ members = [ "echo-evm-address", "echo-raw-slice", "echo-std-string", - "echo-values", "employee-data", "input-output-types", "script-sum", diff --git a/apps/docs-snippets2/sway/counter/src/main.sw b/apps/docs-snippets2/sway/counter/src/main.sw index e3e3beddcd5..615a53c7dce 100644 --- a/apps/docs-snippets2/sway/counter/src/main.sw +++ b/apps/docs-snippets2/sway/counter/src/main.sw @@ -6,6 +6,9 @@ abi Counter { #[storage(write, read)] fn increment_count(amount: u64) -> u64; + + #[storage(write, read)] + fn decrement_count(amount: u64) -> u64; } storage { @@ -24,4 +27,11 @@ impl Counter for Contract { storage.counter.write(current + amount); storage.counter.read() } + + #[storage(write, read)] + fn decrement_count(amount: u64) -> u64 { + let current = storage.counter.read(); + storage.counter.write(current - amount); + storage.counter.read() + } } diff --git a/apps/docs-snippets2/sway/script-transfer-to-contract/Forc.toml b/apps/docs-snippets2/sway/script-transfer-to-contract/Forc.toml new file mode 100644 index 00000000000..27eb944eb8b --- /dev/null +++ b/apps/docs-snippets2/sway/script-transfer-to-contract/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "script-transfer-to-contract" + +[dependencies] diff --git a/apps/docs-snippets2/sway/script-transfer-to-contract/src/main.sw b/apps/docs-snippets2/sway/script-transfer-to-contract/src/main.sw new file mode 100644 index 00000000000..0e8cd4d742e --- /dev/null +++ b/apps/docs-snippets2/sway/script-transfer-to-contract/src/main.sw @@ -0,0 +1,19 @@ +// #region custom-transactions-1 +script; + +use std::asset::transfer; + +fn main( + contract_address: b256, + asset_a: AssetId, + amount_asset_a: u64, + asset_b: AssetId, + amount_asset_b: u64, +) -> bool { + let wrapped_contract = ContractId::from(contract_address); + let contract_id = Identity::ContractId(wrapped_contract); + transfer(contract_id, asset_a, amount_asset_a); + transfer(contract_id, asset_b, amount_asset_b); + true +} +// #endregion custom-transactions-1 diff --git a/apps/docs/src/guide/cookbook/custom-transactions.md b/apps/docs/src/guide/cookbook/custom-transactions.md index 0f25df68887..aafbfade7db 100644 --- a/apps/docs/src/guide/cookbook/custom-transactions.md +++ b/apps/docs/src/guide/cookbook/custom-transactions.md @@ -4,8 +4,14 @@ There may be scenarios where you need to build out transactions that involve mul Consider the following script that transfers multiple assets to a contract: -<<< @/../../docs-snippets/test/fixtures/forc-projects/script-transfer-to-contract/src/main.sw#custom-transactions-1{ts:line-numbers} +<<< @/../../docs-snippets2/sway/script-transfer-to-contract/src/main.sw#custom-transactions-1{rust:line-numbers} This script can be executed by creating a [`ScriptTransactionRequest`](../../api/Account/ScriptTransactionRequest.md), appending the resource and contract inputs/outputs and then sending the transaction, as follows: -<<< @/../../docs-snippets/src/guide/scripts/script-custom-transaction.test.ts#custom-transactions-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/scripts/script-custom-transaction.ts#custom-transactions-2{ts:line-numbers} + +## Full Example + +For a full example, see below: + +<<< @/../../docs-snippets2/src/scripts/script-custom-transaction.ts#full{ts:line-numbers} diff --git a/apps/docs/src/guide/creating-a-fuel-dapp/index.md b/apps/docs/src/guide/creating-a-fuel-dapp/index.md index bf09195b9d0..d56fe445a62 100644 --- a/apps/docs/src/guide/creating-a-fuel-dapp/index.md +++ b/apps/docs/src/guide/creating-a-fuel-dapp/index.md @@ -202,7 +202,7 @@ Testing the integration with your smart contract isn't essential, but it's good We've provided some examples for each program type in the `./test` directory of your project. But let's also add a test for our new `decrement_counter` function in the `./test/contract.test.ts` file: -<<< @/../../docs-snippets/src/guide/create-fuels/decrement_counter.test.ts#decrement-counter{ts:line-numbers} +<<< @/../../docs-snippets2/src/create-fuels/decrement-counter.ts#full{ts:line-numbers} The template also comes with a UI testing setup using [Playwright](https://playwright.dev/). We can add a test for our new `decrement_counter` function in the `./test/ui/ui.test.ts` file: diff --git a/apps/docs/src/guide/encoding/encode-and-decode.md b/apps/docs/src/guide/encoding/encode-and-decode.md index 8a6821829cf..2d55cd7d771 100644 --- a/apps/docs/src/guide/encoding/encode-and-decode.md +++ b/apps/docs/src/guide/encoding/encode-and-decode.md @@ -11,7 +11,7 @@ The `Interface` class requires you to pass the [ABI](https://docs.fuel.network/d Imagine we are working with the following script that returns the sum of two `u32` integers: -<<< @/../../docs-snippets/test/fixtures/forc-projects/sum-script/src/main.sw#encode-and-decode-1{rust:line-numbers} +<<< @/../../docs-snippets2/sway/script-sum/src/main.sw#encode-and-decode-1{rust:line-numbers} When you build this script, using: @@ -27,16 +27,22 @@ Now, let's prepare some data to pass to the `main` function to retrieve the comb First, let's prepare the transaction: -<<< @/../../docs-snippets/src/guide/encoding/encode-and-decode.test.ts#encode-and-decode-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/encode-and-decode.ts#encode-and-decode-3{ts:line-numbers} Now, we can encode the script data to use in the transaction: -<<< @/../../docs-snippets/src/guide/encoding/encode-and-decode.test.ts#encode-and-decode-4{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/encode-and-decode.ts#encode-and-decode-4{ts:line-numbers} Finally, we can decode the result: -<<< @/../../docs-snippets/src/guide/encoding/encode-and-decode.test.ts#encode-and-decode-5{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/encode-and-decode.ts#encode-and-decode-5{ts:line-numbers} A similar approach can be taken with [Predicates](../predicates/index.md); however, you must set the encoded values to the `predicateData` property. [Contracts](../contracts/index.md) require more care. Although you can utilize the `scriptData` property, the arguments must be encoded as part of the [contract call script](https://docs.fuel.network/docs/sway/sway-program-types/smart_contracts/#calling-a-smart-contract-from-a-script). Therefore, it is recommended to use a `FunctionInvocationScope` when working with contracts which will be instantiated for you when [submitting a contract function](../contracts/methods.md), and therefore handles all the encoding. + +## Full Example + +Here is the full example of the encoding and decoding methods: + +<<< @/../../docs-snippets2/src/encoding/encode-and-decode.ts#full{ts:line-numbers} \ No newline at end of file diff --git a/apps/docs/src/guide/encoding/working-with-bytes.md b/apps/docs/src/guide/encoding/working-with-bytes.md index c9e4eda1cdb..e42d996062e 100644 --- a/apps/docs/src/guide/encoding/working-with-bytes.md +++ b/apps/docs/src/guide/encoding/working-with-bytes.md @@ -10,34 +10,40 @@ We know the sizes of all core types at compile time. They are the building block Each type will only contain the number of bits specified in the name. For example, a `u8` will contain 8 bits, and a `u256` will contain 256 bits and take up the exact property space with no additional padding. -<<< @/../../docs-snippets/src/guide/encoding/working-with-bytes.test.ts#working-with-bytes-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/working-with-bytes.ts#working-with-bytes-1{ts:line-numbers} ### Boolean A boolean is encoded as a single byte like a `u8`, its value being either `0` or `1`. -<<< @/../../docs-snippets/src/guide/encoding/working-with-bytes.test.ts#working-with-bytes-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/working-with-bytes.ts#working-with-bytes-2{ts:line-numbers} ### Fixed Length String A fixed-length string's size is known at compile time due to the argument declaration of `str[n]` with `n` denoting its length. Each character in the string is encoded as a `utf-8` bit. -<<< @/../../docs-snippets/src/guide/encoding/working-with-bytes.test.ts#working-with-bytes-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/working-with-bytes.ts#working-with-bytes-3{ts:line-numbers} ### `b256` / `b512` These are fixed-length byte arrays, with `b256` containing 256 bits and `b512` containing 512 bits. You can use them for address and signature formats. -<<< @/../../docs-snippets/src/guide/encoding/working-with-bytes.test.ts#working-with-bytes-4{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/working-with-bytes.ts#working-with-bytes-4{ts:line-numbers} ## Automatically Encoded Types These are the types that will contain nested types and no additional encoding is required other than the encoding of the nested types. This is relevant to `array`s, `tuple`s, and `struct`s and `enum`s. The only caveat here, is an `enum` will also contain a `u64` representing the `enum` case value. `option`s are encoded in the same way as `enum`s. -<<< @/../../docs-snippets/src/guide/encoding/working-with-bytes.test.ts#working-with-bytes-5{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/working-with-bytes.ts#working-with-bytes-5{ts:line-numbers} ## Heap types Heap types are types with a dynamic length that we do not know at compile time. These are `Vec`, `String`, and `raw_slice`. These types are encoded with a `u64` representing the length of the data, followed by the data itself. -<<< @/../../docs-snippets/src/guide/encoding/working-with-bytes.test.ts#working-with-bytes-6{ts:line-numbers} +<<< @/../../docs-snippets2/src/encoding/working-with-bytes.ts#working-with-bytes-6{ts:line-numbers} + +## Full Example + +Here is the full example of the working with bytes functions: + +<<< @/../../docs-snippets2/src/encoding/working-with-bytes.ts#full{ts:line-numbers} diff --git a/apps/docs/src/guide/scripts/configurable-constants.md b/apps/docs/src/guide/scripts/configurable-constants.md index 65a4e6e1a83..b1b9d6a4e20 100644 --- a/apps/docs/src/guide/scripts/configurable-constants.md +++ b/apps/docs/src/guide/scripts/configurable-constants.md @@ -6,16 +6,23 @@ Configurable constants are fairly straightforward to add and set in your scripts Let's consider the following script: -<<< @/../../docs-snippets/test/fixtures/forc-projects/sum-script/src/main.sw#script-with-configurable-contants-1{rust:line-numbers} +<<< @/../../docs-snippets2/sway/script-sum/src/main.sw#script-with-configurable-contants-1{rust:line-numbers} In this script, `AMOUNT` is a configurable constant with a default value of `10`. The main function returns the sum of the `inputted_amount` and the configurable constant `AMOUNT`. To change the value of the `AMOUNT` constant, we can use the `setConfigurableConstants` method as shown in the following example: -<<< @/../../docs-snippets/src/guide/scripts/script-with-configurable.test.ts#script-with-configurable-contants-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/scripts/script-with-configurable.ts#script-with-configurable-contants-2{ts:line-numbers} In this example, we're setting a new value `81` for the `AMOUNT` constant. We then call the main function with an inputted value of `10`. The expectation is that the script will return the sum of the inputted value and the new value of `AMOUNT`. This way, configurable constants in scripts allow for more flexibility and dynamic behavior during execution. + + +## Full Example + +For a full example, see below: + +<<< @/../../docs-snippets2/src/scripts/script-with-configurable.ts#full{ts:line-numbers} diff --git a/apps/docs/src/guide/scripts/custom-script-call.md b/apps/docs/src/guide/scripts/custom-script-call.md index b2960269b95..8c56e95bf7b 100644 --- a/apps/docs/src/guide/scripts/custom-script-call.md +++ b/apps/docs/src/guide/scripts/custom-script-call.md @@ -2,4 +2,4 @@ Akin to Contracts, we can configure the [call parameters](../contracts/call-parameters.md) and [transaction parameters](../transactions/transaction-parameters.md) for Scripts, as well as retrieve the entire transaction request or transaction ID prior to submission. -<<< @/../../docs-snippets/src/guide/scripts/script-with-configurable.test.ts#preparing-scripts{ts:line-numbers} +<<< @/../../docs-snippets2/src/scripts/script-with-configurable.ts#preparing-scripts{ts:line-numbers} diff --git a/apps/docs/src/guide/scripts/deploying-scripts.md b/apps/docs/src/guide/scripts/deploying-scripts.md index c11be125e3e..82f9023e2f1 100644 --- a/apps/docs/src/guide/scripts/deploying-scripts.md +++ b/apps/docs/src/guide/scripts/deploying-scripts.md @@ -17,4 +17,4 @@ This will perform the following actions: We can then utilize the above generated types like so: -<<< @/../../docs-snippets/src/guide/scripts/deploying-scripts.test.ts#deploying-scripts{ts:line-numbers} +<<< @/../../docs-snippets2/src/scripts/deploying-scripts.ts#deploying-scripts{ts:line-numbers} diff --git a/apps/docs/src/guide/testing/advanced-example.md b/apps/docs/src/guide/testing/advanced-example.md index 7989c31b613..d8432d63a53 100644 --- a/apps/docs/src/guide/testing/advanced-example.md +++ b/apps/docs/src/guide/testing/advanced-example.md @@ -8,7 +8,7 @@ A more complex example showcasing genesis block state configuration with [`walletsConfig`](./test-node-options.md#walletsconfig) and deployment of multiple contracts is shown below. -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#advanced-example{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#advanced-example{ts:line-numbers} ## Summary diff --git a/apps/docs/src/guide/testing/basic-example.md b/apps/docs/src/guide/testing/basic-example.md index df30c0b8fcf..4eab7cae852 100644 --- a/apps/docs/src/guide/testing/basic-example.md +++ b/apps/docs/src/guide/testing/basic-example.md @@ -10,7 +10,7 @@ Let's use `launchTestNode` with the counter contract from the [Fuel dApp tutoria _Note: you will have to change the import paths of the contract factory and bytecode to match your folder structure._ -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#basic-example{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#basic-example{ts:line-numbers} ## Summary diff --git a/apps/docs/src/guide/testing/custom-blocks.md b/apps/docs/src/guide/testing/custom-blocks.md index a00447c9ad0..afd35dbd0ab 100644 --- a/apps/docs/src/guide/testing/custom-blocks.md +++ b/apps/docs/src/guide/testing/custom-blocks.md @@ -2,10 +2,15 @@ You can force-produce blocks using the `produceBlocks` helper to achieve an arbitrary block height. This is especially useful when you want to do some testing regarding transaction maturity. -<<< @/../../docs-snippets/src/guide/testing/tweaking-the-blockchain.test.ts#produce-blocks{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/tweaking-the-blockchain.ts#produce-blocks{ts:line-numbers} # Blocks With Custom Timestamps You can also produce blocks with a custom block time using the `produceBlocks` helper by specifying the second optional parameter. -<<< @/../../docs-snippets/src/guide/testing/tweaking-the-blockchain.test.ts#produceBlocks-custom-timestamp{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/tweaking-the-blockchain.ts#produceBlocks-custom-timestamp{ts:line-numbers} + +# Full Example + +For a full example, see the following file: +<<< @/../../docs-snippets2/src/testing/tweaking-the-blockchain.ts#full{ts:line-numbers} diff --git a/apps/docs/src/guide/testing/fuel-core-options.md b/apps/docs/src/guide/testing/fuel-core-options.md index aa6bd11405b..53e449f97ea 100644 --- a/apps/docs/src/guide/testing/fuel-core-options.md +++ b/apps/docs/src/guide/testing/fuel-core-options.md @@ -20,7 +20,7 @@ If you need a different snapshot, you can specify a `DEFAULT_CHAIN_SNAPSHOT_DIR` How and where you specify the environment variable depends on your testing tool. -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#custom-chain-config{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#custom-chain-config{ts:line-numbers} ## Fuel-Core Node Options @@ -32,4 +32,4 @@ fuel-core run --help If you want _all_ your tests to run with the same arguments, consider specifying the `DEFAULT_FUEL_CORE_ARGS` environment variable. -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#custom-fuel-core-args{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#custom-fuel-core-args{ts:line-numbers} diff --git a/apps/docs/src/guide/testing/launching-a-test-node.md b/apps/docs/src/guide/testing/launching-a-test-node.md index 993a0d47672..a08f5f92636 100644 --- a/apps/docs/src/guide/testing/launching-a-test-node.md +++ b/apps/docs/src/guide/testing/launching-a-test-node.md @@ -10,7 +10,7 @@ For usage information for `launchTestNode` including it's inputs, outputs and op We support [explicit resource management](https://www.typescriptlang.org/docs/handbook/variable-declarations.html#using-declarations), introduced in TypeScript 5.2, which automatically calls a `cleanup` function after a variable instantiated with the `using` keyword goes out of block scope: -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#automatic-cleanup{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#automatic-cleanup{ts:line-numbers} ### Configuring Typescript @@ -35,4 +35,4 @@ If you don't want, or can't use [explicit resource management](https://www.types In this case, remember you must call `.cleanup()` to dispose of the node. -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#manual-cleanup{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#manual-cleanup{ts:line-numbers} diff --git a/apps/docs/src/guide/testing/test-node-options.md b/apps/docs/src/guide/testing/test-node-options.md index 65ffb589718..edae0e429d4 100644 --- a/apps/docs/src/guide/testing/test-node-options.md +++ b/apps/docs/src/guide/testing/test-node-options.md @@ -7,7 +7,7 @@ This reference describes all the options of the [`launchTestNode`](./launching-a - [`nodeOptions`](./test-node-options.md#nodeoptions) - [`providerOptions`](./test-node-options.md#provideroptions) -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#options{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#options{ts:line-numbers} Check out the [API reference](../../api/Contract/LaunchTestNodeOptions.md) for usage information on the Test Node Options. @@ -26,17 +26,17 @@ Used to set the node's genesis block state (coins and messages). The `TestAssetId` utility integrates with [`walletsConfig`](./test-node-options.md#walletsconfig) and gives you an easy way to generate multiple random asset ids via the `TestAssetId.random` static method. -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#asset-ids{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#asset-ids{ts:line-numbers} ### `walletsConfig.messages` The `TestMessage` helper class is used to create messages for testing purposes. When passed via `walletsConfig.messages`, the `recipient` field of the message is overriden to be the wallet's address. -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#test-messages{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#test-messages{ts:line-numbers} It can also be used standalone and passed into the initial state of the chain via the `TestMessage.toChainMessage` instance method. -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#test-messages-chain{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#test-messages-chain{ts:line-numbers} ## `contractsConfigs` @@ -54,7 +54,7 @@ Options to modify the behavior of the node. For example, you can specify your own base asset id of the chain like below: -<<< @/../../docs-snippets/src/guide/testing/launching-a-test-node.test.ts#custom-node-options{ts:line-numbers} +<<< @/../../docs-snippets2/src/testing/launching-a-test-node.ts#custom-node-options{ts:line-numbers} _Note: The API for these options is still not fully complete and better documentation will come in the future._ diff --git a/apps/docs/src/guide/transactions/transaction-parameters.md b/apps/docs/src/guide/transactions/transaction-parameters.md index 50b187bfb7e..524d72b5123 100644 --- a/apps/docs/src/guide/transactions/transaction-parameters.md +++ b/apps/docs/src/guide/transactions/transaction-parameters.md @@ -58,4 +58,6 @@ The same method is also accessible within a function invocation scope, so it can ## Full Example +Here is the full example of the transaction parameters: + <<< @/../../docs-snippets2/src/transactions/transaction-parameters.ts#full{ts:line-numbers} diff --git a/apps/docs/src/guide/utilities/unit-conversion.md b/apps/docs/src/guide/utilities/unit-conversion.md index 5903cf4ee7c..8c21d0f70d7 100644 --- a/apps/docs/src/guide/utilities/unit-conversion.md +++ b/apps/docs/src/guide/utilities/unit-conversion.md @@ -10,17 +10,17 @@ Below we will go over some common use cases for unit conversion. Using our `BN` class we can instantiate these numbers. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#instantiation-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#instantiation-1{ts:line-numbers} Or using our `bn` utility function. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#instantiation-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#instantiation-2{ts:line-numbers} ## Contract calls Generally, we will need to convert `u64` and `u256` numbers to a `BN` object when passing them to a Sway program from JavaScript. More information on this can be found [here](../types/numbers.md). -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#contract-calls-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#contract-calls-1{ts:line-numbers} > Note: If a contract call returns a number that is too large to be represented as a JavaScript number, you can convert it to a string using the `toString` method instead of `toNumber`. @@ -28,19 +28,19 @@ Generally, we will need to convert `u64` and `u256` numbers to a `BN` object whe Parsing string-represented numbers (from user input) has never been easier, than using the `parseUnits` function. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#parse-units-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#parse-units-1{ts:line-numbers} We can parse large numbers. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#parse-units-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#parse-units-2{ts:line-numbers} Or numbers formatted for human readability. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#parse-units-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#parse-units-3{ts:line-numbers} We can also parse numbers in other units of measure. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#parse-units-4{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#parse-units-4{ts:line-numbers} ## Formatting @@ -48,26 +48,33 @@ We can format common units of measure using the `format` function. In the following example, we format a BigNumber representation of one Gwei, into units for the Fuel network (with 3 decimal place precision). -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#format-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#format-1{ts:line-numbers} We can also format numbers in other units of measure by specifying the `units` variable. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#format-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#format-2{ts:line-numbers} A `precision` variable will allow for the formatting of numbers with a specific number of decimal places. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#format-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#format-3{ts:line-numbers} ### Format units The `formatUnits` function is a lesser alternative to the `format` function, as it will maintain the same precision as the input value. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#format-units-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#format-units-1{ts:line-numbers} We can also format numbers in other units of measure by specifying the `units` variable. -<<< @/../../docs-snippets/src/guide/utilities/unit-conversion.test.ts#format-units-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#format-units-2{ts:line-numbers} ## See also -- [Sway Numbers](../types/numbers.md) \ No newline at end of file +- [Sway Numbers](../types/numbers.md) + + +## Full Example + +For the full example of unit conversion see the snippet below: + +<<< @/../../docs-snippets2/src/utilities/unit-conversion.ts#full{ts:line-numbers} diff --git a/apps/docs/src/guide/wallets/wallet-manager.md b/apps/docs/src/guide/wallets/wallet-manager.md index 56dd4cf2f48..9f586558c3f 100644 --- a/apps/docs/src/guide/wallets/wallet-manager.md +++ b/apps/docs/src/guide/wallets/wallet-manager.md @@ -28,13 +28,13 @@ For now, let's keep it simple and not worry about the storage. Later we will dis To instantiate a `WalletManager` you can simply: -<<< @/../../docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts#getting-started-with-wallet-manager-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts#getting-started-with-wallet-manager-1{ts:line-numbers} ### Setting `WalletManager` Password By default, a `WalletManager` instance is locked when created. Before using it, you need to unlock it by setting a password. You can do this by calling the `unlock` method. -<<< @/../../docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts#getting-started-with-wallet-manager-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts#getting-started-with-wallet-manager-2{ts:line-numbers} Once your `WalletManager` is unlocked, it can manage your wallets. @@ -44,7 +44,7 @@ A vault in `WalletManager` serves as a secure container for wallets. The `Wallet To add a vault, we utilize the `addVault` method. Here's how we can create a private key vault and add a private key from a wallet we own: -<<< @/../../docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts#getting-started-with-wallet-manager-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts#getting-started-with-wallet-manager-3{ts:line-numbers} The `addVault` method requires an object with three properties: `type`, `secret`, and `title`. The `WalletManager` currently supports two types of vaults: `privateKeyVault` and `mnemonicVault`. For the `secret`, we use our wallet's private key, and for the `title`, we can provide a custom name. @@ -52,7 +52,7 @@ By running this code, `WalletManager` creates a new vault instance of the type ` A key feature of the `WalletManager` is its ability to manage multiple vaults, even of the same type. This implies that if you run the `addVault` method again, with the same parameters, `WalletManager` will create another vault of the type `privateKey`, holding the same wallet. Here's an example: -<<< @/../../docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts#getting-started-with-wallet-manager-4{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts#getting-started-with-wallet-manager-4{ts:line-numbers} After executing this, you will find that your `WalletManager` is managing two `privateKey` vaults, both storing the same wallet. @@ -62,17 +62,17 @@ Remember, both `title` and `secret` are optional when adding vaults, but providi With your `WalletManager` set up, you can now access your vaults and wallets. Here's how to retrieve the details of your vaults: -<<< @/../../docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts#getting-started-with-wallet-manager-5{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts#getting-started-with-wallet-manager-5{ts:line-numbers} This will output something like this: -<<< @/../../docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts#getting-started-with-wallet-manager-6{bash:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts#getting-started-with-wallet-manager-6{bash:line-numbers} As you can see, the `WalletManager` assigns unique `vaultIds` for each vault. The first vault you added has a `vaultId` of `0`, and the second one has a `vaultId` of `1`. Let's retrieve your wallet instance with the `getWallet` method: -<<< @/../../docs-snippets/src/guide/wallet-manager/getting-started-with-wallet-manager.test.ts#getting-started-with-wallet-manager-7{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/getting-started-with-wallet-manager.ts#getting-started-with-wallet-manager-7{ts:line-numbers} This guide walked through the steps to instantiate a `WalletManager`, set up its first vault, and retrieve vault information. The following sections will explore more functionalities of `WalletManager`, and go deeper into the usage of its vaults and the details of its storage system. @@ -84,13 +84,13 @@ This guide will walk you through the process of managing the lock state of your As mentioned earlier, a `WalletManager` instance begins in a locked state. Before usage, you need to unlock it by providing a password via the unlock method. -<<< @/../../docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts#locking-and-unlocking-wallet-manager-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts#locking-and-unlocking-wallet-manager-1{ts:line-numbers} ### Locking the `WalletManager` When you lock the `WalletManager` using the `lock` method, all its vaults and associated accounts (wallets) are cleared. This clearance is possible due to the encryption and saving of all data by the storage system. `WalletManager` frequently uses the storage system to preserve its state. Consequently, sensitive operations including exporting vaults, private keys, accessing wallets, and saving/loading the `WalletManager` state are not possible when it is locked. -<<< @/../../docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts#locking-and-unlocking-wallet-manager-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts#locking-and-unlocking-wallet-manager-2{ts:line-numbers} Remember, it's crucial to lock your `WalletManager` when it's not in use to ensure the safety of your funds. @@ -98,7 +98,7 @@ Remember, it's crucial to lock your `WalletManager` when it's not in use to ensu The `unlock` method requires the previously set password to unlock the `WalletManager` and all its vaults. The password decrypts the stored vaults, allowing `WalletManager` to load its saved data. -<<< @/../../docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts#locking-and-unlocking-wallet-manager-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts#locking-and-unlocking-wallet-manager-3{ts:line-numbers} Providing an incorrect password will result in an error. However, when unlocked successfully, `WalletManager` is ready for use again. @@ -106,18 +106,18 @@ Providing an incorrect password will result in an error. However, when unlocked You can confirm the current lock state of the `WalletManager` by using the `isLocked` method: -<<< @/../../docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts#locking-and-unlocking-wallet-manager-4{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts#locking-and-unlocking-wallet-manager-4{ts:line-numbers} ### Updating the Password To change the current password, invoke the `updatePassphrase` method, and provide both the old and new passwords: -<<< @/../../docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts#locking-and-unlocking-wallet-manager-5{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts#locking-and-unlocking-wallet-manager-5{ts:line-numbers} ### Reminder: Always Lock Your `WalletManager` Always ensure you lock the `WalletManager` after completing operations. This step is critical for securing your wallets. -<<< @/../../docs-snippets/src/guide/wallet-manager/locking-and-unlocking-wallet-manager.test.ts#locking-and-unlocking-wallet-manager-6{ts:line-numbers} +<<< @/../../docs-snippets2/src/wallet-manager/locking-and-unlocking-wallet-manager.ts#locking-and-unlocking-wallet-manager-6{ts:line-numbers} By using `WalletManager` to manage lock and unlock states, you introduce an additional layer of security. Never forget to lock your `WalletManager` when it's not in use. diff --git a/packages/fuels/test/features/deploy.test.ts b/packages/fuels/test/features/deploy.test.ts index 55a2e7f9f00..a9e57186a06 100644 --- a/packages/fuels/test/features/deploy.test.ts +++ b/packages/fuels/test/features/deploy.test.ts @@ -1,6 +1,7 @@ import type { JsonAbi } from '@fuel-ts/abi-coder'; import type { Account } from '@fuel-ts/account'; import { Contract } from '@fuel-ts/program'; +import { exec } from 'child_process'; import { existsSync, readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; @@ -14,6 +15,22 @@ import { runInit, } from '../utils/runCommands'; +beforeAll(async () => { + // Kill any existing process at port 4000 + const killCommand = 'lsof -ti:4000 | xargs kill -9'; + + try { + await new Promise((resolve) => { + exec(killCommand, () => { + // Ignore errors since port may not be in use + resolve(null); + }); + }); + } catch (e) { + // Ignore errors since port may not be in use + } +}); + /** * @group node */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ebf96cb0a59..f320ee8a0b4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4040,9 +4040,6 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/source-map@0.3.3': - resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==} - '@jridgewell/source-map@0.3.6': resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} @@ -20674,11 +20671,6 @@ snapshots: '@jridgewell/set-array@1.2.1': {} - '@jridgewell/source-map@0.3.3': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/source-map@0.3.6': dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -35329,7 +35321,7 @@ snapshots: terser@5.18.2: dependencies: - '@jridgewell/source-map': 0.3.3 + '@jridgewell/source-map': 0.3.6 acorn: 8.12.1 commander: 2.20.3 source-map-support: 0.5.21 diff --git a/tsconfig.test.json b/tsconfig.test.json index 0330aadf23a..3408c0b62a3 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -4,5 +4,5 @@ "noEmit": true }, "include": ["**/*.test.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules", "apps/docs-snippets2/src/**/*.test.ts"] }