From 06a953959a555858d0a3f0afd999067d44d2164a Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Fri, 13 Dec 2024 05:37:28 -0800 Subject: [PATCH] Add bitcoin_get_block_headers --- src/ic-cdk/CHANGELOG.md | 1 + .../api/management_canister/bitcoin/mod.rs | 25 +++++++ .../api/management_canister/bitcoin/types.rs | 69 ++++++++++++++----- 3 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/ic-cdk/CHANGELOG.md b/src/ic-cdk/CHANGELOG.md index de7a3dfe2..dd3515d8e 100644 --- a/src/ic-cdk/CHANGELOG.md +++ b/src/ic-cdk/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add method `bitcoin_get_block_headers`. - Support management canister method: `subnet_info`. (#532) - Add types: `SubnetInfoArgs` and `SubnetInfoResult`. diff --git a/src/ic-cdk/src/api/management_canister/bitcoin/mod.rs b/src/ic-cdk/src/api/management_canister/bitcoin/mod.rs index 4769f17ee..4571431ec 100644 --- a/src/ic-cdk/src/api/management_canister/bitcoin/mod.rs +++ b/src/ic-cdk/src/api/management_canister/bitcoin/mod.rs @@ -23,6 +23,9 @@ const SEND_TRANSACTION_SUBMISSION_TESTNET: u128 = 2_000_000_000; const SEND_TRANSACTION_PAYLOAD_MAINNET: u128 = 20_000_000; const SEND_TRANSACTION_PAYLOAD_TESTNET: u128 = 8_000_000; +const GET_BLOCK_HEADERS_MAINNET: u128 = 4_000_000_000; +const GET_BLOCK_HEADERS_TESTNET: u128 = 4_000_000_000; + /// See [IC method `bitcoin_get_balance`](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-bitcoin_get_balance). /// /// This call requires cycles payment. @@ -115,3 +118,25 @@ pub async fn bitcoin_get_current_fee_percentiles( ) .await } + +/// See [IC method `bitcoin_get_block_headers`](https://internetcomputer.org/docs/current/references/ic-interface-spec#ic-bitcoin_get_block_headers). +/// +/// This call requires cycles payment. +/// This method handles the cycles cost under the hood. +/// Check [API fees & Pricing](https://internetcomputer.org/docs/current/developer-docs/integrations/bitcoin/bitcoin-how-it-works/#api-fees--pricing) for more details. +pub async fn bitcoin_get_block_headers( + arg: GetBlockHeadersRequest, +) -> CallResult<(GetBlockHeadersResponse,)> { + let cycles = match arg.network { + BitcoinNetwork::Mainnet => GET_BLOCK_HEADERS_MAINNET, + BitcoinNetwork::Testnet => GET_BLOCK_HEADERS_TESTNET, + BitcoinNetwork::Regtest => 0, + }; + call_with_payment128( + Principal::management_canister(), + "bitcoin_get_block_headers", + (arg,), + cycles, + ) + .await +} diff --git a/src/ic-cdk/src/api/management_canister/bitcoin/types.rs b/src/ic-cdk/src/api/management_canister/bitcoin/types.rs index 776b45f16..6f84013ba 100644 --- a/src/ic-cdk/src/api/management_canister/bitcoin/types.rs +++ b/src/ic-cdk/src/api/management_canister/bitcoin/types.rs @@ -34,10 +34,10 @@ pub type BitcoinAddress = String; /// Block Hash. pub type BlockHash = Vec; -/// Element in the Response of [bitcoin_get_current_fee_percentiles](super::bitcoin_get_current_fee_percentiles). +/// Element in the Response of [`bitcoin_get_current_fee_percentiles`](super::bitcoin_get_current_fee_percentiles). pub type MillisatoshiPerByte = u64; -/// Identifier of [Utxo]. +/// Identifier of [`Utxo`]. #[derive( CandidType, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, )] @@ -53,7 +53,7 @@ pub struct Outpoint { CandidType, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, )] pub struct Utxo { - /// See [Outpoint]. + /// See [`Outpoint`]. pub outpoint: Outpoint, /// Value in the units of satoshi. pub value: Satoshi, @@ -72,38 +72,38 @@ pub enum UtxoFilter { /// Page reference. /// /// DON'T construct it from scratch. - /// Only get it from the `next_page` field of [GetUtxosResponse]. + /// Only get it from the `next_page` field of [`GetUtxosResponse`]. #[serde(rename = "page")] Page(Vec), } -/// Argument type of [bitcoin_get_balance](super::bitcoin_get_balance). +/// Argument type of [`bitcoin_get_balance`](super::bitcoin_get_balance). #[derive( CandidType, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, )] pub struct GetBalanceRequest { - /// See [BitcoinAddress]. + /// See [`BitcoinAddress`]. pub address: BitcoinAddress, - /// See [BitcoinNetwork]. + /// See [`BitcoinNetwork`]. pub network: BitcoinNetwork, /// Minimum number of confirmations. There is an upper bound of 144. Typically set to a value around 6 in practice. pub min_confirmations: Option, } -/// Argument type of [bitcoin_get_utxos](super::bitcoin_get_utxos). +/// Argument type of [`bitcoin_get_utxos`](super::bitcoin_get_utxos). #[derive( CandidType, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, )] pub struct GetUtxosRequest { - /// See [BitcoinAddress]. + /// See [`BitcoinAddress`]. pub address: BitcoinAddress, - /// See [BitcoinNetwork]. + /// See [`BitcoinNetwork`]. pub network: BitcoinNetwork, - /// See [UtxoFilter]. + /// See [`UtxoFilter`]. pub filter: Option, } -/// Response type of [bitcoin_get_utxos](super::bitcoin_get_utxos). +/// Response type of [`bitcoin_get_utxos`](super::bitcoin_get_utxos). #[derive( CandidType, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, )] @@ -116,11 +116,11 @@ pub struct GetUtxosResponse { pub tip_height: u32, /// Page reference when the response needs to be paginated. /// - /// To be used in [UtxoFilter::Page]. + /// To be used in [`UtxoFilter::Page`]. pub next_page: Option>, } -/// Argument type of [bitcoin_send_transaction](super::bitcoin_send_transaction). +/// Argument type of [`bitcoin_send_transaction`](super::bitcoin_send_transaction). #[derive( CandidType, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, )] @@ -130,11 +130,11 @@ pub struct SendTransactionRequest { /// Several checks are performed. /// See [IC method `bitcoin_send_transaction`](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-bitcoin_send_transaction). pub transaction: Vec, - /// See [BitcoinNetwork]. + /// See [`BitcoinNetwork`]. pub network: BitcoinNetwork, } -/// Argument type of [bitcoin_get_current_fee_percentiles](super::bitcoin_get_current_fee_percentiles). +/// Argument type of [`bitcoin_get_current_fee_percentiles`](super::bitcoin_get_current_fee_percentiles). #[derive( CandidType, Serialize, @@ -150,6 +150,41 @@ pub struct SendTransactionRequest { Default, )] pub struct GetCurrentFeePercentilesRequest { - /// See [BitcoinNetwork]. + /// See [`BitcoinNetwork`]. pub network: BitcoinNetwork, } + +/// Argument type of [`bitcoin_get_block_headers`](super::bitcoin_get_block_headers). +#[derive( + CandidType, + Serialize, + Deserialize, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Clone, + Copy, + Default, +)] +pub struct GetBlockHeadersRequest { + /// The starting block height for the request. + pub start_height: u32, + /// The ending block height for the request, or `None` for the current tip. + pub end_height: Option, + /// See [`BitcoinNetwork`]. + pub network: BitcoinNetwork, +} + +/// Response type of [`bitcoin_get_block_headers`](super::bitcoin_get_block_headers). +#[derive( + CandidType, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, +)] +pub struct GetBlockHeadersResponse { + /// The tip of the blockchain when this request was filled. + pub tip_height: u32, + /// The requested block headers. + pub block_headers: Vec>, +}