This guide tries to explain how to write and deploy smart contracts to Arweave using Javascript.
Table Of Contents
- Fundamentals
- PreRequisites
- Introduction
- Setting up inital state
- Updating state
- Deployment
- Interacting with the contract
- Summary
Fundamentals
What is a smart contract?
Smart contracts are digital substitutes of real world contracts. Once its coded and pushed to the chain, its immuatable, hence cannot be changed!
How to write one?
There are plenty of networks out there. I deployed my contract to Arweave. Unlike many other networks, the smart contracts on Arweave can be written in JavaScript. The process to write and deploy one is fairly straight forward.
PreRequisites
Complete the above steps before moving ahead.
Introduction
There are two steps to deploying Smart Contracts on Arweave once the prerequisites are completed.
- Write the smart contracts Go through the Contract writing guide by Arweave Team. It contains an example of Hello World that should set your fundamentals straight.
- Deploy them via CLI Once the contract files are ready. To deploy it via the CLI, you would need to export the private key of your Arweave/Finnie Wallet which you must have created earlier. Here is the CLI Usage guide.
Setting up initial state
Please go through the introduction section and explore the attached resources before moving ahead.
Example Contract description : Set up a Decentralised marketplace where people can donate to crowdsource fundraiser listings.
Time to build our Crowdsource App 🥳🥳🥳
In order to do that, we need two contracts to make it work.
A Collection contract that would contain all the information regarding the listing in its state
{
"owner": "6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ",
"name": "Tabs over Spaces",
"description":"This is my first petition. Please vote this petition to make spaces illegal",
"funds":{
"raised":0,
"goal":100,
"records":{
}
}
}
A Parent Crowdsource contract that would contain references to the above created collection contracts in its state
{
"owner": "6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ",
"name": "CrowdSource | PeopleHelpPeople",
"collections":{}
}
Updating state
There are two operations that could happen:
- Users enlist a new crowdsource collection
- Users donate funds to the collection
NOTE: These actions are basic and preliminary. Since I didnt have much time during the hackathon, this was all I could build. But obviously it could be expanded to make the system more usable and robust.
Enlisting a Collection Contract
Lets take a look at the enlist function on the Parent Contract
export function handle(state, action) {
if (action.input.function === 'enlist') {
if (typeof action.input.listingId === 'undefined') {
throw new ContractError(`PetitionId cant be null`)
}
if (state.collections.hasOwnProperty(action.input.listingId)) {
throw new ContractError(`PetitionId already exists`)
}
state.collections[action.input.listingId] = 1
return { state }
}
throw new ContractError('Invalid input')
}
The enlist function performs the essential checks firstly, then adds the reference to the collections object of the state. This serves as a means to keep track of all the crowdsource contracts on the chain.
After enlisting a collection contract, the parent contract state should like this:
{
"owner": "6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ",
"name": "CrowdSource | PeopleHelpPeople",
"collections": {
"Ji6MP-Wt_LYk6yaTsxEnhlpbRpAu08248PUTxnp2qOU": 1
}
}
Donating to a Collection Contract
Once the collection is enlisted, users could transfer funds to the collection. Feel free to use any wallet services to transfer tokens. But make sure you got the correct address on the owner field.
Since I used Finnie wallet, I put my Finnie address inside the owner field.
Here is the Collection Contract
export function handle(state, action) {
if (action.input.function === 'donate') {
if (typeof action.input.donorId === 'undefined') {
throw new ContractError(`DonorId cant be null`)
}
if (typeof action.input.amount === 'undefined') {
throw new ContractError(`amount cant be null`)
}
if (typeof action.input.amount !== 'number') {
throw new ContractError(`amount must be a number`)
}
state.funds.records[action.input.donorId] = action.input.amount;
state.funds.raised += action.input.amount;
return { state }
}
throw new ContractError('Invalid input')
}
After performing essential checks, the contracts state is updated with the donor payment ID(address) and the amount of funds they have contributed.
The default currency is assumed to be KOII. Again a place for improvement. To support various currencies, currency field could be added to the record.
This is how the collection contract would look like once users have donated some funds.
{
"owner": "6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ",
"name": "Tabs over Spaces",
"description": "This is my first petition. Please vote this petition to make spaces illegal",
"funds": {
"raised": 1.2109999999999999,
"goal": 100,
"records": {
"Ji6MP-Wt_LYk6yaTsxEnhlpbRpAu0824": 1.21,
"6Jfg5shIvbAcgoD04mOppSxL6LAqx6IfjL0JexxpmFQ": 0.001
}
}
}
Deployment
To deploy the contracts, use the Smartweave create command:
smartweave create [SRC LOCATION] [INITIAL STATE FILE] --key-file [YOUR KEYFILE]
It takes around 10-15 minutes for the contract to be deployed. Note that you would have to spend some AR in order to deploy the contract.
Once the create command completes, the CLI will output a unique transaction ID for the transaction. This ID is essential to proceed forward.
To check the status of the transaction
arweave status [CONTRACT TXID]
To read the state of the contract
smartweave read [CONTRACT TXID]
For a web GUI experience, check out Viewblock.io. Its a handy website to check all the information about your contracts state, tags and transactions.
Interacting with the contract
It is time to send payloads to interact with the contract i.e. update the state. We would be using the enlist and donate functions that we set up earlier on the contracts.
To interact with the transaction:
smartweave write [CONTRACT TXID] --key-file [YOUR KEYFILE] \
--input "[CONTRACT INPUT STRING HERE]"
For enlisting a contract
smartweave write [Parent Crowdsource Contract TXID] --key-file [YOUR KEYFILE] --input "{"function":"enlist","listingId":"<Collection contract TXID>"}"
For donating tokens to a collection
smartweave write [Collection Contract] --key-file [YOUR KEYFILE] --input '{"function":"donate","donorId":"<Donor wallet address>","amount":<number of tokens>}'
Summary
Congratulations 🥳🥳🥳
Hope you liked reading through the article. To summarise the learnings, you should have understood:
- What are smart contracts
- How to write and deploy one on Arweave
- How to Interact with them
Read about my project I built for the hackathon if you're interested below 🙂
Bonus Tip
All of these are done via CLI, but to scale it to a real world application. You would need to the Arweave SDKs and APIs.
Happy Exploring 😉
About my project
Its called People Help People, the origin of the name comes from the idea of a society where people are not dependent on middle men or central systems to help each other. One can find more information about the Aim and Goals on the Pitch Deck.
This is a blockchain based project. It has two parts to it. The smart contracts and the web client interface.
The project presently consists of two prototypes
Both of these prototypes inherits the idea of PHP, i.e. to defeat the intervention of a central system. Hence I covered only one of them in the article. Once I learnt the basic fundamentals of how smart contracts work and how to write one, giving life to these two ideas was plain sailing.
Devfolio Submission link: https://devfolio.co/submissions/people-help-people-a3c8
GitHub Repo link: https://github.com/HarishTeens/PeopleHelpPeople
I had to struggle a lot to walk through the right steps in order to learn this. So I tried my best to make the learning smooth for a beginner. Please share your feedbacks in the comments.
Join the Movement
If you're interested in joining the movement, dm me on Twitter so I could add you to the organisation People Help People on GitHub. It's a very recent org, so it appears to be blank at the moment. But definitely planning to work on it in the future ✨
Follow me on Twitter @HarishTeens
Top comments (0)