Integration
Liquidity Provision
LP API

LP API

These docs are under active development. 🚧

The LP API bundle exposes a JSON API that allows liquidity providers to put up orders programmatically through the JIT AMM. It connects to a State Chain node, and handles the complexities of submitting and monitoring extrinsics, allowing for simpler integration.

Please also see the LP RPCs documentation for information on RPCs and subscriptions exposed by the State Chain directly.

Command line arguments

The ws_endpoint should point at a synced RPC node, the signing_key_file should be the private key for their on-chain account, and that account should already be funded.

./chainflip-lp-api --help
chainflip-lp-api
 
USAGE:
    chainflip-lp-api [OPTIONS]
 
OPTIONS:
    -h, --help
            Print help information
 
        --port <PORT>
            The port number on which the LP server will listen for connections. Use 0 to assign a
            random port. [default: 80]
 
        --state_chain.signing_key_file <SIGNING_KEY_FILE>
            A path to a file that contains the LPs secret key for signing extrinsics. 
            [default: /etc/chainflip/keys/signing_key_file]
 
        --state_chain.ws_endpoint <WS_ENDPOINT>
            The state chain nodes RPC endpoint. [default: ws://localhost:9944]

RPC Parameters

Parameters can be encoded as a JSON array or as an object. The advantage of the latter is that it's more explicit and allows for optional values to be omitted.

Addresses

Addresses should be encoded according to their host chains:

  • Ethereum addresses should be encoded as Hex strings, for example "0xfa36e03defc6e4d140cc61fcaab9d1fbef18642f".
  • Polkadot addresses can be encoded using SS58 or Hex strings, for example: "13zyEWmmLDx63Y99TL9SkxBe1DqPVCrcjXytxM3ZHGRyEJV5" or "0x84aec0876dbb3cb7391eeded2eef5fbcf0d1a34f7c9f86f9af205f944b461761"
  • Bitcoin addresses should be encoded using the appropriate bitcoin standard for the address type. For example "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx" is a valid bech32 address on Bitcoin testnet.

Amounts

JSON only supports numbers up to 2^53. Since many tokens are represented as atomic amounts with 18 decimals, this corresponds for around 0.009 ETH!

Therefore, numbers denoting token amount or prices can be specified either as numbers or encoded as big-endian hex.

For example ETH uses 18 decimal places, so 100ETH is 100,000,000,000,000,000,000 Units. This can be only be encoded as a hex string: "0x56bc75e2d63100000"

Another example: USDC uses 6 decimals, so 10USDC is 10,000,000 Units. This fits in a JSON number: 10000000.

Assets

Assets are specified as a { [chain](#chains), asset } object, where the chain is as described below, and the asset is an upper-case string.

Where the chain is unambiguous (for example for the native currencies), the asset can be submitted simply as the upper-case string.

For example, for BTC, "BTC" and { chain: "Bitcoin", asset: "BTC" } are both valid and resolve to the same asset.

Assets returned from the RPCs will always take the explicit form, for example { chain: "Ethereum", asset: "ETH" }

Chains

Chains are specified as the full name of the chain, capitalised, for example "Ethereum", "Bitcoin", "Polkadot".

Order IDs

Order IDs are interpreted as 64-bit integers and as such can be specified using a JSON number, up to 2^53. Alteratively the ID can be encoded as a hex string, up to 8 bytes (16 hex characters) long.

Order IDs are assigned by the LP, are unique within each pool and for each account, and can be re-used.

Order Updates

Changes in order size are communicated via an increase_or_decrease object which has this shape for range orders:

{
  "increase_or_decrease": {
    "increase": {
      "liquidity": <amount>,
      "amounts": {
        "base": <amount>,
        "pair": <amount>
      }
    }
  }
}
// OR for a decrease:
{
  "increase_or_decrease": {
    "decrease": {
      "liquidity": <amount>,
      "amounts": {
        "base": <amount>,
        "pair": <amount>
      }
    }
  }
}

And this shape for limit orders:

{
  "increase_or_decrease": {
    "increase": <amount>
  }
}
// OR for a decrease:
{
  "increase_or_decrease": {
    "decrease": <amount>
  }
}

RPC Methods

lp_register_account

Parameters:

None

Return:

  • null if successful, otherwise an error.

lp_liquidity_deposit

Parameters:

Return:

  • Encoded deposit address that you should send the deposit to.

Example

Request:

curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "lp_liquidity_deposit", "params": ["ETH"]}' http://localhost:10589

Response:

{"jsonrpc":"2.0","result":"0x56bd3d36a3f7186d8b5aa24baca687d4fa47b24d","id":1}

lp_register_liquidity_refund_address

Parameters:

  • chain: The external chain as a camel-case string, e.g. "Ethereum" or "Polkadot".
  • address: The refund address for the specified external chain. Any assets associated with that chain will be transferred there if a refund is needed, e.g. "USDC" would be tranferred to the address associated with "Ethereum".

Return:

  • The transaction hash of the extrinsic that registered the new withdrawal address.

Example

Request:

curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "lp_register_liquidity_refund_address", "params": {"chain": "Ethereum", "address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"}}' http://localhost:10589

Response:

{"jsonrpc":"2.0","result":"0x006595fa7c1010fece1835c91cfb24971eebe3fa75c587b6b4a2b4b5e6dd7387","id":1}

lp_withdraw_asset

Parameters:

  • asset_amount: Asset amount to be withdrawn as u128.
  • asset: Withdrawn asset.
  • destination_address: The address to which to send the withdrawn funds. The format depends on the asset's destination chain.

Return:

Egress id, which is used as the identifier for the operation/s to egress/withdraw the requested funds.

Example

  • Request

    curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "lp_withdraw_asset", "params": [1000, "USDC", "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"]}' http://localhost:10589
  • Response

    {"jsonrpc":"2.0","result":["Ethereum",48],"id":1}

