ZaaS GRPC API

GRPC API doc for ZaaS API

Please refer to the following server configuration and proto file for the grpc API. You can use https://buf.build/ along with its plugin https://buf.build/grpc-ecosystem/gateway to generate a grpc client. Refer to https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/clients for some example code.

Download zap.proto:

syntax = "proto3";
package zap.v1;

import "buf/validate/validate.proto";
import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

// Dex is the type of dex to zap into/out of. It uses different enum values from the zap contract.
enum Dex {
  // Unspecified value.
  DEX_UNSPECIFIED = 0;
  // For UniSwap V3.
  DEX_UNISWAPV3 = 2;
  // For PancakeSwap V3.
  DEX_PANCAKESWAPV3 = 3;
  // For Uniswap V2.
  DEX_UNISWAPV2 = 4;
  // For SushiSwap V2.
  DEX_SUSHISWAPV2 = 5;
  // For Curve
  DEX_CURVE = 6;
}

option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  info: {
    title: "Zap Service"
    description: "Zap Service for quickly zapping pool liquidity in a single transaction"
    version: "1.2.0"
    contact: {
      url: "https://discord.gg/kyberswap"
      email: "bd@kyber.network"
    }
  }
  host: "pre-zap-api.kyberengineering.io"
  base_path: "/{chain}"
  schemes: HTTPS
  responses: {
    key: "400"
    value: {
      description: "Invalid Argument"
      schema: {
        json_schema: {ref: "#/definitions/rpcStatus"}
      }
      examples: {
        key: "application/json"
        value:
          '{"code":3, "message":"validation error:\\\\\\\\n'
          ' - pool: missing tokens [Pool.tokens]\\\\\\\\n'
          ' - pool.id: value does not match regex pattern `^0x[0-9A-Za-z]{40}$` [string.pattern]\\\\\\\\n'
          ' - position: value is required [required]\\\\\\\\n'
          ' - token_in[0]: value does not match regex pattern `^0x[0-9A-Za-z]{40}(,0x[0-9A-Za-z]{40})*$` [string.pattern]\\\\\\\\n'
          ' - amount_in[0]: value does not match regex pattern `^\\\\\\\\d+(,\\\\\\\\d+)*$` [string.pattern]\\\\\\\\n'
          ' - fee_address: value does not match regex pattern `^0x[0-9A-Za-z]{40}$` [string.pattern]"}'
      }
    }
  }
  responses: {
    key: "404"
    value: {
      description: "Not Found"
      schema: {
        json_schema: {ref: "#/definitions/rpcStatus"}
      }
      examples: {
        key: "application/json"
        value: '{"code":5, "message":"failed to get zap routes: cannot swap tokens [0xE2035f04040A135c4dA2f96AcA742143c57c79F9]"}'
      }
    }
  }
};

// Service allows getting and building zap routes.
service Service {
  // Get the best zap-in route.
  rpc GetInRoute(GetInRouteRequest) returns (GetInRouteResponse) {
    option (google.api.http) = {get: "/api/v1/in/route"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      parameters: {
        headers: {
          name: "X-Client-Id"
          description: "Client Id"
          type: STRING
        }
        headers: {
          name: "X-Request-Id"
          description: "Request Id"
          type: STRING
        }
      }
    };
  }
  // Decode zap-in route for debugging purposes.
  rpc DecodeInRoute(DecodeInRouteRequest) returns (DecodeInRouteResponse) {
    option (google.api.http) = {
      post: "/api/v1/in/route/decode"
      body: "*"
    };
  }
  // Build encoded data for the specified zap-in route.
  rpc BuildInRoute(BuildInRouteRequest) returns (BuildInRouteResponse) {
    option (google.api.http) = {
      post: "/api/v1/in/route/build"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      parameters: {
        headers: {
          name: "X-Client-Id"
          description: "Client Id"
          type: STRING
        }
        headers: {
          name: "X-Request-Id"
          description: "Request Id"
          type: STRING
        }
      }
    };
  }

  // Get the best zap-migrate route.
  rpc GetMigrateRoute(GetMigrateRouteRequest) returns (GetMigrateRouteResponse) {
    option (google.api.http) = {get: "/api/v1/migrate/route"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      parameters: {
        headers: {
          name: "X-Client-Id"
          description: "Client Id"
          type: STRING
        }
        headers: {
          name: "X-Request-Id"
          description: "Request Id"
          type: STRING
        }
      }
      responses: {
        key: '200'
        value: {
          description: "OK"
          examples: {
            key: 'application/json'
            value: '{"code":0,"data":{}}'
          }
        }
      }
    };
  }
  // Decode zap-migrate route for debugging purposes.
  rpc DecodeMigrateRoute(DecodeMigrateRouteRequest) returns (DecodeMigrateRouteResponse) {
    option (google.api.http) = {
      post: "/api/v1/migrate/route/decode"
      body: "*"
    };
  }
  // Build encoded data for the specified zap-migrate route.
  rpc BuildMigrateRoute(BuildMigrateRouteRequest) returns (BuildMigrateRouteResponse) {
    option (google.api.http) = {
      post: "/api/v1/migrate/route/build"
      body: "*"
    };
  }
}

