From 8b9eb36115c1d574bee8b8b28887d17ed0198867 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Thu, 10 Oct 2024 15:20:05 +0200 Subject: [PATCH 01/13] WIP: secret improvements --- README.md | 16 ++++--- packages/hardhat/contracts/NunyaBusiness.sol | 4 +- .../nunya-contract/src/contract.rs | 48 ++++++++----------- .../nunya-contract/src/state.rs | 2 +- 4 files changed, 33 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index b2c1587..876a12b 100644 --- a/README.md +++ b/README.md @@ -111,15 +111,19 @@ cd packages/secret-contracts/my-counter-contract make build ``` -* FIXME: attempt to fix on macOS hack https://github.com/briansmith/ring/issues/1824 +* Note: To build on macOS it was necessary to run the following first as specified here https://github.com/rust-bitcoin/rust-secp256k1/issues/283#issuecomment-1590391777: + ``` -cd packages/secret-contracts/nunya-contract /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install llvm -echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> ~/.zshrc -export LDFLAGS="-L/opt/homebrew/opt/llvm/lib" -export CPPFLAGS="-I/opt/homebrew/opt/llvm/include" -RUSTFLAGS='-C link-arg=-s' cargo build --release --target wasm32-unknown-unknown +llvm-config --version +echo 'export AR=/opt/homebrew/opt/llvm/bin/llvm-ar' >> ~/.zshrc +echo 'export CC=/opt/homebrew/opt/llvm/bin/clang' >> ~/.zshrc +source ~/.zshrc +``` +* FIXME: attempt to fix on macOS hack https://github.com/briansmith/ring/issues/1824 +``` +cd packages/secret-contracts/nunya-contract make build ``` diff --git a/packages/hardhat/contracts/NunyaBusiness.sol b/packages/hardhat/contracts/NunyaBusiness.sol index fe137c0..5756836 100644 --- a/packages/hardhat/contracts/NunyaBusiness.sol +++ b/packages/hardhat/contracts/NunyaBusiness.sol @@ -82,14 +82,14 @@ contract NunyaBusiness { } // Function wrapped in secret network payload encryption - function linkPaymentRef(uint256 _secret, string calldata _ref) public payable returns (uint256){ + function linkPaymentRef(uint256 _secret, string calldata _ref) public payable returns (uint256) { fundGateway(msg.value); uint256 requestId = secretContract.linkPaymentRef(_secret, _ref); expectedResult[requestId]=FunctionCallType.NEW_REF; return(requestId); } - function linkPaymentRefCallback(uint256 _requestId, bool _success) public onlyGateway{ + function linkPaymentRefCallback(uint256 _requestId, bool _success) public onlyGateway { require (expectedResult[_requestId]==FunctionCallType.NEW_REF); if (!_success) emit SecretNetworkError(_requestId, "Error paying - no user found?"); diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 29aee63..2f394ca 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -91,10 +91,8 @@ fn create_new_secret_user( let input: NewSecretUserStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - // Parse as u256 - let secret_user = input - .secret_user - .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + let secret_user = input.secret_user; + // .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; let new_secret_user = NewSecretUser { secret_user: secret_user @@ -151,11 +149,9 @@ fn create_link_payment_ref( let input: LinkPaymentRefStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - // FIXME - // Parse as u256 let secret_user = input - .secret_user - .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + .secret_user; + // .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; let payment_ref = input .payment_ref @@ -223,11 +219,10 @@ fn create_pay( .parse::() .map_err(|err| StdError::generic_err(format!("Invalid _ref: {}", err)))?; - // Parse as u256 let amount = input - .amount - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _amount: {}", err)))?; + .amount; + // .parse::() + // .map_err(|err| StdError::generic_err(format!("Invalid _amount: {}", err)))?; let pay = Pay { payment_ref: payment_ref, @@ -290,17 +285,15 @@ fn create_pay_encrypted_with_receipt( .parse::() .map_err(|err| StdError::generic_err(format!("Invalid _ref: {}", err)))?; - // Parse as u256 let amount = input - .amount - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _amount: {}", err)))?; + .amount; + // .parse::() + // .map_err(|err| StdError::generic_err(format!("Invalid _amount: {}", err)))?; - // Parse as u256 let user_pubkey = input - .user_pubkey - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _userPubkey: {}", err)))?; + .user_pubkey; + // .parse::() + // .map_err(|err| StdError::generic_err(format!("Invalid _userPubkey: {}", err)))?; let pay_encrypted_with_receipt = PayEncryptedWithReceipt { payment_ref: payment_ref, @@ -360,18 +353,17 @@ fn create_withdraw_to( .map_err(|err| StdError::generic_err(err.to_string()))?; let secret_user = input - .secret_user - .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + .secret_user; + // .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; - // Parse as u256 let amount = input - .amount - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid amount: {}", err)))?; + .amount; + // .parse::() + // .map_err(|err| StdError::generic_err(format!("Invalid amount: {}", err)))?; let withdrawal_address = input - .withdrawal_address - .map_err(|err| StdError::generic_err(format!("Invalid withdrawalAddress: {}", err)))?; + .withdrawal_address; + // .map_err(|err| StdError::generic_err(format!("Invalid withdrawalAddress: {}", err)))?; let withdrawal_to = WithdrawTo { secret_user: secret_user, diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index 46ec464..7d71d1d 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -5,8 +5,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; pub static CONFIG: Item = Item::new(b"config"); +pub static NEW_SECRET_USER_MAP: Keymap = Keymap::new(b"NEW_SECRET_USER_MAP"); pub static PUBKEY_MAP: Keymap> = Keymap::new(b"PUBKEY_MAP"); -pub static NEW_SECRET_USER_MAP: Keymap> = Keymap::new(b"NEW_SECRET_USER_MAP"); pub static LINK_PAYMENT_REF_MAP: Keymap> = Keymap::new(b"LINK_PAYMENT_REF_MAP"); pub static PAY_MAP: Keymap> = Keymap::new(b"PAY_MAP"); pub static PAY_ENCRYPTED_WITH_RECEIPT_MAP: Keymap> = Keymap::new(b"PAY_ENCRYPTED_WITH_RECEIPT_MAP"); From 12834591592e1273162b1f849fdd666dab9db303 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Sun, 13 Oct 2024 14:26:18 +0200 Subject: [PATCH 02/13] only allow gateway contract to call secret contract --- .../secret-contracts/nunya-contract/src/contract.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 2f394ca..12d31c8 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -57,12 +57,20 @@ fn try_handle( msg: PrivContractHandleMsg, ) -> StdResult { // verify signature with stored gateway public key - let gateway_key = CONFIG.load(deps.storage)?.gateway_key; + let config = CONFIG.load(deps.storage)?; + + // reference: evm-kv-store-demo + if info.sender != config.gateway_address { + return Err(StdError::generic_err( + "Only SecretPath Gateway can call this function", + )); + } + deps.api .secp256k1_verify( msg.input_hash.as_slice(), msg.signature.as_slice(), - gateway_key.as_slice(), + config.gateway_key.as_slice(), ) .map_err(|err| StdError::generic_err(err.to_string()))?; From 57a0dba0f1a8968acb6cd237ba37e51bc75bd1bd Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Mon, 14 Oct 2024 15:47:27 +0200 Subject: [PATCH 03/13] WIP --- packages/hardhat/contracts/DummyGateway.sol | 11 +- packages/hardhat/contracts/NunyaBusiness.sol | 25 +- .../nunya-contract/src/contract.rs | 486 ++++++++++++------ .../nunya-contract/src/msg.rs | 69 ++- .../nunya-contract/src/state.rs | 50 +- 5 files changed, 416 insertions(+), 225 deletions(-) diff --git a/packages/hardhat/contracts/DummyGateway.sol b/packages/hardhat/contracts/DummyGateway.sol index 2ea8169..fb21679 100644 --- a/packages/hardhat/contracts/DummyGateway.sol +++ b/packages/hardhat/contracts/DummyGateway.sol @@ -13,13 +13,16 @@ contract SecretContract { function linkPaymentRef(uint256 secret, string calldata ref) external returns (uint256) { return 5; } - function pay(string calldata ref, uint256 amount) external returns (uint256) { + // TODO: `string calldata secret` or `uint256 secret` + function pay(string calldata secret, string calldata ref, uint256 amount, uint256 denomination) external returns (uint256) { return 4; } - function payWithReceipt(string calldata ref, uint256 amount, uint256 userPubkey) external returns (uint256) { + // TODO: `string calldata secret` or `uint256 secret` + function payWithReceipt(string calldata secret, string calldata ref, uint256 amount, uint256 denomination, uint256 userPubkey) external returns (uint256) { return 3; } - function withdraw(string calldata secret, address withdrawalAddress) external returns (uint256){ + // TODO: `string calldata secret` or `uint256 secret` + function withdrawTo(string calldata secret, uint256 amount, uint256 denomination, address withdrawalAddress) external returns (uint256){ return 2; } @@ -27,4 +30,4 @@ contract SecretContract { return 1; } -} \ No newline at end of file +} diff --git a/packages/hardhat/contracts/NunyaBusiness.sol b/packages/hardhat/contracts/NunyaBusiness.sol index 5756836..32b22fe 100644 --- a/packages/hardhat/contracts/NunyaBusiness.sol +++ b/packages/hardhat/contracts/NunyaBusiness.sol @@ -9,9 +9,9 @@ import "hardhat/console.sol"; interface SecretContract { function newSecretUser(uint256 secret) external returns (uint256); function linkPaymentRef(uint256 secret, string calldata ref) external returns (uint256); - function pay(string calldata ref, uint256 amount) external returns (uint256); - function payWithReceipt(string calldata ref, uint256 amount, uint256 userPubkey) external returns (uint256); - function withdraw(string calldata secret, address withdrawalAddress) external returns (uint256); + function pay(string calldata ref, uint256 amount, uint256 denomination) external returns (uint256); + function payWithReceipt(string calldata ref, uint256 amount, uint256 denomination, uint256 userPubkey) external returns (uint256); + function withdrawTo(string calldata secret, uint256 amount, uint256 _denomination, address withdrawalAddress) external returns (uint256); function retrievePubkey() external returns (uint256); } @@ -27,6 +27,7 @@ contract NunyaBusiness { struct Receipt { uint256 paymentRef; uint256 amount; + uint256 denomination; bytes32 sig; } @@ -97,21 +98,23 @@ contract NunyaBusiness { } // TODO: use ref encrypted with (user pubkey+salt) - function pay(string calldata _ref, uint256 _amount) public payable returns (uint256) { + // TODO: `string calldata secret` or `uint256 secret` + function pay(string calldata _secret, string calldata _ref, uint256 _amount, uint256 _denomination) public payable returns (uint256) { // >= because we need gas for require (_amount >= msg.value, "Naughty!"); uint256 gasPaid = fundGateway(); - uint256 requestId = secretContract.pay(_ref, msg.value-gasPaid); + uint256 requestId = secretContract.pay(_secret, _ref, msg.value-gasPaid, _denomination); expectedResult[requestId]=FunctionCallType.PAY; return(requestId); } // TODO: use ref encrypted with (user pubkey+salt) - function pay(string calldata _ref, uint256 _amount, uint256 _userPubkey) public payable returns (uint256) { + // TODO: `string calldata secret` or `uint256 secret` + function pay(string calldata _secret, string calldata _ref, uint256 _amount, uint256 _denomination, uint256 _userPubkey) public payable returns (uint256) { // >= because we need gas for require (_amount >= msg.value, "Naughty!"); uint256 gasPaid = fundGateway(); - uint256 requestId = secretContract.payWithReceipt(_ref, msg.value-gasPaid, _userPubkey); + uint256 requestId = secretContract.payWithReceipt(_secret, _ref, msg.value-gasPaid, _denomination, _userPubkey); expectedResult[requestId]=FunctionCallType.PAY; return(requestId); } @@ -155,20 +158,22 @@ contract NunyaBusiness { } // Function wrapped in secret network payload encryption - function withdrawTo(string calldata _secret, uint256 _amount, address _withdrawalAddress) public payable returns (uint256) { + // TODO: `string calldata secret` or `uint256 secret` + function withdrawTo(string calldata _secret, uint256 _amount, uint256 _denomination, address _withdrawalAddress) public payable returns (uint256) { require((_amount > 0), "Account not found or empty."); fundGateway(msg.value); - uint256 requestId = secretContract.withdraw(_secret, _withdrawalAddress); + uint256 requestId = secretContract.withdrawTo(_secret, _amount, _denomination, _withdrawalAddress); // TODO: error check expectedResult[requestId]=FunctionCallType.WITHDRAW; return(requestId); } - function withdrawToCallback(uint256 _requestId, bool _success, uint256 _amount, address payable _withdrawalAddress) onlyGateway public { + function withdrawToCallback(uint256 _requestId, bool _success, uint256 _amount, uint256 _denomination, address payable _withdrawalAddress) onlyGateway public { require (expectedResult[_requestId]==FunctionCallType.WITHDRAW); if (!_success) emit SecretNetworkError(_requestId, "Error withdrawing - out of funds?"); require(_amount > 0, "Account not found or empty."); + // TODO: only if the `_denomination` is "ETH"? _withdrawalAddress.transfer(_amount); emit RequestSuccess(_requestId); } diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 12d31c8..100432c 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -1,18 +1,19 @@ use crate::{ msg::{ ExecuteMsg, GatewayMsg, InstantiateMsg, QueryMsg, - NewSecretUserStoreMsg, LinkPaymentRefStoreMsg, PayStoreMsg, PayEncryptedWithReceiptStoreMsg, WithdrawToStoreMsg, - ResponseStoreMsg, ResponseRetrievePubkeyMsg, + NewAuthOutStoreMsg, LinkPaymentRefStoreMsg, PayStoreMsg, WithdrawToStoreMsg, + ResponseNewAuthOutStoreMsg, ResponseLinkPaymentRefStoreMsg, ResponsePayStoreMsg, ResponseWithdrawToStoreMsg, ResponseRetrievePubkeyMsg, }, state::{ - NewSecretUser, LinkPaymentRef, Pay, PayEncryptedWithReceipt, WithdrawTo, + PaymentReceipt, PaymentReferenceBalance, ResponseStatusCode, State, CONFIG, - PUBKEY_MAP, NEW_SECRET_USER_MAP, LINK_PAYMENT_REF_MAP, PAY_MAP, PAY_ENCRYPTED_WITH_RECEIPT_MAP, WITHDRAW_TO_MAP, + VIEWING_KEY, VIEWING_KEY_TO_BALANCE_MAP, VIEWING_KEY_TO_PAYMENT_REF_MAP, }, }; use cosmwasm_std::{ - entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint128, Uint256 + entry_point, to_binary, coin, Binary, Deps, DepsMut, Env, HumanAddr, MessageInfo, Response, StdError, StdResult, Uint128, Uint256 }; +use secret_toolkit::viewing_key::{ViewingKey, ViewingKeyStore}; use secret_toolkit::utils::{pad_handle_result, pad_query_result, HandleCallback}; use tnls::{ msg::{PostExecutionMsg, PrivContractHandleMsg}, @@ -30,6 +31,7 @@ pub fn instantiate( _info: MessageInfo, msg: InstantiateMsg, ) -> StdResult { + // Initialise state let state = State { gateway_address: msg.gateway_address, gateway_hash: msg.gateway_hash, @@ -38,6 +40,12 @@ pub fn instantiate( CONFIG.save(deps.storage, &state)?; + // let msg = InstantiateMsg { + // gateway_address: gateway.to_string(), + // // TODO: + // secret_contract_pubkey: 1, + // }; + Ok(Response::default()) } @@ -59,6 +67,8 @@ fn try_handle( // verify signature with stored gateway public key let config = CONFIG.load(deps.storage)?; + // Security + // // reference: evm-kv-store-demo if info.sender != config.gateway_address { return Err(StdError::generic_err( @@ -77,17 +87,19 @@ fn try_handle( // determine which function to call based on the included handle let handle = msg.handle.as_str(); match handle { - "newSecretUser" => create_new_secret_user(deps, env, msg.input_values, msg.task, msg.input_hash), + "newSecretUser" => create_new_auth_out(deps, env, msg.input_values, msg.task, msg.input_hash), "linkPaymentRef" => create_link_payment_ref(deps, env, msg.input_values, msg.task, msg.input_hash), + // handle both `pay` and `payWithReceipt` Solidity function calls using the same `create_pay` Secret contract function "pay" => create_pay(deps, env, msg.input_values, msg.task, msg.input_hash), - "payWithReceipt" => create_pay_encrypted_with_receipt(deps, env, msg.input_values, msg.task, msg.input_hash), + "payWithReceipt" => create_pay(deps, env, msg.input_values, msg.task, msg.input_hash), "withdrawTo" => create_withdraw_to(deps, env, msg.input_values, msg.task, msg.input_hash), + // "setSecretContractPubkey" => create_secret_contract_pubkey(deps, env, msg.input_values, msg.task, msg.input_hash), _ => Err(StdError::generic_err("invalid handle".to_string())), } } -fn create_new_secret_user( +fn create_new_auth_out( deps: DepsMut, env: Env, input_values: String, @@ -96,30 +108,58 @@ fn create_new_secret_user( ) -> StdResult { let config = CONFIG.load(deps.storage)?; - let input: NewSecretUserStoreMsg = serde_json_wasm::from_str(&input_values) + let input: NewAuthOutStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - let secret_user = input.secret_user; - // .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + let viewing_key_index = input.secret_user.as_str(); // convert u8 to String + + assert!(viewing_key_index.chars().count() > 0, Err(StdError::generic_err("Secret must not be an empty string"))); + + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-introduction + // https://github.com/scrtlabs/examples/blob/master/secret-viewing-keys/secret-viewing-keys-contract/src/contract.rs + let viewing_key = ViewingKey::create(deps.storage, &info, &env, &gateway_account, b"entropy"); + + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation + let gateway_account = config.gateway_address.to_string(); + let suffix = viewing_key_index.to_string(); + let index_concat = gateway_account.push_str(suffix); + + // Viewing Key + VIEWING_KEY + // TODO - sender is always the gateway contract, or perhaps change this to `info.sender.as_bytes()` + .add_suffix(config.gateway_address.to_string()) + .insert(deps.storage, &viewing_key_index, &viewing_key)?; - let new_secret_user = NewSecretUser { - secret_user: secret_user + // Attempt to retrieve existing + let value_payment_reference_to_balances_map = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; + + // TODO: need to setup viewing key for the mapping, but not necessary to store this example + let init_balance: Coin = coin(0u128, String::new()); + let init_payment_ref = String::new(); + let init_payment_reference_balance = PaymentReferenceBalance { + payment_reference: init_payment_ref, + balance: init_balance, + }; + + let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing + None => Vec::new(), // If none are found, start with an empty vector }; - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = NEW_SECRET_USER_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + // Add the new to vector + value_payment_reference_to_balances.push(init_payment_reference_balance.clone()); - for key in key_iter_result? { - max_key = max_key.max(key?); - } - let new_key = max_key + 1; + // Save updated back to storage + VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; - // Insert the new item with the new key - NEW_SECRET_USER_MAP.insert(deps.storage, &new_key, &new_secret_user)?; + let response_status_code: ResponseStatusCode = 0u16; - let data = ResponseStoreMsg { - message: true, + let data = ResponseNewAuthOutStoreMsg { + _requestId: task, + _code: response_status_code, }; let json_string = @@ -128,9 +168,15 @@ fn create_new_secret_user( let result = base64::encode(json_string); let callback_msg = GatewayMsg::Output { + // Sepolia network gateway contract Solidity source code + // https://github.com/SecretSaturn/SecretPath/blob/main/TNLS-Gateways/public-gateway/src/Gateway.sol + // Sepolia network gateway contract deployed code (line 383, 914) + // https://sepolia.etherscan.io/address/0x0B6c705db59f7f02832d66B97b03E9EB3c0b4AAB#code + // Secret network gateway contract Rust source code `PostExecutionInfo` + // https://github.com/SecretSaturn/SecretPath/blob/main/TNLS-Gateways/solana-gateway/programs/solana-gateway/src/lib.rs#L737 outputs: PostExecutionMsg { result, - task, + task, // task is the requestId input_hash, }, } @@ -142,7 +188,7 @@ fn create_new_secret_user( Ok(Response::new() .add_message(callback_msg) - .add_attribute("status", "stored value with key")) + .add_attribute("status", "create_new_auth_out")) } fn create_link_payment_ref( @@ -157,34 +203,63 @@ fn create_link_payment_ref( let input: LinkPaymentRefStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - let secret_user = input - .secret_user; - // .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + let viewing_key_index = input.secret_user.as_str(); // convert u8 to String - let payment_ref = input - .payment_ref - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _ref: {}", err)))?; + assert!(viewing_key_index.chars().count() > 0, Err(StdError::generic_err("Secret must not be an empty string"))); - let link_payment_reference = LinkPaymentRef { - secret_user: secret_user, - payment_ref: payment_ref, - }; + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation + let gateway_account = config.gateway_address.to_string(); + let suffix = viewing_key_index.to_string(); + let index_concat = gateway_account.push_str(suffix); + + let result = ViewingKey::check(&deps.storage, &index_concat, b"entropy"); + assert_neq!(result, Err(StdError::generic_err("unauthorized"))); - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = LINK_PAYMENT_REF_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + let value_viewing_key = VIEWING_KEY + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY key not found"))?; - for key in key_iter_result? { - max_key = max_key.max(key?); + if value_viewing_key != index_concat { + return Err(StdError::generic_err("Viewing Key incorrect or not found")); } - let new_key = max_key + 1; - // Insert the item with the new key - LINK_PAYMENT_REF_MAP.insert(deps.storage, &new_key, &link_payment_reference)?; + let payment_ref = input.payment_ref.as_str(); // convert Uint256 to String + + assert!(payment_ref.chars().count() > 0, Err(StdError::generic_err("Payment reference must not be an empty string"))); + + // TODO: Check stored correctly but move to tests + let value_payment_reference_to_balances = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; + + // TODO: if payment_ref already exists in VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP value then early exit here + + let new_balance: Coin = coin(0u128, String::new()); + let new_payment_ref = payment_ref; + let new_payment_reference_balance: PaymentReferenceBalance = { + payment_reference: new_payment_ref, + balance: new_balance, + }; + + let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing + None => Vec::new(), // If none are found, start with an empty vector + }; + + // Add the new to vector + value_payment_reference_to_balances.push(new_payment_reference_balance.clone()); + + // Save updated back to storage + VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; + + + let response_status_code: ResponseStatusCode = 0u16; - let data = ResponseStoreMsg { - message: true, + let data = ResponseLinkPaymentRefStoreMsg { + _requestId: task, + _code: response_status_code, + _reference: value_payment_ref.as_str(), }; let json_string = @@ -207,7 +282,7 @@ fn create_link_payment_ref( Ok(Response::new() .add_message(callback_msg) - .add_attribute("status", "stored value with key")) + .add_attribute("status", "create_link_payment_ref")) } fn create_pay( @@ -222,107 +297,109 @@ fn create_pay( let input: PayStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - let payment_ref = input - .payment_ref - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _ref: {}", err)))?; + let viewing_key_index = input.secret_user.as_str(); // convert u8 to String + let payment_ref = input.payment_ref.as_str(); // convert Uint256 to String + // TODO: handle error if issue with amount or denomination received + let amount: Uint128 = input.amount.into(); // Uint128 + let denomination = input.denomination.as_str(); - let amount = input - .amount; - // .parse::() - // .map_err(|err| StdError::generic_err(format!("Invalid _amount: {}", err)))?; + assert!(viewing_key_index.chars().count() > 0, Err(StdError::generic_err("Secret must not be an empty string"))); + assert!(payment_ref.chars().count() > 0, Err(StdError::generic_err("Payment reference must not be an empty string"))); + assert!(amount >= 0u128, Err(StdError::generic_err("Payment amount must be greater than 0"))); + assert!(denomination.chars().count() > 0, Err(StdError::generic_err("Payment denomination must not be an empty string"))); - let pay = Pay { - payment_ref: payment_ref, - amount: amount, - }; + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation + let gateway_account = config.gateway_address.to_string(); + let suffix = viewing_key_index.to_string(); + let index_concat = gateway_account.push_str(suffix); + + let result = ViewingKey::check(&deps.storage, &index_concat, b"entropy"); + assert_neq!(result, Err(StdError::generic_err("unauthorized"))); - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = PAY_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + let value_viewing_key = VIEWING_KEY + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY key not found"))?; - for key in key_iter_result? { - max_key = max_key.max(key?); + if value_viewing_key != index_concat { + return Err(StdError::generic_err("Viewing Key incorrect or not found")); } - let new_key = max_key + 1; - // Insert the item with the new key - PAY_MAP.insert(deps.storage, &new_key, &pay)?; + // Attempt to retrieve existing + let value_payment_reference_to_balances_map = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; - let data = ResponseStoreMsg { - message: true, + let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing + None => StdError::generic_err("No payment references found"), // If none are found, early return }; - let json_string = - serde_json_wasm::to_string(&data).map_err(|err| StdError::generic_err(err.to_string()))?; - - let result = base64::encode(json_string); + // Check if matching `payment_ref` is in the vector since only pay if it exists + let index: usize = value_payment_reference_to_balances.iter().position(|&r| r.payment_reference == payment_ref).unwrap(); - let callback_msg = GatewayMsg::Output { - outputs: PostExecutionMsg { - result, - task, - input_hash, + let value_payment_reference_to_balances_match = match index { + Some(val) => { + println!("Found matching payment reference at index: {:#?}", index); + val }, - } - .to_cosmos_msg( - config.gateway_hash, - config.gateway_address.to_string(), - None, - )?; - - Ok(Response::new() - .add_message(callback_msg) - .add_attribute("status", "stored value with key")) -} - -fn create_pay_encrypted_with_receipt( - deps: DepsMut, - env: Env, - input_values: String, - task: Task, - input_hash: Binary, -) -> StdResult { - let config = CONFIG.load(deps.storage)?; - - let input: PayEncryptedWithReceiptStoreMsg = serde_json_wasm::from_str(&input_values) - .map_err(|err| StdError::generic_err(err.to_string()))?; - - let payment_ref = input - .payment_ref - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _ref: {}", err)))?; - - let amount = input - .amount; - // .parse::() - // .map_err(|err| StdError::generic_err(format!("Invalid _amount: {}", err)))?; - - let user_pubkey = input - .user_pubkey; - // .parse::() - // .map_err(|err| StdError::generic_err(format!("Invalid _userPubkey: {}", err)))?; - - let pay_encrypted_with_receipt = PayEncryptedWithReceipt { - payment_ref: payment_ref, - amount: amount, - user_pubkey: user_pubkey + None => StdError::generic_err("No payment references found"), }; - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = PAY_ENCRYPTED_WITH_RECEIPT_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + // Add pay amount to existing balance associated with the payment reference that was found + let new_balance_amount: Uint128 = value_payment_reference_to_balances_match.balance.amount.saturating_add(amount); + let new_balance: Coin = coin(&new_balance_amount, &denomination); + let new_payment_reference_balance = PaymentReferenceBalance { + payment_reference: payment_ref, + balance: new_balance, + }; - for key in key_iter_result? { - max_key = max_key.max(key?); + // Update the index in the vector with the matching payment reference + value_payment_reference_to_balances[index] = new_payment_reference_balance; + + // Save updated back to storage + VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; + + let mut receipt: Option = None; + + // FIXME: sign receipt using Secret contract's private key, currently just hardcoded. + // But how to get the Secret contract's public and private key? + let signature: bytes32 = "0x".as_bytes(); + + let user_pubkey: Uint256; + if let Some(ref _user_pubkey) = input.user_pubkey { + user_pubkey = _user_pubkey; + + // TODO: if user_pubkey has been provided then return encrypted receipt and signature with the user_pubkey + // TODO: still need to encrypt below with user_pubkey + receipt = Some({ + payment_reference: value_payment_ref, + // TODO: convert Uint256 to Uint128 + // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract + amount: new_balance_amount, + // TODO: serialise denomination + denomination: denomination, + sig: signature, + }); + } else { + // return receipt and signature unencrypted + receipt = Some({ + payment_reference: value_payment_ref, + // TODO: convert Uint256 to Uint128 + // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract + amount: new_balance_amount, + // TODO: serialise denomination + denomination: denomination, + sig: signature, + }); } - let new_key = max_key + 1; - // Insert the item with the new key - PAY_ENCRYPTED_WITH_RECEIPT_MAP.insert(deps.storage, &new_key, &pay_encrypted_with_receipt)?; + let response_status_code: ResponseStatusCode = 0u16; - let data = ResponseStoreMsg { - message: true, + let data = ResponsePayStoreMsg { + _requestId: task, + _code: response_status_code, + _receipt: receipt, }; let json_string = @@ -345,7 +422,7 @@ fn create_pay_encrypted_with_receipt( Ok(Response::new() .add_message(callback_msg) - .add_attribute("status", "stored value with key")) + .add_attribute("status", "create_pay")) } fn create_withdraw_to( @@ -360,39 +437,73 @@ fn create_withdraw_to( let input: WithdrawToStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - let secret_user = input - .secret_user; - // .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + let viewing_key_index = input.secret_user.as_str(); // convert u8 to String - let amount = input - .amount; - // .parse::() - // .map_err(|err| StdError::generic_err(format!("Invalid amount: {}", err)))?; + // Do not include receiving any payment reference since want to ignore it - let withdrawal_address = input - .withdrawal_address; - // .map_err(|err| StdError::generic_err(format!("Invalid withdrawalAddress: {}", err)))?; + // TODO: handle error if issue with amount or denomination received + let amount: Uint128 = input.amount.into(); // Uint128 + let denomination = input.denomination.as_str(); + let withdrawal_address: [u8; 20] = input.withdrawal_address.into(); // or `Addr` - let withdrawal_to = WithdrawTo { - secret_user: secret_user, - amount: amount, - withdrawal_address: withdrawal_address - }; + assert!(viewing_key_index.chars().count() > 0, Err(StdError::generic_err("Secret must not be an empty string"))); + // Do not validate payment reference since want to ignore it + assert!(amount >= 0u128, Err(StdError::generic_err("Payment amount must be greater than 0"))); + assert!(denomination.chars().count() > 0, Err(StdError::generic_err("Payment denomination must not be an empty string"))); + // TODO: validate withdrawal address input. check if could be `Addr` type + + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation + let gateway_account = config.gateway_address.to_string(); + let suffix = viewing_key_index.to_string(); + let index_concat = gateway_account.push_str(suffix); + + let result = ViewingKey::check(&deps.storage, &index_concat, b"entropy"); + assert_neq!(result, Err(StdError::generic_err("unauthorized"))); - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = WITHDRAW_TO_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + let value_viewing_key = VIEWING_KEY + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY key not found"))?; - for key in key_iter_result? { - max_key = max_key.max(key?); + if value_viewing_key != index_concat { + return Err(StdError::generic_err("Viewing Key incorrect or not found")); } - let new_key = max_key + 1; - // Insert the item with the new key - WITHDRAW_TO_MAP.insert(deps.storage, &new_key, &withdrawal_to)?; + // Attempt to retrieve existing + let value_payment_reference_to_balances_map = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; - let data = ResponseStoreMsg { - message: true, + let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing + None => StdError::generic_err("No payment references found"), // If none are found, early return + }; + + // Do not only withdraw associated with a specific payment reference at an index in the storage vector since want to ignore it + // Do not need to check that the `payment_ref` provided exists in storage since ignore it + // Do not need to check using the `payment_ref` that we want to withdraw using: + // the `amount` provided ensuring it is less than or equal to the amount stored associated with the payment reference + // and that the `denomination` matches the provided denomination that we want to withdraw + + // Do not store withdrawal address in state + // Do not transfer anything on Secret Network + // Only authorise the withdrawal + + let mut balance_all_payment_refs: Uint128 = 0u128; + for element in value_payment_reference_to_balances.into_iter() { + if element.balance.denom == denomination { + balance_all_payment_refs += element.balance.amount + } + } + + assert!(balance_all_payment_refs >= amount, Err(StdError::generic_err("Withdrawal amount must be less than or equal to total balance of all payment references"))); + + let response_status_code: ResponseStatusCode = 0u16; + + let data = ResponseWithdrawToStoreMsg { + _requestId: task, + _code: response_status_code, + _amount: amount, + _withdrawalAddress: withdrawal_address, }; let json_string = @@ -415,7 +526,7 @@ fn create_withdraw_to( Ok(Response::new() .add_message(callback_msg) - .add_attribute("status", "stored value with key")) + .add_attribute("status", "DO_THE_WITHDRAWAL")) } #[entry_point] @@ -426,12 +537,61 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { pad_query_result(response, BLOCK_SIZE) } +// TODO: remove `key: u32` fn retrieve_pubkey_query(deps: Deps, key: u32) -> StdResult { - let value = PUBKEY_MAP - .get(deps.storage, &key) - .ok_or_else(|| StdError::generic_err("Value not found"))?; + let config = CONFIG.load(deps.storage)?; + + let value: [u8; 32] = config.secret_contract_pubkey; to_binary(&ResponseRetrievePubkeyMsg { - message: true, + _key: value, }) } + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::testing::{message_info, mock_dependencies, mock_dependencies_with_balances, mock_env}; + use cosmwasm_std::coins; + use cosmwasm_std::{from_binary, StdError}; + + #[test] + fn proper_initialization() { + let mut deps = mock_dependencies(); + // Create some Addr instances for testing + let gateway = deps.api.addr_make("gateway"); + // https://docs.rs/cosmwasm-std/latest/cosmwasm_std/testing/fn.message_info.html + let msg = InstantiateMsg { + gateway_address: gateway.to_string(), + secret_contract_pubkey: 1, + }; + + let info = message_info(&gateway, &coins(1000, "earth")); + // we can just call .unwrap() to assert this was a success + let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); + + assert_eq!(0, res.messages.len()); + + // it worked, let's query the state + let res = query(deps.as_ref(), mock_env(), QueryMsg::RetrievePubkey {}).unwrap(); + let value: PubkeyResponse = from_binary(&res).unwrap(); + assert_eq!(1, value.secret_contract_pubkey); + } + + // // reference: SecretNetwork codebase + // #[test] + // fn querier_callbacks_work() { + // // Secret contract address + // let rich_addr = HumanAddr::from("foobar"); + // let rich_balance = coins(10000, "gold"); + // let deps = mock_dependencies_with_balances(20, &[(&rich_addr, &rich_balance)]); + + // // querying with balance gets the balance + // let bal = query_other_balance(&deps, rich_addr).unwrap(); + // assert_eq!(bal.amount, rich_balance); + + // // querying other accounts gets none + // let bal = query_other_balance(&deps, HumanAddr::from("someone else")).unwrap(); + // assert_eq!(bal.amount, vec![]); + // } +} diff --git a/packages/secret-contracts/nunya-contract/src/msg.rs b/packages/secret-contracts/nunya-contract/src/msg.rs index 0eec5bc..f11e3c9 100644 --- a/packages/secret-contracts/nunya-contract/src/msg.rs +++ b/packages/secret-contracts/nunya-contract/src/msg.rs @@ -1,15 +1,23 @@ use cosmwasm_std::{Addr, Binary, Uint128, Uint256}; use secret_toolkit::utils::HandleCallback; use tnls::msg::{PostExecutionMsg, PrivContractHandleMsg}; +use tnls::state::{Task} use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::{ + state::{ + ResponseStatusCode, + } +} + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct InstantiateMsg { pub gateway_address: Addr, pub gateway_hash: String, pub gateway_key: Binary, + pub secret_contract_pubkey: [u8; 32], } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -19,27 +27,25 @@ pub enum ExecuteMsg { } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct NewSecretUserStoreMsg { - pub secret_user: Addr, +pub struct NewAuthOutStoreMsg { + // TODO - is this key the variable of the parameter provided from Solidity contract to its new_secret_user function? + // secret_user or auth_out + pub secret_user: String, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct LinkPaymentRefStoreMsg { - pub secret_user: Addr, + pub secret_user: String, pub payment_ref: String, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct PayStoreMsg { + pub secret_user: String, pub payment_ref: String, pub amount: Uint128, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct PayEncryptedWithReceiptStoreMsg { - pub payment_ref: String, - pub amount: Uint128, - pub user_pubkey: Uint256, + pub denomination: Uint256, + pub user_pubkey: Option, // encrypted with receipt } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -50,9 +56,32 @@ pub struct WithdrawToStoreMsg { } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ResponseStoreMsg { - // response message - pub message: bool, +pub struct ResponseNewAuthOutStoreMsg { + pub _requestId: Task, + pub _code: ResponseStatusCode, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ResponseLinkPaymentRefStoreMsg { + pub _requestId: Task, + pub _code: ResponseStatusCode, + pub _reference: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ResponsePayStoreMsg { + pub _requestId: Task, + pub _code: ResponseStatusCode, + pub _receipt: Receipt, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ResponseWithdrawToStoreMsg { + pub _requestId: Task, + pub _code: ResponseStatusCode, + pub _amount: Uint128, + // TODO: should this be of type `Addr`? does it support EVM addresses? + pub _withdrawalAddress: Addr, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -63,16 +92,24 @@ pub enum QueryMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct ResponseRetrievePubkeyMsg { - // response message - pub message: bool, + // TODO: can only access `_requestId` if function called from `try_handle` and callback, but not from queries + // pub _requestId: Uint256, + pub _key: Uint256, } -// TODO: this may not be necessary +// TODO: this may not be necessary as not used #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct QueryResponse { pub message: String, } +// We define a custom struct for each query response +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] +pub struct PubkeyResponse { + pub secret_contract_pubkey: [u8; 32], +} + + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum GatewayMsg { diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index 7d71d1d..8077a35 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -1,51 +1,37 @@ -use cosmwasm_std::{Addr, Binary, Uint128, Uint256}; +use cosmwasm_std::{Addr, Binary, Coin, Uint128, Uint256}; use secret_toolkit::storage::{Item, Keymap}; +use secret_toolkit::viewing_key::{ViewingKey, ViewingKeyStore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; pub static CONFIG: Item = Item::new(b"config"); -pub static NEW_SECRET_USER_MAP: Keymap = Keymap::new(b"NEW_SECRET_USER_MAP"); -pub static PUBKEY_MAP: Keymap> = Keymap::new(b"PUBKEY_MAP"); -pub static LINK_PAYMENT_REF_MAP: Keymap> = Keymap::new(b"LINK_PAYMENT_REF_MAP"); -pub static PAY_MAP: Keymap> = Keymap::new(b"PAY_MAP"); -pub static PAY_ENCRYPTED_WITH_RECEIPT_MAP: Keymap> = Keymap::new(b"PAY_ENCRYPTED_WITH_RECEIPT_MAP"); -pub static WITHDRAW_TO_MAP: Keymap> = Keymap::new(b"WITHDRAW_TO_MAP"); +pub static VIEWING_KEY: Keymap = Keymap::new(b"VIEWING_KEY"); +pub static VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP: Keymap> = Keymap::new(b"VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP"); + +pub Index: u8; +pub ViewingKey: String; +pub ContractAddress: [u8; 32]; +pub ResponseStatusCode: u16; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct State { pub gateway_address: Addr, pub gateway_hash: String, pub gateway_key: Binary, + pub secret_contract_pubkey: [u8; 32], } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct NewSecretUser { - pub secret_user: Addr, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct LinkPaymentRef { - pub secret_user: Addr, - pub payment_ref: String, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct Pay { - pub payment_ref: String, - pub amount: Uint128, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct PayEncryptedWithReceipt { - pub payment_ref: String, - pub amount: Uint128, - pub user_pubkey: Uint256, +pub struct PaymentReferenceBalance { + pub payment_reference: String, + pub balance: Coin, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct WithdrawTo { - pub secret_user: Addr, - pub amount: Uint128, - pub withdrawal_address: Addr, +struct PaymentReceipt { + pub payment_reference: Uint256, + pub amount: Uint256, + pub denomination: Uint256, + pub sig: bytes32, } From d4d687a99f772c04899c66dc23b79aa5a81247e6 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Mon, 14 Oct 2024 19:01:41 +0200 Subject: [PATCH 04/13] WIP --- README.md | 26 ++--- packages/hardhat/contracts/DummyGateway.sol | 6 +- .../hardhat/contracts/ISecretContract.sol | 6 +- packages/hardhat/contracts/NunyaBusiness.sol | 8 +- .../nunya-contract/src/contract.rs | 97 +++++++++++-------- .../nunya-contract/src/msg.rs | 15 +-- .../nunya-contract/src/state.rs | 11 +-- 7 files changed, 85 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index 8757f98..844a6bf 100644 --- a/README.md +++ b/README.md @@ -82,21 +82,7 @@ Run smart contract test with `yarn hardhat:test` #### Create, Compile and Deploy Contract (Example: Counter) -* Reference https://docs.scrt.network/secret-network-documentation/development/readme-1/compile-and-deploy - -``` -mkdir -p packages/secret-contracts && cd packages/secret-contracts -cargo generate --git https://github.com/scrtlabs/secret-template.git --name my-counter-contract -``` - -* Compile. Note: Outputs contract.wasm and contract.wasm.gz file in the root directory of the secret-contracts/my-counter-contract folder - -``` -cd packages/secret-contracts/my-counter-contract -make build -``` - -* Note: To build on macOS it was necessary to run the following first as specified here https://github.com/rust-bitcoin/rust-secp256k1/issues/283#issuecomment-1590391777: +* Note: To build on macOS it was necessary to run the following first as specified here https://github.com/rust-bitcoin/rust-secp256k1/issues/283#issuecomment-1590391777. Other details https://github.com/briansmith/ring/issues/1824 ``` /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" @@ -105,14 +91,16 @@ llvm-config --version echo 'export AR=/opt/homebrew/opt/llvm/bin/llvm-ar' >> ~/.zshrc echo 'export CC=/opt/homebrew/opt/llvm/bin/clang' >> ~/.zshrc source ~/.zshrc -``` -* FIXME: attempt to fix on macOS hack https://github.com/briansmith/ring/issues/1824 +``` + +* Compile. Note: Outputs contract.wasm and contract.wasm.gz file in the root directory of the secret-contracts/nunya-contract folder + ``` cd packages/secret-contracts/nunya-contract make build ``` -* OPTIONAL - optimize contract code +* OPTIONAL - optimize contract code. Refer to official Secret network docs * Upload and Instantiate ``` @@ -122,6 +110,8 @@ yarn run secret:start:uploadContract * View logs at ./logs/instantiateOutput.log * View on Secret Testnet block explorer at https://testnet.ping.pub/secret/ +* Reference https://docs.scrt.network/secret-network-documentation/development/readme-1/compile-and-deploy + ### Specification: Notes on state and functions in the Secret contract #### State: diff --git a/packages/hardhat/contracts/DummyGateway.sol b/packages/hardhat/contracts/DummyGateway.sol index 7949c7e..4ff2d3d 100644 --- a/packages/hardhat/contracts/DummyGateway.sol +++ b/packages/hardhat/contracts/DummyGateway.sol @@ -18,17 +18,17 @@ contract DummyGatewayContract is ISecretContract { return 5; } // TODO: `string calldata secret` or `uint256 secret` - function pay(string calldata secret, string calldata ref, uint256 amount, uint256 denomination) external returns (uint256) { + function pay(string calldata secret, string calldata ref, uint256 amount, string calldata denomination) external returns (uint256) { // console.log("------ DummyGateway.pay", secret, ref, amount, denomination); return 4; } // TODO: `string calldata secret` or `uint256 secret` - function payWithReceipt(string calldata secret, string calldata ref, uint256 amount, uint256 denomination, uint256 userPubkey) external returns (uint256) { + function payWithReceipt(string calldata secret, string calldata ref, uint256 amount, string calldata denomination, uint256 userPubkey) external returns (uint256) { // console.log("------ DummyGateway.payWithReceipt", secret, ref, amount, denomination, userPubkey); return 3; } // TODO: `string calldata secret` or `uint256 secret` - function withdrawTo(string calldata secret, uint256 amount, uint256 denomination, address withdrawalAddress) external returns (uint256) { + function withdrawTo(string calldata secret, uint256 amount, string calldata denomination, address withdrawalAddress) external returns (uint256) { // console.log("------ DummyGateway.withdraw", secret, amount, denomination, withdrawalAddress); return 2; } diff --git a/packages/hardhat/contracts/ISecretContract.sol b/packages/hardhat/contracts/ISecretContract.sol index 82422f9..daeafb3 100644 --- a/packages/hardhat/contracts/ISecretContract.sol +++ b/packages/hardhat/contracts/ISecretContract.sol @@ -5,9 +5,9 @@ pragma solidity ^0.8.0; interface ISecretContract { function newSecretUser(string calldata secret) external returns (uint256); function createPaymentReference(string calldata secret, string calldata ref) external returns (uint256); - function pay(string calldata secret, string calldata ref, uint256 amount, uint256 denomination) external returns (uint256); - function payWithReceipt(string calldata secret, string calldata ref, uint256 amount, uint256 denomination, uint256 userPubkey) external returns (uint256); - function withdrawTo(string calldata secret, uint256 amount, uint256 _denomination, address withdrawalAddress) external returns (uint256); + function pay(string calldata secret, string calldata ref, uint256 amount, string calldata denomination) external returns (uint256); + function payWithReceipt(string calldata secret, string calldata ref, uint256 amount, string calldata denomination, uint256 userPubkey) external returns (uint256); + function withdrawTo(string calldata secret, uint256 amount, string calldata _denomination, address withdrawalAddress) external returns (uint256); function retrievePubkey() external returns (uint256); fallback() external payable; receive() external payable; diff --git a/packages/hardhat/contracts/NunyaBusiness.sol b/packages/hardhat/contracts/NunyaBusiness.sol index 4ba36fb..76ca0ce 100644 --- a/packages/hardhat/contracts/NunyaBusiness.sol +++ b/packages/hardhat/contracts/NunyaBusiness.sol @@ -121,7 +121,7 @@ contract NunyaBusiness { // TODO: use ref encrypted with (user pubkey+salt) // TODO: `string calldata secret` or `uint256 secret` - function pay(string calldata _secret, string calldata _ref, uint256 _value, uint256 _denomination) public payable returns (uint256) { + function pay(string calldata _secret, string calldata _ref, uint256 _value, string calldata _denomination) public payable returns (uint256) { // >= because we need gas for fees uint256 gasPaid = fundGateway(50000); // TODO 50000 is the minimum, need to adjust to a good estimate require(msg.value >= _value + gasPaid, "Not enough value sent to pay for gas."); @@ -140,7 +140,7 @@ contract NunyaBusiness { // TODO: use ref encrypted with (user pubkey+salt) // TODO: `string calldata secret` or `uint256 secret` - function payWithReceipt(string calldata _secret, string calldata _ref, uint256 _value, uint256 _denomination, uint256 _userPubkey) public payable returns (uint256) { + function payWithReceipt(string calldata _secret, string calldata _ref, uint256 _value, string calldata _denomination, uint256 _userPubkey) public payable returns (uint256) { uint256 gasPaid = fundGateway(50000); // TODO 50000 is the minimum, need to adjust to a good estimate require(msg.value >= _value + gasPaid, "Not enough value sent to pay for gas."); // QUESTION why is the user's pubkey required? How about the secret contact signs with it's pk and the user can validate using the secret contacts pubkey? @@ -178,7 +178,7 @@ contract NunyaBusiness { // Function wrapped in secret network payload encryption // TODO: `string calldata secret` or `uint256 secret` - function withdrawTo(string calldata _secret, uint256 _amount, uint256 _denomination, address _withdrawalAddress) public payable returns (uint256) { + function withdrawTo(string calldata _secret, uint256 _amount, string calldata _denomination, address _withdrawalAddress) public payable returns (uint256) { // IDEA _amount == 0 could signal I want all funds available; alternatively, sending max value could also work require((_amount > 0), "Need to provide the amount you want to withdraw."); fundGateway(50000); // TODO 50000 is the minimum, need to adjust to a good estimate @@ -189,7 +189,7 @@ contract NunyaBusiness { return(requestId); } - function withdrawToCallback(uint256 _requestId, uint16 _code, uint256 _amount, uint256 _denomination, address payable _withdrawalAddress) onlyGateway validateRequest(_requestId, FunctionCallType.WITHDRAW) public { + function withdrawToCallback(uint256 _requestId, uint16 _code, uint256 _amount, string calldata _denomination, address payable _withdrawalAddress) onlyGateway validateRequest(_requestId, FunctionCallType.WITHDRAW) public { // TODO: handle returning more specific errors in Secret contract if (_code == 0 && _amount == 0) { _code = ERROR_NO_FUNDS; diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 1c8e6fc..603c8cb 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -7,11 +7,11 @@ use crate::{ state::{ PaymentReceipt, PaymentReferenceBalance, ResponseStatusCode, State, CONFIG, - VIEWING_KEY, VIEWING_KEY_TO_BALANCE_MAP, VIEWING_KEY_TO_PAYMENT_REF_MAP, + VIEWING_KEY, VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP, }, }; use cosmwasm_std::{ - entry_point, to_binary, coin, Binary, Deps, DepsMut, Env, HumanAddr, MessageInfo, Response, StdError, StdResult, Uint128, Uint256 + entry_point, to_binary, coin, Binary, Coin, Deps, DepsMut, Env, HumanAddr, MessageInfo, Response, StdError, StdResult, Uint128, Uint256 }; use secret_toolkit::viewing_key::{ViewingKey, ViewingKeyStore}; use secret_toolkit::utils::{pad_handle_result, pad_query_result, HandleCallback}; @@ -61,7 +61,7 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> S fn try_handle( deps: DepsMut, env: Env, - _info: MessageInfo, + info: MessageInfo, msg: PrivContractHandleMsg, ) -> StdResult { // verify signature with stored gateway public key @@ -87,7 +87,7 @@ fn try_handle( // determine which function to call based on the included handle let handle = msg.handle.as_str(); match handle { - "newSecretUser" => create_new_auth_out(deps, env, msg.input_values, msg.task, msg.input_hash), + "newSecretUser" => create_new_auth_out(deps, env, info, msg.input_values, msg.task, msg.input_hash), "createPaymentReference" => create_payment_reference(deps, env, msg.input_values, msg.task, msg.input_hash), // handle both `pay` and `payWithReceipt` Solidity function calls using the same `create_pay` Secret contract function "pay" => create_pay(deps, env, msg.input_values, msg.task, msg.input_hash), @@ -101,6 +101,7 @@ fn try_handle( fn create_new_auth_out( deps: DepsMut, env: Env, + info: MessageInfo, input_values: String, task: Task, input_hash: Binary, @@ -112,17 +113,18 @@ fn create_new_auth_out( let viewing_key_index = input.secret_user.as_str(); // convert u8 to String - assert!(viewing_key_index.chars().count() > 0, Err(StdError::generic_err("Secret must not be an empty string"))); - - // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-introduction - // https://github.com/scrtlabs/examples/blob/master/secret-viewing-keys/secret-viewing-keys-contract/src/contract.rs - let viewing_key = ViewingKey::create(deps.storage, &info, &env, &gateway_account, b"entropy"); + assert!(viewing_key_index.chars().count() > 0, "{:?}", Err(StdError::generic_err("Secret must not be an empty string"))); // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index.to_string(); + let suffix = viewing_key_index.as_str(); let index_concat = gateway_account.push_str(suffix); + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-introduction + // https://github.com/scrtlabs/examples/blob/master/secret-viewing-keys/secret-viewing-keys-contract/src/contract.rs + let entropy: bytes = b"entropy"; + let viewing_key = ViewingKey::create(deps.storage, &info, &env, &gateway_account, entropy.as_str()); + // Viewing Key VIEWING_KEY // TODO - sender is always the gateway contract, or perhaps change this to `info.sender.as_bytes()` @@ -204,15 +206,16 @@ fn create_payment_reference( let viewing_key_index = input.secret_user.as_str(); // convert u8 to String - assert!(viewing_key_index.chars().count() > 0, Err(StdError::generic_err("Secret must not be an empty string"))); + assert!(viewing_key_index.chars().count() > 0, "{:?}", Err(StdError::generic_err("Secret must not be an empty string"))); // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index.to_string(); + let suffix = viewing_key_index.as_str(); let index_concat = gateway_account.push_str(suffix); - let result = ViewingKey::check(&deps.storage, &index_concat, b"entropy"); - assert_neq!(result, Err(StdError::generic_err("unauthorized"))); + let entropy: bytes = b"entropy"; + let result = ViewingKey::check(&deps.storage, &index_concat, entropy.as_str()); + assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let value_viewing_key = VIEWING_KEY .get(deps.storage, &index_concat) @@ -224,10 +227,10 @@ fn create_payment_reference( let payment_ref = input.payment_ref.as_str(); // convert Uint256 to String - assert!(payment_ref.chars().count() > 0, Err(StdError::generic_err("Payment reference must not be an empty string"))); + assert!(payment_ref.chars().count() > 0, "{:?}", Err(StdError::generic_err("Payment reference must not be an empty string"))); // TODO: Check stored correctly but move to tests - let value_payment_reference_to_balances = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + let value_payment_reference_to_balances_map = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP .get(deps.storage, &index_concat) .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; @@ -235,7 +238,7 @@ fn create_payment_reference( let new_balance: Coin = coin(0u128, String::new()); let new_payment_ref = payment_ref; - let new_payment_reference_balance: PaymentReferenceBalance = { + let new_payment_reference_balance = PaymentReferenceBalance { payment_reference: new_payment_ref, balance: new_balance, }; @@ -252,13 +255,12 @@ fn create_payment_reference( VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; - let response_status_code: ResponseStatusCode = 0u16; let data = ResponseLinkPaymentRefStoreMsg { _requestId: task, _code: response_status_code, - _reference: value_payment_ref.as_str(), + _reference: new_payment_ref.as_str(), }; let json_string = @@ -302,24 +304,25 @@ fn create_pay( let amount: Uint128 = input.amount.into(); // Uint128 let denomination = input.denomination.as_str(); - assert!(viewing_key_index.chars().count() > 0, Err(StdError::generic_err("Secret must not be an empty string"))); - assert!(payment_ref.chars().count() > 0, Err(StdError::generic_err("Payment reference must not be an empty string"))); - assert!(amount >= 0u128, Err(StdError::generic_err("Payment amount must be greater than 0"))); - assert!(denomination.chars().count() > 0, Err(StdError::generic_err("Payment denomination must not be an empty string"))); + assert!(viewing_key_index.chars().count() > 0, "{:?}", Err(StdError::generic_err("Secret must not be an empty string"))); + assert!(payment_ref.chars().count() > 0, "{:?}", Err(StdError::generic_err("Payment reference must not be an empty string"))); + assert!(amount >= 0u128.into(), "{:?}", Err(StdError::generic_err("Payment amount must be greater than 0"))); + assert!(denomination.chars().count() > 0, "{:?}", Err(StdError::generic_err("Payment denomination must not be an empty string"))); // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index.to_string(); + let suffix = viewing_key_index.as_str(); let index_concat = gateway_account.push_str(suffix); - let result = ViewingKey::check(&deps.storage, &index_concat, b"entropy"); - assert_neq!(result, Err(StdError::generic_err("unauthorized"))); + let entropy: bytes = b"entropy"; + let result = ViewingKey::check(&deps.storage, &index_concat, entropy.as_str()); + assert_ne!(result, Err(StdError::generic_err("unauthorized"))); - let value_viewing_key = VIEWING_KEY + let viewing_key = VIEWING_KEY .get(deps.storage, &index_concat) .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY key not found"))?; - if value_viewing_key != index_concat { + if viewing_key != index_concat { return Err(StdError::generic_err("Viewing Key incorrect or not found")); } @@ -346,7 +349,7 @@ fn create_pay( // Add pay amount to existing balance associated with the payment reference that was found let new_balance_amount: Uint128 = value_payment_reference_to_balances_match.balance.amount.saturating_add(amount); - let new_balance: Coin = coin(&new_balance_amount, &denomination); + let new_balance: Coin = coin(&new_balance_amount, denomination); let new_payment_reference_balance = PaymentReferenceBalance { payment_reference: payment_ref, balance: new_balance, @@ -367,28 +370,28 @@ fn create_pay( let user_pubkey: Uint256; if let Some(ref _user_pubkey) = input.user_pubkey { - user_pubkey = _user_pubkey; + user_pubkey = *_user_pubkey; // TODO: if user_pubkey has been provided then return encrypted receipt and signature with the user_pubkey // TODO: still need to encrypt below with user_pubkey - receipt = Some({ + receipt = Some(PaymentReceipt { payment_reference: value_payment_ref, // TODO: convert Uint256 to Uint128 // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract amount: new_balance_amount, // TODO: serialise denomination - denomination: denomination, + denomination: denomination.to_string(), sig: signature, }); } else { // return receipt and signature unencrypted - receipt = Some({ + receipt = Some(PaymentReceipt { payment_reference: value_payment_ref, // TODO: convert Uint256 to Uint128 // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract amount: new_balance_amount, // TODO: serialise denomination - denomination: denomination, + denomination: denomination.to_string(), sig: signature, }); } @@ -445,19 +448,20 @@ fn create_withdraw_to( let denomination = input.denomination.as_str(); let withdrawal_address: [u8; 20] = input.withdrawal_address.into(); // or `Addr` - assert!(viewing_key_index.chars().count() > 0, Err(StdError::generic_err("Secret must not be an empty string"))); + assert!(viewing_key_index.chars().count() > 0, "{:?}", Err(StdError::generic_err("Secret must not be an empty string"))); // Do not validate payment reference since want to ignore it - assert!(amount >= 0u128, Err(StdError::generic_err("Payment amount must be greater than 0"))); - assert!(denomination.chars().count() > 0, Err(StdError::generic_err("Payment denomination must not be an empty string"))); + assert!(amount >= 0u128.into(), "{:?}", Err(StdError::generic_err("Payment amount must be greater than 0"))); + assert!(denomination.chars().count() > 0, "{:?}", Err(StdError::generic_err("Payment denomination must not be an empty string"))); // TODO: validate withdrawal address input. check if could be `Addr` type // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index.to_string(); + let suffix = viewing_key_index.as_str(); let index_concat = gateway_account.push_str(suffix); - let result = ViewingKey::check(&deps.storage, &index_concat, b"entropy"); - assert_neq!(result, Err(StdError::generic_err("unauthorized"))); + let entropy: bytes = b"entropy"; + let result = ViewingKey::check(&deps.storage, &index_concat, entropy.as_str()); + assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let value_viewing_key = VIEWING_KEY .get(deps.storage, &index_concat) @@ -487,14 +491,21 @@ fn create_withdraw_to( // Do not transfer anything on Secret Network // Only authorise the withdrawal - let mut balance_all_payment_refs: Uint128 = 0u128; + let mut balance_all_payment_refs: Uint128 = 0u128.into(); for element in value_payment_reference_to_balances.into_iter() { if element.balance.denom == denomination { balance_all_payment_refs += element.balance.amount } } - - assert!(balance_all_payment_refs >= amount, Err(StdError::generic_err("Withdrawal amount must be less than or equal to total balance of all payment references"))); +use crate::{ + msg::{ + ExecuteMsg, GatewayMsg, InstantiateMsg, ProposalStoreMsg, QueryMsg, + ResponseRetrieveProposalMsg, ResponseRetrieveVotesMsg, ResponseStoreProposalMsg, + VoteStoreMsg, + }, + state::{Proposal, State, Vote, CONFIG, PROPOSAL_MAP, VOTE_MAP}, +}; + assert!(balance_all_payment_refs >= amount, "{:?}", Err(StdError::generic_err("Withdrawal amount must be less than or equal to total balance of all payment references"))); let response_status_code: ResponseStatusCode = 0u16; diff --git a/packages/secret-contracts/nunya-contract/src/msg.rs b/packages/secret-contracts/nunya-contract/src/msg.rs index f11e3c9..007f748 100644 --- a/packages/secret-contracts/nunya-contract/src/msg.rs +++ b/packages/secret-contracts/nunya-contract/src/msg.rs @@ -1,7 +1,7 @@ use cosmwasm_std::{Addr, Binary, Uint128, Uint256}; use secret_toolkit::utils::HandleCallback; use tnls::msg::{PostExecutionMsg, PrivContractHandleMsg}; -use tnls::state::{Task} +use tnls::state::{Task}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -10,7 +10,7 @@ use crate::{ state::{ ResponseStatusCode, } -} +}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct InstantiateMsg { @@ -44,15 +44,16 @@ pub struct PayStoreMsg { pub secret_user: String, pub payment_ref: String, pub amount: Uint128, - pub denomination: Uint256, + pub denomination: String, pub user_pubkey: Option, // encrypted with receipt } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct WithdrawToStoreMsg { - pub secret_user: Addr, + pub secret_user: String, pub amount: Uint128, - pub withdrawal_address: Addr, + pub denomination: String, + pub withdrawal_address: [u8; 20], } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -72,7 +73,7 @@ pub struct ResponseLinkPaymentRefStoreMsg { pub struct ResponsePayStoreMsg { pub _requestId: Task, pub _code: ResponseStatusCode, - pub _receipt: Receipt, + pub _receipt: PaymentReceipt, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -81,7 +82,7 @@ pub struct ResponseWithdrawToStoreMsg { pub _code: ResponseStatusCode, pub _amount: Uint128, // TODO: should this be of type `Addr`? does it support EVM addresses? - pub _withdrawalAddress: Addr, + pub _withdrawalAddress: [u8; 20], } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index 8077a35..4dd87be 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -9,10 +9,9 @@ pub static CONFIG: Item = Item::new(b"config"); pub static VIEWING_KEY: Keymap = Keymap::new(b"VIEWING_KEY"); pub static VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP: Keymap> = Keymap::new(b"VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP"); -pub Index: u8; -pub ViewingKey: String; -pub ContractAddress: [u8; 32]; -pub ResponseStatusCode: u16; +pub type Index: u8; +// pub type ContractAddress: [u8; 32]; +pub type ResponseStatusCode: u16; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct State { @@ -29,9 +28,9 @@ pub struct PaymentReferenceBalance { } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -struct PaymentReceipt { +pub struct PaymentReceipt { pub payment_reference: Uint256, pub amount: Uint256, - pub denomination: Uint256, + pub denomination: String, pub sig: bytes32, } From 835684ad718262b9d7fa822abcc23ce6ae996900 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Mon, 14 Oct 2024 21:20:15 +0200 Subject: [PATCH 05/13] feat: allow query Secret contract public key --- .../nunya-contract/src/contract.rs | 44 ++++--------------- .../nunya-contract/src/msg.rs | 12 +---- .../nunya-contract/src/state.rs | 11 ++++- 3 files changed, 20 insertions(+), 47 deletions(-) diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 603c8cb..667caff 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -6,7 +6,7 @@ use crate::{ }, state::{ PaymentReceipt, PaymentReferenceBalance, ResponseStatusCode, - State, CONFIG, + MyKeys, State, CONFIG, MY_KEYS, VIEWING_KEY, VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP, }, }; @@ -40,12 +40,6 @@ pub fn instantiate( CONFIG.save(deps.storage, &state)?; - // let msg = InstantiateMsg { - // gateway_address: gateway.to_string(), - // // TODO: - // secret_contract_pubkey: 1, - // }; - Ok(Response::default()) } @@ -542,19 +536,15 @@ use crate::{ #[entry_point] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { let response = match msg { - QueryMsg::RetrievePubkey { key } => retrieve_pubkey_query(deps, key), + QueryMsg::RetrievePubkey {} => to_binary(&retrieve_pubkey_query(deps)?), }; pad_query_result(response, BLOCK_SIZE) } -// TODO: remove `key: u32` -fn retrieve_pubkey_query(deps: Deps, key: u32) -> StdResult { - let config = CONFIG.load(deps.storage)?; - - let value: [u8; 32] = config.secret_contract_pubkey; - - to_binary(&ResponseRetrievePubkeyMsg { - _key: value, +fn retrieve_pubkey_query(deps: Deps) -> StdResult { + let my_keys = MY_KEYS.load(deps.storage)?; + Ok(ResponseRetrievePubkeyMsg { + _key: my_keys.public_key, }) } @@ -573,7 +563,6 @@ mod tests { // https://docs.rs/cosmwasm-std/latest/cosmwasm_std/testing/fn.message_info.html let msg = InstantiateMsg { gateway_address: gateway.to_string(), - secret_contract_pubkey: 1, }; let info = message_info(&gateway, &coins(1000, "earth")); @@ -584,24 +573,7 @@ mod tests { // it worked, let's query the state let res = query(deps.as_ref(), mock_env(), QueryMsg::RetrievePubkey {}).unwrap(); - let value: PubkeyResponse = from_binary(&res).unwrap(); - assert_eq!(1, value.secret_contract_pubkey); + let res: ResponseRetrievePubkeyMsg = from_binary(&res).unwrap(); + assert!(res._key); } - - // // reference: SecretNetwork codebase - // #[test] - // fn querier_callbacks_work() { - // // Secret contract address - // let rich_addr = HumanAddr::from("foobar"); - // let rich_balance = coins(10000, "gold"); - // let deps = mock_dependencies_with_balances(20, &[(&rich_addr, &rich_balance)]); - - // // querying with balance gets the balance - // let bal = query_other_balance(&deps, rich_addr).unwrap(); - // assert_eq!(bal.amount, rich_balance); - - // // querying other accounts gets none - // let bal = query_other_balance(&deps, HumanAddr::from("someone else")).unwrap(); - // assert_eq!(bal.amount, vec![]); - // } } diff --git a/packages/secret-contracts/nunya-contract/src/msg.rs b/packages/secret-contracts/nunya-contract/src/msg.rs index 007f748..8a5b993 100644 --- a/packages/secret-contracts/nunya-contract/src/msg.rs +++ b/packages/secret-contracts/nunya-contract/src/msg.rs @@ -17,7 +17,6 @@ pub struct InstantiateMsg { pub gateway_address: Addr, pub gateway_hash: String, pub gateway_key: Binary, - pub secret_contract_pubkey: [u8; 32], } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -88,14 +87,14 @@ pub struct ResponseWithdrawToStoreMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { - RetrievePubkey { key: u32 }, + RetrievePubkey {}, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct ResponseRetrievePubkeyMsg { // TODO: can only access `_requestId` if function called from `try_handle` and callback, but not from queries // pub _requestId: Uint256, - pub _key: Uint256, + pub _key: Vec, } // TODO: this may not be necessary as not used @@ -104,13 +103,6 @@ pub struct QueryResponse { pub message: String, } -// We define a custom struct for each query response -#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] -pub struct PubkeyResponse { - pub secret_contract_pubkey: [u8; 32], -} - - #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum GatewayMsg { diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index 4dd87be..5386410 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -5,6 +5,7 @@ use secret_toolkit::viewing_key::{ViewingKey, ViewingKeyStore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +pub static MY_KEYS: Item = Item::new(b"my_keys"); pub static CONFIG: Item = Item::new(b"config"); pub static VIEWING_KEY: Keymap = Keymap::new(b"VIEWING_KEY"); pub static VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP: Keymap> = Keymap::new(b"VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP"); @@ -18,7 +19,15 @@ pub struct State { pub gateway_address: Addr, pub gateway_hash: String, pub gateway_key: Binary, - pub secret_contract_pubkey: [u8; 32], +} + + +// Secret contract keys +// Reference: https://github.com/writersblockchain/aes-encrypt/blob/afa384d69aaddd92b50323fe1b9324f1342a5c0e/src/state.rs#L7 +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct MyKeys { + pub public_key: Vec, + pub private_key: Vec, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] From 93315569ea062851052feea5b8e3f06b2cb12611 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Mon, 14 Oct 2024 23:10:39 +0200 Subject: [PATCH 06/13] chore: fix some compiler errors --- .../nunya-contract/src/contract.rs | 59 ++++++++----------- .../nunya-contract/src/msg.rs | 2 +- .../nunya-contract/src/state.rs | 9 ++- 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 667caff..c8d189d 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -111,7 +111,7 @@ fn create_new_auth_out( // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index.as_str(); + let suffix = viewing_key_index; let index_concat = gateway_account.push_str(suffix); // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-introduction @@ -204,11 +204,11 @@ fn create_payment_reference( // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index.as_str(); + let suffix = viewing_key_index; let index_concat = gateway_account.push_str(suffix); let entropy: bytes = b"entropy"; - let result = ViewingKey::check(&deps.storage, &index_concat, entropy.as_str()); + let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_str()); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let value_viewing_key = VIEWING_KEY @@ -233,7 +233,7 @@ fn create_payment_reference( let new_balance: Coin = coin(0u128, String::new()); let new_payment_ref = payment_ref; let new_payment_reference_balance = PaymentReferenceBalance { - payment_reference: new_payment_ref, + payment_reference: new_payment_ref.to_string(), balance: new_balance, }; @@ -254,7 +254,7 @@ fn create_payment_reference( let data = ResponseLinkPaymentRefStoreMsg { _requestId: task, _code: response_status_code, - _reference: new_payment_ref.as_str(), + _reference: new_payment_ref.to_string(), }; let json_string = @@ -305,11 +305,11 @@ fn create_pay( // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index.as_str(); + let suffix = viewing_key_index; let index_concat = gateway_account.push_str(suffix); let entropy: bytes = b"entropy"; - let result = ViewingKey::check(&deps.storage, &index_concat, entropy.as_str()); + let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_str()); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let viewing_key = VIEWING_KEY @@ -327,36 +327,36 @@ fn create_pay( let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing - None => StdError::generic_err("No payment references found"), // If none are found, early return + None => return Err(StdError::generic_err("No payment references found")), // If none are found, early return }; // Check if matching `payment_ref` is in the vector since only pay if it exists - let index: usize = value_payment_reference_to_balances.iter().position(|&r| r.payment_reference == payment_ref).unwrap(); + let index: Option = Some(value_payment_reference_to_balances.iter().position(|&r| r.payment_reference == payment_ref).unwrap()); - let value_payment_reference_to_balances_match = match index { + let index_value_payment_reference_to_balances = match index { Some(val) => { - println!("Found matching payment reference at index: {:#?}", index); + println!("Found matching payment reference at index: {:#?}", val); val }, - None => StdError::generic_err("No payment references found"), + None => return Err(StdError::generic_err("No payment references found")), }; // Add pay amount to existing balance associated with the payment reference that was found - let new_balance_amount: Uint128 = value_payment_reference_to_balances_match.balance.amount.saturating_add(amount); + let new_balance_amount: Uint128 = index_value_payment_reference_to_balances.balance.amount.saturating_add(amount); let new_balance: Coin = coin(&new_balance_amount, denomination); let new_payment_reference_balance = PaymentReferenceBalance { - payment_reference: payment_ref, + payment_reference: payment_ref.to_string(), balance: new_balance, }; // Update the index in the vector with the matching payment reference - value_payment_reference_to_balances[index] = new_payment_reference_balance; + value_payment_reference_to_balances[index_value_payment_reference_to_balances] = new_payment_reference_balance; // Save updated back to storage VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; - let mut receipt: Option = None; + let mut receipt: PaymentReceipt; // FIXME: sign receipt using Secret contract's private key, currently just hardcoded. // But how to get the Secret contract's public and private key? @@ -368,26 +368,26 @@ fn create_pay( // TODO: if user_pubkey has been provided then return encrypted receipt and signature with the user_pubkey // TODO: still need to encrypt below with user_pubkey - receipt = Some(PaymentReceipt { - payment_reference: value_payment_ref, + receipt = PaymentReceipt { + payment_reference: payment_ref.to_string(), // TODO: convert Uint256 to Uint128 // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract amount: new_balance_amount, // TODO: serialise denomination denomination: denomination.to_string(), sig: signature, - }); + }; } else { // return receipt and signature unencrypted - receipt = Some(PaymentReceipt { - payment_reference: value_payment_ref, + receipt = PaymentReceipt { + payment_reference: payment_ref.to_string(), // TODO: convert Uint256 to Uint128 // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract amount: new_balance_amount, // TODO: serialise denomination denomination: denomination.to_string(), sig: signature, - }); + }; } let response_status_code: ResponseStatusCode = 0u16; @@ -450,11 +450,11 @@ fn create_withdraw_to( // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index.as_str(); + let suffix = viewing_key_index; let index_concat = gateway_account.push_str(suffix); let entropy: bytes = b"entropy"; - let result = ViewingKey::check(&deps.storage, &index_concat, entropy.as_str()); + let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_str()); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let value_viewing_key = VIEWING_KEY @@ -472,7 +472,7 @@ fn create_withdraw_to( let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing - None => StdError::generic_err("No payment references found"), // If none are found, early return + None => return Err(StdError::generic_err("No payment references found")), // If none are found, early return }; // Do not only withdraw associated with a specific payment reference at an index in the storage vector since want to ignore it @@ -491,14 +491,7 @@ fn create_withdraw_to( balance_all_payment_refs += element.balance.amount } } -use crate::{ - msg::{ - ExecuteMsg, GatewayMsg, InstantiateMsg, ProposalStoreMsg, QueryMsg, - ResponseRetrieveProposalMsg, ResponseRetrieveVotesMsg, ResponseStoreProposalMsg, - VoteStoreMsg, - }, - state::{Proposal, State, Vote, CONFIG, PROPOSAL_MAP, VOTE_MAP}, -}; + assert!(balance_all_payment_refs >= amount, "{:?}", Err(StdError::generic_err("Withdrawal amount must be less than or equal to total balance of all payment references"))); let response_status_code: ResponseStatusCode = 0u16; diff --git a/packages/secret-contracts/nunya-contract/src/msg.rs b/packages/secret-contracts/nunya-contract/src/msg.rs index 8a5b993..4b41bad 100644 --- a/packages/secret-contracts/nunya-contract/src/msg.rs +++ b/packages/secret-contracts/nunya-contract/src/msg.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::{ state::{ - ResponseStatusCode, + PaymentReceipt, ResponseStatusCode, } }; diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index 5386410..b8ef013 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -10,9 +10,9 @@ pub static CONFIG: Item = Item::new(b"config"); pub static VIEWING_KEY: Keymap = Keymap::new(b"VIEWING_KEY"); pub static VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP: Keymap> = Keymap::new(b"VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP"); -pub type Index: u8; -// pub type ContractAddress: [u8; 32]; -pub type ResponseStatusCode: u16; +pub type Index = u8; +// pub type ContractAddress = [u8; 32]; +pub type ResponseStatusCode = u16; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct State { @@ -21,7 +21,6 @@ pub struct State { pub gateway_key: Binary, } - // Secret contract keys // Reference: https://github.com/writersblockchain/aes-encrypt/blob/afa384d69aaddd92b50323fe1b9324f1342a5c0e/src/state.rs#L7 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] @@ -38,7 +37,7 @@ pub struct PaymentReferenceBalance { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct PaymentReceipt { - pub payment_reference: Uint256, + pub payment_reference: String, pub amount: Uint256, pub denomination: String, pub sig: bytes32, From 6353dfac86e9512a53d39b72f67379a588a8aaf5 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Mon, 14 Oct 2024 23:23:34 +0200 Subject: [PATCH 07/13] chore: fix more compiler errors --- .../nunya-contract/src/contract.rs | 20 +++++++++---------- .../nunya-contract/src/state.rs | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index c8d189d..147fb2c 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -11,7 +11,7 @@ use crate::{ }, }; use cosmwasm_std::{ - entry_point, to_binary, coin, Binary, Coin, Deps, DepsMut, Env, HumanAddr, MessageInfo, Response, StdError, StdResult, Uint128, Uint256 + entry_point, to_binary, coin, Binary, Coin, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint128, Uint256 }; use secret_toolkit::viewing_key::{ViewingKey, ViewingKeyStore}; use secret_toolkit::utils::{pad_handle_result, pad_query_result, HandleCallback}; @@ -116,8 +116,8 @@ fn create_new_auth_out( // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-introduction // https://github.com/scrtlabs/examples/blob/master/secret-viewing-keys/secret-viewing-keys-contract/src/contract.rs - let entropy: bytes = b"entropy"; - let viewing_key = ViewingKey::create(deps.storage, &info, &env, &gateway_account, entropy.as_str()); + let entropy: Binary = b"entropy".into(); + let viewing_key = ViewingKey::create(deps.storage, &info, &env, &gateway_account, entropy.as_ptr()); // Viewing Key VIEWING_KEY @@ -207,8 +207,8 @@ fn create_payment_reference( let suffix = viewing_key_index; let index_concat = gateway_account.push_str(suffix); - let entropy: bytes = b"entropy"; - let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_str()); + let entropy: Binary = b"entropy".into(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_ptr()); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let value_viewing_key = VIEWING_KEY @@ -308,8 +308,8 @@ fn create_pay( let suffix = viewing_key_index; let index_concat = gateway_account.push_str(suffix); - let entropy: bytes = b"entropy"; - let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_str()); + let entropy: Binary = b"entropy".into(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_ptr()); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let viewing_key = VIEWING_KEY @@ -360,7 +360,7 @@ fn create_pay( // FIXME: sign receipt using Secret contract's private key, currently just hardcoded. // But how to get the Secret contract's public and private key? - let signature: bytes32 = "0x".as_bytes(); + let signature: Binary = "0x".as_bytes().into(); let user_pubkey: Uint256; if let Some(ref _user_pubkey) = input.user_pubkey { @@ -453,8 +453,8 @@ fn create_withdraw_to( let suffix = viewing_key_index; let index_concat = gateway_account.push_str(suffix); - let entropy: bytes = b"entropy"; - let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_str()); + let entropy: Binary = b"entropy".into(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_ptr()); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let value_viewing_key = VIEWING_KEY diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index b8ef013..b83592c 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -40,5 +40,5 @@ pub struct PaymentReceipt { pub payment_reference: String, pub amount: Uint256, pub denomination: String, - pub sig: bytes32, + pub sig: Binary, } From 3022868270e13348a73e8af11ed1f8e2bcfc263f Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Tue, 15 Oct 2024 00:07:42 +0200 Subject: [PATCH 08/13] fix: Fix ViewingKey usage error --- packages/secret-contracts/nunya-contract/src/contract.rs | 6 +++--- packages/secret-contracts/nunya-contract/src/state.rs | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 147fb2c..3e2b495 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -122,7 +122,7 @@ fn create_new_auth_out( // Viewing Key VIEWING_KEY // TODO - sender is always the gateway contract, or perhaps change this to `info.sender.as_bytes()` - .add_suffix(config.gateway_address.to_string()) + .add_suffix(config.gateway_address.as_bytes()) .insert(deps.storage, &viewing_key_index, &viewing_key)?; // Attempt to retrieve existing @@ -211,11 +211,11 @@ fn create_payment_reference( let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_ptr()); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); - let value_viewing_key = VIEWING_KEY + let viewing_key = VIEWING_KEY .get(deps.storage, &index_concat) .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY key not found"))?; - if value_viewing_key != index_concat { + if viewing_key != index_concat { return Err(StdError::generic_err("Viewing Key incorrect or not found")); } diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index b83592c..3445e74 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -1,19 +1,21 @@ use cosmwasm_std::{Addr, Binary, Coin, Uint128, Uint256}; use secret_toolkit::storage::{Item, Keymap}; -use secret_toolkit::viewing_key::{ViewingKey, ViewingKeyStore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; pub static MY_KEYS: Item = Item::new(b"my_keys"); pub static CONFIG: Item = Item::new(b"config"); -pub static VIEWING_KEY: Keymap = Keymap::new(b"VIEWING_KEY"); -pub static VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP: Keymap> = Keymap::new(b"VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP"); +pub static VIEWING_KEY: Keymap = Keymap::new(b"VIEWING_KEY"); +pub static VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP: Keymap> = Keymap::new(b"VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP"); pub type Index = u8; // pub type ContractAddress = [u8; 32]; pub type ResponseStatusCode = u16; +// reference: https://github.com/scrtlabs/examples/blob/master/secret-viewing-keys/secret-viewing-keys-contract/src/state.rs +pub type VK = String; // Viewing Key + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct State { pub gateway_address: Addr, From 7c797e99e76bb0735c8b650213f0d9d4388be6c9 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Tue, 15 Oct 2024 02:52:04 +0200 Subject: [PATCH 09/13] chore: Secret contract fully compiles. now resolve deployment errors --- .../nunya-contract/src/contract.rs | 152 +++++++++++------- .../nunya-contract/src/msg.rs | 10 +- .../nunya-contract/src/state.rs | 4 +- 3 files changed, 99 insertions(+), 67 deletions(-) diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 3e2b495..5f444cd 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -6,7 +6,7 @@ use crate::{ }, state::{ PaymentReceipt, PaymentReferenceBalance, ResponseStatusCode, - MyKeys, State, CONFIG, MY_KEYS, + State, CONFIG, MY_KEYS, VIEWING_KEY, VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP, }, }; @@ -107,28 +107,32 @@ fn create_new_auth_out( let viewing_key_index = input.secret_user.as_str(); // convert u8 to String - assert!(viewing_key_index.chars().count() > 0, "{:?}", Err(StdError::generic_err("Secret must not be an empty string"))); + if viewing_key_index.chars().count() == 0 { + return Err(StdError::generic_err("Secret must not be an empty string")); + } // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation - let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index; - let index_concat = gateway_account.push_str(suffix); + let gateway_account = config.gateway_address.to_owned(); + let mut index_concat: String = gateway_account.to_string(); + let suffix: &str = viewing_key_index; + // mutate in place https://stackoverflow.com/a/30154791/3208553 + index_concat.push_str(suffix); // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-introduction // https://github.com/scrtlabs/examples/blob/master/secret-viewing-keys/secret-viewing-keys-contract/src/contract.rs - let entropy: Binary = b"entropy".into(); - let viewing_key = ViewingKey::create(deps.storage, &info, &env, &gateway_account, entropy.as_ptr()); + let entropy: &[u8] = b"entropy"; + let viewing_key = ViewingKey::create(deps.storage, &info, &env, gateway_account.as_str(), entropy); // Viewing Key VIEWING_KEY // TODO - sender is always the gateway contract, or perhaps change this to `info.sender.as_bytes()` .add_suffix(config.gateway_address.as_bytes()) - .insert(deps.storage, &viewing_key_index, &viewing_key)?; + .insert(deps.storage, &viewing_key_index.to_string(), &viewing_key)?; // Attempt to retrieve existing - let value_payment_reference_to_balances_map = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + let value_payment_reference_to_balances_map: Option> = Some(VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP .get(deps.storage, &index_concat) - .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?); // TODO: need to setup viewing key for the mapping, but not necessary to store this example let init_balance: Coin = coin(0u128, String::new()); @@ -153,7 +157,7 @@ fn create_new_auth_out( let response_status_code: ResponseStatusCode = 0u16; let data = ResponseNewAuthOutStoreMsg { - _requestId: task, + _request_id: task.clone(), _code: response_status_code, }; @@ -188,7 +192,7 @@ fn create_new_auth_out( fn create_payment_reference( deps: DepsMut, - env: Env, + _env: Env, input_values: String, task: Task, input_hash: Binary, @@ -200,15 +204,19 @@ fn create_payment_reference( let viewing_key_index = input.secret_user.as_str(); // convert u8 to String - assert!(viewing_key_index.chars().count() > 0, "{:?}", Err(StdError::generic_err("Secret must not be an empty string"))); + if viewing_key_index.chars().count() == 0 { + return Err(StdError::generic_err("Secret must not be an empty string")); + } // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation - let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index; - let index_concat = gateway_account.push_str(suffix); - - let entropy: Binary = b"entropy".into(); - let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_ptr()); + let gateway_account = config.gateway_address.to_owned(); + let mut index_concat: String = gateway_account.to_string(); + let suffix: &str = viewing_key_index; + index_concat.push_str(suffix); + + let binding = "entropy".to_string(); + let entropy: &str = binding.as_str(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let viewing_key = VIEWING_KEY @@ -221,12 +229,14 @@ fn create_payment_reference( let payment_ref = input.payment_ref.as_str(); // convert Uint256 to String - assert!(payment_ref.chars().count() > 0, "{:?}", Err(StdError::generic_err("Payment reference must not be an empty string"))); + if payment_ref.chars().count() == 0 { + return Err(StdError::generic_err("Payment reference must not be an empty string")); + } // TODO: Check stored correctly but move to tests - let value_payment_reference_to_balances_map = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + let value_payment_reference_to_balances_map: Option> = Some(VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP .get(deps.storage, &index_concat) - .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?); // TODO: if payment_ref already exists in VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP value then early exit here @@ -252,7 +262,7 @@ fn create_payment_reference( let response_status_code: ResponseStatusCode = 0u16; let data = ResponseLinkPaymentRefStoreMsg { - _requestId: task, + _request_id: task.clone(), _code: response_status_code, _reference: new_payment_ref.to_string(), }; @@ -282,7 +292,7 @@ fn create_payment_reference( fn create_pay( deps: DepsMut, - env: Env, + _env: Env, input_values: String, task: Task, input_hash: Binary, @@ -298,18 +308,28 @@ fn create_pay( let amount: Uint128 = input.amount.into(); // Uint128 let denomination = input.denomination.as_str(); - assert!(viewing_key_index.chars().count() > 0, "{:?}", Err(StdError::generic_err("Secret must not be an empty string"))); - assert!(payment_ref.chars().count() > 0, "{:?}", Err(StdError::generic_err("Payment reference must not be an empty string"))); - assert!(amount >= 0u128.into(), "{:?}", Err(StdError::generic_err("Payment amount must be greater than 0"))); - assert!(denomination.chars().count() > 0, "{:?}", Err(StdError::generic_err("Payment denomination must not be an empty string"))); + if viewing_key_index.chars().count() == 0 { + return Err(StdError::generic_err("Secret must not be an empty string")); + } + if payment_ref.chars().count() == 0 { + return Err(StdError::generic_err("Payment reference must not be an empty string")); + } + if amount == >::into(0u128) { + return Err(StdError::generic_err("Payment amount must be greater than 0")); + } + if denomination.chars().count() == 0 { + return Err(StdError::generic_err("Payment denomination must not be an empty string")); + } // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation - let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index; - let index_concat = gateway_account.push_str(suffix); - - let entropy: Binary = b"entropy".into(); - let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_ptr()); + let gateway_account = config.gateway_address.to_owned(); + let mut index_concat: String = gateway_account.to_string(); + let suffix: &str = viewing_key_index; + index_concat.push_str(suffix); + + let binding = "entropy".to_string(); + let entropy: &str = binding.as_str(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let viewing_key = VIEWING_KEY @@ -321,9 +341,9 @@ fn create_pay( } // Attempt to retrieve existing - let value_payment_reference_to_balances_map = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + let value_payment_reference_to_balances_map: Option> = Some(VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP .get(deps.storage, &index_concat) - .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?); let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing @@ -331,7 +351,7 @@ fn create_pay( }; // Check if matching `payment_ref` is in the vector since only pay if it exists - let index: Option = Some(value_payment_reference_to_balances.iter().position(|&r| r.payment_reference == payment_ref).unwrap()); + let index: Option = Some(value_payment_reference_to_balances.iter().position(|r| r.payment_reference == payment_ref).unwrap()); let index_value_payment_reference_to_balances = match index { Some(val) => { @@ -342,8 +362,10 @@ fn create_pay( }; // Add pay amount to existing balance associated with the payment reference that was found - let new_balance_amount: Uint128 = index_value_payment_reference_to_balances.balance.amount.saturating_add(amount); - let new_balance: Coin = coin(&new_balance_amount, denomination); + let new_balance_amount: Uint128 = value_payment_reference_to_balances[index_value_payment_reference_to_balances].balance.amount.saturating_add(amount); + let new_balance: Coin = coin(>::into(new_balance_amount), denomination); + + let new_payment_reference_balance = PaymentReferenceBalance { payment_reference: payment_ref.to_string(), balance: new_balance, @@ -356,7 +378,7 @@ fn create_pay( VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; - let mut receipt: PaymentReceipt; + let receipt: PaymentReceipt; // FIXME: sign receipt using Secret contract's private key, currently just hardcoded. // But how to get the Secret contract's public and private key? @@ -372,7 +394,7 @@ fn create_pay( payment_reference: payment_ref.to_string(), // TODO: convert Uint256 to Uint128 // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract - amount: new_balance_amount, + amount: new_balance_amount.into(), // TODO: serialise denomination denomination: denomination.to_string(), sig: signature, @@ -383,7 +405,7 @@ fn create_pay( payment_reference: payment_ref.to_string(), // TODO: convert Uint256 to Uint128 // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract - amount: new_balance_amount, + amount: new_balance_amount.into(), // TODO: serialise denomination denomination: denomination.to_string(), sig: signature, @@ -393,7 +415,7 @@ fn create_pay( let response_status_code: ResponseStatusCode = 0u16; let data = ResponsePayStoreMsg { - _requestId: task, + _request_id: task.clone(), _code: response_status_code, _receipt: receipt, }; @@ -423,7 +445,7 @@ fn create_pay( fn create_withdraw_to( deps: DepsMut, - env: Env, + _env: Env, input_values: String, task: Task, input_hash: Binary, @@ -442,19 +464,27 @@ fn create_withdraw_to( let denomination = input.denomination.as_str(); let withdrawal_address: [u8; 20] = input.withdrawal_address.into(); // or `Addr` - assert!(viewing_key_index.chars().count() > 0, "{:?}", Err(StdError::generic_err("Secret must not be an empty string"))); + if viewing_key_index.chars().count() == 0 { + return Err(StdError::generic_err("Secret must not be an empty string")); + } // Do not validate payment reference since want to ignore it - assert!(amount >= 0u128.into(), "{:?}", Err(StdError::generic_err("Payment amount must be greater than 0"))); - assert!(denomination.chars().count() > 0, "{:?}", Err(StdError::generic_err("Payment denomination must not be an empty string"))); + if amount == >::into(0u128) { + return Err(StdError::generic_err("Payment amount must be greater than 0")); + } + if denomination.chars().count() == 0 { + return Err(StdError::generic_err("Payment denomination must not be an empty string")); + } // TODO: validate withdrawal address input. check if could be `Addr` type // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation - let gateway_account = config.gateway_address.to_string(); - let suffix = viewing_key_index; - let index_concat = gateway_account.push_str(suffix); - - let entropy: Binary = b"entropy".into(); - let result = ViewingKey::check(deps.storage, &index_concat, entropy.as_ptr()); + let gateway_account = config.gateway_address.to_owned(); + let mut index_concat: String = gateway_account.to_string(); + let suffix: &str = viewing_key_index; + index_concat.push_str(suffix); + + let binding = "entropy".to_string(); + let entropy: &str = binding.as_str(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy); assert_ne!(result, Err(StdError::generic_err("unauthorized"))); let value_viewing_key = VIEWING_KEY @@ -466,11 +496,11 @@ fn create_withdraw_to( } // Attempt to retrieve existing - let value_payment_reference_to_balances_map = VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + let value_payment_reference_to_balances_map: Option> = Some(VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP .get(deps.storage, &index_concat) - .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?; + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?); - let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + let value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing None => return Err(StdError::generic_err("No payment references found")), // If none are found, early return }; @@ -492,15 +522,17 @@ fn create_withdraw_to( } } - assert!(balance_all_payment_refs >= amount, "{:?}", Err(StdError::generic_err("Withdrawal amount must be less than or equal to total balance of all payment references"))); + if amount > balance_all_payment_refs { + return Err(StdError::generic_err("Withdrawal amount must be less than or equal to total balance of all payment references")); + } let response_status_code: ResponseStatusCode = 0u16; let data = ResponseWithdrawToStoreMsg { - _requestId: task, + _request_id: task.clone(), _code: response_status_code, _amount: amount, - _withdrawalAddress: withdrawal_address, + _withdrawal_address: withdrawal_address, }; let json_string = @@ -527,7 +559,7 @@ fn create_withdraw_to( } #[entry_point] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { let response = match msg { QueryMsg::RetrievePubkey {} => to_binary(&retrieve_pubkey_query(deps)?), }; diff --git a/packages/secret-contracts/nunya-contract/src/msg.rs b/packages/secret-contracts/nunya-contract/src/msg.rs index 4b41bad..d4ba81c 100644 --- a/packages/secret-contracts/nunya-contract/src/msg.rs +++ b/packages/secret-contracts/nunya-contract/src/msg.rs @@ -57,31 +57,31 @@ pub struct WithdrawToStoreMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct ResponseNewAuthOutStoreMsg { - pub _requestId: Task, + pub _request_id: Task, pub _code: ResponseStatusCode, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct ResponseLinkPaymentRefStoreMsg { - pub _requestId: Task, + pub _request_id: Task, pub _code: ResponseStatusCode, pub _reference: String, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct ResponsePayStoreMsg { - pub _requestId: Task, + pub _request_id: Task, pub _code: ResponseStatusCode, pub _receipt: PaymentReceipt, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct ResponseWithdrawToStoreMsg { - pub _requestId: Task, + pub _request_id: Task, pub _code: ResponseStatusCode, pub _amount: Uint128, // TODO: should this be of type `Addr`? does it support EVM addresses? - pub _withdrawalAddress: [u8; 20], + pub _withdrawal_address: [u8; 20], } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index 3445e74..d007994 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{Addr, Binary, Coin, Uint128, Uint256}; +use cosmwasm_std::{Addr, Binary, Coin, Uint256}; use secret_toolkit::storage::{Item, Keymap}; use schemars::JsonSchema; @@ -9,7 +9,7 @@ pub static CONFIG: Item = Item::new(b"config"); pub static VIEWING_KEY: Keymap = Keymap::new(b"VIEWING_KEY"); pub static VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP: Keymap> = Keymap::new(b"VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP"); -pub type Index = u8; +pub type Index = String; // pub type ContractAddress = [u8; 32]; pub type ResponseStatusCode = u16; From dc2ccddd969e5e874ace8bff5bb2a0d03b5dde44 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Tue, 15 Oct 2024 02:59:31 +0200 Subject: [PATCH 10/13] fix: Restore sepolia default so CI passes --- packages/hardhat/hardhat.config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/hardhat/hardhat.config.ts b/packages/hardhat/hardhat.config.ts index c76e15f..cbe737b 100644 --- a/packages/hardhat/hardhat.config.ts +++ b/packages/hardhat/hardhat.config.ts @@ -69,8 +69,8 @@ const config: HardhatUserConfig = { sepolia: { chainId: 11155111, url: `${providerRpcUrl || "https://eth-sepolia.g.alchemy.com/v2/"}${providerApiKey}`, - accounts: { mnemonic: MNEMONIC }, - // accounts: [deployerPrivateKey], + // accounts: { mnemonic: MNEMONIC }, + accounts: [deployerPrivateKey], }, arbitrum: { url: `https://arb-mainnet.g.alchemy.com/v2/${providerApiKey}`, From 2c9cc9a8ee544f709963402d92fb67c79d2e94b1 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Tue, 15 Oct 2024 15:34:36 +0200 Subject: [PATCH 11/13] wip --- .../nunya-contract/Cargo.lock | 7 +++ .../nunya-contract/cargo.toml | 4 +- .../nunya-contract/src/contract.rs | 54 +++++++++++++++++-- packages/secret-upload-contract/package.json | 2 +- packages/secret-upload-contract/src/index.ts | 21 ++++++-- 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/packages/secret-contracts/nunya-contract/Cargo.lock b/packages/secret-contracts/nunya-contract/Cargo.lock index 7c4e524..6fcbc9b 100644 --- a/packages/secret-contracts/nunya-contract/Cargo.lock +++ b/packages/secret-contracts/nunya-contract/Cargo.lock @@ -22,6 +22,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "anybuf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5f1dee23caf80904249463cc4493b6789c2250f88c8f8d9160de5c6099bfe7" + [[package]] name = "base16ct" version = "0.1.1" @@ -751,6 +757,7 @@ dependencies = [ name = "secret_evm_storage" version = "0.1.0" dependencies = [ + "anybuf", "base64 0.22.0", "cosmwasm-schema", "schemars", diff --git a/packages/secret-contracts/nunya-contract/cargo.toml b/packages/secret-contracts/nunya-contract/cargo.toml index a410766..3b95b23 100644 --- a/packages/secret-contracts/nunya-contract/cargo.toml +++ b/packages/secret-contracts/nunya-contract/cargo.toml @@ -29,7 +29,7 @@ schema = ["cosmwasm-schema"] [dependencies] cosmwasm-schema = { version = "2.0.0", optional = true } -cosmwasm-std = { package = "secret-cosmwasm-std", version = "1.0.0" } +cosmwasm-std = { package = "secret-cosmwasm-std", version = "1.1.10", features = ["stargate"] } cosmwasm-storage = { package = "secret-cosmwasm-storage", version = "1.0.0" } schemars = "0.8.11" secret-toolkit = { version = "0.10.0", default-features = false, features = [ @@ -49,6 +49,8 @@ secret-toolkit-serialization = { version = "0.10.0", features = ["base64"] } tnls = { git = "https://github.com/SecretSaturn/TNLS", branch = "main", package = "secret_gateway", default-features = false } # cw-storage-plus = { version = "0.14.0", default-features = false } +anybuf = {version = "0.5.0"} + [[bin]] name = "schema" required-features = ["schema"] diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 5f444cd..2cd31fc 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -11,7 +11,7 @@ use crate::{ }, }; use cosmwasm_std::{ - entry_point, to_binary, coin, Binary, Coin, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint128, Uint256 + entry_point, to_binary, to_vec, coin, Binary, Coin, ContractResult, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, SystemResult, Uint128, Uint256 }; use secret_toolkit::viewing_key::{ViewingKey, ViewingKeyStore}; use secret_toolkit::utils::{pad_handle_result, pad_query_result, HandleCallback}; @@ -20,6 +20,8 @@ use tnls::{ state::Task, }; +use anybuf::Anybuf; + /// pad handle responses and log attributes to blocks of 256 bytes to prevent leaking info based on /// response size pub const BLOCK_SIZE: usize = 256; @@ -166,6 +168,9 @@ fn create_new_auth_out( let result = base64::encode(json_string); + // Get the contract's code hash using the gateway address + let gateway_code_hash = get_contract_code_hash(deps, config.gateway_address.to_string())?; + let callback_msg = GatewayMsg::Output { // Sepolia network gateway contract Solidity source code // https://github.com/SecretSaturn/SecretPath/blob/main/TNLS-Gateways/public-gateway/src/Gateway.sol @@ -180,7 +185,7 @@ fn create_new_auth_out( }, } .to_cosmos_msg( - config.gateway_hash, + gateway_code_hash, config.gateway_address.to_string(), None, )?; @@ -272,6 +277,9 @@ fn create_payment_reference( let result = base64::encode(json_string); + // Get the contract's code hash using the gateway address + let gateway_code_hash = get_contract_code_hash(deps, config.gateway_address.to_string())?; + let callback_msg = GatewayMsg::Output { outputs: PostExecutionMsg { result, @@ -280,7 +288,7 @@ fn create_payment_reference( }, } .to_cosmos_msg( - config.gateway_hash, + gateway_code_hash, config.gateway_address.to_string(), None, )?; @@ -425,6 +433,9 @@ fn create_pay( let result = base64::encode(json_string); + // Get the contract's code hash using the gateway address + let gateway_code_hash = get_contract_code_hash(deps, config.gateway_address.to_string())?; + let callback_msg = GatewayMsg::Output { outputs: PostExecutionMsg { result, @@ -433,7 +444,7 @@ fn create_pay( }, } .to_cosmos_msg( - config.gateway_hash, + gateway_code_hash, config.gateway_address.to_string(), None, )?; @@ -540,6 +551,9 @@ fn create_withdraw_to( let result = base64::encode(json_string); + // Get the contract's code hash using the gateway address + let gateway_code_hash = get_contract_code_hash(deps, config.gateway_address.to_string())?; + let callback_msg = GatewayMsg::Output { outputs: PostExecutionMsg { result, @@ -548,7 +562,7 @@ fn create_withdraw_to( }, } .to_cosmos_msg( - config.gateway_hash, + gateway_code_hash, config.gateway_address.to_string(), None, )?; @@ -558,6 +572,36 @@ fn create_withdraw_to( .add_attribute("status", "DO_THE_WITHDRAWAL")) } +// reference: https://github.com/writersblockchain/secretpath-voting/commit/b0b5d8ac7b7d691c7d7ebf0bc52e5aedb8da7e86#diff-a982e501ba4bd05192a8c497bd5093517ea5606f9e341b9b7d09b233068da829R232 +fn get_contract_code_hash(deps: DepsMut, contract_address: String) -> StdResult { + let code_hash_query: cosmwasm_std::QueryRequest = + cosmwasm_std::QueryRequest::Stargate { + path: "/secret.compute.v1beta1.Query/CodeHashByContractAddress".into(), + data: Binary(Anybuf::new().append_string(1, contract_address).into_vec()), + }; + let raw = to_vec(&code_hash_query).map_err(|serialize_err| { + StdError::generic_err(format!("Serializing QueryRequest: {}", serialize_err)) + })?; + let code_hash = match deps.querier.raw_query(&raw) { + SystemResult::Err(system_err) => Err(StdError::generic_err(format!( + "Querier system error: {}", + system_err + ))), + SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(format!( + "Querier contract error: {}", + contract_err + ))), + SystemResult::Ok(ContractResult::Ok(value)) => Ok(value), + }?; + // Remove the "\n@" if it exists at the start of the code_hash + let mut code_hash_str = String::from_utf8(code_hash.to_vec()) + .map_err(|err| StdError::generic_err(format!("Invalid UTF-8 sequence: {}", err)))?; + if code_hash_str.starts_with("\n@") { + code_hash_str = code_hash_str.trim_start_matches("\n@").to_string(); + } + Ok(code_hash_str) +} + #[entry_point] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { let response = match msg { diff --git a/packages/secret-upload-contract/package.json b/packages/secret-upload-contract/package.json index 8aa0253..3e25b4b 100644 --- a/packages/secret-upload-contract/package.json +++ b/packages/secret-upload-contract/package.json @@ -5,7 +5,7 @@ "private": true, "scripts": { "build": "./node_modules/.bin/tsc --build", - "clean": "./node_modules/.bin/tsc --clean", + "clean": "./node_modules/.bin/tsc --build --clean", "start": "yarn build && node ./dist/index.js" }, "dependencies": { diff --git a/packages/secret-upload-contract/src/index.ts b/packages/secret-upload-contract/src/index.ts index 200ae98..5d26ea9 100644 --- a/packages/secret-upload-contract/src/index.ts +++ b/packages/secret-upload-contract/src/index.ts @@ -18,14 +18,27 @@ const rootPath = path.resolve(__dirname, '../../../'); // relative to ./dist console.log('rootPath', rootPath) const contract_wasm: any = fs.readFileSync(`${rootPath}/packages/secret-contracts/nunya-contract/contract.wasm`); -const gatewayAddress = "secret10ex7r7c4y704xyu086lf74ymhrqhypayfk7fkj"; +// Secret Testnet +// reference: https://docs.scrt.network/secret-network-documentation/confidential-computing-layer/ethereum-evm-developer-toolkit/supported-networks/secret-gateway/secretpath-testnet-pulsar-3-contracts +// Code ID 3375 +const gatewayAddress = "secret10ex7r7c4y704xyu086lf74ymhrqhypayfk7fkj"; const gatewayHash = - "012dd8efab9526dec294b6898c812ef6f6ad853e32172788f54ef3c305c1ecc5"; - + "ad8ca07ffba1cb26ebf952c29bc4eced8319c171430993e5b5089887f27b3f70"; const gatewayPublicKey = "0x046d0aac3ef10e69055e934ca899f508ba516832dc74aa4ed4d741052ed5a568774d99d3bfed641a7935ae73aac8e34938db747c2f0e8b2aa95c25d069a575cc8b"; +// Secret Mainnet +// reference: https://docs.scrt.network/secret-network-documentation/confidential-computing-layer/ethereum-evm-developer-toolkit/supported-networks/secret-gateway/secretpath-mainnet-secret-4-contracts + +// Code ID 1533 +// const gatewayAddress = "secret1qzk574v8lckjmqdg3r3qf3337pk45m7qd8x02a"; +// const gatewayHash = +// "012dd8efab9526dec294b6898c812ef6f6ad853e32172788f54ef3c305c1ecc5"; +// // TODO: is it correct that the Gateway public key is the same for both Mainnet and Testnet as shown in the docs here, even though they have a different Gateway address? https://docs.scrt.network/secret-network-documentation/confidential-computing-layer/ethereum-evm-developer-toolkit/supported-networks/secret-gateway +// const gatewayPublicKey = +// "0x04a0d632acd0d2f5da02fc385ea30a8deab4d5639d1a821a3a552625ad0f1759d0d2e80ca3adb236d90caf1b12e0ddf3a351c5729b5e00505472dca6fed5c31e2a"; + const gatewayPublicKeyBytes = Buffer.from( gatewayPublicKey.substring(2), "hex" @@ -88,6 +101,8 @@ async function main () { tx?.arrayLog?.find((log: any) => log?.type === "message" && log?.key === "code_id")?.value ); + console.log("tx.rawLog: ", tx.rawLog); + console.log("codeId: ", codeId); contractCodeHash = ( From ed6c7b59ac9ae693a04297802bbf13c7341605a1 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Tue, 15 Oct 2024 16:50:34 +0200 Subject: [PATCH 12/13] refactor: remove old disused node/ folder from example project --- .../nunya-contract/cargo.toml | 1 - .../nunya-contract/node/.env.example | 4 - .../nunya-contract/node/.gitignore | 21 - .../nunya-contract/node/package-lock.json | 1484 ----------------- .../nunya-contract/node/package.json | 21 - .../nunya-contract/node/query_pubkey.js | 19 - .../nunya-contract/node/upload.js | 101 -- packages/secret-upload-contract/src/index.ts | 57 +- 8 files changed, 45 insertions(+), 1663 deletions(-) delete mode 100644 packages/secret-contracts/nunya-contract/node/.env.example delete mode 100644 packages/secret-contracts/nunya-contract/node/.gitignore delete mode 100644 packages/secret-contracts/nunya-contract/node/package-lock.json delete mode 100644 packages/secret-contracts/nunya-contract/node/package.json delete mode 100644 packages/secret-contracts/nunya-contract/node/query_pubkey.js delete mode 100644 packages/secret-contracts/nunya-contract/node/upload.js diff --git a/packages/secret-contracts/nunya-contract/cargo.toml b/packages/secret-contracts/nunya-contract/cargo.toml index 3b95b23..4fb93ef 100644 --- a/packages/secret-contracts/nunya-contract/cargo.toml +++ b/packages/secret-contracts/nunya-contract/cargo.toml @@ -48,7 +48,6 @@ secret-toolkit-serialization = { version = "0.10.0", features = ["base64"] } # thiserror = { version = "1.0.31" } tnls = { git = "https://github.com/SecretSaturn/TNLS", branch = "main", package = "secret_gateway", default-features = false } # cw-storage-plus = { version = "0.14.0", default-features = false } - anybuf = {version = "0.5.0"} [[bin]] diff --git a/packages/secret-contracts/nunya-contract/node/.env.example b/packages/secret-contracts/nunya-contract/node/.env.example deleted file mode 100644 index e29a6d9..0000000 --- a/packages/secret-contracts/nunya-contract/node/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -# FIXME - update these after deploying nunya-contract -MNEMONIC="shed clerk pray velvet flower tide bug idea private solar prize tackle" -CODE_HASH="e8d3f1c82b620fced20a7d8878ea81cd5af3de28ad7427246c3d7e93b2fa3c4f" -SECRET_ADDRESS="secret1m9d45wakl6vmshxc5kp6ztrf29uc3gzm8vpe47" diff --git a/packages/secret-contracts/nunya-contract/node/.gitignore b/packages/secret-contracts/nunya-contract/node/.gitignore deleted file mode 100644 index 1c0d0e5..0000000 --- a/packages/secret-contracts/nunya-contract/node/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/node_modules* -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc - -.env - -npm-debug.log* -yarn-debug.log* -yarn-error.log* \ No newline at end of file diff --git a/packages/secret-contracts/nunya-contract/node/package-lock.json b/packages/secret-contracts/nunya-contract/node/package-lock.json deleted file mode 100644 index d22a529..0000000 --- a/packages/secret-contracts/nunya-contract/node/package-lock.json +++ /dev/null @@ -1,1484 +0,0 @@ -{ - "name": "node", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "node", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@solar-republic/cosmos-grpc": "^0.14.2", - "@solar-republic/neutrino": "^1.0.8", - "dotenv": "^16.4.5", - "ethers": "^5.7.2", - "secretjs": "^1.12.4", - "secure-random": "^1.1.2" - } - }, - "node_modules/@blake.regalia/belt": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@blake.regalia/belt/-/belt-0.31.1.tgz", - "integrity": "sha512-VuL8sfhn+lYGAow5xht5jjV75k0CfudZpWI0IWdgc2uj20X6UfdLdq4BuA6CAnVEkyWb/NVhU6cs1o5TWtzS0A==" - }, - "node_modules/@cosmjs/encoding": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.27.1.tgz", - "integrity": "sha512-rayLsA0ojHeniaRfWWcqSsrE/T1rl1gl0OXVNtXlPwLJifKBeLEefGbOUiAQaT0wgJ8VNGBazVtAZBpJidfDhw==", - "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" - } - }, - "node_modules/@cosmjs/encoding/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/@cosmjs/math": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.27.1.tgz", - "integrity": "sha512-cHWVjmfIjtRc7f80n7x+J5k8pe+vTVTQ0lA82tIxUgqUvgS6rogPP/TmGtTiZ4+NxWxd11DUISY6gVpr18/VNQ==", - "dependencies": { - "bn.js": "^5.2.0" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/providers/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@noble/hashes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.0.0.tgz", - "integrity": "sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg==" - }, - "node_modules/@noble/secp256k1": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.0.tgz", - "integrity": "sha512-kbacwGSsH/CTout0ZnZWxnW1B+jH/7r/WAAKLBtrRJ/+CUH7lgmQzl3GTrQua3SGKWNSDsS6lmjnDpIJ5Dxyaw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "node_modules/@solar-republic/cosmos-grpc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@solar-republic/cosmos-grpc/-/cosmos-grpc-0.14.2.tgz", - "integrity": "sha512-Q74TXtwUM2J5lvs3MnK1uH9+Wx4DFAyekEpOo0nvkPMh/0JRCdSFPZywWezNi//QVenVHXF2DK1V49UBHPoNyg==", - "dependencies": { - "@solar-republic/crypto": "^0.2.5", - "google-protobuf": "^3.21.2", - "protobufjs": "^7.2.6" - }, - "bin": { - "protoc-gen-secret": "build/protoc/run.js" - } - }, - "node_modules/@solar-republic/cosmos-grpc/node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@solar-republic/cosmos-grpc/node_modules/protobufjs": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", - "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@solar-republic/crypto": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@solar-republic/crypto/-/crypto-0.2.5.tgz", - "integrity": "sha512-ofEsb/AHd6f3dldb93miRBfF8yUnXf3a2k0nJh2eDIP6lK0VxjKwRO3U95xya+nHPLYPJvseh7GMsTAEzbmbPQ==", - "dependencies": { - "@blake.regalia/belt": "^0.31.1", - "@cosmjs/encoding": "^0.32.2", - "@solar-republic/wasm-secp256k1": "^0.2.2", - "hash-wasm": "^4.11.0" - } - }, - "node_modules/@solar-republic/crypto/node_modules/@cosmjs/encoding": { - "version": "0.32.2", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.32.2.tgz", - "integrity": "sha512-WX7m1wLpA9V/zH0zRcz4EmgZdAv1F44g4dbXOgNj1eXZw1PIGR12p58OEkLN51Ha3S4DKRtCv5CkhK1KHEvQtg==", - "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" - } - }, - "node_modules/@solar-republic/crypto/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/@solar-republic/neutrino": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@solar-republic/neutrino/-/neutrino-1.0.8.tgz", - "integrity": "sha512-jvixdoLJrxbaZTQzvXFmTabYLzw2H159kTxxDIa1cXIiNyFHBLr3JwTmxJXBO8jynib2k4O0J2GTMfpa6CwLAg==", - "dependencies": { - "@blake.regalia/belt": "^0.31.1" - } - }, - "node_modules/@solar-republic/wasm-secp256k1": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@solar-republic/wasm-secp256k1/-/wasm-secp256k1-0.2.2.tgz", - "integrity": "sha512-knCVLxIbWw0v/T+qBU5MUpECqkyrbRJIQC4ORAvTRm4O4w1gjxCbrdG0WPd1hZDWYItAlwYh+3LJF7t+tRqjjQ==", - "dependencies": { - "@blake.regalia/belt": "^0.31.0" - } - }, - "node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bignumber.js": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", - "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", - "engines": { - "node": "*" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "dependencies": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip39": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", - "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", - "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" - } - }, - "node_modules/bip39/node_modules/@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/curve25519-js": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/curve25519-js/-/curve25519-js-0.0.4.tgz", - "integrity": "sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==" - }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "node_modules/google-protobuf": { - "version": "3.21.2", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", - "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-wasm": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.11.0.tgz", - "integrity": "sha512-HVusNXlVqHe0fzIzdQOGolnFN6mX/fqcrSAOcTBXdvzrXVHwTz11vXeKRmkR5gTuwVpvHZEIyKoePDvuAR+XwQ==" - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, - "node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "node_modules/miscreant": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/miscreant/-/miscreant-0.3.2.tgz", - "integrity": "sha512-fL9KxsQz9BJB2KGPMHFrReioywkiomBiuaLk6EuChijK0BsJsIKJXdVomR+/bPj5mvbFD6wM0CM3bZio9g7OHA==" - }, - "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/pako": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz", - "integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==" - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/protobufjs/node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readonly-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", - "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==" - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" - }, - "node_modules/secretjs": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/secretjs/-/secretjs-1.12.4.tgz", - "integrity": "sha512-DH16hYTPa4NNxo1T/tY2GyJRte7rgp5kRy8k1pwaPK59WtbQdTBdPQQsEI2L5T7NDVEUXbdbTqyQkt5usN4KcQ==", - "dependencies": { - "@cosmjs/encoding": "0.27.1", - "@cosmjs/math": "0.27.1", - "@noble/hashes": "1.0.0", - "@noble/secp256k1": "1.7.0", - "bech32": "2.0.0", - "big-integer": "1.6.51", - "bignumber.js": "9.0.2", - "bip32": "2.0.6", - "bip39": "3.0.4", - "cross-fetch": "3.1.5", - "curve25519-js": "0.0.4", - "google-protobuf": "^3.14.0", - "miscreant": "0.3.2", - "pako": "2.0.4", - "protobufjs": "7.2.5", - "secure-random": "1.1.2" - } - }, - "node_modules/secure-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/secure-random/-/secure-random-1.1.2.tgz", - "integrity": "sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/tiny-secp256k1/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", - "dependencies": { - "bs58check": "<3.0.0" - } - }, - "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/packages/secret-contracts/nunya-contract/node/package.json b/packages/secret-contracts/nunya-contract/node/package.json deleted file mode 100644 index e93bae4..0000000 --- a/packages/secret-contracts/nunya-contract/node/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "node", - "type": "module", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@solar-republic/cosmos-grpc": "^0.14.2", - "@solar-republic/neutrino": "^1.0.8", - "dotenv": "^16.4.5", - "ethers": "^5.7.2", - "secretjs": "^1.12.4", - "secure-random": "^1.1.2" - } -} diff --git a/packages/secret-contracts/nunya-contract/node/query_pubkey.js b/packages/secret-contracts/nunya-contract/node/query_pubkey.js deleted file mode 100644 index cc931ea..0000000 --- a/packages/secret-contracts/nunya-contract/node/query_pubkey.js +++ /dev/null @@ -1,19 +0,0 @@ -import { SecretNetworkClient } from "secretjs"; -import dotenv from "dotenv"; -dotenv.config(); - -let query = async () => { - const secretjs = new SecretNetworkClient({ - url: "https://api.pulsar3.scrttestnet.com", - chainId: "pulsar-3", - }); - - const query_tx = await secretjs.query.compute.queryContract({ - contract_address: process.env.SECRET_ADDRESS, - code_hash: process.env.CODE_HASH, - query: { retrieve_pubkey_query: { key: 1 } }, - }); - console.log(query_tx); -}; - -query(); diff --git a/packages/secret-contracts/nunya-contract/node/upload.js b/packages/secret-contracts/nunya-contract/node/upload.js deleted file mode 100644 index 344530f..0000000 --- a/packages/secret-contracts/nunya-contract/node/upload.js +++ /dev/null @@ -1,101 +0,0 @@ -import { SecretNetworkClient, Wallet, coinsFromString } from "secretjs"; -import * as fs from "fs"; -import dotenv from "dotenv"; -dotenv.config(); - -const wallet = new Wallet(process.env.MNEMONIC); - -const contract_wasm = fs.readFileSync("../contract.wasm.gz"); - -const gatewayAddress = "secret10ex7r7c4y704xyu086lf74ymhrqhypayfk7fkj"; - -const gatewayHash = - "012dd8efab9526dec294b6898c812ef6f6ad853e32172788f54ef3c305c1ecc5"; - -const gatewayPublicKey = - "0x046d0aac3ef10e69055e934ca899f508ba516832dc74aa4ed4d741052ed5a568774d99d3bfed641a7935ae73aac8e34938db747c2f0e8b2aa95c25d069a575cc8b"; - -const gatewayPublicKeyBytes = Buffer.from( - gatewayPublicKey.substring(2), - "hex" -).toString("base64"); - -const secretjs = new SecretNetworkClient({ - chainId: "pulsar-3", - url: "https://api.pulsar3.scrttestnet.com", - wallet: wallet, - walletAddress: wallet.address, -}); - -// Declare global variables -let codeId; -let contractCodeHash; -let contractAddress; - -let upload_contract = async () => { - console.log("Starting deployment…"); - - let tx = await secretjs.tx.compute.storeCode( - { - sender: wallet.address, - wasm_byte_code: contract_wasm, - source: "", - builder: "", - }, - { - gasLimit: 4_000_000, - } - ); - - codeId = Number( - tx.arrayLog.find((log) => log.type === "message" && log.key === "code_id") - .value - ); - console.log("codeId: ", codeId); - - contractCodeHash = ( - await secretjs.query.compute.codeHashByCodeId({ code_id: codeId }) - ).code_hash; - console.log(`CODE_HASH: ${contractCodeHash}`); -}; - -let instantiate_contract = async () => { - if (!codeId || !contractCodeHash) { - throw new Error("codeId or contractCodeHash is not set."); - } - console.log("Instantiating contract…"); - - let init = { - gateway_address: gatewayAddress, - gateway_hash: gatewayHash, - gateway_key: gatewayPublicKeyBytes, - }; - let tx = await secretjs.tx.compute.instantiateContract( - { - code_id: codeId, - sender: wallet.address, - code_hash: contractCodeHash, - init_msg: init, - label: "SnakePath Encrypt " + Math.ceil(Math.random() * 10000), - }, - { - gasLimit: 400_000, - } - ); - - //Find the contract_address in the logs - const contractAddress = tx.arrayLog.find( - (log) => log.type === "message" && log.key === "contract_address" - ).value; - - console.log("SECRET_ADDRESS: ", contractAddress); -}; - -// Chain the execution using promises -upload_contract() - .then(() => { - instantiate_contract(); - }) - .catch((error) => { - console.error("Error:", error); - }); diff --git a/packages/secret-upload-contract/src/index.ts b/packages/secret-upload-contract/src/index.ts index 5d26ea9..f0416d4 100644 --- a/packages/secret-upload-contract/src/index.ts +++ b/packages/secret-upload-contract/src/index.ts @@ -16,7 +16,7 @@ console.log('wallet: ', wallet); const rootPath = path.resolve(__dirname, '../../../'); // relative to ./dist console.log('rootPath', rootPath) -const contract_wasm: any = fs.readFileSync(`${rootPath}/packages/secret-contracts/nunya-contract/contract.wasm`); +const contract_wasm: any = fs.readFileSync(`${rootPath}/packages/secret-contracts/nunya-contract/contract.wasm.gz`); // Secret Testnet // reference: https://docs.scrt.network/secret-network-documentation/confidential-computing-layer/ethereum-evm-developer-toolkit/supported-networks/secret-gateway/secretpath-testnet-pulsar-3-contracts @@ -71,15 +71,20 @@ async function main () { }; type CODE_PARAMS = { - codeId: String | undefined, - contractCodeHash: String | undefined, + codeId: String, + contractCodeHash: String, + }; + + type CONTRACT_PARAMS = { + contractAddress: String, + contractCodeHash: String, }; let upload_contract = async () => { console.log("Starting deployment..."); - let codeId: String | undefined; - let contractCodeHash: String | undefined; + let codeId: String; + let contractCodeHash: String; let tx: any; try { tx = await secretjs.tx.compute.storeCode( @@ -107,8 +112,12 @@ async function main () { contractCodeHash = ( await secretjs.query.compute.codeHashByCodeId({ code_id: codeId.toString() }) - ).code_hash; + ).code_hash || ""; console.log(`CODE_HASH: ${contractCodeHash}`); + + if (contractCodeHash == "") { + throw Error("Unable to obtain contractCodeHash"); + } return { codeId, @@ -118,7 +127,11 @@ async function main () { let instantiate_contract = async (params: CODE_PARAMS) => { console.log('params: ', params) - let contractAddress; + if (typeof params.codeId == undefined || typeof params.contractCodeHash == undefined) { + throw Error("Unable to instantiate without codeId and contractCodeHash"); + } + + let contractAddress: String; if (!params.codeId || !params.contractCodeHash) { throw new Error("codeId or contractCodeHash is not set."); @@ -138,7 +151,7 @@ async function main () { sender: wallet.address, code_hash: params.contractCodeHash.toString(), init_msg: initMsg, - label: "Encrypt " + Math.ceil(Math.random() * 10000), + label: "SnakePath Encrypt " + Math.ceil(Math.random() * 10000), }, { gasLimit: 400_000, @@ -146,20 +159,40 @@ async function main () { ); console.log('tx: ', tx) - //Find the contract_address in the logs + // Find the contract_address in the logs contractAddress = tx?.arrayLog?.find( (log) => log?.type === "message" && log?.key === "contract_address" - )?.value; + )?.value || ""; console.log("SECRET_ADDRESS: ", contractAddress); - return contractAddress; + if (contractAddress == "") { + throw Error("Unable to find the contract_address"); + } + + let contractParams = { + contractAddress, + contractCodeHash: params.contractCodeHash, + }; + return contractParams; }; + + let query_pubkey = async (params: CONTRACT_PARAMS) => { + const query_tx = await secretjs.query.compute.queryContract({ + contract_address: params?.contractAddress?.toString(), + code_hash: params?.contractCodeHash?.toString(), + query: { retrieve_pubkey_query: { key: 1 } }, + }); + console.log(query_tx); + } // Chain the execution using promises await upload_contract() .then(async (res) => { - await instantiate_contract(res); + await instantiate_contract(res) + .then(async (contractParams) => { + await query_pubkey(contractParams); + }) }) .catch((error) => { console.error("Error:", error); From 4676085e64823c9e8517a1c5460897b8b634d116 Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Tue, 15 Oct 2024 17:19:13 +0200 Subject: [PATCH 13/13] chore: update eslint --- packages/hardhat/.eslintrc.json | 4 ++-- packages/nextjs/.eslintrc.json | 4 ++-- .../app/pay/[paymentReference]/[amount]/[currency]/page.tsx | 1 + packages/nextjs/app/withdraw.tsx | 6 +++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/hardhat/.eslintrc.json b/packages/hardhat/.eslintrc.json index 4020c1b..5d27931 100644 --- a/packages/hardhat/.eslintrc.json +++ b/packages/hardhat/.eslintrc.json @@ -5,10 +5,10 @@ "parser": "@typescript-eslint/parser", "extends": ["plugin:prettier/recommended", "plugin:@typescript-eslint/recommended"], "rules": { - "@typescript-eslint/no-unused-vars": ["warn"], + "@typescript-eslint/no-unused-vars": ["off"], "@typescript-eslint/no-explicit-any": ["off"], "prettier/prettier": [ - "warn", + "off", { "endOfLine": "auto" } diff --git a/packages/nextjs/.eslintrc.json b/packages/nextjs/.eslintrc.json index c120c8c..c200587 100644 --- a/packages/nextjs/.eslintrc.json +++ b/packages/nextjs/.eslintrc.json @@ -2,11 +2,11 @@ "parser": "@typescript-eslint/parser", "extends": ["next/core-web-vitals", "plugin:prettier/recommended", "plugin:@typescript-eslint/recommended"], "rules": { - "@typescript-eslint/no-unused-vars": ["error"], + "@typescript-eslint/no-unused-vars": ["off"], "@typescript-eslint/no-explicit-any": ["off"], "@typescript-eslint/ban-ts-comment": ["off"], "prettier/prettier": [ - "warn", + "off", { "endOfLine": "auto" } diff --git a/packages/nextjs/app/pay/[paymentReference]/[amount]/[currency]/page.tsx b/packages/nextjs/app/pay/[paymentReference]/[amount]/[currency]/page.tsx index 752e049..bca2443 100644 --- a/packages/nextjs/app/pay/[paymentReference]/[amount]/[currency]/page.tsx +++ b/packages/nextjs/app/pay/[paymentReference]/[amount]/[currency]/page.tsx @@ -33,6 +33,7 @@ const PaymentPage: NextPage = ({ params }: PageProps) => { const { targetNetwork } = useTargetNetwork(); // const encoder: TextEncoder = new global.TextEncoder(); + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => { setReference(paymentReferenceParam); diff --git a/packages/nextjs/app/withdraw.tsx b/packages/nextjs/app/withdraw.tsx index 68e5239..ed7ff9d 100644 --- a/packages/nextjs/app/withdraw.tsx +++ b/packages/nextjs/app/withdraw.tsx @@ -7,7 +7,7 @@ import { convertToBigint } from "~~/utils/convert"; interface WithdrawalRequest { amount: string; - address: string; + address: bigint; } const Withdraw: NextPage = () => { @@ -28,13 +28,13 @@ const Withdraw: NextPage = () => { const requestId = await writeContractAsync({ functionName: "withdrawTo", // TODO args: [encoder.encode(secret) ... - args: [secret, parseEther(amount), address], + args: [secret, parseEther(amount), convertToBigint(address), "ETH"], }); console.log("⚡ Requesting new account", requestId, secret, parseEther(amount), address); if (!requestId) { return console.error("No request ID returned."); } - openRequests.set(convertToBigint(requestId), { amount, address }); + openRequests.set(convertToBigint(requestId), { amount, address: convertToBigint(address) }); }; useScaffoldWatchContractEvent({