lp_update_range_order

Parameters:

  • base_asset: Base Asset.
  • pair_asset: Pair Asset.
  • id: Numerical Order ID.
  • tick_range: (Optional) A JSON array of two JSON Integers in the range [-887272, 887272], representing the lower and upper bound of the order's price range. If not specified, the previous tick range of this order id will be used.
  • increase_or_decrease: "Increase" or "Decrease", depending on whether the order size should be increased or decreased.
  • size: A JSON object specifying the change in order size. There are two different ways to provide this:
    1. {"Liquidity": {"liquidity": <liquidity>}} where <liquidity> is an amount specifying the size of the order in microUSDC.
    2. {"AssetAmounts":{"maximum":{"base": <amount>, "pair": <amount>}, "minimum":{"base": <amount>, "pair: <amount>}}} where the <amounts> specify the size of the order in smallest units of the respective asset (base or pair), e.g. For Bitcoin it is in Satoshis. Using "AssetAmounts", the system will try to the change the order by an amount of assets between the specified maxima and minima, subject to available liquidity. If you would not like to change the size of the order you can specify zero values using either "Liquidity" or "AssetAmounts".

Return:

A chronological list of all the updates that were done as part of the operation. Each item in the list is a JSON object:

{
  "base_asset": <asset>,
  "pair_asset": <asset>,
  "id": <order_id>,
  "tick_range": [<tick>, <tick>], 
  "liquidity_total": <liquidity>, 
  "collected_fees": { "base": <amount> , "pair": <amount> }, 
  "size_change": <increase_or_decrease>,
}

For example if a lp_update_range_order request moves an existing range order to a new tick_range, the return would contain two of these, one for the decrease to zero/destruction of the order at the previous tick range, and then one for the increase/creation of the order at the new tick range.

lp_set_range_order

Parameters:

  • base_asset: Base Asset.
  • pair_asset: Pair Asset.
  • id: Numerical Order ID.
  • tick_range: (Optional) A JSON array of two integers in the range [-887272, 887272], representing the lower and upper bound of the order's price range. If not specified, the previous tick range of this order id will be used.
  • size: A JSON object specifying the new size of the order. This can be provided in two different ways:
    1. {"Liquidity": <liquidity>} where <liquidity> is an amount specifying the size of the order in microUSDC.
    2. {"AssetAmounts":{"maximum":{"base": <amount>, "pair": <amount>}, "minimum":{"base": <amount>, "pair: <amount>}}} where the <amounts> specify the size of the order in smallest units of the respective asset (base or pair), e.g. For Bitcoin it is in Satoshis. Using "AssetAmounts", the system will try to the create an order that consumes an amount of assets between the specified maxima and minima, subject to available liquidity. If you would like to close the order you can specify zero values using either "Liquidity" or "AssetAmounts".

Return:

A chronological list of all the updatesupdates that were done as part of the operation. Each item in the list is a JSON object:

{
  "base_asset": <asset>,
  "pair_asset": <asset>,
  "id": <order_id>,
  "tick_range": [<tick>, <tick>], 
  "liquidity_total": <liquidity>, 
  "collected_fees": { "base": <amount> , "pair": <amount> }, 
  "size_change": <increase_or_decrease>,
}

For example if a lp_set_range_order request changes the total size of an existing range order, the return would contain two of these, one for the decrease to zero/destruction of the previous order, and then one for the increase/creation of the order with the new size.

lp_update_limit_order

Update a limit order by increasing or decreasing its size.

Parameters:

  • sell_asset: Sell Asset.
  • buy_asset: Buy Asset.
  • id: Numerical Order ID.
  • tick: (Optional) Price tick in the range [-887272, 887272]. If not specified the previous tick of the order id will be used.
  • increase_or_decrease: "Increase" or "Decrease", depending on whether the order size should be increased or decreased.
  • amount: The desired change in size of the order, expressed as an amount.

Return:

A chronological list of all the updates that were made as a result of the operation. Each item in the list is a JSON object:

Note that during the order's lifetime, swaps may be executed against it, and this results in quantities of the buy_asset accumulating. These are swept into the free balance as a result of any update to any order in the same pool. This swept amount is what bought_amount refers to.

{
  "sell_asset": <asset>,
  "buy_asset": <asset>,
  "id": <order_id>,
  "tick": <tick>,
  "amount_total": <amount>,
  "collected_fees": <amount>,
  "bought_amount": <amount>,
  "amount_change": <increase_or_decrease>,
}

For example if an lp_update_limit_order request moves the limit order, the return would contain two of these, one for the decrease to zero/destruction of the previous order, and then one for the increase/creation of the order with the price/tick.

Example:

  • Request:
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "lp_update_limit_order", "params": {"sell_asset": "ETH", "buy_asset": {"chain": "Ethereum", "asset": "USDC"}, "id": "1", "tick": 100, "increase_or_decrease": "Decrease", 1 }}' http://localhost:10589
  • Response:
{
  "jsonrpc":"2.0",
  "result":[
    {
      "sell_asset": { chain: "Ethereum", "asset": "ETH" },
      "buy_asset": { chain: "Ethereum", "asset": "USDC" },
      "tick":100,
      "amount_total":0,
      "collected_fees":0,
      "bought_amount":0,
      "amount_change":[
        "Decrease",
        1
      ]
    }
  ],
  "id":1
}

lp_set_limit_order

Parameters:

  • sell_asset: Sell Asset as a camel-case string, e.g. "Eth" or "Dot".
  • buy_asset: Buy Asset as a camel-case string, e.g. "Eth" or "Dot".
  • id: Numerical Order ID.
  • tick: (Optional) Price tick in the range [-887272, 887272]. If not specified the previous tick of the order id will be used.
  • amount: The desired change in size of the order, expressed as an amount.

Return:

  • A chronological list of all the updates that were made as part of the operation. Each item in the list is a JSON object:
{
  "sell_asset": <asset>,
  "buy_asset": <asset>,
  "id": <order_id>,
  "tick": <tick>,
  "amount_total": <amount>,
  "collected_fees": <amount>,
  "bought_amount": <amount>,
  "amount_change": <increase_or_decrease>,
}

For example if a lp_set_limit_order request moves the limit order, the return would contain two of these, one for the decrease to zero/destruction of the previous order, and then one for the increase/creation of the order with the price/tick.

Example:

Imagine an order with 1 exists at tick -216338.

  • Request:
curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "lp_set_limit_order", "params": ["sell_asset": "ETH", "buy_asset": "USDC", "id": "1", "tick": 100, 1]}' http://localhost:10589
  • Response:
{
  "jsonrpc":"2.0",
  "result":[
    {
      "sell_asset": { chain: "Ethereum", "asset": "ETH" },
      "buy_asset": { chain: "Ethereum", "asset": "USDC" },
      "tick":-216338,
      "amount_total":0,
      "collected_fees":0,
      "bought_amount":0,
      "amount_change":[
        "Decrease",
        1
      ]
    },
    {
      "sell_asset": { chain: "Ethereum", "asset": "ETH" },
      "buy_asset": { chain: "Ethereum", "asset": "USDC" },
      "tick":100,
      "amount_total":1,
      "collected_fees":0,
      "bought_amount":0,
      "amount_change":[
        "Increase",
        1
      ]
    }
  ],
  "id":1
}

lp_asset_balances

Parameters:

None

Return:

  • An JSON object where each key is a Chain, and the values are arrays of { asset, balance } pairs.

Example:

Request:

curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "lp_asset_balances", "params":[]}' http://localhost:10589

Response:

{
  "jsonrpc":"2.0",
  "result":{
    "Ethereum":[
      {"asset":"ETH","balance":19812894985665653779},
      {"asset":"FLIP","balance":1229999999999994975},
      {"asset":"USDC","balance":600042386654}
    ],
    "Polkadot":[
      {"asset":"DOT","balance":10140000010}
    ],
    "Bitcoin":[
      {"asset":"BTC","balance":101099}
    ]
  },
  "id":1
}

lp_get_open_swap_channels

Parameters:

None

Return:

  • All the open swap channels and their associated details in JSON format.

Working Example

  1. Run the LP API server with the following command:
./chainflip-lp-api \
 --state_chain.ws_endpoint ws://localhost:9944 \
 --state_chain.signing_key_file /path/to/my/signing_key \
 --port 80 # or whatever port you want to use

It will print 🎙 Server is listening on 0.0.0.0:80. and continue to run.

  1. In another terminal: Register as an liquidity provider if you are not already.
curl -H "Content-Type: application/json" \
    -d '{"id":1, "jsonrpc":"2.0", "method": "lp_register_account", "params": [0]}' \
    http://localhost:80

Returns {"jsonrpc":"2.0","result":null,"id":1}

  1. Request a liquidity deposit address:
curl -H "Content-Type: application/json" \
    -d '{"id":1, "jsonrpc":"2.0", "method": "lp_liquidity_deposit", "params": ["Eth"]}' \
    http://localhost:80

The response is a hex-encoded deposit address: {"jsonrpc":"2.0","result":"0x350ec3dfd773978277868212d9f1319cbc93a8bf","id":1}.

Limitations

  • It doesn't seem to work with wss, so make sure the address is specified with ws. It should be ok since we're not going to expose this externally.
;