pay with an invoice, or receive
with an amount.
When you pay an invoice, your bitcoin waits in an Arkade contract, called the
lockup. The solver can claim the lockup only after it pays the invoice. If it
never pays, the bitcoin comes back to you.
Setup
Install the SDK, the swap client, andnostr-tools, which the client uses to
reach the solver:
Wallet. To create one, see
Create Your Wallet.
During the developer preview, one solver serves Lightning on mainnet. Its card
lists what it trades, its limits, and how to reach it. The client finds most
solvers in a public registry, but the registry does not list this one yet. Save
its card as beta-solver.card.json next to your code, and pin it with
discovery.localCards:
pay and receive throw UnsupportedRoute.
beta-solver.card.json
beta-solver.card.json
Pay an Invoice
Pass the BOLT11 invoice topay, with the most you agree to pay in fees:
pay gets a quote from the solver, checks it, and funds the lockup. The
recipient gets exactly the invoice amount. You lock a little more, and the
difference is the solver’s fee. maxFee caps that fee, in BTC.
The payment ends with one of two outcomes:
paid: the solver paid the invoice and claimed the lockup. To claim, the solver needs the invoice’s preimage, which it gets only by paying the invoice.refunded: the solver never paid, and your bitcoin came back. See Refund a Stalled Send.
pay also accepts an Arkade address. That is a plain wallet payment, not a
swap, so pay returns { kind: 'payment', txid }. The snippet checks
result.kind for this reason.
Catch Errors Before Money Moves
pay throws these errors before it funds anything:
AmbiguousDestination: the invoice expired, is for another network, or has no amount. The client contacted no solver.AmountMismatch: you passedamountwith an invoice that sets one. Leaveamountout, even when the numbers match.SwapRefusal: the solver declined, for example because the amount is outside its limits. The error carries the reason. Show it, or ask again.MaxFeeExceeded: the quoted fee is more thanmaxFee.QuoteVerificationFailed: the quote failed a check, such as an unsafe refund window or a lockup address that differs from the one the client derives.InsufficientFunds: the wallet holds too little to fund the lockup.
Refund a Stalled Send
If the solver never pays the invoice, your bitcoin stays in the lockup until the quote’srefundLocktime passes. On the developer-preview solver, that is about
a week after you pay. The client then submits the refund itself, and the
outcome is refunded. If the client is not running at that time, it submits
the refund when it next starts.
If the outcome is needs_recovery instead, the swap needs your attention. See
Recover a Swept Swap.
Receive a Payment
Passreceive the number of sats you want in your Arkade wallet. It returns a
Lightning invoice to show the payer:
amount. The difference is
the solver’s fee.
receive returns only after it saves the swap, so this client can always
claim the invoice you show. Do not show an invoice from quote alone: its
claim secret is not saved yet.
The invoice is a hold invoice. When the payer pays, the solver funds a lockup
in Arkade with the sats you receive. Your client claims the lockup, which
reveals the preimage the solver needs to settle the Lightning payment. Follow the swap until it reaches claimed or lapsed:
claimed: the sats are in your Arkade wallet.lapsed: no payment reached your Arkade wallet. Show it as an expired request.
refunded. None of your money left your wallet, so
nothing comes back.
LNURL and Lightning Addresses
To accept payments to a Lightning address (name@yourdomain) or an LNURL, your
server answers a callback from the payer’s wallet with an invoice. The callback
gives amount in millisatoshis (LUD-06): what the payer sends over Lightning.
The invoice you return must ask for exactly that amount, or the payer’s
wallet refuses it.
Use quote and accept here instead of receive, because receive makes an
invoice for more than its amount. Quote with amountOn: 'give', which fixes
the amount the payer sends. Then call accept before you return the invoice as
pr, so the client saves the claim secret before anyone sees the invoice:
accept does not check a fee ceiling: only pay,
receive, and exchange enforce maxFee. Compare quote.fee.amount with
your limit before you call accept.
To receive while the wallet is offline, run
lnurl-server. With
OFFLINE_SELF_CLAIM on, it claims each lockup itself, so the payment reaches
the Arkade wallet while the wallet is closed. It can also give the wallet a
Lightning address. See
Lightning Services.
Want to learn more?
Swap Client
Storage, errors, outcomes, and recovery for every route.
Markets and Quotes
The model underneath: how quotes are requested, priced, and committed.
Corridor Swaps
The underlying contract: paired HTLCs, timeouts, and recovery.