// Get the best zap-in route.
message GetInRouteRequest {
  // which dex to use zap with
  Dex dex = 1;
  // the pool to zap into
  Pool pool = 2 [(buf.validate.field).required = true];
  // position details
  Position position = 3 [(buf.validate.field).required = true];
  // which token(s) to use as zap source. also accepts comma separated addresses
  repeated string tokens_in = 4 [(buf.validate.field).repeated.items.string.pattern = "^0x[0-9A-Za-z]{40}(,0x[0-9A-Za-z]{40})*$"];
  // amount(s) to zap including fee, corresponding to tokenIn. also accepts comma separated amounts.
  repeated string amounts_in = 5 [(buf.validate.field).repeated.items.string.pattern = "^\\d+(,\\d+)*$"];
  // which token(s) to use as zap source. also accepts comma separated addresses.
  // deprecated: use tokens_in. if both fields are specified, they are combined
  repeated string token_in = 14 [(buf.validate.field).repeated.items.string.pattern = "^0x[0-9A-Za-z]{40}(,0x[0-9A-Za-z]{40})*$"];
  // amount(s) to zap including fee, corresponding to tokenIn. also accepts comma separated amounts.
  // deprecated: use amounts_in. if both fields are specified, they are combined
  repeated string amount_in = 15 [(buf.validate.field).repeated.items.string.pattern = "^\\d+(,\\d+)*$"];
  option (buf.validate.message).cel = {
    id: "GetInRouteRequest.tokens_in"
    message: "missing tokens_in"
    expression: "has(this.token_in) || has(this.tokens_in)"
  };
  option (buf.validate.message).cel = {
    id: "GetInRouteRequest.amounts_in"
    message: "missing amounts_in"
    expression: "has(this.amount_in) || has(this.amounts_in)"
  };
  // aggregator options
  AggregatorOptions aggregator_options = 6;
  // the address of the fee recipient.
  string fee_address = 7 [(buf.validate.field) = {
    string: {pattern: "^0x[0-9A-Za-z]{40}$"}
    ignore: IGNORE_IF_UNPOPULATED
  }];
  // fee percentage in per cent mille (0.001% or 1 in 100,000). Ignored if feeAddress is empty.
  // From 0 to 100,000 inclusively. Example: 1 for 0.001%.
  uint32 fee_pcm = 8 [(buf.validate.field).uint32 = {
    gte: 0
    lte: 100000
  }];
  // maximum slippage tolerance in basis points (0.01%), used for aggregator (exceeding which the transaction will
  // revert) and pool swap during zap (for additional zapping and for refund).
  // From 0 to 10,000 inclusively. Example: 1 for 0.01%.
  uint32 slippage = 9 [(buf.validate.field).uint32 = {
    gte: 0
    lte: 10000
  }];
}

// options for getting aggregator routes
message AggregatorOptions {
  // whether to disable swapping with the aggregator
  bool disable = 1;
  // comma-separated list of sources to use for aggregator
  string included_sources = 2;
  // comma-separated list of sources to exclude for aggregator
  string excluded_sources = 3;
}

