Skip to main content
On Solana you trade against the rwa_market program. Per-asset state lives in PDAs keyed by the SPL mint — the mint address is effectively the “token id”, and you derive every account you need from it. Tokens are Token-2022 mints.

Program IDs (same on every cluster)

A program id equals its deploy keypair’s pubkey, so the same id is used on devnet/testnet/mainnet.
RWA mints are Token-2022 with a transfer hook, at 6 decimals. A classic SPL-Token client will fail on them. Use TOKEN_2022_PROGRAM_ID, and resolve the hook’s extra accounts when you transfer — the rwa_accrual program keeps a per-holder clock that makes coupons time-weighted, and a transfer that omits its accounts cannot execute.Mainnet is live. The programs’ upgrade authority is a 2-of-3 Squads v4 multisig (HnvyE4qeeQ81hWniSZzBWgivg1q1ZvLnZx1g2t3fTidV), so no single key can replace program logic.

Per-cluster addresses

Only the RPC endpoint and the payment-token mints differ per cluster.
Which payment mint applies is per-asset — read payout_token from the token’s TokenMeta before trading.

Getting cNGN on Solana

Most assets are naira-denominated and settle in cNGN, so you need cNGN on Solana before you can buy. Third-party services, listed for convenience — GetEquity does not operate them. The Orca pool is a Whirlpool at DdYMJgiucDr2VuTrYceYDDgGsUAtihvAkUdPjFjYm6ZS, holding cNGN as token A and USDC as token B. Fiat on-ramps sell cNGN too, but they settle it on whichever chain that service uses — not necessarily Solana. The issuer keeps a fuller list at cngn.co/merchants.
Check the mint before you swap. “cNGN” is a name, not an identity — anyone can create a token using it, and a swap interface will route you into one on a symbol match. On Solana, cNGN is 3jiqwBQVRC5zRwHyqvnkQurebJ5RNxg3F5fXMwaxgkv8 and nothing else. Paste the mint rather than picking by name or logo.It is Token-2022, not classic SPL — a wallet or client that only speaks SPL Token will not see it. And cNGN on Solana is a different token from cNGN on Base (0x46C85152bFe9f96829aA94755D9f915F9B10EF5F): they are not bridgeable by sending, and a transfer to an address on the wrong chain is lost.

Tradeable RWA tokens (mainnet)

Token-2022 mints, 6 decimals, transfer hook enabled. Read on chain 2026-09-24 — re-check rather than trusting this table, and note that a mint existing does not mean it trades.
is_active lives on the Asset PDA (["asset", mint] under rwa_market), not on the mint or the token metadata. An inactive asset still has a mint, still has holders and still shows a price, so the only reliable check is that field — buys and sells revert without it.
These are mainnet mints and do not exist on devnet. Point your connection at the cluster that matches the mints you are using — a mainnet mint queried on devnet simply reads as a missing account, which is easy to mistake for an empty balance.

Tradeable RWA tokens (devnet)

Only assets with a Solana mint can be traded here. DPRI is currently the only asset live on Solana — the others are EVM-only, so they have no mint on this cluster.

Deriving the accounts you need

Every per-asset account is a PDA of a constant seed + the SPL mint pubkey. round_idx is a little-endian u64, not a string — new BN(idx).toArrayLike(Buffer, "le", 8).

The program-level Config

One per program, not per asset, and seeded only by a constant: It holds that program’s authority (the Squads vault) and operator. You do not pass it to buy/sell, but every account-creating instruction takes it, and it is what makes per-asset admin fields non-forgeable: they are written from Config.authority rather than from whoever calls first. If you build an instruction from an older IDL that has no config account, the program rejects it.