| name | build-settle-calldata |
| description | Guide through constructing Settlement.settle() calldata from /solve API data using @okx-intent-swap/sdk-solver |
| user-invocable | true |
| argument-hint | ["json-file-path"] |
| allowed-tools | Read, Grep, Glob, Bash, Write, Edit |
Build Settlement Calldata
Guide the user through constructing Settlement.settle() calldata from /solve API data.
If $ARGUMENTS is a file path, read the file and generate concrete code. If empty or "help", explain the full workflow.
Core Data Flow
SolveRequest + SolveResponse → buildSettleCalldata() → hex calldata → Settlement.settle()
Step 1: Understand API Types
SolveRequest (request body)
interface SolveRequest {
auctionId?: string;
orders: SolveRequestOrder[];
}
interface SolveRequestOrder {
fromTokenAddress: string;
toTokenAddress: string;
owner: string;
receiver: string;
fromTokenAmount: string;
toTokenAmount: string;
validTo: number;
appDataHash: string;
swapMode: string;
partiallyFillable: boolean;
signingScheme: string;
signature: string;
commissionInfos: ApiCommissionInfo[];
}
SolveResponse (response body)
interface SolveResponse {
solutions: Solution[];
}
interface Solution {
clearingPrices: Record<string, string>;
orders: SolveResponseOrder[];
surplusFeeInfo: ApiSurplusFeeInfo;
}
interface SolveResponseOrder {
executedFromTokenAmount: string;
executedToTokenAmount: string;
commissionInfos: ApiCommissionInfo[];
solverFeeInfo: ApiSolverFeeInfo;
}
Fee Types
interface ApiCommissionInfo {
feePercent: string;
referrerWalletAddress: string;
feeDirection: boolean;
toB: boolean;
commissionType: string;
}
interface ApiSolverFeeInfo {
feePercent: string;
solverAddress: string;
feeDirection: boolean;
feeAmount: string;
}
interface ApiSurplusFeeInfo {
feePercent: string;
trimReceiver: string;
flag: string;
}
Step 2: Prepare API Data
Strip envelope/extra fields to match SDK types:
const rawApiResponse = await fetch('/solve', { ... }).then(r => r.json());
const request: SolveRequest = {
orders: rawApiResponse.orders,
};
const response: SolveResponse = {
solutions: rawApiResponse.solutions,
};
All numeric amounts are decimal strings (not bigint). The SDK converts internally.
Step 3: Build Interactions (if needed)
import type { Interaction } from '@okx-intent-swap/sdk-common';
const interactions: [Interaction[], Interaction[], Interaction[]] = [
[],
[
{ target: fromTokenAddress, value: 0n, callData: erc20ApproveCalldata },
{ target: dexRouterAddress, value: 0n, callData: swapCalldata },
],
[],
];
Default is [[], [], []] (no interactions).
Step 4: Call buildSettleCalldata
import {
buildSettleCalldata,
type SolveRequest,
type SolveResponse,
} from '@okx-intent-swap/sdk-solver';
const settleId = settleRequest.settleInfos[0].settleId;
const result = buildSettleCalldata(request, response, settleId, {
});
useComputedPrices
true (default): Computes clearing prices from execution amounts + fees. Deterministic, matches contract fee computation.
false: Uses solution.clearingPrices directly (decimal strings → uint256).
Step 5: Verify
pnpm build
import { decodeSettleCalldata } from '@okx-intent-swap/sdk-solver';
const decoded = decodeSettleCalldata(result.calldata);
console.assert(decoded.settleId === result.params.settleId);
console.assert(decoded.tokens.length === result.params.tokens.length);
console.assert(decoded.trades.length === result.params.trades.length);
Complete Example
import {
buildSettleCalldata,
type SolveRequest,
type SolveResponse,
} from '@okx-intent-swap/sdk-solver';
const settleId = '12345';
const request: SolveRequest = {
orders: [{
fromTokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
toTokenAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
owner: '0x1234...owner',
receiver: '0x1234...owner',
fromTokenAmount: '1000000000',
toTokenAmount: '500000000000000',
validTo: 1700000000,
appDataHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
swapMode: 'exactIn',
partiallyFillable: false,
signingScheme: 'eip712',
signature: '0x...',
commissionInfos: [{
feePercent: '10000000',
referrerWalletAddress: '0x...referrer',
feeDirection: true,
toB: false,
commissionType: 'okx',
}],
}],
};
const response: SolveResponse = {
solutions: [{
clearingPrices: {
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '1',
'0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2': '2000',
},
orders: [{
executedFromTokenAmount: '1000000000',
executedToTokenAmount: '510000000000000',
commissionInfos: [{
feePercent: '10000000',
referrerWalletAddress: '0x...referrer',
feeDirection: true,
toB: false,
commissionType: 'okx',
}],
solverFeeInfo: {
feePercent: '5000000',
solverAddress: '0x...solver',
feeDirection: true,
feeAmount: '50000',
},
}],
surplusFeeInfo: {
feePercent: '9800000',
trimReceiver: '0x...trimReceiver',
flag: '0',
},
}],
};
const result = buildSettleCalldata(request, response, settleId);
console.log('Calldata:', result.calldata);
console.log('SettleId:', result.params.settleId);
Troubleshooting
| Issue | Cause | Fix |
|---|
Order count mismatch | request/solution order lengths differ | Ensure parallel arrays |
fromToken not found in tokens array | Address casing mismatch | Use lowercase consistently |
Response contains no solutions | Empty solutions array | Check API response format |
TypeScript .js import errors | ESM requires extensions | Add .js to all relative imports |