- A transfer with
msg(mt_transfer_callor atransferintent) when tokens go in: orders and deposits. - An
auth_callintent when nothing goes in:intents.nearchecks your signature and calls the book’son_authwith your account assigner_id. The book acceptson_authonly fromintents.near.
prune is a plain public method.
The auth_call envelope
msg is a JSON string {"action": "<snake_case name>", "data": {...}}; claim_balance has no data. The action runs
in its own receipt: a panic reverts the book’s state for that call only, not the other intents of the same payload.
Signing (NEP-413)
Intents are signed with NEP-413 by a key thatintents.near knows for your account. An implicit account’s own key is known automatically; a named account first
registers a key with intents.near add_public_key.
1
Build the message
message is this object serialized as a JSON string. Keep the deadline short (a few minutes).2
Build a versioned nonce
32 bytes, each nonce usable once per account:
intents.near rejects it when the salt is not a current one, the nonce deadline is earlier than the message
deadline, or the nonce deadline has passed. Use the message deadline (or a little later) as the nonce deadline.
Legacy random 32-byte nonces are still accepted but deprecated in NEAR Intents.3
Hash and sign
4
Wrap the commitment
5
Submit
-
Gasless: the NEAR Intents solver relay,
POST https://solver-relay-v2.chaindefuser.com/rpcwith your API key (a JWT from the NEAR Intents Partner Portal) inX-API-Key. The relay runsexecute_intentswith 300 Tgas.The answer is{ "status": "OK" | "FAILED", "reason"?, "intent_hash" }.publish_intentstakes several (signed_datas). -
Yourself: call
intents.nearexecute_intents({ "signed": [commitment] })from any NEAR account with the gas you choose (simulate_intentswith the same args dry-runs it). See Submitting your own transaction.
6
Read the outcome
- Through the relay, poll JSON-RPC
get_statuswith{ "intent_hash": "<intent_hash>" }untilstatusisSETTLED(orNOT_FOUND_OR_NOT_VALID: not received, expired or failed).data.hashis the NEAR transaction hash. - Read the transaction’s receipts: NEAR RPC
EXPERIMENTAL_tx_status(with the transaction’s signer assender_account_id) or FastNEAR/v0/transactionsby hash (Data sources). - Find the receipt executed by
hexbook.near(on_authfor anauth_call,mt_on_transferfor a transfer). Its logs are the result: for abatch,epoch,order_closedandorder_created(arraydata: your new hashes) andplace_skipped; see Events. - If that receipt failed, the action reverted (for a
batch: nothing was cancelled or placed) even though the intent itself settled and its nonce is spent. Its error message says why.
Submitting your own transaction
NEAR pre-charges a transaction’s attached gas at a pessimistic gas price and refunds what is unused: keep about 0.3 NEAR on the submitting account for a 300 Tgas call (execute_intents or mt_transfer_call).
deposit
A transfer tohexbook.near with msg {"deposit": true} credits the sender’s internal balance; the book keeps the whole
amount.
- The token must be the base or quote of an existing book, otherwise the call panics and is refunded.
- Logs
deposit {a, tk, v}.
batch
Cancels and places your orders in one book atomically, funded from your internal balance. It never pays out.price and amount must be strings: a JSON number fails to parse and the whole batch panics.
Order: bump_epoch → cancel (in order) → place (in order). Cancel refunds can fund the placements of the same batch.
Panics (the whole batch reverts):
- more than 64 cancels or 32 places;
- a cancel hash that is not your resting order in this book;
- a placement with price 0, off the tick, below the minimum or unable to buy one base unit, or
expires_atnot in the future; - not enough internal balance for a placement (sell: base, buy: quote);
- logs over 16 KiB (split the batch).
The best live price skips dead orders, scanning at most 128 orders per side; past that, the price reached counts as live.
Events. A batch logs
epoch (if bumped), then one order_closed (why: "cancel"), one order_created (with x
and e when non-zero) and one place_skipped ({m, i, why}, i = index in place), each with a data array, one
item per order. See Events.
Gas. Each cancel and placement writes the level, the order and your set of orders. Measured on the book receipt in
sandbox:
Roughly 1 Tgas per operation plus a few Tgas fixed; a full batch fits easily in the relay’s 300 Tgas. Set
min_gas with
headroom (for example 100 Tgas for a full batch).
cancel_all
Bumps your epoch in one book: O(1), whatever the number of orders. Every order you placed there before is dead at once. Logsepoch {m, b, q, e}.
prune (internal balance). Until then they hold their slots: close them in your next batch’s
cancel. batch with bump_epoch: true kills everything and posts a fresh ladder in one step; list the old hashes
in the same batch’s cancel to free their slots too.
close_order
Closes one of your resting orders, refunds it to your internal balance, then claims your whole internal balance likeclaim_balance.
- Panics with
Order not foundorOnly order maker can close the order. - Logs
order_closed(why: "cancel") andclaim.
claim_balance
Pays out your whole internal balance, every token in one call, as many tokens as the gas allows (about 22 Tgas each; the rest stays claimable). Logsclaim. A payout that fails is credited back (payout_failed).
withdraw
Pays one token out of your internal balance to yourintents.near balance.
amount: null(or omitted) withdraws all of that token.- Panics with
Nothing to withdraw,Insufficient internal balanceorNot enough gas to withdraw(give it ~35 Tgas). - Logs
claim. Onemt_transfer; if it fails, the amount is credited back (payout_failed).
set_payout_mode
Where your maker proceeds go; see Payout modes. Logspayout_mode {a, mode}.
mode: "internal" or "intents" (default). Read it with get_payout_mode.
prune
A public method: anyone can close dead orders. No deposit, at most 64 hashes; live and unknown hashes are ignored. Refunds go to the makers’ internal balances. Logs oneorder_closed with a data array
(why: "expired" or "epoch") and returns how many orders it closed.
cancel is cheaper and lands with your requote; prune
is the fallback (for example when you stop quoting).
A typical maker session
Deposit, set payout modeinternal, quote with batch (closing your dead orders in its cancel), cancel_all as the
kill switch, then close and withdraw. The full lifecycle is in
Build a market maker.