aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ark/alice.js
blob: b270edd86076562943e5ccf434b0867fe3c03b4c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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); }
  }
}