From 64ddf168a0e3708e411e861a6273871df0dd0cbe Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Mon, 5 Feb 2024 13:32:32 +0000 Subject: [PATCH] Switch ICDex over to using `Pool` mode (#5325) --- Cargo.lock | 2 + backend/canisters/market_maker/CHANGELOG.md | 6 ++ .../canisters/market_maker/impl/Cargo.toml | 2 + .../market_maker/impl/src/exchanges/icdex.rs | 80 ++++++++++++++++++- .../impl/src/lifecycle/post_upgrade.rs | 12 +-- .../icdex/api/src/updates/accountConfig.rs | 11 +++ .../icdex/api/src/updates/deposit.rs | 13 +++ .../icdex/api/src/updates/mod.rs | 3 + .../icdex/c2c_client/src/lib.rs | 2 + backend/libraries/icdex_client/src/lib.rs | 36 +-------- 10 files changed, 122 insertions(+), 45 deletions(-) create mode 100644 backend/external_canisters/icdex/api/src/updates/accountConfig.rs create mode 100644 backend/external_canisters/icdex/api/src/updates/deposit.rs diff --git a/Cargo.lock b/Cargo.lock index 38e26b0ddc..4676963c0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3757,6 +3757,8 @@ dependencies = [ "ic-cdk-macros", "ic-cdk-timers", "ic-stable-structures", + "icdex_canister", + "icdex_canister_c2c_client", "icdex_client", "icrc-ledger-types", "icrc_ledger_canister_c2c_client", diff --git a/backend/canisters/market_maker/CHANGELOG.md b/backend/canisters/market_maker/CHANGELOG.md index 1fea89a6c3..1ee401f370 100644 --- a/backend/canisters/market_maker/CHANGELOG.md +++ b/backend/canisters/market_maker/CHANGELOG.md @@ -7,6 +7,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed +- Switch ICDex over to using `Pool` mode ([#5325](https://github.com/open-chat-labs/open-chat/pull/5325)) + +## [[2.0.1044](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1044-market_maker)] - 2024-02-03 + +### Changed + - Log request params when there is an error ([#5320](https://github.com/open-chat-labs/open-chat/pull/5320)) ## [[2.0.1043](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1043-market_maker)] - 2024-02-02 diff --git a/backend/canisters/market_maker/impl/Cargo.toml b/backend/canisters/market_maker/impl/Cargo.toml index 5c9a096890..26cdb55447 100644 --- a/backend/canisters/market_maker/impl/Cargo.toml +++ b/backend/canisters/market_maker/impl/Cargo.toml @@ -23,6 +23,8 @@ ic-cdk = { workspace = true } ic-cdk-macros = { workspace = true } ic-cdk-timers = { workspace = true } ic-stable-structures = { workspace = true } +icdex_canister = { path = "../../../external_canisters/icdex/api" } +icdex_canister_c2c_client = { path = "../../../external_canisters/icdex/c2c_client" } icdex_client = { path = "../../../libraries/icdex_client" } icrc_ledger_canister_c2c_client = { path = "../../../external_canisters/icrc_ledger/c2c_client" } icrc-ledger-types = { workspace = true } diff --git a/backend/canisters/market_maker/impl/src/exchanges/icdex.rs b/backend/canisters/market_maker/impl/src/exchanges/icdex.rs index d77a8630e7..f5c39df287 100644 --- a/backend/canisters/market_maker/impl/src/exchanges/icdex.rs +++ b/backend/canisters/market_maker/impl/src/exchanges/icdex.rs @@ -1,8 +1,12 @@ use crate::exchanges::Exchange; +use crate::read_state; use async_trait::async_trait; use ic_cdk::api::call::CallResult; +use icdex_canister::deposit::Token0OrToken1; use icdex_client::ICDexClient; -use types::{AggregatedOrders, CancelOrderRequest, MakeOrderRequest, Order, TokenInfo}; +use icrc_ledger_types::icrc1::account::Account; +use icrc_ledger_types::icrc1::transfer::TransferArg; +use types::{AggregatedOrders, CancelOrderRequest, CanisterId, MakeOrderRequest, Order, TokenInfo}; #[async_trait] impl Exchange for ICDexClient { @@ -40,3 +44,77 @@ impl 0 { + let _ = icrc_ledger_canister_c2c_client::icrc1_transfer( + chat_ledger_canister_id, + &TransferArg { + from_subaccount: None, + to, + fee: None, + created_at_time: None, + memo: None, + amount: amount.into(), + }, + ) + .await; + + let deposit_args = (Token0OrToken1::Token0, amount.saturating_sub(100_000).into(), None); + let _ = icdex_canister_c2c_client::deposit(dex_canister_id, deposit_args).await; + } + } + + if let Ok(response) = + icrc_ledger_canister_c2c_client::icrc1_balance_of(icp_ledger_canister_id, &Account::from(this_canister_id)).await + { + let amount = u128::try_from(response.0).unwrap().saturating_sub(10_000); + + if amount > 0 { + let _ = icrc_ledger_canister_c2c_client::icrc1_transfer( + icp_ledger_canister_id, + &TransferArg { + from_subaccount: None, + to, + fee: None, + created_at_time: None, + memo: None, + amount: amount.into(), + }, + ) + .await; + + let deposit_args = (Token0OrToken1::Token1, amount.saturating_sub(10_000).into(), None); + let _ = icdex_canister_c2c_client::deposit(dex_canister_id, deposit_args).await; + } + } +} diff --git a/backend/canisters/market_maker/impl/src/lifecycle/post_upgrade.rs b/backend/canisters/market_maker/impl/src/lifecycle/post_upgrade.rs index c5f68ee1b6..b646200d01 100644 --- a/backend/canisters/market_maker/impl/src/lifecycle/post_upgrade.rs +++ b/backend/canisters/market_maker/impl/src/lifecycle/post_upgrade.rs @@ -1,12 +1,12 @@ use crate::lifecycle::{init_env, init_state}; use crate::memory::get_upgrades_memory; -use crate::{mutate_state, Data}; +use crate::{exchanges, Data}; use canister_logger::LogEntry; use canister_tracing_macros::trace; use ic_cdk_macros::post_upgrade; use market_maker_canister::post_upgrade::Args; -use market_maker_canister::{ICDEX_EXCHANGE_ID, ICDEX_EXCHANGE_V2_ID}; use stable_memory::get_reader; +use std::time::Duration; use tracing::info; use utils::cycles::init_cycles_dispenser_client; @@ -26,11 +26,5 @@ fn post_upgrade(args: Args) { info!(version = %args.wasm_version, "Post-upgrade complete"); - // Post release - remove this - mutate_state(|state| { - if let Some(mut config) = state.data.exchange_config.get(&ICDEX_EXCHANGE_ID).cloned() { - config.enabled = false; - state.data.exchange_config.insert(ICDEX_EXCHANGE_V2_ID, config); - } - }); + ic_cdk_timers::set_timer(Duration::ZERO, || ic_cdk::spawn(exchanges::icdex::deposit_funds())); } diff --git a/backend/external_canisters/icdex/api/src/updates/accountConfig.rs b/backend/external_canisters/icdex/api/src/updates/accountConfig.rs new file mode 100644 index 0000000000..a15fbbe447 --- /dev/null +++ b/backend/external_canisters/icdex/api/src/updates/accountConfig.rs @@ -0,0 +1,11 @@ +use candid::CandidType; +use serde::{Deserialize, Serialize}; + +pub type Args = (Mode, bool, Vec); +pub type Response = (); + +#[derive(CandidType, Serialize, Deserialize)] +pub enum Mode { + PoolMode, + TunnelMode, +} diff --git a/backend/external_canisters/icdex/api/src/updates/deposit.rs b/backend/external_canisters/icdex/api/src/updates/deposit.rs new file mode 100644 index 0000000000..6cb8088bfd --- /dev/null +++ b/backend/external_canisters/icdex/api/src/updates/deposit.rs @@ -0,0 +1,13 @@ +use candid::{CandidType, Nat}; +use serde::{Deserialize, Serialize}; + +pub type Args = (Token0OrToken1, Nat, Option<[u8; 32]>); +pub type Response = (); + +#[derive(CandidType, Serialize, Deserialize)] +pub enum Token0OrToken1 { + #[serde(rename = "token0")] + Token0, + #[serde(rename = "token1")] + Token1, +} diff --git a/backend/external_canisters/icdex/api/src/updates/mod.rs b/backend/external_canisters/icdex/api/src/updates/mod.rs index fd019fc1fb..4a665ec099 100644 --- a/backend/external_canisters/icdex/api/src/updates/mod.rs +++ b/backend/external_canisters/icdex/api/src/updates/mod.rs @@ -1,3 +1,6 @@ #[allow(non_snake_case)] +pub mod accountConfig; +#[allow(non_snake_case)] pub mod cancelByTxid; +pub mod deposit; pub mod trade; diff --git a/backend/external_canisters/icdex/c2c_client/src/lib.rs b/backend/external_canisters/icdex/c2c_client/src/lib.rs index 5e907bbce6..406f690792 100644 --- a/backend/external_canisters/icdex/c2c_client/src/lib.rs +++ b/backend/external_canisters/icdex/c2c_client/src/lib.rs @@ -9,5 +9,7 @@ generate_candid_c2c_call_tuple_args!(pending); generate_candid_c2c_call_tuple_args!(stats); // Updates +generate_candid_c2c_call_tuple_args!(accountConfig); generate_candid_c2c_call_tuple_args!(cancelByTxid); +generate_candid_c2c_call_tuple_args!(deposit); generate_candid_c2c_call_tuple_args!(trade); diff --git a/backend/libraries/icdex_client/src/lib.rs b/backend/libraries/icdex_client/src/lib.rs index ef74613463..4ea6e34589 100644 --- a/backend/libraries/icdex_client/src/lib.rs +++ b/backend/libraries/icdex_client/src/lib.rs @@ -1,7 +1,6 @@ use candid::Nat; use ic_cdk::api::call::{CallResult, RejectionCode}; use icdex_canister::{ICDexOrderType, MakeOrderResponse, OrderPrice, OrderQuantity, TradingOrder}; -use icrc_ledger_types::icrc1::transfer::TransferArg; use types::{AggregatedOrders, CancelOrderRequest, CanisterId, MakeOrderRequest, Order, OrderType, TokenInfo}; pub struct ICDexClient { @@ -90,32 +89,6 @@ impl ICDexClient { } pub async fn make_order(&self, order: MakeOrderRequest) -> CallResult<()> { - let (account, nonce) = - icdex_canister_c2c_client::getTxAccount(self.dex_canister_id, (self.this_canister_id.to_string(),)) - .await - .map(|(a, _, n, _)| (a, n))?; - - let (ledger_canister_id, amount) = match order.order_type { - OrderType::Bid => ( - self.quote_token.ledger, - order.amount * order.price / self.base_token_units_per_whole(), - ), - OrderType::Ask => (self.base_token.ledger, order.amount), - }; - icrc_ledger_canister_c2c_client::icrc1_transfer( - ledger_canister_id, - &TransferArg { - from_subaccount: None, - to: account, - fee: None, - created_at_time: None, - memo: None, - amount: amount.into(), - }, - ) - .await? - .map_err(|t| (RejectionCode::Unknown, format!("{t:?}")))?; - let quantity = match order.order_type { OrderType::Bid => OrderQuantity::Buy(order.amount.into(), 0u32.into()), OrderType::Ask => OrderQuantity::Sell(order.amount.into()), @@ -123,14 +96,7 @@ impl ICDexClient { // Convert the price per whole into the price per `smallest_order_size` let price = (order.price * self.smallest_order_size / self.base_token_units_per_whole()).into(); - let args = ( - OrderPrice { price, quantity }, - ICDexOrderType::Limit, - None, - Some(nonce), - None, - None, - ); + let args = (OrderPrice { price, quantity }, ICDexOrderType::Limit, None, None, None, None); match icdex_canister_c2c_client::trade(self.dex_canister_id, args.clone()).await?.0 { MakeOrderResponse::Ok(_) => {