Token Transactions
Token transactions are fundamental for managing digital currencies on the ArcBlock platform. They enable developers to create, distribute, and manage custom tokens for various applications, such as utility tokens, in-game currencies, or loyalty points. This section details how to use @ocap/client
to perform key token-related operations.
Before proceeding, it's recommended to understand the basics of how tokens work on ArcBlock. For a conceptual overview, please read Tokens.
This guide will cover the following operations:
- Creating new tokens.
- Transferring tokens between accounts.
- Depositing and withdrawing tokens via an ArcBridge.
Create a New Token#
Developers can issue custom tokens on the ArcBlock chain by sending a CreateTokenTx
. The @ocap/client
library simplifies this process with the createToken
helper method. This method builds, signs, and sends the transaction in a single call.
How it Works#
The following diagram illustrates the process of creating a token using the client:
createToken
#
This method creates a new token and assigns the total supply to the wallet that sends the transaction.
Parameters
Name | Type | Description |
---|---|---|
|
| The full name of the token (e.g., "Demo Token"). |
|
| A brief description of the token's purpose. |
|
| The token's symbol (e.g., "DT"). It's recommended to make this unique to avoid confusion. |
|
| The number of decimal places the token supports. For example, a value of |
|
| The smallest unit of the token (e.g., "d"). |
|
| The total number of tokens that will ever be in circulation. The client automatically converts this to the correct on-chain format based on |
|
| Optional. The amount of tokens to mint initially. Defaults to |
|
| Optional. An object linking this token to one on an EVM-compatible chain, required for ArcBridge operations. See Tokens. |
|
| The wallet object of the token creator, used to sign the transaction. The creator will receive the |
Returns
Promise<[string, string]>
: A promise that resolves to an array containing the transaction hash and the new token's address.
Example
The following example demonstrates how to create a new user account (the owner) and then create a new token owned by that account.
import { fromRandom } from '@ocap/wallet';
import GraphQLClient from '@ocap/client';
const endpoint = process.env.OCAP_API_HOST || 'http://127.0.0.1:4000';
const client = new GraphQLClient(`${endpoint}/api`);
async function createNewToken() {
try {
// 1. Create a new wallet to be the token owner
const owner = fromRandom();
console.log(`Owner Address: ${owner.address}`);
// 2. Declare the owner account on the chain
const declareHash = await client.declare({ moniker: 'token_owner', wallet: owner });
console.log(`Declare transaction hash: ${declareHash}`);
console.log(`View owner account at: ${endpoint}/explorer/accounts/${owner.address}`);
// 3. Create the new token
const [createTxHash, tokenAddress] = await client.createToken({
name: 'Demo Token',
description: 'A token for demonstration purposes',
symbol: `DT_${Date.now()}`,
decimal: 18,
unit: 'd',
totalSupply: 1000000,
wallet: owner,
});
console.log(`Create token transaction hash: ${createTxHash}`);
console.log(`New Token Address: ${tokenAddress}`);
console.log(`View token details at: ${endpoint}/explorer/tokens/${tokenAddress}`);
} catch (err) {
console.error(err);
}
}
createNewToken();
Example Response
[
"z8iZof1aswDR397eA7i3jR2uE6v9Q4b5n7mYkXwD3gV",
"z35n6a7D8b9cE0f1gH2iJ3kL4mN5pQ6rS7tU8vW9xYz"
]
This response provides the transaction hash for the CreateTokenTx
and the newly generated address for the token.
Transfer Tokens#
Once a token is created, it can be transferred between accounts. The transfer
method handles both native (e.g., ABT) and custom tokens by generating a TransferV2Tx
. The client intelligently handles the decimal conversion for any token amounts specified.
transfer
#
Parameters
Name | Type | Description |
---|---|---|
|
| The address of the recipient. |
|
| An array of token objects to transfer. Each object must specify the |
|
| Optional. A short text note to include with the transaction. |
|
| The sender's wallet object, used for signing. The wallet's corresponding account must have a sufficient balance of the tokens being sent. |
Returns
Promise<string>
: A promise that resolves to the transaction hash.
Example
This example creates two accounts, issues a new token to the first account, and then transfers a portion of that token to the second account.
import { fromRandom } from '@ocap/wallet';
import GraphQLClient from '@ocap/client';
const endpoint = process.env.OCAP_API_HOST || 'http://127.0.0.1:4000';
const client = new GraphQLClient(`${endpoint}/api`);
const sleep = (timeout) => new Promise(resolve => setTimeout(resolve, timeout));
async function transferCustomToken() {
try {
// 1. Create wallets for sender and receiver
const sender = fromRandom();
const receiver = fromRandom();
console.log({ sender: sender.address, receiver: receiver.address });
// 2. Declare both accounts on the chain
await client.declare({ moniker: 'sender', wallet: sender });
await client.declare({ moniker: 'receiver', wallet: receiver });
console.log('Accounts declared.');
// Wait for declarations to be confirmed
await sleep(3000);
// 3. Create a new token with the sender as the owner
const [_, tokenAddress] = await client.createToken({
name: 'Demo Transfer Token',
symbol: `DTT_${Math.floor(Math.random() * 10000)}`,
decimal: 8,
totalSupply: 1000000,
wallet: sender,
});
console.log(`Token created with address: ${tokenAddress}`);
// Wait for token creation to be confirmed
await sleep(3000);
// 4. Transfer 100.5 tokens from sender to receiver
const transferHash = await client.transfer({
to: receiver.address,
tokens: [{ address: tokenAddress, value: 100.5 }],
memo: 'Sending you some DTT',
wallet: sender,
});
console.log(`Transfer successful! View transaction at: ${endpoint}/explorer/txs/${transferHash}`);
} catch (err) {
console.error(err);
}
}
transferCustomToken();
Example Response
"z8iZqA9bC8dE7fG6hI5jK4lM3nO2p1R0sT9uV8wX7yZ"
ArcBridge Token Operations#
To enable interoperability between an ArcBlock chain and an EVM-compatible chain (e.g., Ethereum), tokens can be moved across an ArcBridge. This requires the token to have been created with the foreignToken
property. The DepositTokenV2Tx
and WithdrawTokenV2Tx
are used for these cross-chain transfers.
Unlike the helper methods above, these transactions are typically sent using the lower-level send<TxType>Tx
functions, as they often require external evidence from the other chain.
Deposit Tokens#
A DepositTokenV2Tx
is used to record that tokens have been moved from a foreign chain to the ArcBlock chain. This transaction is usually created by a trusted proposer who has observed the corresponding deposit event on the foreign chain.
sendDepositTokenV2Tx
Parameters (itx
object)
Name | Type | Description |
---|---|---|
|
| An object with the token |
|
| The recipient's address on the ArcBlock chain. |
|
| The address of the account proposing this transaction. |
|
| Cryptographic proof from the foreign chain, such as a transaction hash, that the deposit occurred. |
|
| The address of the ArcBridge contract on the ArcBlock chain. |
Withdraw Tokens#
A WithdrawTokenV2Tx
initiates the process of moving tokens from the ArcBlock chain back to a foreign chain. This transaction locks the tokens on ArcBlock and serves as a claim for the user on the other chain.
sendWithdrawTokenV2Tx
Parameters (itx
object)
Name | Type | Description |
---|---|---|
|
| An object with the token |
|
| The recipient's address on the foreign chain (e.g., an Ethereum address). |
|
| The address of the ArcBridge contract on the ArcBlock chain. |
|
| The address of the account proposing this transaction. |
|
| The maximum fee the user is willing to pay for the cross-chain transaction, denominated in the token's smallest unit. |
Now that you know how to create and transfer tokens, you can explore more complex economic interactions. The next section covers how to exchange tokens and assets between parties.
Next, learn about Trading Transactions.