MANTRA Chain
  • Introduction
    • Overview
    • Why MANTRA Chain
    • Building on MANTRA Chain
    • MANTRA RWA Suite
  • Using MANTRA Chain
    • MANTRA Chain Wallet Setup
      • Connect to Testnet
      • Connect to Mainnet
      • Testnet Faucet
    • MANTRA Zone
    • MANTRA Bridge
      • MANTRA Bridge User Guide
      • MANTRA Bridge FAQs
    • Stake
      • Stake User Guide
      • Stake FAQs
    • MANTRA Swap
      • MANTRA Swap User Guide
      • Liquidity Pools User Guide
      • MANTRA Swap FAQs
    • Claiming Journey
      • Check If You're Eligible
      • Claiming Journey User Guide
      • I've redeemed my rewards, now what?
    • Chakra Pool
      • What can I do with my USDY
      • Chakra Pool Deposit Guide
      • How KARMA works for Chakra Pool
        • How much KARMA do I get for depositing into Chakra Pool?
        • Can I make multiple deposits and how will KARMA be calculated then?
        • My KARMA is not updated even though I make multiple deposits?
        • Will I get daily KARMA for my deposit on USDY Chakra Pool launched on Hongbai earlier?
      • Chakra Pool FAQs
    • MANTRA Zone Leaderboard
      • MANTRA Zone Leaderboard User Guide
        • Mission Guides
          • Pledge your OM 🕉️
          • Claim OM Staking Rewards
          • OMly Drip 💧
      • MANTRA Zone Leaderboard FAQs
  • Developing on MANTRA Chain
    • Getting Started
      • DuKong Testnet
      • Install Prerequisites
      • Setting Up Dev Environment
      • Compiling a Contract
      • Deployment and Interaction
    • CosmWasm Quick Start Guide
      • CosmWasm Contracts
      • Understanding CosmWasm File Structure
    • DAPP Tooling
      • Cosmos SDK
      • Important Libraries
      • Developer Resources
    • Developer FAQs
  • MANTRA Smart Contracts
    • Overview
    • MANTRA Dex
      • 🚢Deployments
      • 📚Common Types
      • 💰Fee Collector
      • ⌛Epoch Manager
      • 🌊Pool Manager
      • 🎁Farm Manager
    • Claimdrop Contract
    • Audits
  • Node & Validator Operations
    • Overview
    • Node Setup & Deployment
      • Node System Requirements
      • Running a Node
      • How to run Mantrachain with Systemd
      • Validator Nodes
        • Connect sidecar
    • Validator Architecture Recommendations
      • Secure Validator
    • Governance
      • Draft a Proposal
        • Text Proposal
        • Community Spend Proposal
        • Software Upgrade
        • Cancel Software Upgrade
      • Submitting a Proposal
      • Verifying your transaction
      • Depositing funds
      • Voting on a Proposal
    • Download nodes snapshots
  • MANTRA Chain with EVM (Alpha)
    • Getting Started on OMSTEAD Testnet
  • Setup Instructions
  • Using Foundry
    • Deployment with Foundry
  • Using Hardhat
    • Deployment with Hardhat
  • Mainnet OM Information
    • Background
    • Updated OM Tokenomics
    • OM Distribution Updates
    • Inflation & Vesting Schedule
    • Legacy tokens to mainnet staking tokens
  • Appendix
    • Frequently Asked Questions
      • General FAQs
        • What is MANTRA Chain?
        • What are the key features/ modules available to builders on MANTRA Chain?
        • What support is available for developers and validators that join the ecosystem
        • Where can i find MANTRA Social Accounts & Communities?
        • How can an Issue or a bug be reported?
        • How can I identify official MANTRA communication and websites?
      • Validator FAQs
        • What does a new validator’s journey look like?
        • What are my key responsibilities as a validator?
        • What is uptime and how is it maintained?
        • What are the hardware requirements?
        • How to get validator keys?
        • How can I connect a validator from an older testnet to the newest testnet?
        • How do I create a backup snapshot of a node?
        • How do I restore a node from a snapshot?
        • What are the different states a validator can be in?
        • How do I unjail a validator?
        • How do I edit a validator's description?
        • What is self-delegation?
        • Is there a minimum amount of OM that must be delegated to be an active validator?
      • Developer FAQs
        • What is MANTRA Chain, and how does it utilize the Cosmos ecosystem?
        • How does MANTRA Chain ensure interoperability with other blockchains in the Cosmos ecosystem?
        • What is the Cosmos ecosystem, and how does it differ from other blockchain platforms?
        • Which programming languages are commonly used for developing on the Cosmos ecosystem?
        • How do I get started with development on the Cosmos ecosystem?
        • What are Cosmos SDK and Tendermint, and how do they work together?
        • What are Cosmos zones and how do they interact?
        • How do I build and deploy smart contracts on the Cosmos ecosystem?
        • How do I interact with Cosmos chains and applications programmatically?
        • What is the best way to learn about developing for the MANTRA Chain and Cosmos ecosystem?
      • Hongbai FAQs
        • Where do I sign up for Hongbai?
        • Why do I need to provide 2 wallets during signup?
        • How can I Login?
        • What should I do if I forgot my password?
        • What can I do if i forget my registered email?
        • Where do i verify my email?
        • How to connect my Metamask wallet?
        • Is Hongbai app a testnet or live app?
        • Can I change my wallet ?
        • Error “invalid user credentials“
        • Why can i not Invest?
      • How to Guides
        • Install Keplr Wallet
        • Keplr and Ledger
        • Add DuKong Testnet to Keplr
        • Get Tokens from Faucet
        • Track activity on Leaderboard
      • More Help & Support
      • MANTRA Zone FAQs
        • MANTRA Zone General FAQs
          • What wallets are currently supported on the MANTRA Zone?
          • How do I connect my wallet to the MANTRA Zone?
          • How do I copy my connected wallet’s address?
          • How do I connect a different wallet to the MANTRA Zone?
          • Can I disconnect my wallet from MANTRA Zone?
          • How can I resolve seeing multiple entires of the same amount of testnet OM in my Keplr wallet?
          • The question that I have is not covered by the FAQ, what should I do?
        • MANTRA Bridge FAQs
          • What is MANTRA Bridge?
          • Why should I use the MANTRA Bridge?
          • Is there a fee for using the MANTRA Bridge?
          • Do I have to pay gas fees?
          • What tokens will I receive?
          • How does the migration process work?
          • How long should the MANTRA Bridge order take?
          • How can I track the status of my MANTRA Bridge order?
          • What happens to my ERC20 OM tokens once I use the MANTRA Bridge?
          • Which network can I use on the MANTRA Bridge?
          • What should I do if I see ‘Wrong network’ error on the app?
          • Will there be a two-way bridge in the future?
          • My MANTRA Bridge order is stuck on Ethereum?! How can I fix this?
          • Who can I contact for support during the migration process?
          • Which EVM chains can I bridge from?
          • Are the OM tokens I receive wrapped tokens or the native MANTRA Chain OM tokens?
          • Is the MANTRA Bridge a non-custodial solution?
          • What happens if the MANTRA Bridge is hacked or goes offline?
          • Are there any risks associated with using the MANTRA Bridge?
          • How does the MANTRA Bridge ensure the security of my tokens during migration?
          • Can I use my existing Ethereum wallet to access the MANTRA Bridge?
          • How does wallet linking and airdrop participation work?
        • Stake FAQs
          • What is Stake?
          • What are validators, and how do I choose one?
          • What rewards can I earn by staking $OM?
          • How are staking rewards calculated?
          • Can I choose to unstake my $OM coins?
          • What is the unbonding period?
          • Can I change validators after staking $OM?
          • Can I stake $OM with multiple validators?
          • Are there any risks involved with staking $OM?
          • Will my rewards gets automatically restaked after redemption?
          • Do I lose my claimable rewards when performing actions with a validator with unclaimed rewards?
          • My wallet is showing a 0 balance even though I have funds. What should I do?
          • How do I know if my $OM is staked?
        • Chakra Pool FAQs
          • What are the Chakra Pool rewards?
          • What is USDY?
          • How do I get the yield from the treasury bonds by holding USDY?
          • Can I change my linked wallet?
          • I don’t remember my linked wallet - what can I do?
          • What are the bonus rewards and where I can see my rewards?
          • How are the USDY rewards calculated and when can I redeem my USDY rewards?
          • How are the $OM rewards calculated and when can I redeem my $OM rewards?
          • How are the $ONDO rewards calculated and when can I redeem my $ONDO rewards?
          • What can I do with my USDY and $OM rewards after redemption?
        • MANTRA Zone Leaderboard FAQs
          • I have someone that wants to participate in the MANTRA Zone Leaderboard but they don’t know how.
          • What does the ⚡icon and ‘Get + x KARMA’ text under the ‘KARMA’ section refer to?
          • The KARMA on the Zone Leaderboard only lists MANTRA Chain wallets, how to check my EVM wallet rank?
          • Which wallet IDs are visible on the Leaderboard Ranking Table?
          • Why are there three different categories for the Leaderboard Ranking Table?
          • How can I get the Leaderboard Ranking Table to show where my connected wallet ranks currently?
          • How can I search where a specific wallet ID ranks in the Leaderboard Ranking Table?
          • How can I search what wallet ID currently ranks in a specific ranking number?
          • My KARMA and/or multiplier amount did not update on the Leaderboard Ranking Table, why is that?
          • What is the calculation for the KARMA?
          • I’m unable to see the OMly Faucet on my Keplr/Cosmostation wallet
          • I'm unable to see my OMly Faucet Claim transaction on the explorer
          • The question that I have is not covered by the FAQ, what should I do?
        • MANTRA Swap FAQs
          • What is Swap?
          • How can I swap?
          • I have connected my EVM wallet, but I’m still unable to swap. Why?
          • Where can I view my past transactions?
          • Why is my swap button disabled?
          • Why can’t I swap with a slippage more than 5%?
          • What is Exchange Rate?
          • How do I get OM tokens in my wallet?
          • How do I get other tokens in my wallet?
          • Will the swap fee be deducted from my sell or buy token?
          • Why can’t I see the balance of tokens in my wallet but on the Swap panel?
          • How do I add liquidity to a pool?
          • I am unable to provide liquidity to the pool.
          • While adding liquidity, why are the two tokens USD value not equal?
          • How do I withdraw my funds from Liquidity Pools?
          • Why can I not see my tokens for withdrawal?
          • Why can I not remove liquidity?
          • Why is my deposited value of the two tokens changing in my position?
          • Do liquidity pools have a bonding period?
          • What are LP tokens?
          • What can I do with my LP tokens?
          • Why can I not see any LP token balance?
          • I am connected with my MANTRA wallet, but still cannot view my positions?
          • I provided liquidity, but I can’t see my position. What should I do?
          • Why is my transaction not successful?
    • Glossary
    • MANTRA's Incentivised Testnet
      • Testnet Phase 1
      • Hongbai - Testnet Phase 2
  • Third Party Bridges
    • Base Bridge
    • Polygon Bridge
