Crowdfunding App

Deploying a crowdfunding App using the Andromeda CLI.

We have covered earlier the App contract and its messages. We briefly discussed the steps to deploying an App. In this section we will be providing an example of how to deploy an App using the Andromeda CLI.

If any of the messages in this example do not work, you might want to cross reference the messages with the ADO specific section which always contains the latest ADO versions to make sure they are correct. Other than that the logic will remain the same.

Make sure to read the Introduction to Apps before going through building an app.

The Steps of Deploying an App

We already have an ADODB contract with saved code IDs of the ADOs and Kernel ADO deployed. These addresses can be found in Deployed Contracts section. This means that to deploy an App we only need to instantiate it through the CLI.

You will need the deployed Kernel contract address as it needs to be specified when instantiating any ADO.

Defining our App

For this example we will be building a simple crowdfunding app. We will be creating NFTs that are sold in a crowdfund and then the proceeds are distributed to a sepcified address. If the crowdfund does not reach the threshold of minimum tokens sold, the money is refunded to the buyers.

Defining the Messages

For this example, our App needs to have 5 components/ADOs:

Although not necessary, if you are unfamiliar with these ADOs, it is suggested to read through each of the them before deploying an app.

Let us first start by representing the instantiation message for each of our ADOs:

Keep in mind that the app takes these messages as base64 encoded.

Some of your base64 messages will not be the exact same as the ones in the example as you will be using your own addresses.

Token

Don't forget to set the minter as the crowdfund ADO.

You can get the Kernel address by running "chain config" in CLI.

When referencing a component in an app, you need to put "./<component-name>" similar to what we do here with the minter field.

{
"name":"Example App",
"symbol":"SMMT",
"minter":"./crowdfund",
"kernel_address":"andr159llw7xkpt20llxqmjegsegfn548q5l6jr2x7rh7sy7sal39syfs3tlvmm"
}

The JSON message in our case is the following as Base64:

eyJuYW1lIjoiRXhhbXBsZSBBcHAiLCJzeW1ib2wiOiJTTU1UIiwibWludGVyIjoiLi9jcm93ZGZ1bmQiLCJrZXJuZWxfYWRkcmVzcyI6ImFuZHIxNTlsbHc3eGtwdDIwbGx4cW1qZWdzZWdmbjU0OHE1bDZqcjJ4N3JoN3N5N3NhbDM5c3lmczN0bHZtbSJ9

Crowdfund

{
"token_address":"./tokens",
"can_mint_after_sale":true,
"kernel_address":"andr159llw7xkpt20llxqmjegsegfn548q5l6jr2x7rh7sy7sal39syfs3tlvmm"
}  

As Base64:

eyJ0b2tlbl9hZGRyZXNzIjoiLi90b2tlbnMiLCJjYW5fbWludF9hZnRlcl9zYWxlIjp0cnVlLCJrZXJuZWxfYWRkcmVzcyI6ImFuZHIxNTlsbHc3eGtwdDIwbGx4cW1qZWdzZWdmbjU0OHE1bDZqcjJ4N3JoN3N5N3NhbDM5c3lmczN0bHZtbSJ9IA==

App

The Kernel address used here might be outdated in the future. Check our deployed contracts to get the latest Kernel or run "chain config" in CLI which will also display the address.

{
  "name": "Crowdfunding",
  "app_components": [
    {
      "name": "crowdfund",
      "ado_type": "crowdfund",
      "component_type":{
       "new":"eyJ0b2tlbl9hZGRyZXNzIjoiLi90b2tlbnMiLCJjYW5fbWludF9hZnRlcl9zYWxlIjp0cnVlLCJrZXJuZWxfYWRkcmVzcyI6ImFuZHIxNTlsbHc3eGtwdDIwbGx4cW1qZWdzZWdmbjU0OHE1bDZqcjJ4N3JoN3N5N3NhbDM5c3lmczN0bHZtbSJ9"
       }
     },
    {
      "name": "tokens",
      "ado_type": "cw721",
      "component_type":{
      "new":"eyJuYW1lIjoiRXhhbXBsZSBBcHAiLCJzeW1ib2wiOiJTTU1UIiwibWludGVyIjoiLi9jcm93ZGZ1bmQiLCJrZXJuZWxfYWRkcmVzcyI6ImFuZHIxNTlsbHc3eGtwdDIwbGx4cW1qZWdzZWdmbjU0OHE1bDZqcjJ4N3JoN3N5N3NhbDM5c3lmczN0bHZtbSJ9"
       }
    }
  ],
  "kernel_address":"andr159llw7xkpt20llxqmjegsegfn548q5l6jr2x7rh7sy7sal39syfs3tlvmm"
}

