Sending Transactions (Mutations)
Mutations in the @arcblock/graphql-client library allow your application to send data and execute operations on the blockchain. This section provides a comprehensive guide to the transaction lifecycle, including encoding, signing (single and multi-party), and broadcasting transactions to a Forge-powered blockchain node.
For a deeper understanding of blockchain entities, refer to Wallets and Accounts. For detailed explanations of specific transaction types and their usage, see Transaction Types and Usage.
Transaction Lifecycle#
Every transaction sent to the blockchain follows a general lifecycle: it's first encoded into a binary format, then cryptographically signed by the sender (and potentially other parties), and finally broadcast to the blockchain node.
Encoding Transactions#
The client provides specific encode<TxType>Tx
methods for each supported transaction type. These methods convert a human-readable transaction object into its binary protobuf representation, which is required for signing and broadcasting.
Method Signature (General)
client.encode<TxType>Tx(params: GraphQLClient.TxParam<PartialDeep<GraphQLClient.<TxType>Tx>>): Promise<GraphQLClient.EncodeTxResult>
Parameters
Name | Type | Description |
---|---|---|
|
| The transaction payload containing the inner transaction ( |
|
| The wallet used for signing the transaction, providing the sender's public key. |
|
| Optional. The wallet address that delegated permissions to the |
Returns
Name | Type | Description |
---|---|---|
|
| The encoded transaction as a JavaScript object. |
|
| The encoded transaction as a binary |
Signing Transactions#
After encoding, a transaction must be signed using the sender's private key. The GraphQLClient supports both single and multi-party signatures.
Single Signature#
Use the sign<TxType>Tx
methods when a single wallet needs to sign a transaction. This method takes the transaction object (which may or may not be encoded yet) and applies the signature using the provided wallet.
Method Signature (General)
client.sign<TxType>Tx(params: GraphQLClient.TxParam<PartialDeep<GraphQLClient.<TxType>Tx>> & { encoding?: 'base64' | 'base58' | 'base16' | 'hex' }): Promise<GraphQLClient.Transaction | string | Buffer>
Parameters
Name | Type | Description |
---|---|---|
|
| The transaction payload. If |
|
| The wallet instance used to sign the transaction. |
|
| Optional. The wallet address that delegated permissions. |
|
| Optional. The desired encoding for the returned signed transaction ( |
Returns
Name | Type | Description |
---|---|---|
|
| The signed transaction object or its encoded string/buffer representation. |
Multi-Signature#
For transactions requiring signatures from multiple parties, use the multiSign<TxType>Tx
methods. These methods are designed to add a signature to a transaction that might already have other signatures, typically used in scenarios like multi-sig wallets or complex smart contract interactions.
Method Signature (General)
client.multiSign<TxType>Tx(params: GraphQLClient.TxParam<PartialDeep<GraphQLClient.<TxType>Tx>> & { data?: any; encoding?: 'base64' | 'base58' | 'base16' | 'hex' }): Promise<GraphQLClient.Transaction | string | Buffer>
Parameters
Name | Type | Description |
---|---|---|
|
| The transaction payload, which should include an array of existing |
|
| The wallet instance of the current signer. Must be a valid wallet with |
|
| Optional. The wallet address that delegated permissions. If present, the signature will reflect delegation. |
|
| Optional. Additional data to include in the multi-signature. |
|
| Optional. The desired encoding for the returned multi-signed transaction. |
Returns
Name | Type | Description |
---|---|---|
|
| The multi-signed transaction object or its encoded string/buffer representation. |
Broadcasting Transactions#
The send<TxType>Tx
methods are used to broadcast the signed transaction to the blockchain network. Upon successful broadcast and processing, the transaction hash is returned.
Method Signature (General)
client.send<TxType>Tx(params: GraphQLClient.TxParam<PartialDeep<GraphQLClient.<TxType>Tx>> & { commit?: boolean; extra?: any }, requestExtra?: any): Promise<string>
Parameters
Name | Type | Description |
---|---|---|
|
| The transaction payload, which must include the |
|
| The wallet instance used for signing (if |
|
| Optional. The pre-computed transaction signature. If provided, the method skips the internal signing step. |
|
| Optional. The wallet address that delegated permissions. |
|
| Optional. If |
|
| Optional. Extra parameters to verify the transaction, often used for passkeys. |
|
| Optional. Additional headers or request options for the underlying HTTP request (e.g., |
Returns
Name | Type | Description |
---|---|---|
|
| The hash of the successfully broadcasted transaction. |
Common Transaction Parameters (TxParam
)#
All transaction-sending methods in the GraphQLClient accept a TxParam
object, which encapsulates the transaction details and the signing wallet. The tx
field within TxParam
contains the core transaction data.
Field | Type | Description |
---|---|---|
|
| Optional. A unique number for the transaction from the sender's perspective. Defaults to |
|
| Optional. The sender's address. If not provided, it will be derived from the |
|
| Optional. The sender's public key. If not provided, it will be derived from the |
|
| Optional. The ID of the blockchain network. If not provided, it will be fetched from the client's context. |
|
| Optional. The address of the delegator if this transaction is sent on behalf of another account. |
|
| Optional. The cryptographic signature of the transaction. Usually generated internally by |
|
| Optional. An array of multi-signatures, used for multi-party transactions. |
|
| Required. The inner transaction object, specific to the type of operation (e.g., |
|
| Required. The wallet instance responsible for signing this transaction. |
|
| Optional. The address of the delegator if the transaction is being signed by a delegatee. |
|
| Optional. An externally provided signature for the transaction, bypassing internal signing. |
Helper Methods for Transaction Management#
The GraphQLClient provides convenient methods to list all available transaction-related functions:
Method | Description |
---|---|
| Returns a list of all |
| Returns a list of all |
| Returns a list of all |
| Returns a list of all |
Example: Declaring an Identity#
This example demonstrates the full transaction lifecycle for declaring a new identity on the blockchain using the declare
transaction type. We'll show both the explicit encoding/signing/sending steps and the convenient shortcut method.
const Mcrypto = require('@ocap/mcrypto');
const GraphQLClient = require('@ocap/client');
const { fromRandom, WalletType } = require('@ocap/wallet');
const { bytesToHex } = require('@ocap/util');
// 1. Initialize GraphQLClient
const client = new GraphQLClient('http://localhost:8210/api');
(async () => {
// Ensure client context is ready (fetches chain info, etc.)
await client.getContext();
// 2. Create a new wallet for the identity
const wallet = fromRandom(
WalletType({
role: Mcrypto.types.RoleType.ROLE_ACCOUNT,
pk: Mcrypto.types.KeyType.SECP256K1,
hash: Mcrypto.types.HashType.SHA3,
})
);
console.log(`New wallet address: ${wallet.address}`);
// 3. Define the inner transaction payload (itx)
const declareItx = {
moniker: `username-${Date.now().toString().slice(-4)}`,
};
// --- Explicit Transaction Lifecycle ---
// 4. Encode the transaction
console.log('\n--- Explicit Lifecycle ---');
const { object: encodedTxObject, buffer: encodedTxBuffer } = await client.encodeDeclareTx({
tx: {
itx: declareItx,
},
wallet,
});
console.log('Encoded Transaction Object:', encodedTxObject);
console.log('Encoded Transaction Buffer (Hex):', bytesToHex(encodedTxBuffer));
// 5. Sign the encoded transaction
const signedTx = await client.signDeclareTx({
tx: encodedTxObject,
wallet,
});
console.log('Signed Transaction Object:', signedTx);
// 6. Send the signed transaction to the blockchain
try {
const explicitTxHash = await client.sendDeclareTx({
tx: signedTx,
wallet, // Wallet is still needed for context/gas payer logic in sendTx
commit: true, // Wait for the transaction to be included in a block
});
console.log(`Explicitly sent DeclareTx hash: ${explicitTxHash}`);
} catch (error) {
console.error('Error sending explicit DeclareTx:', error.message);
}
// --- Shortcut Method ---
console.log('\n--- Shortcut Method ---');
try {
const shortcutTxHash = await client.declare({
moniker: `username-shortcut-${Date.now().toString().slice(-4)}`,
wallet,
commit: true,
});
console.log(`Shortcut sent DeclareTx hash: ${shortcutTxHash}`);
} catch (error) {
console.error('Error sending shortcut DeclareTx:', error.message);
}
})().catch(console.error);
This example first demonstrates the explicit steps of encoding, signing, and sending a DeclareTx
. It then shows the equivalent shortcut method client.declare()
, which internally handles the encoding and signing for convenience. The commit: true
option ensures that the method waits for the transaction to be confirmed on the blockchain.
Conclusion#
Understanding the process of sending transactions is crucial for interacting with the blockchain. The GraphQLClient simplifies this by providing intuitive methods for encoding, signing, and broadcasting, alongside convenient shortcuts for common operations. You are now equipped to initiate and manage various types of on-chain interactions.
To learn more about specific transaction types and their parameters, proceed to the Account Transactions section.