Cross-chain swaps and finality proofs
Arrekta connects to other chains without a custodial bridge:
- atomic swaps: both legs lock to the same SHA-256 digest;
- finality proofs: a transaction's settlement can be checked against the checkpoint signer group alone, with no node and no relayer to trust.
Policy and rationale: Interoperability. Wire formats: protocol §4.2 (policy op 9) and §9.9.
1. Prove a transaction is final
Every node serves GET /v1/txs/{txid}/proof once a signed checkpoint covers the transaction's
block (409 tx-not-final before that). Verify the proof yourself:
import { createClient, getFinalityProof, verifyFinalityProof, networkSignerSet } from 'arrekta-sdk'
const client = createClient({ url: 'http://127.0.0.1:28332' })
// fetches and verifies locally against the genesis checkpoint group
const { finality, hex } = await getFinalityProof(client, { txid, network: 'regtest' })
console.log(finality.height, finality.checkpointHeight)
// later, anywhere (no node): only the trusted signer set is needed
verifyFinalityProof(hex, networkSignerSet('regtest')!, 'regtest')from arrekta_sdk import Client, get_finality_proof, verify_finality_proof
p = get_finality_proof(Client("http://127.0.0.1:28332"), txid)
f = verify_finality_proof(p["hex"], None, "regtest") # None: the network's genesis group
print(f.height, f.checkpoint_height)A proof carries the transaction, its merkle branch, the headers up to the checkpointed block,
and every signer-group hand-over since genesis. Verification fails with proof-bad-merkle,
proof-broken-headers, proof-bad-handover, proof-checkpoint-mismatch or proof-not-final.
2. Swap ARRK for BTC
Alice has ARRK and wants BTC; Bob has BTC. The party holding the secret locks first, with the later refund time.
import { newSwapSecret, arrkSwapPolicy, policyLock, encodeAddress,
btcHtlcScript, p2wshAddress, findSwapPreimage } from 'arrekta-sdk'
// Alice
const { preimage, hash } = newSwapSecret() // keep `preimage`, send `hash` to Bob
const lock = policyLock(arrkSwapPolicy({ receiver: bobKey, refund: aliceKey, hash, timeoutHeight: tArrk }))
// …pay ARRK to encodeAddress(lock, 'mainnet')
// Bob, after checking Alice's output is final (section 1)
const script = btcHtlcScript({ hash, claimPubkey: aliceBtcPubkey, refundPubkey: bobBtcPubkey, locktime: tBtc })
const btcAddress = p2wshAddress(script, 'mainnet') // fund it from a Bitcoin wallet
// Alice claims the BTC (witness: btcClaimWitness), revealing `preimage`.
// Bob watches that witness and claims the ARRK before tArrk:
const secret = findSwapPreimage(aliceBtcWitness, hash)The Python SDK has the same helpers in arrekta_sdk.swap (new_swap_secret, arrk_swap_policy,
btc_htlc_script, p2wsh_address, btc_claim_witness, btc_refund_witness,
find_swap_preimage).
Swapping with Ethereum. The Arrekta leg is the same arrkSwapPolicy. The Ethereum leg is
the ArrektaHTLC contract (contracts/src/ArrektaHTLC.sol), which holds ETH or any ERC-20 under the
same SHA-256 hash:
import { ETH_HTLC_ABI, ethHtlcSwapId } from 'arrekta-sdk'
// with viem: lock(recipient, token (0x0 = ETH), amount, hash, deadline)
await wallet.writeContract({ address: htlc, abi: ETH_HTLC_ABI, functionName: 'lock',
args: [bob, zeroAddress, amount, `0x${toHex(hash)}`, BigInt(deadline)], value: amount })
// the counterparty can compute the id in advance and watch for it
const id = ethHtlcSwapId({ chainId: 1, contract: htlc, sender: alice, recipient: bob, amount, hash, deadline })
// claim(id, preimage) emits Claimed(id, preimage): the other side reads the secret from the eventThe contract has no owner and no fees. It refuses fee-on-transfer tokens, and its claim and refund windows don't overlap. It has not been audited yet: don't lock real funds before it is.
Before you swap:
tBtcmust expire well beforetArrk, with hours of margin for confirmations and downtime;- wait for the counterparty's lock to be final before locking yours;
- keep a watcher running until both legs settle, because a swap does not force the other side to finish;
- the Bitcoin script pins the preimage to 32 bytes (
OP_SIZE 32), matching Arrekta's rule. Do not use a Bitcoin HTLC without that check.