diff --git a/wallet/src/cli/programs/native_token_transfer.rs b/wallet/src/cli/programs/native_token_transfer.rs index dbaa3ca7..2949e803 100644 --- a/wallet/src/cli/programs/native_token_transfer.rs +++ b/wallet/src/cli/programs/native_token_transfer.rs @@ -24,21 +24,15 @@ pub enum AuthTransferSubcommand { #[arg( long, conflicts_with = "account_label", - conflicts_with = "pin", - required_unless_present_any = ["account_label", "pin"] + // required_unless_present = "account_label" )] account_id: Option, /// Account label (alternative to --account-id). - #[arg(long, conflicts_with = "account_id", conflicts_with = "pin")] + #[arg(long, conflicts_with = "account_id")] account_label: Option, - #[arg( - long, - conflicts_with = "account_id", - conflicts_with = "account_label", - requires = "key_path" - )] - pin: Option, #[arg(long)] + pin: Option, + #[arg(long, conflicts_with = "account_id", conflicts_with = "account_label")] key_path: Option, }, /// Send native tokens from one account to another with variable privacy. @@ -49,10 +43,10 @@ pub enum AuthTransferSubcommand { /// First is used for owned accounts, second otherwise. Send { /// from - valid 32 byte base58 string with privacy prefix. - #[arg(long, conflicts_with = "from_label", conflicts_with = "pin", required_unless_present_any = ["from_label", "pin"])] + #[arg(long, conflicts_with = "from_label")] from: Option, /// From account label (alternative to --from). - #[arg(long, conflicts_with = "from", conflicts_with = "pin")] + #[arg(long, conflicts_with = "from")] from_label: Option, /// to - valid 32 byte base58 string with privacy prefix. #[arg(long, conflicts_with = "to_label")] @@ -69,11 +63,11 @@ pub enum AuthTransferSubcommand { /// amount - amount of balance to move. #[arg(long)] amount: u128, - #[arg(long)] + #[arg(long, conflicts_with = "from", conflicts_with = "from_label")] pin: Option, #[arg(long, conflicts_with = "from", conflicts_with = "from_label")] from_key_path: Option, - #[arg(long, conflicts_with = "to", conflicts_with = "to_label")] + #[arg(long, conflicts_with = "from", conflicts_with = "from_label")] to_key_path: Option, }, } @@ -173,7 +167,7 @@ impl WalletSubcommand for AuthTransferSubcommand { )?), (None, None, Some(to_key_path)) => { Some(KeycardWallet::get_account_id_for_path_with_connect( - pin.as_ref().expect("Expect a pin as a String."), + &pin.as_ref().expect("Expect a pin as a String."), &to_key_path, )) } @@ -232,6 +226,8 @@ impl WalletSubcommand for AuthTransferSubcommand { from, to, amount, + pin, + key_path: from_key_path, }, ) } @@ -258,6 +254,8 @@ impl WalletSubcommand for AuthTransferSubcommand { to_npk, to_vpk, amount, + pin, + key_path: from_key_path, }, ) } @@ -287,14 +285,9 @@ pub enum NativeTokenTransferProgramSubcommand { /// amount - amount of balance to move. #[arg(long)] amount: u128, - #[arg( - long, - conflicts_with = "from", - conflicts_with = "from_label", - requires = "key_path" - )] + #[arg(long, conflicts_with = "from", conflicts_with = "from_label")] pin: Option, - #[arg(long)] + #[arg(long, conflicts_with = "from", conflicts_with = "from_label")] key_path: Option, }, /// Private execution. @@ -336,6 +329,10 @@ pub enum NativeTokenTransferProgramSubcommandShielded { /// amount - amount of balance to move. #[arg(long)] amount: u128, + #[arg(long)] + pin: Option, + #[arg(long)] + key_path: Option, }, /// Send native token transfer from `from` to `to` for `amount`. /// @@ -353,6 +350,10 @@ pub enum NativeTokenTransferProgramSubcommandShielded { /// amount - amount of balance to move. #[arg(long)] amount: u128, + #[arg(long)] + pin: Option, + #[arg(long)] + key_path: Option, }, } @@ -473,12 +474,18 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded { wallet_core: &mut WalletCore, ) -> Result { match self { - Self::ShieldedOwned { from, to, amount } => { + Self::ShieldedOwned { + from, + to, + amount, + pin, + key_path, + } => { let from: AccountId = from.parse().unwrap(); let to: AccountId = to.parse().unwrap(); let (tx_hash, secret) = NativeTokenTransfer(wallet_core) - .send_shielded_transfer(from, to, amount) + .send_shielded_transfer(from, to, amount, &pin, &key_path) .await?; println!("Transaction hash is {tx_hash}"); @@ -503,6 +510,8 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded { to_npk, to_vpk, amount, + pin, + key_path, } => { let from: AccountId = from.parse().unwrap(); @@ -518,7 +527,9 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded { nssa_core::encryption::shared_key_derivation::Secp256k1Point(to_vpk.to_vec()); let (tx_hash, _) = NativeTokenTransfer(wallet_core) - .send_shielded_transfer_to_outer_account(from, to_npk, to_vpk, amount) + .send_shielded_transfer_to_outer_account( + from, to_npk, to_vpk, amount, &pin, &key_path, + ) .await?; println!("Transaction hash is {tx_hash}"); diff --git a/wallet/src/cli/programs/token.rs b/wallet/src/cli/programs/token.rs index dae92e47..436b54a8 100644 --- a/wallet/src/cli/programs/token.rs +++ b/wallet/src/cli/programs/token.rs @@ -288,6 +288,8 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand { sender_account_id: from, recipient_account_id: to, balance_to_move: amount, + pin, + sender_key_path: from_key_path, }, ) } @@ -564,6 +566,10 @@ pub enum TokenProgramSubcommandPublic { recipient_account_id: String, #[arg(short, long)] balance_to_move: u128, + #[arg(long)] + pin: Option, + #[arg(long)] + sender_key_path: Option, }, // Burn tokens using the token program BurnToken { @@ -796,12 +802,16 @@ impl WalletSubcommand for TokenProgramSubcommandPublic { sender_account_id, recipient_account_id, balance_to_move, + pin, + sender_key_path, } => { Token(wallet_core) .send_transfer_transaction( sender_account_id.parse().unwrap(), recipient_account_id.parse().unwrap(), balance_to_move, + pin, + sender_key_path, ) .await?; Ok(SubcommandReturnValue::Empty) diff --git a/wallet/src/helperfunctions.rs b/wallet/src/helperfunctions.rs index 8e5e3f3e..f299842b 100644 --- a/wallet/src/helperfunctions.rs +++ b/wallet/src/helperfunctions.rs @@ -70,7 +70,8 @@ pub fn resolve_id_or_label( (None, None, Some(pin)) => Ok(KeycardWallet::get_account_id_for_path_with_connect( pin, key_path.as_ref().expect("Expect a key path String."), - )), + ) + .to_string()), _ => anyhow::bail!("provide exactly one of account id, account label or keycard path"), } } diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index c9cf57f1..1362eed8 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -16,16 +16,19 @@ use chain_storage::WalletChainStore; use common::{HashType, transaction::NSSATransaction}; use config::WalletConfig; use key_protocol::key_management::key_tree::{chain_index::ChainIndex, traits::KeyNode as _}; +use keycard_wallet::KeycardWallet; use log::info; use nssa::{ - Account, AccountId, PrivacyPreservingTransaction, + Account, AccountId, PrivacyPreservingTransaction, PublicKey, Signature, privacy_preserving_transaction::{ circuit::{ProgramWithDependencies, Proof}, message::EncryptedAccountData, }, }; use nssa_core::{ - Commitment, MembershipProof, SharedSecretKey, account::Nonce, program::InstructionData, + Commitment, MembershipProof, SharedSecretKey, + account::{AccountWithMetadata, Nonce}, + program::InstructionData, }; pub use privacy_preserving_tx::PrivacyPreservingAccount; use sequencer_service_rpc::{RpcClient as _, SequencerClient, SequencerClientBuilder}; @@ -33,7 +36,7 @@ use tokio::io::AsyncWriteExt as _; use crate::{ config::{PersistentStorage, WalletConfigOverrides}, - helperfunctions::produce_data_for_storage, + helperfunctions::{parse_addr_with_privacy_prefix, produce_data_for_storage}, poller::TxPoller, }; @@ -363,10 +366,17 @@ impl WalletCore { accounts: Vec, instruction_data: InstructionData, program: &ProgramWithDependencies, + pin: &Option, + key_path: &Option, ) -> Result<(HashType, Vec), ExecutionFailureKind> { - self.send_privacy_preserving_tx_with_pre_check(accounts, instruction_data, program, |_| { - Ok(()) - }) + self.send_privacy_preserving_tx_with_pre_check( + accounts, + instruction_data, + program, + |_| Ok(()), + pin, + key_path, + ) .await } @@ -376,10 +386,53 @@ impl WalletCore { instruction_data: InstructionData, program: &ProgramWithDependencies, tx_pre_check: impl FnOnce(&[&Account]) -> Result<(), ExecutionFailureKind>, + pin: &Option, + key_path: &Option, ) -> Result<(HashType, Vec), ExecutionFailureKind> { let acc_manager = privacy_preserving_tx::AccountManager::new(self, accounts).await?; let pre_states = acc_manager.pre_states(); + + let keycard_account = if let Some(pin) = pin.as_ref() { + let account_id = KeycardWallet::get_account_id_for_path_with_connect( + pin, + key_path.as_ref().expect("Expect a key path String."), + ); + + let (acc_id, _) = + parse_addr_with_privacy_prefix(&account_id).expect("Valid parsing of account id"); + + let account_id = acc_id.parse().expect("Expect a valid Account Id"); + let account = self + .get_account_public(account_id) + .await + .expect("Expect valid account"); + + Some(AccountWithMetadata { + account, + is_authorized: true, + account_id, + }) + } else { + None + }; + + let nonces: Vec = acc_manager.public_account_nonces().into_iter().collect(); + + let account_ids: Vec = acc_manager.public_account_ids(); + + let visibility_mask = acc_manager.visibility_mask().to_vec(); + + if let Some(acc) = keycard_account.as_ref() { + nonces.push(acc.account.nonce); + + account_ids.push(acc.account_id); + + visibility_mask.push(0); + + pre_states.push(acc.clone()); + } + tx_pre_check( &pre_states .iter() @@ -391,7 +444,7 @@ impl WalletCore { let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove( pre_states, instruction_data, - acc_manager.visibility_mask().to_vec(), + visibility_mask, private_account_keys .iter() .map(|keys| (keys.npk, keys.ssk)) @@ -404,8 +457,8 @@ impl WalletCore { let message = nssa::privacy_preserving_transaction::message::Message::try_from_circuit_output( - acc_manager.public_account_ids(), - Vec::from_iter(acc_manager.public_account_nonces()), + account_ids, + nonces, private_account_keys .iter() .map(|keys| (keys.npk, keys.vpk.clone(), keys.epk.clone())) @@ -414,7 +467,7 @@ impl WalletCore { ) .unwrap(); - let witness_set = Self::sign_privacy_message(&message, &proof, &acc_manager) + let witness_set = Self::sign_privacy_message(&message, &proof, &acc_manager, pin, key_path) .expect("Expect a valid witness set"); let tx = PrivacyPreservingTransaction::new(message, witness_set); @@ -574,13 +627,68 @@ impl WalletCore { message: &nssa::privacy_preserving_transaction::Message, proof: &Proof, acc_manager: &privacy_preserving_tx::AccountManager, + _pin: &Option, + _key_path: &Option, ) -> Result { + //if pin.is_none() { + Ok( + nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message( + message, + proof.clone(), + &acc_manager.public_account_auth(), + ), + ) + /*} else { + let public_key = KeycardWallet::get_public_key_for_path_with_connect( + &pin.as_ref().expect("Expect a pin as a String."), + &key_path.as_ref().expect("Expect a key path String."), + ); + let signature = KeycardWallet::sign_message_for_path_with_connect( + &pin.as_ref().expect("Expect a pin as a String."), + &key_path.as_ref().expect("Expect a key path String."), + &message.hash_message(), + ) + .expect("Expect a valid signature"); + let mut signatures = Vec::::new(); + signatures.push(signature); + let mut public_keys = Vec::::new(); + public_keys.push(public_key); + Ok( + nssa::privacy_preserving_transaction::witness_set::WitnessSet::from_list( + proof.clone(), + &signatures, + &public_keys, + ), + ) + }*/ + } + + pub fn sign_privacy_message_with_keycard( + message: &nssa::privacy_preserving_transaction::Message, + proof: Proof, + pin: &String, + key_paths: &[String], + ) -> Result + { + let mut signatures = Vec::::new(); + let mut public_keys = Vec::::new(); + + for path in key_paths.iter() { + public_keys.push(KeycardWallet::get_public_key_for_path_with_connect( + &pin, &path, + )); + signatures.push( + KeycardWallet::sign_message_for_path_with_connect(&pin, &path, &message.hash_message()) + .expect("Expect a valid signature"), + ); + } + Ok( - nssa::privacy_preserving_transaction::witness_set::WitnessSet::for_message( - message, - proof.clone(), - &acc_manager.public_account_auth(), + nssa::privacy_preserving_transaction::witness_set::WitnessSet::from_list( + proof, + &signatures, + &public_keys, ), ) } diff --git a/wallet/src/program_facades/ata.rs b/wallet/src/program_facades/ata.rs index ac60fb63..a72d50a9 100644 --- a/wallet/src/program_facades/ata.rs +++ b/wallet/src/program_facades/ata.rs @@ -194,7 +194,13 @@ impl Ata<'_> { ]; self.0 - .send_privacy_preserving_tx(accounts, instruction_data, &ata_with_token_dependency()) + .send_privacy_preserving_tx( + accounts, + instruction_data, + &ata_with_token_dependency(), + &None, + &None, + ) .await .map(|(hash, mut secrets)| { let secret = secrets.pop().expect("expected owner's secret"); @@ -229,7 +235,13 @@ impl Ata<'_> { ]; self.0 - .send_privacy_preserving_tx(accounts, instruction_data, &ata_with_token_dependency()) + .send_privacy_preserving_tx( + accounts, + instruction_data, + &ata_with_token_dependency(), + &None, + &None, + ) .await .map(|(hash, mut secrets)| { let secret = secrets.pop().expect("expected owner's secret"); @@ -263,7 +275,13 @@ impl Ata<'_> { ]; self.0 - .send_privacy_preserving_tx(accounts, instruction_data, &ata_with_token_dependency()) + .send_privacy_preserving_tx( + accounts, + instruction_data, + &ata_with_token_dependency(), + &None, + &None, + ) .await .map(|(hash, mut secrets)| { let secret = secrets.pop().expect("expected owner's secret"); diff --git a/wallet/src/program_facades/native_token_transfer/deshielded.rs b/wallet/src/program_facades/native_token_transfer/deshielded.rs index d51f15ce..e7abbb3e 100644 --- a/wallet/src/program_facades/native_token_transfer/deshielded.rs +++ b/wallet/src/program_facades/native_token_transfer/deshielded.rs @@ -22,6 +22,8 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, + &None, + &None, ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/program_facades/native_token_transfer/private.rs b/wallet/src/program_facades/native_token_transfer/private.rs index c3a2125b..dbf9f5bf 100644 --- a/wallet/src/program_facades/native_token_transfer/private.rs +++ b/wallet/src/program_facades/native_token_transfer/private.rs @@ -19,6 +19,8 @@ impl NativeTokenTransfer<'_> { vec![PrivacyPreservingAccount::PrivateOwned(from)], Program::serialize_instruction(instruction).unwrap(), &Program::authenticated_transfer_program().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -49,6 +51,8 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -76,6 +80,8 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, + &None, + &None, ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/program_facades/native_token_transfer/shielded.rs b/wallet/src/program_facades/native_token_transfer/shielded.rs index 625e1a8b..48d90820 100644 --- a/wallet/src/program_facades/native_token_transfer/shielded.rs +++ b/wallet/src/program_facades/native_token_transfer/shielded.rs @@ -11,6 +11,8 @@ impl NativeTokenTransfer<'_> { from: AccountId, to: AccountId, balance_to_move: u128, + pin: &Option, + from_key_path: &Option, ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); @@ -23,6 +25,8 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, + pin, + from_key_path, ) .await .map(|(resp, secrets)| { @@ -40,6 +44,8 @@ impl NativeTokenTransfer<'_> { to_npk: NullifierPublicKey, to_vpk: ViewingPublicKey, balance_to_move: u128, + pin: &Option, + from_key_path: &Option, ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); @@ -55,6 +61,8 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, + pin, + from_key_path, ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/program_facades/pinata.rs b/wallet/src/program_facades/pinata.rs index 97118ecd..f30fcd5c 100644 --- a/wallet/src/program_facades/pinata.rs +++ b/wallet/src/program_facades/pinata.rs @@ -60,6 +60,8 @@ impl Pinata<'_> { ], nssa::program::Program::serialize_instruction(solution).unwrap(), &nssa::program::Program::pinata().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/program_facades/token.rs b/wallet/src/program_facades/token.rs index 1f941c8c..6a5d7ee1 100644 --- a/wallet/src/program_facades/token.rs +++ b/wallet/src/program_facades/token.rs @@ -1,5 +1,6 @@ use common::{HashType, transaction::NSSATransaction}; -use nssa::{AccountId, program::Program}; +use keycard_wallet::KeycardWallet; +use nssa::{AccountId, program::Program, public_transaction::WitnessSet}; use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey}; use sequencer_service_rpc::RpcClient as _; use token_core::Instruction; @@ -78,6 +79,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -108,6 +111,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -138,6 +143,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -153,6 +160,8 @@ impl Token<'_> { sender_account_id: AccountId, recipient_account_id: AccountId, amount: u128, + pin: Option, + sender_key_path: Option, ) -> Result { let account_ids = vec![sender_account_id, recipient_account_id]; let program_id = nssa::program::Program::token().id(); @@ -164,34 +173,12 @@ impl Token<'_> { .get_accounts_nonces(vec![sender_account_id]) .await .map_err(ExecutionFailureKind::SequencerError)?; - - let mut private_keys = Vec::new(); - let sender_sk = self + let recipient_nonces = self .0 - .storage - .user_data - .get_pub_account_signing_key(sender_account_id) - .ok_or(ExecutionFailureKind::KeyNotFoundError)?; - private_keys.push(sender_sk); - - if let Some(recipient_sk) = self - .0 - .storage - .user_data - .get_pub_account_signing_key(recipient_account_id) - { - private_keys.push(recipient_sk); - let recipient_nonces = self - .0 - .get_accounts_nonces(vec![recipient_account_id]) - .await - .map_err(ExecutionFailureKind::SequencerError)?; - nonces.extend(recipient_nonces); - } else { - println!( - "Receiver's account ({recipient_account_id}) private key not found in wallet. Proceeding with only sender's key." - ); - } + .get_accounts_nonces(vec![recipient_account_id]) + .await + .map_err(ExecutionFailureKind::SequencerError)?; + nonces.extend(recipient_nonces); let message = nssa::public_transaction::Message::try_new( program_id, @@ -200,8 +187,44 @@ impl Token<'_> { instruction, ) .unwrap(); - let witness_set = - nssa::public_transaction::WitnessSet::for_message(&message, &private_keys); + + let witness_set = if pin.is_none() { + let mut private_keys = Vec::new(); + let sender_sk = self + .0 + .storage + .user_data + .get_pub_account_signing_key(sender_account_id) + .ok_or(ExecutionFailureKind::KeyNotFoundError)?; + private_keys.push(sender_sk); + + if let Some(recipient_sk) = self + .0 + .storage + .user_data + .get_pub_account_signing_key(recipient_account_id) + { + private_keys.push(recipient_sk); + } else { + println!( + "Receiver's account ({recipient_account_id}) private key not found in wallet. Proceeding with only sender's key." + ); + } + + nssa::public_transaction::WitnessSet::for_message(&message, &private_keys) + } else { + let sender_public_key = KeycardWallet::get_public_key_for_path_with_connect( + &pin.as_ref().expect("Expect a pin as a String."), + &sender_key_path.as_ref().expect("Expect a key path String."), + ); + let signature = KeycardWallet::sign_message_for_path_with_connect( + &pin.expect("Expect a pin as a String."), + &sender_key_path.expect("Expect a key path String."), + &message.hash_message(), + ) + .expect("Expect a valid signature"); + WitnessSet::from_list(&[signature], &[sender_public_key]) + }; let tx = nssa::PublicTransaction::new(message, witness_set); @@ -232,6 +255,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -266,6 +291,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -296,6 +323,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -327,6 +356,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -362,6 +393,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -435,6 +468,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -465,6 +500,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -496,6 +533,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -591,6 +630,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -625,6 +666,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -655,6 +698,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -686,6 +731,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| { @@ -721,6 +768,8 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), + &None, + &None, ) .await .map(|(resp, secrets)| {