diff --git a/src/conversions.rs b/src/conversions.rs new file mode 100644 index 0000000..63d56a9 --- /dev/null +++ b/src/conversions.rs @@ -0,0 +1,247 @@ +use chia::{ + bls::{PublicKey, SecretKey, Signature}, + protocol::{Bytes, Bytes32, Program}, +}; +use napi::bindgen_prelude::*; +use napi::Result; +use thiserror::Error; + +use crate::{js, rust}; + +#[derive(Error, Debug)] +pub enum ConversionError { + #[error("Expected different byte length {0}")] + DifferentLength(u32), + + #[error("Invalid public key")] + InvalidPublicKey, + + #[error("Invalid private key")] + InvalidPrivateKey, + + #[error("Invalid signature")] + InvalidSignature, + + #[error("Missing proof")] + MissingProof, + + #[error("Missing delegated puzzle info")] + MissingDelegatedPuzzleInfo, + + #[error("Invalid URI: {0}")] + InvalidUri(String), +} + +pub trait FromJs { + fn from_js(value: T) -> Result + where + Self: Sized; +} + +pub trait ToJs { + fn to_js(&self) -> Result; +} + +impl FromJs for Bytes32 { + fn from_js(value: Buffer) -> Result { + Self::try_from(value.as_ref().to_vec()) + .map_err(|_| js::err(ConversionError::DifferentLength(32))) + } +} + +impl ToJs for Bytes32 { + fn to_js(&self) -> Result { + Ok(Buffer::from(self.to_vec())) + } +} + +impl FromJs for Program { + fn from_js(value: Buffer) -> Result { + Ok(Self::from(value.to_vec())) + } +} + +impl ToJs for Program { + fn to_js(&self) -> Result { + Ok(Buffer::from(self.to_vec())) + } +} + +impl FromJs for Bytes { + fn from_js(value: Buffer) -> Result { + Ok(Self::new(value.to_vec())) + } +} + +impl ToJs for Bytes { + fn to_js(&self) -> Result { + Ok(Buffer::from(self.to_vec())) + } +} + +impl FromJs for PublicKey { + fn from_js(value: Buffer) -> Result { + Self::from_bytes( + &<[u8; 48]>::try_from(value.to_vec()) + .map_err(|_| js::err(ConversionError::DifferentLength(48)))?, + ) + .map_err(|_| js::err(ConversionError::InvalidPublicKey)) + } +} + +impl ToJs for PublicKey { + fn to_js(&self) -> Result { + Ok(Buffer::from(self.to_bytes().to_vec())) + } +} + +impl FromJs for SecretKey { + fn from_js(value: Buffer) -> Result { + Self::from_bytes( + &<[u8; 32]>::try_from(value.to_vec()) + .map_err(|_| js::err(ConversionError::DifferentLength(32)))?, + ) + .map_err(|_| js::err(ConversionError::InvalidPrivateKey)) + } +} + +impl ToJs for SecretKey { + fn to_js(&self) -> Result { + Ok(Buffer::from(self.to_bytes().to_vec())) + } +} + +impl FromJs for Signature { + fn from_js(value: Buffer) -> Result { + Self::from_bytes( + &<[u8; 96]>::try_from(value.to_vec()) + .map_err(|_| js::err(ConversionError::DifferentLength(96)))?, + ) + .map_err(|_| js::err(ConversionError::InvalidSignature)) + } +} + +impl ToJs for Signature { + fn to_js(&self) -> Result { + Ok(Buffer::from(self.to_bytes().to_vec())) + } +} + +impl FromJs for u64 { + fn from_js(value: BigInt) -> Result { + Ok(value.get_u64().1) + } +} + +impl ToJs for u64 { + fn to_js(&self) -> Result { + Ok(BigInt::from(*self)) + } +} + +impl FromJs for rust::Coin { + fn from_js(value: js::Coin) -> Result { + Ok(Self { + parent_coin_info: Bytes32::from_js(value.parent_coin_info)?, + puzzle_hash: Bytes32::from_js(value.puzzle_hash)?, + amount: u64::from_js(value.amount)?, + }) + } +} + +impl ToJs for rust::Coin { + fn to_js(&self) -> Result { + Ok(js::Coin { + parent_coin_info: self.parent_coin_info.to_js()?, + puzzle_hash: self.puzzle_hash.to_js()?, + amount: self.amount.to_js()?, + }) + } +} + +impl FromJs for rust::CoinSpend { + fn from_js(value: js::CoinSpend) -> Result { + Ok(Self { + coin: rust::Coin::from_js(value.coin)?, + puzzle_reveal: Program::from_js(value.puzzle_reveal)?, + solution: Program::from_js(value.solution)?, + }) + } +} + +impl ToJs for rust::CoinSpend { + fn to_js(&self) -> Result { + Ok(js::CoinSpend { + coin: self.coin.to_js()?, + puzzle_reveal: self.puzzle_reveal.to_js()?, + solution: self.solution.to_js()?, + }) + } +} + +impl FromJs for rust::LineageProof { + fn from_js(value: js::LineageProof) -> Result { + Ok(Self { + parent_parent_coin_info: Bytes32::from_js(value.parent_parent_coin_info)?, + parent_inner_puzzle_hash: Bytes32::from_js(value.parent_inner_puzzle_hash)?, + parent_amount: u64::from_js(value.parent_amount)?, + }) + } +} + +impl ToJs for rust::LineageProof { + fn to_js(&self) -> Result { + Ok(js::LineageProof { + parent_parent_coin_info: self.parent_parent_coin_info.to_js()?, + parent_inner_puzzle_hash: self.parent_inner_puzzle_hash.to_js()?, + parent_amount: self.parent_amount.to_js()?, + }) + } +} + +impl FromJs for rust::EveProof { + fn from_js(value: js::EveProof) -> Result { + Ok(rust::EveProof { + parent_parent_coin_info: Bytes32::from_js(value.parent_parent_coin_info)?, + parent_amount: u64::from_js(value.parent_amount)?, + }) + } +} + +impl ToJs for rust::EveProof { + fn to_js(&self) -> Result { + Ok(js::EveProof { + parent_parent_coin_info: self.parent_parent_coin_info.to_js()?, + parent_amount: self.parent_amount.to_js()?, + }) + } +} + +impl FromJs for rust::Proof { + fn from_js(value: js::Proof) -> Result { + if let Some(lineage_proof) = value.lineage_proof { + Ok(rust::Proof::Lineage(rust::LineageProof::from_js( + lineage_proof, + )?)) + } else if let Some(eve_proof) = value.eve_proof { + Ok(rust::Proof::Eve(rust::EveProof::from_js(eve_proof)?)) + } else { + Err(js::err(ConversionError::MissingProof)) + } + } +} + +impl ToJs for rust::Proof { + fn to_js(&self) -> Result { + Ok(match self { + rust::Proof::Lineage(lineage_proof) => js::Proof { + lineage_proof: Some(lineage_proof.to_js()?), + eve_proof: None, + }, + rust::Proof::Eve(eve_proof) => js::Proof { + lineage_proof: None, + eve_proof: Some(eve_proof.to_js()?), + }, + }) + } +} diff --git a/src/js.rs b/src/js.rs new file mode 100644 index 0000000..60a63bb --- /dev/null +++ b/src/js.rs @@ -0,0 +1,69 @@ +use napi::bindgen_prelude::*; + +#[napi(object)] +#[derive(Clone)] +/// Represents a coin on the Chia blockchain. +/// +/// @property {Buffer} parentCoinInfo - Parent coin name/id. +/// @property {Buffer} puzzleHash - Puzzle hash. +/// @property {BigInt} amount - Coin amount. +pub struct Coin { + pub parent_coin_info: Buffer, + pub puzzle_hash: Buffer, + pub amount: BigInt, +} + +#[napi(object)] +#[derive(Clone)] +/// Represents a coin spend on the Chia blockchain. +/// +/// @property {Coin} coin - The coin being spent. +/// @property {Buffer} puzzleReveal - The puzzle of the coin being spent. +/// @property {Buffer} solution - The solution. +pub struct CoinSpend { + pub coin: Coin, + pub puzzle_reveal: Buffer, + pub solution: Buffer, +} + +#[napi(object)] +#[derive(Clone)] +/// Represents a lineage proof that can be used to spend a singleton. +/// +/// @property {Buffer} parentParentCoinInfo - Parent coin's parent coin info/name/ID. +/// @property {Buffer} parentInnerPuzzleHash - Parent coin's inner puzzle hash. +/// @property {BigInt} parentAmount - Parent coin's amount. +pub struct LineageProof { + pub parent_parent_coin_info: Buffer, + pub parent_inner_puzzle_hash: Buffer, + pub parent_amount: BigInt, +} + +#[napi(object)] +#[derive(Clone)] +/// Represents an eve proof that can be used to spend a singleton. Parent coin is the singleton launcher. +/// +/// @property {Buffer} parentParentCoinInfo - Parent coin's name. +/// @property {BigInt} parentAmount - Parent coin's amount. +pub struct EveProof { + pub parent_parent_coin_info: Buffer, + pub parent_amount: BigInt, +} + +#[napi(object)] +#[derive(Clone)] +/// Represents a proof (either eve or lineage) that can be used to spend a singleton. Use `new_lineage_proof` or `new_eve_proof` to create a new proof. +/// +/// @property {Option} lineageProof - The lineage proof, if this is a lineage proof. +/// @property {Option} eveProof - The eve proof, if this is an eve proof. +pub struct Proof { + pub lineage_proof: Option, + pub eve_proof: Option, +} + +pub fn err(error: T) -> napi::Error +where + T: ToString, +{ + napi::Error::from_reason(error.to_string()) +} diff --git a/src/lib.rs b/src/lib.rs index 2c0dd08..61f6d6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +mod conversions; +mod js; +mod rust; mod server_coin; mod wallet; @@ -8,12 +11,9 @@ use chia::bls::{ use chia::protocol::{ Bytes as RustBytes, Bytes32 as RustBytes32, Coin as RustCoin, CoinSpend as RustCoinSpend, - NewPeakWallet, Program as RustProgram, ProtocolMessageTypes, SpendBundle as RustSpendBundle, -}; -use chia::puzzles::{ - standard::StandardArgs, DeriveSynthetic, EveProof as RustEveProof, - LineageProof as RustLineageProof, Proof as RustProof, + NewPeakWallet, ProtocolMessageTypes, SpendBundle as RustSpendBundle, }; +use chia::puzzles::{standard::StandardArgs, DeriveSynthetic, Proof as RustProof}; use chia::traits::Streamable; use chia_wallet_sdk::{ connect_peer, create_tls_connector, decode_address, encode_address, load_ssl_cert, @@ -21,9 +21,11 @@ use chia_wallet_sdk::{ DataStoreMetadata as RustDataStoreMetadata, DelegatedPuzzle as RustDelegatedPuzzle, NetworkId, Peer as RustPeer, }; +use conversions::{ConversionError, FromJs, ToJs}; +use js::{Coin, CoinSpend, EveProof, Proof}; use napi::bindgen_prelude::*; -use std::{net::SocketAddr, result::Result as StdResult, sync::Arc}; -use thiserror::Error; +use napi::Result; +use std::{net::SocketAddr, sync::Arc}; use tokio::sync::Mutex; use wallet::{ SuccessResponse as RustSuccessResponse, SyncStoreResponse as RustSyncStoreResponse, @@ -35,312 +37,13 @@ pub use wallet::*; #[macro_use] extern crate napi_derive; -#[derive(Error, Debug)] -pub enum ConversionError { - #[error("Expected different byte length {0}")] - DifferentLength(u32), - - #[error("Invalid public key")] - InvalidPublicKey, - - #[error("Invalid private key")] - InvalidPrivateKey, - - #[error("Invalid signature")] - InvalidSignature, - - #[error("Missing proof")] - MissingProof, - - #[error("Missing delegated puzzle info")] - MissingDelegatedPuzzleInfo, - - #[error("Invalid URI: {0}")] - InvalidUri(String), -} - -pub trait FromJS { - fn from_js(value: T) -> StdResult - where - Self: Sized; -} - -pub trait ToJS { - fn to_js(&self) -> StdResult; -} - -impl FromJS for RustBytes32 { - fn from_js(value: Buffer) -> StdResult { - RustBytes32::try_from(value.as_ref().to_vec()) - .map_err(|_| js(ConversionError::DifferentLength(32))) - } -} - -impl ToJS for RustBytes32 { - fn to_js(&self) -> StdResult { - Ok(Buffer::from(self.to_vec())) - } -} - -impl FromJS for RustProgram { - fn from_js(value: Buffer) -> StdResult { - Ok(RustProgram::from(value.to_vec())) - } -} - -impl ToJS for RustProgram { - fn to_js(&self) -> StdResult { - Ok(Buffer::from(self.to_vec())) - } -} - -impl FromJS for RustBytes { - fn from_js(value: Buffer) -> StdResult { - Ok(RustBytes::new(value.to_vec())) - } -} - -impl ToJS for RustBytes { - fn to_js(&self) -> StdResult { - Ok(Buffer::from(self.to_vec())) - } -} - -impl FromJS for RustPublicKey { - fn from_js(value: Buffer) -> StdResult { - RustPublicKey::from_bytes( - &<[u8; 48]>::try_from(value.to_vec()) - .map_err(|_| js(ConversionError::DifferentLength(48)))?, - ) - .map_err(|_| js(ConversionError::InvalidPublicKey)) - } -} - -impl ToJS for RustPublicKey { - fn to_js(&self) -> StdResult { - Ok(Buffer::from(self.to_bytes().to_vec())) - } -} - -impl FromJS for RustSecretKey { - fn from_js(value: Buffer) -> StdResult { - RustSecretKey::from_bytes( - &<[u8; 32]>::try_from(value.to_vec()) - .map_err(|_| js(ConversionError::DifferentLength(32)))?, - ) - .map_err(|_| js(ConversionError::InvalidPrivateKey)) - } -} - -impl ToJS for RustSecretKey { - fn to_js(&self) -> StdResult { - Ok(Buffer::from(self.to_bytes().to_vec())) - } -} - -impl FromJS for RustSignature { - fn from_js(value: Buffer) -> StdResult { - RustSignature::from_bytes( - &<[u8; 96]>::try_from(value.to_vec()) - .map_err(|_| js(ConversionError::DifferentLength(96)))?, - ) - .map_err(|_| js(ConversionError::InvalidSignature)) - } -} - -impl ToJS for RustSignature { - fn to_js(&self) -> StdResult { - Ok(Buffer::from(self.to_bytes().to_vec())) - } -} - -#[napi(object)] -#[derive(Clone)] -/// Represents a coin on the Chia blockchain. -/// -/// @property {Buffer} parentCoinInfo - Parent coin name/id. -/// @property {Buffer} puzzleHash - Puzzle hash. -/// @property {BigInt} amount - Coin amount. -pub struct Coin { - pub parent_coin_info: Buffer, - pub puzzle_hash: Buffer, - pub amount: BigInt, -} - -impl FromJS for u64 { - fn from_js(value: BigInt) -> StdResult { - Ok(value.get_u64().1) - } -} - -impl ToJS for u64 { - fn to_js(&self) -> StdResult { - Ok(BigInt::from(*self)) - } -} - -impl FromJS for RustCoin { - fn from_js(value: Coin) -> StdResult { - Ok(RustCoin { - parent_coin_info: RustBytes32::from_js(value.parent_coin_info)?, - puzzle_hash: RustBytes32::from_js(value.puzzle_hash)?, - amount: u64::from_js(value.amount)?, - }) - } -} - -impl ToJS for RustCoin { - fn to_js(&self) -> StdResult { - Ok(Coin { - parent_coin_info: self.parent_coin_info.to_js()?, - puzzle_hash: self.puzzle_hash.to_js()?, - amount: self.amount.to_js()?, - }) - } -} - -#[napi(object)] -#[derive(Clone)] -/// Represents a coin spend on the Chia blockchain. -/// -/// @property {Coin} coin - The coin being spent. -/// @property {Buffer} puzzleReveal - The puzzle of the coin being spent. -/// @property {Buffer} solution - The solution. -pub struct CoinSpend { - pub coin: Coin, - pub puzzle_reveal: Buffer, - pub solution: Buffer, -} - -impl FromJS for RustCoinSpend { - fn from_js(value: CoinSpend) -> StdResult { - Ok(RustCoinSpend { - coin: RustCoin::from_js(value.coin)?, - puzzle_reveal: RustProgram::from_js(value.puzzle_reveal)?, - solution: RustProgram::from_js(value.solution)?, - }) - } -} - -impl ToJS for RustCoinSpend { - fn to_js(&self) -> StdResult { - Ok(CoinSpend { - coin: self.coin.to_js()?, - puzzle_reveal: self.puzzle_reveal.to_js()?, - solution: self.solution.to_js()?, - }) - } -} - -#[napi(object)] -#[derive(Clone)] -/// Represents a lineage proof that can be used to spend a singleton. -/// -/// @property {Buffer} parentParentCoinInfo - Parent coin's parent coin info/name/ID. -/// @property {Buffer} parentInnerPuzzleHash - Parent coin's inner puzzle hash. -/// @property {BigInt} parentAmount - Parent coin's amount. -pub struct LineageProof { - pub parent_parent_coin_info: Buffer, - pub parent_inner_puzzle_hash: Buffer, - pub parent_amount: BigInt, -} - -impl FromJS for RustLineageProof { - fn from_js(value: LineageProof) -> StdResult { - Ok(RustLineageProof { - parent_parent_coin_info: RustBytes32::from_js(value.parent_parent_coin_info)?, - parent_inner_puzzle_hash: RustBytes32::from_js(value.parent_inner_puzzle_hash)?, - parent_amount: u64::from_js(value.parent_amount)?, - }) - } -} - -impl ToJS for RustLineageProof { - fn to_js(&self) -> StdResult { - Ok(LineageProof { - parent_parent_coin_info: self.parent_parent_coin_info.to_js()?, - parent_inner_puzzle_hash: self.parent_inner_puzzle_hash.to_js()?, - parent_amount: self.parent_amount.to_js()?, - }) - } -} - -#[napi(object)] -#[derive(Clone)] -/// Represents an eve proof that can be used to spend a singleton. Parent coin is the singleton launcher. -/// -/// @property {Buffer} parentParentCoinInfo - Parent coin's name. -/// @property {BigInt} parentAmount - Parent coin's amount. -pub struct EveProof { - pub parent_parent_coin_info: Buffer, - pub parent_amount: BigInt, -} - -impl FromJS for RustEveProof { - fn from_js(value: EveProof) -> StdResult { - Ok(RustEveProof { - parent_parent_coin_info: RustBytes32::from_js(value.parent_parent_coin_info)?, - parent_amount: u64::from_js(value.parent_amount)?, - }) - } -} - -impl ToJS for RustEveProof { - fn to_js(&self) -> StdResult { - Ok(EveProof { - parent_parent_coin_info: self.parent_parent_coin_info.to_js()?, - parent_amount: self.parent_amount.to_js()?, - }) - } -} - -#[napi(object)] -#[derive(Clone)] -/// Represents a proof (either eve or lineage) that can be used to spend a singleton. Use `new_lineage_proof` or `new_eve_proof` to create a new proof. -/// -/// @property {Option} lineageProof - The lineage proof, if this is a lineage proof. -/// @property {Option} eveProof - The eve proof, if this is an eve proof. -pub struct Proof { - pub lineage_proof: Option, - pub eve_proof: Option, -} - -impl FromJS for RustProof { - fn from_js(value: Proof) -> StdResult { - if let Some(lineage_proof) = value.lineage_proof { - Ok(RustProof::Lineage(RustLineageProof::from_js( - lineage_proof, - )?)) - } else if let Some(eve_proof) = value.eve_proof { - Ok(RustProof::Eve(RustEveProof::from_js(eve_proof)?)) - } else { - Err(js(ConversionError::MissingProof)) - } - } -} - -impl ToJS for RustProof { - fn to_js(&self) -> StdResult { - Ok(match self { - RustProof::Lineage(lineage_proof) => Proof { - lineage_proof: Some(lineage_proof.to_js()?), - eve_proof: None, - }, - RustProof::Eve(eve_proof) => Proof { - lineage_proof: None, - eve_proof: Some(eve_proof.to_js()?), - }, - }) - } -} - #[napi] /// Creates a new lineage proof. /// /// @param {LineageProof} lineageProof - The lineage proof. /// @returns {Proof} The new proof. -pub fn new_lineage_proof(lineage_proof: LineageProof) -> Proof { - Proof { +pub fn new_lineage_proof(lineage_proof: js::LineageProof) -> js::Proof { + js::Proof { lineage_proof: Some(lineage_proof), eve_proof: None, } @@ -373,8 +76,8 @@ pub struct DataStoreMetadata { pub bytes: Option, } -impl FromJS for RustDataStoreMetadata { - fn from_js(value: DataStoreMetadata) -> StdResult { +impl FromJs for RustDataStoreMetadata { + fn from_js(value: DataStoreMetadata) -> Result { Ok(RustDataStoreMetadata { root_hash: RustBytes32::from_js(value.root_hash)?, label: value.label, @@ -388,8 +91,8 @@ impl FromJS for RustDataStoreMetadata { } } -impl ToJS for RustDataStoreMetadata { - fn to_js(&self) -> StdResult { +impl ToJs for RustDataStoreMetadata { + fn to_js(&self) -> Result { Ok(DataStoreMetadata { root_hash: self.root_hash.to_js()?, label: self.label.clone(), @@ -418,8 +121,8 @@ pub struct DelegatedPuzzle { pub oracle_fee: Option, } -impl FromJS for RustDelegatedPuzzle { - fn from_js(value: DelegatedPuzzle) -> StdResult { +impl FromJs for RustDelegatedPuzzle { + fn from_js(value: DelegatedPuzzle) -> Result { Ok( if let Some(admin_inner_puzzle_hash) = value.admin_inner_puzzle_hash { RustDelegatedPuzzle::Admin(RustBytes32::from_js(admin_inner_puzzle_hash)?.into()) @@ -433,14 +136,14 @@ impl FromJS for RustDelegatedPuzzle { u64::from_js(oracle_fee)?, ) } else { - return Err(js(ConversionError::MissingDelegatedPuzzleInfo)); + return Err(js::err(ConversionError::MissingDelegatedPuzzleInfo)); }, ) } } -impl ToJS for RustDelegatedPuzzle { - fn to_js(&self) -> StdResult { +impl ToJs for RustDelegatedPuzzle { + fn to_js(&self) -> Result { match self { RustDelegatedPuzzle::Admin(admin_inner_puzzle_hash) => { let admin_inner_puzzle_hash: RustBytes32 = (*admin_inner_puzzle_hash).into(); @@ -498,8 +201,8 @@ pub struct DataStore { pub delegated_puzzles: Vec, // if empty, there is no delegation layer } -impl FromJS for RustDataStore { - fn from_js(value: DataStore) -> StdResult { +impl FromJs for RustDataStore { + fn from_js(value: DataStore) -> Result { Ok(RustDataStore { coin: RustCoin::from_js(value.coin)?, proof: RustProof::from_js(value.proof)?, @@ -512,14 +215,14 @@ impl FromJS for RustDataStore { .delegated_puzzles .into_iter() .map(RustDelegatedPuzzle::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, }, }) } } -impl ToJS for RustDataStore { - fn to_js(&self) -> StdResult { +impl ToJs for RustDataStore { + fn to_js(&self) -> Result { Ok(DataStore { coin: self.coin.to_js()?, proof: self.proof.to_js()?, @@ -532,7 +235,7 @@ impl ToJS for RustDataStore { .delegated_puzzles .iter() .map(RustDelegatedPuzzle::to_js) - .collect::, napi::Error>>()?, + .collect::>>()?, }) } } @@ -547,27 +250,27 @@ pub struct SuccessResponse { pub new_store: DataStore, } -impl FromJS for RustSuccessResponse { - fn from_js(value: SuccessResponse) -> StdResult { +impl FromJs for RustSuccessResponse { + fn from_js(value: SuccessResponse) -> Result { Ok(RustSuccessResponse { coin_spends: value .coin_spends .into_iter() .map(RustCoinSpend::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, new_datastore: RustDataStore::from_js(value.new_store)?, }) } } -impl ToJS for RustSuccessResponse { - fn to_js(&self) -> StdResult { +impl ToJs for RustSuccessResponse { + fn to_js(&self) -> Result { Ok(SuccessResponse { coin_spends: self .coin_spends .iter() .map(RustCoinSpend::to_js) - .collect::, napi::Error>>()?, + .collect::>>()?, new_store: self.new_datastore.to_js()?, }) } @@ -587,8 +290,8 @@ pub struct SyncStoreResponse { pub latest_height: u32, } -impl FromJS for RustSyncStoreResponse { - fn from_js(value: SyncStoreResponse) -> StdResult { +impl FromJs for RustSyncStoreResponse { + fn from_js(value: SyncStoreResponse) -> Result { let mut root_hash_history = None; if let (Some(root_hashes), Some(root_hashes_timestamps)) = @@ -613,15 +316,15 @@ impl FromJS for RustSyncStoreResponse { }) } } -impl ToJS for RustSyncStoreResponse { - fn to_js(&self) -> StdResult { +impl ToJs for RustSyncStoreResponse { + fn to_js(&self) -> Result { let root_hashes = self .root_hash_history .as_ref() .map(|v| { v.iter() .map(|(rh, _)| rh.to_js()) - .collect::, napi::Error>>() + .collect::>>() }) .transpose()?; @@ -631,7 +334,7 @@ impl ToJS for RustSyncStoreResponse { .map(|v| { v.iter() .map(|(_, ts)| ts.to_js()) - .collect::, napi::Error>>() + .collect::>>() }) .transpose()?; @@ -656,28 +359,28 @@ pub struct UnspentCoinsResponse { pub last_header_hash: Buffer, } -impl FromJS for RustUnspentCoinsResponse { - fn from_js(value: UnspentCoinsResponse) -> StdResult { +impl FromJs for RustUnspentCoinsResponse { + fn from_js(value: UnspentCoinsResponse) -> Result { Ok(RustUnspentCoinsResponse { coins: value .coins .into_iter() .map(RustCoin::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, last_height: value.last_height, last_header_hash: RustBytes32::from_js(value.last_header_hash)?, }) } } -impl ToJS for RustUnspentCoinsResponse { - fn to_js(&self) -> StdResult { +impl ToJs for RustUnspentCoinsResponse { + fn to_js(&self) -> Result { Ok(UnspentCoinsResponse { coins: self .coins .iter() .map(RustCoin::to_js) - .collect::, napi::Error>>()?, + .collect::>>()?, last_height: self.last_height, last_header_hash: self.last_header_hash.to_js()?, }) @@ -706,8 +409,8 @@ impl Peer { cert_path: String, key_path: String, ) -> napi::Result { - let cert = load_ssl_cert(&cert_path, &key_path).map_err(js)?; - let tls = create_tls_connector(&cert).map_err(js)?; + let cert = load_ssl_cert(&cert_path, &key_path).map_err(js::err)?; + let tls = create_tls_connector(&cert).map_err(js::err)?; let (peer, mut receiver) = connect_peer( if tesntet { NetworkId::Testnet11 @@ -718,11 +421,11 @@ impl Peer { if let Ok(socket_addr) = node_uri.parse::() { socket_addr } else { - return Err(js(ConversionError::InvalidUri(node_uri))); + return Err(js::err(ConversionError::InvalidUri(node_uri))); }, ) .await - .map_err(js)?; + .map_err(js::err)?; let inner = Arc::new(peer); let peak = Arc::new(Mutex::new(None)); @@ -762,7 +465,7 @@ impl Peer { RustBytes32::from_js(previous_header_hash)?, ) .await - .map_err(js)?; + .map_err(js::err)?; resp.to_js() } @@ -790,7 +493,7 @@ impl Peer { with_history, ) .await - .map_err(js)?; + .map_err(js::err)?; res.to_js() } @@ -818,7 +521,7 @@ impl Peer { with_history, ) .await - .map_err(js)?; + .map_err(js::err)?; res.to_js() } @@ -843,14 +546,14 @@ impl Peer { coin_spends .into_iter() .map(RustCoinSpend::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, agg_sig, ); Ok( wallet::broadcast_spend_bundle(&self.inner.clone(), spend_bundle) .await - .map_err(js)? + .map_err(js::err)? .error .unwrap_or(String::default()), ) @@ -876,7 +579,7 @@ impl Peer { RustBytes32::from_js(header_hash)?, ) .await - .map_err(js) + .map_err(js::err) } #[napi] @@ -887,7 +590,7 @@ impl Peer { pub async fn get_header_hash(&self, height: u32) -> napi::Result { get_header_hash(&self.inner.clone(), height) .await - .map_err(js)? + .map_err(js::err)? .to_js() } @@ -900,7 +603,7 @@ impl Peer { pub async fn get_fee_estimate(&self, target_time_seconds: BigInt) -> napi::Result { wallet::get_fee_estimate(&self.inner.clone(), u64::from_js(target_time_seconds)?) .await - .map_err(js)? + .map_err(js::err)? .to_js() } @@ -925,13 +628,14 @@ pub fn select_coins(all_coins: Vec, total_amount: BigInt) -> napi::Result< let coins: Vec = all_coins .into_iter() .map(RustCoin::from_js) - .collect::, napi::Error>>()?; - let selected_coins = wallet::select_coins(coins, u64::from_js(total_amount)?).map_err(js)?; + .collect::>>()?; + let selected_coins = + wallet::select_coins(coins, u64::from_js(total_amount)?).map_err(js::err)?; selected_coins .into_iter() .map(|c| c.to_js()) - .collect::, napi::Error>>() + .collect::>>() } #[allow(clippy::too_many_arguments)] @@ -964,7 +668,7 @@ pub fn mint_store( selected_coins .into_iter() .map(RustCoin::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, RustBytes32::from_js(root_hash)?, label, description, @@ -977,10 +681,10 @@ pub fn mint_store( delegated_puzzles .into_iter() .map(RustDelegatedPuzzle::from_js) - .collect::, napi::Error>>()?, - u64::from_js(fee).map_err(js)?, + .collect::>>()?, + u64::from_js(fee).map_err(js::err)?, ) - .map_err(js)?; + .map_err(js::err)?; response.to_js() } @@ -1004,11 +708,11 @@ pub fn oracle_spend( selected_coins .into_iter() .map(RustCoin::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, RustDataStore::from_js(store)?, u64::from_js(fee)?, ) - .map_err(js)?; + .map_err(js::err)?; response.to_js() } @@ -1032,19 +736,19 @@ pub fn add_fee( selected_coins .into_iter() .map(RustCoin::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, assert_coin_ids .into_iter() .map(RustBytes32::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, u64::from_js(fee)?, ) - .map_err(js)?; + .map_err(js::err)?; response .into_iter() .map(|cs| cs.to_js()) - .collect::, napi::Error>>() + .collect::>>() } #[napi] @@ -1104,7 +808,7 @@ pub fn secret_key_to_public_key(secret_key: Buffer) -> napi::Result { pub fn puzzle_hash_to_address(puzzle_hash: Buffer, prefix: String) -> napi::Result { let puzzle_hash = RustBytes32::from_js(puzzle_hash)?; - encode_address(puzzle_hash.into(), &prefix).map_err(js) + encode_address(puzzle_hash.into(), &prefix).map_err(js::err) } #[napi] @@ -1113,7 +817,7 @@ pub fn puzzle_hash_to_address(puzzle_hash: Buffer, prefix: String) -> napi::Resu /// @param {String} address - The address. /// @returns {Promise} The puzzle hash. pub fn address_to_puzzle_hash(address: String) -> napi::Result { - let (puzzle_hash, _) = decode_address(&address).map_err(js)?; + let (puzzle_hash, _) = decode_address(&address).map_err(js::err)?; let puzzle_hash: RustBytes32 = RustBytes32::new(puzzle_hash); puzzle_hash.to_js() @@ -1172,11 +876,11 @@ pub fn sign_coin_spends( let coin_spends = coin_spends .iter() .map(|cs| RustCoinSpend::from_js(cs.clone())) - .collect::, napi::Error>>()?; + .collect::>>()?; let private_keys = private_keys .iter() .map(|sk| RustSecretKey::from_js(sk.clone())) - .collect::, napi::Error>>()?; + .collect::>>()?; let sig = wallet::sign_coin_spends( coin_spends, @@ -1187,7 +891,7 @@ pub fn sign_coin_spends( TargetNetwork::Mainnet }, ) - .map_err(js)?; + .map_err(js::err)?; sig.to_js() } @@ -1234,7 +938,7 @@ pub fn update_store_metadata( (None, None, Some(writer_public_key)) => { DataStoreInnerSpend::Writer(RustPublicKey::from_js(writer_public_key)?) } - _ => return Err(js( + _ => return Err(js::err( "Exactly one of owner_public_key, admin_public_key, writer_public_key must be provided", )), }; @@ -1251,7 +955,7 @@ pub fn update_store_metadata( }, inner_spend_info, ) - .map_err(js)?; + .map_err(js::err)?; res.to_js() } @@ -1285,7 +989,7 @@ pub fn update_store_ownership( DataStoreInnerSpend::Admin(RustPublicKey::from_js(admin_public_key)?) } _ => { - return Err(js( + return Err(js::err( "Exactly one of owner_public_key, admin_public_key must be provided", )) } @@ -1297,10 +1001,10 @@ pub fn update_store_ownership( new_delegated_puzzles .into_iter() .map(RustDelegatedPuzzle::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, inner_spend_info, ) - .map_err(js)?; + .map_err(js::err)?; res.to_js() } @@ -1316,11 +1020,11 @@ pub fn melt_store(store: DataStore, owner_public_key: Buffer) -> napi::Result, napi::Error>>() + .collect::>>() } #[napi] @@ -1334,7 +1038,7 @@ pub fn sign_message(message: Buffer, private_key: Buffer) -> napi::Result) -> napi::Result { coin_spends .into_iter() .map(RustCoinSpend::from_js) - .collect::, napi::Error>>()?, + .collect::>>()?, ) - .map_err(js)? + .map_err(js::err)? .to_js() } - -fn js(error: T) -> napi::Error -where - T: ToString, -{ - napi::Error::from_reason(error.to_string()) -} diff --git a/src/rust.rs b/src/rust.rs new file mode 100644 index 0000000..611af0a --- /dev/null +++ b/src/rust.rs @@ -0,0 +1,2 @@ +pub use chia::protocol::*; +pub use chia::puzzles::{EveProof, LineageProof, Proof};