Dash 回调函数

下面是一套 Dash 常用回调函数(Callback Functions)大全,适用于 钱包状态监听、交易广播、InstantSend 确认、ChainLocks 验证、Dash Platform 数据同步 等场景。

使用 DashJS + WebSocket + DAPI 实现 实时回调,支持 错误处理、状态更新、UI 联动


1. 基础准备(CDN 引入)

<script src="https://cdn.jsdelivr.net/npm/dash@4.0.0/dist/dash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
const MNEMONIC = 'your testnet mnemonic here'; // 替换为测试网助记词
const client = new Dash.Client({
  network: 'testnet',
  wallet: { mnemonic: MNEMONIC },
  apps: { dashpay: { contractId: 'dashpay-contract-id' } } // 可选
});

2. 常用回调函数列表

功能回调函数说明
钱包同步完成onWalletReady钱包同步完成
新交易广播onTransactionCreated本地创建交易
交易已发送onTransactionBroadcast广播到网络
InstantSend 锁定onInstantSendLock交易被主节点锁定
ChainLocks 确认onChainLock链级最终确认
余额变化onBalanceChange余额更新
接收新付款onNewPayment地址收到 DASH
Dash Platform 数据变更onPlatformData身份、联系人、用户名更新

3. 完整回调实现代码

// 全局状态
let lastBalance = 0;
let account;

// 1. 钱包同步完成回调
async function onWalletSync(callback) {
  const account = await client.wallet.getAccount();
  account.isSynchronized().then(synced => {
    if (synced) {
      console.log('Wallet synced');
      callback(account);
    } else {
      setTimeout(() => onWalletSync(callback), 2000); // 轮询
    }
  });
}

// 2. 交易广播成功回调
async function onTransactionBroadcast(tx, callback) {
  try {
    const txid = await account.broadcastTransaction(tx);
    console.log('TX broadcast:', txid);
    callback(txid);
  } catch (err) {
    Swal.fire('广播失败', err.message, 'error');
  }
}

// 3. InstantSend 锁定回调(WebSocket)
function onInstantSendLock(txid, callback) {
  const ws = new WebSocket('wss://testnet-insight.dashevo.org/insight-api');
  ws.onopen = () => {
    ws.send(JSON.stringify({ "op": "islock_sub", "txid": txid }));
  };
  ws.onmessage = (e) => {
    const data = JSON.parse(e.data);
    if (data.op === 'islock' && data.x.txid === txid) {
      console.log('InstantSend locked:', txid);
      callback(data.x);
      ws.close();
    }
  };
}

// 4. ChainLocks 确认回调
function onChainLock(txid, callback) {
  const ws = new WebSocket('wss://testnet-insight.dashevo.org/insight-api');
  ws.onopen = () => {
    ws.send(JSON.stringify({ "op": "block_sub" }));
  };
  ws.onmessage = async (e) => {
    const data = JSON.parse(e.data);
    if (data.op === 'block') {
      const block = await client.getDAPIClient().core.getBlockByHeight(data.x.height);
      if (block.chainlock) {
        const txs = await client.getDAPIClient().core.getBlockByHash(block.hash);
        if (txs.tx.some(t => t === txid)) {
          console.log('ChainLocked:', txid);
          callback(block);
          ws.close();
        }
      }
    }
  };
}

// 5. 余额变化监听
async function onBalanceChange(callback) {
  const account = await client.wallet.getAccount();
  const balance = account.getTotalBalance() / 1e8;
  if (balance !== lastBalance) {
    console.log(`Balance changed: ${lastBalance} → ${balance}`);
    callback(balance, lastBalance);
    lastBalance = balance;
  }
  setTimeout(() => onBalanceChange(callback), 5000);
}

// 6. 接收新付款(地址监听)
function onNewPayment(address, callback) {
  const ws = new WebSocket('wss://testnet-insight.dashevo.org/insight-api');
  ws.onopen = () => {
    ws.send(JSON.stringify({ "op": "addr_sub", "addr": address }));
  };
  ws.onmessage = (e) => {
    const data = JSON.parse(e.data);
    if (data.op === 'utx') {
      const value = data.x.vout[0].value / 1e8;
      const txid = data.x.hash;
      console.log(`New payment: +${value} DASH`);
      callback({ txid, value, from: data.x.vin[0].addr });
    }
  };
}

// 7. Dash Platform 数据变更(用户名、联系人)
async function onPlatformData(identityId, type, callback) {
  const platform = client.platform;
  await platform.initialize();

  // 示例:监听 DashPay 联系人变更
  if (type === 'contact') {
    const query = { where: [['$ownerId', '==', identityId]] };
    const contacts = await platform.names.search('', 'dashpay', query);
    callback(contacts);
  }

  // 持续监听(轮询)
  setTimeout(() => onPlatformData(identityId, type, callback), 10000);
}

4. 实际使用示例(发送 + 全链路回调)

<button onclick="sendWithCallbacks()">发送并监听</button>
<div id="status"></div>

