Swap API
Three endpoints: list the tokens, get a quote, get a transaction. The API checks the V2 and V3 pools, picks the best route and hands you calldata for the swap entrypoint. You never have to think about pools.
The ground rules
- Base URL:
https://www.litvmswap.com/api - Auth: none. CORS is open, so browsers can call it directly.
- Amounts: human-readable decimal strings like
"0.5". The API applies the token's decimals for you. - Native zkLTC: use
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE. - Tokens: the API covers the tokens in
/partner/tokens. Anything else comes back as a404. - Chain:
chainIddefaults to4441. You can leave it out.
List tokens
Every token the Swap API can route, in a shape that's easy to drop into a token picker.
curl https://www.litvmswap.com/api/partner/tokens{
"chainId": 4441,
"tokens": [
{
"address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"symbol": "zkLTC",
"name": "zkLTC",
"decimals": 18,
"logoURI": "https://s2.coinmarketcap.com/static/img/coins/64x64/2.png",
"isNative": true
},
{
"address": "0x315374AA9b5536037Cc1Efeea2439CCC0913A77e",
"symbol": "wzkLTC",
"name": "Wrapped zkLTC",
"decimals": 18,
"logoURI": "https://assets.coingecko.com/coins/images/2/standard/litecoin.png?1696501400",
"isNative": false
}
]
}Need richer metadata (verified flags, on-chain names)? The Token List API has it.
Get a quote
A read-only price check. Use it while the user types.
| Query param | Required | What it is |
|---|---|---|
fromToken | yes | Address you sell. Native placeholder for zkLTC |
toToken | yes | Address you buy |
amount | yes | How much you sell, in human units ("0.5") |
partnerFeeBps | no | Your integrator fee in basis points, 0 to 500. Defaults to 10, so pass 0 if you don't charge one |
chainId | no | Defaults to 4441 |
curl "https://www.litvmswap.com/api/partner/quote?fromToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&toToken=0xdf69970B2fE416339187aA41D39882e864984CE9&amount=0.5&partnerFeeBps=0"{
"fromToken": { "address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "symbol": "zkLTC", "decimals": 18 },
"toToken": { "address": "0xdf69970B2fE416339187aA41D39882e864984CE9", "symbol": "ZKUSDC", "decimals": 18 },
"fromAmount": "0.5",
"toAmount": "126.450390772208070106",
"exchangeRate": "252.90078154441613",
"partnerFeeBps": 0,
"partnerFeeAmount": "0",
"route": {
"dexName": "OurV2",
"poolType": "v2",
"poolAddress": "0x5Ab5906CFBc21642A7f526521318bA33262E3954"
},
"spender": "0xF664B56933f3cF0d7d69982b5A8eC9101b80059D"
}| Field | Meaning |
|---|---|
toAmount | What the user gets, after fees, in human units |
exchangeRate | toAmount / fromAmount |
route | Which pool the best route uses. poolType is v2 or v3 |
spender | Who needs an allowance if fromToken is an ERC-20 |
| fee fields | A breakdown of fees that are already taken out of toAmount |
priceImpact | Not calculated yet, always 0. Don't build logic on it |
Build a swap transaction
Returns a transaction you can hand straight to a wallet. Send a JSON body:
| Body field | Required | What it is |
|---|---|---|
fromToken | yes | Address you sell |
toToken | yes | Address you buy |
amount | yes | Amount to sell, human units, as a string |
userAddress | yes | The wallet that signs. Bought tokens go here |
slippage | no | Max price movement you accept, in percent. Default 0.5 |
partnerFeeBps | no | Your fee, 0 to 500. Default 10 |
referrerAddress | no | Where your fee goes. No referrerAddress, no fee paid |
chainId | no | Defaults to 4441 |
curl -X POST https://www.litvmswap.com/api/partner/swap \
-H 'content-type: application/json' \
-d '{
"fromToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"toToken": "0xdf69970B2fE416339187aA41D39882e864984CE9",
"amount": "0.5",
"userAddress": "0xYourWalletAddress",
"slippage": 0.5,
"partnerFeeBps": 0
}'{
"transaction": {
"to": "0xF664B56933f3cF0d7d69982b5A8eC9101b80059D",
"data": "0xce1e7030…",
"value": "500000000000000000",
"chainId": 4441
},
"estimate": {
"fromAmount": "0.5",
"toAmount": "126.32",
"minAmountOut": "125.69",
"partnerFeeBps": 0
},
"spender": "0xF664B56933f3cF0d7d69982b5A8eC9101b80059D"
}| Field | Meaning |
|---|---|
transaction.to / data / value | Send exactly these. value is in wei, as a string |
estimate.toAmount | Expected output after fees. This is the number to show before signing |
estimate.minAmountOut | The least the user can receive. Below that, the swap reverts instead |
spender | Approve this address when selling an ERC-20 |
The estimate object also carries a fee breakdown. Like with quotes, fees are already taken out of toAmount.
/partner/quote is for live price display. /partner/swap is built for one exact transaction, so when the two
differ a little, trust the /partner/swap estimate.
Wrapping and unwrapping
Swapping native zkLTC to wzkLTC (or back) skips routing. You get a direct deposit() or withdraw(uint256) call on
the wzkLTC contract, 1:1, no fees.
Integrator fees
Building a wallet, bot or dApp? You can take a small cut of the swaps you send:
- Pass
partnerFeeBps(basis points,100= 1%, max500). - Pass
referrerAddress, the wallet that should receive it.
The fee comes out of the output token and lands in referrerAddress in the same transaction. Nothing to claim
later. The contract refuses anything above 500 bps.
body: JSON.stringify({
fromToken, toToken, amount, userAddress,
partnerFeeBps: 25, // 0.25%
referrerAddress: '0xYourFeeWallet',
})Be upfront with your users about the fee. It shows up in estimate.toAmount either way.
Errors
Errors come back as JSON with an error field (and sometimes a message).
| Status | error | What to do |
|---|---|---|
| 400 | Missing required parameters: ... | Add the missing field |
| 400 | Invalid partnerFeeBps: must be between 0 and 500 (5%) | Keep it in range |
| 400 | Invalid amount / Invalid userAddress | Check the format. Amount must be a positive number string |
| 404 | Token not found | The token isn't routed by the API. Check /partner/tokens |
| 404 | No route found / No liquidity or route found for this pair | No pool path with enough liquidity. Try a smaller amount |
| 500 | Internal server error | Something on our side. Retry with backoff, then ping us |
TypeScript types
Copy these if you like typed fetches:
export type ApiToken = { address: `0x${string}`; symbol: string; decimals: number }
export type QuoteResponse = {
fromToken: ApiToken
toToken: ApiToken
fromAmount: string
toAmount: string
exchangeRate: string
partnerFeeBps?: number // missing on wrap and unwrap quotes
partnerFeeAmount?: string
route: { dexName: string; poolType: 'v2' | 'v3' | string; poolAddress: `0x${string}` } | string
spender: `0x${string}`
}
export type SwapResponse = {
transaction: { to: `0x${string}`; data: `0x${string}`; value: string; chainId: number }
estimate?: { fromAmount: string; toAmount: string; minAmountOut: string; partnerFeeBps: number }
spender: `0x${string}`
}
export type ApiError = { error: string; message?: string }route is the string "Direct (Wrap/Unwrap)" for wrap and unwrap quotes, and estimate is missing on wrap and
unwrap transactions.