Links

API Access

Direct access for any of the ~5,000 token pairs with Uniswap V3 liquidity on Ethereum & Polygon

Overview

To facilitate smart contract interaction, our API server offers three helpful API calls: choose pool, calculate trade parameters, and review all trades. For direct smart contract interactions, three main solidity functions: create, ping, and close. Deployment addresses: Addresses

Typical flow

To execute a new Limit trade:
  1. 1.
    API call: Choose pool
  2. 2.
    API call: Calculate trade parameters: ticks, liquidity
  3. 3.
    Smart Contract: Create position

Example

Trade 1.3 ETH for CIV @ price of 29146 CIV/ETH on Ethereum (chainId = 1):
  1. 1.
    API call: getPool(WETH/CIV) → returns poolContract 0x2b1b8052eed6467967d047b58b71f8e9ffa057b5
  2. 2.
    API call: evaluateLimitTrade(pool and prices above) → returns tickLower:-102840, tickUpper:-102780, liquidity: 73998408845592650000000
  3. 3.
    Smart Contract: createPos(true [ETH=native token], true [address of WETH>CIV], false [not relayed], <poolContract>, <tickLower>, <tickUpper>, <liquidity>) → opens the position

Javascript example code

Simple example using axios for API calls, Defender Relayers, and ethers JS to submit the transaction. Set as you please the variables tokenGiven, tokenWanted, sendNative, targetAmount, targetPrice:
exports.handler = async function(credentials) {
const provider = new DefenderRelayProvider(credentials);
const network = await provider.getNetwork();
const chainId = network.chainId;
const signer = new DefenderRelaySigner(credentials, provider, { speed: 'fast' });
const civposmgr = new ethers.Contract(getCivPosMgrAddress(chainId), civPosMgrAbi, signer);
let response, linkTarget
let sentTokenTwo = tokenGiven > tokenWanted
try {
linkTarget = 'https://api.civfund.org/getPool/' + tokenGiven + '/' + tokenWanted + '?chainId=' + chainId
response = await fetch(linkTarget, { method: 'GET', headers: { 'Content-Type': 'application/json' }, });
response = await response.json();
} catch (err) { console.log("fetch error", err); }
let targetPool = response.poolContract
try {
linkTarget = 'https://api.civfund.org/evaluateLimitTrade/' + targetPool + '/' + tokenGiven + '/' + tokenWanted + '/' + targetAmount + '/' + targetPrice + '?chainId=' + chainId
response = await fetch(linkTarget, { method: 'GET', headers: { 'Content-Type': 'application/json' }, });
response = await response.json();
} catch (err) { console.log("fetch error", err); }
let amountSent = Math.round( Math.max(response.amount0, response.amount1) ) + 1; //only sending one of the two tokens
let txValue = sendNative ? amountSent : 0
let tx = await civposmgr.createPos(true, sentTokenTwo, false, targetPool, tickLower, tickUpper, liquidity, { value: txValue })
return 'Transaction hash: ' + tx.hash;
}

API calls

Choose pool

The ASR (Auto-Smart-Router) selects the best pool to trade a given token pair based on the volume, liquidity, and fee tier of all the pools available for that pair. Errors if no pool available. For more info, click here.
Average latency: ~500ms. The poolContract output of this API call can be used as direct input to the smart contract createPos function, and also as input to the API call evaluateLimitTrade as detailed below.
NOTE: All API calls require specifying the chainId for the target blockchain as query parameter, 1 for Ethereum and 137 for Polygon. Refer to https://chainlist.org/ for details on chainId settings.
GET /getPool/:tokenGiven/:tokenWanted

Input

  • tokenGiven, contract address of the input token
  • tokenWanted, contract address of the output token
  • chainId, query parameter, 1 for Ethereum and 137 for Polygon

Returns

  • poolContract, contract address of the chosen pool
  • rate, current pool rate of tokenWanted per tokenGiven
  • feeTier, pool fee tier expressed in 10000 x %, for example 0.3% = 3000
  • decimalsFrom, number of contract decimals of the Given token
  • decimalsTo, number of contract decimals of the Wanted token
  • tickCurrent, current pool tick

Usage example

https://api.civfund.org/getPool/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2/0x37fe0f067fa808ffbdd12891c0858532cfe7361d?chainId=1

Result

{"poolContract":"0x2b1b8052eed6467967d047b58b71f8e9ffa057b5","rate":27758.25199344553,"feeTier":"3000","decimalsFrom":"18","decimalsTo":"18","tickCurrent":"-102318","result":"OK"}

Calculate trade parameters

Helps determine the smart contract input. Average latency: ~220ms. The tickLower, tickUpper, liquidity output can be used as direct input to the smart contract createPos function.
GET /evaluateLimitTrade/:pool/:tokenGiven/:tokenWanted/:amountGiven/:targetPrice

Input

  • pool, pool to be traded - for example, from the previous getPool call
  • tokenGiven, contract address of the input token
  • tokenWanted, contract address of the output token
  • amountGiven, amount of tokenGiven traded, expressed in token number
  • targetPrice, target price in tokenWanted per 1 tokenGiven
  • chainId, query parameter, 1 for Ethereum and 137 for Polygon

