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) | object | ChainLock 最终确认 |
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 吗? 随时说!