Compile and Deploy on Secret testnet (best for Javascript devs)
Get started developing on Secret Network using the public testnet and secret.js
What is Secret.js?
In the previous section, we learned how to upload, execute, and query a Secret Network smart contract using SecretCLI and Secret testnet. Now we are going to repeat this process, but we will be uploading, executing, and querying our smart contract on a public testnet using Secret.js.
Secret.js is a JavaScript SDK for writing applications that interact with the Secret Network blockchain.
Key features include:
Written in TypeScript and provided with type definitions.
Provides simple abstractions over core data structures.
Supports every possible message and transaction type.
Exposes every possible query type.
Handles input/output encryption/decryption for Secret Contracts.
Works in Node.js, modern web browsers and React Native.
By the end of this tutorial, you will learn how to:
Add the Secret Testnet to your keplr wallet (and fund your wallet with testnet tokens)
Optimize and compile your Secret Network smart contract
Upload and Instantiate your contract using Secret.js
Execute and Query your contract using Secret.js
Let's get started!
Environment Configuration
To follow along with the guide, we will be using npm,
git,
make,
rust,
and docker
. Follow the Setting Up Your Environment guide here if you need any assistance.
Additionally, you will need to have the Secret Testnet configured with your keplr wallet and also fund it with testnet tokens.
Generate your new counter contract
We will be working with a basic counter contract, which allows users to increment a counter variable by 1 and also reset the counter. If you've never worked with smart contracts written in Rust before that is perfectly fine.
The first thing you need to do is clone the counter contract from the Secret Network github repo. Secret Network developed this counter contract template so that developers have a simple structure to work with when developing new smart contracts, but we're going to use the contract exactly as it is for learning purposes.
Go to the folder in which you want to save your counter smart contract and run:
When you run the above code, it will name your contract folder directory "my-counter-contract". But you can change the name by altering the text that follows the --name
flag.
Start by opening the my-counter-contract
project folder in your text editor. If you navigate to my-counter-contract/src
you will seecontract.rs, msg.rs, lib.rs, and state.rs
โthese are the files that make up our counter smart contract. If you've never worked with a Rust smart contract before, perhaps take some time to familiarize yourself with the code, although in this tutorial we will not be going into detail discussing the contract logic.
In your root project folder, ie
my-counter-contract
, create a new folder. For this tutorial I am choosing to call the foldernode
.In your
my-counter-contract/node
folder, create a new javascript fileโโI chose to name mineupload.js
.Run
npm init -y
to create a package.json file.Add
"type" : "module"
to your package.json file.Install secret.js and dotenv:
npm i secretjs@v1.15.0-beta.1 dotenv
Create a
.env
file in yournode
folder, and add the variableMNEMONIC
along with your wallet address seed phrase, like so:
Never use a wallet with actual funds when working with the testnet. If your seed phrase were pushed to github you could lose all of your funds. Create a new wallet that you use solely for working with the testnet.
Congrats! ๐ You now have your environment configured to develop with secret.js.
Compile the Code
Since we are not making any changes to the contract code, we are going to compile it exactly as it is. To compile the code, run make
build-mainnet-reproducible
in your terminal. This will take our Rust code and build a Web Assembly file that we can deploy to Secret Network. Basically, it just takes the smart contract that we've written and translates the code into a language that the blockchain can understand.
This will create a contract.wasm.gz
file in the root directory.
Uploading the Contract
Now that we have a working contract and an optimized wasm file, we can upload it to the blockchain and see it in action. This is called storing the contract code. We are using a public testnet environment, but the same commands apply no matter which network you want to use - local, public testnet, or mainnet.
Start by configuring your upload.js
file like so:
You now have secret.js imported, a wallet
variable that points to your wallet address, and a contract_wasm
variable that points to the smart contract wasm file that we are going to upload to the testnet. The next step is to configure your Secret Network Client, which is used to broadcast transactions, send queries and receive chain information.
Secret Network Client
Note the chainId and the url that we are using. This chainId and url are for the Secret Network testnet. If you want to upload to LocalSecret or Mainnet instead, all you would need to do is swap out the chainId and url. A list of alternate API endpoints can be found here.
Now console.log(secretjs)
and run node upload.js
in the terminal of your my-counter-contract/node
folder to see that you have successfully connected to the Secret Network Client:
Uploading with secret.js
To upload a compiled contract to Secret Network, you can use the following code:
Run node upload.js
in your terminal to call the upload_contract()
function. Upon successful upload, a codeId and a contractCodeHash will be logged in your terminal:
Be sure to save the codeId
and contractCodeHash
as variables so you can access them in additional function calls.
Instantiating the Contract
In the previous step, we stored the contract code on the blockchain. To actually use it, we need to instantiate a new instance of it. Comment out upload_contract()
and then add instantiate_contract()
.
Note that there is an initMsg
which contains count:0
. You can make the starting count whatever you'd like (as well as the contract label
).
Run node upload.js
in your terminal to call the instantiate_contract()
function. Upon successful instantiation, a contractAddress will be logged in your terminal:
Be sure to save the contractAddress as a variable so you can access it in additional function calls.
Congrats ๐! You just finished uploading and instantiating your first contract on a public Secret Network testnet! Now it's time to see it in action!
Executing and Querying the contract
The way you interact with contracts on a blockchain is by sending contract messages. A message contains the JSON description of a specific action that should be taken on behalf of the sender, and in most Rust smart contracts they are defined in the msg.rs
file.
In our msg.rs
file, there are two enums: ExecuteMsg
, and QueryMsg
. They are enums because each variant of them represents a different message which can be sent. For example, the ExecuteMsg::Increment
corresponds to the try_increment
message in our contract.rs
file.
In the previous section, we compiled, uploaded and instantiated our counter smart contract. Now we are going to query the contract and also execute messages to update the contract state. Let's start by querying the counter contract we instantiated.
Query Message
A Query Message is used to request information from a contract; unlike execute messages
, query messages do not change contract state, and are used just like database queries. You can think of queries as questions you can ask a smart contract.
Let's query our counter smart contract to return the current count. It should be 0, because that was the count we instantiated in the previous section. We query the count by calling the Query Message get_count {}
, which is defined in our msg.rs file. Comment out instantiate_contract()
and then add try_query_count()
.
The query returns:
Great! Now that we have queried the contract's starting count, let's execute an increment{}
message to modify the contract state.
Execute Message
An Execute Message is used for handling messages which modify contract state. They are used to perform contract actions.
Did you know? Messages aren't free! Each transaction costs a small fee, which represents how many resources were required to complete it. This cost is measured in gas units.
The counter contract consists of two execute messages: increment{}
, which increments the count by 1, and reset{}
, which resets the count to any i32
you want. The current count is 0, let's call the Execute Message increment{}
to increase the contract count by 1.
Nice work! Now we can query the contract once again to see if the contract state was successfully incremented by 1. The query returns:
Way to go! You have now successfully interacted with a Secret Network smart contract on the public testnet!
Next Steps
Congratulations! You completed the tutorial and successfully compiled, uploaded, deployed and executed a Secret Contract! The contract is the business logic that powers a blockchain application, but a full application contains other components as well. If you want to learn more about Secret Contracts, or explore what you just did more in depth, feel free to explore these awesome resources:
Millionaire's problem breakdown - explains how a Secret Contract works
CosmWasm Documentation - everything you want to know about CosmWasm
Secret.JS - Building a web UI for a Secret Contract
Last updated