// Pool describes the pool to zap into.
message Pool {
  // id of the pool to zap into.
  string id = 1 [(buf.validate.field).string.pattern = "^0x[0-9A-Za-z]{40}$"];
}

// Position describes either an existing position or a new one.
message Position {
  option (buf.validate.message).cel = {
    id: "position.ticks_check"
    message: "tick_lower must be less than tick_upper"
    expression: "!(has(this.tick_lower) || has(this.tick_upper)) || this.tick_lower < this.tick_upper"
  };
  // id of the position to add liquidity to; omit to create a new uniswapV3 position. for uniswapV2 this is user address
  optional string id = 1;
  // min tick of the position, required if creating a new uniswapV3 position.
  optional sint32 tick_lower = 2;
  // max tick of the position, required if creating a new uniswapV3 position.
  optional sint32 tick_upper = 3;
}

// Returns the best route to zap-in to the specified pool position.
message GetInRouteResponse {
  // grpc error code
  int32 code = 1;
  // grpc error message
  string message = 2;
  // response data
  Data data = 3;
  // request trace id
  string request_id = 4;

  // Encompasses returned data.
  message Data {
    PoolDetails pool_details = 1;

    PositionDetails position_details = 2;

    // zap details
    ZapDetails zap_details = 3;

    // the zap route to pass to build API to get call-data
    bytes route = 4;

    // the router address to check approval amount
    string router_address = 5;

    // rough estimate of gas required for the transaction
    string gas = 6;
    // USD value of estimated gas required
    string gas_usd = 7;
  }
}

// details of the pool
message PoolDetails {
  string category = 1;
  oneof pool {
    UniswapV3 uniswap_v3 = 8;
    UniswapV2 uniswap_v2 = 9;
  }
  // details of the uniswapV3 pool
  message UniswapV3 {
    // pool tick before zap
    optional sint32 tick = 1;
    // pool tick after zap
    optional sint32 new_tick = 2;
    // pool sqrt price (times 2^96) before zap
    optional string sqrt_p = 3;
    // pool sqrt price (times 2^96) after zap
    optional string new_sqrt_p = 4;
  }
  // details of the uniswapV2 pool
  message UniswapV2 {
    // reserve0 before zap
    optional string reserve0 = 1;
    // reserve0 after zap
    optional string new_reserve0 = 2;
    // reserve1 before zap
    optional string reserve1 = 3;
    // reserve1 after zap
    optional string new_reserve1 = 4;
  }
}

// details of the new position state
message PositionDetails {
  // how much position liquidity to be removed
  string removed_liquidity = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field).pattern = "\\d+"];
  // total USD value of the position to be removed
  string removed_amount_usd = 2;
  // how much position liquidity to be added
  string added_liquidity = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field).pattern = "\\d+"];
  // total USD value of the position to be added
  string added_amount_usd = 4;
}

// details of the zap
message ZapDetails {
  // USD value of the source zap token amount
  string initial_amount_usd = 1;
  // list of zap actions
  repeated Action actions = 2;
  // one of the zap actions, specified by the type field
  message Action {
    ActionType type = 1;
    oneof action {
      FeeAction protocol_fee = 2;
      FeeAction partner_fee = 3;
      SwapAction aggregator_swap = 4;
      SwapAction pool_swap = 5;
      LiquidityAction add_liquidity = 6;
      LiquidityAction remove_liquidity = 7;
      RefundAction refund = 8;
    }
  }
  // type of the zap action
  enum ActionType {
    // Unspecified action
    ACTION_TYPE_UNSPECIFIED = 0;
    // protocol fee
    ACTION_TYPE_PROTOCOL_FEE = 1;
    // partner fee
    ACTION_TYPE_PARTNER_FEE = 2;
    // aggregator swap
    ACTION_TYPE_AGGREGATOR_SWAP = 3;
    // pool swap
    ACTION_TYPE_POOL_SWAP = 4;
    // add liquidity
    ACTION_TYPE_ADD_LIQUIDITY = 5;
    // remove liquidity
    ACTION_TYPE_REMOVE_LIQUIDITY = 6;
    // refund
    ACTION_TYPE_REFUND = 7;
  }
  // fee collection
  message FeeAction {
    // fee per cent mille (0.001%) of the source zap amount
    uint32 pcm = 1;
    // token amounts
    repeated TokenAmount tokens = 2;
  }
  // token swap, either with aggregator or with pool
  message SwapAction {
    repeated Swap swaps = 1;
    // a single swap
    message Swap {
      // swapped token amount
      TokenAmount token_in = 1;
      // returned token amount
      TokenAmount token_out = 2;
    }
  }
  // added or removed liquidity
  message LiquidityAction {
    // added or removed token amounts
    repeated TokenAmount tokens = 1;
    // collected fees
    repeated TokenAmount fees = 2;
    // added or removed token 0 amount. deprecated: use tokens
    TokenAmount token0 = 3;
    // added or removed token 1 amount. deprecated: use tokens
    TokenAmount token1 = 4;
  }
  // refund left-over tokens to user
  message RefundAction {
    // refunded token amounts
    repeated TokenAmount tokens = 1 [(buf.validate.field).repeated.items.required = true];
  }
  // token address and amount in wei and in usd
  message TokenAmount {
    // token address
    string address = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field).pattern = "^0x[0-9A-Za-z]{40}$"];
    // wei amount of the token
    string amount = 2;
    // USD value of the token
    string amount_usd = 3;
  }
  // USD value of the final amount including the added position and the left-over amount
  string final_amount_usd = 3;
  // price impact after zapping of final amount against initial amount
  optional float price_impact = 4;
}

