5 releases (breaking)
new 0.6.0 | Dec 18, 2024 |
---|---|
0.5.0 | Dec 10, 2024 |
0.4.0 | Nov 20, 2024 |
0.3.0 | Nov 1, 2024 |
0.2.0 | Sep 25, 2024 |
#234 in Magic Beans
3,643 downloads per month
91KB
2K
SLoC
canfund
Welcome to canfund
! This library provides automated cycles management for canisters on the Internet Computer (IC). canfund
helps ensure your canisters have sufficient cycles by automating the process of balance checking, funding, and cycle-minting based on configurable rules.
Features
- Automated Cycles Management: Automatically manages cycles for specified canisters, including the canister running
canfund
, according to predefined rules. - Periodic Balance Monitoring:
canfund
periodically checks cycle balances using ICP timers, ensuring your canisters stay adequately funded. - Optional Cycle Minting: If funding canister lacks sufficient cycles,
canfund
can mint new cycles from ICP. - Configurable Funding Strategies: Offers three customizable strategies for managing cycles, allowing you to tailor it to specific needs.
- Configurable Balance Fetching: Supports multiple methods for fetching the cycle balance of canisters during registration, accommodating different levels of access and canister configurations.
- Funding Callback: Canfund supports providing a callback function that is triggered after each funding round, which can be used for monitoring or logging purposes.
Table of Contents
Installation
To integrate canfund
into your Internet Computer project, add the library as a dependency:
cargo install `canfund`
Or alternatively manually define the dependency in your Cargo.toml
file:
{
"dependencies": {
"canfund": {
"git": "https://github.com/dfinity/canfund",
"version": "0.1.0"
}
}
}
Then, use canfund
in your canister code:
use canfund;
Usage
Configuration
To use canfund
, configure it with rules for managing cycles for your canisters. The configuration includes:
- Target Canisters: Specify the canisters that should be managed.
- Funding Rules: Set the thresholds and strategies that trigger additional cycle funding.
- Cycle Minting: Enable or disable the minting of cycles from the ICP balance when necessary.
Canister Registration
Each canister that you want to fund using canfund
must be registered. During registration, you must specify the method by which the canister's cycle balance will be fetched. canfund
supports two different balance-fetching methods:
-
FetchCyclesBalanceFromCanisterStatus: Retrieves the cycle balance from the response of an update call to a canister, typically using the
canister_status
method on the management canister. It can also work with responses from other canisters, such as a blackhole, or from self-exposed methods on any canister, as long as the response follows the CanisterStatusResponse specification.This method is only applicable if the funding canister has the required permissions to invoke the target canister’s method, such as being a controller when interacting with the management canister.
// By default, using the management canister (funding canister is a controller) let fetcher = FetchCyclesBalanceFromCanisterStatus::new(); // Using the blackhole canister (Blackhole is a controller) let fetcher = FetchCyclesBalanceFromCanisterStatus::new() .with_proxy(Principal::from_text("e3mmv-5qaaa-aaaah-aadma-cai").unwrap())); ); // Using a custom method of a canister (method is public) let fetcher = FetchCyclesBalanceFromCanisterStatus::new() .with_proxy(Principal::from_text("ml52i-qqaaa-aaaar-qaaba-cai").unwrap()) .with_method("get_canister_status".to_string()); );
Note: This method is currently the only one that accounts for the freezing threshold of the funded canister. As a result, the runtime and threshold-based funding strategies (explained below) are calculated based on when the canister becomes frozen. This behavior does not apply to the Blackhole proxy, as it currently does not return the required idle_cycles_burned_per_day field in its response.
-
FetchCyclesBalanceFromPrometheusMetrics: Fetches the cycle balance by leveraging Prometheus metrics exposed by the canister through an HTTP endpoint.
let fetcher = FetchCyclesBalanceFromPrometheusMetrics::new( "/metrics".to_string(), // path "canister_cycles_balance".to_string(), // metric name );
To register a canister with selected fetcher
:
fund_manager.register(
Principal::from_text("funded_canister_id").unwrap(),
RegisterOpts::new().with_cycles_fetcher(
Arc::new(fetcher)
),
);
Funding Strategies
canfund
provides three distinct strategies for funding your canisters:
-
BelowThreshold (Default): Funds the canister when its cycle balance falls below a predefined threshold.
let strategy = FundStrategy::BelowThreshold( CyclesThreshold::new() .with_min_cycles(125_000_000_000) .with_fund_cycles(250_000_000_000) );
-
BelowEstimatedRuntime: Funds the canister based on an estimated runtime in seconds. This strategy calculates the required cycles to keep the canister running for the specified duration.
let strategy = FundStrategy::BelowEstimatedRuntime( EstimatedRuntime::new() .with_min_runtime_secs(2 * 24 * 60 * 60) // 2 day .with_fund_runtime_secs(3 * 24 * 60 * 60) // 3 days .with_max_runtime_cycles_fund(1_000_000_000_000) .with_fallback_min_cycles(125_000_000_000) .with_fallback_fund_cycles(250_000_000_000), );
-
Always: Funds the canister at a fixed interval with a specified amount of cycles, regardless of the current balance.
let strategy = FundStrategy::Always(1_000);
Obtaining Cycles
canfund
can also be configured to obtain cycles from an ICP account balance if your canister requires more cycles than it currently holds. This is achieved by interacting with the ICP Ledger and the Cycles Minting Canister (CMC).
To enable this feature, you must provide the necessary configuration to allow canfund
to mint cycles. This configuration can also be set for each registered canister to override the global configuration.
let obtain_cycles_config = ObtainCyclesOptions {
obtain_cycles: Arc::new(MintCycles {
ledger: Arc::new(IcLedgerCanister::new(MAINNET_LEDGER_CANISTER_ID)),
cmc: Arc::new(IcCyclesMintingCanister::new(
MAINNET_CYCLES_MINTING_CANISTER_ID,
)),
from_subaccount: Subaccount::from(DEFAULT_SUBACCOUNT),
}),
};
funding_options.with_obtain_cycles_options(Some(obtain_cycles_config));
With this configuration, canfund
will periodically check the ICP balance and mint new cycles as needed to ensure that your canisters remain adequately funded.
Funding Callback
canfund
also supports registering a callback function that will be triggered after a funding round is completed. This feature is useful for monitoring and logging purposes, allowing you to capture and read data such as the remaining cycle balances and total cycles deposited per canister.
Example of registering a callback:
let funding_config = FundManagerOptions::new()
.with_funding_callback(Rc::new(|canister_records| {
// custom monitoring || logging logic
})
);
Initialization
Initialize canfund
with your configuration:
let funding_config = FundManagerOptions::new()
.with_interval_secs(12 * 60 * 60) // check twice a day
.with_strategy(strategy);
fund_manager.with_options(funding_config);
Examples
Here's a basic example of using canfund
for automated cycles management:
use canfund::{manager::{options::{CyclesThreshold, FundManagerOptions, FundStrategy}, RegisterOpts}, operations::fetch::FetchCyclesBalanceFromCanisterStatus, FundManager};
#[ic_cdk_macros::init]
fn initialize() {
let mut fund_manager = FundManager::new();
let funding_config = FundManagerOptions::new()
.with_interval_secs(12 * 60 * 60)
.with_strategy(FundStrategy::BelowThreshold(
CyclesThreshold::new()
.with_min_cycles(125_000_000_000)
.with_fund_cycles(250_000_000_000),
));
fund_manager.with_options(funding_config);
fund_manager.register(
Principal::from_text("funded_canister_id").unwrap(),
RegisterOpts::new().with_cycles_fetcher(
Arc::new(FetchCyclesBalanceFromCanisterStatus::new())
),
);
// Note: the funding canister is NOT automatically registered
fund_manager.register(
id(),
RegisterOpts::new(),
);
fund_manager.start();
}
Full examples can be found in the examples folder for simple and advanced funding configurations.
License
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
This README provides an overview of canfund
, along with installation instructions and examples to help you get started. Contributions and feedback are welcome!
Dependencies
~4–11MB
~138K SLoC