Skip to main content
TraderCodes, the referral program of PitPass, give every Monaco user a unique referral code tied to their wallet. When a referred user trades, the referrer earns a share of the protocol fee from that trade — across a referral chain up to 10 levels deep. The number of levels and their rates can be configured per client application, and a trade pays the levels of the client it was placed through. Rewards land in an app-agnostic rewards bucket and can be moved into any trading balance with a single ledger-only call. Every wallet has a default code derived from its address, and a user can optionally claim a custom (vanity) handle — a human-readable code that is easier to share. Use TraderCodes to capture a referral at signup, display a user’s code for sharing, let users claim a custom handle, and let them check and move their earned rewards.

Surface Map

Concepts

TraderCode. Every wallet has a default code derived from its address, displayed by clients as Monaco - <address>. Codes are globally unique, work across every app on Monaco, and the default is permanent. Calling getMyTraderCode is idempotent — the code row is created on demand, so the endpoint never 404s for a signed-in wallet. Render the response’s display field rather than building the display string yourself; it already reflects a custom handle when one is set. Custom handle. A wallet can claim a custom (vanity) handle to use in place of the wallet-derived default: letter-first, [A-Za-z0-9_], 5–20 characters, stored exactly as entered (casing preserved) but unique case-insensitively. Claim or edit it with setTraderCode, drop it with clearTraderCode (reverting to the default), and preview a handle with the public checkTraderCodeAvailability. getMyTraderCode reports isCustom and the claimed customCode alongside the default code. The referral chain always keys on the wallet, so changing or clearing a handle never affects earned rewards or referral relationships. Referral chain. A referral relationship is recorded once at first signup. The chain is a directed graph: L1 is the direct referrer, L2 is their referrer, L3 is L2’s referrer, and so on. TraderCodes rewards a configured number of levels, at most 10, and each rewarded level earns its own configured rate of the fee generated by the referred user’s trades (see Reward rates). Levels and rates can be configured per client application; a trade pays the levels of the client it was placed through. Reading referral state. Three self-scoped, authenticated reads back the referral UI. getMyReferralPosition() returns your upline — the chain above you, nearest first: L1 (who referred you), L2, and so on, with as many entries as the levels your trades on this client application pay (never more than 10) — plus your direct referrer as referrer ("" when you were not referred; upline is empty then, and also when this client application pays no referral levels), your all-time totalEarned, and recent reward rows (up to the 100 newest; totalEarned stays the complete aggregate) — use it for an “already referred” state and an earnings header. getMyReferralDownline(params?) returns one page of earningsBySource (who pays you, across every reward level, ordered by each source account’s total, largest first), your L1 directReferees roster (including referees who have not traded yet, showing up to the 500 most recent effective referees (after per-wallet dedupe), drawn from a bounded scan so a very large history may yield an incomplete roster — the earnings views stay complete), and a per-level summary. getMyReferralTree() renders your full downline as a tree, one level per call: with no parent it lists your L1 referees; pass one of their wallets as parent to list its referees (L2), and so on down to the deepest level any client application rewards, since a wallet in your downline pays you at the levels of the client it trades through. Your L1 referees are always listed. Each node carries its level, parent, referredAt, refereeCount (expand it when above 0; always 0 at the deepest rewarded level), and totalEarned (what you earned from that wallet’s own trades). Pages hold up to 200 nodes (default 50) with a nextPageToken. Each wallet appears once, under the referrer that earns from it, and any parent that is not you or one of your referees above the deepest rewarded level returns 404. All three identify every other user by wallet address plus a display (their custom handle when claimed), never an internal id, and only ever return your own chain. Paging the downline. earningsBySource is paged: pass pageSize (1–500, default 100) and pageToken (the opaque nextPageToken from the previous response) — as SDK params, or as query parameters on GET /api/v1/pitpass/referrals/me/downline. A call without paging parameters returns only the first page (up to 100 rows), not every row — keep requesting with the returned nextPageToken until it is "". Rows are ordered by each source account’s total; rows of a wallet that traded through several applications are merged within a page at its first part’s position, so a merged row can sit below a smaller one, and that wallet can appear again on a later page. summary always covers every level and source, whatever the page: summary.byLevel lists { level, earned } (raw atomic units) in ascending level order, one entry per level you have earnings at, including levels deeper than TraderCodes rewards today. summary.level1Earned, level2Earned, and level3Earned are deprecated — they cover levels 1–3 only; use byLevel.
Rewards bucket. Earned rewards land in a dedicated per-user rewards bucket that is separate from any application’s trading balance. The bucket is app-agnostic — a referrer earns rewards regardless of which app their referee trades on. To spend rewards, move them into a trading balance via transferRewards. Transfer. The transfer between rewards bucket and trading balance is ledger-only (Monaco operates a single shared vault). No on-chain transaction, no gas. Funds are tradeable immediately after the transfer.

