4. Starknet.js
WTF Starknet 4: Starknet.js
Starknet.js is a JavaScript library to interact with Starknet, typically in script or a decentralized applications. Starknet.js is inspired by Ethers.js, so it's easier if you have experience with it.
If you are not familiar with Ethers.js, check WTF Ethers Tutorial.
1. Install with npm
First, get your VSCode and Node.js ready. Then open your terminal to install starknet.js with npm.
npm install starknet
2. Provider
Provider
allows you to interact with the Starknet network, without signing transactions or messages.
const provider = new Provider({ sequencer: { network: 'goerli-alpha' } }) // for testnet 1
// output chainId
console.log("Chain ID: ", await provider.getChainId());
3. Account
Account
extends Provider
and allows you to create and verify signatures.
It is similar to Wallet
in ethers.js, but different since all accounts are abstract on Starknet. You need a KeyPair
to create an account instance.
const privateKey = process.env.PRIVATE_KEY;
console.log(privateKey)
const accountAddr = "0x06b59aEC7b1cC7248E206abfabe62062ba1aD75783E7A2Dc19E7F3f351Ac3309";
const starkKeyPair = ec.getKeyPair(privateKey);
const account = new Account(provider, accountAddr, starkKeyPair);
4. Get Account Nonce
Gets the nonce of the account with respect to a specific block.
const addr = "0x06b59aEC7b1cC7248E206abfabe62062ba1aD75783E7A2Dc19E7F3f351Ac3309"
const nonce = await provider.getNonceForAddress(addr)
console.log(Number(nonce));
5. A Simple Contract
We deployed a simple contract to interact with. It has a storage variable balance
, an event log_data
, and 2 functions: read_balance()
and set_balance()
to read and set the balance
. You can find the contract on starkscan here.
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
// starage variable: balance
@storage_var
func balance() -> (res: felt) {
}
// event
@event
func log_data(value: felt) {
}
// set balance.
@external
func set_balance{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr,
}(amount: felt) {
balance.write(amount);
// 释放事件
log_data.emit(amount);
return ();
}
// read balance.
@view
func read_balance{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr,
}() -> (amount: felt) {
let (res) = balance.read();
return (amount=res);
}
6. Read Contract
You can create a contract instance with Contract
method, and pass ABI, contract address, and provider to it. Then you can interact with the contract on Starknet.
const testAddress = "0x0352654644b53b008b9fd565846cca116c0911d0eeabb57df00b55ed77ad211e";
// Read ABI from contract address
const { abi: testAbi } = await provider.getClassAt(testAddress);
if (testAbi === undefined) { throw new Error("no abi.") };
// create contract instance
const myTestContract = new Contract(testAbi, testAddress, provider);
// call read_balance method
const bal1 = await myTestContract.read_balance();
// you can also use call method
// const bal1 = await myTestContract.call("read_balance");
console.log("Current Balance =", bal1.toString());
7. Write Contract
To write on the blockchain, you need to connect the contract instance with account.
// Connect account with the contract
myTestContract.connect(account);
// or you can use invoke
// const result = await myTestContract.invoke("set_balance", [888]);
const result = await myTestContract.set_balance(999);
const txReceiptDeployTest = await provider.waitForTransaction(result.transaction_hash);
const bal2 = await myTestContract.read_balance();
console.log("New Balance =", bal2.toString());
8. Write Contract with Verification
If you interact with a function that needs the proof that you have the private key of the account, you have to invoke this function with account.execute
, and pass following variables:
contractAddress
: address of the contract to invoke.entrypoint
: name of the function to invoke.calldata
: array of parameters for this function.
// account.execute: when you interact with the function that needs the proof that you have the private key of the account.
const executeHash = await account.execute(
{
contractAddress: myContractAddress,
entrypoint: 'transfer',
calldata: stark.compileCalldata({
recipient: receiverAddress,
amount: ['10']
})
}
);
await provider.waitForTransaction(executeHash.transaction_hash);
9. Read Events
It is easy to read event from transaction receipt. But a transaction can contain multiple events, so you need to filter out the one you need.
// Events
// there are multiple events in the tx, because ERC20 and argent tx also emit events.
// we need to filter out the event that we care
const events = txReceiptDeployTest.events;
const event = events.find(
(it) => number.cleanHex(it.from_address) === number.cleanHex(testAddress)
) || {data: []};
console.log("event: ", event);
10. Summary
In this tutorial, we introduced how to use Starknet.js, including provider, account, read/write contract, and read events.