This tutorial illustrates how Avalanche can be used to create and trade a fixed-cap, fungible asset. A specific quantity of the asset is created at the asset’s initialization, and then, no more is ever created.
Suppose there is an Income Sharing Agreement (ISA) with 10M shares, and no more shares are ever created. Let’s create an asset where one unit of the asset represents one share of the ISA.
You've completed Run an Avalanche Node and are familiar with Avalanche's architecture.
Our asset will exist on the X-Chain, so to create our asset we’ll call avm.createFixedCapAsset
, a method of the X-Chain’s API.
The signature for this method is:
avm.createFixedCapAsset({
name: string,
symbol: string,
denomination: int,
initialHolders: []{
address: string,
amount: int
},
from: []string,
changeAddr: string,
username: string,
password: string
}) ->
{
assetID: string,
changeAddr: string,
}
name
is a human-readable name for the asset. Not necessarily unique.symbol
is a shorthand symbol for the asset. Between 0 and 4 characters. Not necessarily unique. May be omitted.denomination
determines how balances of this asset are displayed by user interfaces. If denomination is 0, 100 units of this asset are displayed as 100. If denomination is 1, 100 units of this asset are displayed as 10.0. If denomination is 2, 100 units of this asset are displays as .100, etc.- Performing a transaction on the X-Chain requires a transaction fee paid in AVAX.
username
andpassword
denote the user paying the fee. - Each element in
initialHolders
specifies thataddress
holdsamount
units of the asset at genesis. from
are the addresses that you want to use for this operation. If omitted, uses any of your addresses as needed.changeAddr
is the address any change will be sent to. If omitted, change is sent to one of the addresses controlled by the user.
assetID
is the ID of the new asset.changeAddr
in the result is the address where any change was sent.
Now, on to creating the asset. You’ll want to replace address
with an address you control so that you will control all of the newly minted assets and be able to send it later in this tutorial.
curl -X POST --data '{
"jsonrpc":"2.0",
"id" : 1,
"method" :"avm.createFixedCapAsset",
"params" :{
"name": "ISA Shares",
"symbol":"ISAS",
"denomination": 0,
"initialHolders": [
{
"address": "X-avax10pvk9anjqrjfv2xudkdptza654695uwc8ecyg5",
"amount": 10000000
}
],
"from":["X-avax1s65kep4smpr9cnf6uh9cuuud4ndm2z4jguj3gp"],
"changeAddr":"X-avax1turszjwn05lflpewurw96rfrd3h6x8flgs5uf8",
"username":"USERNAME GOES HERE",
"password":"PASSWORD GOES HERE"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/X
The response contains the asset’s ID, which is also the ID of this transaction:
{
"jsonrpc":"2.0",
"id" :1,
"result" :{
"assetID":"keMuoTQSGjqZbNVTCcbrwuNNNv9eEEZWBaRY3TapcgjkoZmQ1",
"changeAddr":"X-avax1turszjwn05lflpewurw96rfrd3h6x8flgs5uf8"
}
}
All 10,000,000 units of the asset (shares) are controlled by the address we specified in initialHolders
.
To verify this, we call avm.getBalance
:
curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"avm.getBalance",
"params" :{
"address":"X-avax10pvk9anjqrjfv2xudkdptza654695uwc8ecyg5",
"assetID":"keMuoTQSGjqZbNVTCcbrwuNNNv9eEEZWBaRY3TapcgjkoZmQ1"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/X
The response confirms that our asset creation was successful and that the expected address holds all 10,000,000 shares:
{
"jsonrpc":"2.0",
"id" :1,
"result" :{
"balance":10000000
}
}
Now, let’s send 100 shares by calling avm.send
.
To send the shares, we need to prove that we control the user the shares are being sent from. Therefore, this time we’ll need to fill in username
and password
.
curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"avm.send",
"params" :{
"username":"USERNAME GOES HERE",
"password":"PASSWORD GOES HERE",
"assetID" :"keMuoTQSGjqZbNVTCcbrwuNNNv9eEEZWBaRY3TapcgjkoZmQ1",
"amount" :100,
"to" :"X-avax1t8sl0knfzly3t3sherctxwezy533ega3sxww2k"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/X
The response from the above call should look like this:
{
"jsonrpc":"2.0",
"id" :1,
"result" :{
"txID":"2EAgR1YbsaJrwFiU4DpwjUfTLkt97WrjQYYNQny13AheewnxSR",
"changeAddr": "X-avax1turszjwn05lflpewurw96rfrd3h6x8flgs5uf8"
}
}
txID
is the ID of the send
transaction we sent to the network.
After a second or two, the transaction should be finalized. We can check the status of the transaction with avm.getTxStatus
:
curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"avm.getTxStatus",
"params" :{
"txID":"2EAgR1YbsaJrwFiU4DpwjUfTLkt97WrjQYYNQny13AheewnxSR"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/X
The response should look like this:
{
"jsonrpc":"2.0",
"id" :1,
"result" :{
"status":"Accepted"
}
}
You might also see that status
is Pending
if the network has not yet finalized it yet.
Now let’s check the balance of the to
address:
curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"avm.getBalance",
"params" :{
"address":"X-avax1t8sl0knfzly3t3sherctxwezy533ega3sxww2k",
"assetID":"keMuoTQSGjqZbNVTCcbrwuNNNv9eEEZWBaRY3TapcgjkoZmQ1"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/X
The response should be:
{
"jsonrpc":"2.0",
"id" :1,
"result" :{
"balance":100
}
}
In this tutorial, we:
- Called
createFixedCapAsset
to create a fixed cap asset - Called
getBalance
to check address balances - Called
send
to transfer a quantity of our asset