Skip to content

Commit 857d975

Browse files
silva-fjkziemianekKailai-Wang
authored
Implement cross chain swaps (#3364)
* feat(binance): add wallet API functionality * feat(cross-chain): integrate Binance API dependency in the cross-chain executor * feat(cross-chain): integrate BinanceApi in executor * feat(cross-chain): add initial Binance integration Implement initial Binance API integration in the cross-chain executor * cross-order should only be all for cross chain swaps * feat(solana): implement RemoteSigner for transactions Add RemoteSigner implementation that connects to the pumpx signer service for securely signing Solana transactions. * refactor(solana): inject runtime Handle to RemoteSigner Update RemoteSigner implementation to receive a tokio runtime Handle through constructor rather than retrieving it internally. * feat(solana): create independent module for SDK Extract Solana functionality into a dedicated module * feat(solana): implement client for transactions Add SolanaClient implementation that provides functionality for: - Transferring SOL to specified addresses - Transferring SPL tokens between wallets - Managing transaction signing and confirmations - Error handling and logging for transaction failures This extends the Solana module with client capabilities needed for cross-chain swaps and other DeFi operations. * fixing solana exports * refactoring solana client, injecting it to the cross chain intent executor * feat(solana): add SPL token mapping for cross-chain swaps * feat(cross-chain): implement Solana token transfers * feat(cross-chain): implement Binance trading for swaps Add integration with Binance spot trading API for cross-chain swaps: - Expose Binance API types needed for order creation - Implement market order creation with appropriate trading pairs - Add status monitoring to verify order execution - Implement error handling with failure notifications - Support USDC, USDT and SOL pairs with BNB * fixing fmt issue * feat(cross-chain): integrate accounting contract client Add Ethereum accounting contract integration to cross-chain swaps: - Add AccountingContractClient as a dependency to relevant crates - Initialize accounting contract client with Ethereum RPC provider - Set up contract address in executor initialization - Update cross-chain executor to use accounting client - Implement proper type parameters for RPC providers * initial setup accounting contract call * fixing fmt issue * adding more TODO's * determine cross chain payout address * taplo fmt * taplo fmt * remove address * create pumpx market order * calculate binance traded amount * add debug info * fix clippy * use new api * to_address * binance fills with decimals * binance bnb amount received to bnb jagers * add contract adress --------- Co-authored-by: Kasper Ziemianek <[email protected]> Co-authored-by: Kailai-Wang <[email protected]>
1 parent 3d0e3db commit 857d975

File tree

24 files changed

+1377
-113
lines changed

24 files changed

+1377
-113
lines changed

tee-worker/omni-executor/Cargo.lock

Lines changed: 494 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tee-worker/omni-executor/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ members = [
2525
"parentchain/signer",
2626
"pumpx",
2727
"rpc-server",
28+
"solana",
2829
]
2930

3031
resolver = "2"
@@ -59,6 +60,7 @@ regex = "1.7"
5960
reqwest = { version = "0.12", features = ["json"] }
6061
ring = "0.16.20"
6162
rsa = "0.9.7"
63+
rust_decimal = "1.37.1"
6264
scale-encode = "0.10.0"
6365
scale-info = "2.11.6"
6466
secp256k1 = "=0.29.1"
@@ -71,6 +73,7 @@ solana-client = "2.1.5"
7173
solana-sdk = "2.1.5"
7274
sp-core = "35.0.0"
7375
sp-state-machine = { version = "0.44.0", features = ["std"] }
76+
spl-associated-token-account = "6.0.0"
7477
spl-token = "7.0.0"
7578
subxt = "0.38.0"
7679
subxt-core = "0.38.0"
@@ -105,6 +108,7 @@ parentchain-rpc-client = { path = "parentchain/rpc-client" }
105108
parentchain-signer = { path = "parentchain/signer" }
106109
pumpx = { path = "pumpx" }
107110
rpc-server = { path = "rpc-server" }
111+
solana = { path = "solana" }
108112
solana-intent-executor = { path = "intent/executors/solana" }
109113

110114
[workspace.lints.clippy]

tee-worker/omni-executor/binance-api/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
mod convert_api;
22
mod error;
3-
mod spot_trading_api;
3+
pub mod spot_trading_api;
44
mod traits;
55
mod types;
6+
mod wallet_api;
67

78
use convert_api::ConvertApi;
89
use error::Error;
@@ -16,6 +17,7 @@ use std::{
1617
time::{SystemTime, UNIX_EPOCH},
1718
};
1819
use url::Url;
20+
use wallet_api::WalletApi;
1921

2022
const MAX_RECV_WINDOW: u32 = 60000;
2123

@@ -47,6 +49,11 @@ impl BinanceApi {
4749
SpotTradingApi::new(self)
4850
}
4951

52+
/// Create a new WalletApi instance
53+
pub fn wallet(&self) -> WalletApi {
54+
WalletApi::new(self)
55+
}
56+
5057
/// Create HMAC SHA256 signature for request parameters
5158
pub fn sign_request(&self, query_string: &str) -> String {
5259
let mut mac = Hmac::<Sha256>::new_from_slice(self.api_secret.as_bytes())

tee-worker/omni-executor/binance-api/src/spot_trading_api/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
mod types;
1+
pub mod types;
22

33
use crate::{error::Error, traits::TryIntoParams, BinanceApi, Method};
44
use std::collections::HashMap;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
mod types;
2+
3+
use types::{CoinInfo, DepositAddress};
4+
5+
use crate::{error::Error, BinanceApi, Method};
6+
use std::collections::HashMap;
7+
8+
/// https://developers.binance.com/docs/wallet/Introduction
9+
const WALLET_API: &str = "/sapi/v1";
10+
11+
pub struct WalletApi<'a> {
12+
base_api: &'a BinanceApi,
13+
}
14+
15+
impl<'a> WalletApi<'a> {
16+
pub fn new(binance_api: &BinanceApi) -> WalletApi {
17+
WalletApi { base_api: binance_api }
18+
}
19+
20+
/// Get information of coins (available for deposit and withdraw).
21+
pub async fn get_all_coins_info(&self) -> Result<Vec<CoinInfo>, Error> {
22+
let endpoint = format!("{}/capital/config/getall", WALLET_API);
23+
self.base_api.make_signed_request(&endpoint, Method::GET, None, None).await
24+
}
25+
26+
/// Get deposit address with network
27+
pub async fn get_deposit_address(&self, coin: &str, network: &str) -> Result<String, Error> {
28+
let endpoint = format!("{}/capital/deposit/address", WALLET_API);
29+
let mut params = HashMap::new();
30+
params.insert("coin".to_string(), coin.to_string());
31+
params.insert("network".to_string(), network.to_string());
32+
let response: DepositAddress = self
33+
.base_api
34+
.make_signed_request(&endpoint, Method::GET, Some(params), None)
35+
.await?;
36+
Ok(response.address)
37+
}
38+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use serde::Deserialize;
2+
3+
#[derive(Debug, Deserialize)]
4+
#[allow(dead_code)]
5+
pub struct DepositAddress {
6+
pub address: String,
7+
pub coin: String,
8+
pub tag: String,
9+
pub url: String,
10+
}
11+
12+
#[derive(Debug, Clone, Deserialize)]
13+
#[serde(rename_all = "camelCase")]
14+
pub struct CoinInfo {
15+
pub coin: String,
16+
pub deposit_all_enable: bool,
17+
pub free: String,
18+
pub freeze: String,
19+
pub ipoable: String,
20+
pub ipoing: String,
21+
pub is_legal_money: bool,
22+
pub locked: String,
23+
pub name: String,
24+
pub network_list: Vec<NetworkInfo>,
25+
pub storage: Option<String>,
26+
pub trading: Option<bool>,
27+
pub withdraw_all_enable: Option<bool>,
28+
pub withdrawing: Option<String>,
29+
}
30+
31+
#[derive(Debug, Clone, Deserialize)]
32+
#[serde(rename_all = "camelCase")]
33+
pub struct NetworkInfo {
34+
pub address_regex: String,
35+
pub coin: String,
36+
// Optional fields that are only present under certain conditions
37+
pub deposit_desc: Option<String>,
38+
pub deposit_enable: bool,
39+
pub is_default: bool,
40+
pub memo_regex: String,
41+
pub min_confirm: u32,
42+
pub name: String,
43+
pub network: String,
44+
pub special_tips: String,
45+
pub special_withdraw_tips: Option<String>,
46+
pub un_lock_confirm: u32,
47+
pub withdraw_desc: Option<String>,
48+
pub withdraw_enable: bool,
49+
pub withdraw_fee: String,
50+
pub withdraw_integer_multiple: String,
51+
pub withdraw_max: String,
52+
pub withdraw_min: String,
53+
pub withdraw_internal_min: Option<String>,
54+
pub same_address: bool,
55+
pub estimated_arrival_time: u32,
56+
pub busy: bool,
57+
pub contract_address_url: String,
58+
pub contract_address: String,
59+
pub reset_address_status: Option<bool>,
60+
pub deposit_dust: Option<String>,
61+
pub denomination: Option<u64>,
62+
}

tee-worker/omni-executor/executor-primitives/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ pub use auth::*;
2525
pub mod signature;
2626
pub mod utils;
2727
pub use heima_primitives::{
28-
omni::*, teebag::DcapQuote, AccountId, BlockNumber, ChainAsset, Hash, Identity, MrEnclave,
29-
Nonce, ShardIdentifier, Web2IdentityType,
28+
identity::Address32, omni::*, teebag::DcapQuote, AccountId, BlockNumber, ChainAsset, Hash,
29+
Identity, MrEnclave, Nonce, ShardIdentifier, Web2IdentityType,
3030
};
3131
use std::fmt::Debug;
3232

tee-worker/omni-executor/executor-worker/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] }
1515
url = { workspace = true }
1616

