Allow ALP–XEC AMM pairs without wrapping XEC. Config accepts the XEC
sentinel; atoms are sats (2 decimals). Exact-size XEC inventory lives on
BIP44 account 2 (sellerXec) so postage fuel on seller stays stamps-only.
Quotes, parse/validate, and settle handle both directions: buy ALP with
native XEC, or sell ALP for XEC by stitching sellerXec inputs onto the
postage tx before addFuelAndSign(seller). Spec is now v2; HTTP stays
/api/v1.
Details
- Reviewers
Fabien - Group Reviewers
Restricted Project
- cd apps/alp-dex && pnpm test
- Copy config.sample.json to config.json, set an ALP–XEC pair, start alp-dex, and confirm GET /api/v1/status lists sellerXecAddress and the pair as tokenId/XEC
- GET /api/v1/swap/XEC/<tokenId>/quote/<qty> and /api/v1/swap/<tokenId>/XEC/quote/<qty> return templates with native sat XEC legs
Diff Detail
- Repository
- rABC Bitcoin ABC
- Branch
- alp-dex-xec-pairs
- Lint
Lint Passed - Unit
No Test Coverage - Build Status
Buildable 38025 Build 75468: Build Diff ai-review · alp-dex-tests Build 75467: arc lint + arc unit
Event Timeline
Build Bitcoin ABC Diffs / Diff Testing (ai-review) passed.
CodeRabbit Review
Diff : committed changes only
Compare : HEAD → master
Directory : work
────────────────────────────────────────
(\(\
(• .•) Hello, it's me. I was wondering if after all these reviews you'd like to meet...to celebrate bug-free code.
────────────────────────────────────────────────────────────────────────
major [Stability & Availability]
→ ]8;;vscode://file//work/apps/alp-dex/src/inventory/maintain.ts:283apps/alp-dex/src/inventory/maintain.ts:283-288]8;;
Reserve slush sats for postage before funding XEC inventory.
remaining is derived from the full slush spendable balance. The loop
then funds XEC inventory batches until remaining reaches 0 or the batch
cap is hit. This drains the slush pool. Step 4 computes
postageFundBatchCount(postage.length, spendableSats) from what is left,
so postage funding can become 0 stamps and seller postage starves. The
comment on Line 267-268 states the opposite intent.
Subtract a postage reserve from the sat total before converting to XEC
inventory units.
♻️ Proposed fix
- let remaining = inventoryUnitCount(
- slush
- .spendableSatsOnlyUtxos()
- .reduce((sum, utxo) => sum + utxo.sats, 0n),
- xecToken.utxoAtoms,
- );
+ const slushSatsAvailableForXec = (): bigint => {
+ const total = slush
+ .spendableSatsOnlyUtxos()
+ .reduce((sum, utxo) => sum + utxo.sats, 0n);
+ const reserve = POSTAGE_RESERVE_SATS;
+ return total > reserve ? total - reserve : 0n;
+ };
+ let remaining = inventoryUnitCount(
+ slushSatsAvailableForXec(),
+ xecToken.utxoAtoms,
+ );
Apply the same helper at Line 303-308 for nextRemaining.────────────────────────────────────────────────────────────────────────
minor [Security & Privacy]
→ ]8;;vscode://file//work/apps/alp-dex/src/settle/parseSwap.ts:522apps/alp-dex/src/settle/parseSwap.ts:522-530]8;;
Reject zero-sat non-token outputs on the ALP–XEC path.
An output with no ALP amount and sats === 0n is skipped here, so it
never enters mids. validatePartiallySignedTx then never sees it, and
the rest.length > 2 limits do not count it. The ALP–ALP path rejects
this case explicitly (Line 272-276).
A taker can therefore append arbitrary zero-sat outputs. The node pays for
the added transaction size through postage fuel.
🛡️ Proposed fix
if (out.sats > 0n) {
mids.push({
idx: outIdx,
script: out.script.toHex(),
sats: out.sats,
tokenId: XEC_ASSET_ID,
atoms: out.sats,
});
+ continue;
}
+ throw new ValidationError(
+ `Invalid swap: non-token output ${outIdx} must have sats`,
+ );────────────────────────────────────────
Review complete
2 findings ✔
Major 1
Minor 1
32 files reviewed:
- apps/alp-dex/README.md
- apps/alp-dex/SPEC.md
- apps/alp-dex/config.sample.json
- apps/alp-dex/index.ts
- apps/alp-dex/scripts/printHdAddresses.ts
- apps/alp-dex/scripts/summarizeWallets.ts
- apps/alp-dex/src/app.ts
- apps/alp-dex/src/config/tradedConfig.ts
- apps/alp-dex/src/config/tradedPairs.ts
- apps/alp-dex/src/constants.ts
... and 22 more files
────────────────────────────────────────
Print all AI prompts: coderabbit review --show-prompts
This presents significant complexity (maintaining another whole specially-sized address with UTXO filter expectations). XECX is effectively "the same thing."
Can revisit this depending on demand but at the moment there is still only one server.