curl --request POST \
--url https://propamm.kipseli.win/v2/swap/sign \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"tokenIn": "0x4200000000000000000000000000000000000006",
"tokenOut": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"fee": "3000",
"userAddress": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
}
'{
"verificationData": "0xabcdef...",
"timestamp": 1741737600
}Request Swap Verification
ABI-encodes (tokenIn, tokenOut, timestamp, fee, originRate, userAddress),
Keccak256-hashes the payload, and signs it with secp256k1.
The recovery ID is adjusted from [0,1] to [27,28] per the Ethereum Yellow Paper.
The response contains ABI-encoded verification data (fee, originRate, userAddress, signature)
ready for on-chain submission.
Use the chainId body field to select the chain the swap will be executed on;
the token pair must be supported there. Omitting it (or passing 0) targets the
default chain, Base (8453).
Note that the signed payload itself does not include the chain id — chainId
selects which chain’s pair list and signing key are used.
curl --request POST \
--url https://propamm.kipseli.win/v2/swap/sign \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"tokenIn": "0x4200000000000000000000000000000000000006",
"tokenOut": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"fee": "3000",
"userAddress": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
}
'{
"verificationData": "0xabcdef...",
"timestamp": 1741737600
}verificationData and timestamp. Both values must be passed directly into the swap() function — if either is modified or expired, the transaction will revert.
Optionally, pass amountIn (and minAmountOut) to receive pre-built calldata ready for direct submission.
Selecting a Chain
Pass the target chain in the request body withchainId:
| Chain | chainId | Router (PropAmm) | Quote token |
|---|---|---|---|
| BNB Chain | 56 | 0x4cb2140C29518db6203f661B9F6dD60B68BB7f0d | USDT |
| Base | 8453 | 0x71C2Ed90CC288229Be59F26b8B3EEF3C07d7ab99 | USDC |
| Robinhood Chain | 4663 | 0x4f1ce663bF2E5e3b4A4ba88F6D1BF227e5597402 | USDG |
tokenIn/tokenOut must be that chain’s quote token — USDT on BNB Chain, not USDC. See Get Orderbook for addresses.
chainId is omitted (or 0), the request targets Base (8453). chainId selects which chain’s pair list is validated against and which signing key is used — the token pair must be supported on that chain, or the request fails with 400 PAIR_NOT_FOUND. An unsupported chain returns 400 UNSUPPORTED_CHAIN.Swap Execution Flow
Step 1 — Call this endpoint
Minimal (verification data only):curl -X POST https://propamm.kipseli.win/v2/swap/sign \
-H "Content-Type: application/json" \
-H "X-API-KEY: $KIPSELI_API_KEY" \
-d '{
"chainId": 8453,
"tokenIn": "0x4200000000000000000000000000000000000006",
"tokenOut": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"fee": "30",
"userAddress": "0x1111111111111111111111111111111111111111"
}'
{
"verificationData": "0x...",
"timestamp": 1741737600
}
amountIn and optionally minAmountOut):
curl -X POST https://propamm.kipseli.win/v2/swap/sign \
-H "Content-Type: application/json" \
-H "X-API-KEY: $KIPSELI_API_KEY" \
-d '{
"chainId": 8453,
"tokenIn": "0x4200000000000000000000000000000000000006",
"tokenOut": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"fee": "30",
"userAddress": "0x1111111111111111111111111111111111111111",
"amountIn": "1000000000000000000",
"minAmountOut": "3150000000"
}'
{
"verificationData": "0x...",
"timestamp": 1741737600,
"calldata": "0x..."
}
calldata field is ABI-encoded for swap(address,uint256,address,uint256,uint256,bytes) and can be submitted directly to the router without further encoding.
Step 2 — Approve the Router
Use the Router for the chain you passed aschainId (see Selecting a Chain). The example below is Base.
IERC20(tokenIn).approve(
0x71C2Ed90CC288229Be59F26b8B3EEF3C07d7ab99, // Router on Base (8453)
amountIn
);
Step 3 — Execute the swap on-chain
Option A — build the call yourself:IPropAmm(0x71C2Ed90CC288229Be59F26b8B3EEF3C07d7ab99).swap( // Router on Base (8453)
tokenIn,
amountIn,
tokenOut,
minOutAmount, // slippage protection — use quote() to calculate
timestamp, // from API response
verificationData // from API response
);
| Parameter | Description |
|---|---|
tokenIn | Input token address |
amountIn | Amount of input token (in token decimals) |
tokenOut | Output token address |
minOutAmount | Minimum acceptable output — set this to protect against slippage |
timestamp | Returned by this API — pass through unchanged |
verificationData | Returned by this API — pass through unchanged |
calldata from the API (requires amountIn in Step 1):
// Router on Base (8453)
(bool success, ) = address(0x71C2Ed90CC288229Be59F26b8B3EEF3C07d7ab99).call(calldata);
require(success, "swap failed");
calldata is already ABI-encoded for swap(address,uint256,address,uint256,uint256,bytes) — no further encoding needed.
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
chainId | integer | No | Chain the swap will be executed on. Omitted or 0 targets 8453 (Base). |
tokenIn | string | Yes | Input token address on chainId |
tokenOut | string | Yes | Output token address on chainId |
fee | string | Yes | Fee tier in 0.1 bps resolution — see Fee Parameter |
userAddress | string | Yes | Address that will submit the swap |
amountIn | string | No | Input amount in wei. When provided, the response includes calldata |
minAmountOut | string | No | Minimum accepted output in wei. Only used with amountIn; defaults to 0 |
Fee Parameter
Thefee field uses 0.1 bps resolution:
| Value | Rate |
|---|---|
1 | 0.1 bps (0.001%) |
10 | 1 bps (0.01%) |
30 | 3 bps (0.03%) |
100 | 10 bps (0.10%) |
amountOut) and settled monthly in a mutually agreed currency.Authorizations
API key issued by the Kipseli team. Required on every request.
Authorization: Bearer <key> is accepted as an alternative.
Body
EVM hex address of the input token (checksummed or lowercase)
"0x4200000000000000000000000000000000000006"
EVM hex address of the output token (checksummed or lowercase)
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
Fee tier as a decimal string in 0.1 bps resolution(e.g. "3000" = 3%)
"3000"
EVM hex address of the user submitting the swap
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
Chain the swap will be executed on. Supported values: 56 (BNB Chain),
8453 (Base), 4663 (Robinhood Chain). Omit it (or pass 0) for the
default chain, Base (8453).
It selects the pair list validated against and the signing key used. A chain
the service does not serve returns 400 UNSUPPORTED_CHAIN; a pair not tracked
on it returns 400 PAIR_NOT_FOUND.
x >= 08453
Input token amount in wei as a decimal string. When provided, the response
will include a calldata field with ABI-encoded calldata for the swap function.
"1000000000000000000"
Minimum accepted output token amount in wei as a decimal string.
Only used when amountIn is provided. Defaults to 0 if omitted.
"3150000000"
Response
Quote signed successfully
ABI-encoded hex string (with 0x prefix) containing
(fee, originRate, userAddress, signature). Pass this directly
to the on-chain verification contract.
"0xabcdef..."
Unix timestamp (seconds) at which the signature was generated
1741737600
ABI-encoded calldata (with 0x prefix) for the swap(address,uint256,address,uint256,uint256,bytes)
function. Only present when amountIn was provided in the request.
The encoded arguments are (tokenIn, amountIn, tokenOut, minAmountOut, quoteTimestamp, verificationData).
"0x..."