diff --git a/README.md b/README.md index 5e37b8f6..92f26936 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ Returns the Solana address you should send SOL to in order to deposit. When `own ```sh icp canister call -e prod cksol_minter get_deposit_address \ - '(record { owner = null; subaccount = null })' --query + '(record { owner = null; subaccount = null })' ``` ### Notify the minter of a deposit diff --git a/integration_tests/src/lib.rs b/integration_tests/src/lib.rs index 53c291d9..e4a28f48 100644 --- a/integration_tests/src/lib.rs +++ b/integration_tests/src/lib.rs @@ -376,7 +376,7 @@ impl CkSolMinter<'_> { &self, args: impl Into, ) -> Result { - self.try_query_call("get_deposit_address", (args.into(),)) + self.try_update_call("get_deposit_address", (args.into(),), 0) .await } diff --git a/minter/cksol_minter.did b/minter/cksol_minter.did index f81e36f2..b6ce2f14 100644 --- a/minter/cksol_minter.did +++ b/minter/cksol_minter.did @@ -467,7 +467,7 @@ service : (MinterArg) -> { // // If the owner is not set, it defaults to the caller's principal. // The resolved owner must be a non-anonymous principal. - get_deposit_address: (GetDepositAddressArgs) -> (Address) query; + get_deposit_address: (GetDepositAddressArgs) -> (Address); // Register an account for automated deposit monitoring. // diff --git a/minter/src/address/mod.rs b/minter/src/address/mod.rs index 00ec5729..44323163 100644 --- a/minter/src/address/mod.rs +++ b/minter/src/address/mod.rs @@ -13,11 +13,9 @@ mod tests; pub(crate) type DerivationPath = Vec>; /// Implementation of the `get_deposit_address` canister endpoint. -/// Because the endpoint is a query, it must be synchronous and cannot fetch the -/// master key on demand — it traps if the key has not yet been initialized. -pub fn get_deposit_address(account: &Account) -> Address { - let master_key = read_state(|s| s.minter_public_key().cloned()) - .unwrap_or_else(|| ic_cdk::trap("master key not yet initialized")); +/// Fetches the Schnorr master key lazily if not yet cached. +pub async fn get_deposit_address(runtime: &R, account: &Account) -> Address { + let master_key = lazy_get_schnorr_master_key(runtime).await; account_address(&master_key, account) } diff --git a/minter/src/address/tests.rs b/minter/src/address/tests.rs index 5a471dc1..73d8c9d8 100644 --- a/minter/src/address/tests.rs +++ b/minter/src/address/tests.rs @@ -84,24 +84,30 @@ mod lazy_schnorr_master_key { mod get_deposit_address_tests { use super::*; - #[test] - fn returns_address_when_key_is_cached() { + #[tokio::test] + async fn returns_address_when_key_is_cached() { init_state(); init_schnorr_master_key(); + let runtime = TestCanisterRuntime::new(); let master_key = read_state(|s| s.minter_public_key().cloned().unwrap()); let acc = account(1); assert_eq!( - get_deposit_address(&acc), + get_deposit_address(&runtime, &acc).await, account_address(&master_key, &acc), ); } - #[test] - #[should_panic] - fn traps_when_key_is_not_cached() { + #[tokio::test] + async fn fetches_key_when_not_cached() { init_state(); - get_deposit_address(&account(1)); + let runtime = TestCanisterRuntime::new().with_schnorr_public_key(test_key_result()); + let acc = account(1); + + assert_eq!( + get_deposit_address(&runtime, &acc).await, + account_address(&test_key(), &acc), + ); } } diff --git a/minter/src/main.rs b/minter/src/main.rs index 4d144410..8cc8ccc0 100644 --- a/minter/src/main.rs +++ b/minter/src/main.rs @@ -59,10 +59,12 @@ fn post_upgrade(args: Option) { setup_timers(); } -#[ic_cdk::query] -fn get_deposit_address(args: GetDepositAddressArgs) -> Address { +#[ic_cdk::update] +async fn get_deposit_address(args: GetDepositAddressArgs) -> Address { let account = assert_non_anonymous_account(args.owner, args.subaccount); - cksol_minter::address::get_deposit_address(&account).into() + cksol_minter::address::get_deposit_address(&IcCanisterRuntime::new(), &account) + .await + .into() } #[ic_cdk::update]