Used to check for browser translation.
用于检测浏览器翻译。
ブラウザの翻訳を検出する
Transaction Types and Usage

Account Transactions


This section provides a detailed guide to managing identities and accounts on the ArcBlock blockchain using the @arcblock/graphql-client library. You will learn how to declare new identities, migrate existing accounts, and manage delegated privileges. For a general understanding of transaction sending and commitment, refer to Sending Transactions (Mutations). For core blockchain concepts like DIDs and Wallets, see Core Blockchain Concepts.

Declare Identities#

The DeclareTx transaction type is used to register a new identity on the blockchain. This can represent various entities such as a user, application, or node. When you declare an identity, it creates an on-chain record for that Decentralized Identity (DID).

client.declare(params)#

This helper method simplifies the process of sending a DeclareTx. It automatically handles the transaction encoding and signing process using the provided wallet.

Parameters

Name

Type

Description

moniker

string

A unique name or alias for the identity being declared.

data

Any

Optional. Additional arbitrary data to be associated with the identity. This field can hold various types and shapes of data, encoded using the Any type.

wallet

WalletObject

The wallet instance of the sender, used to sign the transaction.

Example

import { fromRandom } = require('@ocap/wallet');
import GraphQLClient from '@arcblock/graphql-client';

const endpoint = process.env.OCAP_API_HOST || 'http://127.0.0.1:4000'; // testnet
const client = new GraphQLClient(`${endpoint}/api`);

(async () => {
try {
// Send without explicit sign (client.declare handles signing internally)
const user1 = fromRandom();
const hash1 = await client.declare({
moniker: `poke_user_${Math.round(Math.random() * 10000)}`,
data: { type: 'json', value: Math.random() },
wallet: user1,
});

console.log('View user1 account:', `${endpoint}/explorer/accounts/${user1.address}`);
console.log('View user1 transaction:', `${endpoint}/explorer/txs/${hash1}`);

// Alternatively, sign and then send explicitly using sendDeclareTx
const user2 = fromRandom();
const signedTx2 = await client.signDeclareTx({
tx: {
itx: {
moniker: 'sign_and_send_explicitly',
data: { type: 'json', value: Math.random() },
},
},
wallet: user2,
});
const hash2 = await client.sendDeclareTx({ tx: signedTx2, wallet: user2 });
console.log('View user2 account:', `${endpoint}/explorer/accounts/${user2.address}`);
console.log('View user2 transaction:', `${endpoint}/explorer/txs/${hash2}`);

// Or using the generic sendTx after signing
const user3 = fromRandom();
const signedTx3 = await client.signDeclareTx({
tx: {
itx: {
moniker: 'sign_and_send_generic',
data: { type: 'json', value: Math.random() },
},
},
wallet: user3,
encoding: 'base64',
});
const hash3 = await client.sendTx({ tx: signedTx3 });
console.log('View user3 account:', `${endpoint}/explorer/accounts/${user3.address}`);
console.log('View user3 transaction:', `${endpoint}/explorer/txs/${hash3.hash}`);

} catch (err) {
console.error(err);
}
})();

This example demonstrates how to declare a new identity using the client.declare helper. It also shows alternative ways to sign the transaction first using client.signDeclareTx and then sending it via client.sendDeclareTx or the more generic client.sendTx.

Migrate Accounts#

The AccountMigrateTx transaction type allows an existing account's on-chain data (such as tokens and assets) to be associated with a new DID. This is useful for scenarios like key rotation or changing the underlying DID of an entity.

client.migrateAccount(params)#

This method facilitates the migration of an account from an old wallet/DID to a new one.

Parameters

Name

Type

Description

from

WalletObject

The wallet of the original account (the one to be migrated from).

to

WalletObject

The wallet of the new account (the destination for the migration).

Example

import { fromRandom } = require('@ocap/wallet');
import GraphQLClient from '@arcblock/graphql-client';

const endpoint = process.env.OCAP_API_HOST || 'http://127.0.0.1:4000'; // testnet
const client = new GraphQLClient(`${endpoint}/api`);
const sleep = (timeout) =>
new Promise((resolve) => {
setTimeout(resolve, timeout);
});

(async () => {
try {
const migrateFrom = fromRandom();
const migrateTo = fromRandom();

// 1. Declare the 'from' account first (if not already declared)
let hash = await client.declare({
moniker: `migrate_from_${Math.round(Math.random() * 10000)}`,
wallet: migrateFrom,
});

console.log('From account:', `${endpoint}/explorer/accounts/${migrateFrom.address}`);
console.log('From account declaration transaction:', `${endpoint}/explorer/txs/${hash}`);
await sleep(3000); // Wait for the transaction to be processed

// 2. Migrate the account: with from's pk/sk
hash = await client.migrateAccount({
from: migrateFrom,
to: migrateTo,
});

console.log('Migrate transaction:', `${endpoint}/explorer/txs/${hash}`);
console.log('To account:', `${endpoint}/explorer/accounts/${migrateTo.address}`);
} catch (err) {
console.error(err);
}
})();

This example first declares a source account and then migrates its identity to a newly generated account. After migration, all on-chain data previously associated with migrateFrom will be linked to migrateTo.

Delegate Privileges#

The DelegateTx transaction type allows an account (the delegator) to grant specific privileges to another account (the delegatee). This enables the delegatee to send certain types of transactions on behalf of the delegator, without having access to the delegator's private key.

client.delegate(params)#

