Intro to MultiversX blockchain interactions with JavaScript SDK

github twitter github

Writing low-level code for blockchain applications is one thing, but you must also write tools to interact with the protocol and smart contracts. What is the best programming language for that? A couple exist, but what's quickest to pick up, especially with a great SDK? Of course, JavaScript.

I want to cover interactions in a Node.js environment with MultiversX SDK. For web application integration, I will prepare separate articles.

What we will cover in this article:

  • How to prepare the environment and tools
  • How to prepare and broadcast a simple transaction

You will find a video walkthrough at the end of this article.

Let's focus on the Node.js environment first. It will be more helpful to show how the MultiversX JS SDK works in Node.js before introducing you to abstractions like web apps-related tooling.

Preparing the tools

We will need Node.js to interact with the MultiversX blockchain using the JavaScript SDK. If you are a JavaScript developer, there is no need to explain how to install Node.js. If not, it would be better to understand how it all works before reading further, so please learn more about it and then go back to this article.

Ok, let's jump into it. First of all, we need to initialize our dummy project. So create a directory, and inside of it, use npm to initialize the Node.js project:

npm init

It will guide you in creating a package.json file with the setup.

Then we must install @multiversx/sdk-core, @multiversx/sdk-network-providers and @multiversx/sdk-wallet. I will use the second library to prepare a convenient way of making network requests and broadcasting transactions. The third library will be required to prepare a 'signer' wallet for tests, but we will primarily work with the sdk-core.

npm install @multiversx/sdk-core @multiversx/sdk-network-providers @multiversx/sdk-wallet

We will work without the Typescript configuration just for simplicity, but of course, you can also configure this step if you want to.

The next step is to create a wallet. The simplest way is to use the Devnet Web Wallet. Check devnet-wallet.multiversx.com and create a new wallet there. Save the password you provided, the seed phrase, and the generated Keystore file. You will need them later. Remember, all that data should stay private, so don't share it with anyone. I will share everything for demo purposes, but it is still on the devnet, so nothing harm me if the data leaks.

You also need some funds in your wallet. After connecting to the Web wallet using the Keystore, you will find a faucet. You can request some 'fake' EGLD (the native MultiversX token) for testing. The Web Wallet UI should be intuitive enough, but here are the docs on how to use it: Web Wallet docs.

Ok, let's return to our JavaScript code. Now that we have all the necessary libraries, let's create a setup.js file and move the Keystore JSON file to the same directory for convenience.

Till now, you should have:

node_modules
package.json
erd....json
setup.js

We must initialize and prepare some things: our signer to sign transactions with our newly created wallet, our user account to synchronize it with the network, and the network provider to broadcast transactions.

You will do that using helper functions from our previously installed npm packages. It should look like:

import { promises } from "node:fs";
import { Address, Account } from "@multiversx/sdk-core";
import { ApiNetworkProvider } from "@multiversx/sdk-network-providers";
import { UserSigner } from "@multiversx/sdk-wallet";

export const senderAddress =
  "erd10dgr4hshjgkv6wxgmzs9gaxk5q27cq2sntgwugu87ah5pelknegqc6suj6";
export const receiverAddress =
  "erd176ddeqqde20rhgej35taa5jl828n9z4pur52x3lnfnj75w4v2qyqa230vx";

const keyFilePath = `./${senderAddress}.json`;

// Should be always kept privately, here hardcoded for the demo
const password = "Ab!12345678";

// The convenient way of doing network requests using the devnet API
export const apiNetworkProvider = new ApiNetworkProvider(
  "https://devnet-api.multiversx.com"
);

export const syncAndGetAccount = async () => {
  const address = new Address(senderAddress);
  const userAccount = new Account(address);
  const userAccountOnNetwork = await apiNetworkProvider.getAccount(address);
  userAccount.update(userAccountOnNetwork);
  return userAccount;
};

// We read the Keystore file contents here
const getKeyFileObject = async () => {
  const fileContents = await promises.readFile(keyFilePath, {
    encoding: "utf-8",
  });
  return fileContents;
};

export const getSigner = async () => {
  const wallet = await getKeyFileObject();
  return UserSigner.fromWallet(JSON.parse(wallet), password);
};

The functions are self-explanatory, but basically, the tools are:

  • apiNetworkProvider - required for broadcasting transactions
  • syncAndGetAccount - preparing and synchronization of the user account
  • getSigner - prepare the wallet signer for transaction signing

Sign and broadcast the transaction

With our tools ready, we can review our transactions. We want to use the simplest method to prepare and send some EGLD with an attached custom message.

The flow is as follows:

  • We synchronize and prepare the user instance
  • We prepare the transaction configuration and payload
  • We increment the nonce using the user's on-chain data
  • We serialize the transaction data for signing
  • We sign the transaction data
  • We get and set the signature on the transaction object
  • We broadcast the transaction

It looks like that in the code:

import { Transaction, TransactionComputer } from "@multiversx/sdk-core";
import {
  receiverAddress,
  syncAndGetAccount,
  senderAddress,
  getSigner,
  apiNetworkProvider,
} from "./setup.js";

const sendEgld = async () => {
  const user = await syncAndGetAccount();

  const transaction = new Transaction({
    data: Buffer.from("This is the demo transaction!"),
    gasLimit: 100000n,
    sender: senderAddress,
    receiver: receiverAddress,
    value: 1000000000000000n, // 0.001 EGLD
    chainID: "D",
  });

  transaction.nonce = user.getNonceThenIncrement();

  const computer = new TransactionComputer();
  const serializedTransaction = computer.computeBytesForSigning(transaction);

  const signer = await getSigner();

  transaction.signature = await signer.sign(serializedTransaction);

  const txHash = await apiNetworkProvider.sendTransaction(transaction);

  console.log(
    "Check in the explorer: ",
    `https://devnet-explorer.multiversx.com/transactions/${txHash}`
  );
};

sendEgld();

For more information about all the helper functions from MultiversX JavaScript SDK, you can check the autogenerated API documentation.

There is also a cookbook with the basics like here, but also with much more. You can find it here: sdk-js-cookbook.

I'll also try to prepare more articles on topics like interaction with custom smart contracts and token management, but these will be included in the following articles.

Summary

The MultiversX JavaScript SDK is a powerful tool for interacting with blockchain and smart contracts. Here, you have complete logic for managing simple transactions, but you can also reuse that for any other transaction. The only difference will be how the transaction payload is built.

Follow me on X (@theJulianIo) and YouTube (@julian_io) for more MultiversX magic.

Please check the tools that I maintain: the Elven Family tools and Buildo.dev. Also, check the xDevGuild GitHub organization, where you'll find many resources for developers. Thanks.

Walkthrough video

The demo code