Full-Stack Starknet:
Completed code on GitHub here.
If you remember back in part 2, we waited a while for contracts to be deployed & transactions to be processed during our testing. Although the public testnet is nice for retaining state across manual or end to end tests, it's not the best experience while quickly iterating on a project.
Instead of working with the testnet and it's longer block times, let's use another tool to speed things up. A local devnet server actually comes installed with nile.
This will be our own sandbox to build and transact in.
Let's also create a .env
file to keep our private key & other configuration in:
๐ก NOTE: running
source .env
will bring these variables into scope for your session
Turns out, nile can also interact with our devnet. To deploy a new account contract, we can run the following:
The setup
command reads the private key SIGNER_SECRET
from the environment variable we exported earlier โ $SIGNER_SECRET
โ and deploys an account around that private key.
To compile & deploy our newest blackbox contract:
We'll take the deployment addresses in the output, and update the .env
file accordingly:
We've now:
Time to refactor our registration and commitment code in the application server
Before we get to that, a quick housekeeping item. A new module app/config.py
will help us easily load our environment variables without it being hardcoded into the app:
Pydantic will automatically read & convert types for the environment variables listed in that class (case insensitive). This will just make it easier to keep our private keys and other configuration out of version control.
Alright, back to the part of the API that interacts with StarkNet.
Previously, our application had to construct the calldata, keep track of a nonce, hash, and sign it all. Sizable chunk of code. For what should be a super common task.
Luckily, the talented folks at software-mansion provide first class support for the OpenZeppelin Account contract. So by using standard account contracts over in our cairo project, we can immediately leverage some powerful helpers on the python side.
In a new terminal window, within the pi application directory, we can test this out by running the application server:
Then back in our old terminal session for the contract, send a request to register our vehicle:
Looks like it went through!
Using nile, we can veify the transaction was processed by getting the current owner of the vehicle:
โฆit's our account contract's address!
โจ Exercise: Using the AccountClient pattern observed in the registration logic, are you able to refactor the bits that call
attest_state
in thePOST /api/commit
endpoint?
(answer hidden below)
Something along these lines would work well enough. Now letting us separate smart contract interactions and state_hash calculation (i.e. reading from OBD2, formatting & storing data, etcโฆ the boring parts ๐).
If you've implemented it correctly, hitting the route should now return something like this after creating the transaction.
Subsequently, we can verify by reading back the state in the CLI. For car 1, at state_id 1, we see our state was updated correctly: