Quickstart (5 minutes)
Get your first PayPerCall request working on testnet—either with the dashboard (no code) or with a minimal viem/Wagmi snippet. This page is intentionally short and practical; deeper explanations live elsewhere.
⚠️ Sylan is under active development. Only trust contract/wallet addresses published on Architecture → Addresses & ABIs and announcements on official channels.
What you’ll do
- Connect a wallet on testnet
- Approve SYL spending for the Escrow contract (ERC‑20 allowance)
- Lock funds for a single API call (
APIEscrow.lockForCall) - Wait for consensus → funds settle automatically (success or failure)
Prerequisites
- Node.js 18+, pnpm (for local dev)
- Wallet (Rabby / MetaMask) funded with testnet gas
- SYL test tokens (obtained per Deploy → Testnet)
- Contract addresses from Architecture → Addresses & ABIs
Option A — Dashboard (no code)
- Open the dashboard and connect your wallet.
- From Marketplace, pick an API listing (pricing: PayPerCall or Subscription).
- Click Approve SYL and confirm in wallet (sets ERC‑20 allowance for Escrow).
- Click Request to lock funds. The app computes a
requestHashfrom your inputs and callsAPIEscrow.lockForCall(apiId, requestHash, expiresAtMs). - Watch the status: Pending → Finalized/Failed. On success, a receipt is shown and the escrow auto‑settles.
⏱️
expiresAtMsis a Unix timestamp in milliseconds (uint64) beyond current time (e.g., now + 2 minutes).
Option B — Minimal viem/Wagmi example (code)
The snippet below shows Approve → Lock. Replace addresses with the ones listed under Architecture → Addresses & ABIs.
// app/example/ApproveAndLock.tsx
'use client'
import * as React from 'react'
import { erc20Abi, keccak256, toHex } from 'viem'
import type { Address } from 'viem'
import { useAccount, useWriteContract } from 'wagmi'
// Minimal ABI for APIEscrow.lockForCall
const apiEscrowAbi = [
{
type: 'function',
name: 'lockForCall',
stateMutability: 'nonpayable',
inputs: [
{ name: 'apiId', type: 'bytes32' },
{ name: 'requestHash', type: 'bytes32' },
{ name: 'expiresAtMs', type: 'uint64' },
],
outputs: [],
},
] as const
// Get these from Architecture → Addresses & ABIs
const SYL_ADDRESS: Address = '0xCF922Aa372c087006cd2739689450bE4cc226bB7' // Polygon Amoy
const APIESCROW_ADDRESS: Address = '0xfd685eFeeB6E69358Cf87c9c5Bf41E56154461B1' // Polygon Amoy
export default function ApproveAndLock() {
const { address } = useAccount()
const { writeContractAsync: write } = useWriteContract()
const onApprove = async () => {
// Approve 10 SYL to Escrow (adjust decimals as needed)
await write({
abi: erc20Abi,
address: SYL_ADDRESS,
functionName: 'approve',
args: [APIESCROW_ADDRESS, 10n * 10n ** 18n],
})
}
const onLock = async () => {
// Example payload → requestHash
const payload = { path: '/v1/price', query: { symbol: 'BTC' } }
const requestHash = keccak256(toHex(JSON.stringify(payload)))
// bytes32 apiId for the selected listing (hex string, 0x…32 bytes)
const apiId =
'0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
// Expire after 2 minutes
const expiresAtMs = BigInt(Date.now() + 120_000)
await write({
abi: apiEscrowAbi,
address: APIESCROW_ADDRESS,
functionName: 'lockForCall',
args: [apiId as `0x${string}`, requestHash, expiresAtMs],
})
}
return (
<div className="space-y-3">
<div className="text-sm opacity-80">Connected: {address ?? '—'}</div>
<button onClick={onApprove} className="rounded-md border px-3 py-1.5">Approve SYL</button>
<button onClick={onLock} className="rounded-md border px-3 py-1.5">Lock for Call</button>
</div>
)
}💡 Where do I get
apiId? From the marketplace UI or by reading the listing in AccessRegistry (e.g.,descriptorOf(apiId)and plan metadata). This page keeps code minimal—see Contracts → Access Registry for details.
Verify settlement (optional)
You can listen to settlement events with Wagmi. (Event names and signatures are documented under Architecture → Events.)
import { useWatchContractEvent } from 'wagmi'
useWatchContractEvent({
address: APIESCROW_ADDRESS,
abi: [
{
type: 'event',
name: 'Settled',
inputs: [
{ name: 'apiId', type: 'bytes32', indexed: true },
{ name: 'requestHash', type: 'bytes32', indexed: true },
{ name: 'success', type: 'bool', indexed: false },
],
},
] as const,
eventName: 'Settled',
onLogs(logs) {
console.log('Escrow settled:', logs)
},
})Troubleshooting
- Allowance insufficient → Call Approve first or increase amount.
- Wrong network → Switch wallet to the documented testnet.
- Bad
apiId→ Ensure it’s a 32‑byte hex string and corresponds to an active listing. - Expired request →
expiresAtMsmust be in the future; clock skew can matter.
Next steps
- Learn the Request Lifecycle
- Get addresses/ABIs in Addresses & ABIs
- Explore escrow & consensus internals in Contracts and Architecture sections