Building Beanstick: Autonomous Fiat-to-Crypto Settlement on Solana with Anchor PDAs & zkTLS

Moving value between traditional banking (Web2) and decentralized finance (Web3) has long been one of crypto's biggest bottlenecks. Traditional centralized onramps impose 3% to 8% fees, hold customer funds for days, and require users to trust custodial intermediaries.

For the MLH Solana Hackathon 2026, we built Beanstick (BeanSol): an autonomous, non-custodial fiat-to-crypto settlement network designed specifically around Solana's high-speed architecture, sub-second finality, and negligible fees.

Here is an architectural walkthrough of how we engineered Beanstick using Rust, Anchor 0.30.1, autonomous AI LP agents, and zkTLS proofs.

⚡ Why Solana?

On EVM chains, high gas spikes and multi-block confirmation delays make real-time payment settlement impractical. A user at a point-of-sale or online checkout cannot wait 15 minutes for block finality.

Solana solves this natively:

  • ~400ms Block Times: Escrows lock and release in sub-second timeframes, matching the UX of modern fiat rails like UPI or Venmo.
  • Predictable Micro-Fees: Transactions cost less than $0.001, allowing micro-swaps without fee penalties.
  • Composable Program Derived Addresses (PDAs): Enable deterministic, program-owned escrow vaults with zero human intermediaries.

🧠 The Architecture: How It Works End-to-End

┌──────────────────┐ ┌───────────────────────┐ ┌────────────────────┐ │ Buyer (User) │ ───────> │ Autonomous AI Swarm │ <──────> │ Neo4j AuraDB Graph│ │ "100 USD to SOL" │ │ (Reverse Auction) │ │ (Reputation & Trust│ └────────┬─────────┘ └───────────┬───────────┘ └────────────────────┘ │ │ │ ▼ lock_escrow() │ ┌───────────────────────┐ │ │ Solana Anchor Program │ │ │ [PDA Token Vault] │ │ └──────────┬────────────┘ ▼ Fiat Transfer │ ┌──────────────────┐ │ │ Web2 Bank / UPI │ │ └────────┬─────────┘ │ ▼ TLS Response │ ┌──────────────────┐ │ │ zkTLS Attestor │ ─────────────────────┘ │ (MPC ZK-SNARK) │ submit_zktls_attestation() ──> release_escrow() (PDA Vault -> Buyer) └──────────────────┘ 

The protocol coordinates three independent layers:

  1. Agentic Swarm Protocol: Independent Liquidity Provider (LP) AI agents hold dedicated Solana keypairs, monitor order intents, and compete in sub-millisecond automated reverse auctions to offer the lowest spread.
  2. Anchor Escrow Program: Manages non-custodial token vaults via PDAs and enforces a strict finite-state machine (INITIATED → LOCKED → ATTESTED → RELEASED / REFUNDED).
  3. zkTLS Cryptographic Verification: Attestor agents use Multi-Party Computation (MPC) to verify bank receipts without ever seeing or storing user banking credentials, submitting zero-knowledge proofs on-chain.

🛠️ Solana Anchor Implementation: PDA Escrows & Vaults

In our Anchor program (programs/beanstick), token vaults are strictly controlled by Program Derived Addresses. As Prasiddh Naik noted in his dive on Solana PDAs and Kode-n-Rolla discussed on Anchor escrow programs, deriving deterministic seeds is key to avoiding state collisions.

Here is how our escrow account and token vault are canonically derived:

#[derive(Accounts)] #[instruction(order_id: u64)] pub struct LockEscrow<'info> { #[account(mut)] pub lp_authority: Signer<'info>, #[account( init, payer = lp_authority, space = 8 + Escrow::INIT_SPACE, seeds = [b"escrow", order_id.to_le_bytes().as_ref()], bump )] pub escrow: Account<'info, Escrow>, #[account( init, payer = lp_authority, seeds = [b"escrow-vault", escrow.key().as_ref()], bump, token::mint = token_mint, token::authority = escrow_vault, )] pub escrow_vault: InterfaceAccount<'info, TokenAccount>, #[account(mut)] pub lp_token_account: InterfaceAccount<'info, TokenAccount>, pub token_mint: InterfaceAccount<'info, Mint>, pub token_program: Interface<'info, TokenInterface>, pub system_program: Program<'info, System>, } 

When an LP locks liquidity:

  1. The program transfers tokens (native SOL, SPL USDC, or PYUSD) into escrow_vault.
  2. A deadline timestamp is set. If the buyer never sends fiat, the LP can call refund_escrow after expiration.
  3. When the bank transaction is verified off-chain, the attestor invokes submit_zktls_attestation.
  4. The program signs the release using the PDA seeds:
let order_bytes = escrow.order_id.to_le_bytes(); let signer_seeds: &[&[&[u8]]] = &[&[ b"escrow-vault", escrow_key.as_ref(), &[escrow.vault_bump], ]]; token_interface::transfer_checked( CpiContext::new_with_signer( token_program.to_account_info(), TransferChecked { from: escrow_vault.to_account_info(), to: buyer_token_account.to_account_info(), authority: escrow_vault.to_account_info(), mint: token_mint.to_account_info(), }, signer_seeds, ), escrow.amount, token_mint.decimals, )?; 

The buyer receives their tokens in ~400ms—pure on-chain settlement with zero counterparty risk.

🛡️ zkTLS: Bridging Web2 Banking to Web3

The hardest challenge in fiat onramping is proving that a bank transfer actually happened without centralized bank API keys.

Beanstick uses zkTLS:

  1. When a buyer completes a payment (via UPI, Venmo, or SEPA), the bank sends a TLS-encrypted HTTP response.
  2. An MPC attestor participates in key-splitting with the TLS session, verifying the authenticator MAC and response payload.
  3. The attestor produces a concise ZK-SNARK proving:
    • The transaction status is SUCCESS.
    • The recipient matches the winning LP agent's bank account.
    • The reference ID matches the order_id.
  4. The on-chain Anchor program verifies the proof hash and triggers instant vault disbursement.

No passwords, session cookies, or bank accounts are ever broadcast or stored on-chain.

🚀 Live Demo & Links

💡 What We Learned

  • Anchor 0.30.1 Interface Accounts: Using InterfaceAccount<'info, TokenAccount> and TokenInterface allows seamless compatibility across both standard SPL tokens and Token-2022 extensions.
  • Compute Budget Optimization: On Solana, explicitly requesting compute units and priority fees (setComputeUnitPrice) ensures instant inclusion even during high-traffic network periods.
  • Agent Coordination on Solana: Giving autonomous AI agents their own Solana keypairs unlocks a completely new design space for decentralized market-making.

If you are exploring Solana, Anchor PDAs, or zkTLS, check out the repo and let us know what you think in the comments!