diff --git a/docs/sdk-and-tools/sdk-js/extending-sdk-js.md b/docs/sdk-and-tools/sdk-js/extending-sdk-js.md index 13b15aa68..c5f2c79c1 100644 --- a/docs/sdk-and-tools/sdk-js/extending-sdk-js.md +++ b/docs/sdk-and-tools/sdk-js/extending-sdk-js.md @@ -1,6 +1,7 @@ --- id: extending-sdk-js title: Extending sdk-js +pagination_prev: sdk-and-tools/sdk-js/sdk-js --- [comment]: # (mx-abstract) diff --git a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook.md b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v12.md similarity index 99% rename from docs/sdk-and-tools/sdk-js/sdk-js-cookbook.md rename to docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v12.md index 097f3e1c5..aa3b9d888 100644 --- a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook.md +++ b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v12.md @@ -1,6 +1,7 @@ --- -id: sdk-js-cookbook -title: Cookbook +id: sdk-js-cookbook-v12 +title: Cookbook (v12) +pagination_next: sdk-and-tools/sdk-js/extending-sdk-js --- [comment]: # (mx-abstract) @@ -8,7 +9,7 @@ title: Cookbook This page will guide you through the process of handling common tasks using **sdk-js**. :::important -This cookbook makes use of `sdk-js 12`. In order to migrate from `sdk-js 11.x` to `sdk-js 12`, please follow [the migration guide](/sdk-and-tools/sdk-js/sdk-js-migration-guides). +This cookbook makes use of `sdk-js v12`. In order to migrate from `sdk-js v11.x` to `sdk-js v12`, please follow [the migration guide](/sdk-and-tools/sdk-js/sdk-js-migration-guides). ::: diff --git a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v13.md b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v13.md new file mode 100644 index 000000000..4ceb7afb3 --- /dev/null +++ b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v13.md @@ -0,0 +1,305 @@ +--- +id: sdk-js-cookbook-v13 +title: Cookbook (v13) +pagination_next: null +pagination_prev: sdk-and-tools/sdk-js/sdk-js-cookbook-versions +--- + +[comment]: # (mx-abstract) + +This page will guide you through the process of handling common tasks using **upcoming versions** of **sdk-js**. + +:::important +This cookbook makes use of `sdk-js v13`. In order to migrate from `sdk-js v12.x` to `sdk-js v13`, please also follow [the migration guide](https://github.com/multiversx/mx-sdk-js-core/issues/392). +::: + +:::important +This page is a work in progress. Please check back later for more content. +::: + +## Creating network providers + +Creating an API provider: + +``` +import { ApiNetworkProvider } from "@multiversx/sdk-network-providers"; + +const apiNetworkProvider = new ApiNetworkProvider("https://devnet-api.multiversx.com"); +``` + +Creating a Proxy provider: + +``` +import { ProxyNetworkProvider } from "@multiversx/sdk-network-providers"; + +const proxyNetworkProvider = new ProxyNetworkProvider("https://devnet-gateway.multiversx.com"); +``` + +Use the classes from `@multiversx/sdk-network-providers` **only as a starting point**. +As your dApp matures, make sure you **switch to using your own network provider**, tailored to your requirements +(whether deriving from the default ones or writing a new one, from scratch) that directly interacts with the MultiversX API (or Gateway). + +On this topic, please see [extending sdk-js](https://docs.multiversx.com/sdk-and-tools/sdk-js/extending-sdk-js). + +## Fetching network parameters + +``` +const networkConfig = await apiNetworkProvider.getNetworkConfig(); +console.log(networkConfig.MinGasPrice); +console.log(networkConfig.ChainID); +``` + +## Working with accounts + +### Synchronizing an account object + +The following snippet fetches (from the Network) the **nonce** and the **balance** of an account, and updates the local representation of the account. + +``` +import { Account } from "@multiversx/sdk-core"; + +const alice = new Account(addressOfAlice); +const aliceOnNetwork = await apiNetworkProvider.getAccount(addressOfAlice); +alice.update(aliceOnNetwork); + +console.log("Nonce:", alice.nonce); +console.log("Balance:", alice.balance.toString()); +``` + +### Managing the sender nonce locally + +When sending a bunch of transactions, you usually have to first fetch the account nonce from the network (see above), then manage it locally (e.g. increment upon signing & broadcasting a transaction): + +``` +alice.incrementNonce(); +console.log("Nonce:", alice.nonce); +``` + +:::note +Since `sdk-core v13`, the `Transaction` class exhibits its state as public read-write properties. For example, you can access and set the `nonce` property, instead of using `getNonce` and `setNonce`. +::: + +If you are using `sdk-core v13` or later, use `tx.nonce = ` to apply the nonce to a transaction. +For `sdk-core v12` or earlier, use the legacy `tx.setNonce()` to apply the nonce to a transaction. + +``` + +notYetSignedTx.nonce = alice.getNonceThenIncrement(); +``` + +For further reference, please see [nonce management](https://docs.multiversx.com/integrators/creating-transactions/#nonce-management). +## Broadcasting transactions + +### Preparing a simple transaction + +:::note +Since `sdk-core v13`, the `Transaction` class exhibits its state as public read-write properties. For example, you can access and set the `nonce` property, instead of using `getNonce` and `setNonce`. +::: + +``` +import { Transaction } from "@multiversx/sdk-core"; + + +const tx = new Transaction({ + data: Buffer.from("food for cats"), + gasLimit: 70000n, + sender: addressOfAlice.toBech32(), + receiver: addressOfBob.toBech32(), + value: 1000000000000000000n, + chainID: "D" +}); + +tx.nonce = 42n; +``` + +### Signing a transaction + +:::important +Note that the transactions **must be signed before being broadcasted**. +On the front-end, signing can be achieved using a signing provider. +On this purpose, **we recommend using [sdk-dapp](https://github.com/multiversx/mx-sdk-dapp)** instead of integrating the signing providers on your own. +::: + +:::important +For the sake of simplicity, in this section we'll use a private key to sign the transaction. +In real-world dApps, transactions are signed by end-users using their wallet, through a signing provider. +::: + +``` +import { TransactionComputer } from "@multiversx/sdk-core"; +import { UserSigner } from "@multiversx/sdk-wallet"; +import { promises } from "fs"; + +const fileContent = await promises.readFile("../testwallets/alice.json", { encoding: "utf8" }); +const walletObject = JSON.parse(fileContent); +const signer = UserSigner.fromWallet(walletObject, "password"); + +const computer = new TransactionComputer(); +const serializedTx = computer.computeBytesForSigning(tx); + +tx.signature = await signer.sign(serializedTx); +``` + +### Broadcast using a network provider + +In order to broadcast a transaction, use a network provider: + +``` + +const txHash = await apiNetworkProvider.sendTransaction(readyToBroadcastTx); +console.log("TX hash:", txHash); +``` + +### Wait for transaction completion + +``` +import { TransactionWatcher } from "@multiversx/sdk-core"; + +const watcherUsingApi = new TransactionWatcher(apiNetworkProvider); +const transactionOnNetworkUsingApi = await watcherUsingApi.awaitCompleted(txHash); +``` + +If, instead, you use a `ProxyNetworkProvider` to instantiate the `TransactionWatcher`, you'll need to patch the `getTransaction` method, +so that it instructs the network provider to fetch the so-called _processing status_, as well (required by the watcher to detect transaction completion). + +``` +const watcherUsingProxy = new TransactionWatcher({ + getTransaction: async (hash) => { return await proxyNetworkProvider.getTransaction(hash, true) } +}); + +const transactionOnNetworkUsingProxy = await watcherUsingProxy.awaitCompleted(txHash); +``` + +In order to wait for multiple transactions: + +``` +await Promise.all([ + watcherUsingApi.awaitCompleted(tx1), + watcherUsingApi.awaitCompleted(tx2), + watcherUsingApi.awaitCompleted(tx3) +]); +``` + +For a different awaiting strategy, also see [extending sdk-js](https://docs.multiversx.com/sdk-and-tools/sdk-js/extending-sdk-js). +## Token transfers + +Generally speaking, in order to create transactions that transfer native tokens or ESDT tokens, one should use the `TransferTransactionsFactory` class. + +:::note +In `sdk-core v13`, the `TransferTransactionsFactory` class was extended with new methods, +to be aligned with the [SDKs specs](https://github.com/multiversx/mx-sdk-specs/blob/main/core/transactions-factories/transfer_transactions_factory.md). +The old, legacy methods are still available (see below), thus existing client code isn't affected. +::: + +:::note +In `sdk-core v13`, the `TokenTransfer` class has changed, in a non-breaking manner. +Though, from now on, it should only be used for prepairing ESDT token transfers, not native EGLD transfers. + +A `TokenTransfer` object can be instantiated using the legacy approaches, e.g. `fungibleFromAmount`, `nonFungible` (which are still available), +or with the new approach (which, among others, makes abstraction of the number of decimals a token has). +::: + +:::tip +For formatting or parsing token amounts, see [formatting and parsing amounts](#formatting-and-parsing-amounts). +::: + +First, let's create a `TransferTransactionsFactory`: + +``` +import { Token, TokenComputer, TokenTransfer, TransactionsFactoryConfig, TransferTransactionsFactory } from "@multiversx/sdk-core"; + +// The new approach of creating a "TransferTransactionsFactory": +const factoryConfig = new TransactionsFactoryConfig({ chainID: "D" }); +const factory = new TransferTransactionsFactory({ config: factoryConfig, tokenComputer: new TokenComputer() }); +``` + +Now, we can use the factory to create transfer transactions. + +### **EGLD** transfers (value movements) + +``` +const tx1 = factory.createTransactionForNativeTokenTransfer({ + sender: addressOfAlice, + receiver: addressOfBob, + // 1 EGLD + nativeAmount: BigInt("1000000000000000000"), +}); + +tx1.nonce = 42n; +``` + +### Single ESDT transfer + +``` +const tx2 = factory.createTransactionForESDTTokenTransfer({ + sender: addressOfAlice, + receiver: addressOfBob, + tokenTransfers: [ + new TokenTransfer({ + token: new Token({ identifier: "TEST-8b028f", nonce: 0n }), + amount: 10000n, + }) + ], +}); + +tx2.nonce = 43n; +``` + +### Single NFT transfer + +``` +const tx3 = factory.createTransactionForESDTTokenTransfer({ + sender: addressOfAlice, + receiver: addressOfBob, + tokenTransfers: [ + new TokenTransfer({ + token: new Token({ identifier: "TEST-38f249", nonce: 1n }), + amount: 1n, + }) + ], +}); + +tx3.nonce = 44n; +``` + +### Single SFT transfer + +``` +const tx4 = factory.createTransactionForESDTTokenTransfer({ + sender: addressOfAlice, + receiver: addressOfBob, + tokenTransfers: [ + new TokenTransfer({ + token: new Token({ identifier: "SEMI-9efd0f", nonce: 1n }), + amount: 5n, + }) + ], +}); + +tx4.nonce = 45n; +``` + +### Multi ESDT / NFT transfer + +``` +const tx5 = factory.createTransactionForESDTTokenTransfer({ + sender: addressOfAlice, + receiver: addressOfBob, + tokenTransfers: [ + new TokenTransfer({ + token: new Token({ identifier: "TEST-8b028f", nonce: 0n }), + amount: 10000n, + }), + new TokenTransfer({ + token: new Token({ identifier: "TEST-38f249", nonce: 1n }), + amount: 1n, + }), + new TokenTransfer({ + token: new Token({ identifier: "SEMI-9efd0f", nonce: 1n }), + amount: 5n, + }) + ], +}); + +tx5.nonce = 46n; +``` diff --git a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-versions.md b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-versions.md new file mode 100644 index 000000000..e5e45575f --- /dev/null +++ b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-versions.md @@ -0,0 +1,16 @@ +--- +id: sdk-js-cookbook-versions +title: Cookbook (other versions) +pagination_next: null +--- + +[comment]: # (mx-abstract) + +This page lists all available versions of the **sdk-js cookbook**. + +The cookbook version corresponds to the version of the [**sdk-js-core**](https://github.com/multiversx/mx-sdk-js-core) package, even though other satellite packages of **sdk-js** have separate versioning. + +Please follow the version you are interested in: + + - [Cookbook v12 **(stable, current version)**](/sdk-and-tools/sdk-js/sdk-js-cookbook-v12) + - [Cookbook v13 **(unstable, upcoming version)**](/sdk-and-tools/sdk-js/sdk-js-cookbook-v13) diff --git a/docusaurus.config.js b/docusaurus.config.js index 9ff5cdedf..c6133113b 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -325,11 +325,11 @@ const config = { }, { from: "/sdk-and-tools/erdjs/erdjs-cookbook", - to: "/sdk-and-tools/sdk-js/sdk-js-cookbook", + to: "/sdk-and-tools/sdk-js/sdk-js-cookbook-versions", }, { - from: "/sdk-and-tools/erdjs/extending-erdjs", - to: "/sdk-and-tools/sdk-js/extending-sdk-js", + from: "/sdk-and-tools/sdk-js/sdk-js-cookbook", + to: "/sdk-and-tools/sdk-js/sdk-js-cookbook-v12", }, { from: "/sdk-and-tools/erdjs/writing-and-testing-erdjs-interactions", diff --git a/sidebars.js b/sidebars.js index 6a43aebb5..f1aa016eb 100644 --- a/sidebars.js +++ b/sidebars.js @@ -274,7 +274,23 @@ const sidebars = { label: "Javascript SDK", items: [ "sdk-and-tools/sdk-js/sdk-js", - "sdk-and-tools/sdk-js/sdk-js-cookbook", + { + label: "Cookbook", + type: "doc", + id: "sdk-and-tools/sdk-js/sdk-js-cookbook-v12", + }, + { + type: "category", + label: "Cookbook (versioned)", + link: { + type: "doc", + id: "sdk-and-tools/sdk-js/sdk-js-cookbook-versions" + }, + items: [ + "sdk-and-tools/sdk-js/sdk-js-cookbook-v12", + "sdk-and-tools/sdk-js/sdk-js-cookbook-v13", + ] + }, "sdk-and-tools/sdk-js/extending-sdk-js", "sdk-and-tools/sdk-js/writing-and-testing-sdk-js-interactions", "sdk-and-tools/sdk-js/sdk-js-migration-guides",