diff --git a/.changeset/clever-bikes-itch.md b/.changeset/clever-bikes-itch.md new file mode 100644 index 00000000000..928b49a6c27 --- /dev/null +++ b/.changeset/clever-bikes-itch.md @@ -0,0 +1,5 @@ +--- +"create-fuels": patch +--- + +chore: bumped `@fuels/*` deps to `0.36.1` diff --git a/.changeset/gentle-toes-play.md b/.changeset/gentle-toes-play.md new file mode 100644 index 00000000000..98b9a4d469b --- /dev/null +++ b/.changeset/gentle-toes-play.md @@ -0,0 +1,5 @@ +--- +"@fuel-ts/account": patch +--- + +feat: added method to duplicate predicate diff --git a/.changeset/lazy-ears-tap.md b/.changeset/lazy-ears-tap.md new file mode 100644 index 00000000000..a25355967f5 --- /dev/null +++ b/.changeset/lazy-ears-tap.md @@ -0,0 +1,5 @@ +--- +"create-fuels": patch +--- + +feat: auto-detect package manager in `create fuels` diff --git a/.changeset/small-plums-talk.md b/.changeset/small-plums-talk.md new file mode 100644 index 00000000000..83f4952100f --- /dev/null +++ b/.changeset/small-plums-talk.md @@ -0,0 +1,8 @@ +--- +"@fuel-ts/address": minor +"@fuel-ts/errors": patch +"@fuel-ts/recipes": patch +"@fuel-ts/logger": minor +--- + +chore!: remove Bech32 address diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 88a07d3af77..0c2b4b5f108 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -244,10 +244,7 @@ During the CI process an automated end-to-end (e2e) test is executed. This test The e2e test can be found at: `packages/fuel-gauge/src/e2e-script.test.ts` -The Bech32 address of this wallet is `fuel1x33ajpj0jy5p2wcqqu45e32r75zrwfeh6hwqfv5un670rv4p0mns58enjg`. This address can be funded via the [faucet](https://faucet-testnet.fuel.network/). - -> [!NOTE] Note -> `Bech32` addresses like `fuel1..` are now deprecated. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) +The B256 address of this wallet is `0x3463d9064f9128153b00072b4cc543f504372737d5dc04b29c9ebcf1b2a17ee7`. This address can be funded via the [faucet](https://faucet-testnet.fuel.network/). If you want to run an e2e test locally, you can provide your own wallet address and private key. For obvious security reasons, the private key should not be shared. @@ -270,8 +267,6 @@ This will enable you to run the e2e test locally against the live network: pnpm test:filter e2e-script ``` - - # Commit Convention Before you create a Pull Request, please check whether your commits comply with diff --git a/apps/create-fuels-counter-guide/package.json b/apps/create-fuels-counter-guide/package.json index deba01e8324..5d7b658ef34 100644 --- a/apps/create-fuels-counter-guide/package.json +++ b/apps/create-fuels-counter-guide/package.json @@ -14,8 +14,8 @@ "postbuild": "run-s fuels:build original:build" }, "dependencies": { - "@fuels/connectors": "^0.27.1", - "@fuels/react": "^0.27.1", + "@fuels/connectors": "^0.36.1", + "@fuels/react": "^0.36.1", "@tanstack/react-query": "^5.55.4", "clsx": "2.1.1", "@wagmi/connectors": "^5.1.14", diff --git a/apps/create-fuels-counter-guide/src/lib.tsx b/apps/create-fuels-counter-guide/src/lib.tsx index cd4fbd76e68..f01d5ca33e1 100644 --- a/apps/create-fuels-counter-guide/src/lib.tsx +++ b/apps/create-fuels-counter-guide/src/lib.tsx @@ -11,6 +11,7 @@ export const isTestnet = environment === environments.TESTNET; export const localProviderUrl = `http://127.0.0.1:${process.env.VITE_FUEL_NODE_PORT || 4000}/v1/graphql`; export const testnetProviderUrl = 'https://testnet.fuel.network/v1/graphql'; export const providerUrl = isLocal ? localProviderUrl : testnetProviderUrl; +export const chainId = 0; // Local and testnet are both on chain 0 export const playgroundUrl = providerUrl.replace('v1/graphql', 'v1/playground'); // #region deploying-dapp-to-testnet-frontend-contract-id @@ -28,7 +29,7 @@ export const renderTransactionId = (transactionId: string) => { return ( - + diff --git a/apps/demo-wallet-sdk-react/package.json b/apps/demo-wallet-sdk-react/package.json index 80f73573e3d..5484a2e69cb 100644 --- a/apps/demo-wallet-sdk-react/package.json +++ b/apps/demo-wallet-sdk-react/package.json @@ -9,8 +9,8 @@ "lint": "next lint" }, "dependencies": { - "@fuels/connectors": "^0.27.1", - "@fuels/react": "^0.27.1", + "@fuels/connectors": "^0.36.1", + "@fuels/react": "^0.36.1", "@tanstack/react-query": "^5.55.4", "fuels": "workspace:*", "next": "14.2.15", diff --git a/apps/docs/.vitepress/config.ts b/apps/docs/.vitepress/config.ts index 17fbc9b5931..05ea76b776e 100644 --- a/apps/docs/.vitepress/config.ts +++ b/apps/docs/.vitepress/config.ts @@ -487,10 +487,6 @@ export default defineConfig({ text: 'Asset Id', link: '/guide/types/asset-id', }, - { - text: 'Bech32', - link: '/guide/types/bech32', - }, { text: 'Bits256', link: '/guide/types/bits256', diff --git a/apps/docs/spell-check-custom-words.txt b/apps/docs/spell-check-custom-words.txt index aa3ebc175d7..bd79fd9cf81 100644 --- a/apps/docs/spell-check-custom-words.txt +++ b/apps/docs/spell-check-custom-words.txt @@ -21,7 +21,6 @@ backends backoff backtrace backtraces -Bech BigNumber Bitfield bitmask diff --git a/apps/docs/src/guide/contracts/managing-deployed-contracts.md b/apps/docs/src/guide/contracts/managing-deployed-contracts.md index b24d3752125..361a9e37599 100644 --- a/apps/docs/src/guide/contracts/managing-deployed-contracts.md +++ b/apps/docs/src/guide/contracts/managing-deployed-contracts.md @@ -6,16 +6,13 @@ To interact with a deployed contract using the SDK without redeploying it, you o The `contractId` property from the [`Contract`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_program.Contract.html) class is of type [`AbstractAddress`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_interfaces.AbstractAddress.html), an abstract class that is exclusively extended by the [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class. -The [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class wraps all methods from the [`AbstractAddress`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_interfaces.AbstractAddress.html) class and adds a single property: `bech32Address`. This property is a string encoded in [`Bech32`](../types/bech32.md) format, recognizable by the human-readable prefix `fuel` followed by the separator `1`. - -> [!NOTE] Note -> `Bech32` addresses like `fuel1..` are now deprecated; please switch to B256 format, for more details see [here](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256). +The [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class wraps all methods from the [`AbstractAddress`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_interfaces.AbstractAddress.html) class and adds a single property: `b256Address`. This property is a string encoded in [`B256`](../types/bits256.md) format. When you log the `contractId` property of an instantiated Contract using `console.log`, the output appears as follows: ```console Address { - bech32Address: 'fuel1e5tdjlzufcvwut5dvs5yglweepmrevpnvuvt2djj6pyl3mygkwaq8m7f20' + b256Address: '0xcd16d97c5c4e18ee2e8d6428447dd9c8763cb0336718b53652d049f8ec88b3ba' } ``` 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 ac9b3eb234f..1f5e6954ee6 100644 --- a/apps/docs/src/guide/creating-a-fuel-dapp/index.md +++ b/apps/docs/src/guide/creating-a-fuel-dapp/index.md @@ -20,15 +20,15 @@ The first step is to run the command: ::: code-group ```sh-vue [npm] -npm create fuels@{{fuels}} -- --npm +npm create fuels@{{fuels}} ``` ```sh-vue [pnpm] -pnpm create fuels@{{fuels}} --pnpm +pnpm create fuels@{{fuels}} ``` ```sh-vue [bun] -bunx --bun create-fuels@{{fuels}} --bun +bun create fuels@{{fuels}} ``` ::: diff --git a/apps/docs/src/guide/creating-a-fuel-dapp/options.md b/apps/docs/src/guide/creating-a-fuel-dapp/options.md index 8719900be02..0e016e8b6ac 100644 --- a/apps/docs/src/guide/creating-a-fuel-dapp/options.md +++ b/apps/docs/src/guide/creating-a-fuel-dapp/options.md @@ -10,15 +10,15 @@ The `npm create fuels` command has several command-line options that you can use ::: code-group ```sh-vue [pnpm] -pnpm create fuels@{{fuels}} --pnpm [project-name] [options] +pnpm create fuels@{{fuels}} [project-name] [options] ``` ```sh-vue [npm] -npm create fuels@{{fuels}} -- --npm [project-name] [options] +npm create fuels@{{fuels}} -- [project-name] [options] ``` ```sh-vue [bun] -bunx --bun create-fuels@{{fuels}} --bun [project-name] [options] +bun create fuels@{{fuels}} [project-name] [options] ``` ::: @@ -27,18 +27,6 @@ bunx --bun create-fuels@{{fuels}} --bun [project-name] [options] Specifies the template to use for your project. The available templates are: `vite` and `nextjs`. The default template is `vite`. -## `--pnpm` - -Notifies the tool to use pnpm as the package manager to install the necessary dependencies. - -## `--npm` - -Notifies the tool to use npm as the package manager to install the necessary dependencies. - -## `--bun` - -Notifies the tool to use bun as the package manager to install the necessary dependencies. - ## `--verbose` Enables verbose logging. Useful when debugging issues with the tool. diff --git a/apps/docs/src/guide/types/address.md b/apps/docs/src/guide/types/address.md index a87f80b38af..73e4a971ea9 100644 --- a/apps/docs/src/guide/types/address.md +++ b/apps/docs/src/guide/types/address.md @@ -10,7 +10,7 @@ The SDK defines the [AbstractAddress](https://fuels-ts-docs-api.vercel.app/class ## Address Class -Besides conforming to the interface of the [`AbstractAddress`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_interfaces.AbstractAddress.html), the [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class also defines one property; `bech32Address`, which is of the [`Bech32`](./bech32.md) type. +Besides conforming to the interface of the [`AbstractAddress`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_interfaces.AbstractAddress.html), the [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class also defines one property; `b256Address`, which is of the [`B256`](./bits256.md) type. <<< @/../../../packages/address/src/address.ts#address-2{ts:line-numbers} @@ -18,14 +18,11 @@ Besides conforming to the interface of the [`AbstractAddress`](https://fuels-ts- Thanks to the utility functions provided by the [`AbstractAddress`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_interfaces.AbstractAddress.html) class, there are several ways to create an [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) instance: -### From a `Bech32` Address +### From a b256 address -To create an [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) from a `Bech32` address, use the following code snippet: - -<<< @./snippets/address/creating-an-address.ts#full{ts:line-numbers} +To create an [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) from a 256-bit address, use the following code snippet: -> [!NOTE] Note -> `Bech32` addresses like `fuel1..` are now deprecated. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) +<<< @./snippets/address/from-a-b256.ts#full{ts:line-numbers} ### From a Public Key @@ -33,17 +30,11 @@ To create an [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_a <<< @./snippets/address/from-a-public-key.ts#full{ts:line-numbers} -### From a 256-bit Address - -To create an [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) from a 256-bit address, use the following code snippet: - -<<< @./snippets/address/from-a-b256.ts#full{ts:line-numbers} - ## Utility Functions The [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class also provides some practical utility functions: -1. `fromString`: Create a new [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) from an ambiguous source that may be a `Bech32` or `B256` address: +1. `fromString`: Create a new [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) from an ambiguous source that may be a `B256` address: <<< @./snippets/address/utilities-function-1.ts#full{ts:line-numbers} diff --git a/apps/docs/src/guide/types/bech32.md b/apps/docs/src/guide/types/bech32.md deleted file mode 100644 index 58e0d72e4a6..00000000000 --- a/apps/docs/src/guide/types/bech32.md +++ /dev/null @@ -1,22 +0,0 @@ -# `Bech32` - -> [!NOTE] Note -> `Bech32` addresses like `fuel1..` are now deprecated. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) - -The SDK uses the `Bech32` type as the core property of the [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class, specifically through the `bech32Address` property. - -Originally designed for Bitcoin, the `Bech32` format offers numerous advantages such as enhanced error detection, simplified integrations, and improved compatibility with future upgrades. Given these benefits, the [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class is constructed around the `Bech32` type. - -You can read more about the `Bech32` type [here](https://thebitcoinmanual.com/articles/btc-bech32-address/). - -## Default Human-Readable Part (HRP) - -A `Bech32` address consists of an HRP (Human-Readable Part) followed by the number `1`, which acts as a separator: - -<<< @/../../../packages/interfaces/src/index.ts#bech32-1{ts:line-numbers} - -A complete `Bech32` address will resemble the following: - -<<< @./snippets/bech32.ts#bech32-2{5 ts:line-numbers} - -The HRP in the example above is `fuel`. This human-readable prefix is included to provide better readability and prevent users from accidentally using addresses on the wrong network. diff --git a/apps/docs/src/guide/types/snippets/address/creating-an-address.ts b/apps/docs/src/guide/types/snippets/address/creating-an-address.ts index bdc0642e38d..377e02066d2 100644 --- a/apps/docs/src/guide/types/snippets/address/creating-an-address.ts +++ b/apps/docs/src/guide/types/snippets/address/creating-an-address.ts @@ -1,10 +1,10 @@ // #region full import { Address } from 'fuels'; -const ADDRESS_BECH32 = - 'fuel1elnmzsav56dqnp95sx4e2pckq36cvae9ser44m5zlvgtwxw49fmqd7e42e'; +const ADDRESS_B256 = + '0xcfe7b143aca69a0984b481ab950716047586772586475aee82fb10b719d52a76'; -const address = new Address(ADDRESS_BECH32); +const address = new Address(ADDRESS_B256); // #endregion full console.log('address', address); diff --git a/apps/docs/src/guide/types/snippets/address/utilities-function-1.ts b/apps/docs/src/guide/types/snippets/address/utilities-function-1.ts index b1acbcd343a..0823a6f9400 100644 --- a/apps/docs/src/guide/types/snippets/address/utilities-function-1.ts +++ b/apps/docs/src/guide/types/snippets/address/utilities-function-1.ts @@ -3,9 +3,7 @@ import { Address } from 'fuels'; const address = Address.fromRandom(); -const addressCloneFromBech = Address.fromString(address.toString()); const addressCloneFromB256 = Address.fromString(address.toB256()); // #endregion full -console.log('addressCloneFromBech', addressCloneFromBech); console.log('addressCloneFromB256', addressCloneFromB256); diff --git a/apps/docs/src/guide/types/snippets/b256.ts b/apps/docs/src/guide/types/snippets/b256.ts new file mode 100644 index 00000000000..595b44ff156 --- /dev/null +++ b/apps/docs/src/guide/types/snippets/b256.ts @@ -0,0 +1,6 @@ +// #region addresses-1 +const b256 = + '0x9ae5b658754e096e4d681c548daf46354495a437cc61492599e33fc64dcdc30c'; +// #endregion addresses-1 + +console.log('b256', b256); diff --git a/apps/docs/src/guide/types/snippets/bech32.ts b/apps/docs/src/guide/types/snippets/bech32.ts deleted file mode 100644 index 5e3c399ec44..00000000000 --- a/apps/docs/src/guide/types/snippets/bech32.ts +++ /dev/null @@ -1,16 +0,0 @@ -// #region bech32-2 -import { Address } from 'fuels'; - -const address = Address.fromRandom(); - -console.log('Bech32', address.bech32Address); - -// fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs -// #endregion bech32-2 - -// #region addresses-1 -const bech32 = - 'fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs'; -// #endregion addresses-1 - -console.log('bech32', bech32); diff --git a/apps/docs/src/guide/utilities/address-conversion.md b/apps/docs/src/guide/utilities/address-conversion.md index 2bb1eaf8c82..ba42aeca586 100644 --- a/apps/docs/src/guide/utilities/address-conversion.md +++ b/apps/docs/src/guide/utilities/address-conversion.md @@ -2,12 +2,9 @@ Addresses and varying address formats are commonplace when interacting with decentralized applications. Furthermore, different networks may enforce different address formats. -The Fuel Network uses the [`Bech32`](../types/bech32.md) address format for its interactions, an example of which can be seen below: +The Fuel Network uses the [`Bits256`](../types/bits256.md) address format for its interactions, an example of which can be seen below: -<<< @/../../docs/src/guide/types/snippets/bech32.ts#addresses-1{ts:line-numbers} - -> [!NOTE] Note -> `Bech32` addresses like `fuel1..` are now deprecated. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) +<<< @/../../docs/src/guide/types/snippets/b256.ts#addresses-1{ts:line-numbers} However, a hexlified [Bits256](../types/bits256.md) (hex) is another common address format; an example can be seen below: @@ -26,26 +23,6 @@ The following [conversion guide](./address-conversion.md#address-conversion) wil This guide demonstrates how to convert between address formats and Sway Standard Types using helper functions. Native types are wrappers for bytes, and you can perform conversions between them by leveraging these functions and classes. -## From `Bech32` to `b256` - -By instantiating an [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html), we can validate a `Bech32` address and easily convert it to a `b256`: - -<<< @./snippets/address-conversion/bech32-to-b256.ts#conversion-5{ts:line-numbers} - -Or, if you'd prefer to use utility functions directly for validation and conversion, you can use `isBech32` and `toB256`: - -<<< @./snippets/address-conversion/bech32-to-b256-utilities.ts#conversion-6{ts:line-numbers} - -## From `b256` to `Bech32` - -In a similar fashion, we have both class functions on the [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) and utilities available for `b256` validation and conversion: - -<<< @./snippets/address-conversion/b256-to-bech32.ts#conversion-7{ts:line-numbers} - -And by using the `isB256` and `toBech32` utilities: - -<<< @./snippets/address-conversion/b256-to-bech32-utilities.ts#conversion-8{ts:line-numbers} - ## Converting a Contract ID The Contract `id` property has the [`AbstractAddress`](../types/address.md#abstractaddress-class) type. Therefore, it can be converted using the [`Address`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_address.Address.html) class functions such as `toAddress` and `toB256`: diff --git a/apps/docs/src/guide/utilities/snippets/address-conversion/b256-to-bech32-utilities.ts b/apps/docs/src/guide/utilities/snippets/address-conversion/b256-to-bech32-utilities.ts deleted file mode 100644 index f06ca69b731..00000000000 --- a/apps/docs/src/guide/utilities/snippets/address-conversion/b256-to-bech32-utilities.ts +++ /dev/null @@ -1,12 +0,0 @@ -// #region conversion-8 -import { isB256, toBech32 } from 'fuels'; - -const b256 = - '0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f'; -const bech32 = isB256(b256) ? toBech32(b256) : null; -// fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs -// #endregion conversion-8 - -const expectedBech32 = - 'fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs'; -console.log('Bech32 should be equal to example', bech32 === expectedBech32); diff --git a/apps/docs/src/guide/utilities/snippets/address-conversion/b256-to-bech32.ts b/apps/docs/src/guide/utilities/snippets/address-conversion/b256-to-bech32.ts deleted file mode 100644 index 24dc999e4aa..00000000000 --- a/apps/docs/src/guide/utilities/snippets/address-conversion/b256-to-bech32.ts +++ /dev/null @@ -1,16 +0,0 @@ -// #region conversion-7 -import type { B256Address, Bech32Address } from 'fuels'; -import { Address } from 'fuels'; - -const b256: B256Address = - '0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f'; - -const address: Address = Address.fromDynamicInput(b256); - -const bech32: Bech32Address = address.bech32Address; -// fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs -// #endregion conversion-7 - -const expectedBech32 = - 'fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs'; -console.log('Bech32 should be equal to example', bech32 === expectedBech32); diff --git a/apps/docs/src/guide/utilities/snippets/address-conversion/bech32-to-b256-utilities.ts b/apps/docs/src/guide/utilities/snippets/address-conversion/bech32-to-b256-utilities.ts deleted file mode 100644 index 037e6e7e7a3..00000000000 --- a/apps/docs/src/guide/utilities/snippets/address-conversion/bech32-to-b256-utilities.ts +++ /dev/null @@ -1,14 +0,0 @@ -// #region conversion-6 -import type { B256Address, Bech32Address } from 'fuels'; -import { isBech32, toB256 } from 'fuels'; - -const bech32: Bech32Address = - 'fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs'; - -const b256: B256Address | null = isBech32(bech32) ? toB256(bech32) : null; -// 0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f -// #endregion conversion-6 - -const expectedB256 = - '0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f'; -console.log('B256 should be equal to example', b256 === expectedB256); diff --git a/apps/docs/src/guide/utilities/snippets/address-conversion/bech32-to-b256.ts b/apps/docs/src/guide/utilities/snippets/address-conversion/bech32-to-b256.ts deleted file mode 100644 index 82af1183028..00000000000 --- a/apps/docs/src/guide/utilities/snippets/address-conversion/bech32-to-b256.ts +++ /dev/null @@ -1,16 +0,0 @@ -// #region conversion-5 -import type { B256Address, Bech32Address } from 'fuels'; -import { Address } from 'fuels'; - -const bech32: Bech32Address = - 'fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs'; - -const address: Address = Address.fromDynamicInput(bech32); - -const b256: B256Address = address.toB256(); -// 0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f -// #endregion conversion-5 - -const expectedB256 = - '0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f'; -console.log('B256 should be equal to example', b256 === expectedB256); diff --git a/apps/docs/src/guide/utilities/snippets/address-conversion/contract.ts b/apps/docs/src/guide/utilities/snippets/address-conversion/contract.ts index 0182740b52a..b6d4fbd8c5a 100644 --- a/apps/docs/src/guide/utilities/snippets/address-conversion/contract.ts +++ b/apps/docs/src/guide/utilities/snippets/address-conversion/contract.ts @@ -1,5 +1,5 @@ // #region conversion-2 -import type { Bech32Address } from 'fuels'; +import type { B256Address } from 'fuels'; import { Address, Provider, Contract } from 'fuels'; import { LOCAL_NETWORK_URL } from '../../../../env'; @@ -14,10 +14,10 @@ const contractAddress = Address.fromB256( const contract = new Contract(contractAddress, contractAbi, provider); -const bech32: Bech32Address = contract.id.toAddress(); -// fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs +const b256: B256Address = contract.id.toAddress(); +// 0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f // #endregion conversion-2 -const expectedBech32 = - 'fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs'; -console.log('Bech32 address should equal expected', bech32 === expectedBech32); +const expectedB256 = + '0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f'; +console.log('B256 address should equal expected', b256 === expectedB256); diff --git a/apps/docs/src/guide/utilities/snippets/address-conversion/wallet.ts b/apps/docs/src/guide/utilities/snippets/address-conversion/wallet.ts index 03c90a4a6ba..75ffce97322 100644 --- a/apps/docs/src/guide/utilities/snippets/address-conversion/wallet.ts +++ b/apps/docs/src/guide/utilities/snippets/address-conversion/wallet.ts @@ -1,5 +1,5 @@ // #region conversion-3 -import type { Bech32Address, WalletLocked } from 'fuels'; +import type { B256Address, WalletLocked } from 'fuels'; import { Address, Provider, Wallet } from 'fuels'; import { LOCAL_NETWORK_URL } from '../../../../env'; @@ -12,10 +12,10 @@ const address = Address.fromB256( const wallet: WalletLocked = Wallet.fromAddress(address, provider); -const bech32: Bech32Address = wallet.address.toAddress(); -// fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs +const b256: B256Address = wallet.address.toAddress(); +// 0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f // #endregion conversion-3 -const expectedBech32 = - 'fuel1d5cfwekq78r0zq73g7eg0747etkaxxltrqx5tncm7lvg89awe3hswhqjhs'; -console.log('Bech32 address should equal expected', bech32 === expectedBech32); +const expectedB256 = + '0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f'; +console.log('b256 address should equal expected', b256 === expectedB256); diff --git a/apps/docs/src/guide/wallets/instantiating-wallets.md b/apps/docs/src/guide/wallets/instantiating-wallets.md index 8c15954f6b5..b7a501ee524 100644 --- a/apps/docs/src/guide/wallets/instantiating-wallets.md +++ b/apps/docs/src/guide/wallets/instantiating-wallets.md @@ -40,7 +40,7 @@ It's possible to instantiate a `WalletUnlocked` from a `WalletLocked`: You can also instantiate [`WalletLocked`](https://fuels-ts-docs-api.vercel.app/classes/_fuel_ts_account.WalletLocked.html) instances using just the wallet address: -<<< @./snippets/instantiating/from-bech32-address.ts#instantiating-wallets-8{ts:line-numbers} +<<< @./snippets/instantiating/from-b256-address.ts#instantiating-wallets-8{ts:line-numbers} ## Connecting to a Provider diff --git a/apps/docs/src/guide/wallets/snippets/instantiating/from-bech32-address.ts b/apps/docs/src/guide/wallets/snippets/instantiating/from-b256-address.ts similarity index 58% rename from apps/docs/src/guide/wallets/snippets/instantiating/from-bech32-address.ts rename to apps/docs/src/guide/wallets/snippets/instantiating/from-b256-address.ts index 1ef57e2f503..795333a26ae 100644 --- a/apps/docs/src/guide/wallets/snippets/instantiating/from-bech32-address.ts +++ b/apps/docs/src/guide/wallets/snippets/instantiating/from-b256-address.ts @@ -1,8 +1,8 @@ // #region instantiating-wallets-8 -import type { WalletLocked } from 'fuels'; +import type { B256Address, WalletLocked } from 'fuels'; import { Wallet } from 'fuels'; -const address = `fuel14kjrdcdcp7z4l9xk0pm3cwz9qnjxxd04wx4zgnc3kknslclxzezqyeux5d`; +const address: B256Address = `0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f`; const wallet: WalletLocked = Wallet.fromAddress(address); // #endregion instantiating-wallets-8 diff --git a/apps/docs/src/guide/wallets/snippets/instantiating/unlock-from-private-key.ts b/apps/docs/src/guide/wallets/snippets/instantiating/unlock-from-private-key.ts index 2e27e7cfd66..1785aa15f89 100644 --- a/apps/docs/src/guide/wallets/snippets/instantiating/unlock-from-private-key.ts +++ b/apps/docs/src/guide/wallets/snippets/instantiating/unlock-from-private-key.ts @@ -3,7 +3,7 @@ import type { WalletLocked, WalletUnlocked } from 'fuels'; import { Wallet } from 'fuels'; const address = - 'fuel1fjett54ahnydhklerngqhclzmmkmp6s0xnykns8dwsdpjfg3r2rsfazpw5'; + '0x4cb2b5d2bdbcc8dbdbf91cd00be3e2deedb0ea0f34c969c0ed741a1925111a87'; const privateKey = '0x9deba03f08676716e3a4247797672d8008a5198d183048be65415ef89447b890'; diff --git a/apps/docs/src/guide/wallets/snippets/signing/sign-message.ts b/apps/docs/src/guide/wallets/snippets/signing/sign-message.ts index f1a8e0ab0a5..5528e1804b3 100644 --- a/apps/docs/src/guide/wallets/snippets/signing/sign-message.ts +++ b/apps/docs/src/guide/wallets/snippets/signing/sign-message.ts @@ -16,7 +16,7 @@ const hashedMessage = hashMessage(message); const recoveredAddress = Signer.recoverAddress(hashedMessage, signedMessage); // Example output: Address { -// bech32Address: 'fuel1za0wl90u09c6v88faqkvczu9r927kewvvr0asejv5xmdwtm98w0st7m2s3' +// b256Address: '0x6d309766c0f1c6f103d147b287fabecaedd31beb180d45cf1bf7d88397aecc6f' // } // #endregion signing-1 diff --git a/packages/account/src/predicate/predicate.ts b/packages/account/src/predicate/predicate.ts index 1bc90f4a05e..2e9dacdb4c0 100644 --- a/packages/account/src/predicate/predicate.ts +++ b/packages/account/src/predicate/predicate.ts @@ -48,7 +48,8 @@ export class Predicate< bytes: Uint8Array; predicateData: TData = [] as unknown as TData; interface: Interface; - + initialBytecode: Uint8Array; + configurableConstants: TConfigurables | undefined; /** * Creates an instance of the Predicate class. * @@ -73,8 +74,10 @@ export class Predicate< const address = Address.fromB256(getPredicateRoot(predicateBytes)); super(address, provider); + this.initialBytecode = arrayify(bytecode); this.bytes = predicateBytes; this.interface = predicateInterface; + this.configurableConstants = configurableConstants; if (data !== undefined && data.length > 0) { this.predicateData = data; } @@ -147,6 +150,23 @@ export class Predicate< return mainFn?.encodeArguments(this.predicateData) || new Uint8Array(); } + /** + * Creates a new Predicate instance from an existing Predicate instance. + * @param overrides - The data and configurable constants to override. + * @returns A new Predicate instance with the same bytecode, ABI and provider but with the ability to set the data and configurable constants. + */ + toNewInstance( + overrides: Pick, 'data' | 'configurableConstants'> = {} + ) { + return new Predicate({ + bytecode: this.initialBytecode, + abi: this.interface.jsonAbi, + provider: this.provider, + data: overrides.data ?? this.predicateData, + configurableConstants: overrides.configurableConstants ?? this.configurableConstants, + }); + } + /** * Processes the predicate data and returns the altered bytecode and interface. * diff --git a/packages/account/src/signer/signer.test.ts b/packages/account/src/signer/signer.test.ts index a6edf44d149..a24c9ef0593 100644 --- a/packages/account/src/signer/signer.test.ts +++ b/packages/account/src/signer/signer.test.ts @@ -11,7 +11,7 @@ describe('Signer', () => { const expectedPrivateKey = '0x5f70feeff1f229e4a95e1056e8b4d80d0b24b565674860cc213bdb07127ce1b1'; const expectedPublicKey = '0x2f34bc0df4db0ec391792cedb05768832b49b1aa3a2dd8c30054d1af00f67d00b74b7acbbf3087c8e0b1a4c343db50aa471d21f278ff5ce09f07795d541fb47e'; - const expectedAddress = 'fuel1785jcs4epy625cmjuv9u269rymmwv6s6q2y9jhnw877nj2j08ehqce3rxf'; + const expectedAddress = '0xf1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e'; const expectedMessage = 'my message'; const expectedB256Address = '0xf1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e'; const expectedSignedMessage = diff --git a/packages/account/src/wallet/keystore-wallet.test.ts b/packages/account/src/wallet/keystore-wallet.test.ts index c68d6331ac8..036f395f27b 100644 --- a/packages/account/src/wallet/keystore-wallet.test.ts +++ b/packages/account/src/wallet/keystore-wallet.test.ts @@ -14,7 +14,7 @@ describe('Keystore Wallet', () => { const privateKey = '0xeac85e732b683119e62fb52ce3b04c0d2f60539cd55af34c731fcdcf802e5ef4'; const address = Address.fromAddressOrString( - 'fuel1v77yj3g6xcatrhkcz72m2njx4cxxzgj8yepywz7ylf4fhkpptawqkh3dft' + '0x67bc49451a363ab1ded81795b54e46ae0c6122472642470bc4fa6a9bd8215f5c' ); const password = '123456'; diff --git a/packages/account/src/wallet/wallet-unlocked.test.ts b/packages/account/src/wallet/wallet-unlocked.test.ts index c6f4919a8ef..23975271f92 100644 --- a/packages/account/src/wallet/wallet-unlocked.test.ts +++ b/packages/account/src/wallet/wallet-unlocked.test.ts @@ -23,7 +23,7 @@ describe('WalletUnlocked', () => { const expectedPrivateKey = '0x5f70feeff1f229e4a95e1056e8b4d80d0b24b565674860cc213bdb07127ce1b1'; const expectedPublicKey = '0x2f34bc0df4db0ec391792cedb05768832b49b1aa3a2dd8c30054d1af00f67d00b74b7acbbf3087c8e0b1a4c343db50aa471d21f278ff5ce09f07795d541fb47e'; - const expectedAddress = 'fuel1785jcs4epy625cmjuv9u269rymmwv6s6q2y9jhnw877nj2j08ehqce3rxf'; + const expectedAddress = '0xf1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e'; const expectedMessage = 'my message'; const expectedSignedMessage = '0x8eeb238db1adea4152644f1cd827b552dfa9ab3f4939718bb45ca476d167c6512a656f4d4c7356bfb9561b14448c230c6e7e4bd781df5ee9e5999faa6495163d'; diff --git a/packages/address/README.md b/packages/address/README.md index 73b0cb482f7..26620e2a7f7 100644 --- a/packages/address/README.md +++ b/packages/address/README.md @@ -2,10 +2,7 @@ **@fuel-ts/address** is a sub-module for interacting with **Fuel**. -This module contains the utilities for encoding and decoding address and contract ids between Bech32 and other address formats. - -> [!NOTE] Note -> `Bech32` addresses like `fuel1..` are now deprecated. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) +This module contains the utilities for encoding and decoding address and contract ids between B256 and other address formats. # Table of contents diff --git a/packages/address/package.json b/packages/address/package.json index f82a413a602..717aea35601 100644 --- a/packages/address/package.json +++ b/packages/address/package.json @@ -41,7 +41,6 @@ "@fuel-ts/errors": "workspace:*", "@fuel-ts/interfaces": "workspace:*", "@fuel-ts/utils": "workspace:^", - "@noble/hashes": "^1.5.0", - "bech32": "^2.0.0" + "@noble/hashes": "^1.5.0" } } diff --git a/packages/address/src/address.test.ts b/packages/address/src/address.test.ts index 12e62237ba1..a168d1e9104 100644 --- a/packages/address/src/address.test.ts +++ b/packages/address/src/address.test.ts @@ -1,6 +1,6 @@ import { FuelError } from '@fuel-ts/errors'; import { expectToThrowFuelError } from '@fuel-ts/errors/test-utils'; -import type { AssetId, B256AddressEvm, Bech32Address, EvmAddress } from '@fuel-ts/interfaces'; +import type { AssetId, B256Address, B256AddressEvm, EvmAddress } from '@fuel-ts/interfaces'; import Address from './address'; import * as utils from './utils'; @@ -11,19 +11,12 @@ const ADDRESS_B256 = '0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3 const ADDRESS_B256_EVM_PADDED: B256AddressEvm = '0x00000000000000000000000007a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a'; const ADDRESS_EVM = '0x07a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a'; -const ADDRESS_BECH32: Bech32Address = - 'fuel1a7r2l2tfdncdccu9utzq0fhptxs3q080kl32up3klvea8je2ne9qrqnt6n'; const ADDRESS_CHECKSUM = '0xEf86Afa9696cF0Dc6385E2c407a6E159A1103CEfb7e2Ae0636fb33D3cb2A9e4a'; -const ADDRESS_WORDS = [ - 29, 30, 3, 10, 31, 10, 11, 9, 13, 19, 24, 13, 24, 24, 28, 5, 28, 11, 2, 0, 15, 9, 23, 1, 11, 6, - 16, 17, 0, 15, 7, 15, 22, 31, 17, 10, 28, 1, 17, 22, 31, 12, 25, 29, 7, 18, 25, 10, 19, 25, 5, 0, -]; const ADDRESS_BYTES = [ 239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161, 16, 60, 239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74, ]; -const expectedAddress = 'fuel1785jcs4epy625cmjuv9u269rymmwv6s6q2y9jhnw877nj2j08ehqce3rxf'; const expectedB256Address = '0xf1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6e3fbd392a4f3e6e'; /** @@ -31,51 +24,12 @@ const expectedB256Address = '0xf1e92c42b90934aa6372e30bc568a326f6e66a1a0288595e6 * @group browser */ describe('Address utils', () => { - test('fromBech32 (bech32 to decoded bech32)', () => { - const result = utils.fromBech32(ADDRESS_BECH32); - - expect(result).toEqual({ - prefix: utils.FUEL_BECH32_HRP_PREFIX, - words: ADDRESS_WORDS, - }); - }); - - test('normalizeBech32 (bech32 to lowercase bech32)', () => { - const result = utils.normalizeBech32(ADDRESS_BECH32.toUpperCase() as Bech32Address); - - expect(result).toEqual(ADDRESS_BECH32); - }); - - test('isBech32 (bech32)', () => { - const result = utils.isBech32(ADDRESS_BECH32); - - expect(result).toBeTruthy(); - }); - - test('isBech32 (b256)', () => { - const result = utils.isBech32(ADDRESS_B256); - - expect(result).toBeFalsy(); - }); - - test('isBech32 (bytes)', () => { - const result = utils.isBech32(new Uint8Array(ADDRESS_BYTES)); - - expect(result).toBeFalsy(); - }); - test('isB256 (b256)', () => { const result = utils.isB256(ADDRESS_B256); expect(result).toBeTruthy(); }); - test('isB256 (bech32)', () => { - const result = utils.isB256(ADDRESS_BECH32); - - expect(result).toBeFalsy(); - }); - test('isB256 (invalid chars)', () => { const result = utils.isB256(`${ADDRESS_B256}/?`); @@ -100,12 +54,6 @@ describe('Address utils', () => { expect(result).toBeFalsy(); }); - test('isB256 (using toB256)', () => { - const result = utils.isB256(utils.toB256(ADDRESS_BECH32)); - - expect(result).toBeTruthy(); - }); - test('isPublicKey (publicKey)', () => { const result = utils.isPublicKey(PUBLIC_KEY); @@ -166,43 +114,8 @@ describe('Address utils', () => { expect(result).toBeFalsy(); }); - test('getBytesFromBech32 (bech32 to Uint8Array)', () => { - const result = utils.getBytesFromBech32(ADDRESS_BECH32); - - expect(result).toEqual(new Uint8Array(ADDRESS_BYTES)); - }); - - test('toBech32 (b256 to bech32)', () => { - const result = utils.toBech32(ADDRESS_B256); - - expect(result).toEqual(ADDRESS_BECH32); - }); - - test('toB256 (bech32 to b256)', () => { - const result = utils.toB256(ADDRESS_BECH32); - - expect(result).toEqual(ADDRESS_B256); - }); - - test('toB256 (b256 to b256)', async () => { - const address = ADDRESS_B256 as Bech32Address; - const expectedError = new FuelError( - FuelError.CODES.INVALID_BECH32_ADDRESS, - `Invalid Bech32 Address: ${address}.` - ); - await expectToThrowFuelError(() => utils.toB256(address), expectedError); - }); - - test('toBech32=>toB256', () => { - const ADDRESS = '0x000000000000000000000000000000000000000000000000000000000000002a'; - const result = utils.toBech32(ADDRESS); - const finalResult = utils.toB256(result); - - expect(finalResult).toEqual(ADDRESS); - }); - test('clearFirst12BytesFromB256 (b256 to evm b256)', () => { - const result = utils.clearFirst12BytesFromB256(ADDRESS_B256); + const result = utils.toB256AddressEvm(ADDRESS_B256); expect(result).toEqual(ADDRESS_B256_EVM_PADDED); }); @@ -213,7 +126,7 @@ describe('Address utils', () => { FuelError.CODES.PARSE_FAILED, `Cannot generate EVM Address B256 from: ${invalidB256}.` ); - await expectToThrowFuelError(() => utils.clearFirst12BytesFromB256(invalidB256), expectedError); + await expectToThrowFuelError(() => utils.toB256AddressEvm(invalidB256), expectedError); }); test('padFirst12BytesOfEvmAddress (evm Address to b256)', () => { @@ -237,9 +150,9 @@ describe('Address utils', () => { describe('Address class', () => { test('instantiate an Address class', () => { - const result = new Address(ADDRESS_BECH32.toUpperCase() as Bech32Address); + const result = new Address(ADDRESS_B256.toUpperCase() as B256Address); - expect(result.toAddress()).toEqual(ADDRESS_BECH32); + expect(result.toAddress()).toEqual(ADDRESS_B256); expect(result.toString()).toEqual(ADDRESS_CHECKSUM); expect(`cast as string${result}`).toEqual(`cast as string${ADDRESS_CHECKSUM}`); expect(result.toB256()).toEqual(ADDRESS_B256); @@ -247,8 +160,8 @@ describe('Address class', () => { }); test('instance equality', () => { - const resultA = new Address(ADDRESS_BECH32); - const resultB = new Address(ADDRESS_BECH32.toUpperCase() as Bech32Address); + const resultA = new Address(ADDRESS_B256); + const resultB = new Address(ADDRESS_B256.toUpperCase() as B256Address); expect(resultA).toEqual(resultB); expect(resultA.equals(resultB)).toBeTruthy(); @@ -258,7 +171,7 @@ describe('Address class', () => { test('create an Address class using public key', () => { const address = Address.fromPublicKey(PUBLIC_KEY); - expect(address.toAddress()).toEqual(expectedAddress); + expect(address.toAddress()).toEqual(expectedB256Address); expect(address.toB256()).toEqual(expectedB256Address); }); @@ -275,7 +188,7 @@ describe('Address class', () => { test('create an Address class using b256Address', () => { const address = Address.fromB256(ADDRESS_B256); - expect(address.toAddress()).toEqual(ADDRESS_BECH32); + expect(address.toAddress()).toEqual(ADDRESS_B256); expect(address.toB256()).toEqual(ADDRESS_B256); }); @@ -289,13 +202,13 @@ describe('Address class', () => { await expectToThrowFuelError(() => Address.fromB256(address), expectedError); }); - test('when parsing to JSON it should show the bech32 address', () => { + test('when parsing to JSON it should show the b256 address', () => { const result = Address.fromB256(expectedB256Address); - expect(JSON.stringify(result)).toEqual(`"${expectedAddress}"`); + expect(JSON.stringify(result)).toEqual(`"${expectedB256Address}"`); }); test('valueOf matches toString', () => { - const address = new Address(ADDRESS_BECH32); + const address = new Address(ADDRESS_B256); expect(address.toString()).toEqual(address.valueOf()); }); @@ -303,18 +216,18 @@ describe('Address class', () => { test('create an Address class fromDynamicInput [public key]', () => { const address = Address.fromDynamicInput(PUBLIC_KEY); - expect(address.toAddress()).toEqual(expectedAddress); + expect(address.toAddress()).toEqual(expectedB256Address); expect(address.toB256()).toEqual(expectedB256Address); }); test('create an Address class fromDynamicInput [b256Address]', () => { const address = Address.fromDynamicInput(expectedB256Address); - expect(address.toAddress()).toEqual(expectedAddress); + expect(address.toAddress()).toEqual(expectedB256Address); }); - test('create an Address class fromDynamicInput [bech32Address]', () => { - const address = Address.fromDynamicInput(expectedAddress); + test('create an Address class fromDynamicInput [b256Address]', () => { + const address = Address.fromDynamicInput(expectedB256Address); expect(address.toB256()).toEqual(expectedB256Address); }); @@ -328,7 +241,7 @@ describe('Address class', () => { test('create an Address class fromDynamicInput [bad input]', async () => { const expectedError = new FuelError( FuelError.CODES.PARSE_FAILED, - `Unknown address format: only 'Bech32', 'B256', or 'Public Key (512)' are supported.` + `Unknown address format: only 'B256', or 'Public Key (512)' are supported.` ); await expectToThrowFuelError(() => Address.fromDynamicInput('badinput'), expectedError); }); @@ -390,7 +303,7 @@ describe('Address class', () => { test('validate checksum address for invalid types', () => { const address = Address.fromRandom(); - expect(Address.isChecksumValid(address.toB256())).toBeFalsy(); + expect(Address.isChecksumValid(address.toB256().toLowerCase())).toBeFalsy(); expect( Address.isChecksumValid('0x9cfB2CAd509D417ec40b70ebE1DD72a3624D46fdD1Ea5420dBD755CE7f4dc897') ).toBeFalsy(); diff --git a/packages/address/src/address.ts b/packages/address/src/address.ts index 6f99a248fe5..c6ac5de0744 100644 --- a/packages/address/src/address.ts +++ b/packages/address/src/address.ts @@ -1,27 +1,17 @@ import { FuelError } from '@fuel-ts/errors'; import { AbstractAddress } from '@fuel-ts/interfaces'; -import type { - Bech32Address, - B256Address, - EvmAddress, - AssetId, - ChecksumAddress, -} from '@fuel-ts/interfaces'; +import type { B256Address, EvmAddress, AssetId, ChecksumAddress } from '@fuel-ts/interfaces'; import { arrayify, hexlify } from '@fuel-ts/utils'; import { sha256 } from '@noble/hashes/sha256'; import { - normalizeBech32, - isBech32, - toB256, - getBytesFromBech32, - toBech32, getRandomB256, isPublicKey, isB256, - clearFirst12BytesFromB256, isEvmAddress, padFirst12BytesOfEvmAddress, + toB256AddressEvm, + normalizeB256, } from './utils'; /** @@ -30,31 +20,23 @@ import { */ export default class Address extends AbstractAddress { // #region address-2 - /** - * @deprecated - * Type `Bech32Address` is now deprecated, as is this property. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) - */ - readonly bech32Address: Bech32Address; + readonly b256Address: B256Address; // #endregion address-2 /** - * @param address - A Bech32 address or B256 address + * @param address - A B256 address */ - constructor(address: Bech32Address | B256Address) { + constructor(address: B256Address) { super(); - if (isB256(address)) { - this.bech32Address = toBech32(address); - } else { - this.bech32Address = normalizeBech32(address as Bech32Address); - - if (!isBech32(this.bech32Address)) { - throw new FuelError( - FuelError.CODES.INVALID_BECH32_ADDRESS, - `Invalid Bech32 Address: ${this.bech32Address}.` - ); - } + if (!isB256(address)) { + throw new FuelError( + FuelError.CODES.INVALID_B256_ADDRESS, + `Invalid B256 Address: ${address}.` + ); } + + this.b256Address = normalizeB256(address); } /** @@ -64,38 +46,38 @@ export default class Address extends AbstractAddress { * @returns A new `ChecksumAddress` instance */ toChecksum(): ChecksumAddress { - return Address.toChecksum(this.toB256()); + return Address.toChecksum(this.b256Address); } /** - * Returns the `bech32Address` property - * @deprecated - * Type `Bech32Address` is now deprecated, as is this method. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) - * @returns The `bech32Address` property + * Returns the `b256Address` property */ - toAddress(): Bech32Address { - return this.bech32Address; + toAddress(): B256Address { + return this.b256Address; } /** - * Converts and returns the `bech32Address` property to a 256 bit hash string - * @returns The `bech32Address` property as a 256 bit hash string + * Returns the B256 hash address as a string + * + * @returns The B256 address */ toB256(): B256Address { - return toB256(this.bech32Address); + return this.b256Address; } /** - * Converts and returns the `bech32Address` property to a byte array - * @returns The `bech32Address` property as a byte array + * Returns the B256 hash address as a Uint8Array + * + * @returns The B256 address as a Uint8Array */ toBytes(): Uint8Array { - return getBytesFromBech32(this.bech32Address); + return arrayify(this.b256Address); } /** - * Converts the `bech32Address` property to a 256 bit hash string - * @returns The `bech32Address` property as a 256 bit hash string + * Returns the B256 hash address as a string + * + * @returns The B256 address */ toHexString(): B256Address { return this.toB256(); @@ -104,29 +86,28 @@ export default class Address extends AbstractAddress { /** * returns the address `checksum` as a string * - * @returns The `bech32Address` property as a string + * @returns The `b256Address` property as a string */ toString(): string { return this.toChecksum(); } /** - * Converts and returns the `bech32Address` property as a string - * @returns The `bech32Address` property as a JSON string + * Converts and returns the `b256Address` property as a string + * @returns The `b256Address` property as a JSON string */ toJSON(): string { - return this.bech32Address; + return this.b256Address; } /** - * Clears the first 12 bytes of the `bech32Address` property and returns it as a `EvmAddress` - * @returns The `bech32Address` property as an {@link EvmAddress | `EvmAddress`} + * Converts to an EVM address + * + * @returns an {@link EvmAddress | `EvmAddress`} representation of the address */ toEvmAddress(): EvmAddress { - const b256Address = toB256(this.bech32Address); - return { - bits: clearFirst12BytesFromB256(b256Address), + bits: toB256AddressEvm(this.b256Address), } as EvmAddress; } @@ -136,7 +117,7 @@ export default class Address extends AbstractAddress { */ toAssetId(): AssetId { return { - bits: this.toB256(), + bits: this.b256Address, } as AssetId; } @@ -149,12 +130,12 @@ export default class Address extends AbstractAddress { } /** - * Compares this the `bech32Address` property to another for direct equality + * Compares this the `b256Address` property to another for direct equality * @param other - Another address to compare against * @returns The equality of the comparison */ equals(other: Address): boolean { - return this.bech32Address === other.bech32Address; + return this.toChecksum() === other.toChecksum(); } /** @@ -169,7 +150,7 @@ export default class Address extends AbstractAddress { } const b256Address = hexlify(sha256(arrayify(publicKey))); - return new Address(toBech32(b256Address)); + return new Address(b256Address); } /** @@ -186,11 +167,11 @@ export default class Address extends AbstractAddress { ); } - return new Address(toBech32(b256Address)); + return new Address(b256Address); } /** - * Creates an `Address` with a randomized `bech32Address` property + * Creates an `Address` with a randomized `b256Address` property * * @returns A new `Address` instance */ @@ -205,7 +186,7 @@ export default class Address extends AbstractAddress { * @returns A new `Address` instance */ static fromString(address: string): Address { - return isBech32(address) ? new Address(address as Bech32Address) : this.fromB256(address); + return this.fromB256(address); } /** @@ -220,7 +201,7 @@ export default class Address extends AbstractAddress { /** * Takes a dynamic string or `AbstractAddress` and creates an `Address` * - * @param addressId - A string containing Bech32, B256, or Public Key + * @param addressId - A string containing B256, or Public Key * @throws Error - Unknown address if the format is not recognised * @returns A new `Address` instance */ @@ -235,10 +216,6 @@ export default class Address extends AbstractAddress { return Address.fromPublicKey(address); } - if (isBech32(address)) { - return new Address(address as Bech32Address); - } - if (isB256(address)) { return Address.fromB256(address); } @@ -249,7 +226,7 @@ export default class Address extends AbstractAddress { throw new FuelError( FuelError.CODES.PARSE_FAILED, - `Unknown address format: only 'Bech32', 'B256', or 'Public Key (512)' are supported.` + `Unknown address format: only 'B256', or 'Public Key (512)' are supported.` ); } @@ -267,8 +244,7 @@ export default class Address extends AbstractAddress { } const paddedAddress = padFirst12BytesOfEvmAddress(evmAddress); - - return new Address(toBech32(paddedAddress)); + return new Address(paddedAddress); } /** diff --git a/packages/address/src/utils.ts b/packages/address/src/utils.ts index 8123b22c8f9..9f4b7be00e0 100644 --- a/packages/address/src/utils.ts +++ b/packages/address/src/utils.ts @@ -2,61 +2,13 @@ import { randomBytes } from '@fuel-ts/crypto'; import { FuelError } from '@fuel-ts/errors'; import { AbstractContract, AbstractAccount } from '@fuel-ts/interfaces'; import type { - Bech32Address, B256Address, AddressLike, ContractIdLike, AbstractAddress, B256AddressEvm, - BytesLike, } from '@fuel-ts/interfaces'; -import { arrayify, hexlify } from '@fuel-ts/utils'; -import type { Decoded } from 'bech32'; -import { bech32m } from 'bech32'; - -/** - * Fuel Network HRP (human-readable part) for bech32 encoding - * - * @hidden - */ -export const FUEL_BECH32_HRP_PREFIX = 'fuel'; - -/** - * Decodes a Bech32 address string into Decoded - * @deprecated - * Type `Bech32Address` is now deprecated, as is this function. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) - * @hidden - */ -export function fromBech32(address: Bech32Address): Decoded { - return bech32m.decode(address); -} - -/** - * Converts a B256 address string into Bech32 - * @deprecated - * Type `Bech32Address` is now deprecated, as is this function. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) - * @hidden - */ -export function toBech32(address: B256Address): Bech32Address { - return bech32m.encode( - FUEL_BECH32_HRP_PREFIX, - bech32m.toWords(arrayify(hexlify(address))) - ) as Bech32Address; -} - -/** - * Determines if a given string is Bech32 format - * @deprecated - * Type `Bech32Address` is now deprecated, as is this function. Use `B256` addresses instead. ([help](https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256)) - * @hidden - */ -export function isBech32(address: BytesLike): boolean { - return ( - typeof address === 'string' && - address.indexOf(FUEL_BECH32_HRP_PREFIX + 1) === 0 && - fromBech32(address as Bech32Address).prefix === FUEL_BECH32_HRP_PREFIX - ); -} +import { arrayify, concat, hexlify } from '@fuel-ts/utils'; /** * Determines if a given string is B256 format @@ -85,42 +37,8 @@ export function isEvmAddress(address: string): boolean { return address.length === 42 && /(0x)[0-9a-f]{40}$/i.test(address); } -/** - * Takes a Bech32 address and returns the byte data - * @deprecated - * The `bech32Address` is now deprecated. Please migrate to B256 format (see https://docs.fuel.network/docs/specs/abi/argument-encoding/#b256 for more details) as this will be the standard going forward. - * @hidden - */ -export function getBytesFromBech32(address: Bech32Address): Uint8Array { - return new Uint8Array(bech32m.fromWords(fromBech32(address).words)); -} - -/** - * Converts a Bech32 address string into B256 - * @hidden - */ -export function toB256(address: Bech32Address): B256Address { - if (!isBech32(address)) { - throw new FuelError( - FuelError.CODES.INVALID_BECH32_ADDRESS, - `Invalid Bech32 Address: ${address}.` - ); - } - - return hexlify(getBytesFromBech32(address)); -} - -/** - * Takes a Bech32 address and returns a normalized (i.e. lower case) representation of it. - * - * The input is validated along the way, which makes this significantly safer than - * using `address.toLowerCase()`. - * - * @hidden - */ -export function normalizeBech32(address: Bech32Address): Bech32Address { - const { words } = fromBech32(address); - return bech32m.encode(FUEL_BECH32_HRP_PREFIX, words) as Bech32Address; +export function normalizeB256(address: B256Address): B256Address { + return address.toLowerCase(); } /** @@ -153,27 +71,21 @@ export const getRandomB256 = () => hexlify(randomBytes(32)); * * @hidden */ -export const clearFirst12BytesFromB256 = (b256: B256Address): B256AddressEvm => { - let bytes; - +export const toB256AddressEvm = (b256: B256Address): B256AddressEvm => { try { if (!isB256(b256)) { - throw new FuelError( - FuelError.CODES.INVALID_BECH32_ADDRESS, - `Invalid Bech32 Address: ${b256}.` - ); + throw new FuelError(FuelError.CODES.INVALID_B256_ADDRESS, `Invalid B256 Address: ${b256}.`); } - bytes = getBytesFromBech32(toBech32(b256)); - bytes = hexlify(bytes.fill(0, 0, 12)) as B256AddressEvm; + const evmBytes = arrayify(b256).slice(12); + const paddedBytes = new Uint8Array(12).fill(0); + return hexlify(concat([paddedBytes, evmBytes])) as B256AddressEvm; } catch (error) { throw new FuelError( FuelError.CODES.PARSE_FAILED, `Cannot generate EVM Address B256 from: ${b256}.` ); } - - return bytes; }; /** diff --git a/packages/create-fuels/src/cli.ts b/packages/create-fuels/src/cli.ts index 6b33723e20a..2b9078f83c6 100644 --- a/packages/create-fuels/src/cli.ts +++ b/packages/create-fuels/src/cli.ts @@ -63,7 +63,7 @@ export const runScaffoldCli = async ({ let projectPath = program.args[0] ?? (await promptForProjectPath()); const verboseEnabled = opts.verbose ?? false; - const packageManager = getPackageManager(opts); + const packageManager = getPackageManager(); if (!process.env.VITEST) { await tryInstallFuelUp(verboseEnabled); diff --git a/packages/create-fuels/src/lib/getPackageManager.test.ts b/packages/create-fuels/src/lib/getPackageManager.test.ts index 9fb4b0fb780..5eab1e42f71 100644 --- a/packages/create-fuels/src/lib/getPackageManager.test.ts +++ b/packages/create-fuels/src/lib/getPackageManager.test.ts @@ -3,14 +3,6 @@ import { mockLogger } from '../../test/utils/mockLogger'; import type { PackageManager } from './getPackageManager'; import { availablePackageManagers, getPackageManager, packageMangers } from './getPackageManager'; -const mockAllDeps = () => { - const { warn } = mockLogger(); - - return { - warn, - }; -}; - const installScenarios: [PackageManager, string][] = [ ['pnpm', 'pnpm install'], ['npm', 'npm install'], @@ -24,17 +16,30 @@ const runScenarios: [PackageManager, string][] = [ ['bun', 'bun run fuels:dev'], ]; +const mockAllDeps = () => { + const { warn } = mockLogger(); + + return { + warn, + }; +}; + /** * @group node */ describe('getPackageManager', () => { + beforeEach(() => { + delete process.env.npm_config_user_agent; + }); + it.each(availablePackageManagers)( `should get the correct package manager for %s`, (packageManager: PackageManager) => { const expectedPackageManager = packageMangers[packageManager]; - const opts = { [packageManager]: true }; - const result = getPackageManager(opts); + process.env.npm_config_user_agent = packageManager; + + const result = getPackageManager(); expect(result).toEqual(expectedPackageManager); } @@ -43,7 +48,9 @@ describe('getPackageManager', () => { it.each(installScenarios)( 'should have the correct install commands', (packageManager, expectedInstallCommand) => { - const command = getPackageManager({ [packageManager]: true }); + process.env.npm_config_user_agent = packageManager; + + const command = getPackageManager(); const install = command.install; @@ -54,7 +61,9 @@ describe('getPackageManager', () => { it.each(runScenarios)( 'should have the correct run commands', (packageManager, expectedRunCommand) => { - const command = getPackageManager({ [packageManager]: true }); + process.env.npm_config_user_agent = packageManager; + + const command = getPackageManager(); const run = command.run(runCommand); @@ -62,24 +71,14 @@ describe('getPackageManager', () => { } ); - it('should warn the user if more than one package manager selected', () => { - const { warn } = mockAllDeps(); - const opts = { pnpm: true, npm: true }; - - getPackageManager(opts); - - expect(warn).toBeCalledWith('More than one package manager was selected.'); - }); - - it('should default to npm if no package manager is selected', () => { + it('should default to npm', () => { const packageManager = 'npm'; const expectedPackageManager = packageMangers[packageManager]; const { warn } = mockAllDeps(); - const opts = {}; - const result = getPackageManager(opts); + const result = getPackageManager(); - expect(warn).not.toBeCalled(); expect(result).toEqual(expectedPackageManager); + expect(warn).toHaveBeenCalledWith(`This package manager is not supported. Using npm instead.`); }); }); diff --git a/packages/create-fuels/src/lib/getPackageManager.ts b/packages/create-fuels/src/lib/getPackageManager.ts index f1982f13b84..fcbc60fc84d 100644 --- a/packages/create-fuels/src/lib/getPackageManager.ts +++ b/packages/create-fuels/src/lib/getPackageManager.ts @@ -1,7 +1,5 @@ import { warn } from '../utils/logger'; -import type { ProgramOptions } from './setupProgram'; - export const availablePackageManagers = ['pnpm', 'npm', 'bun'] as const; export type PackageManager = (typeof availablePackageManagers)[number]; @@ -10,39 +8,53 @@ const runnableApplicator = (command: string = '') => `${commandPrefix} ${command}`; -export const packageMangers = { +export const packageMangers: Record< + PackageManager, + { + install: string; + run: (command: string) => string; + name: PackageManager; + } +> = { pnpm: { install: 'pnpm install', run: runnableApplicator('pnpm'), + name: 'pnpm', }, npm: { install: 'npm install', run: runnableApplicator('npm run'), + name: 'npm', }, bun: { install: 'bun install', run: runnableApplicator('bun run'), + name: 'bun', }, } as const; -export const getPackageManager = (opts: ProgramOptions) => { - const packageMangerOpts = { - pnpm: opts.pnpm, - npm: opts.npm, - bun: opts.bun, - }; +export function getUserPkgManager(): PackageManager { + const userAgent = process.env.npm_config_user_agent || ''; - const cliChosenPackageManagerSelected = Object.entries(packageMangerOpts) - .filter(([, v]) => v) - .map(([k]) => k) as PackageManager[]; + if (userAgent.startsWith(packageMangers.pnpm.name)) { + return packageMangers.pnpm.name; + } - let packageManager: PackageManager | undefined = cliChosenPackageManagerSelected[0]; - if (cliChosenPackageManagerSelected.length > 1) { - warn('More than one package manager was selected.'); + if (userAgent.startsWith(packageMangers.bun.name)) { + return packageMangers.bun.name; } - if (!packageManager) { - packageManager = 'npm'; // default to npm if the user has not specified a package manager (eg. --pnpm, --bun) + if (userAgent.startsWith(packageMangers.npm.name)) { + return packageMangers.npm.name; } + + warn(`This package manager is not supported. Using npm instead.`); + + return packageMangers.npm.name; +} + +export const getPackageManager = () => { + const packageManager = getUserPkgManager(); + return packageMangers[packageManager]; }; diff --git a/packages/create-fuels/src/lib/setupProgram.test.ts b/packages/create-fuels/src/lib/setupProgram.test.ts index 642afdce40c..f63913dc072 100644 --- a/packages/create-fuels/src/lib/setupProgram.test.ts +++ b/packages/create-fuels/src/lib/setupProgram.test.ts @@ -6,20 +6,8 @@ import { setupProgram } from './setupProgram'; describe('setupProgram', () => { test('setupProgram takes in args properly', () => { const program = setupProgram(); - program.parse([ - '', - '', - 'test-project-name', - '--template', - 'nextjs', - '--pnpm', - '--npm', - '--bun', - ]); + program.parse(['', '', 'test-project-name', '--template', 'nextjs']); expect(program.args[0]).toBe('test-project-name'); - expect(program.opts().pnpm).toBe(true); - expect(program.opts().npm).toBe(true); - expect(program.opts().bun).toBe(true); expect(program.opts().install).toBe(true); expect(program.opts().template).toBe('nextjs'); }); diff --git a/packages/create-fuels/src/lib/setupProgram.ts b/packages/create-fuels/src/lib/setupProgram.ts index 7576240c803..009ba4ce257 100644 --- a/packages/create-fuels/src/lib/setupProgram.ts +++ b/packages/create-fuels/src/lib/setupProgram.ts @@ -10,9 +10,6 @@ export interface ProgramOptions { contract?: boolean; predicate?: boolean; script?: boolean; - pnpm?: boolean; - npm?: boolean; - bun?: boolean; verbose?: boolean; install?: boolean; template?: Template; @@ -22,9 +19,6 @@ export const setupProgram = () => { const program = new Command(packageJson.name) .version(packageJson.version) .arguments('[projectDirectory]') - .option('--pnpm', 'Use pnpm to install dependencies') - .option('--npm', 'Use npm to install dependencies') - .option('--bun', 'Use bun to install dependencies') .option('--verbose', 'Enable verbose logging') .option('--no-install', 'Do not install dependencies') .option('--template