From ec1c8a08fe120a0d5b4d5199d68d27b506e7c317 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Fri, 16 Aug 2024 15:38:14 -0400 Subject: [PATCH 1/3] feat: add fee estimate from peer --- index.d.ts | 8 ++++++++ src/lib.rs | 30 ++++++++++++++++++++++++++++++ src/wallet.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/index.d.ts b/index.d.ts index 2b7abe1..e7200b7 100644 --- a/index.d.ts +++ b/index.d.ts @@ -350,6 +350,14 @@ export declare class Peer { * @returns {Promise} The sync store response. */ syncStore(storeInfo: DataStoreInfo, lastHeight: number | undefined | null, lastHeaderHash: Buffer, withHistory: boolean): Promise + /** + * Retrieves the fee estimate for a given target time. + * + * @param {Peer} peer - The peer connection to the Chia node. + * @param {number} targetTimeSeconds - The target time in seconds for the fee estimate. + * @returns {Promise} The estimated fee in mojos per CLVM cost. + */ + getFeeEstimate(peer: Peer, targetTimeSeconds: BigInt): Promise /** * Synchronizes a store using its launcher ID. * diff --git a/src/lib.rs b/src/lib.rs index 8c8b269..9b5513c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ use std::sync::Arc; use chia::bls::derive_keys::master_to_wallet_unhardened; use chia::bls::{SecretKey as RustSecretKey, Signature as RustSignature}; use chia::client::Peer as RustPeer; +use chia::client::Error as ClientError; use chia::{bls::PublicKey as RustPublicKey, traits::Streamable}; use chia_protocol::Coin as RustCoin; use chia_protocol::CoinSpend as RustCoinSpend; @@ -31,6 +32,7 @@ pub use debug::*; pub use drivers::*; pub use merkle_tree::*; use napi::bindgen_prelude::*; +use std::time::{SystemTime, UNIX_EPOCH}; pub use puzzles::*; pub use puzzles_info::*; use puzzles_info::{ @@ -675,6 +677,34 @@ impl Peer { Ok(Self(Arc::new(peer))) } + #[napi] + /// Retrieves the fee estimate for a given target time. + /// + /// @param {Peer} peer - The peer connection to the Chia node. + /// @param {BigInt} targetTimeSeconds - The target time in seconds from the current time for the fee estimate. + /// @returns {Promise} The estimated fee in mojos per CLVM cost. + pub async fn get_fee_estimate(&self, target_time_seconds: BigInt) -> napi::Result { + // Convert the target_time_seconds BigInt to u64 + let target_time_seconds_u64: u64 = target_time_seconds.get_u64().1; + + // Get the current time as a Unix timestamp in seconds + let current_time = SystemTime::now().duration_since(UNIX_EPOCH) + .expect("Time went backwards") + .as_secs(); + + // Calculate the target Unix timestamp + let target_timestamp = current_time + target_time_seconds_u64; + + // Call the Rust get_fee_estimate function with the calculated Unix timestamp + match wallet::get_fee_estimate(&self.0.clone(), target_timestamp).await { + Ok(fee_estimate) => Ok(BigInt::from(fee_estimate)), + Err(ClientError::Rejection(error_message)) => { + Err(napi::Error::from_reason(format!("Fee estimate rejection: {}", error_message))) + } + Err(e) => Err(napi::Error::from_reason(format!("Failed to request fee estimates: {:?}", e))), + } + } + #[napi] /// Retrieves all coins that are unspent on the chain. Note that coins part of spend bundles that are pending in the mempool will also be included. /// diff --git a/src/wallet.rs b/src/wallet.rs index 9492b6c..1547152 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -772,6 +772,32 @@ pub async fn get_header_hash( .map(|resp| resp.header_hash()) } +pub async fn get_fee_estimate( + peer: &Peer, + target_time_seconds: u64 +) -> Result> { + let time_targets = vec![target_time_seconds]; + + // Call the request_fee_estimates function with the specified time target + let fee_estimate_group = peer + .request_fee_estimates(time_targets) + .await + .map_err(|e| ClientError::Rejection(format!("Request failed: {:?}", e)))?; + + // Check if there is an error in the response + if let Some(error_message) = fee_estimate_group.error { + return Err(ClientError::Rejection(error_message)); + } + + // Extract the first fee estimate from the response + if let Some(first_estimate) = fee_estimate_group.estimates.first() { + return Ok(first_estimate.estimated_fee_rate.mojos_per_clvm_cost); + } + + // If no estimates are found, return a custom error + Err(ClientError::Rejection("No fee estimates available".to_string())) +} + pub async fn is_coin_spent( peer: &Peer, coin_id: Bytes32, From 54d95951603545046e7c59f5b163737ed193d4c4 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Fri, 16 Aug 2024 20:03:27 -0400 Subject: [PATCH 2/3] add sign and verify msg --- index.d.ts | 18 ++++++++++++++++++ src/lib.rs | 29 +++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index e7200b7..1968462 100644 --- a/index.d.ts +++ b/index.d.ts @@ -320,6 +320,24 @@ export declare function updateStoreOwnership(storeInfo: DataStoreInfo, newOwnerP * @returns {Vec} The coin spends that the owner can sign to melt the store. */ export declare function meltStore(storeInfo: DataStoreInfo, ownerPublicKey: Buffer): Array +/** + * Signs a message using a private key. + * + * @param {Buffer} message - The message to be signed. + * @param {Buffer} privateKey - The private key to sign the message with. + * @returns {Promise} The signed message as a Buffer. + */ +export declare function signMessage(message: Buffer, privateKey: Buffer): Buffer + +/** + * Verifies a signed message using a public key. + * + * @param {Buffer} sig - The signature to verify. + * @param {Buffer} publicKey - The public key to verify the signature with. + * @param {Buffer} message - The original message that was signed. + * @returns {Promise} Whether the signature is valid. + */ +export declare function verifySignedMessage(sig: Buffer, publicKey: Buffer, message: Buffer): boolean export declare class Peer { /** * Creates a new Peer instance. diff --git a/src/lib.rs b/src/lib.rs index 9b5513c..6597db0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,11 +10,11 @@ mod wallet; use std::sync::Arc; use chia::bls::derive_keys::master_to_wallet_unhardened; -use chia::bls::{SecretKey as RustSecretKey, Signature as RustSignature}; +use chia::bls::{SecretKey as RustSecretKey, Signature as RustSignature, sign, verify}; use chia::client::Peer as RustPeer; use chia::client::Error as ClientError; use chia::{bls::PublicKey as RustPublicKey, traits::Streamable}; -use chia_protocol::Coin as RustCoin; +use chia_protocol::{Bytes, Coin as RustCoin}; use chia_protocol::CoinSpend as RustCoinSpend; use chia_protocol::Program as RustProgram; use chia_protocol::SpendBundle as RustSpendBundle; @@ -1235,6 +1235,31 @@ pub fn update_store_ownership( Ok(res.to_js()) } +#[napi] +pub fn sign_message( + message: Buffer, + private_key: Buffer, +) -> Result { + let sk = RustSecretKey::from_js(private_key); + let signed = sign(&sk, &message); + + // Convert the Vec to a Buffer + Ok(Buffer::from(signed.to_bytes().to_vec())) +} + +#[napi] +pub fn verify_signed_message( + sig: Buffer, + public_key: Buffer, + message: Buffer, +) -> Result { + let sig = RustSignature::from_js(sig); + let public_key = RustPublicKey::from_js(public_key); + let is_valid = verify(&sig, &public_key, &message); + + Ok(is_valid) +} + #[napi] /// Melts a store. The 1 mojo change will be used as a fee. /// From 2476b6f6e7d64f86967de656ba01c1ede6134562 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Fri, 16 Aug 2024 21:29:59 -0400 Subject: [PATCH 3/3] add sign and verify msg --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6597db0..f0fe387 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1249,13 +1249,13 @@ pub fn sign_message( #[napi] pub fn verify_signed_message( - sig: Buffer, + signature: Buffer, public_key: Buffer, message: Buffer, ) -> Result { - let sig = RustSignature::from_js(sig); - let public_key = RustPublicKey::from_js(public_key); - let is_valid = verify(&sig, &public_key, &message); + let sig = RustSignature::from_js(signature); + let pk = RustPublicKey::from_js(public_key); + let is_valid = verify(&sig, &pk, &message); Ok(is_valid) }