diff --git a/Cargo.lock b/Cargo.lock index 320304e..11d57c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -758,6 +758,7 @@ dependencies = [ "napi", "napi-build", "napi-derive", + "native-tls", "num-bigint", "openssl", "openssl-sys", diff --git a/Cargo.toml b/Cargo.toml index 5a3a535..3b8ca26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ chia-wallet-sdk = { version = "0.13.0", features = ["chip-0035"] } hex-literal = "0.4.1" num-bigint = "0.4.6" hex = "0.4.3" +native-tls = "0.2.12" [target.aarch64-unknown-linux-gnu.dependencies] openssl = { version = "0.10.64", features = ["vendored"] } diff --git a/index.d.ts b/index.d.ts index 75ec3f4..a4abea4 100644 --- a/index.d.ts +++ b/index.d.ts @@ -403,17 +403,25 @@ export declare function syntheticKeyToPuzzleHash(syntheticKey: Buffer): Buffer * @returns {BigInt} The cost of the coin spends. */ export declare function getCost(coinSpends: Array): bigint +export declare class Tls { + /** + * Creates a new TLS connector. + * + * @param {String} certPath - Path to the certificate file (usually '~/.chia/mainnet/config/ssl/wallet/wallet_node.crt'). + * @param {String} keyPath - Path to the key file (usually '~/.chia/mainnet/config/ssl/wallet/wallet_node.key'). + */ + constructor(certPath: string, keyPath: string) +} export declare class Peer { /** * Creates a new Peer instance. * * @param {String} nodeUri - URI of the node (e.g., '127.0.0.1:58444'). * @param {bool} testnet - True for connecting to testnet11, false for mainnet. - * @param {String} certPath - Path to the certificate file (usually '~/.chia/mainnet/config/ssl/wallet/wallet_node.crt'). - * @param {String} keyPath - Path to the key file (usually '~/.chia/mainnet/config/ssl/wallet/wallet_node.key'). + * @param {Tls} tls - TLS connector. * @returns {Promise} A new Peer instance. */ - static new(nodeUri: string, tesntet: boolean, certPath: string, keyPath: string): Promise + static new(nodeUri: string, tesntet: boolean, tls: Tls): Promise /** * 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/index.js b/index.js index 9f71def..e4bcd2e 100644 --- a/index.js +++ b/index.js @@ -310,10 +310,11 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { newLineageProof, newEveProof, Peer, selectCoins, sendXch, morphLauncherId, createServerCoin, mintStore, oracleSpend, addFee, masterPublicKeyToWalletSyntheticKey, masterPublicKeyToFirstPuzzleHash, masterSecretKeyToWalletSyntheticSecretKey, secretKeyToPublicKey, puzzleHashToAddress, addressToPuzzleHash, adminDelegatedPuzzleFromKey, writerDelegatedPuzzleFromKey, oracleDelegatedPuzzle, signCoinSpends, getCoinId, updateStoreMetadata, updateStoreOwnership, meltStore, signMessage, verifySignedMessage, syntheticKeyToPuzzleHash, getCost } = nativeBinding +const { newLineageProof, newEveProof, Tls, Peer, selectCoins, sendXch, morphLauncherId, createServerCoin, mintStore, oracleSpend, addFee, masterPublicKeyToWalletSyntheticKey, masterPublicKeyToFirstPuzzleHash, masterSecretKeyToWalletSyntheticSecretKey, secretKeyToPublicKey, puzzleHashToAddress, addressToPuzzleHash, adminDelegatedPuzzleFromKey, writerDelegatedPuzzleFromKey, oracleDelegatedPuzzle, signCoinSpends, getCoinId, updateStoreMetadata, updateStoreOwnership, meltStore, signMessage, verifySignedMessage, syntheticKeyToPuzzleHash, getCost } = nativeBinding module.exports.newLineageProof = newLineageProof module.exports.newEveProof = newEveProof +module.exports.Tls = Tls module.exports.Peer = Peer module.exports.selectCoins = selectCoins module.exports.sendXch = sendXch diff --git a/src/lib.rs b/src/lib.rs index 883772d..1f7f966 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ use conversions::{ConversionError, FromJs, ToJs}; use js::{Coin, CoinSpend, CoinState, EveProof, Proof, ServerCoin}; use napi::bindgen_prelude::*; use napi::Result; +use native_tls::TlsConnector; use std::{net::SocketAddr, sync::Arc}; use tokio::sync::Mutex; use wallet::{SuccessResponse as RustSuccessResponse, SyncStoreResponse as RustSyncStoreResponse}; @@ -384,6 +385,23 @@ impl ToJs for rust::UnspentCoinsResponse { } } +#[napi] +pub struct Tls(TlsConnector); + +#[napi] +impl Tls { + #[napi(constructor)] + /// Creates a new TLS connector. + /// + /// @param {String} certPath - Path to the certificate file (usually '~/.chia/mainnet/config/ssl/wallet/wallet_node.crt'). + /// @param {String} keyPath - Path to the key file (usually '~/.chia/mainnet/config/ssl/wallet/wallet_node.key'). + pub fn new(cert_path: String, key_path: String) -> napi::Result { + let cert = load_ssl_cert(&cert_path, &key_path).map_err(js::err)?; + let tls = create_tls_connector(&cert).map_err(js::err)?; + Ok(Self(tls)) + } +} + #[napi] pub struct Peer { inner: Arc, @@ -397,24 +415,16 @@ impl Peer { /// /// @param {String} nodeUri - URI of the node (e.g., '127.0.0.1:58444'). /// @param {bool} testnet - True for connecting to testnet11, false for mainnet. - /// @param {String} certPath - Path to the certificate file (usually '~/.chia/mainnet/config/ssl/wallet/wallet_node.crt'). - /// @param {String} keyPath - Path to the key file (usually '~/.chia/mainnet/config/ssl/wallet/wallet_node.key'). + /// @param {Tls} tls - TLS connector. /// @returns {Promise} A new Peer instance. - pub async fn new( - node_uri: String, - tesntet: bool, - cert_path: String, - key_path: String, - ) -> napi::Result { - let cert = load_ssl_cert(&cert_path, &key_path).map_err(js::err)?; - let tls = create_tls_connector(&cert).map_err(js::err)?; + pub async fn new(node_uri: String, tesntet: bool, tls: &Tls) -> napi::Result { let (peer, mut receiver) = connect_peer( if tesntet { NetworkId::Testnet11 } else { NetworkId::Mainnet }, - tls, + tls.0.clone(), if let Ok(socket_addr) = node_uri.parse::() { socket_addr } else {