Web3 JavaScript API
What is PUT-Web3.js?
The PUT-Web3.js library aims to provide complete coverage of PUT. The library was built on top of the PUT JSON RPC API.
You can find the full documentation for the @put/web3.js library here.
Common Terminology
For the full list of terms, see PUT terminology
Getting Started
Installation
yarn#
npm#
Bundle#
Usage
Javascript#
ES6#
Browser Bundle#
Quickstart
Connecting to a Wallet
To allow users to use your dApp or application on PUT, they will need to get access to their Keypair. A Keypair is a private key with a matching public key, used to sign transactions.
There are two ways to obtain a Keypair:
You can obtain a new Keypair with the following:
This will generate a brand new Keypair for a user to fund and use within your application.
You can allow entry of the secretKey using a textbox, and obtain the Keypair with Keypair.fromSecretKey(secretKey).
Many wallets today allow users to bring their Keypair using a variety of extensions or web wallets. The general recommendation is to use wallets, not Keypairs, to sign transactions. The wallet creates a layer of separation between the dApp and the Keypair, ensuring that the dApp never has access to the secret key. You can find ways to connect to external wallets with the wallet-adapter library.
Creating and Sending Transactions
To interact with programs on PUT, you create, sign, and send transactions to the network. Transactions are collections of instructions with signatures. The order that instructions exist in a transaction determines the order they are executed.
A transaction in PUT-Web3.js is created using the Transaction object and adding desired messages, addresses, or instructions.
Take the example of a transfer transaction:
The above code achieves creating a transaction ready to be signed and broadcasted to the network. The SystemProgram.transfer instruction was added to the transaction, containing the amount of lamports to send, and the to and from public keys.
All that is left is to sign the transaction with keypair and send it over the network. You can accomplish sending a transaction by using sendAndConfirmTransaction if you wish to alert the user or do something after a transaction is finished, or use sendTransaction if you don't need to wait for the transaction to be confirmed.
The above code takes in a TransactionInstruction using SystemProgram, creates a Transaction, and sends it over the network. You use Connection in order to define which PUT network you are connecting to, namely mainnet-beta, testnet, or devnet.
Interacting with Custom Programs
The previous section visits sending basic transactions. In PUT everything you do interacts with different programs, including the previous section's transfer transaction. At the time of writing programs on Put are either written in Rust or C.
Let's look at the SystemProgram. The method signature for allocating space in your account on PUT in Rust looks like this:
In PUT when you want to interact with a program you must first know all the accounts you will be interacting with.
You must always provide every account that the program will be interacting within the instruction. Not only that, but you must provide whether or not the account is isSigner or isWritable.
In the allocate method above, a single account pubkey is required, as well as an amount of space for allocation. We know that the allocate method writes to the account by allocating space within it, making the pubkey required to be isWritable. isSigner is required when you are designating the account that is running the instruction. In this case, the signer is the account calling to allocate space within itself.
Let's look at how to call this instruction using put-web3.js:
First, we set up the account Keypair and connection so that we have an account to make allocate on the testnet. We also create a payer Keypair and airdrop some sol so we can pay for the allocate transaction.
We create the transaction allocateTransaction, keys, and params objects. feePayer is an optional field when creating a transaction that specifies who is paying for the transaction, defaulting to the pubkey of the first signer in the transaction. keys represents all accounts that the program's allocate function will interact with. Since the allocate function also required space, we created params to be used later when invoking the allocate function.
The above is created using u32 and ns64 from @put/buffer-layout to facilitate the payload creation. The allocate function takes in the parameter space. To interact with the function we must provide the data as a Buffer format. The buffer-layout library helps with allocating the buffer and encoding it correctly for Rust programs on PUT to interpret.
Let's break down this struct.
index is set to 8 because the function allocate is in the 8th position in the instruction enum for SystemProgram.
Next up is u32('instruction').
The layout in the allocate struct must always have u32('instruction') first when you are using it to call an instruction.
ns64('space') is the argument for the allocate function. You can see in the original allocate function in Rust that space was of the type u64. u64 is an unsigned 64bit integer. Javascript by default only provides up to 53bit integers. ns64 comes from @put/buffer-layout to help with type conversions between Rust and Javascript. You can find more type conversions between Rust and Javascript at put-labs/buffer-layout.
Using the previously created bufferLayout, we can allocate a data buffer. We then assign our params { space: 100 } so that it maps correctly to the layout, and encode it to the data buffer. Now the data is ready to be sent to the program.
Finally, we add the transaction instruction with all the account keys, payer, data, and programId and broadcast the transaction to the network.
The full code can be found below.
Last updated