Transferring Tokens
Start moving tokens between wallets.
You will need to transfer tokens for:
- Implementing various gameplay features such as gifting, trading, and rewards.
- Supporting secure and efficient token transactions.
- Providing a seamless user experience by allowing token transfers without leaving the game environment.
What you'll need
- Some Enjin Coin on Enjin Matrixchain to pay for Transaction Fees.
You can obtain cENJ (Canary ENJ) for testing from the Canary faucet.- An Enjin Platform Account.
- A Collection and a Token to transfer.
Keep Alive: False
When transferring tokens you've created using the Enjin Platform, always set
keepAlive
toFalse
.This flag only relates to your Enjin Coin balance and has no impact on any other token on the network.
There are two ways to transfer a token:
Option A. Using the Enjin Dashboard
In the Platform menu, navigate to "Tokens".
Locate the token you wish to transfer, click the 3 vertical dots (⋮) to it's right, then click the "Transfer" button.
Need to perform multiple transfers?
Click on the "Batch" button, followed by "Batch Transfer".
Fill in the recipient, amount, and other optional arguments in the corresponding fields.
Once you're satisfied with the options, click on the "Transfer" button at the bottom right corner to create the request.
Since this transaction is a Mutation, you will need to sign the transaction using your Wallet.
- If a Wallet Daemon is running and configured, the transaction request will be signed automatically.
- If a wallet is connected such as the Enjin Wallet or Polkadot.js, the transaction must be signed manually by clicking the "Sign" button and approving the signature request in your wallet.
If you're looking to distribute tokens to your community or players, but don't have their account addresses, don't worry! Our solution is Enjin Beam.
Proceed to the Distributing Tokens via QR tutorial to learn more.
Option B. Using the Enjin API & SDKs
Transferring an asset
SimpleTransferToken
mutation simplifies the process of transferring a specific token from one wallet to another. It is a straightforward way to facilitate token transfers without the need for complex intermediary steps.
mutation TransferToken{
SimpleTransferToken(
collectionId: 36105 #Specify the collection ID
recipient: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f" #Specify the recipent address
params: {
tokenId: {integer: 0} #Specify the token ID
amount: 1 #Choose the transfer amount
}
){
id
method
state
}
}
curl -X POST "https://platform.enjin.io/graphql" \
-H "Content-Type: application/json" \
-H "Authorization: enjin_api_key" \
-d '{"query": "mutation TransferToken { SimpleTransferToken(collectionId: 36105, recipient: \"cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f\", params: { tokenId: {integer: 0}, amount: 1 }) { id method state } }"}'
using System.Text.Json;
using Enjin.Platform.Sdk;
// Define the simple transfer parameters
var simpleTransferParams = new SimpleTransferParams()
.SetTokenId(new EncodableTokenIdInput().SetInteger(0))
.SetAmount(1);
// Setup the mutation
var simpleTransferToken = new SimpleTransferToken()
.SetRecipient("cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f")
.SetCollectionId(36105)
.SetParams(simpleTransferParams);
// Define and assign the return data fragment to the mutation
var simpleTransferTokenFragment = new TransactionFragment()
.WithId()
.WithMethod()
.WithState();
simpleTransferToken.Fragment(simpleTransferTokenFragment);
// Create and auth a client to send the request to the platform
var client = PlatformClient.Builder()
.SetBaseAddress("https://platform.canary.enjin.io")
.Build();
client.Auth("Your_Platform_Token_Here");
// Send the request and write the output to the console.
// Only the fields that were requested in the fragment will be filled in,
// other fields which weren't requested in the fragment will be set to null.
var response = await client.SendSimpleTransferToken(simpleTransferToken);
Console.WriteLine(JsonSerializer.Serialize(response.Result.Data));
#include "EnjinPlatformSdk/CoreMutations.hpp"
#include <iostream>
using namespace enjin::platform::sdk;
using namespace std;
int main() {
// Define the simple transfer params
shared_ptr tokenId = make_shared<EncodableTokenIdInput>();
tokenId->SetInteger(make_shared<SerializableString>("0"));
SimpleTransferParams simpleTransferParams = SimpleTransferParams()
.SetAmount(make_shared<SerializableString>("1"))
.SetTokenId(tokenId);
// Setup mutation
SimpleTransferToken simpleTransferToken = SimpleTransferToken()
.SetRecipient(make_shared<SerializableString>("cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f"))
.SetCollectionId(make_shared<SerializableString>("36105"))
.SetParams(make_shared<SimpleTransferParams>(simpleTransferParams));
// Define and assign the return data fragment to the mutation
shared_ptr<TransactionFragment> transactionFragment = make_shared<TransactionFragment>();
transactionFragment
->WithId()
.WithMethod()
.WithState();
simpleTransferToken.SetFragment(transactionFragment);
// Create and auth a client to send the request to the platform
unique_ptr<PlatformClient> client = PlatformClient::Builder()
.SetBaseAddress("https://platform.canary.enjin.io")
.Build();
client->Auth("Your_Platform_Token_Here");
// Send the request then get the response and write the output to the console.
// Only the fields that were requested in the fragment will be filled in,
// other fields which weren't requested in the fragment will be set to null.
future<shared_ptr<IPlatformResponse<GraphQlResponse<Transaction>>>> futureResponse = SendSimpleTransferToken(*client, simpleTransferToken);
// Get the platform response holding the HTTP data
PlatformResponsePtr<GraphQlResponse<Transaction>> response = futureResponse.get();
// Get the result, a GraphQL response, holding the GraphQL data
const optional<GraphQlResponse<Transaction>>& gqlResult = response->GetResult();
// Write the result data to the console
if (gqlResult.has_value() && gqlResult->IsSuccess())
{
const optional<Transaction>& transaction = gqlResult->GetData()->GetResult();
std::cout << to_string(transaction->GetId().value()) << std::endl;
std::cout << ToString(transaction->GetMethod().value()) << std::endl;
}
// Write any error messages to the console
if (gqlResult.has_value() && gqlResult->HasErrors())
{
const optional<vector<GraphQlError>>& errors = gqlResult->GetErrors();
for (const GraphQlError& error : errors.value()) {
std::cout << error.GetMessage().value() << std::endl;
}
}
client.reset();
return 0;
}
fetch('https://platform.canary.enjin.io/graphql', {
method: 'POST',
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'},
body: JSON.stringify({
query: `
mutation TransferToken(
$collection_id: BigInt!
$token_id: BigInt!
$recipient: String!
$amount: BigInt!
) {
SimpleTransferToken(
collectionId: $collection_id
recipient: $recipient
params: {
tokenId: {integer: $token_id}
amount: $amount
}
){
id
method
state
}
}
`,
variables: {
collection_id: 36105, //Specify the collection ID
token_id: 0, //Specify the token ID
recipient: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", //Specify the recipent address
amount: 1 //Choose the transfer amount
}
}),
})
.then(response => response.json())
.then(data => console.log(data));
const axios = require('axios');
axios.post('https://platform.canary.enjin.io/graphql', {
query: `
mutation TransferToken(
$collection_id: BigInt!
$token_id: BigInt!
$recipient: String!
$amount: BigInt!
) {
SimpleTransferToken(
collectionId: $collection_id
recipient: $recipient
params: {
tokenId: {integer: $token_id}
amount: $amount
}
){
id
method
state
}
}
`,
variables: {
collection_id: 36105, //Specify the collection ID
token_id: 0, //Specify the token ID
recipient: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", //Specify the recipent address
amount: 1 //Choose the transfer amount
}
}, {
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'}
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
import requests
query = '''
mutation TransferToken(
$collection_id: BigInt!
$token_id: BigInt!
$recipient: String!
$amount: BigInt!
) {
SimpleTransferToken(
collectionId: $collection_id
recipient: $recipient
params: {
tokenId: {integer: $token_id}
amount: $amount
}
){
id
method
state
}
}
'''
variables = {
'collection_id': 36105, #Specify the collection ID
'token_id': 0, #Specify the token ID
'recipient': "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", #Specify the recipent address
'amount': 1 #Choose the transfer amount
}
response = requests.post('https://platform.canary.enjin.io/graphql',
json={'query': query, 'variables': variables},
headers={'Content-Type': 'application/json', 'Authorization': 'Your_Platform_Token_Here'}
)
print(response.json())
Transferring ENJ token
To send ENJ / CENJ tokens from one wallet to another, we use the TransferBalance
mutation:
mutation TransferENJTokens {
TransferBalance(
recipient: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f" #Specify the recipent address
amount: 5000000000000000000 #Specify the amount of tokens to transfer
keepAlive: true #Set to true if you want to make sure the account doesn't get reaped
) {
id
method
state
}
}
curl -X POST "https://platform.enjin.io/graphql" \
-H "Content-Type: application/json" \
-H "Authorization: enjin_api_key" \
-d '{"query": "mutation TransferENJTokens { TransferBalance(recipient: \"cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f\", amount: 5000000000000000000, keepAlive: true) { id method state } }"}'
Work In Progress
Work In Progress
fetch('https://platform.canary.enjin.io/graphql', {
method: 'POST',
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'},
body: JSON.stringify({
query: `
mutation TransferENJTokens(
$recipient: String!
$amount: BigInt!
$keep_alive: Boolean
) {
TransferBalance(
recipient: $recipient
amount: $amount
keepAlive: $keep_alive
){
id
method
state
}
}
`,
variables: {
recipient: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", //Specify the recipent address
amount: 1, //Specify the amount of tokens to transfer
keep_alive: true //Set to true if you want to make sure the account doesn't get reaped
}
}),
})
.then(response => response.json())
.then(data => console.log(data));
const axios = require('axios');
axios.post('https://platform.canary.enjin.io/graphql', {
query: `
mutation TransferENJTokens(
$recipient: String!
$amount: BigInt!
$keep_alive: Boolean
) {
TransferBalance(
recipient: $recipient
amount: $amount
keepAlive: $keep_alive
){
id
method
state
}
}
`,
variables: {
recipient: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", //Specify the recipent address
amount: 1, //Specify the amount of tokens to transfer
keep_alive: true //Set to true if you want to make sure the account doesn't get reaped
}
}, {
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'}
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
import requests
query = '''
mutation TransferENJTokens(
$recipient: String!
$amount: BigInt!
$keep_alive: Boolean
) {
TransferBalance(
recipient: $recipient
amount: $amount
keepAlive: $keep_alive
){
id
method
state
}
}
'''
variables = {
'recipient': "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", #Specify the recipent address
'amount': 1, #Specify the amount of tokens to transfer
'keep_alive': True #Set to true if you want to make sure the account doesn't get reaped
}
response = requests.post('https://platform.canary.enjin.io/graphql',
json={'query': query, 'variables': variables},
headers={'Content-Type': 'application/json', 'Authorization': 'Your_Platform_Token_Here'}
)
print(response.json())
Notes:
amount
argument
- In the
TransferBalance
mutation, theamount
argument is denoted inu128
. This means that the number you specify is divided by 10^18 to determine the actual amount of ENJ to be transferred.
In the example above, anamount
of5000000000000000000
will actually send 5 ENJ. Keep this in mind when specifying theamount
in your mutations.keepAlive
argument
- Set to true if you want to make sure the account doesn't get reaped.
Learn more about keepAlive argument here
More Fields and Arguments Available!
While the examples here cover the core functionalities of the
SimpleTransferToken
mutation, there are a few more settings you can adjust.To view and understand all the available settings for the
SimpleTransferToken
mutation, refer to our GraphQL Schema on Apollo.This resource will guide you in tailoring the
SimpleTransferToken
mutation to your specific requirements.For instance, by setting the
keepAlive
argument to true, you ensure that the sender's token count won't drop to zero. This could be useful in very specific scenarios. For example, when a player sends a token representing a key, and all users must have at least one key at all times.
Batch Transferring ENJ token
To send ENJ / CENJ tokens from one wallet to multiple addresses or in multiple transactions, we use the BatchTransferBalance
mutation
mutation BatchSendENJ{
BatchTransferBalance(
recipients: [
{
account: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", #Specify the recipent address
transferBalanceParams: {
value: 5000000000000000000 #Specify the amount of tokens to transfer
}
},
{
account: "cxKy7aqhQTtoJYUjpebxFK2ooKhcvQ2FQj3FePrXhDhd9nLfu", #Specify the recipent address
transferBalanceParams: {
value: 15250000000000000000 #Specify the amount of tokens to transfer
keepAlive: true #Set to true if you want to make sure the account doesn't get reaped
}
},
]
){
id
transactionId
state
}
}
curl -X POST "https://platform.enjin.io/graphql" \
-H "Content-Type: application/json" \
-H "Authorization: enjin_api_key" \
-d '{"query": "mutation BatchSendENJ { BatchTransferBalance(recipients: [{ account: \"cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f\", transferBalanceParams: { value: 5000000000000000000 } }, { account: \"cxKy7aqhQTtoJYUjpebxFK2ooKhcvQ2FQj3FePrXhDhd9nLfu\", transferBalanceParams: { value: 15250000000000000000, keepAlive: true } }]) { id transactionId state } }"}'
Work In Progress
Work In Progress
fetch('https://platform.canary.enjin.io/graphql', {
method: 'POST',
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'},
body: JSON.stringify({
query: `
mutation BatchSendENJ($recipients: [TransferRecipient!]!){
BatchTransferBalance(
recipients: $recipients
){
id
transactionId
state
}
}
`,
variables: {
recipients:[
{
account: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", //Specify the recipent address
transferBalanceParams: { value: 5000000000000000000 } //Specify the amount of tokens to transfer
},
{
account: "cxKy7aqhQTtoJYUjpebxFK2ooKhcvQ2FQj3FePrXhDhd9nLfu", //Specify the recipent address
transferBalanceParams: {
value: 15250000000000000000, //Specify the amount of tokens to transfer
keepAlive: true //Set to true if you want to make sure the account doesn't get reaped
}
}
]
}
}),
})
.then(response => response.json())
.then(data => console.log(data));
const axios = require('axios');
axios.post('https://platform.canary.enjin.io/graphql', {
query: `
mutation BatchSendENJ($recipients: [TransferRecipient!]!){
BatchTransferBalance(
recipients: $recipients
){
id
transactionId
state
}
}
`,
variables: {
recipients:[
{
account: "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", //Specify the recipent address
transferBalanceParams: { value: 5000000000000000000 } //Specify the amount of tokens to transfer
},
{
account: "cxKy7aqhQTtoJYUjpebxFK2ooKhcvQ2FQj3FePrXhDhd9nLfu", //Specify the recipent address
transferBalanceParams: {
value: 15250000000000000000, //Specify the amount of tokens to transfer
keepAlive: true //Set to true if you want to make sure the account doesn't get reaped
}
}
]
}
}, {
headers: {'Content-Type': 'application/json','Authorization': 'Your_Platform_Token_Here'}
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
import requests
query = '''
mutation BatchSendENJ($recipients: [TransferRecipient!]!){
BatchTransferBalance(
recipients: $recipients
){
id
transactionId
state
}
}
'''
variables = {
'recipients':[
{
'account': "cxLU94nRz1en6gHnXnYPyTdtcZZ9dqBasexvexjArj4V1Qr8f", #Specify the recipent address
'transferBalanceParams': { 'value': 5000000000000000000 } #Specify the amount of tokens to transfer
},
{
'account': "cxKy7aqhQTtoJYUjpebxFK2ooKhcvQ2FQj3FePrXhDhd9nLfu", #Specify the recipent address
'transferBalanceParams': {
'value': 15250000000000000000, #Specify the amount of tokens to transfer
'keepAlive': True #Set to true if you want to make sure the account doesn't get reaped
}
}
]
}
response = requests.post('https://platform.canary.enjin.io/graphql',
json={'query': query, 'variables': variables},
headers={'Content-Type': 'application/json', 'Authorization': 'Your_Platform_Token_Here'}
)
print(response.json())
A WebSocket event will also be fired so you can pick up the transfer transaction in real time by listening to the app channel on the WebSocket.
Need to send a transaction request to user's wallet?
This can be done using Enjin Platform API & WalletConnect!
To learn more, check out the Using WalletConnect page.
Proceed to the Distributing Tokens via QR tutorial to learn more.
Distribute tokens to your players, even if they don't have wallets!
Updated 24 days ago