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:
- 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.
-
Anchor Escrow Program: Manages non-custodial token vaults via PDAs and enforces a strict finite-state machine (
INITIATEDβLOCKEDβATTESTEDβRELEASED/REFUNDED). - 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:
- The program transfers tokens (native SOL, SPL USDC, or PYUSD) into
escrow_vault. - A deadline timestamp is set. If the buyer never sends fiat, the LP can call
refund_escrowafter expiration. - When the bank transaction is verified off-chain, the attestor invokes
submit_zktls_attestation. - 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:
- When a buyer completes a payment (via UPI, Venmo, or SEPA), the bank sends a TLS-encrypted HTTP response.
- An MPC attestor participates in key-splitting with the TLS session, verifying the authenticator MAC and response payload.
- 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.
- The transaction status is
- 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
- π Live Web Application: https://beanstick.vercel.app/
- π» GitHub Repository: https://github.com/ayushkumar2601/sol_bean
- π½οΈ Video Walkthrough: https://youtu.be/K4bAbqF7MX4
- π Technical Documentation: Architecture Docs
π‘ What We Learned
-
Anchor 0.30.1 Interface Accounts: Using
InterfaceAccount<'info, TokenAccount>andTokenInterfaceallows 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!
Top comments (0)