Returns

  • amount0, number of the first token in the pool (in the correct alphabetical order by contract ID) including all Solidity decimals
  • amount1, number of the second token in the pool
  • tickTarget, target tick based on the specified targetPrice
  • tickLower, lower end of the concentrated tick range
  • tickUpper, upper end of the concentrated tick range
  • liquidity, the amount of liquidity to provide
  • tickCurrent, current tick of the target pool

Usage example

https://api.civfund.org/evaluateLimitTrade/0x2b1b8052eed6467967d047b58b71f8e9ffa057b5/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2/0x37fe0f067fa808ffbdd12891c0858532cfe7361d/1.3/29146.16459265?chai

Result

{"amount0":"0","amount1":"1300000000000000000","tickTarget":"-102806","tickLower":-102840,"tickUpper":-102780,"liquidity":"73998408845592650000000","tickCurrent":-102318,"check":true,"result":"OK"}

Review trades

Status of all trades for a given wallet. Average latency: depends on how many trades the wallet has opened historically. Note: similar information is also available online in easy-to-read format at https://app.civfund.org/your-trades
GET /trades/:wallet

Input

  • wallet, wallet address to be queried
  • chainId, query parameter, 1 for Ethereum and 137 for Polygon

Returns

Array containing, for each trade:
  • token0, contract address of the input token in the trade
  • tokenSymbol0, symbol of the input token in the trade
  • tokenName0, name of the input token in the trade
  • amount0, number of input tokens
  • token1, contract address of the output token in the trade
  • tokenSymbol1, symbol of the output token in the trade
  • tokenName1, name of the output token in the trade
  • amount1, number of output tokens
  • dateOpened, readable date/time of the opening transaction in UTC time
  • dateOpenedRaw, machine date/time of the opening transaction in UTC time
  • dateOpenedDay, readable date of the opening transaction in UTC time
  • dateOpenedTime, readable time of the opening transaction in UTC time
  • dateClosed, readable date/time of the closing transaction in UTC time
  • elapsed, readable time elapsed since opening (if open) or until closing time (if closed)
  • currentAmount0, number of input tokens currently in the position,
  • currentAmount1, number of output tokens currently in the position,
  • status, text describing the current trade status,
  • orderId, ID of the trade,
  • token0Decimals, number of Solidity contract decimals for the input token,
  • token1Decimals, number of Solidity contract decimals for the output token,
  • percentFilled, % of input token already traded - note, this can also go down, read https://docs.civfund.org/civilization/civtrade/building-the-binance-of-defi/your-questions#filled-decreased for more information,
  • targetPrice, target number of output token per input token,
  • invertedPrice, target number of input token per output token,
  • actualPrice, current number of output token per input token,
  • actualInverted, current number of input token per output token,
  • initialPrice, initial number of output token per input token at the time of open,
  • initialInverted, initial number of input token per output token at the time of open,
  • pairName, text describing the pair traded,
  • pairInverted, text describing the pair traded in the inverted direction,
  • openTxn, block explorer link of the opening transaction,
  • closeTxn, block explorer link of the closing transaction (if closed),
  • version, version of CivTrade (1 = legacy or 2 = current),
  • tradeType, type of trade (Faster or Cheaper)
  • feePercent, pool fee tier expressed in 10000 x %, for example 0.3% = 3000

Usage example

https://api.civfund.org/trades/0x46DaD8f630736C7265849422F943efD77CB8714f?chainId=1

Result