// Decode zap-in route for debugging purposes.
message DecodeInRouteRequest {
  // the route as returned from get-route endpoint.
  bytes route = 1;
}

// Returns the zap-in route details.
message DecodeInRouteResponse {
  // grpc error code
  int32 code = 1;
  // grpc error message
  string message = 2;
  // response data
  Data data = 3;
  // request trace id
  string request_id = 4;

  // Encompasses returned data.
  message Data {
    // JSON encode of the zap in route.
    string json = 1;
  }
}

// Build encoded data for zap-in transaction from the specified route.
message BuildInRouteRequest {
  // the wallet sending the transaction, and thus, the tokens.
  string sender = 1 [(buf.validate.field).string.pattern = "^0x[0-9A-Za-z]{40}$"];
  // the wallet receiving the new position. default to sender if empty.
  string recipient = 2 [(buf.validate.field) = {
    string: {pattern: "^0x[0-9A-Za-z]{40}$"}
    ignore: IGNORE_IF_UNPOPULATED
  }];
  // the route as returned from get-route endpoint.
  bytes route = 3;
  // deadline for the swap transaction to execute.
  fixed32 deadline = 4 [(buf.validate.field).cel = {
    id: "deadline.gte_now"
    message: "deadline must be in the future"
    expression: "this == 0u || this > int(now)"
  }];
  // the source of the zap-in transaction.
  string source = 5;
  // map of each token address to its ERC20 permit using EIP-2612 to skip a separate approval step.
  map<string, string> permits = 6 [
    (buf.validate.field).map.keys.string.pattern = "^0x[0-9A-Za-z]{40}$",
    (buf.validate.field).map.values.string.pattern = "^0x[0-9A-Za-z]{448}$"
  ];
}

// Returns the zap-in transaction details.
message BuildInRouteResponse {
  // grpc error code
  int32 code = 1;
  // grpc error message
  string message = 2;
  // response data
  Data data = 3;
  // request trace id
  string request_id = 4;

  // Encompasses returned data.
  message Data {
    // zap router address to send the zap-in transaction to
    string router_address = 1;
    // call data for the zap-in transaction
    string call_data = 2;
    // native token value to transfer with the zap-in transaction in case of zapping with native tokens
    string value = 3;
  }
}

