From 7ff350dec88aad4d9a3cbedce34764e395d28fc7 Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Mon, 1 Jun 2026 23:11:02 +0200 Subject: [PATCH 1/4] Migrate regtest usage off nigiri (in-house Node CLI) arkade-regtest replaced nigiri/chopsticks/esplora with an in-house Docker Compose stack (Bitcoin Core + Fulcrum + mempool + ...) driven by a Node CLI. This updates the emulator's standalone integration-test environment to match. - Esplora REST endpoints moved to mempool's /api: - host side: http://localhost:3000 -> http://localhost:3000/api (all mempoolexplorer.NewExplorer(...) calls in test/) - in-network: http://chopsticks:3000 -> http://mempool_web/api (ARKD_ESPLORA_URL in docker-compose.regtest.yml; `ark init --explorer`) - Replaced direct `nigiri` CLI use in Go integration tests with the documented container interface: `docker exec bitcoin bitcoin-cli ...` helpers (onchainFaucet / mineBlocks / bitcoinCli). nigiri auto-mined; the new stack does not, so onchainFaucet mines 1 block to preserve confirm-on-faucet. - CI: replaced the nigiri GitHub Action with setup-node + the arkade-regtest Node CLI (REGTEST_PROFILES=base ... start / clean). - README: updated prerequisites and testing steps off nigiri. - docker-compose.regtest.yml: point the shared external network at the arkade-regtest stack's default network. Blocked by ArkLabsHQ/arkade-regtest#27 --- .github/workflows/test.yaml | 13 +++- README.md | 16 ++++- docker-compose.regtest.yml | 8 ++- test/asset_account_covenant_test.go | 2 +- test/asset_test.go | 4 +- test/batch_continuation_test.go | 2 +- test/contract_id_test.go | 2 +- test/cross_input_script_validation_test.go | 2 +- test/delegate_test.go | 2 +- test/deprecated_key_signing_test.go | 11 ++-- test/onchain_test.go | 22 +++---- test/pay_2_out_test.go | 4 +- test/recursive_covenant_test.go | 2 +- test/signed_pay_to_output_test.go | 2 +- test/tx_test.go | 69 ++++++++++++++++++---- test/utils_test.go | 4 +- 16 files changed, 113 insertions(+), 52 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d3d9abd..93d53da 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -29,9 +29,14 @@ jobs: - uses: actions/setup-go@v6 with: go-version: '1.26.3' + - uses: actions/setup-node@v4 + with: + node-version: '20' - - name: Run Nigiri - uses: vulpemventures/nigiri-github-action@v1 + - name: Start regtest base stack (Bitcoin Core + Fulcrum + mempool) + run: | + git clone --branch master https://github.com/ArkLabsHQ/arkade-regtest.git regtest + REGTEST_PROFILES=base node regtest/regtest.mjs start - name: Run regtest environment run: make docker-run @@ -50,3 +55,7 @@ jobs: - name: Tear down if: always() run: make docker-stop + + - name: Tear down regtest stack + if: always() + run: node regtest/regtest.mjs clean || true diff --git a/README.md b/README.md index 8aa86a5..7859529 100644 --- a/README.md +++ b/README.md @@ -197,8 +197,8 @@ The service can be configured using environment variables: - Go 1.26+ - Docker and Docker Compose +- Node.js 18+ (to drive the [arkade-regtest](https://github.com/ArkLabsHQ/arkade-regtest) stack for integration testing) - Buf CLI (for protocol buffer generation) -- [Nigiri](https://nigiri.vulpem.com) (for integration testing) ### Building @@ -223,12 +223,22 @@ make run # Run unit tests make test -# Run docker regtest environment -nigiri start +# Bring up the regtest base stack (Bitcoin Core + Fulcrum + mempool) via the +# arkade-regtest Node CLI (replaces `nigiri start`). Esplora's REST API is served +# by mempool under /api (http://localhost:3000/api on the host, +# http://mempool_web/api in-network). +git clone https://github.com/ArkLabsHQ/arkade-regtest.git regtest +REGTEST_PROFILES=base node regtest/regtest.mjs start + +# Run the emulator + arkd docker environment make docker-run # Run integration tests make integrationtest + +# Tear down +make docker-stop +node regtest/regtest.mjs clean ``` ## Supported Opcodes diff --git a/docker-compose.regtest.yml b/docker-compose.regtest.yml index 81b43db..0d27c49 100644 --- a/docker-compose.regtest.yml +++ b/docker-compose.regtest.yml @@ -99,7 +99,7 @@ services: - ARKD_CHECKPOINT_EXIT_DELAY=512 - ARKD_DATADIR=./data/regtest - ARKD_WALLET_ADDR=arkd-wallet:6060 - - ARKD_ESPLORA_URL=http://chopsticks:3000 + - ARKD_ESPLORA_URL=http://mempool_web/api - ARKD_ROUND_MIN_PARTICIPANTS_COUNT=${ARKD_ROUND_MIN_PARTICIPANTS_COUNT:-1} - ARKD_ROUND_MAX_PARTICIPANTS_COUNT=${ARKD_ROUND_MAX_PARTICIPANTS_COUNT:-128} - ARKD_VTXO_MIN_AMOUNT=1 @@ -113,7 +113,11 @@ services: - type: tmpfs target: /app/data +# Join the network created by the arkade-regtest stack so this compose's arkd / +# arkd-wallet can reach the shared bitcoin, nbxplorer and mempool_web containers. +# Docker Compose names the default network "_default"; arkade-regtest's +# compose project is "arkade-regtest", hence "arkade-regtest_default". networks: default: - name: nigiri + name: arkade-regtest_default external: true diff --git a/test/asset_account_covenant_test.go b/test/asset_account_covenant_test.go index d1c4ba2..d8551e9 100644 --- a/test/asset_account_covenant_test.go +++ b/test/asset_account_covenant_test.go @@ -90,7 +90,7 @@ func TestAssetAccountCovenant(t *testing.T) { }) indexerSvc := setupIndexer(t) - explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) infos, err := grpcAlice.GetInfo(ctx) diff --git a/test/asset_test.go b/test/asset_test.go index 0d45d63..422e4c3 100644 --- a/test/asset_test.go +++ b/test/asset_test.go @@ -157,7 +157,7 @@ func TestOffchainTxWithAsset(t *testing.T) { encodedValidTx, err := validTx.B64Encode() require.NoError(t, err) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) signedTx, err := bobWallet.SignTransaction( @@ -216,7 +216,7 @@ func TestSettlementWithAsset(t *testing.T) { conn.Close() }) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) // ========================================================================= diff --git a/test/batch_continuation_test.go b/test/batch_continuation_test.go index c3c7502..753b9b2 100644 --- a/test/batch_continuation_test.go +++ b/test/batch_continuation_test.go @@ -65,7 +65,7 @@ func TestCounterContractBatchContinuation(t *testing.T) { indexerSvc := setupIndexer(t) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) // ========================================================================= diff --git a/test/contract_id_test.go b/test/contract_id_test.go index 86f5111..da2c1e1 100644 --- a/test/contract_id_test.go +++ b/test/contract_id_test.go @@ -56,7 +56,7 @@ func TestContractIdWithAssetIdentity(t *testing.T) { require.NoError(t, err) indexerSvc := setupIndexer(t) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) // Recipient for the reader's value after the co-spend. diff --git a/test/cross_input_script_validation_test.go b/test/cross_input_script_validation_test.go index 68dafa0..aa50f87 100644 --- a/test/cross_input_script_validation_test.go +++ b/test/cross_input_script_validation_test.go @@ -414,7 +414,7 @@ func newCrossInputTestEnv(t *testing.T) *crossInputTestEnv { indexerSvc := setupIndexer(t) - explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) recipientPrivKey, err := btcec.NewPrivateKey() diff --git a/test/delegate_test.go b/test/delegate_test.go index 3e2827b..cf68372 100644 --- a/test/delegate_test.go +++ b/test/delegate_test.go @@ -85,7 +85,7 @@ func TestCovenantDelegate(t *testing.T) { indexerSvc := setupIndexer(t) explorerSvc, err := mempoolexplorer.NewExplorer( - "http://localhost:3000", arklib.BitcoinRegTest, + "http://localhost:3000/api", arklib.BitcoinRegTest, ) require.NoError(t, err) diff --git a/test/deprecated_key_signing_test.go b/test/deprecated_key_signing_test.go index f4aee75..96f5d44 100644 --- a/test/deprecated_key_signing_test.go +++ b/test/deprecated_key_signing_test.go @@ -73,7 +73,7 @@ func runSubmitTxWithDeprecatedKey( bobWallet, _, bobPubKey := setupWallet(t, ctx) aliceAddr := fundAndSettleAlice(t, ctx, alice, 10_000) indexerSvc := setupIndexer(t) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) alicePkScript, err := script.P2TRScript(aliceAddr.VtxoTapKey) @@ -164,7 +164,7 @@ func runSubmitIntentFinalizationWithDeprecatedKey( t.Cleanup(func() { grpcClient.Close() }) aliceAddr := fundAndSettleAlice(t, ctx, alice, 100_000) indexerSvc := setupIndexer(t) - explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) delegateArkadeScript := enforceSelfSend(t) @@ -325,13 +325,12 @@ func runSubmitOnchainWithDeprecatedKey( tapAddr, err := btcutil.NewAddressTaproot(schnorr.SerializePubKey(vtxoTapKey), getRegtestParams(t)) require.NoError(t, err) - _, err = runCommand("nigiri", "faucet", tapAddr.EncodeAddress(), "0.01") + _, err = onchainFaucet(tapAddr.EncodeAddress(), "0.01") require.NoError(t, err) - explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) fundingUtxo := waitForUtxo(t, explorerSvc, tapAddr.EncodeAddress(), 60*time.Second) - _, err = runCommand("nigiri", "rpc", "-generate", "1") - require.NoError(t, err) + require.NoError(t, mineBlocks(1)) rawFundingHex, err := explorerSvc.GetTxHex(fundingUtxo.Txid) require.NoError(t, err) rawFundingBytes, err := hex.DecodeString(rawFundingHex) diff --git a/test/onchain_test.go b/test/onchain_test.go index 55bd8a3..beae40d 100644 --- a/test/onchain_test.go +++ b/test/onchain_test.go @@ -25,9 +25,9 @@ import ( "github.com/stretchr/testify/require" ) -// TestSubmitOnchainTx funds an arkade-tweaked P2TR address directly via -// `nigiri faucet`, then spends it via a plain Bitcoin transaction where the -// emulator co-signs after running the embedded arkade script. +// TestSubmitOnchainTx funds an arkade-tweaked P2TR address directly via the +// regtest Bitcoin Core node, then spends it via a plain Bitcoin transaction +// where the emulator co-signs after running the embedded arkade script. func TestSubmitOnchainTx(t *testing.T) { ctx := context.Background() @@ -93,12 +93,12 @@ func TestSubmitOnchainTx(t *testing.T) { require.NoError(t, err) tapAddrStr := tapAddr.EncodeAddress() - // --- Fund the address via nigiri --- - _, err = runCommand("nigiri", "faucet", tapAddrStr, "0.01") + // --- Fund the address via the regtest Bitcoin Core node --- + _, err = onchainFaucet(tapAddrStr, "0.01") require.NoError(t, err) explorerSvc, err := mempoolexplorer.NewExplorer( - "http://localhost:3000", arklib.BitcoinRegTest, + "http://localhost:3000/api", arklib.BitcoinRegTest, ) require.NoError(t, err) @@ -106,8 +106,7 @@ func TestSubmitOnchainTx(t *testing.T) { fundingUtxo := waitForUtxo(t, explorerSvc, tapAddrStr, 60*time.Second) // Mine a block so the funding tx is confirmed. - _, err = runCommand("nigiri", "rpc", "-generate", "1") - require.NoError(t, err) + require.NoError(t, mineBlocks(1)) rawFundingHex, err := explorerSvc.GetTxHex(fundingUtxo.Txid) require.NoError(t, err) @@ -337,16 +336,13 @@ func TestSubmitOnchainTx(t *testing.T) { require.NoError(t, err) exitAddrStr := exitAddr.EncodeAddress() - _, err = runCommand("nigiri", "faucet", exitAddrStr, "0.01") + _, err = onchainFaucet(exitAddrStr, "0.01") require.NoError(t, err) exitUtxo := waitForUtxo(t, explorerSvc, exitAddrStr, 60*time.Second) // Mine CSV + 1 blocks so the relative locktime is satisfied. - for i := uint32(0); i < csvBlocks+1; i++ { - _, err = runCommand("nigiri", "rpc", "-generate", "1") - require.NoError(t, err) - } + require.NoError(t, mineBlocks(int(csvBlocks+1))) exitRawHex, err := explorerSvc.GetTxHex(exitUtxo.Txid) require.NoError(t, err) diff --git a/test/pay_2_out_test.go b/test/pay_2_out_test.go index 5a9ff13..6c2c36c 100644 --- a/test/pay_2_out_test.go +++ b/test/pay_2_out_test.go @@ -72,7 +72,7 @@ func TestPayToTwoOutputs(t *testing.T) { aliceAddr, err := arklib.DecodeAddressV0(offchainAddr) require.NoError(t, err) - _, err = runCommand("nigiri", "faucet", boardingAddress) + _, err = onchainFaucet(boardingAddress, "") require.NoError(t, err) time.Sleep(5 * time.Second) @@ -229,7 +229,7 @@ func TestPayToTwoOutputs(t *testing.T) { RevealedTapscripts: []string{hex.EncodeToString(arkadeTapscript)}, } - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) // ======================================== diff --git a/test/recursive_covenant_test.go b/test/recursive_covenant_test.go index 86583c3..54bf022 100644 --- a/test/recursive_covenant_test.go +++ b/test/recursive_covenant_test.go @@ -179,7 +179,7 @@ func TestRecursivePolicy(t *testing.T) { alicePkScript, err := txscript.PayToTaprootScript(alicePubKey) require.NoError(t, err) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) submitAndFinalize := func(candidateTx *psbt.Packet, checkpoints []*psbt.Packet) { diff --git a/test/signed_pay_to_output_test.go b/test/signed_pay_to_output_test.go index aaaeaa5..61a68e9 100644 --- a/test/signed_pay_to_output_test.go +++ b/test/signed_pay_to_output_test.go @@ -44,7 +44,7 @@ func TestSignedPayToOutput(t *testing.T) { indexerSvc := setupIndexer(t) explorerSvc, err := mempoolexplorer.NewExplorer( - "http://localhost:3000", arklib.BitcoinRegTest, + "http://localhost:3000/api", arklib.BitcoinRegTest, ) require.NoError(t, err) diff --git a/test/tx_test.go b/test/tx_test.go index 850078b..8414f13 100644 --- a/test/tx_test.go +++ b/test/tx_test.go @@ -12,6 +12,7 @@ import ( "net/http" "os" "os/exec" + "strconv" "strings" "sync" "testing" @@ -90,7 +91,7 @@ func TestSubmitOffchain(t *testing.T) { altIntroWallet, _, altIntroPubKey := setupWallet(t, ctx) emulatorClient, emulatorPublicKey, _ := setupEmulatorClient(t, ctx) indexerSvc := setupIndexer(t) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) bobPaysAliceContract := createVtxoScriptWithArkadeScript(bobPubKey, aliceAddr.Signer, emulatorPublicKey, arkade.ArkadeScriptHash(mustPayAliceScript)) @@ -724,7 +725,7 @@ func TestSettlement(t *testing.T) { encodedIntentProof, err := intentPtx.B64Encode() require.NoError(t, err) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) signedIntentProof, err := bobWallet.SignTransaction(ctx, explorer, encodedIntentProof) @@ -892,15 +893,13 @@ func TestBoarding(t *testing.T) { require.NoError(t, err) // faucet the contract address with onchain funds - faucetOutput, err := runCommand("nigiri", "faucet", contractBtcAddr.EncodeAddress()) + faucetTxid, err := onchainFaucet(contractBtcAddr.EncodeAddress(), "") require.NoError(t, err) - faucetTxid := strings.TrimSpace(strings.TrimPrefix(faucetOutput, "txId:")) - time.Sleep(5 * time.Second) // get the raw transaction to find the contract output - rawTxHex, err := runCommand("nigiri", "rpc", "getrawtransaction", faucetTxid) + rawTxHex, err := bitcoinCli("getrawtransaction", faucetTxid) require.NoError(t, err) rawTxBytes, err := hex.DecodeString(strings.TrimSpace(rawTxHex)) @@ -991,7 +990,7 @@ func TestBoarding(t *testing.T) { encodedIntentProof, err := intentPtx.B64Encode() require.NoError(t, err) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) signedIntentProof, err := bobWallet.SignTransaction(ctx, explorer, encodedIntentProof) @@ -1148,7 +1147,7 @@ func TestEmulatorRejectsInvalidArkadeScript(t *testing.T) { checkpointScriptBytes, err := hex.DecodeString(infos.CheckpointTapscript) require.NoError(t, err) - explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorer, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) invalidArkadeScript, err := txscript.NewScriptBuilder(). @@ -1407,8 +1406,7 @@ func runCommand(name string, arg ...string) (string, error) { } func generateBlock() error { - _, err := runCommand("nigiri", "rpc", "--generate", "1") - return err + return mineBlocks(1) } var ErrAlreadySetup = errors.New("already setup") @@ -1518,8 +1516,7 @@ func setupServerWalletAndCLI() error { const numberOfFaucet = 15 // must cover the liquidity needed for all tests for i := 0; i < numberOfFaucet; i++ { - _, err = runCommand("nigiri", "faucet", addr.Address) - if err != nil { + if _, err = onchainFaucet(addr.Address, ""); err != nil { return fmt.Errorf("failed to fund wallet: %s", err) } } @@ -1528,7 +1525,7 @@ func setupServerWalletAndCLI() error { if _, err := runArkCommand( "init", "--server-url", "localhost:7070", "--password", password, - "--explorer", "http://chopsticks:3000", + "--explorer", "http://mempool_web/api", ); err != nil { return fmt.Errorf("error initializing ark config: %s", err) } @@ -1558,6 +1555,52 @@ func runArkCommand(arg ...string) (string, error) { return runDockerExec("arkd", args...) } +// bitcoinCliArgs is the bitcoin-cli prefix used to drive the regtest Bitcoin +// Core node inside the `bitcoin` container of the arkade-regtest stack. +var bitcoinCliArgs = []string{ + "exec", "bitcoin", + "bitcoin-cli", "-regtest", "-rpcuser=admin1", "-rpcpassword=123", +} + +// bitcoinCli runs `bitcoin-cli ` inside the `bitcoin` container and +// returns the trimmed stdout. It replaces the old `nigiri rpc ` +// passthrough. +func bitcoinCli(arg ...string) (string, error) { + args := append(append([]string{}, bitcoinCliArgs...), arg...) + out, err := runCommand("docker", args...) + if err != nil { + return "", err + } + return strings.TrimSpace(out), nil +} + +// mineBlocks mines n blocks to the node wallet (bitcoin-cli -generate n), +// replacing the old `nigiri rpc -generate n`. +func mineBlocks(n int) error { + _, err := bitcoinCli("-generate", strconv.Itoa(n)) + return err +} + +// onchainFaucet sends amountBtc to address from the Bitcoin Core node wallet +// and mines one block to confirm it, then returns the funding txid. It replaces +// the old `nigiri faucet
` (nigiri auto-mined; the +// arkade-regtest stack does not, so we mine 1 block here to preserve the +// confirm-on-faucet behavior). Defaults to 1 BTC when amountBtc is empty, +// matching nigiri's default faucet amount. +func onchainFaucet(address, amountBtc string) (string, error) { + if amountBtc == "" { + amountBtc = "1" + } + txid, err := bitcoinCli("sendtoaddress", address, amountBtc) + if err != nil { + return "", err + } + if err := mineBlocks(1); err != nil { + return "", err + } + return strings.TrimSpace(txid), nil +} + func runDockerExec(container string, arg ...string) (string, error) { args := append([]string{"exec", "-t", container}, arg...) out, err := runCommand("docker", args...) diff --git a/test/utils_test.go b/test/utils_test.go index 535945c..7109c41 100644 --- a/test/utils_test.go +++ b/test/utils_test.go @@ -481,7 +481,7 @@ func fundAndSettleAlice(t *testing.T, ctx context.Context, alice arksdk.ArkClien amountBtc := strings.TrimSuffix(btcutil.Amount(amount).Format(btcutil.AmountBTC), " BTC") - _, err = runCommand("nigiri", "faucet", boardingAddress, amountBtc) + _, err = onchainFaucet(boardingAddress, amountBtc) require.NoError(t, err) time.Sleep(5 * time.Second) @@ -603,7 +603,7 @@ func submitWithArkd( ) { t.Helper() - explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000", arklib.BitcoinRegTest) + explorerSvc, err := mempoolexplorer.NewExplorer("http://localhost:3000/api", arklib.BitcoinRegTest) require.NoError(t, err) encodedTx, err := candidateTx.B64Encode() From 10b30e69de48d3de43460b7baa2842f14b6503fa Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Wed, 3 Jun 2026 11:33:19 +0200 Subject: [PATCH 2/4] CI: clone arkade-regtest denigiri-regtest branch (regtest.mjs) The base-stack step cloned master, which predates regtest.mjs (#27 unmerged), so CI failed with 'Cannot find module regtest.mjs'. Track the denigiri-regtest branch until #27 merges, then switch back to master. --- .github/workflows/test.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 93d53da..4df8ccf 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -35,7 +35,9 @@ jobs: - name: Start regtest base stack (Bitcoin Core + Fulcrum + mempool) run: | - git clone --branch master https://github.com/ArkLabsHQ/arkade-regtest.git regtest + # Temporary: track the unmerged #27 branch so regtest.mjs exists. + # Switch back to master once ArkLabsHQ/arkade-regtest#27 merges. + git clone --branch denigiri-regtest https://github.com/ArkLabsHQ/arkade-regtest.git regtest REGTEST_PROFILES=base node regtest/regtest.mjs start - name: Run regtest environment From 32505a1a6217fea8f9e113cc62d6744b842356f5 Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Wed, 3 Jun 2026 12:39:27 +0200 Subject: [PATCH 3/4] Rename emulator's nbxplorer to avoid base-stack collision On the shared arkade-regtest network, this repo's own `nbxplorer` container/port (32838) collided with the base stack's nbxplorer ('container name /nbxplorer is already in use'). Rename to `emulator-nbxplorer`, drop its host port (only arkd-wallet uses it in-network), and update arkd-wallet's URL/depends_on. --- docker-compose.regtest.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docker-compose.regtest.yml b/docker-compose.regtest.yml index 0d27c49..5cb1554 100644 --- a/docker-compose.regtest.yml +++ b/docker-compose.regtest.yml @@ -34,11 +34,12 @@ services: interval: 2s timeout: 2s retries: 30 - nbxplorer: + # Renamed from `nbxplorer` (+ host port dropped) to avoid colliding with the + # arkade-regtest base stack's own `nbxplorer` container/port on the shared + # network. Only arkd-wallet talks to it, in-network. + emulator-nbxplorer: restart: unless-stopped - container_name: nbxplorer - ports: - - 32838:32838 + container_name: emulator-nbxplorer image: nicolasdorier/nbxplorer:2.5.30 environment: - NBXPLORER_NETWORK=regtest @@ -66,12 +67,12 @@ services: image: ghcr.io/arkade-os/arkd-wallet:v0.9.3 container_name: arkd-wallet depends_on: - - nbxplorer + - emulator-nbxplorer ports: - "6060:6060" environment: - ARKD_WALLET_LOG_LEVEL=5 - - ARKD_WALLET_NBXPLORER_URL=http://nbxplorer:32838 + - ARKD_WALLET_NBXPLORER_URL=http://emulator-nbxplorer:32838 - ARKD_WALLET_DATADIR=./data/regtest - ARKD_WALLET_NETWORK=regtest - ARKD_WALLET_SIGNER_KEY=afcd3fa10f82a05fddc9574fdb13b3991b568e89cc39a72ba4401df8abef35f0 From 2d03e9341d4526f789008b6c3fed94e7942ea097 Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Wed, 3 Jun 2026 14:47:08 +0200 Subject: [PATCH 4/4] Bump arkd stack to base versions (arkd v0.9.6, nbxplorer 2.6.7) Old nbxplorer 2.5.30 crash-loops against the base stack's Bitcoin Core 31 (indexer dies -> arkd-wallet can't init -> arkd fatal: failed to connect to wallet). Align with arkade-regtest's working base (arkd/arkd-wallet v0.9.6, nbxplorer 2.6.7). --- docker-compose.regtest.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.regtest.yml b/docker-compose.regtest.yml index 5cb1554..ba710b1 100644 --- a/docker-compose.regtest.yml +++ b/docker-compose.regtest.yml @@ -40,7 +40,7 @@ services: emulator-nbxplorer: restart: unless-stopped container_name: emulator-nbxplorer - image: nicolasdorier/nbxplorer:2.5.30 + image: nicolasdorier/nbxplorer:2.6.7 environment: - NBXPLORER_NETWORK=regtest - NBXPLORER_CHAINS=btc @@ -64,7 +64,7 @@ services: arkd-wallet: restart: unless-stopped - image: ghcr.io/arkade-os/arkd-wallet:v0.9.3 + image: ghcr.io/arkade-os/arkd-wallet:v0.9.6 container_name: arkd-wallet depends_on: - emulator-nbxplorer @@ -81,7 +81,7 @@ services: target: /app/data arkd: build: - context: https://github.com/arkade-os/arkd.git#v0.9.3 + context: https://github.com/arkade-os/arkd.git#v0.9.6 dockerfile: Dockerfile container_name: arkd restart: unless-stopped