Sign an order
This page describes the client path: deploy the owner’s UserProxyV6,
approve that proxy for each input token, sign the unchanged 12-field flat Order
on IntentSettlerV3, then publish the authorization envelope with announce.
There is no AgentSwap SDK to install. The examples below are self-contained, and any EIP-712 signer can produce the owner signature.
1. Prepare the input token
Section titled “1. Prepare the input token”The order uses ERC-20 tokens on one chain. Before signing, the owner must give
their proxy an allowance for tokenIn:
tokenIn.approve(userProxy, allowance)The approval is the on-chain gate for the later proxy pull and is separate from
the order signature. The proxy pulls exactly amountIn from owner to
the settler only when a solver calls fill.
See signing and authorization for the domain and authorization model, and the order reference for the frozen 12-field struct.
2. Build the order
Section titled “2. Build the order”The client helper derives raw integer amounts and Unix-second timestamps. Its
recipient is set explicitly; it is not inferred by the settler.
// Amounts are integer strings in the token's own decimals; times are Unix seconds.const order = { owner, // the proxy owner and order signer recipient, // where the output lands; need not be the owner tokenIn, amountIn, // exact, not a ceiling tokenOut, startAmountOut, // the floor at startTime endAmountOut, // the floor the curve rests at startTime, // decay begins decayEndTime, // decay ends; the floor rests from here endTime, // the last timestamp at which the order lives appData, // bytes32 attribution tag, or 32 zero bytes nonce, // an unused owner-proxy nonce};The invariants the settler enforces on these values are on
the curve page; an order that violates one reverts at
announce, at fill and at resolve alike.
startAmountOut == endAmountOut represents a fixed-price limit order.
startAmountOut > endAmountOut represents a descending Dutch auction. The
owner signs the nonce as one of the 12 fields in the flat Order.
3. Build and sign the flat order
Section titled “3. Build and sign the flat order”The primary type is Order, under the IntentSettlerV3 EIP-712 domain.
const typedData = { primaryType: 'Order', domain: { name: 'AgentSwap IntentSettler', version: '3', chainId, verifyingContract: intentSettlerV3, }, types: { EIP712Domain: [ { name: 'name', type: 'string' }, { name: 'version', type: 'string' }, { name: 'chainId', type: 'uint256' }, { name: 'verifyingContract', type: 'address' }, ], Order: [ { name: 'owner', type: 'address' }, { name: 'recipient', type: 'address' }, { name: 'tokenIn', type: 'address' }, { name: 'amountIn', type: 'uint256' }, { name: 'tokenOut', type: 'address' }, { name: 'startAmountOut', type: 'uint256' }, { name: 'endAmountOut', type: 'uint256' }, { name: 'startTime', type: 'uint256' }, { name: 'decayEndTime', type: 'uint256' }, { name: 'endTime', type: 'uint256' }, { name: 'appData', type: 'bytes32' }, { name: 'nonce', type: 'uint256' }, ], }, message: order,};
const ownerSignature = await provider.request({ method: 'eth_signTypedData_v4', params: [owner, JSON.stringify(typedData)],});The Order type includes all 12 order fields, including nonce. The signature
is over the settler’s domain.
The typed data must contain the following bindings:
| Binding | Value |
|---|---|
domain.name |
AgentSwap IntentSettler |
domain.version |
3 |
domain.verifyingContract |
the deployed IntentSettlerV3 address |
primaryType |
Order |
message |
all 12 fields of order |
Wrap the owner signature for announce as the V6 owner authorization:
abi.encode(AuthKind.Owner, abi.encode(bytes(ownerSignature)))AuthKind.Owner is 0. orderDigest(order) returns the digest that the proxy
recomputes when it authorizes the pull.
4. Publish the authorization
Section titled “4. Publish the authorization”announce(order, auth) is permissionless and optional. The owner can
self-submit it, or another broadcaster can publish the same authorization. The
envelope is carried in IntentAnnounced; it is checked again and consumed by
fill.
// announce((O),bytes) — selector 0x294470ec. Any account may send it.await provider.request({ method: 'eth_sendTransaction', params: [{ from: account, to: intentSettlerV3, data: encodeAnnounce(order, auth) }],});Verify what you built before you rely on it: orderDigest(order) returns the
exact V6 digest, and orderHash(order) (0xd94a1dc6) returns the id the events
are keyed by. Both are eth_calls against the settler.
The announcement verifies the signature, but it does not make the order
fillable. A spent proxy nonce, a missing proxy allowance, a changed ERC-1271
wallet configuration, or an unusable route can still prevent settlement. A
solver must screen the order and eth_call-dry-run fill immediately before
submitting it; see fill an order.