Dokumentasi
Semua yang dibutuhkan untuk integrasi Commish atau memanggil program secara langsung.
Gambaran umum
Commish is one Solana program written with Pinocchio, used as a holdback for agent payments. A tool creates a campaign that names a router cut, a refund window and an attestor key (the relayer). An agent pays the tool over HTTP 402 in USDC, straight into the campaign's vault, with a memo naming the router that sent it. The relayer reads that payment on-chain and records it; the program reserves the router's cut in a commission account. After the refund window anyone can release the cut to the payee. Before that, the payee can sell it to a buyer for an agreed price. On-chain the instruction and field names are the original ones: the tool is the brand, the router is the creator, and a paid call is a record_sale.
| Program | CmSHpw9QTwvRSNCCBrQz275ESTCw8D79Z8jjhWmPJfFB |
| Token | USDC EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| Source | github.com/bryankwandou/commish |
| Binary | 9,272 bytes, SBPF v0, built with build-std and panic_immediate_abort |
| 402 endpoint | https://getcommish.vercel.app/api/agent/call |
Akun
| Account | Address | Size | Holds |
|---|---|---|---|
| Campaign | ["campaign", brand, id_le_u64] | 176 | brand, attestor, mint, vault, id, hold, reserved, paid, bps |
| Commission | ["commission", campaign, order_hash] | 184 | campaign, creator, payee, rent_payer, order_hash, amount, release_at, sold flag |
| Vault | ATA(campaign, USDC) | 165 | The campaign's budget. Owned by the campaign PDA. |
Records are #[repr(C)], little-endian, 8-byte aligned. Byte 0 is a tag (1 campaign, 2 commission), byte 1 the version, byte 2 the bump. A commission account is closed when it is paid or cancelled, and its rent returns to rent_payer.
Instruksi
Instruction data is an 8-byte header with the tag in byte 0, followed by the arguments as a #[repr(C)] struct. Bumps and the rent for new accounts are passed by the client; the runtime rejects a wrong bump and any new account below the rent-exempt minimum.
| Tag | Instruction | Signers | Accounts | Arguments |
|---|---|---|---|---|
| 0 | create_campaign | brand | brand, campaign, vault, mint, system | id, hold, bps, bump, lamports, attestor |
| 1 | record_sale | attestor, payer | attestor, payer, campaign, vault, commission, system | order_hash, order_amount, creator, lamports, bump |
| 2 | cancel | attestor | attestor, campaign, commission, rent_payer | none, only before release_at |
| 3 | release | none | campaign, vault, commission, payee_token, rent_payer, token_program | none, only after release_at |
| 4 | withdraw | brand | brand, campaign, vault, dest, token_program | amount ≤ vault − reserved |
| 5 | sell | payee, buyer | payee, buyer, campaign, commission, buyer_token, payee_token, token_program | price, 0 < price ≤ amount, before release_at |
Kode error
| Code | Meaning |
|---|---|
6000 | Invalid instruction |
6001 | Not enough accounts |
6002 | A required signature is missing |
6003 | Account is not the expected record |
6004 | Signer is not this campaign's attestor |
6005 | Signer is not this campaign's brand |
6006 | An account does not match the campaign |
6007 | Commission rate must be between 0.01% and 50% |
6008 | Refund window must be between 0 and 90 days |
6009 | Order is too small to earn a commission |
6010 | Not enough unreserved budget in the vault |
6011 | The refund window has not closed yet |
6012 | The refund window has already closed |
6013 | Signer or account is not the current payee |
6014 | Price must be above zero and at most the commission |
6015 | Arithmetic overflow |
6016 | Too many accounts |
6017 | Runtime error |
Integrasi toko
- Create a campaign in the tool console with your relayer key as the attestor, a router cut and a refund window.
- Answer unpaid calls with
402 Payment Required: the price, the vault address and the memo formatcommish:<router wallet>. - When the agent retries with
X-Payment: <signature>, read the transaction, check that the vault received at least the price in USDC and that the memo names the?ref=router, then sendrecord_salewith order hashsha256("commish:x402:" + campaign + ":" + signature). - If the call is refunded inside the window, send
cancel. After the window, anyone can sendrelease. The live endpoint does all of this; its source isweb/src/app/api/agent/call/route.ts.
The client in web/src/lib/commish/program.ts builds every instruction and derives every address. It depends only on@solana/kit primitives, so it runs in a browser, a server route or a worker.
Model keamanan
- The program cannot see the payment. The relayer (the attestor) records a call only after it has read a successful USDC transfer into the vault. A compromised relayer key could reserve fake cuts, but only up to the vault's unreserved balance.
- Funds leave the vault only through
release(to the payee's token account, after the window) andwithdraw(the unreserved part, to the tool). - Only the legacy SPL Token program is accepted, and every token account is checked for the campaign's mint.
- Lamports sent to a commission address before it exists no longer block
record_sale: since the 5 Oct 2026 upgrade the program creates the account withCreateAccountAllowPrefund, so an unkeyed order hash is safe. - A payment could be recorded again after its commission is paid or cancelled, because the account is closed. The relayer refuses any payment whose commission address has a successful
record_salein its history, so one payment earns one cut. - The program is covered by 33 end-to-end tests that run against the compiled binary, most of them attacks that must fail.