From 272e4b423137bb48410cfaa657d05ed1ae10cd9a Mon Sep 17 00:00:00 2001 From: nick-zkp <88881925+nick-zkp@users.noreply.github.com> Date: Tue, 28 Nov 2023 19:07:29 +0800 Subject: [PATCH] json-rpc-signer support input customize provider for frontend(fix #91) (#92) * json-rpc-signer support input customize provider for frontend(fix #91) * fix review suggests * fix review suggests --- bindings/wasm/src/json_rpc_signer.rs | 20 ++++++------ .../Javascript/js-example/1_change_pubkey.js | 31 +++++++++++++++---- examples/Javascript/js-example/2_transfer.js | 8 +++-- .../Javascript/js-example/3_order_matching.js | 7 +++-- examples/Javascript/js-example/4_withdraw.js | 8 +++-- .../Javascript/js-example/5_forced_exit.js | 8 +++-- examples/Javascript/js-example/index.html | 4 +-- interface/src/json_rpc_signer.rs | 26 ++++++++++------ signers/src/eth_signer/json_rpc_signer.rs | 22 ++----------- signers/src/zklink_signer/pk_signer.rs | 0 10 files changed, 77 insertions(+), 57 deletions(-) mode change 100644 => 100755 bindings/wasm/src/json_rpc_signer.rs mode change 100644 => 100755 examples/Javascript/js-example/1_change_pubkey.js mode change 100644 => 100755 examples/Javascript/js-example/2_transfer.js mode change 100644 => 100755 examples/Javascript/js-example/3_order_matching.js mode change 100644 => 100755 examples/Javascript/js-example/4_withdraw.js mode change 100644 => 100755 examples/Javascript/js-example/5_forced_exit.js mode change 100644 => 100755 examples/Javascript/js-example/index.html mode change 100644 => 100755 interface/src/json_rpc_signer.rs mode change 100644 => 100755 signers/src/eth_signer/json_rpc_signer.rs mode change 100644 => 100755 signers/src/zklink_signer/pk_signer.rs diff --git a/bindings/wasm/src/json_rpc_signer.rs b/bindings/wasm/src/json_rpc_signer.rs old mode 100644 new mode 100755 index 4ab1a180..ed3d9741 --- a/bindings/wasm/src/json_rpc_signer.rs +++ b/bindings/wasm/src/json_rpc_signer.rs @@ -1,3 +1,4 @@ +use crate::rpc_type_converter::TxZkLinkSignature; use crate::tx_types::change_pubkey::{ChangePubKey, Create2Data}; use crate::tx_types::forced_exit::ForcedExit; use crate::tx_types::order_matching::{Order, OrderMatching}; @@ -6,7 +7,7 @@ use crate::tx_types::withdraw::Withdraw; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; use zklink_sdk_interface::json_rpc_signer::JsonRpcSigner as InterfaceJsonRpcSigner; -use zklink_sdk_types::basic_types::ZkLinkAddress; +use zklink_sdk_signers::eth_signer::json_rpc_signer::Provider; 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; @@ -25,14 +26,14 @@ pub struct JsonRpcSigner { #[wasm_bindgen] impl JsonRpcSigner { #[wasm_bindgen(constructor)] - pub fn new() -> Result { - let inner = InterfaceJsonRpcSigner::new()?; + pub fn new(provider: Provider) -> Result { + let inner = InterfaceJsonRpcSigner::new(provider)?; Ok(JsonRpcSigner { inner }) } #[wasm_bindgen(js_name = initZklinkSigner)] - pub async fn init_zklink_signer(&mut self) -> Result<(), JsValue> { - Ok(self.inner.init_zklink_signer().await?) + pub async fn init_zklink_signer(&mut self, signature: Option) -> Result<(), JsValue> { + Ok(self.inner.init_zklink_signer(signature).await?) } #[wasm_bindgen(js_name = signTransfer)] @@ -51,15 +52,12 @@ impl JsonRpcSigner { pub async fn sign_change_pubkey_with_eth_ecdsa_auth( &self, tx: ChangePubKey, - l1_client_id: u32, - main_contract: &str, ) -> Result { let inner_tx = tx.json_value()?; let change_pubkey: TxChangePubKey = serde_wasm_bindgen::from_value(inner_tx)?; - let contract_address = ZkLinkAddress::from_hex(main_contract)?; let signature = self .inner - .sign_change_pubkey_with_eth_ecdsa_auth(change_pubkey, l1_client_id, contract_address) + .sign_change_pubkey_with_eth_ecdsa_auth(change_pubkey) .await?; Ok(serde_wasm_bindgen::to_value(&signature)?) } @@ -117,9 +115,9 @@ impl JsonRpcSigner { } #[wasm_bindgen(js_name=submitterSignature)] - pub fn submitter_signature(&self, tx: JsValue) -> Result { + pub fn submitter_signature(&self, tx: JsValue) -> Result { let zklink_tx: ZkLinkTx = serde_wasm_bindgen::from_value(tx)?; let zklink_signature = self.inner.submitter_signature(&zklink_tx)?; - Ok(zklink_signature.as_hex()) + Ok(zklink_signature.into()) } } diff --git a/examples/Javascript/js-example/1_change_pubkey.js b/examples/Javascript/js-example/1_change_pubkey.js old mode 100644 new mode 100755 index d1a04e52..29372ac7 --- a/examples/Javascript/js-example/1_change_pubkey.js +++ b/examples/Javascript/js-example/1_change_pubkey.js @@ -1,4 +1,5 @@ import init, * as wasm from "./web-dist/zklink-sdk-web.js"; +import { ethers } from "https://cdn-cors.ethers.io/lib/ethers-5.5.4.esm.min.js"; async function testEcdsaAuth() { await init(); @@ -10,8 +11,23 @@ async function testEcdsaAuth() { 1,"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b", ts); let tx = wasm.newChangePubkey(tx_builder); - const signer = new wasm.JsonRpcSigner(); - await signer.initZklinkSigner(); + //use stand window.ethereum as metamask .. + //await window.ethereum.request({ method: 'eth_requestAccounts' }); + //const provider = window.ethereum; + + //use not stand window.ethereum as bitget .. + const provider = window.bitkeep && window.bitkeep.ethereum; + await provider.request({ method: 'eth_requestAccounts' }); + + const signer = new wasm.JsonRpcSigner(provider); + + // use cached ethereum signature to init zklink signer + //const signature = "0x1111111111"; + //await signer.initZklinkSigner(signature); + // use wallet to init the zklink signer + await signer.initZklinkSigner(null); + console.log(signer); + let tx_signature = await signer.signChangePubkeyWithEthEcdsaAuth(tx); console.log(tx_signature); @@ -30,7 +46,6 @@ async function testEcdsaAuth() { async function testCreate2() { await init(); - const private_key = "43be0b8bdeccb5a13741c8fd076bf2619bfc9f6dcc43ad6cf965ab489e156ced"; const new_pubkey_hash = "0xd8d5fb6a6caef06aa3dc2abdcdc240987e5330fe"; const ts = Math.floor(Date.now() / 1000); try { @@ -39,14 +54,18 @@ async function testCreate2() { 1,"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b", ts); let tx = wasm.newChangePubkey(tx_builder); - const signer = new wasm.Signer(private_key); + const provider = window.bitkeep && window.bitkeep.ethereum; + await provider.request({ method: 'eth_requestAccounts' }); + const signer = new wasm.JsonRpcSigner(provider); + await signer.initZklinkSigner(null); + console.log(signer); + //auth type 'Create2' const creator_address = "0x6E253C951A40fAf4032faFbEc19262Cd1531A5F5"; const salt = "0x0000000000000000000000000000000000000000000000000000000000000000"; const code_hash = "0x4f063cd4b2e3a885f61fefb0988cc12487182c4f09ff5de374103f5812f33fe7"; let create2_data = new wasm.Create2Data(creator_address,salt,code_hash); - let from_account = "0x4504d5BE8634e3896d42784A5aB89fc41C3d4511"; - let tx_signature = signer.signChangePubkeyWithCreate2DataAuth(tx,create2_data); + let tx_signature = await signer.signChangePubkeyWithCreate2DataAuth(tx,create2_data); console.log(tx_signature); let submitter_signature = signer.submitterSignature(tx_signature.tx); diff --git a/examples/Javascript/js-example/2_transfer.js b/examples/Javascript/js-example/2_transfer.js old mode 100644 new mode 100755 index c9d65ab5..2c11cb89 --- a/examples/Javascript/js-example/2_transfer.js +++ b/examples/Javascript/js-example/2_transfer.js @@ -10,8 +10,12 @@ async function main() { let tx_builder = new wasm.TransferBuilder(10, to_address, 1, 1, 18, fee, amount, 1,ts); let transfer = wasm.newTransfer(tx_builder); - let signer = new wasm.JsonRpcSigner(); - await signer.initZklinkSigner(); + const provider = window.bitkeep && window.bitkeep.ethereum; + await provider.request({ method: 'eth_requestAccounts' }); + const signer = new wasm.JsonRpcSigner(provider); + await signer.initZklinkSigner(null); + console.log(signer); + let signature = await signer.signTransfer(transfer,"USDC") console.log(signature); diff --git a/examples/Javascript/js-example/3_order_matching.js b/examples/Javascript/js-example/3_order_matching.js old mode 100644 new mode 100755 index 1ac15399..5d9ad9e5 --- a/examples/Javascript/js-example/3_order_matching.js +++ b/examples/Javascript/js-example/3_order_matching.js @@ -3,9 +3,12 @@ import init, * as wasm from "./web-dist/zklink-sdk-web.js"; async function main() { await init(); try { + const provider = window.bitkeep && window.bitkeep.ethereum; + await provider.request({ method: 'eth_requestAccounts' }); + const signer = new wasm.JsonRpcSigner(provider); + await signer.initZklinkSigner(null); + console.log(signer); - let signer = new wasm.JsonRpcSigner(); - await signer.initZklinkSigner(); //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); diff --git a/examples/Javascript/js-example/4_withdraw.js b/examples/Javascript/js-example/4_withdraw.js old mode 100644 new mode 100755 index cc5cad74..8c358fe8 --- a/examples/Javascript/js-example/4_withdraw.js +++ b/examples/Javascript/js-example/4_withdraw.js @@ -8,8 +8,12 @@ async function main() { 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.JsonRpcSigner(); - await signer.initZklinkSigner(); + const provider = window.bitkeep && window.bitkeep.ethereum; + await provider.request({ method: 'eth_requestAccounts' }); + const signer = new wasm.JsonRpcSigner(provider); + await signer.initZklinkSigner(null); + console.log(signer); + let signature = await signer.signWithdraw(withdraw,"USDC") console.log(signature); diff --git a/examples/Javascript/js-example/5_forced_exit.js b/examples/Javascript/js-example/5_forced_exit.js old mode 100644 new mode 100755 index 3fca3b4e..7f6da230 --- a/examples/Javascript/js-example/5_forced_exit.js +++ b/examples/Javascript/js-example/5_forced_exit.js @@ -2,14 +2,16 @@ 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.JsonRpcSigner(); - await signer.initZklinkSigner(); + const provider = window.bitkeep && window.bitkeep.ethereum; + await provider.request({ method: 'eth_requestAccounts' }); + const signer = new wasm.JsonRpcSigner(provider); + await signer.initZklinkSigner(null); + console.log(signer); let signature = signer.signForcedExit(forced_exit) console.log(signature); diff --git a/examples/Javascript/js-example/index.html b/examples/Javascript/js-example/index.html old mode 100644 new mode 100755 index 0c7edc07..4555fba2 --- a/examples/Javascript/js-example/index.html +++ b/examples/Javascript/js-example/index.html @@ -6,10 +6,10 @@ - + \ No newline at end of file diff --git a/interface/src/json_rpc_signer.rs b/interface/src/json_rpc_signer.rs old mode 100644 new mode 100755 index 18f932aa..71d44251 --- a/interface/src/json_rpc_signer.rs +++ b/interface/src/json_rpc_signer.rs @@ -5,9 +5,11 @@ use crate::sign_forced_exit::sign_forced_exit; use crate::sign_order_matching::sign_order_matching; use crate::sign_transfer::sign_transfer; use crate::sign_withdraw::sign_withdraw; -use zklink_sdk_signers::eth_signer::json_rpc_signer::JsonRpcSigner as EthJsonRpcSigner; +use zklink_sdk_signers::eth_signer::json_rpc_signer::{ + JsonRpcSigner as EthJsonRpcSigner, Provider, +}; use zklink_sdk_signers::zklink_signer::{ZkLinkSignature, ZkLinkSigner}; -use zklink_sdk_types::basic_types::ZkLinkAddress; +use zklink_sdk_types::prelude::PackedEthSignature; use zklink_sdk_types::signatures::TxSignature; use zklink_sdk_types::tx_type::change_pubkey::{ChangePubKey, ChangePubKeyAuthData, Create2Data}; use zklink_sdk_types::tx_type::forced_exit::ForcedExit; @@ -23,8 +25,8 @@ pub struct JsonRpcSigner { } impl JsonRpcSigner { - pub fn new() -> Result { - let eth_json_rpc_signer = EthJsonRpcSigner::new()?; + pub fn new(provider: Provider) -> Result { + let eth_json_rpc_signer = EthJsonRpcSigner::new(provider)?; let default_zklink_signer = ZkLinkSigner::new()?; Ok(Self { zklink_signer: default_zklink_signer, @@ -32,8 +34,14 @@ impl JsonRpcSigner { }) } - pub async fn init_zklink_signer(&mut self) -> Result<(), SignError> { - let zklink_signer = ZkLinkSigner::new_from_eth_rpc_signer(&self.eth_signer).await?; + pub async fn init_zklink_signer(&mut self, signature: Option) -> Result<(), SignError> { + let zklink_signer = if let Some(s) = signature { + let signature = PackedEthSignature::from_hex(&s)?; + let seed = signature.serialize_packed(); + ZkLinkSigner::new_from_seed(&seed)? + } else { + ZkLinkSigner::new_from_eth_rpc_signer(&self.eth_signer).await? + }; self.zklink_signer = zklink_signer; Ok(()) } @@ -59,18 +67,16 @@ impl JsonRpcSigner { pub async fn sign_change_pubkey_with_eth_ecdsa_auth( &self, mut tx: ChangePubKey, - l1_client_id: u32, - main_contract_address: ZkLinkAddress, ) -> Result { tx.sign(&self.zklink_signer)?; let should_valid = tx.is_signature_valid(); assert!(should_valid); // create auth data - let typed_data = tx.to_eip712_request_payload(l1_client_id, &main_contract_address)?; + let eth_sign_msg = ChangePubKey::get_eth_sign_msg(&tx.new_pk_hash, tx.nonce, tx.account_id); let eth_signature = self .eth_signer - .sign_message_eip712(typed_data.raw_data.as_bytes()) + .sign_message(eth_sign_msg.as_bytes()) .await?; tx.eth_auth_data = ChangePubKeyAuthData::EthECDSA { eth_signature }; diff --git a/signers/src/eth_signer/json_rpc_signer.rs b/signers/src/eth_signer/json_rpc_signer.rs old mode 100644 new mode 100755 index 6fae3d5a..b552fb67 --- a/signers/src/eth_signer/json_rpc_signer.rs +++ b/signers/src/eth_signer/json_rpc_signer.rs @@ -18,36 +18,20 @@ extern "C" { /// An EIP-1193 provider object. Available by convention at `window.ethereum` pub type Provider; - #[wasm_bindgen(catch, method)] + #[wasm_bindgen(structural,catch, method)] async fn request(_: &Provider, args: JsValue) -> Result; #[wasm_bindgen(method,getter)] fn selectedAddress(this: &Provider) -> Option; } -#[wasm_bindgen(inline_js = "export function get_provider_js() {return window.ethereum}")] -extern "C" { - #[wasm_bindgen(catch)] - fn get_provider_js() -> Result, JsValue>; -} - -pub fn get_provider() -> Result, EthSignerError> { - get_provider_js().map_err(|_e| EthSignerError::MissingEthSigner) -} - pub struct JsonRpcSigner { provider: Provider, } impl JsonRpcSigner { - pub fn new() -> Result { - let provider = get_provider()?; - if provider.is_none() { - return Err(EthSignerError::MissingEthSigner); - } - Ok(JsonRpcSigner { - provider: provider.unwrap(), - }) + pub fn new(provider: Provider) -> Result { + Ok(JsonRpcSigner { provider }) } pub async fn sign_message(&self, message: &[u8]) -> Result { diff --git a/signers/src/zklink_signer/pk_signer.rs b/signers/src/zklink_signer/pk_signer.rs old mode 100644 new mode 100755