CA · pending

[ Arc mainnet · chain 5042 ]

One integration.
Every supported stock.

Two surfaces. The hub on Arc is the write side: a protocol places orders exactly like a user does, and gets STOCK.afol it can pool, lend against or wrap. The HTTP API is the read side: reserves, quotes, orders and the stock layer as JSON, no RPC needed. The SDK wraps both.

SDK

@arcfolio/sdk
import { createArcfolio } from "@arcfolio/sdk";
import { createWalletClient, custom } from "viem";
const folio = createArcfolio({ apiUrl: "https://jellybelly.fun/api/v1" });
// reads: no wallet, no RPC
const reserves = await folio.reserves(); // reserve vs supply, every stock
const quote = await folio.quote({ stock: "NVDA", side: "buy", amount: 1000 });
// writes: a viem wallet on Arc (USDC is the native asset, nothing to approve)
const wallet = createWalletClient({ transport: custom(window.ethereum) });
const id = await folio.requestBuy({ stock: "NVDA", usdc: 1000 }, wallet);
const order = await folio.waitForOrder(id); // filled in a few seconds
console.log(order.amountOut, order.amountOutUnit); // "4.61…", "NVDA.afol"

The package lives in this repo at packages/sdk and is typed end to end with viem. Every quote response also carries the raw call (contract, function, args, value), so any language can place the same order.

The hub, directly

viem · writeContract
// ArcfolioHub on Arc: 0xHUB…
await wallet.writeContract({
address: "0xHUB…",
abi: arcfolioHubAbi,
functionName: "requestBuy",
args: ["0xNVDA…", parseUnits("4.5", 18)], // NVDA, at least 4.5 NVDA.afol
value: parseEther("1000"), // 1,000 USDC
});
  • requestBuy(address underlying, uint256 minSharesOut) payable

    Deposit USDC (msg.value, 18 dp) for a stock. Returns the order id; the operator fills it.

  • requestSell(address underlying, uint256 sharesIn, uint256 minUsdcOut)

    Escrow STOCK.afol to redeem. USDC arrives when the operator fills it.

  • cancel(uint256 id)

    Yours to call after 30 minutes if an order is still pending. Everything comes back.

  • getOrder(uint256 id) · ordersOf(address) · pendingOrders()

    Read any order, a wallet’s history, or what is in flight.

  • supplyOf(address underlying) · allListings()

    Supply per stock and every STOCK.afol address.

  • previewBuyFee(uint256 usdcIn, address caller)

    The fee a deposit pays, including any integrator fee for caller.

HTTP API

openapi.json · v1.0.0
curl
curl https://jellybelly.fun/api/v1/reserves
curl "https://jellybelly.fun/api/v1/quote?stock=NVDA&side=buy&amount=1000"
curl -X POST https://jellybelly.fun/api/v1/keys -d '{"name":"my protocol"}'

Infrastructure fee

Protocols that route their users through the hub can be registered as integrators. The hub then adds their tier on top of the 0.25% (capped at 1% in total) and keeps the accounting on-chain: integratorFeeBps(address). API keys are metered the same way. Nothing is billed during the MVP.

Full protocol reference in the docs
0101