Powered by GitBook
On this page
  • mantrachaind CLI
  • CosmJS Node Console
  1. Developing on MANTRA Chain
  2. Getting Started

Deployment and Interaction

PreviousCompiling a ContractNextCosmWasm Quick Start Guide

Last updated 6 months ago

Deployment on the MANTRA Chain can be performed in two ways, depending on your operating system compatibility and preferred development approach. These methods are as follows:

Using mantrachaind

In this method, the instantiation and interaction with the binary are done using the mantrachaind CLI or the CosmJS Node Console, which results in deploying CW contracts on-chain. Refer to this section for understanding the deployment and interaction with the chain. Additionally, see the section “” for deploying the contract on the DuKong Testnet with the poke.wasm example.

Using TypeScript

This approach utilizes cosmwasm-tools and ts-codegen, which let you generate TypeScript classes for your contracts' interaction and on-chain deployment. Refer to the section “” below to set up your development environment and deploy your contracts on the DuKong Testnet.

From the previous section, we have the wasm binary ready. Now it is time to deploy it on DuKong and start interacting. You can use the mantrachaind CLI or the CosmJS Node Console as you prefer.

mantrachaind CLI

Let's deploy the code to the blockchain. Once that is complete, you can download the bytecode to verify it.

See the list of codes that was uploaded to the network previously.