Flow

1. Capture a referral at signup

Pass the referral code in the auth verify body. The code is silently ignored if it is invalid or if the user already exists, so it never blocks sign-in. The trading front-end captures ?ref=CODE from the URL and forwards it here.
1

Validate the code (optional)

Before showing the user a confirmation, call the public lookup to verify the code resolves.
Returns 404 when the code does not resolve to a known wallet.
2

Pass the code on verify

Include referralCode in the auth verify request.
For returning users the field is ignored. Self-referrals are silently dropped.

2. Get and display a user’s TraderCode

Fetch the authenticated user’s code to display it in the UI as a shareable link or copyable string.
Response:
When the wallet has claimed a custom handle, customCode holds it (as entered), isCustom is true, and display is the handle.

3. Claim a custom handle (optional)

Let a user replace the wallet-derived default with a vanity handle. Preview availability as they type with the public check, then claim it. The handle is stored exactly as entered, must be letter-first [A-Za-z0-9_] and 5–20 characters, and is unique case-insensitively.
setTraderCode maps rejections to 409 (handle already taken, or a recently-freed handle still in cooldown), 422 (validation, with a reason code), 429 (edited too frequently), and 403 (custom handles are disabled). clearTraderCode counts against the same rolling-hour edit limit, so it can also return 429 or 403. The public availability check is rate-limited and returns 429 once a caller exceeds the allowance — treat it as advisory feedback, not the authoritative gate.

4. Check rewards balance

Read accumulated rewards across all reward tokens. Returns an empty list if no rewards have been earned yet.
Response:
available is in raw atomic units. Divide by the token’s decimals (e.g., 10^6 for USDC) to display a human-readable amount.

5. Transfer rewards to a trading balance

Move earned rewards from the rewards bucket into the authenticated application’s trading balance. The transfer is instant and ledger-only — no on-chain transaction. Each call spends the per-user movement budget that withdrawals and collateral transfers share, whatever the rewards balance; past it the answer is 429 with Retry-After once that budget is enforced.
Returns 409 when the requested amount exceeds the available rewards balance.

Reward Rates

Monaco configures how many referral levels TraderCodes rewards — from 1 up to a hard maximum of 10 — and a separate reward rate for each level. Levels and rates can be configured per client application, and a trade pays the levels and rates of the client it was placed through. Reward amounts are a share of the protocol fee generated by the referred user’s trades:
  • Each level’s rate applies to the TraderCodes base of the fill: the part of the protocol fee Monaco sets aside for referral rewards.
  • Every level takes its rate of that same base; levels do not compound on each other. The rates of all levels together never exceed 100% of the base.
  • Rewards are computed at fill time and credited instantly to the referrer’s rewards bucket. Each reward row records the rateApplied at that fill.
  • Levels the chain does not reach — where it is shorter than the configured depth — are simply not paid.
  • Configuration changes apply to future fills only. Rewards already earned at a level deeper than the current depth stay readable in your reward history, earningsBySource, and summary.byLevel.

Builder Checklist

  • Capture ?ref=CODE from the URL before the user completes sign-in, and pass it as sdk.auth.authenticate(clientId, code) or via the raw auth verify endpoint — sdk.login does not forward a referral code.
  • Validate the code with getTraderCodeInfo before showing a confirmation to the user; return a clean message on 404 instead of an error.
  • Never block sign-in on referral-code validation failures — a bad code is silently ignored server-side, but front-end validation errors should not prevent login.
  • Render the display field from getMyTraderCode rather than composing the display string yourself, and read isCustom to reflect whether a vanity handle is set.
  • In a custom-handle claim form, debounce checkTraderCodeAvailability for live feedback, but always handle 409/422/429 on setTraderCode — the server is the authoritative gate, not the advisory check.
  • Display available reward balances in human-readable form by dividing by the token’s decimal precision.
  • Handle 409 on transferRewards by refreshing the balance and showing the user their current available amount.