diff --git a/Makefile b/Makefile index 6335974a..73eeb893 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,9 @@ wasm: wasm-pack build --release --target=web --out-name=zklink-sdk-web --out-dir=web-dist && \ wasm-pack build --release --target=nodejs --out-name=zklink-sdk-node --out-dir=node-dist #wasm-pack build --release --target=bundler --out-name=zklink-bundler-node --out-dir=dist +test_wasm: + cd ${ROOT_DIR}/bindings/wasm && \ + wasm-pack test --firefox --headless -- --test test_rpc run_example_go_%: ${ROOT_DIR}/examples/Golang/%.go diff --git a/bindings/wasm/Cargo.toml b/bindings/wasm/Cargo.toml index 80e781a1..86277e24 100644 --- a/bindings/wasm/Cargo.toml +++ b/bindings/wasm/Cargo.toml @@ -18,6 +18,7 @@ serde-wasm-bindgen = "0.5" getrandom = { version = "0.2.10", features = ["js"] } web-sys = "0.3" hex = "0.4.3" +serde = "1.0.137" reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "rustls-tls"] } [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/bindings/wasm/src/lib.rs b/bindings/wasm/src/lib.rs index 5bb43983..5894b515 100644 --- a/bindings/wasm/src/lib.rs +++ b/bindings/wasm/src/lib.rs @@ -3,7 +3,5 @@ pub mod rpc_client; pub mod rpc_type_converter; pub mod signer; pub mod tx_types; -// pub mod wallet; -// pub mod error; extern crate getrandom; diff --git a/bindings/wasm/src/rpc_client.rs b/bindings/wasm/src/rpc_client.rs index 0f27cd3d..83304a1a 100644 --- a/bindings/wasm/src/rpc_client.rs +++ b/bindings/wasm/src/rpc_client.rs @@ -4,6 +4,7 @@ use jsonrpsee::core::params::ArrayParams; use jsonrpsee::core::traits::ToRpcParams; use jsonrpsee::types::request::Request; use jsonrpsee::types::Id; +use serde::Deserialize; use std::collections::HashMap; use std::str::FromStr; use wasm_bindgen::prelude::wasm_bindgen; @@ -24,6 +25,13 @@ use zklink_sdk_types::signatures::TxLayer1Signature as TypesTxLayer1Signature; use zklink_sdk_types::tx_type::zklink_tx::ZkLinkTx; use zklink_sdk_types::tx_type::zklink_tx::ZkLinkTxType; +#[derive(Deserialize, Clone)] +pub struct ErrMsg { + #[allow(dead_code)] + code: i32, + message: String, +} + macro_rules! rpc_request { ($method:expr,$builder:expr, $server_url:expr, $resp_type: ty) => {{ let params = $builder @@ -47,10 +55,16 @@ macro_rules! rpc_request { let resp = serde_json::from_value::<$resp_type>(result.clone()); match resp { Ok(resp) => Ok(serde_wasm_bindgen::to_value(&resp)?), - Err(_e) => Err(RpcError::ParseJsonError.into()), + Err(e) => Err(RpcError::ParseJsonError(e.to_string()).into()), + } + } else if let Some(&ref error) = res.get("error") { + let err_msg = serde_json::from_value::(error.clone()); + match err_msg { + Ok(msg) => Err(RpcError::GetErrorResult(msg.message).into()), + Err(_) => Err(RpcError::GetErrorResult("Other error response".to_string()).into()), } } else { - Err(RpcError::ParseJsonError.into()) + Err(RpcError::GetErrorResult("Other error response".to_string()).into()) } }}; } diff --git a/bindings/wasm/src/signer.rs b/bindings/wasm/src/signer.rs index 9172d387..8e442339 100644 --- a/bindings/wasm/src/signer.rs +++ b/bindings/wasm/src/signer.rs @@ -1,12 +1,20 @@ use crate::tx_types::change_pubkey::{ChangePubKey, Create2Data}; +use crate::tx_types::forced_exit::ForcedExit; +use crate::tx_types::order_matching::{Order, OrderMatching}; use crate::tx_types::transfer::Transfer; +use crate::tx_types::withdraw::Withdraw; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; use zklink_sdk_interface::signer::Signer as InterfaceSigner; use zklink_sdk_types::basic_types::ZkLinkAddress; use zklink_sdk_types::tx_type::change_pubkey::ChangePubKey as TxChangePubKey; use zklink_sdk_types::tx_type::change_pubkey::Create2Data as ChangePubKeyCreate2Data; +use zklink_sdk_types::tx_type::forced_exit::ForcedExit as TxForcedExit; +use zklink_sdk_types::tx_type::order_matching::{ + Order as TxOrder, OrderMatching as TxOrderMatching, +}; use zklink_sdk_types::tx_type::transfer::Transfer as TxTransfer; +use zklink_sdk_types::tx_type::withdraw::Withdraw as TxWithdraw; use zklink_sdk_types::tx_type::zklink_tx::ZkLinkTx; #[wasm_bindgen] @@ -67,6 +75,38 @@ impl Signer { Ok(serde_wasm_bindgen::to_value(&signature)?) } + #[wasm_bindgen(js_name=createSignedOrder)] + pub fn create_signed_order(&self, order: Order) -> Result { + let inner_order = order.get_inner_order()?; + let mut order: TxOrder = serde_wasm_bindgen::from_value(inner_order)?; + let signed_order = self.inner.sign_order(&mut order)?; + Ok(serde_wasm_bindgen::to_value(&signed_order)?) + } + + #[wasm_bindgen(js_name=signOrderMatching)] + pub fn sign_order_matching(&self, tx: OrderMatching) -> Result { + let inner_tx = tx.get_inner_tx()?; + let order_matching: TxOrderMatching = serde_wasm_bindgen::from_value(inner_tx)?; + let signature = self.inner.sign_order_matching(order_matching)?; + Ok(serde_wasm_bindgen::to_value(&signature)?) + } + + #[wasm_bindgen(js_name=signWithdraw)] + pub fn sign_withdraw(&self, tx: Withdraw, token_symbol: &str) -> Result { + let inner_tx = tx.get_inner_tx()?; + let withdraw: TxWithdraw = serde_wasm_bindgen::from_value(inner_tx)?; + let signature = self.inner.sign_withdraw(withdraw, token_symbol)?; + Ok(serde_wasm_bindgen::to_value(&signature)?) + } + + #[wasm_bindgen(js_name=signForcedExit)] + pub fn sign_forced_exit(&self, tx: ForcedExit) -> Result { + let inner_tx = tx.get_inner_tx()?; + let forced_exit: TxForcedExit = serde_wasm_bindgen::from_value(inner_tx)?; + let signature = self.inner.sign_forced_exit(forced_exit)?; + Ok(serde_wasm_bindgen::to_value(&signature)?) + } + #[wasm_bindgen(js_name=submitterSignature)] pub fn submitter_signature(&self, tx: JsValue) -> Result { let zklink_tx: ZkLinkTx = serde_wasm_bindgen::from_value(tx)?; diff --git a/bindings/wasm/src/tx_types/forced_exit.rs b/bindings/wasm/src/tx_types/forced_exit.rs new file mode 100644 index 00000000..901f997a --- /dev/null +++ b/bindings/wasm/src/tx_types/forced_exit.rs @@ -0,0 +1,66 @@ +use std::str::FromStr; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; +use zklink_sdk_types::basic_types::{BigUint, ZkLinkAddress}; +use zklink_sdk_types::tx_builder::ForcedExitBuilder as TxForcedExitBuilder; +use zklink_sdk_types::tx_type::forced_exit::ForcedExit as ForcedExitTx; + +#[wasm_bindgen] +pub struct ForcedExit { + inner: ForcedExitTx, +} + +#[wasm_bindgen] +impl ForcedExit { + pub fn get_inner_tx(&self) -> Result { + Ok(serde_wasm_bindgen::to_value(&self.inner)?) + } +} + +#[wasm_bindgen] +pub struct ForcedExitBuilder { + inner: TxForcedExitBuilder, +} + +#[wasm_bindgen] +impl ForcedExitBuilder { + #[wasm_bindgen(constructor)] + pub fn new( + to_chain_id: u8, + initiator_account_id: u32, + initiator_sub_account_id: u8, + target_sub_account_id: u8, + target: String, + l2_source_token: u32, + l1_target_token: u32, + exit_amount: String, + initiator_nonce: u32, + ts: u32, + ) -> Result { + let inner = TxForcedExitBuilder { + to_chain_id: to_chain_id.into(), + initiator_account_id: initiator_account_id.into(), + initiator_sub_account_id: initiator_sub_account_id.into(), + target: ZkLinkAddress::from_hex(&target)?, + l2_source_token: l2_source_token.into(), + timestamp: ts.into(), + l1_target_token: l1_target_token.into(), + initiator_nonce: initiator_nonce.into(), + target_sub_account_id: target_sub_account_id.into(), + exit_amount: BigUint::from_str(&exit_amount).unwrap(), + }; + Ok(ForcedExitBuilder { inner }) + } + + #[wasm_bindgen] + pub fn build(self) -> ForcedExit { + ForcedExit { + inner: ForcedExitTx::new(self.inner), + } + } +} + +#[wasm_bindgen(js_name=newForcedExit)] +pub fn new_forced_exit(builder: ForcedExitBuilder) -> ForcedExit { + builder.build() +} diff --git a/bindings/wasm/src/tx_types/mod.rs b/bindings/wasm/src/tx_types/mod.rs index 21c79913..bcb8e962 100644 --- a/bindings/wasm/src/tx_types/mod.rs +++ b/bindings/wasm/src/tx_types/mod.rs @@ -1,2 +1,5 @@ pub mod change_pubkey; +pub mod forced_exit; +pub mod order_matching; pub mod transfer; +pub mod withdraw; diff --git a/bindings/wasm/src/tx_types/order_matching.rs b/bindings/wasm/src/tx_types/order_matching.rs new file mode 100644 index 00000000..c27ae35e --- /dev/null +++ b/bindings/wasm/src/tx_types/order_matching.rs @@ -0,0 +1,108 @@ +use std::str::FromStr; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; +use zklink_sdk_types::basic_types::BigUint; +use zklink_sdk_types::tx_builder::OrderMatchingBuilder as TxOrderMatchingBuilder; +use zklink_sdk_types::tx_type::order_matching::{ + Order as OrderTx, OrderMatching as OrderMatchingTx, +}; +#[wasm_bindgen] +pub struct Order { + inner: OrderTx, +} + +#[wasm_bindgen] +pub struct OrderMatching { + inner: OrderMatchingTx, +} +#[wasm_bindgen] +impl Order { + #[wasm_bindgen(constructor)] + pub fn new( + account_id: u32, + sub_account_id: u8, + slot_id: u32, + nonce: u32, + base_token_id: u32, + quote_token_id: u32, + amount: String, + price: String, + is_sell: bool, + fee_ratio1: u8, + fee_ratio2: u8, + ) -> Order { + Order { + inner: OrderTx { + account_id: account_id.into(), + sub_account_id: sub_account_id.into(), + slot_id: slot_id.into(), + nonce: nonce.into(), + base_token_id: base_token_id.into(), + quote_token_id: quote_token_id.into(), + amount: BigUint::from_str(&amount).unwrap(), + price: BigUint::from_str(&price).unwrap(), + is_sell: is_sell as u8, + fee_ratio1, + fee_ratio2, + signature: Default::default(), + }, + } + } + + pub fn get_inner_order(&self) -> Result { + Ok(serde_wasm_bindgen::to_value(&self.inner)?) + } +} + +#[wasm_bindgen] +impl OrderMatching { + pub fn get_inner_tx(&self) -> Result { + Ok(serde_wasm_bindgen::to_value(&self.inner)?) + } +} + +#[wasm_bindgen] +pub struct OrderMatchingBuilder { + inner: TxOrderMatchingBuilder, +} + +#[wasm_bindgen] +impl OrderMatchingBuilder { + #[wasm_bindgen(constructor)] + pub fn new( + account_id: u32, + sub_account_id: u8, + taker: JsValue, + maker: JsValue, + fee: String, + fee_token: u32, + expect_base_amount: String, + expect_quote_amount: String, + ) -> Result { + let maker: OrderTx = serde_wasm_bindgen::from_value(maker)?; + let taker: OrderTx = serde_wasm_bindgen::from_value(taker)?; + let inner = TxOrderMatchingBuilder { + account_id: account_id.into(), + sub_account_id: sub_account_id.into(), + taker, + fee: BigUint::from_str(&fee).unwrap(), + fee_token: fee_token.into(), + expect_base_amount: BigUint::from_str(&expect_base_amount).unwrap(), + maker, + expect_quote_amount: BigUint::from_str(&expect_quote_amount).unwrap(), + }; + Ok(OrderMatchingBuilder { inner }) + } + + #[wasm_bindgen] + pub fn build(self) -> OrderMatching { + OrderMatching { + inner: OrderMatchingTx::new(self.inner), + } + } +} + +#[wasm_bindgen(js_name=newOrderMatching)] +pub fn new_order_matching(builder: OrderMatchingBuilder) -> OrderMatching { + builder.build() +} diff --git a/bindings/wasm/src/tx_types/withdraw.rs b/bindings/wasm/src/tx_types/withdraw.rs new file mode 100644 index 00000000..5e19ade6 --- /dev/null +++ b/bindings/wasm/src/tx_types/withdraw.rs @@ -0,0 +1,70 @@ +use std::str::FromStr; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; +use zklink_sdk_types::basic_types::{BigUint, ZkLinkAddress}; +use zklink_sdk_types::tx_builder::WithdrawBuilder as TxWithdrawBuilder; +use zklink_sdk_types::tx_type::withdraw::Withdraw as WithdrawTx; + +#[wasm_bindgen] +pub struct Withdraw { + inner: WithdrawTx, +} + +#[wasm_bindgen] +impl Withdraw { + pub fn get_inner_tx(&self) -> Result { + Ok(serde_wasm_bindgen::to_value(&self.inner)?) + } +} + +#[wasm_bindgen] +pub struct WithdrawBuilder { + inner: TxWithdrawBuilder, +} + +#[wasm_bindgen] +impl WithdrawBuilder { + #[wasm_bindgen(constructor)] + pub fn new( + account_id: u32, + sub_account_id: u8, + to_chain_id: u8, + to_address: String, + l2_source_token: u32, + fee: String, + fast_withdraw: bool, + withdraw_fee_ratio: u16, + l1_target_token: u32, + amount: String, + nonce: u32, + ts: u32, + ) -> Result { + let inner = TxWithdrawBuilder { + account_id: account_id.into(), + sub_account_id: sub_account_id.into(), + to_chain_id: to_chain_id.into(), + to_address: ZkLinkAddress::from_hex(&to_address)?, + l2_source_token: l2_source_token.into(), + fee: BigUint::from_str(&fee).unwrap(), + nonce: nonce.into(), + fast_withdraw, + withdraw_fee_ratio, + timestamp: ts.into(), + amount: BigUint::from_str(&amount).unwrap(), + l1_target_token: l1_target_token.into(), + }; + Ok(WithdrawBuilder { inner }) + } + + #[wasm_bindgen] + pub fn build(self) -> Withdraw { + Withdraw { + inner: WithdrawTx::new(self.inner), + } + } +} + +#[wasm_bindgen(js_name=newWithdraw)] +pub fn new_withdraw(builder: WithdrawBuilder) -> Withdraw { + builder.build() +} diff --git a/bindings/wasm/src/wallet.rs b/bindings/wasm/src/wallet.rs deleted file mode 100644 index 9b0a527f..00000000 --- a/bindings/wasm/src/wallet.rs +++ /dev/null @@ -1,114 +0,0 @@ -use crate::error::ClientError; -use crate::signer::Signer; -use crate::{AccountType, Wallet}; -use num::BigUint; -use zklink_sdk_interface::{ChangePubKeyAuthRequest, TxSignature}; -use zklink_sdk_provider::response::{AccountQuery, ChainResp, TokenResp, AccountInfoResp}; -use zklink_sdk_provider::rpc::ZkLinkRpcClient; -use zklink_sdk_signers::eth_signer::eth_signature::TxEthSignature; -use zklink_sdk_signers::zklink_signer::pk_signer::ZkLinkSigner; - -use zklink_sdk_signers::zklink_signer::pubkey_hash::PubKeyHash; -use zklink_sdk_signers::zklink_signer::signature::ZkLinkSignature; -use zklink_sdk_types::basic_types::params::MAIN_SUB_ACCOUNT_ID; -use zklink_sdk_types::basic_types::tx_hash::TxHash; -use zklink_sdk_types::basic_types::{AccountId, ChainId, Nonce, SubAccountId, TokenId, ZkLinkAddress}; -use zklink_sdk_types::tx_type::order_matching::Order; -use std::collections::HashMap; -use wasm_bindgen::JsValue; - -#[wasm_bindgen] -pub struct Wallet { - pub provider: ZkLinkRpcProvider, - pub address: ZklinkAddress, - pub account_info: AccountInfoResp, - pub account_type: AccountType, - pub chains: HashMap, - pub tokens: HashMap, -} - -#[wasm_bindgen] -impl Wallet { - #[wasm_bindgen] - pub async fn new( - provider: ZkLinkRpcProvider, - address: ZkLinkAddress, - account_type: AccountType, - ) -> Result { - let chains = provider.get_support_chains().await?; - let chains = chains.iter().map(|c| (c.chain_id, c.clone())).collect(); - let tokens = provider.tokens().await?; - let account_info = provider - .account_info(AccountQuery::Address(address.clone())) - .await?; - - let wallet = Wallet { - provider, - address, - account_info, - account_type, - chains, - tokens, - }; - - Ok(wallet) - } - - /// Returns the wallet address. - #[wasm_bindgen] - pub fn address(&self) -> ZkLinkAddress { - self.address.clone() - } - - /// Returns the current account id - #[wasm_bindgen] - pub fn account_id(&self) -> AccountId { - self.account_info.id - } - - /// Returns the current account pub key hash - #[wasm_bindgen] - pub fn account_pubkey_hash(&self) -> PubKeyHash { - self.account_info.pub_key_hash - } - - #[wasm_bindgen] - pub fn account_nonce(&self) -> Nonce { - self.account_info.nonce - } - - /// Updates account info stored in the wallet. - #[wasm_bindgen] - pub async fn update_account_info(&mut self) -> Result<(), JsValue> { - self.account_info = self - .provider - .account_info(AccountQuery::Address(self.address.clone())) - .await?; - - Ok(()) - } - - /// Returns `true` if signing key for account was set in zkLink network. - /// In other words, returns `true` if `ChangePubKey` operation was performed for the - /// account. - /// - /// If this method has returned `false`, one must send a `ChangePubKey` transaction - /// via `Wallet::start_change_pubkey` method. - #[wasm_bindgen] - pub async fn is_signing_key_set(&self) -> Result { - let signer_pub_key_hash = self.signer.pub_key_hash; - - let key_set = self.account_pubkey_hash() == signer_pub_key_hash; - Ok(key_set) - } - - #[wasm_bindgen] - pub fn get_chain(&self, chain_id: &ChainId) -> Option { - self.chains.get(chain_id).cloned() - } - - #[wasm_bindgen] - pub fn get_token(&self, token_id: &TokenId) -> Option { - self.tokens.get(token_id).cloned() - } -} diff --git a/bindings/wasm/tests/test_rpc.rs b/bindings/wasm/tests/test_rpc.rs index 5d441756..607dc807 100644 --- a/bindings/wasm/tests/test_rpc.rs +++ b/bindings/wasm/tests/test_rpc.rs @@ -12,36 +12,35 @@ use zklink_sdk_types::tx_type::change_pubkey::ChangePubKey; use zklink_sdk_types::tx_type::zklink_tx::ZkLinkTx as TypesZkLinkTx; use zklink_sdk_types::tx_type::ZkSignatureTrait; use zklink_sdk_wasm::rpc_client::RpcClient; -use zklink_sdk_wasm::rpc_type_converter::{AccountQuery, AccountQueryType, ZkLinkTx}; +use zklink_sdk_wasm::rpc_type_converter::{AccountQuery, AccountQueryType}; wasm_bindgen_test_configure!(run_in_worker); -// #[wasm_bindgen_test] -// async fn test_get_tokens() { -// let client = RpcClient::new("testnet"); -// let ret = client.tokens().await; -// if let Err(e) = ret { -// web_sys::console::log_1(&JsValue::from_str(&format!("{:?}", e))); -// } else { -// web_sys::console::log_1(&JsValue::from_str(&format!("{:?}", ret.unwrap()))); -// } -// // assert!(ret.is_err()); -// } -// -// #[wasm_bindgen_test] -// async fn test_account_query() { -// let client = RpcClient::new("testnet"); -// let account_id = AccountQuery::new(AccountQueryType::AccountId, "5".to_string()); -// let account_resp = client.account_query(account_id.into(), None, None).await; -// if let Err(e) = account_resp { -// web_sys::console::log_1(&JsValue::from_str(&format!("{:?}", e))); -// } else { -// web_sys::console::log_1(&JsValue::from_str(&format!("{:?}", account_resp.unwrap()))); -// } -// } +#[wasm_bindgen_test] +async fn test_get_tokens() { + let client = RpcClient::new("testnet"); + let ret = client.tokens().await; + if let Err(e) = ret { + web_sys::console::log_1(&JsValue::from_str(&format!("{:?}", e))); + } else { + web_sys::console::log_1(&JsValue::from_str(&format!("{:?}", ret.unwrap()))); + } + // assert!(ret.is_err()); +} + +#[wasm_bindgen_test] +async fn test_account_query() { + let client = RpcClient::new("testnet"); + let account_id = AccountQuery::new(AccountQueryType::AccountId, "5".to_string()); + let account_resp = client.account_query(account_id.into(), None, None).await; + if let Err(e) = account_resp { + web_sys::console::log_1(&JsValue::from_str(&format!("{:?}", e))); + } else { + web_sys::console::log_1(&JsValue::from_str(&format!("{:?}", account_resp.unwrap()))); + } +} #[wasm_bindgen_test] async fn test_send_change_pubkey() { - web_sys::console::log_1(&JsValue::from_str("123")); let client = RpcClient::new("devnet"); let private_key = "be725250b123a39dab5b7579334d5888987c72a58f4508062545fe6e08ca94f4"; let eth_signer = EthSigner::try_from(private_key).unwrap(); @@ -62,7 +61,7 @@ async fn test_send_change_pubkey() { eth_signature: None, timestamp: TimeStamp(ts), }; - let mut change_pubkey = ChangePubKey::new(builder); + let change_pubkey = ChangePubKey::new(builder); let message = change_pubkey .to_eip712_request_payload( l1_client_id, diff --git a/examples/Javascript/js-example/1_change_pubkey.js b/examples/Javascript/js-example/1_change_pubkey.js index c53a27e3..8eb9925a 100644 --- a/examples/Javascript/js-example/1_change_pubkey.js +++ b/examples/Javascript/js-example/1_change_pubkey.js @@ -20,7 +20,7 @@ async function testEcdsaAuth() { let submitter_signature = signer.submitterSignature(tx_signature.tx); console.log(submitter_signature); //send to zklink - let rpc_client = new wasm.RpcClient("devnet"); + let rpc_client = new wasm.RpcClient("testnet"); let tx_hash = await rpc_client.sendTransaction(tx_signature.tx,null,submitter_signature); console.log(tx_hash); @@ -65,4 +65,4 @@ async function testCreate2() { } await testEcdsaAuth(); -await testCreate2(); +// await testCreate2(); diff --git a/examples/Javascript/js-example/2_transfer.js b/examples/Javascript/js-example/2_transfer.js index 68f0c420..e60a9e1a 100644 --- a/examples/Javascript/js-example/2_transfer.js +++ b/examples/Javascript/js-example/2_transfer.js @@ -15,7 +15,7 @@ async function main() { let submitter_signature = signer.submitterSignature(signature.tx); console.log(submitter_signature); let rpc_client = new wasm.RpcClient("testnet"); - let l1_signature = new wasm.TxL1Signature(wasm.L1SignatureType.Eth,signature.eth_signature); + let l1_signature = new wasm.TxLayer1Signature(wasm.L1SignatureType.Eth,signature.eth_signature); let tx_hash = await rpc_client.sendTransaction(signature.tx,l1_signature,submitter_signature); console.log(tx_hash); diff --git a/examples/Javascript/js-example/3_order_matching.js b/examples/Javascript/js-example/3_order_matching.js new file mode 100644 index 00000000..c95712f5 --- /dev/null +++ b/examples/Javascript/js-example/3_order_matching.js @@ -0,0 +1,33 @@ +import init, * as wasm from "./web-dist/zklink-sdk-web.js"; + +async function main() { + await init(); + const private_key = "be725250b123a39dab5b7579334d5888987c72a58f4508062545fe6e08ca94f4"; + try { + + let signer = new wasm.Signer(private_key); + //maker = taker = submitter + let maker_order = new wasm.Order(5,1,1,1,18,17,"10000000000000","10000000000",true,5,3); + let maker = signer.createSignedOrder(maker_order); + console.log(maker); + let taker_order = new wasm.Order(5,1,1,1,18,17,"10000000000000","10000000000",false,5,3); + let taker = signer.createSignedOrder(taker_order); + console.log(taker); + let tx_builder = new wasm.OrderMatchingBuilder(10, 1, taker, maker, "1000000000", 18,"10000000000000000", "10000000000000000"); + let order_matching = wasm.newOrderMatching(tx_builder); + let signature = signer.signOrderMatching(order_matching); + console.log(signature); + + let submitter_signature = signer.submitterSignature(signature.tx); + console.log(submitter_signature); + let rpc_client = new wasm.RpcClient("testnet"); + let tx_hash = await rpc_client.sendTransaction(signature.tx,null,submitter_signature); + console.log(tx_hash); + + } catch (error) { + console.error(error); + } + +} + +main(); diff --git a/examples/Javascript/js-example/4_withdraw.js b/examples/Javascript/js-example/4_withdraw.js new file mode 100644 index 00000000..7028ea01 --- /dev/null +++ b/examples/Javascript/js-example/4_withdraw.js @@ -0,0 +1,28 @@ +import init, * as wasm from "./web-dist/zklink-sdk-web.js"; + +async function main() { + await init(); + const private_key = "be725250b123a39dab5b7579334d5888987c72a58f4508062545fe6e08ca94f4"; + const to_address = "0x5505a8cD4594Dbf79d8C59C0Df1414AB871CA896"; + const ts = Math.floor(Date.now() / 1000); + try { + let tx_builder = new wasm.WithdrawBuilder(10, 1, 1, to_address,18, "100000000000000", false,10,18,"10000000000000000", 1,ts); + let withdraw = wasm.newWithdraw(tx_builder); + let signer = new wasm.Signer(private_key); + let signature = signer.signWithdraw(withdraw,"USDC") + console.log(signature); + + let submitter_signature = signer.submitterSignature(signature.tx); + console.log(submitter_signature); + let rpc_client = new wasm.RpcClient("testnet"); + let l1_signature = new wasm.TxLayer1Signature(wasm.L1SignatureType.Eth,signature.eth_signature); + let tx_hash = await rpc_client.sendTransaction(signature.tx,l1_signature,submitter_signature); + console.log(tx_hash); + + } catch (error) { + console.error(error); + } + +} + +main(); diff --git a/examples/Javascript/js-example/5_forced_exit.js b/examples/Javascript/js-example/5_forced_exit.js new file mode 100644 index 00000000..185261c8 --- /dev/null +++ b/examples/Javascript/js-example/5_forced_exit.js @@ -0,0 +1,27 @@ +import init, * as wasm from "./web-dist/zklink-sdk-web.js"; + +async function main() { + await init(); + const private_key = "be725250b123a39dab5b7579334d5888987c72a58f4508062545fe6e08ca94f4"; + const to_address = "0x5505a8cD4594Dbf79d8C59C0Df1414AB871CA896"; + const ts = Math.floor(Date.now() / 1000); + try { + let tx_builder = new wasm.ForcedExitBuilder(1,10, 1, 1, to_address,18, 18,"100000000000000", 1,ts); + let forced_exit = wasm.newForcedExit(tx_builder); + let signer = new wasm.Signer(private_key); + let signature = signer.signForcedExit(forced_exit) + console.log(signature); + + let submitter_signature = signer.submitterSignature(signature.tx); + console.log(submitter_signature); + let rpc_client = new wasm.RpcClient("testnet"); + let tx_hash = await rpc_client.sendTransaction(signature.tx,null,submitter_signature); + console.log(tx_hash); + + } catch (error) { + console.error(error); + } + +} + +main(); diff --git a/examples/Javascript/js-example/rpc.js b/examples/Javascript/js-example/6_rpc.js similarity index 98% rename from examples/Javascript/js-example/rpc.js rename to examples/Javascript/js-example/6_rpc.js index bad186aa..764396db 100644 --- a/examples/Javascript/js-example/rpc.js +++ b/examples/Javascript/js-example/6_rpc.js @@ -2,7 +2,7 @@ import init, * as wasm from "./web-dist/zklink-sdk-web.js"; async function main() { await init(); try { - let client = new wasm.RpcClient("mainet"); + let client = new wasm.RpcClient("testnet"); // 1.getSupportTokens let tokens = await client.getSupportTokens(); console.log(tokens); diff --git a/examples/Javascript/js-example/index.html b/examples/Javascript/js-example/index.html index 2de4a22b..0c7edc07 100644 --- a/examples/Javascript/js-example/index.html +++ b/examples/Javascript/js-example/index.html @@ -6,9 +6,10 @@ - \ No newline at end of file diff --git a/interface/src/sign_order.rs b/interface/src/sign_order.rs index ca380f0a..ad90bc20 100644 --- a/interface/src/sign_order.rs +++ b/interface/src/sign_order.rs @@ -5,10 +5,10 @@ use zklink_sdk_signers::zklink_signer::pk_signer::ZkLinkSigner; use zklink_sdk_types::tx_type::order_matching::Order; use zklink_sdk_types::tx_type::TxTrait; #[cfg(not(feature = "ffi"))] -pub fn sign(order: &mut Order, signer: &ZkLinkSigner) -> Result<(), ZkSignerError> { - let bytes = order.get_bytes(); - order.signature = signer.sign_musig(&bytes)?; - Ok(()) +pub fn sign_order(order: &Order, zklink_signer: &ZkLinkSigner) -> Result { + let mut order = order.clone(); + order.signature = zklink_signer.sign_musig(&order.get_bytes())?; + Ok(order) } #[cfg(feature = "ffi")] diff --git a/interface/src/signer.rs b/interface/src/signer.rs index 2babbaa7..c39ae236 100644 --- a/interface/src/signer.rs +++ b/interface/src/signer.rs @@ -1,5 +1,6 @@ use crate::error::SignError; use crate::sign_forced_exit::sign_forced_exit; +use crate::sign_order::sign_order; use crate::sign_order_matching::sign_order_matching; use crate::sign_transfer::sign_transfer; use crate::sign_withdraw::sign_withdraw; @@ -15,7 +16,7 @@ use zklink_sdk_signers::zklink_signer::signature::ZkLinkSignature; use zklink_sdk_types::basic_types::ZkLinkAddress; use zklink_sdk_types::tx_type::change_pubkey::{ChangePubKey, ChangePubKeyAuthData, Create2Data}; use zklink_sdk_types::tx_type::forced_exit::ForcedExit; -use zklink_sdk_types::tx_type::order_matching::OrderMatching; +use zklink_sdk_types::tx_type::order_matching::{Order, OrderMatching}; use zklink_sdk_types::tx_type::transfer::Transfer; use zklink_sdk_types::tx_type::withdraw::Withdraw; use zklink_sdk_types::tx_type::zklink_tx::ZkLinkTx; @@ -215,6 +216,12 @@ impl Signer { Ok(signature) } + #[cfg(not(feature = "ffi"))] + pub fn sign_order(&self, order: &Order) -> Result { + let signed_order = sign_order(order, &self.zklink_signer)?; + Ok(signed_order) + } + #[cfg(feature = "ffi")] pub fn sign_order_matching(&self, tx: Arc) -> Result { let tx = (*tx).clone(); diff --git a/provider/src/error.rs b/provider/src/error.rs index c676958d..fdc814c0 100644 --- a/provider/src/error.rs +++ b/provider/src/error.rs @@ -14,8 +14,10 @@ pub enum RpcError { RequestError(reqwest::Error), #[error("Parse response error: {0}")] ResponseError(reqwest::Error), - #[error("Parse json value error")] - ParseJsonError, + #[error("Parse json value error: {0}")] + ParseJsonError(String), + #[error("Get error result: {0}")] + GetErrorResult(String), } impl From for JsValue { diff --git a/provider/src/lib.rs b/provider/src/lib.rs index 56f1f87a..afd32117 100644 --- a/provider/src/lib.rs +++ b/provider/src/lib.rs @@ -1,12 +1,10 @@ pub mod error; pub mod network; pub mod response; -#[cfg(not(feature = "ffi"))] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(any(feature = "ffi", target_arch = "wasm32")))] pub mod rpc; -#[cfg(not(feature = "ffi"))] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(any(feature = "ffi", target_arch = "wasm32")))] mod not_ffi { use crate::network::Network; use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; @@ -38,12 +36,9 @@ mod not_ffi { } } -#[cfg(not(feature = "ffi"))] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(any(feature = "ffi", target_arch = "wasm32")))] pub use crate::rpc::ZkLinkRpcClient; -#[cfg(not(feature = "ffi"))] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(any(feature = "ffi", target_arch = "wasm32")))] pub use jsonrpsee::core::Error as RpcError; -#[cfg(not(feature = "ffi"))] -#[cfg(not(target_arch = "wasm32"))] +#[cfg(not(any(feature = "ffi", target_arch = "wasm32")))] pub use not_ffi::*; diff --git a/provider/tests/test_rpc.rs b/provider/tests/test_rpc.rs index 3c53348c..de1ec6f7 100644 --- a/provider/tests/test_rpc.rs +++ b/provider/tests/test_rpc.rs @@ -9,10 +9,11 @@ mod test { use zklink_sdk_types::basic_types::{ AccountId, ChainId, Nonce, SubAccountId, TimeStamp, TokenId, ZkLinkAddress, }; - use zklink_sdk_types::tx_builder::ChangePubKeyBuilder; + use zklink_sdk_types::tx_builder::{ChangePubKeyBuilder, OrderMatchingBuilder}; use zklink_sdk_types::tx_type::change_pubkey::ChangePubKey; + use zklink_sdk_types::tx_type::order_matching::{Order, OrderMatching}; use zklink_sdk_types::tx_type::zklink_tx::ZkLinkTx; - use zklink_sdk_types::tx_type::ZkSignatureTrait; + use zklink_sdk_types::tx_type::{TxTrait, ZkSignatureTrait}; #[tokio::test] async fn test_send_change_pubkey() { @@ -70,8 +71,70 @@ mod test { None, Some(submitter_signature), ) - .await + .await; + println!("{:?}", ret) + } + + #[tokio::test] + async fn test_send_order_matching() { + let private_key = "be725250b123a39dab5b7579334d5888987c72a58f4508062545fe6e08ca94f4"; + let zklink_signer = ZkLinkSigner::new_from_hex_eth_signer(private_key).unwrap(); + let maker_order = Order::new( + 5.into(), + 1.into(), + 1.into(), + 1.into(), + 18.into(), + 17.into(), + BigUint::from_str("10000000000000").unwrap(), + BigUint::from_str("10000000000").unwrap(), + true, + 5, + 3, + ); + let mut maker = maker_order.clone(); + maker.signature = zklink_signer.sign_musig(&maker_order.get_bytes()).unwrap(); + let taker_order = Order::new( + 5.into(), + 1.into(), + 1.into(), + 1.into(), + 18.into(), + 17.into(), + BigUint::from_str("10000000000000").unwrap(), + BigUint::from_str("10000000000").unwrap(), + false, + 5, + 3, + ); + let mut taker = taker_order.clone(); + taker.signature = zklink_signer.sign_musig(&taker_order.get_bytes()).unwrap(); + //auth type 'ECDSA' + let builder = OrderMatchingBuilder { + account_id: AccountId(10), + sub_account_id: SubAccountId(1), + taker, + fee_token: TokenId(18), + expect_base_amount: BigUint::from(10000000000000000u64), + fee: BigUint::from(100000000000000u64), + maker, + expect_quote_amount: BigUint::from(100000000000000u64), + }; + let mut order_matching = OrderMatching::new(builder); + order_matching.sign(&zklink_signer).unwrap(); + let submitter_signature = order_matching.submitter_signature(&zklink_signer).unwrap(); + + //use jsonrpsee + let client = HttpClientBuilder::default() + .build("https://aws-gw-v2.zk.link") .unwrap(); + let ret = client + .tx_submit( + ZkLinkTx::OrderMatching(Box::new(order_matching.clone())), + None, + Some(submitter_signature), + ) + .await; println!("{:?}", ret) } }