Introduction
The Build on Dogecoin book is intended for developers to explain how smart contracts on the Internet Computer, often referred as canisters, can interact with the Dogecoin blockchain.
Background
Through a protocol-level integration with the Dogecoin network, canisters deployed on ICP can interact with the Dogecoin network directly without using a bridge or oracle.
To interact with the Dogecoin blockchain, your canister will make use of the following:
-
Dogecoin canister: Think of it as your decentralized gateway to reach the Dogecoin blockchain. This canister provides an API that can be used by others to query information about the Dogecoin network state, for example, unspent transaction outputs (UTXOs), block headers, or the balance of any Dogecoin address; and to send transactions to the network.
-
Threshold ECDSA: Your canister can have a secret key that is stored in a secure and decentralized manner using chain-key cryptography (several such keys can be computed by key derivation). Messages sent by the canister can be signed using this key, enabling your canister to send signed transactions to the Dogecoin network through the Dogecoin canister.
To submit a Dogecoin transaction from a canister, the following steps are typically performed:
- Request a public key from the threshold ECDSA API
- Derive a Dogecoin address from the public key
- Read UTXOs from the Dogecoin API
- Build the transaction payload
- Sign the transaction using the threshold ECDSA API
- Submit the transaction to the Dogecoin API
Getting Started
First, set up your development environment. Then, to build canisters interacting with the Dogecoin network, you will need to know how to:
-
Generate a Dogecoin address. Dogecoin addresses are necessary for your canister to sign transactions and hold DOGE. A canister can have multiple addresses.
-
Create a Dogecoin transaction. Dogecoin transactions spend UTXOs and create new UTXOs. A UTXO is the output of a Dogecoin transaction. It exists until it is used as the input of another transaction.
-
Sign the transaction using threshold ECDSA API. All inputs of a transaction must be signed before the transaction can be submitted to the Dogecoin network.
-
Submit the transaction by sending a request to the Dogecoin API that specifies the blob of the transaction and the target Dogecoin network (mainnet or regtest).
-
Read information from the Dogecoin network, such as UTXOs, address balances, or block headers.
Additional resources
Building Dogecoin applications is not trivial. It’s beneficial to understand core Bitcoin concepts which underpin Dogecoin, including transactions, UTXOs, the Script language, and hash formats.
Developer Environment
To develop Dogecoin applications to be deployed on ICP, your local developer environment will need to include:
-
A local Dogecoin regtest node.
-
The Rust toolchain for installing Rust crates and compiling Rust code.
-
The IC SDK for creating, deploying, and managing canisters. You can install it natively on macOS and Linux; however, Windows users will need to set up WSL 2 before installing the IC SDK.
Create a local Dogecoin network (regtest) with dogecoind
It is recommended to set up a local Dogecoin regtest network to mine blocks quickly and at will, which facilitates testing various cases without having to rely on the Dogecoin mainnet where blocks are produced every minute on average.
Example for a Linux machine:
# Download the binary
curl -L -O https://github.com/dogecoin/dogecoin/releases/download/v1.14.9/dogecoin-1.14.9-x86_64-linux-gnu.tar.gz
# Unpack
tar -xvf dogecoin-1.14.9-x86_64-linux-gnu.tar.gz
# Add binaries to the PATH environment variable
export PATH="$(pwd)/dogecoin-1.14.9/bin:$PATH"
There are currently no released binaries for Mac OS X. You will need to build Dogecoin Core from source. Follow the instructions in the Dogecoin Core repository.
This should be created in the project folder root. This allows you to run different local Dogecoin regtest networks for different projects.
mkdir dogecoin_data
cat > dogecoin_data/dogecoin.conf <<EOF
regtest=1
txindex=1
rpcuser=ic-doge-integration
rpcpassword=QPQiNaph19FqUsCrBRN0FII7lyM26B51fAMeBQzCb-E=
rpcauth=ic-doge-integration:cdf2741387f3a12438f69092f0fdad8e\$62081498c98bee09a0dce2b30671123fa561932992ce377585e8e08bb0c11dfa
EOF
Explanation of settings:
-
regtest=1: Enables Dogecoin’s regression test mode for local testing. -
txindex=1: Maintains a full transaction index to support lookups by transaction ID. -
rpcuser=ic-doge-integration: Sets a default username for JSON-RPC authentication. -
rpcpassword=QPQ…b-E=: Sets the password for JSON-RPC authentication. -
rpcauth=ic-doge-integration:cdf…dfa: Uses an alternative authentication method for RPC, combining the username and a salted hash.
Find more details about the dogecoin.conf settings in the Dogecoin Core Daemon documentation.
dogecoind -datadir=$(pwd)/dogecoin_data -printoconsole --port=18444
This command assumes that port 18444 on your machine is available. If it isn't, change the specified port accordingly.
Deploy your first app locally
Dogecoin API Endpoints
To be able to reach the Dogecoin network, your canister needs to target one of the available endpoints on the Dogecoin canister.
Dogecoin canister principal ID: gordg-fyaaa-aaaan-aaadq-cai
Available Endpoints
dogecoin_get_utxos
Returns the UTXOs associated with a Dogecoin address. UTXOs can be filtered by minimum confirmations (only UTXOs with at least the provided number of confirmations are returned, with some upper bound which varies with the current difficulty target) or via a page reference when pagination is used for addresses with many UTXOs.
dogecoin_get_utxos_query
Queries dogecoin_get_utxos using a query call. Since this is a query call, it returns quickly but results are not trustworthy.
dogecoin_get_balance
Returns the balance of a Dogecoin address in koinus (1 DOGE = 100,000,000 koinus). Takes an optional argument min_confirmations which can be used to limit the set of considered UTXOs for the calculation of the balance to those with at least the provided number of confirmations.
dogecoin_get_balance_query
Queries dogecoin_get_balance using a query call. Since this is a query call, it returns quickly but results are not trustworthy.
dogecoin_get_current_fee_percentiles
Returns fee percentiles (in millikoinus/byte) from the most recent 1,000 Dogecoin transactions.
dogecoin_get_block_headers
Returns raw block headers for a given range of heights. At most 100 block headers are returned per request.
dogecoin_send_transaction
Sends a raw Dogecoin transaction to the specified network (mainnet or regtest).
See the Dogecoin canister interface specification for more details.
Cycles Cost
The costs of API calls in cycles and USD for the Dogecoin Mainnet APIs are presented in the following table. As a general principle for the Dogecoin API, some API calls must have a minimum number of cycles attached to them, as indicated in the column Minimum cycles to send with call. Requiring a relatively large minimum number of cycles makes it possible to change the pricing of API calls without breaking existing canisters when the Dogecoin subnet grows in terms of its replication factor in the future. Cycles not consumed by the call are returned to the caller.
The call for submitting a Dogecoin transaction to the Dogecoin network does not require a minimum number of cycles to send with the call as the charged cost is independent of the replication factor of the subnet.
The cost per API call in USD uses the XDR/USD exchange rate of November 25, 2025 (1 XDR = 1.411492 USD).
| API call | Description | Price (Cycles) | Price (USD) | Minimum cycles to send with call |
|---|---|---|---|---|
dogecoin_get_utxos | Retrieve the UTXO set for a Dogecoin address | 50_000_000 + 1 cycle per Wasm instruction | $0.00007058 + Wasm instruction cost | 10_000_000_000 |
dogecoin_get_current_fee_percentiles | Obtain the fee percentiles of the most recent transactions | 10_000_000 | $0.00001412 | 100_000_000 |
dogecoin_get_balance | Retrieve the balance of a given Dogecoin address | 10_000_000 | $0.00001412 | 100_000_000 |
dogecoin_send_transaction | Submit a Dogecoin transaction to the Dogecoin network, per transaction | 5_000_000_000 | $0.00706 | N/A |
dogecoin_send_transaction | Submit a Dogecoin transaction to the Dogecoin network, per byte of payload | 20_000_000 | $0.00002823 | N/A |
dogecoin_get_block_headers | Retrieve the block headers in specified range | 50_000_000 + 1 cycle per Wasm instruction | $0.00007058 + Wasm instruction cost | 10_000_000_000 |
Fees for calling the dogecoin_get_utxos and dogecoin_get_block_headers endpoints depend on the number of Wasm instructions that the Dogecoin canister consumes when processing the requests to ensure fair charging.
Dogecoin Transactions
Generating a Dogecoin address
Dogecoin, like Bitcoin, doesn't use accounts; instead, it uses a UTXO model. A UTXO is a Dogecoin transaction output that is unspent.
Each UTXO is associated with a Dogecoin address that is derived from either a public key or a script that defines the conditions under which the UTXO can be spent. A Dogecoin address is often used as a single-use invoice instead of a persistent address to increase privacy.
Dogecoin P2PKH addresses
Pay-to-public-key-hash (P2PKH) addresses are the most common types of addresses in Dogecoin. On mainnet, they start with the prefix D. They encode the hash of an ECDSA public key.
Dogecoin P2SH addresses
Another type of address is pay-to-script-hash (P2SH) address. It encodes the hash of a Dogecoin script and starts with a A or 9 on mainnet. The script can define complex locking conditions such as multisig or timelocks.
Generating addresses with threshold ECDSA
To generate a Dogecoin address, you need to generate an ECDSA public key. An ECDSA public key can be retrieved using the ecdsa_public_key system API endpoint. The basic Dogecoin example demonstrates how to generate a P2PKH address from a public key:
#[update]
pub async fn get_p2pkh_address() -> String {
let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());
// Unique derivation paths are used for every address type generated, to ensure
// each address has its own unique key pair.
let derivation_path = DerivationPath::p2pkh(0, 0);
// Get the ECDSA public key of this smart contract at the given derivation path
let public_key = get_ecdsa_public_key(&ctx, derivation_path.to_vec_u8_path()).await;
// Convert the public key to the format used by the Dogecoin library
let public_key = PublicKey::from_slice(&public_key).unwrap();
// Generate a P2PKH address from the public key.
// The address encoding (Base58) depends on the network type.
Address::p2pkh(public_key, ctx.dogecoin_network).to_string()
}
View the source on GitHub: get_p2pkh_address.rs
/// Retrieves the ECDSA public key for the given derivation path from the ECDSA API.
///
/// This function checks the local in-memory cache first. If no cached key exists,
/// it queries the ECDSA API for the public key at the given derivation path
/// and stores the result in the cache.
pub async fn get_ecdsa_public_key(ctx: &DogecoinContext, derivation_path: Vec<Vec<u8>>) -> Vec<u8> {
// Check in-memory cache first.
if let Some(key) = ECDSA_KEY_CACHE.with_borrow(|map| map.get(&derivation_path).cloned()) {
return key;
}
// Request the ECDSA public key from the ECDSA API.
let public_key = management_canister::ecdsa_public_key(&EcdsaPublicKeyArgs {
canister_id: None,
derivation_path: derivation_path.clone(),
key_id: EcdsaKeyId {
curve: EcdsaCurve::Secp256k1,
name: ctx.key_name.to_string(),
},
})
.await
.unwrap()
.public_key;
// Store it in the in-memory cache for future reuse.
ECDSA_KEY_CACHE.with_borrow_mut(|map| {
map.insert(derivation_path, public_key.clone());
});
public_key
}
View the source on GitHub: ecdsa.rs
Resources
Learn more about Dogecoin P2PKH addresses.
Learn more about the ecdsa_public_key API.
Creating Dogecoin Transactions
Unspent transaction outputs (UTXOs) are used as inputs to build Dogecoin transactions. Every Dogecoin transaction spends one or more UTXOs and in return creates new UTXOs. A UTXO exists until it is used as input in a transaction. In order to create a Dogecoin transaction, you need to:
-
Get the available UTXOs corresponding to a Dogecoin address controlled by your canister using the
dogecoin_get_utxosAPI endpoint. -
Calculate an appropriate transaction fee using the
dogecoin_get_current_fee_percentilesAPI endpoint. -
Select a subset of the available UTXOs to spend that covers the transaction amount and fee.
-
Create a transaction that spends the selected UTXOs and creates new UTXOs. You will need at least one for the recipient and, in most cases, one to collect the change.
A UTXO has the following structure:
// Unspent transaction output (UTXO).
pub struct Utxo {
/// See [Outpoint].
pub outpoint: Outpoint,
/// Value in the units of koinu.
pub value: Koinu,
/// Height in the blockchain.
pub height: u32,
}
/// Identifier of [Utxo].
pub struct Outpoint {
/// Transaction Identifier.
pub txid: Vec<u8>,
/// The output index in the transaction.
pub vout: u32,
}
Get available UTXOs
To get the available UTXOs for a Dogecoin address, use the dogecoin_get_utxos API endpoint. The following example demonstrates how to retrieve UTXOs for a given Dogecoin P2PKH address.
use crate::{dogecoin_get_utxos, DOGE_CONTEXT};
use ic_cdk::{
bitcoin_canister::{GetUtxosRequest, GetUtxosResponse},
update,
};
/// Returns the UTXOs of the given Dogecoin address.
#[update]
pub async fn get_utxos(address: String) -> GetUtxosResponse {
let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());
dogecoin_get_utxos(&GetUtxosRequest {
address,
network: ctx.network.into(),
filter: None,
})
.await
.unwrap()
}
View the source on GitHub: get_utxo.rs
pub async fn dogecoin_get_utxos(arg: &GetUtxosRequest) -> CallResult<GetUtxosResponse> {
let canister_id = get_dogecoin_canister_id(&into_dogecoin_network(arg.network));
// same cycles cost as for the Bitcoin canister
let cycles = bitcoin_canister::cost_get_utxos(arg);
Ok(Call::bounded_wait(canister_id, "dogecoin_get_utxos")
.with_arg(arg)
.with_cycles(cycles)
.await?
.candid()?)
}
View the source on GitHub: lib.rs
Calculate transaction fee per byte
The transaction fee of a Dogecoin transaction is calculated based on the size of the transaction in bytes. An appropriate fee per byte can be determined by looking at the fees of recent transactions on the Dogecoin mainnet. The following snippet shows how to estimate the fee per byte for a transaction using the dogecoin_get_current_fee_percentiles API endpoint and choosing the 50th percentile.
use crate::{dogecoin_get_fee_percentiles, MillikoinuPerByte, DOGE_CONTEXT};
use ic_cdk::{bitcoin_canister::GetCurrentFeePercentilesRequest, update};
/// Returns the 100 fee percentiles measured in millikoinu/byte.
/// Percentiles are computed from the last 10,000 transactions (if available).
#[update]
pub async fn get_current_fee_percentiles() -> Vec<MillikoinuPerByte> {
let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());
dogecoin_get_fee_percentiles(&GetCurrentFeePercentilesRequest {
network: ctx.network.into(),
})
.await
.unwrap()
}
View the source on GitHub: get_current_fee_percentiles.rs
pub async fn dogecoin_get_fee_percentiles(
arg: &GetCurrentFeePercentilesRequest,
) -> CallResult<Vec<MillikoinuPerByte>> {
let canister_id = get_dogecoin_canister_id(&into_dogecoin_network(arg.network));
// same cycles cost as for the Bitcoin canister
let cycles = bitcoin_canister::cost_get_current_fee_percentiles(arg);
Ok(
Call::bounded_wait(canister_id, "dogecoin_get_current_fee_percentiles")
.with_arg(arg)
.with_cycles(cycles)
.await?
.candid()?,
)
}
View the source on GitHub: lib.rs
Build the transaction
Now the transaction can be built. Since the fee of a transaction is based on its size, the transaction has to be built iteratively and signed with a mock signer that adds the respective size of the signature. Each selected UTXO is used as an input for the transaction and requires a signature.
The following snippet shows a simplified version of how to build a transaction that will be signed by a P2PKH address:
// Builds a transaction to send the given `amount` of koinu to the
// destination address.
pub async fn build_transaction(
ctx: &DogecoinContext,
own_public_key: &PublicKey,
own_address: &Address,
own_utxos: &[Utxo],
primary_output: &PrimaryOutput,
fee_per_byte: MillisatoshiPerByte,
) -> Transaction {
// We have a chicken-and-egg problem where we need to know the length
// of the transaction in order to compute its proper fee, but we need
// to know the proper fee in order to figure out the inputs needed for
// the transaction.
//
// We solve this problem iteratively. We start with a fee of zero, build
// and sign a transaction, see what its size is, and then update the fee,
// rebuild the transaction, until the fee is set to the correct amount.
let amount = match primary_output {
PrimaryOutput::Address(_, amt) => *amt, // grab the amount
PrimaryOutput::OpReturn(_) => trap("expected an address output, got OP_RETURN"),
};
let mut fee = 0;
loop {
let utxos_to_spend = select_utxos_greedy(own_utxos, amount, fee).unwrap();
let transaction =
build_transaction_with_fee(utxos_to_spend, own_address, primary_output, fee).unwrap();
// Sign the transaction. In this case, we only care about the size
// of the signed transaction, so we use a mock signer here for efficiency.
let signed_transaction = sign_transaction(
ctx,
own_public_key,
own_address,
transaction.clone(),
vec![], // mock derivation path
mock_sign_with_ecdsa,
)
.await;
let tx_vsize = signed_transaction.vsize() as u64;
if (tx_vsize * fee_per_byte) / 1000 == fee {
return transaction;
} else {
fee = (tx_vsize * fee_per_byte) / 1000;
}
}
}
View the source on GitHub: p2pkh.rs
Signing Transactions
Before a transaction can be sent to the Dogecoin network, each input must be signed. Canisters can sign transactions with threshold ECDSA through the sign_with_ecdsa system API endpoint.
Threshold ECDSA
The following snippet shows a simplified example of how to sign a Dogecoin transaction where all UTXOs are owned by own_address and own_address is a P2PKH address.
pub async fn sign_transaction<SignFun, Fut>(
ctx: &DogecoinContext,
own_public_key: &PublicKey,
own_address: &Address,
mut transaction: Transaction,
derivation_path: Vec<Vec<u8>>,
signer: SignFun,
) -> Transaction
where
SignFun: Fn(String, Vec<Vec<u8>>, Vec<u8>) -> Fut,
Fut: std::future::Future<Output = SecpSignature>,
{
assert_eq!(
own_address.address_type(),
Some(AddressType::P2pkh),
"Only P2PKH addresses are supported"
);
let transaction_clone = transaction.clone();
let sighash_cache = SighashCache::new(&transaction_clone);
for (index, input) in transaction.input.iter_mut().enumerate() {
let sighash = sighash_cache
.legacy_signature_hash(
index,
&own_address.script_pubkey(),
EcdsaSighashType::All.to_u32(),
)
.unwrap();
let signature = signer(
ctx.key_name.to_string(),
derivation_path.clone(),
sighash.as_byte_array().to_vec(),
)
.await;
let mut signature = signature.serialize_der().to_vec();
signature.push(EcdsaSighashType::All.to_u32() as u8);
let sig_bytes = PushBytesBuf::try_from(signature).unwrap();
let pubkey_bytes = PushBytesBuf::try_from(own_public_key.to_bytes()).unwrap();
input.script_sig = Builder::new()
.push_slice(sig_bytes)
.push_slice(pubkey_bytes)
.into_script();
}
transaction
}
View the source on GitHub: p2pkh.rs
The signature function signer: SignFun passed as argument is shown below. This function makes a call to the sign_with_ecdsa system API endpoint to sign the provided transaction sighash.
/// Signs a 32-byte message hash using the ECDSA key derived from the given path.
///
/// This function uses the ICP ECDSA signing API to produce a compact, 64-byte signature.
pub async fn sign_with_ecdsa(
key_name: String,
derivation_path: Vec<Vec<u8>>,
message_hash: Vec<u8>,
) -> Signature {
let signature = management_canister::sign_with_ecdsa(&SignWithEcdsaArgs {
message_hash,
derivation_path,
key_id: EcdsaKeyId {
curve: EcdsaCurve::Secp256k1,
name: key_name,
},
})
.await
.unwrap()
.signature;
Signature::from_compact(&signature).unwrap()
}
View the source on GitHub: ecdsa.rs
Resources
Complete flow
The following snippet shows the full process, from generating a transaction to submitting it to the Dogecoin network:
use crate::{
common::{get_fee_per_byte, DerivationPath, PrimaryOutput},
dogecoin_get_utxos, dogecoin_send_transaction,
ecdsa::{get_ecdsa_public_key, sign_with_ecdsa},
p2pkh::{self},
SendRequest, DOGE_CONTEXT,
};
use bitcoin::{consensus::serialize, dogecoin::Address, PublicKey};
use ic_cdk::{
bitcoin_canister::{GetUtxosRequest, SendTransactionRequest},
trap, update,
};
use std::str::FromStr;
/// Sends the given amount of dogecoin from this smart contract's P2PKH address to the given address.
/// Returns the transaction ID.
#[update]
pub async fn send_from_p2pkh_address(request: SendRequest) -> String {
let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());
if request.amount_in_koinu == 0 {
trap("Amount must be greater than 0");
}
// Parse and validate the destination address. The address type needs to be
// valid for the Dogecoin network we are on.
let dst_address = Address::from_str(&request.destination_address)
.unwrap()
.require_network(ctx.dogecoin_network)
.unwrap();
// Unique derivation paths are used for every address type generated, to ensure
// each address has its own unique key pair. To generate a user-specific address,
// you would typically use a derivation path based on the user's identity or some other unique identifier.
let derivation_path = DerivationPath::p2pkh(0, 0);
// Get the ECDSA public key of this smart contract at the given derivation path.
let own_public_key = get_ecdsa_public_key(&ctx, derivation_path.to_vec_u8_path()).await;
// Convert the public key to the format used by the rust-dogecoin library.
let own_public_key = PublicKey::from_slice(&own_public_key).unwrap();
// Generate a P2PKH address from the public key.
let own_address = Address::p2pkh(own_public_key, ctx.dogecoin_network);
// Note that pagination may have to be used to get all UTXOs for the given address.
// For the sake of simplicity, it is assumed here that the `utxo` field in the response
// contains all UTXOs.
let own_utxos = dogecoin_get_utxos(&GetUtxosRequest {
address: own_address.to_string(),
network: ctx.network.into(),
filter: None,
})
.await
.unwrap()
.utxos;
// Build the transaction.
let fee_per_byte = get_fee_per_byte(&ctx).await;
let transaction = p2pkh::build_transaction(
&ctx,
&own_public_key,
&own_address,
&own_utxos,
&PrimaryOutput::Address(dst_address, request.amount_in_koinu),
fee_per_byte,
)
.await;
// Sign the transaction.
let signed_transaction = p2pkh::sign_transaction(
&ctx,
&own_public_key,
&own_address,
transaction,
derivation_path.to_vec_u8_path(),
sign_with_ecdsa,
)
.await;
// Send the transaction to the Dogecoin API.
dogecoin_send_transaction(&SendTransactionRequest {
network: ctx.network.into(),
transaction: serialize(&signed_transaction),
})
.await
.unwrap();
// Return the transaction ID.
signed_transaction.compute_txid().to_string()
}
View the source on GitHub: send_from_p2pkh_address.rs
/// Input structure for sending Dogecoin.
/// Used in P2PKH transfer endpoint.
#[derive(candid::CandidType, candid::Deserialize)]
pub struct SendRequest {
pub destination_address: String,
pub amount_in_koinu: u64,
}
View the source on GitHub: lib.rs
To submit transactions to the Dogecoin network, the Dogecoin API exposes the dogecoin_send_transaction method.
pub async fn dogecoin_send_transaction(arg: &SendTransactionRequest) -> CallResult<()> {
let canister_id = get_dogecoin_canister_id(&into_dogecoin_network(arg.network));
// same cycles cost as for the Bitcoin canister
let cycles = bitcoin_canister::cost_send_transaction(arg);
Ok(
Call::unbounded_wait(canister_id, "dogecoin_send_transaction")
.with_arg(arg)
.with_cycles(cycles)
.await?
.candid()?,
)
}
View the source on GitHub: lib.rs
Reading the Dogecoin State
Canisters can query information about the Dogecoin mainnet programmatically.
Reading unspent transaction outputs (UTXOs)
To read unspent transaction outputs (UTXOs) associated with an address from the Dogecoin network, make a call to the dogecoin_get_utxos Dogecoin API method.
use crate::{dogecoin_get_utxos, DOGE_CONTEXT};
use ic_cdk::{
bitcoin_canister::{GetUtxosRequest, GetUtxosResponse},
update,
};
/// Returns the UTXOs of the given Dogecoin address.
#[update]
pub async fn get_utxos(address: String) -> GetUtxosResponse {
let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());
dogecoin_get_utxos(&GetUtxosRequest {
address,
network: ctx.network.into(),
filter: None,
})
.await
.unwrap()
}
View the source on GitHub: get_utxo.rs
/// Gets the UTXOs of a specified address.
///
/// **Bounded-wait call**
///
/// Check the [Dogecoin Canisters Interface Specification](https://github.com/dfinity/dogecoin-canister/blob/master/INTERFACE_SPECIFICATION.md#dogecoin_get_utxos) for more details.
pub async fn dogecoin_get_utxos(arg: &GetUtxosRequest) -> CallResult<GetUtxosResponse> {
let canister_id = get_dogecoin_canister_id(&into_dogecoin_network(arg.network));
// same cycles cost as for the Bitcoin canister
let cycles = bitcoin_canister::cost_get_utxos(arg);
Ok(Call::bounded_wait(canister_id, "dogecoin_get_utxos")
.with_arg(arg)
.with_cycles(cycles)
.await?
.candid()?)
}
View the source on GitHub: lib.rs
Reading current balance
To read the current balance of a Dogecoin address, make a call to the dogecoin_get_balance Dogecoin API method.
use crate::{dogecoin_get_balance, Amount, DOGE_CONTEXT};
use ic_cdk::{bitcoin_canister::GetBalanceRequest, update};
/// Returns the balance of the given Dogecoin address.
#[update]
pub async fn get_balance(address: String) -> Amount {
let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());
dogecoin_get_balance(&GetBalanceRequest {
address,
network: ctx.network.into(),
min_confirmations: None,
})
.await
.unwrap()
}
View the source on GitHub: get_balance.rs
/// Gets the current balance of a Dogecoin address in Koinu.
///
/// **Bounded-wait call**
///
/// Check the [Dogecoin Canisters Interface Specification](https://github.com/dfinity/dogecoin-canister/blob/master/INTERFACE_SPECIFICATION.md#dogecoin_get_balance) for more details.
pub async fn dogecoin_get_balance(arg: &GetBalanceRequest) -> CallResult<Amount> {
let canister_id = get_dogecoin_canister_id(&into_dogecoin_network(arg.network));
// same cycles cost as for the Bitcoin canister
let cycles = bitcoin_canister::cost_get_balance(arg);
Ok(Call::bounded_wait(canister_id, "dogecoin_get_balance")
.with_arg(arg)
.with_cycles(cycles)
.await?
.candid()?)
}
View the source on GitHub: lib.rs
Reading the fee percentiles
The transaction fees on the Dogecoin network change dynamically based on the number of pending transactions. In order to get fee percentiles of the last 1,000 transactions, call the dogecoin_get_current_fee_percentiles Dogecoin API method.
This endpoint returns 101 numbers that are fees measured in millikoinus (1,000 millikoinus = 1 koinu; 100,000,000 koinus = 1 DOGE) per byte. The ith element of the result corresponds to the ith percentile fee. For example, to get the median fee over the last few blocks, look at the 50th element of the result.
use crate::{dogecoin_get_fee_percentiles, MillikoinuPerByte, DOGE_CONTEXT};
use ic_cdk::{bitcoin_canister::GetCurrentFeePercentilesRequest, update};
/// Returns the 100 fee percentiles measured in millikoinu/byte.
/// Percentiles are computed from the last 10,000 transactions (if available).
#[update]
pub async fn get_current_fee_percentiles() -> Vec<MillikoinuPerByte> {
let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());
dogecoin_get_fee_percentiles(&GetCurrentFeePercentilesRequest {
network: ctx.network.into(),
})
.await
.unwrap()
}
View the source on GitHub: get_current_fee_percentiles.rs
/// Gets the current transaction fee percentiles on the Dogecoin network.
///
/// **Bounded-wait call**
///
/// Check the [Dogecoin Canisters Interface Specification](https://github.com/dfinity/dogecoin-canister/blob/master/INTERFACE_SPECIFICATION.md#dogecoin_get_current_fee_percentiles) for more details.
pub async fn dogecoin_get_fee_percentiles(
arg: &GetCurrentFeePercentilesRequest,
) -> CallResult<Vec<MillikoinuPerByte>> {
let canister_id = get_dogecoin_canister_id(&into_dogecoin_network(arg.network));
// same cycles cost as for the Bitcoin canister
let cycles = bitcoin_canister::cost_get_current_fee_percentiles(arg);
Ok(
Call::bounded_wait(canister_id, "dogecoin_get_current_fee_percentiles")
.with_arg(arg)
.with_cycles(cycles)
.await?
.candid()?,
)
}
View the source on GitHub: lib.rs
Reading the block headers
To read the block headers within a provided range of start and end heights, make a call to the dogecoin_get_block_headers Dogecoin API method. Note that at most 100 block headers are returned per request.
use crate::{dogecoin_get_block_headers, DOGE_CONTEXT};
use ic_cdk::{
bitcoin_canister::{GetBlockHeadersRequest, GetBlockHeadersResponse},
update,
};
/// Returns the block headers in the given height range.
#[update]
pub async fn get_block_headers(
start_height: u32,
end_height: Option<u32>,
) -> GetBlockHeadersResponse {
let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());
dogecoin_get_block_headers(&GetBlockHeadersRequest {
start_height,
end_height,
network: ctx.network.into(),
})
.await
.unwrap()
}
View the source on GitHub: get_block_headers.rs
/// Gets the block headers in the provided range of block heights.
///
/// **Bounded-wait call**
///
/// Check the [Dogecoin Canisters Interface Specification](https://github.com/dfinity/dogecoin-canister/blob/master/INTERFACE_SPECIFICATION.md#dogecoin_get_block_headers) for more details.
pub async fn dogecoin_get_block_headers(
arg: &GetBlockHeadersRequest,
) -> CallResult<GetBlockHeadersResponse> {
let canister_id = get_dogecoin_canister_id(&into_dogecoin_network(arg.network));
// same cycles cost as for the Bitcoin canister
let cycles = bitcoin_canister::cost_get_block_headers(arg);
Ok(
Call::bounded_wait(canister_id, "dogecoin_get_block_headers")
.with_arg(arg)
.with_cycles(cycles)
.await?
.candid()?,
)
}
View the source on GitHub: lib.rs