How to deserialize data fetched from Nexis Native Chain accounts.
@nexis-network/web3.js
simplifies this process for you so that all you need to focus
on is adding instructions and signatures. The library builds the array of
accounts based on that information and handles the logic for including a recent
blockhash.
Borsh stands for Binary Object Representation Serializer for Hashing. It is meant to be used in security-critical projects as it prioritizes consistency, safety, speed; and comes with a strict specification.Borsh maintains a JS library that handles serializing common types into a buffer. There are also other packages built on top of Borsh that try to make this process even easier. We’ll be using the
@coral-xyz/borsh
library which can be installed using npm
.
Building off of the previous game inventory example, let’s look at a
hypothetical scenario where we are instructing the program to equip a player
with a given item. Assume the program is designed to accept a buffer that
represents a struct with the following properties:
variant
is an unsigned, 8-bit integer that instructs the program which
instruction, or function, to execute.playerId
is an unsigned, 16-bit integer that represents the player ID of
the player who is to be equipped with the given item.itemId
is an unsigned, 256-bit integer that represents the item ID of the
item that will be equipped for the given player.encode
method. This method
accepts as arguments an object representing the data to be serialized and a
buffer. In the below example, we allocate a new buffer that’s much larger than
needed, then encode the data into that buffer and slice the original buffer down
into a new buffer that’s only as large as needed.
player
, playerInfoAccount
, and PROGRAM_ID
are already defined somewhere
outside the code snippetplayer
is a user’s public keyplayerInfoAccount
is the public key of the account where inventory changes
will be writtenSystemProgram
will be used in the process of executing the instruction.CenYq6bDRB7p73EjsPEpiYN7uveyPUTdXkDkgUduboaN
.
WalletContextProvider
we created in the Wallets lesson, a Card
component for
displaying a movie review, a MovieList
component that displays reviews in a
list, a Form
component for submitting a new review, and a Movie.ts
file that
contains a class definition for a Movie
object.
Note that for now, the movies displayed on the page when you run npm run dev
are mocks. In this lesson, we’ll focus on adding a new review but we won’t be
able to see that review displayed. Next lesson, we’ll focus on deserializing
custom data from onchain accounts.
variant
as an unsigned, 8-bit integer representing which instruction should
be executed (in other words which function on the program should be called).title
as a string representing the title of the movie that you are
reviewing.rating
as an unsigned, 8-bit integer representing the rating out of 5 that
you are giving to the movie you are reviewing.description
as a string representing the written portion of the review you
are leaving for the movie.borsh
layout in the Movie
class. Start by importing
@coral-xyz/borsh
. Next, create a borshInstructionSchema
property and set it
to the appropriate borsh
struct containing the properties listed above.
Movie
called serialize()
that will return a Buffer
with a Movie
object’s
properties encoded into the appropriate layout.
{ ...this, variant: 0 }
into the buffer. Because the Movie
class
definition contains 3 of the 4 properties required by the buffer layout and uses
the same naming, we can use it directly with the spread operator and just add
the variant
property. Finally, the method returns a new buffer that leaves off
the unused portion of the original.
Form.tsx
and locate
the handleTransactionSubmit
function. This gets called by handleSubmit
each
time a user submits the Movie Review form.
Inside this function, we’ll be creating and sending the transaction that
contains the data submitted through the form.
Start by importing @nexis-network/web3.js
and importing useConnection
and
useWallet
from @nexis-network/wallet-adapter-react
.
handleSubmit
function, call useConnection()
to get a
connection
object and call useWallet()
to get publicKey
and
sendTransaction
.
handleTransactionSubmit
, let’s talk about what needs to be
done. We need to:
publicKey
exists to ensure that the user has connected their
wallet.serialize()
on movie
to get a buffer representing the instruction
data.Transaction
object.Instruction
object that includes all of these accounts in the
keys
argument, includes the buffer in the data
argument, and includes the
program’s public key in the programId
argument.sendTransaction
, passing in the assembled transaction.pda
is the address to the account where data will be
stored:
SystemProgram
, so our array needs to include web3.SystemProgram.programId
as
well.
With that, we can finish the remaining steps:
HdE95RSVsdb315jfJtaykXhXY478h53X6okDupVfY9yf
.
StudentIntro.ts
. The program
expects instruction data to contain:
variant
as an unsigned, 8-bit integer representing the instruction to
run (should be 0).name
as a string representing the student’s name.message
as a string representing the message the student is sharing
about their Nexis Native Chain journey.StudentIntro.ts
that will use the buffer layout to
serialize a StudentIntro
object.Form
component, implement the handleTransactionSubmit
function so
that it serializes a StudentIntro
, builds the appropriate transaction and
transaction instructions, and submits the transaction to the user’s wallet.