There are several components found here. A simple name for the app, the components of the app itself and a reference to the “Kernel”. Each component of the app provides two values: a name used for referencing for other components within the app, and the base64 encoded instantiation message.

Instantiating the App

If you do not have the CLI downloaded, go to the Introduction to Apps section to get the latest version.

First, let us open the CLI by running andr in our terminal. We then need to choose the chain we want to deploy on. Run "chain use" in the CLI and select the testnet that you want to deploy on. For this example I will be using the Andromeda test-net Galileo-3.

If this is the first time using the CLI make sure to run "wallet add <wallet-name>"in order to create a wallet. Then go to that chain's faucet (usually located in their discord) and request tokens.

We have already uploaded the App ADO to the Andromeda testnet. A simple way to check the latest code id for the App ADO is to query it from the ADODB using the chain you want to use.

In the CLI, while connected to the chain of choice, run:

ado db getcodeid app-contract

The code Id to use will be returned.

Now we can instantiate our App. We will be using our wasm command to instantiate our app:

Note that the instantiation message will not be the exact same for you since you will be using a different recipient address.

Do not copy and paste the command below as it will not work. Make sure to make the appropriate changes before running the command.

Replace the <code_id> with the returned code-id for the app ADO.

wasm instantiate <code-id> '{"name": "Crowdfunding","app_components": [{"name": "crowdfund","ado_type": "crowdfund","component_type":{"new":"eyJ0b2tlbl9hZGRyZXNzIjoiLi90b2tlbnMiLCJjYW5fbWludF9hZnRlcl9zYWxlIjp0cnVlLCJrZXJuZWxfYWRkcmVzcyI6ImFuZHIxNTlsbHc3eGtwdDIwbGx4cW1qZWdzZWdmbjU0OHE1bDZqcjJ4N3JoN3N5N3NhbDM5c3lmczN0bHZtbSJ9"}},{"name": "tokens","ado_type": "cw721","component_type":{"new":"eyJuYW1lIjoiRXhhbXBsZSBBcHAiLCJzeW1ib2wiOiJTTU1UIiwibWludGVyIjoiLi9jcm93ZGZ1bmQiLCJrZXJuZWxfYWRkcmVzcyI6ImFuZHIxNTlsbHc3eGtwdDIwbGx4cW1qZWdzZWdmbjU0OHE1bDZqcjJ4N3JoN3N5N3NhbDM5c3lmczN0bHZtbSJ9"}}],"kernel_address":"andr159llw7xkpt20llxqmjegsegfn548q5l6jr2x7rh7sy7sal39syfs3tlvmm"}'

Upon instantiation, we will get a link to the explorer where we can check the transaction. Also the contract address of the App is displayed:

Transaction

Open the explorer link where you can see that the instantiation was a success. Three contracts were instantiated in total which are the App and the 2 components we used.

Interacting with the App

You will be using the contract addresses that were instantiated for you instead of the ones in this tutorial.

You will prompted to add funds when executing. Do not add any funds unless specified in the example.

Crowdfund

Now that the App has been created and we have ownership over all the components, we can proceed with minting the tokens for the crowdfund.

Mint

We will be minting three new tokens using the crowdfund component.

Here we use a random token uri. This uri should point to the saved metada of the NFT (IPFS).

{
    "mint":[
        {
            "token_id":"1",
            "token_uri":"https://gateway.pinata.cloud/ipfs...",
            "extension": {
                "publisher": "Andromeda"
              }            
        },
         {
            "token_id":"2",
            "token_uri":"https://gateway.pinata.cloud/ipfs...",
            "extension": {
                "publisher": "Andromeda"
              }            
        },
         {
            "token_id":"3",
            "token_uri":"https://gateway.pinata.cloud/ipfs...",
            "extension": {
                "publisher": "Andromeda"
              }            
        }
    ]
}

Let us run the execute:

