Tokens
FURL Token
FURL is FurlPay's ecosystem payment token on Solana: a Token-2022 mint with 6 decimals and a fixed 1,000,000,000 supply. This page is what you need to integrate it correctly — and the disclosures you must not drop when you do.
FURL has no peg, no reserves, and no redemption
Identity
| Method | Path | Description |
|---|---|---|
| MINT | FYatJq71zqvaQNLLtbBy4hQcsV25dMATYfCSVBzV3gY1 | The one and only FURL mint (mainnet-beta) |
| PROGRAM | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb | Token-2022 — NOT the legacy SPL Token program |
| DECIMALS | 6 | Fixed at creation; amounts are base units ×10⁻⁶ |
| SUPPLY | 1,000,000,000 | 1e15 base units; mint authority not yet revoked |
In this repository every FURL constant comes from one module — apps/web/src/lib/token/furl.ts — and a test asserts it agrees with the launch package (packages/furl-token/src/config.ts) and the published metadata mirror. Import from there; never paste the mint address into a second place.
Token-2022, not legacy SPL
This is the single most common integration bug with FURL. The associated-token-account address is derived from the token program id, so deriving with the legacy program yields a different address that no FURL transfer will ever reach — and a balance query against the legacy program returns nothing, which renders as a confident zero.
- Pass
TOKEN_2022_PROGRAM_IDtogetAssociatedTokenAddressSync. - Pass it again to the ATA-creation and
transferCheckedinstruction builders. - When reading balances with
getTokenAccountsByOwner, query both programs (or filter by mint) — seelib/onchain/balances.ts.
Paying in FURL
FURL rides the existing Solana Actions payment path; it is a parameter, not a parallel system. The same builder produces SOL, USDC and FURL transactions.
| Method | Path | Description |
|---|---|---|
| GET | /api/actions/pay/[orderId] | Blink metadata; the FURL button appears only when FURL pricing is configured |
| POST | /api/actions/pay/[orderId]?asset=FURL | Base64 Token-2022 transferChecked transaction to sign |
| GET | /api/token/furl | Identity, allocation model, live authorities, concentration, disclosures |
| GET | /api/token/furl/balance?owner=… | FURL balance for one address; 503 when the chain is unreadable |
Pricing fails closed. FURL has no oracle and no market, so the USD→FURL conversion uses an explicitly configured price (FURL_USD_PRICE). With it unset, the FURL button is not rendered and a ?asset=FURL POST is rejected — the code never invents a rate. SOL still converts via its live oracle; USDC is quoted 1:1.
# FURL checkout is off unless a real, defensible price is configured
FURL_USD_PRICE=
# balance of any address (public chain data, rate-limited)
curl "https://furlpay.com/api/token/furl/balance?owner=<solana address>"
# identity + live authority state + disclosures
curl https://furlpay.com/api/token/furlAmounts and precision
One FURL is 1,000,000 base units. Never hold a FURL amount in a JavaScript number: at 6 decimals, base units exceed Number.MAX_SAFE_INTEGER above roughly 9,007 FURL, so float arithmetic starts losing value inside ordinary amounts.
furlToBaseUnits("12.5")— string/bigint in, bigint out; more than 6 decimal places is rejected, not truncated.baseUnitsToFurl(12500000n)— bigint in, decimal string out. No float in the path.- Compare balances with bigint (
hasSufficientFurl), never withNumber().
Validating the mint
A lookalike token with the same name, symbol and icon costs nothing to create. Base58 is case-sensitive, so compare exactly — never lowercased.
import { assertFurlMint, isFurlMint } from "@/lib/token/furl";
// throws before any transaction is built
assertFurlMint(userSuppliedMint);
// reads are scoped by the server, not by the caller:
// /api/token/furl/balance pins the mint in code, so no query
// parameter can point it at a different token.On-chain, transfers go out as transferChecked, which makes the runtime verify both the mint and the decimals. A wrong-mint or wrong-scale transfer fails on-chain instead of moving the wrong amount.
Current state, honestly
- Supply concentration: 100% of FURL is in a single token account owned by the deployer key. No multisig stands in front of it yet.
- Mint authority: still active. The 1B cap is published intent, not yet runtime-enforced. Revoking is irreversible and has not been done.
- Freeze authority: null — no account can ever be frozen, so holders cannot be censored.
- Liquidity: none. No pool exists, so FURL has no market price and price aggregators have nothing to index.
- Audit: none. No third-party audit or attestation exists.
The live values for the first three are read from the chain by /api/token/furl and rendered on /token, so they stay correct as they change rather than going stale in prose.
Metadata
Name, symbol and URI live on the mint itself via the Token-2022 metadata-pointer and token-metadata extensions — no Metaplex dependency. The URI points at Arweave (via Irys), so FURL's identity resolves even if furlpay.com does not.
curl https://gateway.irys.xyz/4WYcrbavrRd4BA7Ls61czF8z1cjNg6M3xPdzw24HQgFH