-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Description OKX dex integration. See also dedicated issue: #93 # Changes Added new `okx` modules in `dex`, `config` and `tests`. Created dto basing on documentation: https://www.okx.com/en-au/web3/build/docs/waas/dex-swap. OKX requires signing of swap request, it is implemented in function: `sign_request()`, basing on documentation: https://www.okx.com/en-au/web3/build/docs/waas/rest-authentication#signature Also implemented custom error handling function: `handle_api_error()`, as OKX in error cases returns valid json http body which causes that trait implementation from `RoundtripError` to `dto::Error` is not used. ## How to test Created dedicated tests which uses http mocking and real endpoint tests (ignored) which requires providing API credentials. If API credentials are needed for running ignored test I can provide that.
- Loading branch information
Showing
18 changed files
with
1,338 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
node-url = "http://localhost:8545" | ||
|
||
[dex] | ||
# Specify which chain to use, 1 for Ethereum. | ||
# More info here: https://www.okx.com/en-au/web3/build/docs/waas/walletapi-resources-supported-networks | ||
chain-id = "1" | ||
|
||
# Optionally specify a custom OKX Swap API endpoint | ||
# endpoint = "https://www.okx.com/api/v5/dex/aggregator/swap" | ||
|
||
# OKX Project ID. Instruction on how to create a project: | ||
# https://www.okx.com/en-au/web3/build/docs/waas/introduction-to-developer-portal-interface#create-project | ||
api-project-id = "$OKX_PROJECT_ID" | ||
|
||
# OKX API Key. Instruction on how to generate an API key: | ||
# https://www.okx.com/en-au/web3/build/docs/waas/introduction-to-developer-portal-interface#generate-api-keys | ||
api-key = "$OKX_API_KEY" | ||
|
||
# OKX Secret key used for signing request. Instruction on how to get a security token: | ||
# https://www.okx.com/en-au/web3/build/docs/waas/introduction-to-developer-portal-interface#view-the-secret-key | ||
api-secret-key = "$OKX_SECRET_KEY" | ||
|
||
# OKX Secret key passphrase. Instruction on how to get a passphrase: | ||
# https://www.okx.com/en-au/web3/build/docs/waas/introduction-to-developer-portal-interface#generate-api-keys | ||
api-passphrase = "$OKX_PASSPHRASE" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
pub mod balancer; | ||
mod file; | ||
pub mod okx; | ||
pub mod oneinch; | ||
pub mod paraswap; | ||
pub mod zeroex; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
use { | ||
crate::{ | ||
domain::eth, | ||
infra::{config::dex::file, dex::okx}, | ||
util::serialize, | ||
}, | ||
serde::Deserialize, | ||
serde_with::serde_as, | ||
std::path::Path, | ||
}; | ||
|
||
#[serde_as] | ||
#[derive(Deserialize)] | ||
#[serde(rename_all = "kebab-case", deny_unknown_fields)] | ||
struct Config { | ||
/// The versioned URL endpoint for the OKX swap API. | ||
#[serde(default = "default_endpoint")] | ||
#[serde_as(as = "serde_with::DisplayFromStr")] | ||
endpoint: reqwest::Url, | ||
|
||
/// Chain ID used to automatically determine contract addresses. | ||
#[serde_as(as = "serialize::ChainId")] | ||
chain_id: eth::ChainId, | ||
|
||
/// OKX API credentials | ||
#[serde(flatten)] | ||
okx_credentials: OkxCredentialsConfig, | ||
} | ||
|
||
#[derive(Deserialize)] | ||
#[serde(rename_all = "kebab-case", deny_unknown_fields)] | ||
struct OkxCredentialsConfig { | ||
/// OKX Project ID. Instruction on how to create a project: | ||
/// https://www.okx.com/en-au/web3/build/docs/waas/introduction-to-developer-portal-interface#create-project | ||
api_project_id: String, | ||
|
||
/// OKX API Key. Instruction on how to generate an API key: | ||
/// https://www.okx.com/en-au/web3/build/docs/waas/introduction-to-developer-portal-interface#generate-api-keys | ||
api_key: String, | ||
|
||
/// OKX Secret key used for signing request. Instruction on how to get a | ||
/// security token: https://www.okx.com/en-au/web3/build/docs/waas/introduction-to-developer-portal-interface#view-the-secret-key | ||
api_secret_key: String, | ||
|
||
/// OKX Secret key passphrase. Instruction on how to get a passphrase: | ||
/// https://www.okx.com/en-au/web3/build/docs/waas/introduction-to-developer-portal-interface#generate-api-keys | ||
api_passphrase: String, | ||
} | ||
|
||
#[allow(clippy::from_over_into)] | ||
impl Into<okx::OkxCredentialsConfig> for OkxCredentialsConfig { | ||
fn into(self) -> okx::OkxCredentialsConfig { | ||
okx::OkxCredentialsConfig { | ||
project_id: self.api_project_id, | ||
api_key: self.api_key, | ||
api_secret_key: self.api_secret_key, | ||
api_passphrase: self.api_passphrase, | ||
} | ||
} | ||
} | ||
|
||
fn default_endpoint() -> reqwest::Url { | ||
"https://www.okx.com/api/v5/dex/aggregator/swap" | ||
.parse() | ||
.unwrap() | ||
} | ||
|
||
/// Load the OKX solver configuration from a TOML file. | ||
/// | ||
/// # Panics | ||
/// | ||
/// This method panics if the config is invalid or on I/O errors. | ||
pub async fn load(path: &Path) -> super::Config { | ||
let (base, config) = file::load::<Config>(path).await; | ||
|
||
super::Config { | ||
okx: okx::Config { | ||
endpoint: config.endpoint, | ||
chain_id: config.chain_id, | ||
okx_credentials: config.okx_credentials.into(), | ||
block_stream: base.block_stream.clone(), | ||
}, | ||
base, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pub mod file; | ||
|
||
pub struct Config { | ||
pub okx: crate::infra::dex::okx::Config, | ||
pub base: super::Config, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
//! DTOs for the OKX swap API. Full documentation for the API can be found | ||
//! [here](https://www.okx.com/en-au/web3/build/docs/waas/dex-swap). | ||
use { | ||
crate::{ | ||
domain::{dex, order}, | ||
util::serialize, | ||
}, | ||
bigdecimal::BigDecimal, | ||
ethereum_types::{H160, U256}, | ||
serde::{Deserialize, Serialize}, | ||
serde_with::serde_as, | ||
}; | ||
|
||
/// A OKX API swap request parameters (only mandatory fields). | ||
/// OKX supports only sell orders. | ||
/// | ||
/// See [API](https://www.okx.com/en-au/web3/build/docs/waas/dex-swap) | ||
/// documentation for more detailed information on each parameter. | ||
#[serde_as] | ||
#[derive(Clone, Default, Serialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct SwapRequest { | ||
/// Chain ID | ||
#[serde_as(as = "serde_with::DisplayFromStr")] | ||
pub chain_id: u64, | ||
|
||
/// Input amount of a token to be sold set in minimal divisible units. | ||
#[serde_as(as = "serialize::U256")] | ||
pub amount: U256, | ||
|
||
/// Contract address of a token to be sent | ||
pub from_token_address: H160, | ||
|
||
/// Contract address of a token to be received | ||
pub to_token_address: H160, | ||
|
||
/// Limit of price slippage you are willing to accept | ||
pub slippage: Slippage, | ||
|
||
/// User's wallet address. Where the sell tokens will be taken from. | ||
pub user_wallet_address: H160, | ||
} | ||
|
||
/// A OKX slippage amount. | ||
#[derive(Clone, Debug, Default, Serialize)] | ||
pub struct Slippage(BigDecimal); | ||
|
||
impl SwapRequest { | ||
pub fn with_domain(self, order: &dex::Order, slippage: &dex::Slippage) -> Option<Self> { | ||
// Buy orders are not supported on OKX | ||
if order.side == order::Side::Buy { | ||
return None; | ||
}; | ||
|
||
Some(Self { | ||
from_token_address: order.sell.0, | ||
to_token_address: order.buy.0, | ||
amount: order.amount.get(), | ||
slippage: Slippage(slippage.as_factor().clone()), | ||
user_wallet_address: order.owner, | ||
..self | ||
}) | ||
} | ||
} | ||
|
||
/// A OKX API swap response - generic wrapper for success and failure cases. | ||
/// | ||
/// See [API](https://www.okx.com/en-au/web3/build/docs/waas/dex-swap) | ||
/// documentation for more detailed information on each parameter. | ||
#[serde_as] | ||
#[derive(Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct SwapResponse { | ||
/// Error code, 0 for success, otherwise one of: | ||
/// [error codes](https://www.okx.com/en-au/web3/build/docs/waas/dex-error-code) | ||
#[serde_as(as = "serde_with::DisplayFromStr")] | ||
pub code: i64, | ||
|
||
/// Response data. | ||
pub data: Vec<SwapResponseInner>, | ||
|
||
/// Error code text message. | ||
pub msg: String, | ||
} | ||
|
||
/// A OKX API swap response. | ||
#[serde_as] | ||
#[derive(Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct SwapResponseInner { | ||
/// Quote execution path. | ||
pub router_result: SwapResponseRouterResult, | ||
|
||
/// Contract related response. | ||
pub tx: SwapResponseTx, | ||
} | ||
|
||
/// A OKX API swap response - quote execution path. | ||
/// Deserializing fields which are only used by the implementation. | ||
/// For all possible fields look into the documentation: | ||
/// [API](https://www.okx.com/en-au/web3/build/docs/waas/dex-swap) | ||
#[serde_as] | ||
#[derive(Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct SwapResponseRouterResult { | ||
/// The information of a token to be sold. | ||
pub from_token: SwapResponseFromToToken, | ||
|
||
/// The information of a token to be bought. | ||
pub to_token: SwapResponseFromToToken, | ||
|
||
/// The input amount of a token to be sold. | ||
#[serde_as(as = "serialize::U256")] | ||
pub from_token_amount: U256, | ||
|
||
/// The resulting amount of a token to be bought. | ||
#[serde_as(as = "serialize::U256")] | ||
pub to_token_amount: U256, | ||
} | ||
|
||
/// A OKX API swap response - token information. | ||
/// Deserializing fields which are only used by the implementation. | ||
/// For all possible fields look into the documentation: | ||
/// [API](https://www.okx.com/en-au/web3/build/docs/waas/dex-swap) | ||
#[serde_as] | ||
#[derive(Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct SwapResponseFromToToken { | ||
/// Address of the token smart contract. | ||
pub token_contract_address: H160, | ||
} | ||
|
||
/// A OKX API swap response - contract related information. | ||
/// Deserializing fields which are only used by the implementation. | ||
/// For all possible fields look into the documentation: | ||
/// [API](https://www.okx.com/en-au/web3/build/docs/waas/dex-swap) | ||
#[serde_as] | ||
#[derive(Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct SwapResponseTx { | ||
/// Estimated amount of the gas limit. | ||
#[serde_as(as = "serialize::U256")] | ||
pub gas: U256, | ||
|
||
/// The contract address of OKX DEX router. | ||
pub to: H160, | ||
|
||
/// Call data. | ||
#[serde_as(as = "serialize::Hex")] | ||
pub data: Vec<u8>, | ||
} | ||
|
||
#[derive(Deserialize)] | ||
pub struct Error { | ||
pub code: i64, | ||
pub reason: String, | ||
} |
Oops, something went wrong.