Case Studies
By AnchorFactory ·
Three production anchors dissected: what they built, how they built it, and what they learned.
Alpaca DEX — AMM-Powered FX Anchor
Type: FX Anchor Endpoint: api.alpacadex.com Live since: 2025
Alpaca DEX runs its own FX anchor that routes swap requests through its automated market maker (AMM) pools. Unlike the official Keeta FX anchor which uses external price feeds, Alpaca prices everything against its own on-chain liquidity.
Architecture
User request → /estimate → lookup pool in Firestore → compute AMM quote
→ /quote → SignData-signed quote with expiry
→ /create-exchange → VerifySignedData → build swap blocks → publishKey decisions:
Firestore as pool registry — pools are created via Cloud Functions and stored in Firestore. The FX anchor queries Firestore to find matching pools, not the on-chain resolver.
BigInt precision throughout — all token math uses BigInt with 1e18 precision via
bignumber.js. Never floating-point.Dual environment — every endpoint has a production and test variant (
/quotevs/test-quote). Test mode uses separate Firestore collections (pools_test) and hardcoded seeds.
Technical Challenges
Block chaining in batch trades — when processing multiple trades in a single batch, pool account blocks must chain correctly. Each block's
previousmust reference the prior block's hash, not the original head. Getting this wrong causesLEDGER_SUCCESSOR_VOTE_EXISTS.
Fee block computation — every publish requires a voting fee block computed by the SDK. The fee block callback must be passed to
publish()and is computed from the full staple. Forgetting this causes silent publish failures.
Slippage in AMM quotes — quotes are computed at request time but executed later. The pool state may change between quote and execution. Solution: client submits
minAmountOutin their RECEIVE operation; server rejects if actual output is below that threshold.
Lessons Learned
Keep quote expiry short (60 seconds) to minimize stale-quote risk
Always verify
SignDatasignatures before executing — replay attacks are trivial otherwiseUse a lock mechanism for concurrent trade processing (Firestore transactions + distributed locks)
Bivo — Licensed Fiat Banking Anchor
Type: Asset Movement Anchor (Banking) Endpoint: bivo-anchor.keeta.com NMLS: #2572288 Coverage: 30+ countries
Bivo is a licensed money transmitter that bridges on-chain fiat tokens ($USD, $EUR, $GBP, etc.) with real bank accounts via ACH, WIRE, SEPA, INTERAC, PIX, UPI, and FPS rails.
Architecture
User → shareKYCAttributes() → Bivo verifies on-chain certificate
→ simulateTransfer() → fee estimate + compliance check
→ initiateTransfer() → creates pending transfer
→ executeTransfer() → triggers bank railKey decisions:
On-chain fiat tokens — each supported currency has its own Keeta token ($USD, $EUR, etc.) with 2 decimal places. These are NOT stablecoins — they're tokenized fiat representations issued by the Bivo anchor.
KYC via certificate sharing — instead of building its own KYC flow, Bivo accepts Keeta's on-chain KYC certificates. Users verify once (with Footprint or another KYC anchor) and share the same certificate with Bivo.
Shorthand asset IDs — Bivo uses
$USDC,$USD,$EURinstead of fullkeeta_a...token addresses. This is a documented quirk that catches every developer.
Technical Challenges
Multi-hop conversions — converting crypto to non-USD fiat requires multiple steps: crypto → USDC (via ChangeNow) → $USD (via Bivo) → target fiat (via Bivo again). Each hop is a separate anchor call.
KYC attribute extraction — the
SharableCertificateAttributesflow requires: create sharable → grant access to transport account → export as PEM → send to anchor → anchor imports with transport key → read proven values. Missing any step produces cryptic errors.
Persistent forwarding addresses — Bivo supports
createPersistentForwardingfor recurring deposits. These are permanent Keeta addresses that auto-forward to the user's bank account.
Lessons Learned
Document any non-standard conventions (like shorthand asset IDs) prominently
Multi-hop flows need clear error handling at each stage — a failure at hop 2 of 3 is hard to debug
Banking rails have different settlement times — ACH (1-3 days), WIRE (same day), SEPA (1 day) — surface this to users
Keeta EVM Anchor — Cross-Chain Bridge
Type: Asset Movement Anchor (Bridge) Endpoint: evm-anchor.keeta.com/api Routes: Base (EVM) ↔ Keeta
The EVM anchor bridges tokens between the Base blockchain (an Ethereum L2) and Keeta. It supports KTA, USDC, EURC, and cbBTC with persistent forwarding addresses for seamless deposits.
Architecture
Base → Keeta: User deposits to forwarding address on Base → anchor detects → mints/sends on Keeta
Keeta → Base: User sends to anchor on Keeta → anchor detects → sends on BaseKey decisions:
Persistent forwarding — each user gets a permanent deposit address on Base. Any tokens sent there are automatically forwarded to their Keeta wallet. No need to initiate a transfer each time.
Multi-chain monitoring — the anchor watches both chains simultaneously for incoming deposits and processes them in order.
Token mapping — the same token (e.g., USDC) has different addresses on Base vs Keeta. The anchor maintains an internal mapping table.
Technical Challenges
Finality differences — Base has probabilistic finality (requires confirmation blocks), while Keeta has instant finality. The anchor must wait for sufficient Base confirmations before crediting on Keeta.
Token decimal mismatches — USDC is 6 decimals on both chains, but KTA is 18 on Keeta mainnet. Decimal conversion must be exact — any rounding error means lost funds.
Reorg handling — Base block reorgs can reverse a deposit that was already credited on Keeta. The anchor needs a confirmation threshold and a dispute resolution mechanism.
Lessons Learned
Bridge anchors are the most complex anchor type — start with a simpler anchor first
Always wait for sufficient confirmations on probabilistic-finality chains
Maintain detailed audit logs of every cross-chain transfer for reconciliation
Common Patterns Across All Case Studies
Every production anchor shares these patterns:
Pattern | Why |
|---|---|
SignData authentication | No API keys needed — wallet signature is the identity |
Dual environment | Test and production variants with separate data stores |
Idempotent operations | Network failures shouldn't cause double-execution |
Comprehensive logging | Cross-chain and async operations need detailed audit trails |
Graceful degradation | If the anchor is down, wallet apps should show clear error states |
Build Your Own
Ready to build? Start with the simplest anchor type and work up:
Build an FX Anchor — the foundation pattern
Wallet Signatures — authentication for any anchor
Publishing Metadata — make your anchor discoverable
Anchor Business Models — how to monetize