[{"token0":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","tokenSymbol0":"ETH","tokenName0":"Ether","amount0":"1.2","token1":"0x37fe0f067fa808ffbdd12891c0858532cfe7361d","tokenSymbol1":"CIV","tokenName1":"Civilization","amount1":"29,845.162","dateOpened":"3 Feb 2022, 13:25:11 UTC","dateOpenedRaw":"2022-02-03T13:25:11.000Z","dateOpenedDay":"3 Feb 2022","dateOpenedTime":"13:25:11 UTC","dateClosed":"6 Feb 2022, 3:10:40 UTC","elapsed":"22 days, 23h:57m,15s","currentAmount0":"1.2","currentAmount1":"0","status":"Closed","orderId":"2","token0Decimals":18,"token1Decimals":18,"percentFilled":"","targetPrice":"25,578.119","invertedPrice":"-","initialPrice":"20,733.438","initialInverted":"-","pairName":"CIV per ETH","pairInverted":"ETH per CIV","openTxn":"https://etherscan.io/tx/0x804f87aaadb56e79172bdf5af538683d4ba7c5931499816e784e3b0d8abe9841","closeTxn":"https://etherscan.io/tx/0xb83dae1ec492db9ddf8a94e7abd9939ef5ad3f32769c3b668aab6007388968ef","version":2,"tradeType":"Cheaper","feePercent":"1%"}, (...) ]

Smart Contract calls

Create

Open a new position. Interface specs:
function createPos(
bool _nativeETH,
bool userSentTokenTwo,
bool relayed,
IUniswapV3Pool _pool,
int24 _tickLower,
int24 _tickUpper,
uint128 _liquidity
)

Input

Parameters, in order:
  1. 1.
    bool _nativeETH, must be true if any of the two tokens is ETH (on Ethereum) or MATIC (on Polygon); false in any other case including WETH or WMATIC. CivTrade Limit does not support ETH<->WETH wrap/unwrap: not a Limit trade, since their ratio is fixed 1:1 - (use CivTrade Market to wrap/unwrap). Maybe useful to know that with DeFi it is always gas-cheaper to trade in/out of WETH rather than ETH, so to trade frequently, consider using WETH. Usage examples:
    1. 1.
      ETH -> CIV: true
    2. 2.
      CIV -> ETH: true
    3. 3.
      WETH -> CIV: false
    4. 4.
      CIV -> WETH: false
    5. 5.
      ETH -> WETH: not allowed
  2. 2.
    bool userSentTokenTwo, must be true if the contract ID of the input token is alphabetically higher than the contract ID of the output token, false otherwise. For example, the Ethereum contract ID of CIV is 0x37fe0f067fa808ffbdd12891c0858532cfe7361d and of WETH is 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 there usage examples:
    1. 1.
      WETH -> CIV: true (sending WETH which is 0xc02 alphabetically higher than CIV 0x37)
    2. 2.
      CIV -> WETH: false (the other way around)
  3. 3.
    bool relayed, used only for “Cheaper” trades. Always set to false otherwise. Usage examples:
    1. 1.
      WETH -> CIV: false
    2. 2.
      CIV -> WETH: false
  4. 4.
    IUniswapV3Pool _pool, target pool address, for example 0x2b1b8052eed6467967d047b58b71f8e9ffa057b5 is the CIV/WETH 0.3% pool. The contract will fail if the pool does not exist, but will not make any assessment to the quality or volume of the target pool. Can be calculated for any token pair using the API call getPool. Usage examples:
    1. 1.
      WETH -> CIV: 0x2b1b8052eed6467967d047b58b71f8e9ffa057b5
    2. 2.
      CIV -> WETH: 0x2b1b8052eed6467967d047b58b71f8e9ffa057b5
  5. 5.
    int24 _tickLower, the lower-end of the tick range. This must be an initialised tick in the pool, at least “tickSpacing” away from the tickUpper. The contract will accept any valid range, error otherwise. Can be calculated for any token pair using the API call evaluateLimitTrade. Usage examples:
    1. 1.
      WETH -> CIV @ 29146: -102840
    2. 2.
      CIV -> WETH @ 29146: 102780
  6. 6.
    int24 _tickUpper, the higher-end of the tick range. Can be calculated for any token pair using the API call evaluateLimitTrade. Usage examples:
    1. 1.
      WETH -> CIV @ 29146: -102780
    2. 2.
      CIV -> WETH @ 29146: 102840
  7. 7.
    uint128 _liquidity, the amount of liquidity to create. The contract will then calculate the correct amounts to debit the wallet with; due to their peculiar behaviour, tax-on-transfer tokens are supported only for purchase (e.g. ETH -> Token) but not sale (e.g. Token -> ETH) unless manually adjusting the liquidity calculation, not recommended. Can be calculated for any token pair using the API call evaluateLimitTrade. Usage examples:
    1. 1.
      1.3 WETH -> CIV @ 29146: 73998408845592650000000
    2. 2.
      1000 CIV -> WETH @ 29146: 56921852958152060000000000
This function emits the event:
event OpenedCivTrade(
uint256 orderId,
address user,
address pool,
bool nativeETH,
bool relayed,
uint256 initialAmount0,
uint256 initialAmount1,
int24 tickLower,
int24 tickUpper,
uint128 liquidity
)
The uint256 orderId is used in all other function calls.
The initialAmount0 / initialAmount1 are the amounts of input tokens debited, including all Solidity decimals. So 2 WETH will show as 2 * 10^18 in the initialAmount, as WETH is a token with 18 decimals.
Note: the amount of input token is calculated, not an explicit input; the transaction will fail if the wallet does not have sufficient funds to create the target liquidity, for example, if the market price moves across the tickLower-tickUpper range before execution - keep at least 0.1% away from the current price to limit this risk.

Ping

Ping an existing position while open.

Interface

function civTrade(uint256 orderId)
returns (
bool nativeETH,
bool userSentTokenTwo,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
address user,
IUniswapV3Pool pool
)
Errors if the orderId is closed or does not exist.

Close

Close an open position manually. The position will auto-close when filled, no need to call this function except to return funds when not yet filled.

Interface

function closePos(uint256 _orderId)
This function emits the event:
event ClosedCivTrade(
uint256 orderId,
bool autoClosed,
uint256 amountReturned0,
uint256 amountReturned1,
uint256 feesPaid0,
uint256 feesPaid1,
bool zeroFee
)
The bool autoClosed is false for manually closed positions.