<script>
async function sendWithCallbacks() {
  const account = await client.wallet.getAccount();
  const to = 'yP...';
  const amount = 0.01;

  const status = document.getElementById('status');
  status.innerHTML = '<p>创建交易...</p>';

  // 1. 创建交易
  const tx = account.createTransaction({
    recipient: to,
    satoshis: amount * 1e8,
    instantSend: true
  });

  // 2. 广播 + 回调
  onTransactionBroadcast(tx, (txid) => {
    status.innerHTML += `<p>广播成功: ${txid.slice(0,16)}...</p>`;

    // 3. 监听 InstantSend
    onInstantSendLock(txid, (lock) => {
      status.innerHTML += `<p>InstantSend 锁定 (签名: ${lock.signatures})</p>`;

      // 4. 监听 ChainLock
      onChainLock(txid, (block) => {
        status.innerHTML += `<p>ChainLock 确认!区块: ${block.height}</p>`;
        Swal.fire('完成', '交易已永久确认', 'success');
      });
    });
  });
}
</script>

5. 回调流程图

[创建交易]
    ↓
[广播交易] → onTransactionBroadcast(txid)
    ↓
[InstantSend 锁定] → onInstantSendLock(lock)
    ↓
[ChainLock 确认] → onChainLock(block)
    ↑
[余额更新] ←──── onBalanceChange(newBalance)

6. 高级:封装为 Promise + Callback

function sendDashWithCallbacks(to, amount, callbacks = {}) {
  return new Promise(async (resolve, reject) => {
    try {
      const account = await client.wallet.getAccount();
      const tx = account.createTransaction({
        recipient: to,
        satoshis: amount * 1e8,
        instantSend: true
      });

      callbacks.onCreate?.(tx);

      const txid = await account.broadcastTransaction(tx);
      callbacks.onBroadcast?.(txid);

      // InstantSend
      onInstantSendLock(txid, (lock) => {
        callbacks.onInstantSend?.(lock);
      });

      // ChainLock
      callbacks.onChainLock?.(await waitForChainLock(txid));

      resolve(txid);
    } catch (err) {
      callbacks.onError?.(err);
      reject(err);
    }
  });
}

// 使用
sendDashWithCallbacks('yP...', 0.01, {
  onCreate: (tx) => console.log('TX created'),
  onBroadcast: (txid) => console.log('Broadcasted:', txid),
  onInstantSend: (lock) => console.log('IS locked'),
  onError: (err) => Swal.fire('错误', err.message, 'error')
});

7. 回调函数汇总表

回调参数触发时机
onWalletSync(account)account钱包同步完成
onTransactionBroadcast(txid)string交易广播成功
onInstantSendLock(lock)object主节点锁定交易
onChainLock(block)objectChainLock 最终确认
onBalanceChange(new, old)number余额变化
onNewPayment(payment){txid, value, from}收到付款
onPlatformData(data)array平台数据更新

8. 生产建议

// 错误重试
function withRetry(fn, max = 3) {
  return async (...args) => {
    for (let i = 0; i < max; i++) {
      try { return await fn(...args); }
      catch (e) { if (i === max-1) throw e; await sleep(1000); }
    }
  };
}

// 防抖
function debounce(fn, delay) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

立即测试

将以下代码保存为 dash-callbacks.html,替换 MNEMONIC,打开浏览器:

<!DOCTYPE html>
<html>
<head>
  <title>Dash 回调测试</title>
  <script src="https://cdn.jsdelivr.net/npm/dash@4.0.0/dist/dash.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</head>
<body>
  <h3>Dash 回调测试</h3>
  <button onclick="startAllCallbacks()">启动监听</button>
  <div id="log" style="font-family:monospace; margin-top:20px"></div>

  <script>
    const MNEMONIC = 'abandon ... art';
    const client = new Dash.Client({ network: 'testnet', wallet: { mnemonic: MNEMONIC } });
    const log = (msg) => document.getElementById('log').innerHTML += `<div>${new Date().toLocaleTimeString()} | ${msg}</div>`;

    async function startAllCallbacks() {
      const account = await client.wallet.getAccount();
      const address = account.getUnusedAddress().address;

      log('启动监听...');

      // 余额变化
      onBalanceChange((n, o) => log(`余额: ${o} → ${n} DASH`));

      // 新付款
      onNewPayment(address, (p) => log(`新付款: +${p.value} DASH (TX: ${p.txid.slice(0,10)}...)`));

      // 发送测试
      setTimeout(async () => {
        try {
          const tx = account.createTransaction({ recipient: address, satoshis: 10000, instantSend: true });
          onTransactionBroadcast(tx, (txid) => {
            log(`广播: ${txid}`);
            onInstantSendLock(txid, () => log('InstantSend 锁定'));
            onChainLock(txid, () => log('ChainLock 确认'));
          });
        } catch {}
      }, 3000);
    }
  </script>
</body>
</html>

需要我生成 React Hook 版、Node.js 后台监听、或集成到 Telegram Bot 吗? 随时说!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注