mantrachaind query wasm list-code $NODE
# Here is an alternative if you haven't set up the environment variables to interact with the network previously:
mantrachaind query wasm list-code --node <https://rpc.dukong.mantrachain.io:443>

Now let us store the bytecode onchain and acquire the Code Id. The Code Id will later be used to create an instance of the cw_namespace contract.

# If you have already set up the environment variables, you can use the following command:
RES=$(mantrachaind tx wasm store artifacts/cw_nameservice.wasm --from wallet $TXFLAG -y --output json)
# Otherwise, you will have to type in the following command to upload the wasm binary to the network:
RES=$(mantrachaind tx wasm store artifacts/cw_nameservice.wasm --from wallet --node <https://rpc.dukong.mantrachain.io:443> --chain-id mantra-dukong-1 --gas-prices 0.01uom --gas auto --gas-adjustment 2 -y --output json)
# The response contains the Code Id of the uploaded wasm binary.
echo $RES

# Get the Transaction Hash from the response
TX_HASH=$(echo $RES | jq -r .txhash)

# Get the full transaction details with events 
CODE_ID=$(mantrachaind query tx $TX_HASH --node <https://rpc.dukong.mantrachain.io:443> -o json| jq -r '.logs[0].events[] | select(.type == "store_code") | .attributes[] | select(.key == "code_id") | .value')

echo $CODE_ID

Let's see the list of contracts instantiated using the Code Id above.

mantrachaind query wasm list-contract-by-code $CODE_ID --node <https://rpc.dukong.mantrachain.io:443> --output json

The response should be an empty list as we have not instantiated any contract yet.

{"contracts":[],"pagination":{"next_key":null,"total":"0"}}

Before we instantiate a contract with the Code Id and interact with it, let us check if the code stored on the blockchain is indeed the cw_namespace.wasm binary we uploaded. This step is optional.

# Download the wasm binary from the chain and compare it to the original one
mantrachaind query wasm code $CODE_ID --node <https://rpc.dukong.mantrachain.io:443> download.wasm
# The two binaries should be identical, and the `diff` command should return notnothing
diff artifacts/cw_nameservice.wasm download.wasm

Instantiating the Contract

We can now create an instance of the wasm contract. Following the instantiation, we can make queries and this time receive non-empty responses.

# Prepare the instantiation message
INIT='{"purchase_price":{"amount":"100","denom":"uom"},"transfer_price":{"amount":"999","denom":"uom"}}'
# Instantiate the contract
mantrachaind tx wasm instantiate $CODE_ID "$INIT" --from wallet --label "name service" $TXFLAG -y --no-admin

# Check the contract details and account balance
mantrachaind query wasm list-contract-by-code $CODE_ID $NODE --output json
CONTRACT=$(mantrachaind query wasm list-contract-by-code $CODE_ID $NODE --output json | jq -r '.contracts[-1]')
echo $CONTRACT

# See the contract details
mantrachaind query wasm contract $CONTRACT $NODE
# Check the contract balance
mantrachaind query bank balances $CONTRACT $NODE

# Upon instantiation the cw_nameservice contract will store the instatiation message data in the contract's storage with the storage key "config".
# Query the entire contract state
mantrachaind query wasm contract-state all $CONTRACT $NODE
models:
- key: 0006636F6E666967
  value: eyJwdXJjaGFzZV9wcmljZSI6eyJkZW5vbSI6InVtbGciLCJhbW91bnQiOiIxMDAifSwidHJhbnNmZXJfcHJpY2UiOnsiZGVub20iOiJ1bWxnIiwiYW1vdW50IjoiOTk5In19
pagination:
  next_key: null
  total: "0"
 # Note that the storage key "config" is hex encoded and prefixed with two bytes indicating its length
# echo -n config | xxd -ps
# gives 636f6e666967
# thus we have the following output: 0006636f6e666967
 
# You can also query a storage key directly
mantrachaind query wasm contract-state raw $CONTRACT 0006636f6e666967 $NODE --hex

# The base64 encoded response is the stored value corresponding to the storage key "config" and reads as follows:
# {"purchase_price":{"denom":"uom","amount":"100"},"transfer_price":{"denom":"uom","amount":"999"}}

# Note that keys are hex encoded, and the values are base64 encoded.
# To view the returned data (assuming it is ascii), try something like:
# (Note that in many cases the binary data returned is not in ascii format, thus the encoding)
mantrachaind query wasm contract-state all $CONTRACT $NODE --output "json" | jq -r '.models[0].key' | xxd -r -ps
mantrachaind query wasm contract-state all $CONTRACT $NODE --output "json" | jq -r '.models[0].value' | base64 -d

# The cw_namespace contract implements a QueryMsg that returns the contents of the storage
# So, we can also try "smart querying" the contract
CONFIG_QUERY='{"config": {}}'
mantrachaind query wasm contract-state smart $CONTRACT "$CONFIG_QUERY" $NODE --output json

# and the contract will return the following response:
# {"data":{"purchase_price":{"denom":"uom","amount":"100"},"transfer_price":{"denom":"uom","amount":"999"}}}

Contract Interaction

Now that the contract is instantiated, let's register a name and transfer it to another address by paying the transfer fee.

# Register a name for the wallet address
REGISTER='{"register":{"name":"fred"}}'
mantrachaind tx wasm execute $CONTRACT "$REGISTER" --amount 100uom --from wallet $TXFLAG -y

# Query the owner of the name record
NAME_QUERY='{"resolve_record": {"name": "fred"}}'
mantrachaind query wasm contract-state smart $CONTRACT "$NAME_QUERY" $NODE --output json
# {"data":{"address":"wasm1pze5wsf0dg0fa4ysnttugn0m22ssf3t4a9yz3h"}}

# Transfer the ownership of the name record to wallet2 (change the "to" address to wallet2 generated during environment setup)
mantrachaind keys list
TRANSFER='{"transfer":{"name":"fred","to":"wasm1lwcrr9ktsmn2f7fej6gywxcm8uvxlzz5ch40hm"}}'
mantrachaind tx wasm execute $CONTRACT "$TRANSFER" --amount 999uom --from wallet $TXFLAG -y

# Query the record owner again to see the new owner address:
NAME_QUERY='{"resolve_record": {"name": "fred"}}'
mantrachaind query wasm contract-state smart $CONTRACT "$NAME_QUERY" $NODE --output json
# {"data":{"address":"wasm1lwcrr9ktsmn2f7fej6gywxcm8uvxlzz5ch40hm"}}

CosmJS Node Console

The binary can be deployed to the chain, instantiated and interacted with using the CosmJS Node Console as well.

Open a new Terminal window and initialize a CosmJS CLI session with the following command:

npx @cosmjs/cli@^0.28.1 --init <https://raw.githubusercontent.com/InterWasm/cw-plus-helpers/main/base.ts>

Now, let's import the necessary utilities, generate a wallet address, and deploy the wasm binary to the blockchain.

import { calculateFee, StdFee} from "@cosmjs/stargate"
import { coin } from "@cosmjs/amino"

const [addr, client] = await useOptions(malagaOptions).setup("password");
// Make sure you use the right path for the wasm binary
const wasm = fs.readFileSync("/home/{username}/.../cw-contracts/contracts/nameservice/artifacts/cw_nameservice.wasm")
const uploadFee = calculateFee(malagaOptions.fees.upload, malagaOptions.gasPrice)
const result = await client.upload(addr, wasm, uploadFee)
console.log(result)
{
  originalSize: 140819,
  originalChecksum: 'f388fff922ffbb3845311608887636346eac6246ee20578e11e3577226466e7b',
  compressedSize: 52176,
  compressedChecksum: 'e5a1d70aedf1c2d6b1a3cbeec2981ac84c3ae48f642e221608b1624ccc6d65ba',
  codeId: 17,
  logs: [ { msg_index: 0, log: '', events: [Array] } ],
  transactionHash: '34FA5BE9991578C56961C6BA7F5B25474BAFCE44954035217A93FE91BCC673A1'
}

Please note the codeId of the uploaded wasm binary. This is the codeId that will be used to instantiate the contract.

You may compare the value of originalChecksum with the contents of the file artifacts/checksums.txt to make sure the code on the chain is identical to the cw_nameservice.wasm binary.

For future reference, you may get the checksum for a given Code Id as follows:

//If you haven't created/loaded a wallet yet, you can do so with the following command:
//const [addr, client] = await useOptions(malagaOptions).setup("password"); 

const codeIdToVerify = 17
const codes = await client.getCodes() 
const hash = codes.filter((x) => x.id === codeIdToVerify).map((x) => x.checksum)[0];
console.log(hash)

You may then compile the contract code yourself, optimize the resulting binary and compare the checksum to the value of hash to make sure the code on the chain was not tampered with.

Instantiating the Contract

Now, the wasm binary is uploaded to the chain with a Code Id and is ready to be instantiated.

First define a defaultFee to be passed into instantiation and execution functions later on:

const defaultFee: StdFee = { amount: [{amount: "200000", denom: "uom",},], gas: "200000",};

Create a cw_nameservice contract instance using the code id we have received upon upload.

//Replace the Code Id with the one you have received earlier
const codeId = 17
//Define the instantiate message
const instantiateMsg = {"purchase_price":{"amount":"100","denom":"uom"},"transfer_price":{"amount":"999","denom":"uom"}}
//Instantiate the contract
const instantiateResponse = await client.instantiate(addr, codeId, instantiateMsg, "Our Name Service", defaultFee)

console.log(instantiateResponse)
{
  contractAddress: 'wasm1s66zhks8v3fm24974crzxufh7w6ktt69jq8e3zt8q7cyvr52vlqqlzl7sc',
  logs: [ { msg_index: 0, log: '', events: [Array] } ],
  transactionHash: '27F4B6B41C36AB6B8324C125EFAE6C535093A6229CDF3665B998CD071E1566E2'
}

We've successfully instantiated the contract and have a contract address for the new instance.

The list of contracts instantiated using a certain codeId can be queried using the following command:

const contracts = await client.getContracts(17)
console.log(contracts);

Contract Interaction

Now let us register a name on the nameservice contract instance and transfer it to another address.

//Enable REPL editor mode to edit multiple lines of code
.editor

const executeResponse = await client.execute(
         addr,
         instantiateResponse.contractAddress,
         {
           register:{name:"fred"}
         },
         defaultFee,
         '',
         [coin(100, "uom")]
       )
//Exit the editor using `^D` to execute the code entered
^D

Query the name record to see the owner address.

const queryResponse = await client.queryContractSmart(instantiateResponse.contractAddress, {resolve_record: {name:"fred"}})
console.log(queryResponse)
//It should match your wallet address
console.log(addr)

Now, let us create another wallet and transfer the ownership of the name to the new wallet address.

const [anotherAddress, anotherClient] = await useOptions(malagaOptions).setup("password",".another_wallet.key");

//Enable REPL editor mode to edit multiple lines of code
.editor

const executeResponse_2 = await client.execute(
         addr,
         instantiateResponse.contractAddress,
         {
          transfer:{
            name:"fred",
            to:anotherAddress
          }
         },
         defaultFee,
         '',
         [coin(999, "uom")]
       )

Query the name record one more time to see the address for the new owner.

const queryResponse_2 = await client.queryContractSmart(instantiateResponse.contractAddress, {resolve_record: {name:"fred"}})
console.log(queryResponse_2)
//The response should match the new wallet address after the change of ownership
console.log(anotherAddress)
A Quick Example for Deployment Using mantrachaind
Deployment Using TypeScript (Windows/Linux/Mac)