This method creates and sends a delegation transaction.

Parameters

Name

Type

Description

from

WalletObject

The wallet of the delegator, who is granting the privileges.

to

WalletObject

The wallet of the delegatee, who will receive the authorized privileges.

privileges

Array<{ typeUrl: string, rules?: Array<string>, limit?: { tokens: Array<string>, assets: Array<string> } }>

An array defining the specific privileges to be delegated. Each object must include typeUrl (the transaction type allowed) and can optionally include rules or limit for more granular control.

TDelegateOp Structure

type TDelegateOp = {
typeUrl: string; // The type URL of the transaction to delegate (e.g., "fg:t:transfer_v2")
rules?: Array<string>; // Optional. Specific rules for the delegation.
limit?: {
tokens: Array<string>; // Optional. List of token addresses that can be transferred/managed.
assets: Array<string>; // Optional. List of asset addresses that can be transferred/managed.
}; // Optional. Limits on what can be delegated.
}

Example

import { fromRandom } = require('@ocap/wallet');
import GraphQLClient from '@arcblock/graphql-client';

const endpoint = process.env.OCAP_API_HOST || 'http://127.0.0.1:4000'; // testnet
const client = new GraphQLClient(`${endpoint}/api`);
const sleep = (timeout) =>
new Promise((resolve) => {
setTimeout(resolve, timeout);
});

(async () => {
try {
const alice = fromRandom();
const bob = fromRandom();
const betty = fromRandom();

// Declare accounts for Alice, Bob, and Betty
await client.declare({ moniker: 'alice', wallet: alice });
await client.declare({ moniker: 'bob', wallet: bob });
await client.declare({ moniker: 'betty', wallet: betty });
await sleep(1000);

// Delegate from Alice to Betty, allowing Betty to send TransferV2Tx and TransferTx on Alice's behalf
const [delegateHash, delegateAddress] = await client.delegate({
from: alice,
to: betty,
privileges: [
{ typeUrl: 'fg:t:transfer_v2', rules: [] },
{ typeUrl: 'fg:t:transfer', rules: [] },
],
});
console.log('Alice delegated privileges. Delegation transaction hash:', delegateHash);

// Verify the delegation state
const { state } = await client.getDelegateState({ address: delegateAddress });
console.log('Delegation state:', JSON.stringify(state, null, 2));

// Betty can now send a transfer transaction on behalf of Alice
const transferHash = await client.transfer({
to: bob.address,
token: 1, // 1 unit of native token
delegator: alice.address, // Alice is the delegator
wallet: betty, // Betty is the one sending the transaction
});
console.log('Betty sent transfer on Alice\'s behalf. Transaction hash:', transferHash);

} catch (err) {
console.error(err);
}
})();

This example illustrates how Alice can delegate the ability to send TransferV2Tx and TransferTx to Betty. After delegation, Betty can initiate a transfer using Alice's account as the delegator, even though Betty's wallet signs the transaction.

Revoke Delegations#

The RevokeDelegateTx transaction type is used to revoke previously granted privileges from a delegatee. This allows the delegator to reclaim control over their account and stop the delegatee from acting on their behalf for specific transaction types.

client.revokeDelegate(params)#

This method sends a transaction to revoke delegated privileges.

Parameters

Name

Type

Description

from

WalletObject

The wallet of the delegator, who is revoking the privileges.

to

WalletObject

The wallet of the delegatee, whose privileges are being revoked.

privileges

Array<string>

An array of typeUrl strings representing the specific transaction types whose delegation should be revoked.

Example

import { fromRandom } = require('@ocap/wallet');
import GraphQLClient from '@arcblock/graphql-client';

const endpoint = process.env.OCAP_API_HOST || 'http://127.0.0.1:4000'; // testnet
const client = new GraphQLClient(`${endpoint}/api`);
const sleep = (timeout) =>
new Promise((resolve) => {
setTimeout(resolve, timeout);
});

(async () => {
try {
const alice = fromRandom();
const betty = fromRandom();

// Declare accounts (if not already declared)
await client.declare({ moniker: 'alice', wallet: alice });
await client.declare({ moniker: 'betty', wallet: betty });
await sleep(1000);

// Delegate transfer privilege from Alice to Betty (as shown in the previous example)
const [delegateHash, delegateAddress] = await client.delegate({
from: alice,
to: betty,
privileges: [
{ typeUrl: 'fg:t:transfer_v2', rules: [] },
{ typeUrl: 'fg:t:transfer', rules: [] },
],
});
console.log('Alice delegated privileges. Delegation transaction hash:', delegateHash);
await sleep(1000);

// Alice revokes the 'fg:t:transfer' privilege from Betty
const revokeHash = await client.revokeDelegate({
from: alice,
to: betty,
privileges: ['fg:t:transfer'],
});
console.log('Alice revoked privilege. Revocation transaction hash:', revokeHash);

// Check the updated delegation state after revocation
const { state } = await client.getDelegateState({ address: delegateAddress });
console.log('Updated delegation state:', JSON.stringify(state, null, 2));

} catch (err) {
console.error(err);
}
})();

This example demonstrates how Alice can revoke the fg:t:transfer privilege previously granted to Betty. After this transaction is processed, Betty will no longer be able to send TransferTx on behalf of Alice.


This section covered essential account-related transactions. You now understand how to establish identities, manage account migrations, and control delegated authorities on the blockchain. Proceed to NFT Transactions to learn how to manage Non-Fungible Tokens.