Replace <crowdfund-contract-address> with your instantiated crowdfund contract address. You can get the addresses of the components by using an App query.

wasm execute <crowdfund-contract-address> '{"mint":[{"token_id":"1","token_uri":"https://gateway.pinata.cloud/ipfs...","extension": {"publisher": "Andromeda"}},{"token_id":"2","token_uri":"https://gateway.pinata.cloud/ipfs...","extension": {"publisher": "Andromeda"}},{"token_id":"3","token_uri":"https://gateway.pinata.cloud/ipfs...","extension": {"publisher": "Andromeda"}}]}' 

Transaction

In this message multiple tokens are minted and their mint messages are proxied to the “tokens” contract found within the app. No owner is provided, although one can be declared, so the crowdfund contract is assigned as the owner of the tokens for the duration of the sale.

Since we have minted our tokens, we can now start the crowdfund sale.

Start Sale

We call the StartSale message to start the crowfunding sale on the NFTs we minted.

{"start_sale": {
        "expiration": {
          "at_time": "1751933560585000000"
        },
        "price": {
          "amount": "1000",
          "denom": "uandr"
        },
        "min_tokens_sold": "0",
        "recipient":{
            "address":"<address-to-receive-funds>"
          }
        }
      }

Make sure the at_time you specify is not in the past. You can use an online converter to convert a date to a timestamp. Alternatively, you can use a block height to specify the expiration.

Use your own recipient address.

Let us run the execute:

wasm execute <crowdfund-contract-address> '{"start_sale": {"expiration": {"at_time": "1701933560585000000"},"price": {"amount": "1000","denom": "uandr"},"min_tokens_sold": "0","recipient":{"address":"andr14pmn28jyqgphd5wv0z28ppxe5ryeraqqgqfr2v"}}}'

Transaction

This message commences a sale, listing each token for 1000uandr with a minimum of 0 and expires at time 1751933560585000000 . The recipient defined in this message will be the receiver of the funds after the sale has ended. In this case the recipient is another address.

Let's query the balance of the recipient before purchasing the NFTs. We run the following command::

? user@galileo-3> bank balance uandr <recipient-address>

Result:

{ denom: 'uandr', amount: '56926827' }

Balance
uandr: 56926827

The sale has started, time to purchase our minted tokens.

Purchase the tokens

{
"purchase":{
    "number_of_tokens":1
    }
}

In order to purchase a token, you will need to attach funds to the message equal to the price of the NFT which is 1000 uandr in our case. When you run the message, you will be asked "Would you like to add funds to this message?". Select yes and input 1000uandr as the amount.

wasm execute <crowdfund-contract-address> '{"purchase":{"number_of_tokens":1}}'

For purchasing the tokens I will be using three addresses representing buyers.

Purchase token 1

Purchase token 2

Purchase token 3

EndSale

Now that the tokens have been sold the sale can be ended:

You can only end a sale if all the tokens have been sold or the expiration has been reached. In our case, we have bought all the tokens for sale, so we can end the sale.

{
"end_sale":{}
}

Two messages should be sent due to pagination concerns. One will distribute the tokens to the purchasers and the other sends the funds.

wasm execute <crowdfund-contract-address> '{"end_sale":{}}'

First EndSale

We have successfully:

  1. Minted tokens for the crowdfund

  2. Started a sale to sell the tokens

  3. Purchased the tokens for 1000 uandr each

  4. Ended the sale

Since each of the tokens was sold for 1000 uandr we should have 3000uandr sent to the recipient address that we specified in the StartSale message/ To make sure of the results, let us check the balance again:

? user@galileo-3> bank balance uandr andr14pmn28jyqgphd5wv0z28ppxe5ryeraqqgqfr2v
{ denom: 'uandr', amount: '56929827' }

Balance
uandr: 56929827

We can see that 3000uandr has been added to the balance.

You can also use the OwnerOf query to check who owns the NFTs now. It should correspond to your buyers.

Conclusion

This example serves as a small tutorial for building an Andromeda app using the CLI. We will have many more examples like this coming soon representing the different apps that we can build using our ADOs. These tutorials are mostly made for developers looking to use and build using our ADOs. All what we did here and more can be done using our user friendly web-app with a few clicks.

Last updated

Additional Resources

GithubWebsite