Full-Stack Starknet:
Completed code on GitHub here.
We've built the cairo contracts and a raspberry pi server that will attest to a vehicle state periodically. Ideally though, a user shouldn't need to issue commands on the pi to register a vehicle or rotate the signing account. They should instead get a more modern experience: a webapp that connects to their Argent X browser extension (current leading wallet provider).
Not a huge fan of frontend work personally. Just never caught the JS bug 🤷 (I'm not bitter about it, I swear)
Fortunately, a few community members have crafted cairopal – a batteries-included frontend template for dapps on StarkNet. Thanks to their heavy lifting (seriously, thank you 🙌🙏) we have a massive head start in making a functional frontend with a smooth and clean UI.
💡 If you're coming here just looking for React library to use, check out starknet-react from Francesco Ceccon. The template we'll use here is based on an early version of that work. Though it may be ported in the near future to use startknet-react now that it's an official package.
We'll use this head start to quickly create a fontend that:
Clone cairopal to be the base of our project:
Install the dependencies with a yarn install
and start it with a yarn dev
– then we'll be able to see the site at http://localhost:3000
Looks pretty sleek without needing to modify much. Right out of the box, we can connect our account in the Argent X browser extension.
Two foundational components are included as well:
Between these, we should be able to re-use the same underlying mechanisms to build out our frontend.
But before we move on, remember back to Part 4 and try to setup our dev session.
✨ Exercise: Start a local devnet and deploy our contract. Then, use the Argent X wallet to deploy a new account on that same local network.
First, a nile node
to bring up the local network:
Then, a compile & deploy:
To verify it was deployed, we can check with the CLI:
💡 Tip: you can use this same command to display error messages from rejected transactions
Finally, open the extension & select the localhost network. Clicking the + button will deploy to our local network.
NOTE: If you want to skip local devnet and just work against testnet, use this goerli contract I deployed: 0x0220d51c9f7ad564c4cc2fecfeeebb35f18646329c8f5cfcc5b6ec00cf31cbc0
You'll still need your own argent account deployed to goerli.
As we saw earlier, there's a Transactions List view and a Mint Tokens button to build off of. If ya go to the <MintTokens>
component, we can rename this file (and it's references) to RegisterVehicle
. That will be the only responsibility of this component.
The first obvious change is to set the contract address to what we've deployed.
We're also going to need access to the currently connected account address. We can bring it into scope by modifying this line:
Then head down to the mintTokens
function, where the contract interaction happens.
Let's modify it to match the function signature we want to hit (func register_vehicle(vehicle_id : felt, signer_address : felt):
). Overall it should feel pretty similar to how we've called our contracts from python. Just a slightly different layout.
Heading back to our refreshed site, we should be able to try it out:
Once sent & accepted, we can use nile to check if the owner of vehicle 42 was updated:
If you were pointing your frontend at the testnet contract I mentioned earlier, you won't be able to see the transaction in the contract's explorer page (at least, not at time of writing). Rather, you'll see it show up on your account's contract page in the explorer.
You can however query the testnet contract to see if the transaction updated the state:
✨ Exercise: Can you figure out how to accept Vehicle ID using an input box?
Never heard of chakra ui
before, but a quick google came up with an Input component.
Using the docs I was able to come up with a quick and dirty implementation:
It doesn't do any input validation like we'd want in prod, but good enough to demo. Try registering some arbitrary integer like 5
, then checking the owner.
Reading from contract state shows us it went through!
So the frontend can be used to register a vehicle, and the rapberry pi can sign & commit state attestations on chain using the registered account. Though, we still need a way to send a set_signer()
transaction to let the owner change what account has the signing rights.
Doesn't really make much sense to put that logic in the onboard raspberry pi. Instead, it should be a new React component on the frontend of our management dashboard.
Some quick copypasta from the last component brings us to this starter template:
✨ Exercise: Using the building blocks from the last section, add a
UpdateSigner
component belowRegisterVehicle
. It should take in a vehicle ID and a new signer account address as input, and invoke ourset_signer(vehicle_id, signer_address)
function.
You may have noticed one thing that didn't work right away – the Transaction List. I'm uhh still trying to figure that one out myself 😅.
I was able to take a stab at porting cairopal to use starknet-react, in this PR. Though since you may read this before that change goes in, you can check out the starknet-react demo site in the meantime. The transaction manager is used here:
https://github.com/auclantis/starknet-react/blob/main/website/src/components/Demo.tsx#L146-L178