// Get the best zap-migrate route.
message GetMigrateRouteRequest {
  // which dex to zap migrate out from
  Dex dex_from = 10;
  // which dex to zap migrate in to
  Dex dex_to = 1;
  // the pool to zap into
  Pool pool_from = 11 [(buf.validate.field).required = true];
  // the pool to zap into
  Pool pool_to = 2 [(buf.validate.field).required = true];
  // old position details
  Position position_from = 12 [
    (buf.validate.field).required = true,
    (buf.validate.field).cel = {
      id: "position_from.has_id"
      message: "position_from must provide an existing nft id"
      expression: "has(this.id)"
    }
  ];
  // new position details
  Position position_to = 3 [(buf.validate.field).required = true];
  // liquidity amount to withdraw, or empty or 0 to withdraw all
  string liquidity_out = 4 [(buf.validate.field).string.pattern = "^\\d*$"];
  // aggregator options
  AggregatorOptions aggregator_options = 6;
  // options for getting aggregator routes
  // the address of the fee recipient.
  string fee_address = 7 [(buf.validate.field) = {
    string: {pattern: "^0x[0-9A-Za-z]{40}$"}
    ignore: IGNORE_IF_UNPOPULATED
  }];
  // fee percentage in per cent mille (0.001% or 1 in 100,000). Ignored if feeAddress is empty.
  // From 0 to 100,000 inclusively. Example: 1 for 0.001%.
  uint32 fee_pcm = 8 [(buf.validate.field).uint32 = {
    gte: 0
    lte: 100000
  }];
  // maximum slippage tolerance in basis points (0.01%), used for aggregator (exceeding which the transaction will
  // revert) and pool swap during zap (for additional zapping and for refund).
  // From 0 to 10,000 inclusively. Example: 1 for 0.01%.
  uint32 slippage = 9 [(buf.validate.field).uint32 = {
    gte: 0
    lte: 10000
  }];
}

// Returns the best route to zap-migrate from an existing position to the specified pool position.
message GetMigrateRouteResponse {
  // grpc error code
  int32 code = 1;
  // grpc error message
  string message = 2;
  // response data
  Data data = 3;
  // request trace id
  string request_id = 4;

  // Encompasses returned data.
  message Data {
    PoolDetails pool_details = 1;

    PositionDetails position_details = 2;

    // zap details
    ZapDetails zap_details = 3;

    // the zap route to pass to build API to get call-data
    bytes route = 4;

    // the router address to check approval amount
    string router_address = 5;

    // rough estimate of gas required for the transaction
    string gas = 6;
    // USD value of estimated gas required
    string gas_usd = 7;
  }
}

// Decode zap-migrate route for debugging purposes.
message DecodeMigrateRouteRequest {
  // the route as returned from get-route endpoint.
  bytes route = 1;
}

// Returns the zap-migrate route details.
message DecodeMigrateRouteResponse {
  // grpc error code
  int32 code = 1;
  // grpc error message
  string message = 2;
  // response data
  Data data = 3;
  // request trace id
  string request_id = 4;

  // Encompasses returned data.
  message Data {
    // JSON encode of the zap in route.
    string json = 1;
  }
}

// Build encoded data for zap-migrate transaction from the specified route.
message BuildMigrateRouteRequest {
  // the wallet sending the transaction, and thus, the tokens.
  string sender = 1 [(buf.validate.field).string.pattern = "^0x[0-9A-Za-z]{40}$"];
  // the wallet receiving the new position. default to sender if empty.
  string recipient = 2 [(buf.validate.field) = {
    string: {pattern: "^0x[0-9A-Za-z]{40}$"}
    ignore: IGNORE_IF_UNPOPULATED
  }];
  // the route as returned from get-route endpoint.
  bytes route = 3;
  // deadline for the swap transaction to execute.
  fixed32 deadline = 4 [(buf.validate.field).cel = {
    id: "deadline.gte_now"
    message: "deadline must be in the future"
    expression: "this == 0u || this > int(now)"
  }];
  // the source of the zap-migrate transaction.
  string source = 5;
  // whether to throw away the position NFT or keep it.
  bool burn_nft = 6;
}

// Returns the zap-migrate transaction details.
message BuildMigrateRouteResponse {
  // grpc error code
  int32 code = 1;
  // grpc error message
  string message = 2;
  // response data
  Data data = 3;
  // request trace id
  string request_id = 4;

  // Encompasses returned data.
  message Data {
    // zap router address to send the zap-migrate transaction to
    string router_address = 1;
    // call data for the zap-migrate transaction
    string call_data = 2;
    // native token value to transfer with the zap-migrate transaction in case of zapping with native tokens
    string value = 3;
  }
}

Last updated