diff --git a/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_api.rs b/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_api.rs index df4c61244..c69c66d20 100644 --- a/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_api.rs +++ b/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_api.rs @@ -1,32 +1,20 @@ -use candid::Principal; -use ic_cdk::api::call::call_with_payment; use ic_cdk::api::management_canister::bitcoin::{ - BitcoinNetwork, GetBalanceRequest, GetCurrentFeePercentilesRequest, GetUtxosRequest, - GetUtxosResponse, MillisatoshiPerByte, Satoshi, SendTransactionRequest, + bitcoin_get_balance, bitcoin_get_current_fee_percentiles, bitcoin_get_utxos, + bitcoin_send_transaction, BitcoinNetwork, GetBalanceRequest, GetCurrentFeePercentilesRequest, + GetUtxosRequest, GetUtxosResponse, MillisatoshiPerByte, SendTransactionRequest, }; -// The fees for the various bitcoin endpoints. -const GET_BALANCE_COST_CYCLES: u64 = 100_000_000; -const GET_UTXOS_COST_CYCLES: u64 = 10_000_000_000; -const GET_CURRENT_FEE_PERCENTILES_CYCLES: u64 = 100_000_000; -const SEND_TRANSACTION_BASE_CYCLES: u64 = 5_000_000_000; -const SEND_TRANSACTION_PER_BYTE_CYCLES: u64 = 20_000_000; - /// Returns the balance of the given bitcoin address. /// /// Relies on the `bitcoin_get_balance` endpoint. /// See https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-bitcoin_get_balance pub async fn get_balance(network: BitcoinNetwork, address: String) -> u64 { - let balance_res: Result<(Satoshi,), _> = call_with_payment( - Principal::management_canister(), - "bitcoin_get_balance", - (GetBalanceRequest { - address, - network: network.into(), - min_confirmations: None, - },), - GET_BALANCE_COST_CYCLES, - ) + let min_confirmations = None; + let balance_res = bitcoin_get_balance(GetBalanceRequest { + address, + network, + min_confirmations, + }) .await; balance_res.unwrap().0 @@ -37,16 +25,12 @@ pub async fn get_balance(network: BitcoinNetwork, address: String) -> u64 { /// NOTE: Relies on the `bitcoin_get_utxos` endpoint. /// See https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-bitcoin_get_utxos pub async fn get_utxos(network: BitcoinNetwork, address: String) -> GetUtxosResponse { - let utxos_res: Result<(GetUtxosResponse,), _> = call_with_payment( - Principal::management_canister(), - "bitcoin_get_utxos", - (GetUtxosRequest { - address, - network: network.into(), - filter: None, - },), - GET_UTXOS_COST_CYCLES, - ) + let filter = None; + let utxos_res = bitcoin_get_utxos(GetUtxosRequest { + address, + network, + filter, + }) .await; utxos_res.unwrap().0 @@ -58,15 +42,8 @@ pub async fn get_utxos(network: BitcoinNetwork, address: String) -> GetUtxosResp /// Relies on the `bitcoin_get_current_fee_percentiles` endpoint. /// See https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-bitcoin_get_current_fee_percentiles pub async fn get_current_fee_percentiles(network: BitcoinNetwork) -> Vec { - let res: Result<(Vec,), _> = call_with_payment( - Principal::management_canister(), - "bitcoin_get_current_fee_percentiles", - (GetCurrentFeePercentilesRequest { - network: network.into(), - },), - GET_CURRENT_FEE_PERCENTILES_CYCLES, - ) - .await; + let res = + bitcoin_get_current_fee_percentiles(GetCurrentFeePercentilesRequest { network }).await; res.unwrap().0 } @@ -76,18 +53,10 @@ pub async fn get_current_fee_percentiles(network: BitcoinNetwork) -> Vec) { - let transaction_fee = SEND_TRANSACTION_BASE_CYCLES - + (transaction.len() as u64) * SEND_TRANSACTION_PER_BYTE_CYCLES; - - let res: Result<(), _> = call_with_payment( - Principal::management_canister(), - "bitcoin_send_transaction", - (SendTransactionRequest { - network: network.into(), - transaction, - },), - transaction_fee, - ) + let res = bitcoin_send_transaction(SendTransactionRequest { + network, + transaction, + }) .await; res.unwrap(); diff --git a/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_wallet.rs b/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_wallet.rs index 4b0ddf939..75773eafd 100644 --- a/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_wallet.rs +++ b/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_wallet.rs @@ -14,7 +14,9 @@ use bitcoin::{ hashes::Hash, Address, AddressType, EcdsaSighashType, OutPoint, Script, Transaction, TxIn, TxOut, Txid, }; -use ic_cdk::api::management_canister::bitcoin::{MillisatoshiPerByte, BitcoinNetwork, Satoshi, Utxo}; +use ic_cdk::api::management_canister::bitcoin::{ + BitcoinNetwork, MillisatoshiPerByte, Satoshi, Utxo, +}; use ic_cdk::print; use sha2::Digest; use std::str::FromStr; @@ -28,7 +30,7 @@ pub async fn get_p2pkh_address( derivation_path: Vec>, ) -> String { // Fetch the public key of the given derivation path. - let public_key = ecdsa_api::ecdsa_public_key(key_name, derivation_path).await; + let public_key = ecdsa_api::get_ecdsa_public_key(key_name, derivation_path).await; // Compute the address. public_key_to_p2pkh_address(network, &public_key) @@ -59,7 +61,7 @@ pub async fn send( // Fetch our public key, P2PKH address, and UTXOs. let own_public_key = - ecdsa_api::ecdsa_public_key(key_name.clone(), derivation_path.clone()).await; + ecdsa_api::get_ecdsa_public_key(key_name.clone(), derivation_path.clone()).await; let own_address = public_key_to_p2pkh_address(network, &own_public_key); print("Fetching UTXOs..."); @@ -85,7 +87,7 @@ pub async fn send( .await; let tx_bytes = transaction.serialize(); - print(&format!("Transaction to sign: {}", hex::encode(tx_bytes))); + print(format!("Transaction to sign: {}", hex::encode(tx_bytes))); // Sign the transaction. let signed_transaction = sign_transaction( @@ -94,12 +96,12 @@ pub async fn send( transaction, key_name, derivation_path, - ecdsa_api::sign_with_ecdsa, + ecdsa_api::get_ecdsa_signature, ) .await; let signed_transaction_bytes = signed_transaction.serialize(); - print(&format!( + print(format!( "Signed transaction: {}", hex::encode(&signed_transaction_bytes) )); @@ -151,7 +153,7 @@ async fn build_transaction( let signed_tx_bytes_len = signed_transaction.serialize().len() as u64; if (signed_tx_bytes_len * fee_per_byte) / 1000 == total_fee { - print(&format!("Transaction built with fee {}.", total_fee)); + print(format!("Transaction built with fee {}.", total_fee)); return transaction; } else { total_fee = (signed_tx_bytes_len * fee_per_byte) / 1000; diff --git a/rust/basic_bitcoin/src/basic_bitcoin/src/ecdsa_api.rs b/rust/basic_bitcoin/src/basic_bitcoin/src/ecdsa_api.rs index 54a64c7f1..b50593137 100644 --- a/rust/basic_bitcoin/src/basic_bitcoin/src/ecdsa_api.rs +++ b/rust/basic_bitcoin/src/basic_bitcoin/src/ecdsa_api.rs @@ -1,49 +1,43 @@ -use crate::types::*; -use candid::Principal; -use ic_cdk::{api::call::call_with_payment, call}; - -// The fee for the `sign_with_ecdsa` endpoint using the test key. -const SIGN_WITH_ECDSA_COST_CYCLES: u64 = 10_000_000_000; +use ic_cdk::api::management_canister::ecdsa::{ + ecdsa_public_key, sign_with_ecdsa, EcdsaCurve, EcdsaKeyId, EcdsaPublicKeyArgument, + SignWithEcdsaArgument, +}; /// Returns the ECDSA public key of this canister at the given derivation path. -pub async fn ecdsa_public_key(key_name: String, derivation_path: Vec>) -> Vec { +pub async fn get_ecdsa_public_key(key_name: String, derivation_path: Vec>) -> Vec { // Retrieve the public key of this canister at the given derivation path // from the ECDSA API. - let res: Result<(ECDSAPublicKeyReply,), _> = call( - Principal::management_canister(), - "ecdsa_public_key", - (ECDSAPublicKey { - canister_id: None, - derivation_path, - key_id: EcdsaKeyId { - curve: EcdsaCurve::Secp256k1, - name: key_name, - }, - },), - ) + let canister_id = None; + let key_id = EcdsaKeyId { + curve: EcdsaCurve::Secp256k1, + name: key_name, + }; + + let res = ecdsa_public_key(EcdsaPublicKeyArgument { + canister_id, + derivation_path, + key_id, + }) .await; res.unwrap().0.public_key } -pub async fn sign_with_ecdsa( +pub async fn get_ecdsa_signature( key_name: String, derivation_path: Vec>, message_hash: Vec, ) -> Vec { - let res: Result<(SignWithECDSAReply,), _> = call_with_payment( - Principal::management_canister(), - "sign_with_ecdsa", - (SignWithECDSA { - message_hash, - derivation_path, - key_id: EcdsaKeyId { - curve: EcdsaCurve::Secp256k1, - name: key_name, - }, - },), - SIGN_WITH_ECDSA_COST_CYCLES, - ) + let key_id = EcdsaKeyId { + curve: EcdsaCurve::Secp256k1, + name: key_name, + }; + + let res = sign_with_ecdsa(SignWithEcdsaArgument { + message_hash, + derivation_path, + key_id, + }) .await; res.unwrap().0.signature