Skip to main content

Server Wallets Integration

This guide covers integrating AxonVault server wallets into your backend services for treasury management, automated trading, and payment processing.

Overview

Server wallets are designed for:
  • Backend automation
  • Treasury management
  • Payment processing
  • Programmatic trading

Setup

1. Create API Credentials

  1. Log in to AxonVault Dashboard
  2. Navigate to Settings > API Keys
  3. Create a new API key with appropriate permissions
  4. Store the Client Key and Secret Key securely

2. Configure Environment

# .env
AXONVAULT_CLIENT_KEY=ak_live_abc123
AXONVAULT_SECRET_KEY=sk_live_xyz789...
AXONVAULT_BASE_URL=https://api.axonvault.io

SDK Setup

Node.js

import crypto from 'crypto';

class AxonVaultClient {
  constructor(clientKey, secretKey, baseUrl = 'https://api.axonvault.io') {
    this.clientKey = clientKey;
    this.secretKey = secretKey;
    this.baseUrl = baseUrl;
  }
  
  sign(method, path, body = null) {
    const timestamp = new Date().toISOString();
    const bodyStr = body ? JSON.stringify(body) : '';
    const payload = `${method}\n${path}\n${timestamp}\n${bodyStr}`;
    
    const signature = crypto
      .createHmac('sha256', this.secretKey)
      .update(payload)
      .digest('hex');
    
    return {
      'X-Access-Key': this.clientKey,
      'X-Signature': signature,
      'X-Timestamp': timestamp,
      'Content-Type': 'application/json'
    };
  }
  
  async request(method, path, body = null) {
    const headers = this.sign(method, path, body);
    
    const response = await fetch(`${this.baseUrl}${path}`, {
      method,
      headers,
      body: body ? JSON.stringify(body) : undefined
    });
    
    if (!response.ok) {
      const error = await response.json();
      throw new Error(`${error.errorType}: ${error.errorMessage}`);
    }
    
    return response.json();
  }
  
  // Wallet methods
  async createWallet(name) {
    return this.request('POST', '/v1/server/wallets', { walletName: name });
  }
  
  async getWallet(walletId) {
    return this.request('GET', `/v1/server/wallets/${walletId}`);
  }
  
  async listWallets(limit = 20, cursor = null) {
    const params = new URLSearchParams({ limit: limit.toString() });
    if (cursor) params.append('cursor', cursor);
    return this.request('GET', `/v1/server/wallets?${params}`);
  }
  
  // Transaction methods
  async buildTransaction(params) {
    return this.request('POST', '/v1/transactions/build', params);
  }
  
  async signTransaction(params) {
    return this.request('POST', '/v1/signature/sign', params);
  }
  
  async submitTransaction(txId, signedTxHex) {
    return this.request('POST', '/v1/transactions/submit', { txId, signedTxHex });
  }
}

// Usage
const client = new AxonVaultClient(
  process.env.AXONVAULT_CLIENT_KEY,
  process.env.AXONVAULT_SECRET_KEY
);

Python

import hmac
import hashlib
import json
import os
from datetime import datetime, timezone
import requests

class AxonVaultClient:
    def __init__(self, client_key: str, secret_key: str, base_url: str = 'https://api.axonvault.io'):
        self.client_key = client_key
        self.secret_key = secret_key
        self.base_url = base_url
    
    def _sign(self, method: str, path: str, body: dict = None) -> dict:
        timestamp = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
        body_str = json.dumps(body, separators=(',', ':')) if body else ''
        payload = f"{method}\n{path}\n{timestamp}\n{body_str}"
        
        signature = hmac.new(
            self.secret_key.encode(),
            payload.encode(),
            hashlib.sha256
        ).hexdigest()
        
        return {
            'X-Access-Key': self.client_key,
            'X-Signature': signature,
            'X-Timestamp': timestamp,
            'Content-Type': 'application/json'
        }
    
    def _request(self, method: str, path: str, body: dict = None):
        headers = self._sign(method, path, body)
        
        response = requests.request(
            method,
            f"{self.base_url}{path}",
            headers=headers,
            json=body
        )
        
        if not response.ok:
            error = response.json()
            raise Exception(f"{error['errorType']}: {error['errorMessage']}")
        
        return response.json()
    
    # Wallet methods
    def create_wallet(self, name: str):
        return self._request('POST', '/v1/server/wallets', {'walletName': name})
    
    def get_wallet(self, wallet_id: str):
        return self._request('GET', f'/v1/server/wallets/{wallet_id}')
    
    # Transaction methods
    def build_transaction(self, **params):
        return self._request('POST', '/v1/transactions/build', params)
    
    def sign_transaction(self, **params):
        return self._request('POST', '/v1/signature/sign', params)
    
    def submit_transaction(self, tx_id: str, signed_tx_hex: str):
        return self._request('POST', '/v1/transactions/submit', {
            'txId': tx_id,
            'signedTxHex': signed_tx_hex
        })

