aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ark/alice.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-07 09:13:31 -0700
committerAdam Soltys <[email protected]>2026-10-07 09:13:31 -0700
commit95b72a73545cd2a3700b0e0866eee54e59d3b50e (patch)
tree81cc50c71d5e6cb78beaa1a7f755a23691f8983f /tools/ark/alice.js
parent3aff6e4cc9eb97fc0fa488f1f95001f69f24330a (diff)
parentdf87bd84560fec4b085b6f0f4785b61502ffd480 (diff)
downloadcoinosv3-95b72a73545cd2a3700b0e0866eee54e59d3b50e.tar.gz
coinosv3-95b72a73545cd2a3700b0e0866eee54e59d3b50e.zip
Merge branch 'worktree-agent-a9ba2f8bea9a7dafc'
Diffstat (limited to 'tools/ark/alice.js')
-rw-r--r--tools/ark/alice.js49
1 files changed, 49 insertions, 0 deletions
diff --git a/tools/ark/alice.js b/tools/ark/alice.js
new file mode 100644
index 0000000..b270edd
--- /dev/null
+++ b/tools/ark/alice.js
@@ -0,0 +1,49 @@
+// alice = the bark CLI wallet the regtest ark tests fund from.
+//
+// scheduled-refresh-test mines a coin's whole lifetime, which expires alice's
+// coins too — an expired vtxo can be refreshed but not sent, so any test that
+// runs after it would fund nothing ("spendableSat 0") or hand out an expired
+// coin. Every funding test also drains her a little. aliceReady() refreshes
+// expired coins back to life and boards more when she runs low; a no-op when
+// she's healthy.
+
+import { execSync } from 'node:child_process';
+
+export const ALICE = `${process.env.HOME}/bark/target/debug/bark --datadir ${process.env.HOME}/ark-regtest/alice`;
+const BCLI = 'docker exec bc bitcoin-cli -rpcwallet=coinos';
+const sh = (cmd) => execSync(cmd, { shell: '/bin/bash' }).toString().trim();
+const mine = (n) => sh(`${BCLI} generatetoaddress ${n} $(${BCLI} getnewaddress) >/dev/null`);
+const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
+
+const LOW_SAT = 200_000;
+const TOP_UP_BTC = '0.01';
+
+export const aliceBalance = () => JSON.parse(sh(`${ALICE} -q balance`)).spendable_sat;
+const expiredCoins = () => {
+ const tip = Number(sh(`${BCLI} getblockcount`));
+ return JSON.parse(sh(`${ALICE} -q vtxos`)).filter((v) => v.expiry_height <= tip);
+};
+
+export async function aliceReady() {
+ if (expiredCoins().length) {
+ console.log(' … refreshing alice\'s expired coins first');
+ // maintain = refresh what's expiring + resume any action a killed run left
+ // half-done (those hold their coins locked); errors surface below as a
+ // balance that never comes back
+ try { sh(`${ALICE} -q maintain >/dev/null 2>&1`); } catch {}
+ // the round's output turns spendable once its funding tx confirms and the
+ // indexer has seen it — keep mining until bark agrees
+ for (let i = 0; i < 20 && (expiredCoins().length || !aliceBalance()); i++) { mine(1); await sleep(1500); }
+ }
+ if (aliceBalance() < LOW_SAT) {
+ console.log(` … topping alice up (board ${TOP_UP_BTC} BTC)`);
+ const { address } = JSON.parse(sh(`${ALICE} -q onchain address`));
+ sh(`${BCLI} sendtoaddress ${address} ${TOP_UP_BTC} >/dev/null`);
+ mine(1);
+ for (let i = 0; i < 20; i++) {
+ try { sh(`${ALICE} -q board --all >/dev/null 2>&1`); break; } catch { await sleep(1500); } // wallet sync lag
+ }
+ const before = aliceBalance();
+ for (let i = 0; i < 20 && aliceBalance() <= before; i++) { mine(1); await sleep(1500); }
+ }
+}