C1/C2 Orders API Guide
How to convert UI Commands into Coinweb L2 transactions and sign/broadcast them.
Prerequisites
- Node.js (v18 or higher recommended)
- Yarn package manager (v1.22.0 or higher)
1. Install dependencies
Add .yarnrc.yml file to project repository
checksumBehavior: update
nodeLinker: node-modules
npmScopes:
coinweb:
npmRegistryServer: "https://npm.coinweb.io/"Then run
yarn add @coinweb/wallet-lib bip39 hdkey secp256k12. Create coinweb-wallet.ts file
This class can be used to operate wallet functions of Coinweb.
import {
create_wallet as createWallet,
from_hex_string as fromHexString,
compose_ui_commands as composeUiCommand,
create_tx_monitor as createTxMonitor,
add_txs as addTxs,
sign,
NetworkName,
embed,
L2TransactionDataInput,
UiCommand,
TransactionMonitor,
type Transaction,
} from '@coinweb/wallet-lib';
import { mnemonicToSeedSync } from 'bip39';
import HDKey from 'hdkey';
import secp256k1 from 'secp256k1';
/**
* CoinWeb Wallet class
* Manages wallet instance, transaction monitor, and UI command execution
*/
export class CoinWebWallet {
public readonly wallet: Awaited<ReturnType<typeof createWallet>>;
public readonly txMonitor: TransactionMonitor;
public readonly pubKey: string;
private constructor(
wallet: Awaited<ReturnType<typeof createWallet>>,
txMonitor: TransactionMonitor
) {
this.wallet = wallet;
this.txMonitor = txMonitor;
this.pubKey = wallet.pub_key;
}
/**
* Creates a CoinWeb wallet instance from a mnemonic phrase
* Factory method to create and initialize a wallet with transaction monitor
*
* @param params - Wallet configuration parameters
* @returns CoinWebWallet instance ready for L2 operations
*/
static async create(params: {
mnemonic: string;
backendUrl: string;
shard: NetworkName;
}): Promise<CoinWebWallet> {
// Generate HD key from mnemonic
const hdkey = CoinWebWallet.mnemonicToHDKey(params.mnemonic);
// Create wallet with backend connection and signing configuration
const wallet = await createWallet({
address: params.backendUrl, // HTTP endpoint for wallet operations
ws_address: `${params.backendUrl.replace(/^https:/, 'wss:')}`, // WebSocket endpoint (convert https to wss)
pub_key: hdkey.publicKey?.toString('hex') ?? '', // Public key in hex format
shard: params.shard, // Network shard
max_retry_time_secs: null, // No retry timeout limit
enable_retries: null, // Retry behavior (null = default)
// Callback function for signing messages - converts private key and signs
sign_callback: (msg) => {
return sign(fromHexString(hdkey.privateKey?.toString('hex') ?? ''), msg);
},
broadcaster_wallet_address: null, // No custom broadcaster address
});
// Create transaction monitor
const pendingTxs: Transaction[] = [];
const utxos = new Map<string, unknown[]>();
const txMonitor = createTxMonitor(pendingTxs, utxos);
return new CoinWebWallet(wallet, txMonitor);
}
/**
* Converts a mnemonic phrase to an HD (Hierarchical Deterministic) key
* This function generates a master key from the mnemonic seed and sets up
* a custom signing function that uses secp256k1 elliptic curve cryptography
*
* @param mnemonic - BIP39 mnemonic phrase (12 or 24 words)
* @returns HDKey instance with custom signing capability for CoinWeb wallet
*/
private static mnemonicToHDKey(mnemonic: string) {
// Convert mnemonic to seed using BIP39 standard
const seed = mnemonicToSeedSync(mnemonic);
// Generate HD key from master seed
const hdkey = HDKey.fromMasterSeed(seed);
// Override the sign method to use secp256k1 signing algorithm
// This is required for CoinWeb wallet signature format
hdkey.sign = function (hash: Buffer<ArrayBufferLike>) {
// Sign the hash with the private key using secp256k1 ECDSA
const sig = secp256k1.ecdsaSign(Uint8Array.from(hash), Uint8Array.from(hdkey.privateKey ?? []));
// Normalize the signature to ensure consistent format
const array = secp256k1.signatureNormalize(sig.signature);
// Export signature as Buffer for CoinWeb wallet library
return Buffer.from(secp256k1.signatureExport(array));
};
return hdkey;
}
/**
* Executes a UI command by composing it into an L2 transaction and embedding it
* This is a convenience method that combines compose and embed operations
*
* @param jsonTokenCommand - UI command in JSON format (deposit, orders, etc.)
* @param networkWrite - Optional network name for write operations (null = default)
* @returns Transaction UUID (hash) for tracking the transaction
*/
async executeUiCommand(
jsonTokenCommand: UiCommand,
networkWrite: NetworkName | null = null
): Promise<string> {
if (!jsonTokenCommand) throw new Error('UI command not found');
// Compose the UI command into an L2 transaction structure
const l2TransactionData = await composeUiCommand(this.wallet, [jsonTokenCommand], networkWrite);
// Add the transaction to the monitor for tracking and state management
await addTxs(this.txMonitor, l2TransactionData?.l2_transaction);
// Submit transaction to L2 network and get transaction UUID
const uuid = await embed(this.wallet, l2TransactionData.l2_transaction);
return uuid;
}
/**
* Composes and adds a token command to the transaction monitor
* This function takes a UI command (like deposit or create orders), composes it into
* an L2 transaction, and adds it to the transaction monitor for tracking
*
* @param jsonTokenCommand - UI command in JSON format (deposit, orders, etc.)
* @param networkWrite - Optional network name for write operations (null = default)
* @returns Object containing L2 transaction data and newly added transactions
*/
async composeTokenCommand(
jsonTokenCommand: UiCommand,
networkWrite: NetworkName | null = null
) {
if (!jsonTokenCommand) throw new Error('UI command not found');
// Compose the UI command into an L2 transaction structure
const l2TransactionData = await composeUiCommand(this.wallet, [jsonTokenCommand], networkWrite);
// Add the transaction to the monitor for tracking and state management
const newTxs = await addTxs(this.txMonitor, l2TransactionData?.l2_transaction);
return { l2TransactionData, newTxs };
}
/**
* Embeds an L2 transaction into the blockchain
* This submits the transaction to the CoinWeb L2 network and returns a transaction UUID
*
* @param l2Transaction - L2 transaction data to embed
* @returns Transaction UUID (hash) for tracking the transaction
*/
async embedTransaction(l2Transaction: L2TransactionDataInput): Promise<string> {
if (!l2Transaction) throw new Error('L2 transaction not found');
// Submit transaction to L2 network and get transaction UUID
const uuid = await embed(this.wallet, l2Transaction);
return uuid;
}
}3. Example how to propagate the /c2/makeDeposit UI Command
Processing the "Deposit CWEB collateral into C2(Ask) token contract" UI Command.
// Step 1: Import dependencies
import { CoinWebWallet } from "./coinweb-wallet.ts"
import { NetworkName } from '@coinweb/claims-client';
// Step 2: Create wallet from mnemonic
const coinWebWallet = await CoinWebWallet.create({
mnemonic: 'Coinweb Wallet mnemonic',
backendUrl: 'https://api-cloud.coinweb.io/wallet', // Coinweb Backend wallet url'
shard: NetworkName.BNB // Shard to operate on Coinweb Chain
});
console.log('✅ Wallet created');
console.log(' Public Key:', coinWebWallet.pubKey);
// Step 3: Call Pactswap REST API to build the UI Command for the "/c2/makeDeposit"
const depositAmount = 100 * 10 ** 18; // 100 CWEB
const data = await axios.post<{ rawTx: string }>(`https://cwap-api.coinhq.store/pactswap_cm/ui-commands/c2/makeDeposit`, {
contractId: 'C2 contract id',
depositAmount: depositAmount,
});
// The UI Command
const rawTx = data.data.rawTx;
console.log(' 📝 Composed deposit collateral command');
// Step 4: Propagate(Compose/Sign/Broadcast) the UI Command via the Coinweb wallet library
const hashTxDeposit = await this.coinWebWallet.executeUiCommand(JSON.parse(rawTx));
console.log(' ✅ Deposit transaction hash:', hashTxDeposit); Was this documentation helpful? Any suggestions?