aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/electrum-ws.test.js66
1 files changed, 39 insertions, 27 deletions
diff --git a/tools/electrum-ws.test.js b/tools/electrum-ws.test.js
index 1d5b5d0..f743819 100644
--- a/tools/electrum-ws.test.js
+++ b/tools/electrum-ws.test.js
@@ -1,6 +1,9 @@
// Verify the regtest electrum-ws bridge gives realtime push: subscribe to an
// address scripthash over ws://localhost:50003, fund it, expect a notification.
-// Run (stack + ews up): bun tools/electrum-ws.test.js
+// Run (stack + ews up): bun test tools/electrum-ws.test.js
+// Integration test: skips (with a note) when no bridge listens on :50003 — the
+// WS<->TCP bridge (coinos-server/electrum-ws) in front of a regtest electrs.
+import { test, expect } from 'bun:test';
import { $ } from 'bun';
import { p2wpkh } from '@scure/btc-signer/payment';
import * as btc from '@scure/btc-signer';
@@ -8,37 +11,46 @@ import { secp256k1 } from '@noble/curves/secp256k1';
import { sha256 } from '@noble/hashes/sha2';
import { bytesToHex } from '@noble/hashes/utils';
+const URL = 'ws://localhost:50003';
const REGTEST = { ...btc.TEST_NETWORK, bech32: 'bcrt' };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const bcli = (...a) => $`docker exec bc bitcoin-cli -regtest -rpcuser=admin1 -rpcpassword=123 ${a}`.text();
-const pub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey(), true);
-const pay = p2wpkh(pub, REGTEST);
-const sh = sha256(pay.script).reverse(); // electrum scripthash (reversed)
-const shHex = bytesToHex(sh);
-console.log('address', pay.address, '\nscripthash', shHex);
+// open the socket up front so an absent bridge becomes a skip, not a failure
+const ws = await new Promise((res) => {
+ const s = new WebSocket(URL);
+ const t = setTimeout(() => { s.close(); res(null); }, 3000);
+ s.onopen = () => { clearTimeout(t); res(s); };
+ s.onerror = () => { clearTimeout(t); res(null); };
+});
+if (!ws) console.log(`SKIP: no Electrum-over-WebSocket bridge at ${URL} (start the regtest ews bridge to run this)`);
-const ws = new WebSocket('ws://localhost:50003');
-let gotInitial = false, gotPush = false;
-ws.onmessage = (ev) => {
- for (const line of String(ev.data).split('\n')) {
- if (!line.trim()) continue;
- let m; try { m = JSON.parse(line); } catch { continue; }
- if (m.id === 2) { gotInitial = true; console.log('subscribe ok (initial status:', m.result, ')'); }
- if (m.method === 'blockchain.scripthash.subscribe') { gotPush = true; console.log('PUSH notification received:', JSON.stringify(m.params)); }
- }
-};
-await new Promise((res, rej) => { ws.onopen = res; ws.onerror = rej; });
-ws.send(JSON.stringify({ id: 1, method: 'server.version', params: ['test', '1.4'] }) + '\n');
-ws.send(JSON.stringify({ id: 2, method: 'blockchain.scripthash.subscribe', params: [shHex] }) + '\n');
+test.skipIf(!ws)('realtime scripthash push over the WS bridge', async () => {
+ const pub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey(), true);
+ const pay = p2wpkh(pub, REGTEST);
+ const shHex = bytesToHex(sha256(pay.script).reverse()); // electrum scripthash (reversed)
+ console.log('address', pay.address, '\nscripthash', shHex);
-await sleep(1500);
-if (!gotInitial) { console.log('FAIL — no subscribe response'); process.exit(1); }
+ let gotInitial = false, gotPush = false;
+ ws.onmessage = (ev) => {
+ for (const line of String(ev.data).split('\n')) {
+ if (!line.trim()) continue;
+ let m; try { m = JSON.parse(line); } catch { continue; }
+ if (m.id === 2) { gotInitial = true; console.log('subscribe ok (initial status:', m.result, ')'); }
+ if (m.method === 'blockchain.scripthash.subscribe') { gotPush = true; console.log('PUSH notification received:', JSON.stringify(m.params)); }
+ }
+ };
+ ws.send(JSON.stringify({ id: 1, method: 'server.version', params: ['test', '1.4'] }) + '\n');
+ ws.send(JSON.stringify({ id: 2, method: 'blockchain.scripthash.subscribe', params: [shHex] }) + '\n');
-console.log('funding the address…');
-await bcli('-rpcwallet=coinos', 'sendtoaddress', pay.address, '0.005');
-await bcli('generatetoaddress', '1', (await bcli('-rpcwallet=coinos', 'getnewaddress')).trim());
+ await sleep(1500);
+ expect(gotInitial).toBe(true);
-for (let i = 0; i < 20 && !gotPush; i++) await sleep(500);
-console.log(gotPush ? '\nPASS — realtime push delivered over the WS bridge' : '\nFAIL — no push within timeout');
-process.exit(gotPush ? 0 : 1);
+ console.log('funding the address…');
+ await bcli('-rpcwallet=coinos', 'sendtoaddress', pay.address, '0.005');
+ await bcli('generatetoaddress', '1', (await bcli('-rpcwallet=coinos', 'getnewaddress')).trim());
+
+ for (let i = 0; i < 20 && !gotPush; i++) await sleep(500);
+ ws.close();
+ expect(gotPush).toBe(true);
+}, 30000);