diff --git a/docs/docs/guides/getting_started/return-formats.md b/docs/docs/guides/getting_started/return-formats.md new file mode 100644 index 00000000000..ae4287a8336 --- /dev/null +++ b/docs/docs/guides/getting_started/return-formats.md @@ -0,0 +1,121 @@ +--- +sidebar_position: 3 +sidebar_label: Return Formats +--- + +# Return Formats + +By default, Web3.js formats byte values as hexadecimal strings (e.g. `"0x221`") and number values as [`BigInt`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). The default formats can be configured at the global level by updating the [`defaultReturnFormat` configuration option](/guides/web3_config/#defaultreturnformat). Many Web3.js functions (e.g. [`getBlock`](/api/web3-eth/function/getBlock), [`sendTransaction`](/api/web3-eth/function/sendTransaction)) accept an optional parameter named `returnFormat` of the [type `DataFormat`](/api/web3-types#DataFormat) that can be used to configure the format for data returned by that single function invocation. + +The following example demonstrates working with return formats: + +```ts +import { Block, FMT_BYTES, FMT_NUMBER, Numbers, Web3 } from "web3"; + +const web3 = new Web3("https://eth.llamarpc.com"); + +// use the default return format +web3.eth.getBlock().then((block: Block) => { + console.log(`Block #${block.number} Hash: ${block.hash}`); +}); +// ↳ Block #20735255 Hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 + +// specify the return format for a single function invocation +web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.HEX, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); +// ↳ Block #0x13c6517 + +// configure default return format for the web3-eth package +web3.eth.defaultReturnFormat = { + bytes: FMT_BYTES.UINT8ARRAY, + number: FMT_NUMBER.HEX, +}; + +web3.eth.getBlock().then((block: Block) => { + console.log(`Block #${block.number} Hash: [${block.hash}]`); +}); +// ↳ Block #0x13c6517 Hash: [186,234,109,...,162,62,34] +``` + +The supported return formats are: + +- Bytes + - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + ```ts + web3.eth + .getBlock(undefined, undefined, { + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + }) + .then((block: Block) => { + console.log(`Block hash: ${block.hash}`); + }); + // ↳ Block hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 + ``` + - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) + ```ts + web3.eth + .getBlock(undefined, undefined, { + bytes: FMT_BYTES.UINT8ARRAY, + number: FMT_NUMBER.BIGINT, + }) + .then((block: Block) => { + console.log(`Block hash: [${block.hash}]`); + }); + // ↳ Block hash: [186,234,109,...,162,62,34] + ``` +- Numbers + - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` + - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.HEX, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #0x13c6517 + ``` + - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.NUMBER, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` + - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.STR, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` diff --git a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md b/docs/docs/guides/web3_utils_module/mastering_web3-utils.md index c1ea5b833f7..b60d2a50deb 100644 --- a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md +++ b/docs/docs/guides/web3_utils_module/mastering_web3-utils.md @@ -240,3 +240,70 @@ console.log(web3.utils.compareBlockNumbers(2, 2)); // 0 ``` +### Formatting + +The [`format` function](/api/web3-utils/function/format) in the `web3-utils` package is used to convert data between equivalent formats. For example, bytes that are represented as a [`Uint8Array` type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) can be formatted as a hexademical string (e.g. `"0xdd"`) or primitive JavaScript [`Number` types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) can be formatted as [`BigInt` types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). The `format` function expects two required parameters, `schema` and `data`, and accepts a third optional parameter, `returnFormat`. The `schema` parameter is used to describe how the data should be interpreted. The `data` parameter represents the data that is to be formatted. The [`returnFormat` parameter](#return-formats) specifies how the data should be formatted. + +Here are some example that demonstrate the use of the `format` function: + +```js +import { format } from "web3-utils"; +import { FMT_BYTES, FMT_NUMBER } from "web3-types"; + +// format a primitive number as a hexidecimal string +console.log(format({ format: "uint" }, 221, { number: FMT_NUMBER.HEX })); +// ↳ 0xdd + +// format a primitive number as a BigInt +console.log(format({ format: "uint" }, 221, { number: FMT_NUMBER.BIGINT })); +// ↳ 221n + +// format a stringified number as a hexidecimal string +console.log(format({ format: "uint" }, "221", { number: FMT_NUMBER.HEX })); +// ↳ 0xdd + +// format a Uint8Array of bytes as a hexidecimal string +console.log( + format({ format: "bytes" }, new Uint8Array([2, 33]), { + bytes: FMT_BYTES.HEX, + }), +); +// ↳ 0x0221 + +// format an array of values +console.log( + format({ type: "array", items: { format: "uint" } }, ["221", 1983], { + number: FMT_NUMBER.HEX, + }), +); +// ↳ [ '0xdd', '0x7bf' ] + +// format an object with multiple properties +console.log( + format( + { + type: "object", + properties: { + aNumber: { format: "uint" }, + someBytes: { format: "bytes" }, + }, + }, + { aNumber: "221", someBytes: new Uint8Array([2, 33]) }, + { bytes: FMT_BYTES.UINT8ARRAY, number: FMT_NUMBER.HEX }, + ), +); +// ↳ { aNumber: '0xdd', someBytes: Uint8Array(2) [ 2, 33 ] } +``` + +#### Return Formats + +The following return formats are supported: + +- Bytes + - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) +- Numbers + - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) + - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) + - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) diff --git a/packages/web3-types/src/data_format_types.ts b/packages/web3-types/src/data_format_types.ts index 46c1f5352b8..b94521b935e 100644 --- a/packages/web3-types/src/data_format_types.ts +++ b/packages/web3-types/src/data_format_types.ts @@ -41,6 +41,11 @@ export type ByteTypes = { [FMT_BYTES.UINT8ARRAY]: Uint8Array; }; +/** + * Used to specify how data should be formatted. Bytes can be formatted as hexadecimal strings or + * Uint8Arrays. Numbers can be formatted as BigInts, hexadecimal strings, primitive numbers, or + * strings. + */ export type DataFormat = { readonly number: FMT_NUMBER; readonly bytes: FMT_BYTES; diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts index 5050a26ef7d..9457d7e78c3 100644 --- a/packages/web3-utils/src/formatter.ts +++ b/packages/web3-utils/src/formatter.ts @@ -349,6 +349,27 @@ export const convert = ( return object; }; +/** + * Given data that can be interpreted according to the provided schema, returns equivalent data that has been formatted + * according to the provided return format. + * + * @param schema - how to interpret the data + * @param data - data to be formatted + * @param returnFormat - how to format the data + * @returns - formatted data + * + * @example + * + * ```js + * import { FMT_NUMBER, utils } from "web3"; + * + * console.log( + * utils.format({ format: "uint" }, "221", { number: FMT_NUMBER.HEX }), + * ); + * // 0xdd + * ``` + * + */ export const format = < DataType extends Record | unknown[] | unknown, ReturnType extends DataFormat,