1717
# Local dependencies
18+
accounting-contract-client = { workspace = true }
19+
binance-api = { workspace = true }
1820
cross-chain-intent-executor = { workspace = true }
1921
ethereum-intent-executor = { workspace = true }
22+
ethereum-rpc = { workspace = true }
2023
executor-core = { workspace = true }
2124
executor-crypto = { workspace = true }
2225
executor-primitives = { workspace = true }
@@ -29,6 +32,7 @@ parentchain-rpc-client = { workspace = true }
2932
parentchain-signer = { workspace = true }
3033
pumpx = { workspace = true }
3134
rpc-server = { workspace = true }
35+
solana = { workspace = true }
3236
solana-intent-executor = { workspace = true }
3337

3438
[lints]

tee-worker/omni-executor/executor-worker/src/main.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
// along with Litentry. If not, see <https://www.gnu.org/licenses/>.
1616

1717
use crate::cli::Cli;
18+
use accounting_contract_client::AccountingContractClient;
19+
use binance_api::BinanceApi;
1820
use clap::Parser;
1921
use cli::*;
2022
use cross_chain_intent_executor::{Chain, CrossChainIntentExecutor, RpcEndpointRegistry};
@@ -38,8 +40,10 @@ use parentchain_rpc_client::{
3840
ToPrimitiveType,
3941
};
4042
use parentchain_signer::{key_store::SubstrateKeyStore, TxSigner};
43+
use pumpx::signer_client::SignerClient;
4144
use pumpx::PumpxApi;
4245
use rpc_server::{start_server as start_rpc_server, AuthTokenKeyStore};
46+
use solana::SolanaClient;
4347
use solana_intent_executor::SolanaIntentExecutor;
4448
use std::env;
4549
use std::io::Write;
@@ -72,7 +76,6 @@ async fn main() -> Result<(), ()> {
7276

7377
match cli.cmd {
7478
Commands::Run(args) => {
75-
let _binance_api_key = env::var("OE_BINANCE_API_KEY").unwrap_or("".to_string());
7679
let auth_token_key_store =
7780
AuthTokenKeyStore::new(args.auth_token_key_store_path.clone());
7881
let jwt_rsa_private_key = auth_token_key_store.read().expect("Could not read jwt key");
@@ -116,10 +119,11 @@ async fn main() -> Result<(), ()> {
116119
let aes256_key_store = Aes256KeyStore::new(args.aes256_key_store_path.clone());
117120
let aes256_key = aes256_key_store.read().expect("Could not read aes256 key");
118121

119-
let pumpx_signer_client = Arc::new(pumpx::signer_client::SignerClient::new(
120-
args.pumpx_signer_url.clone(),
121-
pumpx_signer_pair,
122-
));
122+
let pumpx_signer_client: Arc<Box<dyn SignerClient>> =
123+
Arc::new(Box::new(pumpx::signer_client::PumpxSignerClient::new(
124+
args.pumpx_signer_url.clone(),
125+
pumpx_signer_pair,
126+
)));
123127

124128
let ethereum_intent_executor =
125129
EthereumIntentExecutor::new(&args.ethereum_url, &args.delegation_contract_address)?;
@@ -139,13 +143,34 @@ async fn main() -> Result<(), ()> {
139143
let pumpx_api_base_url = std::env::var("OE_PUMPX_API_BASE_URL").ok();
140144
let pumpx_api = Arc::new(PumpxApi::new(pumpx_api_base_url));
141145

146+
let binance_api_key = env::var("OE_BINANCE_API_KEY").unwrap_or("".to_string());
147+
let binance_api_secret = env::var("OE_BINANCE_API_SECRET").unwrap_or("".to_string());
148+
let binance_api_base_url = env::var("OE_BINANCE_API_BASE_URL").ok();
149+
let binance_api = Arc::new(BinanceApi::new(
150+
binance_api_key,
151+
binance_api_secret,
152+
binance_api_base_url,
153+
));
154+
155+
let solana_client = Arc::new(SolanaClient::new(&args.solana_url));
156+
157+
let ethereum_rpc_provider = ethereum_rpc::AlloyRpcProvider::new(&args.ethereum_url);
158+
let accounting_contract_client = AccountingContractClient::new(
159+
ethereum_rpc_provider,
160+
//todo: from CLI
161+
"0xb0830ef478a215ed393c20a0c97aa69869a0beea".parse().unwrap(),
162+
);
163+
142164
let cross_chain_intent_executor = CrossChainIntentExecutor::new(
143165
parentchain_rpc_client_factory.clone(),
144166
tx_signer.clone(),
145167
rpc_endpoint_registry,
146168
pumpx_signer_client.clone(),
147169
pumpx_api.clone(),
148170
storage_db.clone(),
171+
binance_api,
172+
solana_client,
173+
Arc::new(accounting_contract_client),
149174
)?;
150175

151176
let intent_id_store: Arc<Box<dyn IntentIdStore>> =

tee-worker/omni-executor/intent/executors/cross-chain/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,15 @@ async-trait = { workspace = true }
99
hex = { workspace = true }
1010
log = { workspace = true }
1111
parity-scale-codec = { workspace = true }
12+
rust_decimal = { workspace = true }
13+
tokio = { workspace = true }
1214

1315
# Local dependencies
16+
accounting-contract-client = { workspace = true }
17+
alloy = { workspace = true }
18+
base58 = { workspace = true }
19+
binance-api = { workspace = true }
20+
ethereum-rpc = { workspace = true }
1421
executor-core = { workspace = true }
1522
executor-primitives = { workspace = true }
1623
executor-storage = { workspace = true }
@@ -21,6 +28,7 @@ parentchain-api-interface = { workspace = true }
2128
parentchain-rpc-client = { workspace = true }
2229
parentchain-signer = { workspace = true }
2330
pumpx = { workspace = true }
31+
solana = { workspace = true }
2432

2533
[lints]
2634
workspace = true

0 commit comments

Comments
 (0)