# Usage
client = AxonVaultClient(
    os.environ['AXONVAULT_CLIENT_KEY'],
    os.environ['AXONVAULT_SECRET_KEY']
)

Common Workflows

Create Treasury Wallet

async function setupTreasury() {
  // Create wallet
  const { wallet } = await client.createWallet('Treasury');
  
  // Create account
  const { account } = await client.request('POST', 
    `/v1/server/wallets/${wallet.walletId}/accounts`,
    { accountIndex: 0, accountName: 'Main' }
  );
  
  // Derive addresses for needed chains
  const chains = ['eip155:1', 'eip155:8453', 'solana:mainnet'];
  const addresses = [];
  
  for (const chainId of chains) {
    const { address } = await client.request('POST',
      `/v1/wallets/${wallet.walletId}/accounts/${account.accountId}/addresses/derive`,
      { chainId }
    );
    addresses.push(address);
  }
  
  return { wallet, account, addresses };
}

Send Payment

async function sendPayment(from, to, amount, chainRef, keyId) {
  // Build transaction
  const { txId, unsignedTxHex } = await client.buildTransaction({
    fromAddress: from,
    toAddress: to,
    amount: amount,
    chainReference: chainRef
  });
  
  // Sign
  const { signature } = await client.signTransaction({
    chainReference: chainRef,
    unsignedTxHex: unsignedTxHex,
    keyId: keyId,
    coinType: 60,
    accountIndex: 0
  });
  
  // Construct signed
  const { signedTxHex } = await client.request('POST',
    '/v1/transactions/construct-signed',
    { txId, signature }
  );
  
  // Submit
  const { txHash } = await client.submitTransaction(txId, signedTxHex);
  
  return txHash;
}

Batch Payments

async function batchPayments(payments, keyId) {
  const results = [];
  
  for (const payment of payments) {
    try {
      const txHash = await sendPayment(
        payment.from,
        payment.to,
        payment.amount,
        payment.chainRef,
        keyId
      );
      results.push({ success: true, txHash, payment });
    } catch (error) {
      results.push({ success: false, error: error.message, payment });
    }
  }
  
  return results;
}

Webhook Integration

Set up webhooks to receive transaction notifications:
// Create webhook
await client.request('POST', '/v1/tx-relay/webhooks', {
  tenantId: 'ten_abc123',
  projectId: 'proj_abc123',
  url: 'https://yourapp.com/webhooks/axonvault',
  events: ['transaction.confirmed', 'transaction.failed'],
  secret: 'your_webhook_secret',
  enabled: true
});

// Handle webhook (Express.js)
app.post('/webhooks/axonvault', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  
  // Verify signature
  const expectedSig = crypto
    .createHmac('sha256', webhookSecret)
    .update(JSON.stringify(req.body))
    .digest('hex');
  
  if (signature !== expectedSig) {
    return res.status(401).send('Invalid signature');
  }
  
  const { event, data } = req.body;
  
  switch (event) {
    case 'transaction.confirmed':
      console.log(`Transaction ${data.txHash} confirmed`);
      break;
    case 'transaction.failed':
      console.log(`Transaction ${data.txId} failed: ${data.error}`);
      break;
  }
  
  res.status(200).send('OK');
});

Best Practices

  • Store credentials in secret managers (AWS Secrets Manager, HashiCorp Vault)
  • Rotate API keys regularly
  • Use IP allowlisting
  • Implement request logging
  • Implement retry with exponential backoff
  • Use idempotency keys for transactions
  • Monitor webhook delivery
  • Set up alerting for failures
  • Configure policies before going live
  • Enable audit logging
  • Implement approval workflows for large transactions
  • Regular security reviews