Creating a Token by Gateway API
Tokens on Radix
Creating your own token on Radix is easy. Token creation is a built-in feature of the Radix network, and requires only a single transaction using the Radix Node API.
A token creation transaction is no more complicated than one to perform a simple transfer of tokens, as described in Making Transactions. The only difference is that you use a special transaction type and must specify the parameters of the token you want to create, such as its name and supply.
This page describes the types of tokens you can create, the parameters you can specify, and how to use these tokens after created.
Radix Tokens vs. Smart Contract-based Tokens
If you’re familiar with creating tokens on Ethereum or other smart contract blockchains, Radix’s approach is very different. Because Radix is designed as a platform for decentralized finance, secure creation and management of tokenized assets is a core feature. Therefore Radix’s design makes tokens a global feature of the ledger, rather than requiring developers to deploy nearly-duplicate smart contracts each time they want token-like functionality.
For example, on Ethereum the native ETH
token is a special, with all other tokens implemented simply smart contracts that seek to follow a common interface standard (ERC-20 and similar). Developers must interact with ETH and ERC-20 tokens differently. On Radix, because tokens are a core feature of the platform, the network’s native token XRD
is implemented and transacted in exactly the same way as user-created tokens. The only thing special about XRD
is that it is was created at genesis and is the only token that may be used to pay transaction fees or staked to validators.
The built-in token functionality described on this page is available on the current Olympia mainnet. This functionality is defined in the network’s application layer: Radix Engine v1. Later versions of the network will implement Radix Engine v2, which will include full smart contract functionality that will retain, and greatly extend, this core concept of tokens as global resources.
For more on Radix’s plans for Radix Engine v2, see this page on our Knowledgebase
Token Types and Features
Radix’s Olympia mainnet implements two simple types of token:
Fixed tokens |
A token with fixed supply specified at creation. No minting/burning is possible. |
Mutable tokens |
A token with mutable supply whose creator is able to mint/burn tokens. |
Fixed tokens have a supply that cannot ever be affected by anyone, including its creator, and so can provide confidence to holders in some cases. Mutable tokens are more flexible, but require trust in the creator to only mint or burn tokens appropriately.
Deriving Token rri identifier
For both types of tokens, before build transactions that create tokens, the rri needs to be derived. The API call to derive token token would look like below
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"public_key": {
"hex": "03f89249c269bde09e72f351b0debb348ced0d3542d7dc26ff1bf39b7ed4bb25ca"
},
"symbol":"gum"
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/token/derive" | python -m json.tool
The public_key.hex
in above request is the hex of the account which will sign the transaction for the creation of token
/token/derive
call{
"token_identifier": {
"rri": "gum_rr1q0l7z7v5gvpezrhvvq0avfgwntfh6rvyfwqjddr4z4rsxvw6j8"
}
}
Making a Create Token Transaction
Both types of token may be created using a simple transaction. This transaction is created using exactly the same API process described on Making Transactions. The only difference is that the /transaction/build
method call must include an action
of type CreateTokenDefinition
.
The two types of token use a set of similar, but slightly different, data fields to describe the token:
Fixed token action data
This type immediately issues the fixed supply of tokens, and so a recipient to
address must be specified. Below are the fields in action that define creation of token
type |
|
to_account.address |
The Radix address that will receive the new fixed supply of tokens |
token_properties.symbol |
Like |
token_properties.name |
Like |
token_properties.description |
A brief description of the nature of the token and its use (max 255 characters) |
token_properties.icon_url |
A URL of a token icon page, recommended to be a 32x32 pixel PNG image |
token_properties.url |
A URL to a page providing more information about the token |
token_properties.is_supply_mutable |
As this is Fixed token, this is set to false |
token_properties.token_supply.value |
The total fixed number of tokens to be created and that will ever exist, specified in sub-unit quantities of 1x10^18 subunits per "whole" token. eg: A supply of 1000 tokens would be specified as |
token_properties.token_supply.token_identifier.rri |
the rri of token derived by making call '/token/derive' |
token_properties.granularity |
Granularity of the token. At the Olympia release, the only supported value is '1' |
token_properties.owner.address |
Owner address of the token |
Mutable token action data
This type allows the creator to mint and burn tokens freely and so no immediate supply is specified.
type |
|
to_account.address |
The Radix address that will receive the new fixed supply of tokens |
token_properties.symbol |
Like |
token_properties.name |
Like |
token_properties.description |
A brief description of the nature of the token and its use (max 255 characters) |
token_properties.icon_url |
A URL of a token icon page, recommended to be a 32x32 pixel PNG image |
token_properties.url |
A URL to a page providing more information about the token |
token_properties.is_supply_mutable |
As this is Mutable token, this is set to true |
token_properties.token_supply.value |
This needs to be set to zero |
token_properties.token_supply.token_identifier.rri |
the rri of token derived by making call '/token/derive' |
token_properties.granularity |
Granularity of the token. At the Olympia release, the only supported value is '1' |
token_properties.owner.address |
Owner address of the token |
Example token creation transaction
The API call to build the token creation transaction would look something like this:
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"actions": [
{
"type" : "CreateTokenDefinition",
"token_properties":{
"name": "Bubblegum",
"description" : "With this token, you will never be all out of bubblegum.",
"icon_url" :"https://www.roddysbubblegum.io/icon-gum-32x32.png",
"url" :"https://www.roddysbubblegum.io/about-gum/",
"symbol":"gum",
"is_supply_mutable" : false,
"granularity": "1",
"owner": { "address":"rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"}
},
"token_supply":{
"value":"100000000000000000000000",
"token_identifier": {
"rri":"gum_rr1q0l7z7v5gvpezrhvvq0avfgwntfh6rvyfwqjddr4z4rsxvw6j8"
}
},
"to_account" :{
"address":"rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"
}
}
],
"fee_payer": {
"address": "rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"
} ,
"disable_token_mint_and_burn": true
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/transaction/build" | python -m json.tool
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"actions": [
{
"type" : "CreateTokenDefinition",
"token_properties":{
"name": "Bubblegum",
"description" : "With this token, you will never be all out of bubblegum.",
"icon_url" :"https://www.roddysbubblegum.io/icon-gum-32x32.png",
"url" :"https://www.roddysbubblegum.io/about-gum/",
"symbol":"gum",
"is_supply_mutable" : false,
"granularity": "1",
"owner": { "address":"rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"}
},
"token_supply":{
"value":"100000000000000000000000",
"token_identifier": {
"rri":"gum_rr1q0l7z7v5gvpezrhvvq0avfgwntfh6rvyfwqjddr4z4rsxvw6j8"
}
},
"to_account" :{
"address":"rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"
}
}
],
"fee_payer": {
"address": "rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"
} ,
"disable_token_mint_and_burn": true
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/transaction/build" | python -m json.tool
This should build the transaction; now you just need to sign, finalize, and submit it. See Making Transactions to see how.
Minting and Burning
If you have created a mutable supply token, the address that created the token has the exclusive ability to mint or burn these tokens. Doing either is also done by a simple transaction, this time of action
type MintTokens
or BurnTokens
. If you wish , you can include these in same transaction during the token creation.
Here is what a build step of this might look like.
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"actions": [
{
"type": "MintTokens",
"to_account":{
"address": "rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"
},
"amount": {
"value": "1000000000000000000000"
"token_identifier" : {
"rri": "gum_rr1q0l7z7v5gvpezrhvvq0avfgwntfh6rvyfwqjddr4z4rsxvw6j8"
}
}
}
]
"feePayer":
{
"address": "rdx1qspl7mgjqwgwqyjvy2tj8swe8a4lr6mxqdhwmn60cujl6a85mqh69eg37p9ph"
}
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/transaction/build" | python -m json.tool
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"actions": [
{
"type": "BurnTokens",
"from_account":{
"address": "rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"
},
"amount": {
"value": "1000000000000000"
"token_identifier" : {
"rri": "gum_rr1q0l7z7v5gvpezrhvvq0avfgwntfh6rvyfwqjddr4z4rsxvw6j8"
}
}
}
]
"feePayer":
{
"address": "rdx1qspl7mgjqwgwqyjvy2tj8swe8a4lr6mxqdhwmn60cujl6a85mqh69eg37p9ph"
}
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/transaction/build" | python -m json.tool
As before, this should build the transaction; now you just need to sign, finalize, and submit it. See Making Transactions to see how.