Agent pledge guide: the $CRANK fair launch end to end¶
Status: Rolling out -- participation opens when the launch gate opens; the pledge_to_ilo plan response reports the current launch_gate state, and while the gate is closed the refusal error carries the same state in details.launch_gate.
This guide walks a third-party agent through participating in the $CRANK utility token fair launch on behalf of its user, from reading the sale state to claiming an allocation. Every value-bearing step responds with an unsigned transaction that the user's own wallet signs -- Crank never holds, sees, or co-signs a key.
Participation is gated
Pledging opens only after legal sign-off, the launch prerequisites, and
the adoption milestone are all in place. Until then every pledge call is
refused with POLICY_VIOLATION (see Error codes). US
persons and persons in Australia cannot pledge.
The flow at a glance¶
read state (REST or MCP)
-> read disclosures
-> jurisdiction attestation
-> pledge_to_ilo (plan: preview, no bytes)
-> pledge_to_ilo confirm (unsigned transaction)
-> user signs + broadcasts
-> verify_transaction
-> after settlement: claim_ilo_tokens (succeeded) or refund_pledge (failed)
1. Read the sale state¶
No MCP connection is needed to see the sale. The public REST endpoint is read-only and requires no authentication:
Key fields of launch:
| Field | Meaning |
|---|---|
phase |
not_created, pre_open, open, closed_awaiting_settlement, settled_succeeded, settled_finalized, settled_failed |
terms |
Minimum/maximum raise, token allocation, window, per-wallet cap (all integer base units) |
progress |
Total pledged, pledger count, progress toward minimum and maximum, seconds until open/close |
clearing_rate |
The uniform rate range: at the minimum raise, at the maximum raise, at the current total |
launch_gate |
Whether participation is open, and which leg is pending if not |
explorer |
Explorer links for the launch config, pledge escrow, vault, and mints |
settlement |
Present once settled: outcome, allocation formula, whether refunds are open |
Over MCP the same read is get_ilo_details(launch_id=<id>), which also responds with
live escrow token balances and the full disclosure bundle. Both are free.
Do not take the mirror on trust for anything that matters: the settlement verification recipe recomputes every number from chain state.
2. Read the disclosures¶
get_ilo_details and every pledge_to_ilo response carry a disclosures
object -- the mandatory pre-pledge disclosure block shown on
crank.ing/launch:
purpose-- $CRANK is a utility token; a pledge is not a purchase of an expectation of profit.proceeds_split-- 40% liquidity, 40% rescission reserve (held liquid for 12 months), 20% legal-compliance reserve; zero percent funds operator costs.pledge_asset--USDC(the only pledge asset in v1).proceeds_tax_status-- proceeds are pre-tax company funds; the split buckets are ring-fenced regardless.pledge_fees-- no Crank fee applies to pledging; the full pledged amount moves into the escrow.price_range-- token allocation, softcap and cap with the implied per-token price at each; the final uniform price is set by total participation.no_external_audit,total_loss_risk-- there is no independent external security audit; pledged funds can be lost in full.refund_mechanics-- how the failed-launch refund path works.jurisdiction_restrictions-- who cannot pledge.
Show these to the user before asking them to confirm. A confirmed pledge
requires disclosures_acknowledged=true; your agent should set it only after
the user has actually seen and accepted them.
3. Jurisdiction attestation¶
Unknown jurisdiction is denied. Either declare it once (persists 90 days):
await client.call_tool("declare_jurisdiction", {
"wallet_address": USER_WALLET,
"jurisdiction": "SG", # ISO-3166-1 alpha-2, self-declared by the user, never inferred
})
or pass jurisdiction inline on the pledge_to_ilo call. US persons and
Australia are blocked, and sanctioned (OFAC SDN) wallets are blocked
regardless of jurisdiction. The contract itself is permissionless, so on-chain
blocking is best-efforts; the attestation is the user's own declaration.
An additional on-chain gate-attestation step (binding the off-chain gate to the pledge instruction) is planned; when it ships this section will document the extra account the pledge transaction carries. Until then, the flow below is complete.
4. Plan the pledge¶
amount is in pledge-mint base units (USDC has 6 decimals, so 1_000_000 is
1 USDC). Without confirm, the call is a priced, fully screened preview and
responds with no transaction bytes:
plan = await client.call_tool("pledge_to_ilo", {
"launch_id": 1,
"amount": 25_000_000,
"wallet_address": USER_WALLET,
"jurisdiction": "SG",
})
assert plan["action"] == "plan"
print(plan["would_execute"], plan["preflight"], plan["anti_sybil"])
print(plan["projected_allocation"]) # pro-rata at today's total; moves with every pledge
preflight evaluates every guard the chain applies (window, status, remaining
capacity, per-wallet cap) so a doomed transaction is never built.
projected_allocation is a projection of the on-chain formula at the current
total, not a fixed amount -- the final allocation is set at settlement.
5. Confirm and sign¶
tx = await client.call_tool("pledge_to_ilo", {
"launch_id": 1,
"amount": 25_000_000,
"wallet_address": USER_WALLET,
"jurisdiction": "SG",
"confirm": True,
"disclosures_acknowledged": True, # only after the user accepted them
})
assert tx["action"] == "sign_required"
unsigned_b64 = tx["transaction"]
Sign unsigned_b64 with the user's wallet (any signer works -- see the
signer cookbook), broadcast it, then confirm:
await client.call_tool("verify_transaction", {
"tx_signature": signature,
"wallet_address": USER_WALLET,
})
A pledge is an irreversible commitment of funds into the escrow until
settlement. Check the user's position any time with
get_my_pledge_status(launch_id, wallet_address) or
GET /api/v1/ilo/launches/<launch_id>/?wallet=<pubkey>.
6. After settlement¶
Succeeded. Allocations unlock on the liquidity release schedule. When
something is releasable, claim_ilo_tokens(launch_id, wallet_address) responds with
an unsigned release_tokens transaction for the user to sign; otherwise it
responds with action: "nothing_to_claim" with the next release check time.
Failed. The minimum raise was not met: no tokens are allocated and the
full pledge is refundable. get_my_pledge_status reports
refund_available: true; the refund is the on-chain refund_pledge
instruction, signed by the pledger's own wallet.
Error codes¶
All errors use the standard Crank error envelope (code, message,
retryable, details).
| Code | When | What the agent should do |
|---|---|---|
GEO_RESTRICTED |
Jurisdiction undeclared, expired, US, Australia, or an OFAC-listed wallet. details.reason is one of jurisdiction_unknown, attestation_expired, reg_s_us_person, ilo_au_geo_gate, ofac |
Stop. Ask the user to declare a jurisdiction only if the reason is jurisdiction_unknown / attestation_expired; never retry other reasons |
POLICY_VIOLATION |
Participation not open (details.launch_gate.reason), disclosures not acknowledged, or the wallet fails the anti-sybil screen |
Do not retry until the cause changes; show the user the message |
INVALID_PARAMS |
Bad amount/wallet, or the preflight would fail on chain (window closed, cap exceeded, launch full) -- see details.preflight.blockers |
Fix the input or stop |
NOT_FOUND |
No launch with that launch_id on this cluster, or no pledge for that wallet |
Check launch_id against /api/v1/ilo/status/ |
CONFIG_ERROR |
The chain client is unavailable in this deployment | Fall back to the REST status read; retry later |
Rules this flow never bends¶
- Non-custodial. Every write is an unsigned transaction the user signs. Crank never asks for, stores, or co-signs a key.
- No discretion. The agent pledges only the amount the user chose, after the user saw the disclosures. Nothing in this flow recommends an amount or a timing.
- Utility framing. $CRANK grants fee discounts and staking utility within the Crank rails. Describe a pledge as participation in a utility token fair launch -- never as a way to make money.