Skip to main content

Flare for JavaScript Devs

This guide is for developers who want to interact with Flare using JavaScript. In this guide, using JavaScript, you will learn how to:

  • Query a contract on Flare using web3.js, an async/sync library for interacting with Ethereum-like chains.
  • Compile a Solidity contract using the CLI interface of solc, the Solidity compiler.
  • Deploy your compiled contract on Flare.
tip

All examples in this guide are available at developer-hub/examples.

Getting started

Install the Solidity compiler by following the instructions in the Solidity documentation. The main commands are provided here:

brew tap ethereum/ethereum
brew install solidity

Install web3.js using either npm or yarn:

npm install web3

Usage

You need to connect to testnet or mainnet via an RPC, any RPC listed on the Network Configuration page will work. For this guide, you can use the Public RPC.

chainId.js
import { Web3 } from "web3";

export async function main() {
const web3 = new Web3("https://coston2-api.flare.network/ext/C/rpc");
const chainId = await web3.eth.getChainId();
console.log(chainId);
// 114n
return chainId;
}

Querying a contract

To query a contract, two pieces of information are required:

  • Contract address
  • Contract ABI (Application Binary Interface)

For this example, you can query the FlareContractRegistry contract which has the same address 0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019 across both testnet and mainnet.

Fetch ABI

To fetch a contract's ABI programmatically, you can query the Flare Blockchain Explorer API:

fetchAbi.js
const base_url = "https://coston2-explorer.flare.network/api";

export async function main() {
const params =
"?module=contract&action=getabi&address=0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019";

const response = await fetch(base_url + params);
const abi = JSON.parse((await response.json())["result"]);
return abi;
}

Make query

You can now query the FlareContractRegistry contract to get the addresses of other Flare contracts.

For example, querying it for the address of the WNat contract:

makeQuery.js
import { Web3 } from "web3";

const registry_addr = "0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019";
const base_url = "https://coston2-explorer.flare.network/api";

export async function main() {
// Fetch ABI
const params = `?module=contract&action=getabi&address=${registry_addr}`;
const response = await fetch(base_url + params);
const abi = JSON.parse((await response.json())["result"]);

// Query contract
const w3 = new Web3("https://coston2-api.flare.network/ext/C/rpc");
const registry = new w3.eth.Contract(abi, registry_addr);
const res = await registry.methods.getContractAddressByName("WNat").call();
console.log("WNat address: ", res);
// WNat address: 0xC67DCE33D7A8efA5FfEB961899C73fe01bCe9273

return res;
}

Compiling with solc

For this example, you can use the FtsoV2FeedConsumer contract to query the FTSOv2 feeds. Copy the FtsoV2FeedConsumer sample contract code given below, and save the .sol file in the same folder as your package.json.

FtsoV2FeedConsumer sample contract

Note that the contract interface dependencies have been inlined to avoid any import issues.

FtsoV2FeedConsumer.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

interface IFlareContractRegistry {
function getContractAddressByName(
string calldata _name
) external view returns (address);
}

/**
* THIS IS A TEST INTERFACE.
* Functions are payable in the production interface.
*/
interface TestFtsoV2Interface {
function getFeedsById(
bytes21[] calldata _feedIds
)
external
view
returns (
uint256[] memory _values,
int8[] memory _decimals,
uint64 _timestamp
);
}

/**
* THIS IS AN EXAMPLE CONTRACT.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
contract FtsoV2FeedConsumer {
IFlareContractRegistry internal contractRegistry;
TestFtsoV2Interface internal ftsoV2;

// Feed IDs, see https://dev.flare.network/ftso/feeds for full list
bytes21[] public feedIds = [
bytes21(0x01464c522f55534400000000000000000000000000), // FLR/USD
bytes21(0x014254432f55534400000000000000000000000000), // BTC/USD
bytes21(0x014554482f55534400000000000000000000000000) // ETH/USD
];

/**
* Constructor initializes the FTSOv2 contract.
* The contract registry is used to fetch the FtsoV2 contract address.
*/
constructor() {
contractRegistry = IFlareContractRegistry(
0xaD67FE66660Fb8dFE9d6b1b4240d8650e30F6019
);
ftsoV2 = TestFtsoV2Interface(
contractRegistry.getContractAddressByName("FtsoV2")
);
}

/**
* Get the current value of the feeds.
*/
function getFtsoV2CurrentFeedValues()
external
view
returns (
uint256[] memory _feedValues,
int8[] memory _decimals,
uint64 _timestamp
)
{
/* Your custom feed consumption logic. In this example the values are just returned. */
return ftsoV2.getFeedsById(feedIds);
}
}
solc --evm-version london FtsoV2FeedConsumer.sol --abi --bin -o build

This will generate two files build/FtsoV2FeedConsumer.abi and build/FtsoV2FeedConsumer.bin files with the contract's ABI and bytecode. Rename FtsoV2FeedConsumer.abi to FtsoV2FeedConsumer.json.

Create account

Before deploying a contract, you need to have an account with some testnet or mainnet gas tokens. You can create a new Flare account using createAccount.js:

createAccount.js
import { Web3 } from "web3";

const w3 = new Web3();
w3.eth.accounts.wallet.create(1);
console.log(
`Account: ${w3.eth.accounts.wallet[0].address}, Private key: ${w3.eth.accounts.wallet[0].privateKey}`,
);

This will output a new private key and an account pair.

danger
  • Never share your private keys.
  • Never put your private keys in source code.
  • Never commit private keys to a Git repository.

You can save the account and private key into environment variables ACCOUNT and ACCOUNT_PRIVATE_KEY respectively.

note

You can also import the raw hex private key to MetaMask and any other wallet - the private key can be shared between your JavaScript code and any number of wallets.

  • For testnet, you can get free testnet C2FLR on the Coston2 Faucet.
  • For mainnet you will need to fund the account with FLR. You can buy FLR with regular currency in places like centralized exchanges, crypto on-ramps, or swap other tokens for FLR on decentralized exchanges.

Deploying with web3.js

With the account ready, you can now deploy the contract. In a deployContract.js file, you can define the following code to deploy the contract:

deployContract.js
// THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.
import { Web3 } from "web3";
import fs from "fs";

const web3 = new Web3(
new Web3.providers.HttpProvider(
"https://coston2-api.flare.network/ext/C/rpc",
),
);

const bytecode = fs.readFileSync("./build/FtsoV2FeedConsumer.bin", "utf8");
import abi from "./build/FtsoV2FeedConsumer.json" assert { type: "json" };
const FtsoV2FeedConsumer = new web3.eth.Contract(abi);

FtsoV2FeedConsumer.handleRevert = true;

async function deploy() {
const privateKey = process.env.ACCOUNT_PRIVATE_KEY.toString();
const wallet = web3.eth.accounts.wallet.add(privateKey);

const contractDeployer = FtsoV2FeedConsumer.deploy({
data: "0x" + bytecode,
});

const tx = await contractDeployer.send({
from: wallet[0].address,
nonce: await web3.eth.getTransactionCount(wallet[0].address),
gasPrice: await web3.eth.getGasPrice(),
});
console.log("Contract deployed at address: " + tx.options.address);
}

deploy();

You can now run the deployContract.js script to deploy the contract. The contract address will be printed once the deployment is successful. You can check the contract address on a Flare Blockchain Explorer, linked on the Network Configuration page.

Congratulations! You have now successfully deployed a contract on Flare using JavaScript.

What's next?

Learn how to interact with Flare's enshrined oracle FTSOv2 using JavaScript.