Deploying a Smart Contract on Elrond Network in JavaScript
A Beginner’s Guide to Deploying Smart Contracts (NFT Minter) on Elrond Network
Hello readers! In this article, we will explore deploying a smart contract on the Elrond network.
Smart contracts are self-executing contracts with the terms of the agreement between buyer and seller being directly written into lines of code. They are an integral part of many decentralized applications and allow for the automation of various processes.
In this tutorial, we will walk through the steps of setting up the necessary components and writing a script to deploy a smart contract on the Elrond network. We will then look closely at the code itself and see how everything comes together. So without further ado, let’s get started!
Prerequisites for this article
- Node.js
- NPM Package Manager
- Basic JavaScript knowledge
- Basic knowledge of how to use a CLI
Initial Setup
First, we need initial a new node project in an empty folder of your choice:
npm init -y
Next, we need to install a few npm packages:
npm install @elrondnetwork/erdjs
npm install @elrondnetwork/erdjs-walletcore
npm install @elrondnetwork/erdjs-network-providers
I will provide a brief explanation of the purpose of the installed packages.
The @elrondnetwork/erdjs package is a JavaScript library that provides an interface for interacting with the Elrond network. It includes classes and functions for performing various actions on the network, such as creating and signing transactions, interacting with smart contracts, and fetching network information. Overall, the purpose of this package is to provide developers with a convenient way to access and use the Elrond network from within JavaScript code.
The @elrondnetwork/erdjs-walletcore package is a JavaScript library that provides utility functions for working with secret keys and signers on the Elrond network. It includes classes for creating and parsing secret keys, as well as a signer class that can be used to sign transactions. The purpose of this package is to provide developers with a set of tools for securely handling secret keys and signing transactions on the Elrond network.
The @elrondnetwork/erdjs-network-providers package is a JavaScript library that provides classes for interacting with various Elrond network providers. It includes a ProxyNetworkProvider
class that allows developers to connect to the Elrond network via a proxy server and perform actions such as fetching network configuration, sending transactions, and fetching account information. The purpose of this package is to provide developers with a convenient way to access and use the Elrond network from within JavaScript code.
Then we import a number of dependencies:
const {
Account,
AbiRegistry,
SmartContract,
SmartContractAbi,
Code,
CodeMetadata,
TransactionWatcher,
ResultsParser,
} = require('@elrondnetwork/erdjs')
const fs = require('fs')
const {
UserSecretKey,
UserSigner,
parseUserKey,
} = require('@elrondnetwork/erdjs-walletcore')
const {
ProxyNetworkProvider,
} = require('@elrondnetwork/erdjs-network-providers')
Setting Up a Wallet on the Elrond Devnet
To set up a wallet on the Elrond devnet and get a pem file, follow these steps:
- Go to the Elrond devnet website (https://devnet.elrond.com/) and click on the “Get Started” button.
- On the next page, click on the “Create Wallet” button to create a new wallet.
- Follow the prompts to enter a password and set up your wallet. Make sure to remember your password, as you will need it to access your wallet.
- Once your wallet has been created, click on the “Download Pem” button to download a pem file containing your secret key.
- Save the pem file to a secure location on your computer. You will need this file to sign transactions and interact with the Elrond network.
- If you ever need to retrieve your pem file in the future, you can access it by logging into your wallet on the Elrond devnet website and clicking on the “Download Pem” button again.
And that’s it! You should now have a wallet on the Elrond devnet and a pem file containing your secret key. You can use this pem file to sign transactions and interact with the Elrond network. Just make sure to keep it safe and secure.
Write a script in JavaScript to deploy a Smart Contract to the Elrond Network
Next, the script defines a setup
function that initializes the necessary components for deploying the smart contract. This includes reading in a private key from a file, creating a signer object with the key, setting up a network provider and fetching the network configuration, and creating an Account
object with the public key derived from the private key.
Please place the pem key next to the script and replace the pemKeyFileName.
For simplicity, we are using the ProxyNetworkProvider to manage our transaction, if you wanna use another provider you can read more here.
const setup = async () => {
const pemKeyFileName = './yourwalletpemfilename.pem'
const walletPemKey = fs.readFileSync(pemKeyFileName, 'utf8')
const pemKey = UserSecretKey.fromPem(walletPemKey)
const signer = new UserSigner(pemKey)
const provider = new ProxyNetworkProvider('https://devnet-gateway.elrond.com')
const networkConfig = await provider.getNetworkConfig()
const userKey = parseUserKey(walletPemKey)
const account = new Account(userKey.generatePublicKey().toAddress())
let accountOnNetwork = await provider.getAccount(
userKey.generatePublicKey().toAddress(),
)
account.update(accountOnNetwork)
return {
signer,
account,
provider,
networkConfig,
}
}
The getContract
function reads in the ABI (Application Binary Interface) for the smart contract from a file and creates a SmartContract
object with it.
What is an ABI?
A smart contract ABI (Application Binary Interface) is a specification that defines the functions and variables of a smart contract and how they can be called and accessed. It is essentially a set of rules for interacting with the smart contract, and it is written in a standardized format that can be understood by multiple programming languages.
Download the output folder from this repository that holds the content of the compiled Elrond Rust Smart Contract. If you know how to compile an Elrond Smart Contract or you wanna go through the Rust Contract we will deploy you can go here.
What's the SmartContract object?
The SmartContract object is a class provided by the @elrondnetwork/erdjs library that represents a smart contract on the Elrond network. It is created with an ABI (Application Binary Interface) object that defines the functions and variables of the contract, and it provides methods for interacting with the contract such as calling functions and accessing variables.
const getContract = async () => {
const jsonContent = await fs.promises.readFile(
'./output/nft-minter.abi.json',
{ encoding: 'utf8' },
)
const json = JSON.parse(jsonContent)
const registry = AbiRegistry.create(json)
const abi = new SmartContractAbi(registry)
return new SmartContract({
abi,
})
}
The getTransaction
function then loads the actual contract code from a file, creates a Code
object with it, and creates a SmartContract
deployment transaction with the code and the metadata specified in the metaData
object. The transaction is signed with the signer
object and returned.
const getTransaction = async (account, networkConfig, signer, contract) => {
const buffer = await fs.promises.readFile('./output/nft-minter.wasm')
const code = Code.fromBuffer(buffer)
const metaData = {
upgradeable: true,
readable: true,
payable: true,
payableBySc: true,
}
const transaction = contract.deploy({
code: code,
codeMetadata: new CodeMetadata(
metaData.upgradeable,
metaData.readable,
metaData.payable,
metaData.payableBySc,
),
gasLimit: 200000000,
chainID: networkConfig.ChainID,
})
transaction.setNonce(account.getNonceThenIncrement())
signer.sign(transaction)
return transaction
}
The sendTransaction
function sends the transaction to the network via the provider.
const sendTransaction = async (provider, transaction) => {
const txHash = await provider.sendTransaction(transaction)
console.log(
`Transaction link: https://devnet-explorer.elrond.com/transactions/${txHash}\n`,
)
}
The setSmartContractAddress
function computes the address of the deployed smart contract based on the transaction sender and nonce.
const setSmartContractAddress = (transaction, contract) => {
const smartContractAddress = SmartContract.computeAddress(
transaction.getSender(),
transaction.getNonce(),
)
contract.setAddress(smartContractAddress)
return smartContractAddress
}
Finally, the parseContractResponse
function uses a TransactionWatcher
to wait for the transaction to be completed on the network and then parses the outcome using a ResultsParser
.
const parseContractResponse = async (provider, transaction) => {
const watcher = new TransactionWatcher(provider)
let transactionOnNetwork = await watcher.awaitCompleted(transaction)
return new ResultsParser().parseUntypedOutcome(transactionOnNetwork)
}
The main
function ties everything together by calling the setup
, getContract
, and getTransaction
functions, sending the transaction, setting the smart contract address, and parsing the response. This completes the deployment of the smart contract on the Elrond network.
const main = async () => {
const { signer, account, provider, networkConfig } = await setup()
const contract = await getContract()
const transaction = await getTransaction(
account,
networkConfig,
signer,
contract,
)
await sendTransaction(provider, transaction)
const smartContractAddress = setSmartContractAddress(transaction, contract)
const { returnCode } = await parseContractResponse(provider, transaction)
console.log(`Transaction return code: ${returnCode}`)
console.log(`Smart Contract address: ${smartContractAddress}\n`)
}
Now you can call the main function to deploy the NFT Minter Smart Contract to the Elrond Network.
main()
On the CLI you can now run the script we just wrote to finally deploy the Smart Contract. Replace the name deploy.js be your filename.
node deploy.js
You should see a similar output like this on your CLI.
Transaction link: https://devnet-explorer.elrond.com/transactions/c2dd876679492a7e0b5227c615d20a317a899a6d410896f4c0cf9b0051630e29
TransactionCompletionStrategy.isCompleted(), found event: SCDeploy
Transaction return code: ok
Smart Contract address: erd1qqqqqqqqqqqqqpgqf365h5m5c7zgnwe0fua6uvfgg5pt5t2zrfyqsyshf7
In this article, we learned about the process of deploying a smart contract on the Elrond network using a script written in JavaScript.
We looked at the various dependencies that are required for this process, including the @elrondnetwork/erdjs and @elrondnetwork/erdjs-walletcore packages, and we saw how they are used to set up the necessary components and create and sign a transaction.
We also examined the steps involved in sending the transaction to the network and parsing the response, and we saw how the smart contract ABI is used to interact with the deployed contract.
I hope this article was helpful in giving you an understanding of how to deploy a smart contract on the Elrond network. If you have any questions or comments, please don’t hesitate to reach out. Thank you for reading, and have a great day!