refactor and add pin support to program facades

This commit is contained in:
jonesmarvin8 2026-04-24 22:10:04 -04:00
parent 93a1487553
commit 7b4f973f96
25 changed files with 347 additions and 132 deletions

38
Cargo.lock generated
View File

@ -4011,6 +4011,43 @@ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.18",
] ]
[[package]]
name = "keycard_wallet"
version = "0.1.0"
dependencies = [
"amm_core",
"anyhow",
"async-stream",
"ata_core",
"base58",
"bip39",
"clap",
"common",
"env_logger",
"futures",
"hex",
"humantime",
"humantime-serde",
"indicatif",
"itertools 0.14.0",
"key_protocol",
"log",
"nssa",
"nssa_core",
"optfield",
"pyo3",
"rand 0.8.5",
"sequencer_service_rpc",
"serde",
"serde_json",
"sha2",
"testnet_initial_state",
"thiserror 2.0.18",
"token_core",
"tokio",
"url",
]
[[package]] [[package]]
name = "lazy-regex" name = "lazy-regex"
version = "3.6.0" version = "3.6.0"
@ -9107,6 +9144,7 @@ dependencies = [
"indicatif", "indicatif",
"itertools 0.14.0", "itertools 0.14.0",
"key_protocol", "key_protocol",
"keycard_wallet",
"log", "log",
"nssa", "nssa",
"nssa_core", "nssa_core",

View File

@ -38,6 +38,7 @@ members = [
"examples/program_deployment/methods/guest", "examples/program_deployment/methods/guest",
"bedrock_client", "bedrock_client",
"testnet_initial_state", "testnet_initial_state",
"keycard_wallet",
] ]
[workspace.dependencies] [workspace.dependencies]
@ -67,6 +68,7 @@ ata_program = { path = "programs/associated_token_account" }
test_program_methods = { path = "test_program_methods" } test_program_methods = { path = "test_program_methods" }
bedrock_client = { path = "bedrock_client" } bedrock_client = { path = "bedrock_client" }
testnet_initial_state = { path = "testnet_initial_state" } testnet_initial_state = { path = "testnet_initial_state" }
keycard_wallet = { path = "keycard_wallet" }
tokio = { version = "1.50", features = [ tokio = { version = "1.50", features = [
"net", "net",

View File

@ -134,6 +134,8 @@ async fn amm_public() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 7, amount: 7,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -163,6 +165,8 @@ async fn amm_public() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 7, amount: 7,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -551,6 +555,8 @@ async fn amm_new_pool_using_labels() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 5, amount: 5,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
@ -575,6 +581,8 @@ async fn amm_new_pool_using_labels() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 5, amount: 5,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;

View File

@ -269,6 +269,8 @@ async fn transfer_and_burn_via_ata() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: fund_amount, amount: fund_amount,
from_pin: None,
from_key_path: None,
}), }),
) )
.await?; .await?;
@ -501,6 +503,8 @@ async fn transfer_via_ata_private_owner() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: fund_amount, amount: fund_amount,
from_pin: None,
from_key_path: None,
}), }),
) )
.await?; .await?;
@ -615,6 +619,8 @@ async fn burn_via_ata_private_owner() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: fund_amount, amount: fund_amount,
from_pin: None,
from_key_path: None,
}), }),
) )
.await?; .await?;

View File

@ -31,6 +31,8 @@ async fn private_transfer_to_owned_account() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -72,6 +74,8 @@ async fn private_transfer_to_foreign_account() -> Result<()> {
to_npk: Some(to_npk_string), to_npk: Some(to_npk_string),
to_vpk: Some(hex::encode(to_vpk.0)), to_vpk: Some(hex::encode(to_vpk.0)),
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
let result = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; let result = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -122,6 +126,8 @@ async fn deshielded_transfer_to_public_account() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -187,6 +193,8 @@ async fn private_transfer_to_owned_account_using_claiming_path() -> Result<()> {
to_npk: Some(hex::encode(to_keys.nullifier_public_key.0)), to_npk: Some(hex::encode(to_keys.nullifier_public_key.0)),
to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)), to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)),
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
let sub_ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; let sub_ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -237,6 +245,8 @@ async fn shielded_transfer_to_owned_private_account() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -281,6 +291,8 @@ async fn shielded_transfer_to_foreign_account() -> Result<()> {
to_npk: Some(to_npk_string), to_npk: Some(to_npk_string),
to_vpk: Some(hex::encode(to_vpk.0)), to_vpk: Some(hex::encode(to_vpk.0)),
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
let result = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; let result = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -353,6 +365,8 @@ async fn private_transfer_to_owned_account_continuous_run_path() -> Result<()> {
to_npk: Some(hex::encode(to_keys.nullifier_public_key.0)), to_npk: Some(hex::encode(to_keys.nullifier_public_key.0)),
to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)), to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)),
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
let sub_ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; let sub_ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -399,6 +413,8 @@ async fn initialize_private_account() -> Result<()> {
let command = Command::AuthTransfer(AuthTransferSubcommand::Init { let command = Command::AuthTransfer(AuthTransferSubcommand::Init {
account_id: Some(format_private_account_id(account_id)), account_id: Some(format_private_account_id(account_id)),
account_label: None, account_label: None,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -456,6 +472,8 @@ async fn private_transfer_using_from_label() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -499,6 +517,8 @@ async fn initialize_private_account_using_label() -> Result<()> {
let command = Command::AuthTransfer(AuthTransferSubcommand::Init { let command = Command::AuthTransfer(AuthTransferSubcommand::Init {
account_id: None, account_id: None,
account_label: Some(label), account_label: Some(label),
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;

View File

@ -24,6 +24,8 @@ async fn successful_transfer_to_existing_account() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -82,6 +84,8 @@ pub async fn successful_transfer_to_new_account() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -120,6 +124,8 @@ async fn failed_transfer_with_insufficient_balance() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 1_000_000, amount: 1_000_000,
pin: None,
key_path: None,
}); });
let failed_send = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await; let failed_send = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await;
@ -160,6 +166,8 @@ async fn two_consecutive_successful_transfers() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -194,6 +202,8 @@ async fn two_consecutive_successful_transfers() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -238,6 +248,8 @@ async fn initialize_public_account() -> Result<()> {
let command = Command::AuthTransfer(AuthTransferSubcommand::Init { let command = Command::AuthTransfer(AuthTransferSubcommand::Init {
account_id: Some(format_public_account_id(account_id)), account_id: Some(format_public_account_id(account_id)),
account_label: None, account_label: None,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -279,6 +291,8 @@ async fn successful_transfer_using_from_label() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -326,6 +340,8 @@ async fn successful_transfer_using_to_label() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;

View File

@ -113,6 +113,8 @@ async fn indexer_state_consistency() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -149,6 +151,8 @@ async fn indexer_state_consistency() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -235,6 +239,8 @@ async fn indexer_state_consistency_with_labels() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;

View File

@ -76,6 +76,8 @@ async fn sync_private_account_with_non_zero_chain_index() -> Result<()> {
to_npk: Some(hex::encode(to_keys.nullifier_public_key.0)), to_npk: Some(hex::encode(to_keys.nullifier_public_key.0)),
to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)), to_vpk: Some(hex::encode(to_keys.viewing_public_key.0)),
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
let sub_ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; let sub_ret = wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -152,6 +154,8 @@ async fn restore_keys_from_seed() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 100, amount: 100,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -164,6 +168,8 @@ async fn restore_keys_from_seed() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 101, amount: 101,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -204,6 +210,8 @@ async fn restore_keys_from_seed() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 102, amount: 102,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -216,6 +224,8 @@ async fn restore_keys_from_seed() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 103, amount: 103,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -281,6 +291,8 @@ async fn restore_keys_from_seed() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 10, amount: 10,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -292,6 +304,8 @@ async fn restore_keys_from_seed() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: 11, amount: 11,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;

View File

@ -54,6 +54,8 @@ async fn claim_pinata_to_uninitialized_public_account_fails_fast() -> Result<()>
Command::Pinata(PinataProgramAgnosticSubcommand::Claim { Command::Pinata(PinataProgramAgnosticSubcommand::Claim {
to: Some(winner_account_id_formatted), to: Some(winner_account_id_formatted),
to_label: None, to_label: None,
pin: None,
key_path: None,
}), }),
) )
.await; .await;
@ -109,6 +111,8 @@ async fn claim_pinata_to_uninitialized_private_account_fails_fast() -> Result<()
Command::Pinata(PinataProgramAgnosticSubcommand::Claim { Command::Pinata(PinataProgramAgnosticSubcommand::Claim {
to: Some(winner_account_id_formatted), to: Some(winner_account_id_formatted),
to_label: None, to_label: None,
pin: None,
key_path: None,
}), }),
) )
.await; .await;
@ -141,6 +145,8 @@ async fn claim_pinata_to_existing_public_account() -> Result<()> {
let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim { let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim {
to: Some(format_public_account_id(ctx.existing_public_accounts()[0])), to: Some(format_public_account_id(ctx.existing_public_accounts()[0])),
to_label: None, to_label: None,
pin: None,
key_path: None,
}); });
let pinata_balance_pre = ctx let pinata_balance_pre = ctx
@ -182,6 +188,8 @@ async fn claim_pinata_to_existing_private_account() -> Result<()> {
ctx.existing_private_accounts()[0], ctx.existing_private_accounts()[0],
)), )),
to_label: None, to_label: None,
pin: None,
key_path: None,
}); });
let pinata_balance_pre = ctx let pinata_balance_pre = ctx
@ -247,6 +255,8 @@ async fn claim_pinata_to_new_private_account() -> Result<()> {
let command = Command::AuthTransfer(AuthTransferSubcommand::Init { let command = Command::AuthTransfer(AuthTransferSubcommand::Init {
account_id: Some(winner_account_id_formatted.clone()), account_id: Some(winner_account_id_formatted.clone()),
account_label: None, account_label: None,
pin: None,
key_path: None,
}); });
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
@ -263,6 +273,8 @@ async fn claim_pinata_to_new_private_account() -> Result<()> {
let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim { let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim {
to: Some(winner_account_id_formatted), to: Some(winner_account_id_formatted),
to_label: None, to_label: None,
pin: None,
key_path: None,
}); });
let pinata_balance_pre = ctx let pinata_balance_pre = ctx

View File

@ -135,6 +135,8 @@ async fn create_and_transfer_public_token() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -180,6 +182,8 @@ async fn create_and_transfer_public_token() -> Result<()> {
holder: Some(format_public_account_id(recipient_account_id)), holder: Some(format_public_account_id(recipient_account_id)),
holder_label: None, holder_label: None,
amount: burn_amount, amount: burn_amount,
holder_pin: None,
holder_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -228,6 +232,8 @@ async fn create_and_transfer_public_token() -> Result<()> {
holder_npk: None, holder_npk: None,
holder_vpk: None, holder_vpk: None,
amount: mint_amount, amount: mint_amount,
holder_pin: None,
holder_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -373,6 +379,8 @@ async fn create_and_transfer_token_with_private_supply() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -400,6 +408,8 @@ async fn create_and_transfer_token_with_private_supply() -> Result<()> {
holder: Some(format_private_account_id(recipient_account_id)), holder: Some(format_private_account_id(recipient_account_id)),
holder_label: None, holder_label: None,
amount: burn_amount, amount: burn_amount,
holder_pin: None,
holder_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -567,6 +577,8 @@ async fn create_token_with_private_definition() -> Result<()> {
holder_npk: None, holder_npk: None,
holder_vpk: None, holder_vpk: None,
amount: mint_amount_public, amount: mint_amount_public,
holder_pin: None,
holder_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -615,6 +627,8 @@ async fn create_token_with_private_definition() -> Result<()> {
holder_npk: None, holder_npk: None,
holder_vpk: None, holder_vpk: None,
amount: mint_amount_private, amount: mint_amount_private,
holder_pin: None,
holder_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -757,6 +771,8 @@ async fn create_token_with_private_definition_and_supply() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -888,6 +904,8 @@ async fn shielded_token_transfer() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -1014,6 +1032,8 @@ async fn deshielded_token_transfer() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -1149,6 +1169,8 @@ async fn token_claiming_path_with_private_accounts() -> Result<()> {
holder_npk: Some(hex::encode(holder_keys.nullifier_public_key.0)), holder_npk: Some(hex::encode(holder_keys.nullifier_public_key.0)),
holder_vpk: Some(hex::encode(holder_keys.viewing_public_key.0)), holder_vpk: Some(hex::encode(holder_keys.viewing_public_key.0)),
amount: mint_amount, amount: mint_amount,
holder_pin: None,
holder_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;
@ -1352,6 +1374,8 @@ async fn transfer_token_using_from_label() -> Result<()> {
to_npk: None, to_npk: None,
to_vpk: None, to_vpk: None,
amount: transfer_amount, amount: transfer_amount,
from_pin: None,
from_key_path: None,
}; };
wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?; wallet::cli::execute_subcommand(ctx.wallet_mut(), Command::Token(subcommand)).await?;

View File

@ -31,7 +31,11 @@ impl WitnessSet {
} }
#[must_use] #[must_use]
pub fn from_list(proof: Proof, signatures: &Vec<Signature>, public_keys: &Vec<PublicKey>) -> Self { pub fn from_list(
proof: Proof,
signatures: &Vec<Signature>,
public_keys: &Vec<PublicKey>,
) -> Self {
assert_eq!(signatures.len(), public_keys.len()); assert_eq!(signatures.len(), public_keys.len());
let signatures_and_public_keys = signatures let signatures_and_public_keys = signatures

View File

@ -106,7 +106,7 @@ class KeycardWallet:
public_only = True, public_only = True,
keypath = path keypath = path
) )
# TODO (marvin) clean this up
public_key = public_key.public_key public_key = public_key.public_key
public_key = VerifyingKey.from_string(public_key[1:], curve=SECP256k1) public_key = VerifyingKey.from_string(public_key[1:], curve=SECP256k1)
public_key = public_key.to_string("compressed")[1:] public_key = public_key.to_string("compressed")[1:]
@ -117,11 +117,12 @@ class KeycardWallet:
print(f"Error getting public key: {e}") print(f"Error getting public key: {e}")
return None return None
def sign_message_for_path(self, message: bytes = b"DefaultMessageTestDefaultMessage", path: str = "m/44'/60'/0'/0/0") -> bytes | None: def sign_message_for_path(self, message: bytes = b"DefaultMessageTestDefaultMessage", path: str = "m/44'/60'/0'/0/0") -> bytes | None:
try: try:
if not self.card.is_secure_channel_open or not self.card.is_pin_verified: if not self.card.is_secure_channel_open or not self.card.is_pin_verified:
return None return None
signature = self.card.sign_with_path( signature = self.card.sign_with_path(
digest = message, digest = message,
path = path, path = path,

View File

@ -72,7 +72,7 @@ pub unsafe extern "C" fn wallet_ffi_transfer_public(
let transfer = NativeTokenTransfer(&wallet); let transfer = NativeTokenTransfer(&wallet);
match block_on(transfer.send_public_transfer(from_id, to_id, amount)) { match block_on(transfer.send_public_transfer(from_id, to_id, amount, &None, &None)) {
Ok(tx_hash) => { Ok(tx_hash) => {
let tx_hash = CString::new(tx_hash.to_string()) let tx_hash = CString::new(tx_hash.to_string())
.map_or(ptr::null_mut(), std::ffi::CString::into_raw); .map_or(ptr::null_mut(), std::ffi::CString::into_raw);
@ -566,7 +566,7 @@ pub unsafe extern "C" fn wallet_ffi_register_public_account(
let transfer = NativeTokenTransfer(&wallet); let transfer = NativeTokenTransfer(&wallet);
match block_on(transfer.register_account(account_id)) { match block_on(transfer.register_account(account_id, &None, &None)) {
Ok(tx_hash) => { Ok(tx_hash) => {
let tx_hash = CString::new(tx_hash.to_string()) let tx_hash = CString::new(tx_hash.to_string())
.map_or(ptr::null_mut(), std::ffi::CString::into_raw); .map_or(ptr::null_mut(), std::ffi::CString::into_raw);

View File

@ -40,3 +40,4 @@ async-stream.workspace = true
indicatif = { version = "0.18.3", features = ["improved_unicode"] } indicatif = { version = "0.18.3", features = ["improved_unicode"] }
optfield = "0.4.0" optfield = "0.4.0"
url.workspace = true url.workspace = true
keycard_wallet.workspace = true

View File

@ -32,12 +32,15 @@ pub enum AccountSubcommand {
short, short,
long, long,
conflicts_with = "account_label", conflicts_with = "account_label",
required_unless_present = "account_label"
)] )]
account_id: Option<String>, account_id: Option<String>,
/// Account label (alternative to --account-id). /// Account label (alternative to --account-id).
#[arg(long, conflicts_with = "account_id")] #[arg(long, conflicts_with = "account_id")]
account_label: Option<String>, account_label: Option<String>,
#[arg(long, conflicts_with = "account_id", conflicts_with = "account_id")]
pin: Option<String>,
#[arg(long, conflicts_with = "account_id", conflicts_with = "account_id")]
key_path: Option<String>,
}, },
/// Produce new public or private account. /// Produce new public or private account.
#[command(subcommand)] #[command(subcommand)]
@ -191,12 +194,16 @@ impl WalletSubcommand for AccountSubcommand {
keys, keys,
account_id, account_id,
account_label, account_label,
pin,
key_path,
} => { } => {
let resolved = resolve_id_or_label( let resolved = resolve_id_or_label(
account_id, account_id,
account_label, account_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&pin,
&key_path,
)?; )?;
let (account_id_str, addr_kind) = parse_addr_with_privacy_prefix(&resolved)?; let (account_id_str, addr_kind) = parse_addr_with_privacy_prefix(&resolved)?;
@ -407,6 +414,8 @@ impl WalletSubcommand for AccountSubcommand {
account_label, account_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let (account_id_str, _) = parse_addr_with_privacy_prefix(&resolved)?; let (account_id_str, _) = parse_addr_with_privacy_prefix(&resolved)?;

View File

@ -1,10 +1,11 @@
use anyhow::Result; use anyhow::Result;
use clap::Subcommand; use clap::Subcommand;
use keycard_wallet::{KeycardWallet, python_path};
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::{ use crate::{
WalletCore, WalletCore,
cli::{SubcommandReturnValue, WalletSubcommand, keycard_wallet::KeycardWallet, python_path}, cli::{SubcommandReturnValue, WalletSubcommand},
}; };
/// Represents generic chain CLI subcommand. /// Represents generic chain CLI subcommand.

View File

@ -27,9 +27,7 @@ pub mod account;
pub mod chain; pub mod chain;
pub mod config; pub mod config;
pub mod keycard; pub mod keycard;
pub mod keycard_wallet;
pub mod programs; pub mod programs;
pub mod python_path;
pub(crate) trait WalletSubcommand { pub(crate) trait WalletSubcommand {
async fn handle_subcommand(self, wallet_core: &mut WalletCore) async fn handle_subcommand(self, wallet_core: &mut WalletCore)

View File

@ -51,7 +51,7 @@ pub enum AmmProgramAgnosticSubcommand {
#[arg(long)] #[arg(long)]
balance_a: u128, balance_a: u128,
#[arg(long)] #[arg(long)]
balance_b: u128, balance_b: u128,
}, },
/// Swap specifying exact input amount. /// Swap specifying exact input amount.
/// ///
@ -216,18 +216,24 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
user_holding_a_label, user_holding_a_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let user_holding_b = resolve_id_or_label( let user_holding_b = resolve_id_or_label(
user_holding_b, user_holding_b,
user_holding_b_label, user_holding_b_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let user_holding_lp = resolve_id_or_label( let user_holding_lp = resolve_id_or_label(
user_holding_lp, user_holding_lp,
user_holding_lp_label, user_holding_lp_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let (user_holding_a, user_holding_a_privacy) = let (user_holding_a, user_holding_a_privacy) =
parse_addr_with_privacy_prefix(&user_holding_a)?; parse_addr_with_privacy_prefix(&user_holding_a)?;
@ -282,12 +288,16 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
user_holding_a_label, user_holding_a_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let user_holding_b = resolve_id_or_label( let user_holding_b = resolve_id_or_label(
user_holding_b, user_holding_b,
user_holding_b_label, user_holding_b_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let (user_holding_a, user_holding_a_privacy) = let (user_holding_a, user_holding_a_privacy) =
parse_addr_with_privacy_prefix(&user_holding_a)?; parse_addr_with_privacy_prefix(&user_holding_a)?;
@ -368,18 +378,24 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
user_holding_a_label, user_holding_a_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let user_holding_b = resolve_id_or_label( let user_holding_b = resolve_id_or_label(
user_holding_b, user_holding_b,
user_holding_b_label, user_holding_b_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let user_holding_lp = resolve_id_or_label( let user_holding_lp = resolve_id_or_label(
user_holding_lp, user_holding_lp,
user_holding_lp_label, user_holding_lp_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let (user_holding_a, user_holding_a_privacy) = let (user_holding_a, user_holding_a_privacy) =
parse_addr_with_privacy_prefix(&user_holding_a)?; parse_addr_with_privacy_prefix(&user_holding_a)?;
@ -437,18 +453,24 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
user_holding_a_label, user_holding_a_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let user_holding_b = resolve_id_or_label( let user_holding_b = resolve_id_or_label(
user_holding_b, user_holding_b,
user_holding_b_label, user_holding_b_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let user_holding_lp = resolve_id_or_label( let user_holding_lp = resolve_id_or_label(
user_holding_lp, user_holding_lp,
user_holding_lp_label, user_holding_lp_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let (user_holding_a, user_holding_a_privacy) = let (user_holding_a, user_holding_a_privacy) =
parse_addr_with_privacy_prefix(&user_holding_a)?; parse_addr_with_privacy_prefix(&user_holding_a)?;

View File

@ -1,12 +1,13 @@
use anyhow::Result; use anyhow::Result;
use clap::Subcommand; use clap::Subcommand;
use common::transaction::NSSATransaction; use common::transaction::NSSATransaction;
use keycard_wallet::KeycardWallet;
use nssa::AccountId; use nssa::AccountId;
use crate::{ use crate::{
AccDecodeData::Decode, AccDecodeData::Decode,
WalletCore, WalletCore,
cli::{SubcommandReturnValue, WalletSubcommand, keycard_wallet::KeycardWallet}, cli::{SubcommandReturnValue, WalletSubcommand},
helperfunctions::{ helperfunctions::{
AccountPrivacyKind, parse_addr_with_privacy_prefix, resolve_account_label, AccountPrivacyKind, parse_addr_with_privacy_prefix, resolve_account_label,
resolve_id_or_label, resolve_id_or_label,
@ -85,16 +86,15 @@ impl WalletSubcommand for AuthTransferSubcommand {
pin, pin,
key_path, key_path,
} => { } => {
let resolved = if pin.is_none() { // TODO: I'm not sure if the string is correct...
resolve_id_or_label( let resolved = resolve_id_or_label(
account_id, account_id,
account_label, account_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
)? &pin,
} else { &key_path
String::default() )?;
};
let (account_id, addr_privacy) = if pin.is_none() { let (account_id, addr_privacy) = if pin.is_none() {
parse_addr_with_privacy_prefix(&resolved)? parse_addr_with_privacy_prefix(&resolved)?
@ -104,10 +104,14 @@ impl WalletSubcommand for AuthTransferSubcommand {
match addr_privacy { match addr_privacy {
AccountPrivacyKind::Public => { AccountPrivacyKind::Public => {
// TODO: crucial (Marvin)
let account_id = if pin.is_none() { let account_id = if pin.is_none() {
account_id.parse()? account_id.parse()?
} else { } else {
KeycardWallet::get_account_id_for_path_with_connect(&pin.as_ref().expect("TODO"), &key_path.as_ref().expect("TODO")) KeycardWallet::get_account_id_for_path_with_connect(
&pin.as_ref().expect("TODO"),
&key_path.as_ref().expect("TODO"),
)
}; };
let tx_hash = NativeTokenTransfer(wallet_core) let tx_hash = NativeTokenTransfer(wallet_core)
@ -159,18 +163,15 @@ impl WalletSubcommand for AuthTransferSubcommand {
pin, pin,
key_path, key_path,
} => { } => {
let from = if pin.is_none() { let from = resolve_id_or_label(
resolve_id_or_label( from,
from, from_label,
from_label, &wallet_core.storage.labels,
&wallet_core.storage.labels, &wallet_core.storage.user_data,
&wallet_core.storage.user_data, &pin,
)? &key_path,
} else { )?;
KeycardWallet::get_account_id_for_path_with_connect(&pin.as_ref().expect("TODO"), &key_path.as_ref().expect("TODO")).to_string()
};
let to = match (to, to_label) { let to = match (to, to_label) {
(v, None) => v, (v, None) => v,
(None, Some(label)) => Some(resolve_account_label( (None, Some(label)) => Some(resolve_account_label(
@ -202,7 +203,13 @@ impl WalletSubcommand for AuthTransferSubcommand {
match (from_privacy, to_privacy) { match (from_privacy, to_privacy) {
(AccountPrivacyKind::Public, AccountPrivacyKind::Public) => { (AccountPrivacyKind::Public, AccountPrivacyKind::Public) => {
NativeTokenTransferProgramSubcommand::Public { from, to, amount, pin, key_path } NativeTokenTransferProgramSubcommand::Public {
from,
to,
amount,
pin,
key_path,
}
} }
(AccountPrivacyKind::Private, AccountPrivacyKind::Private) => { (AccountPrivacyKind::Private, AccountPrivacyKind::Private) => {
NativeTokenTransferProgramSubcommand::Private( NativeTokenTransferProgramSubcommand::Private(
@ -255,7 +262,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
to_vpk, to_vpk,
amount, amount,
pin, pin,
key_path key_path,
}, },
) )
} }
@ -474,7 +481,13 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
wallet_core: &mut WalletCore, wallet_core: &mut WalletCore,
) -> Result<SubcommandReturnValue> { ) -> Result<SubcommandReturnValue> {
match self { match self {
Self::ShieldedOwned { from, to, amount , pin: _, key_path: _} => { Self::ShieldedOwned {
from,
to,
amount,
pin: _,
key_path: _,
} => {
let from: AccountId = from.parse().unwrap(); let from: AccountId = from.parse().unwrap();
let to: AccountId = to.parse().unwrap(); let to: AccountId = to.parse().unwrap();
@ -505,7 +518,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
to_vpk, to_vpk,
amount, amount,
pin: _, pin: _,
key_path: _ key_path: _,
} => { } => {
let from: AccountId = from.parse().unwrap(); let from: AccountId = from.parse().unwrap();
@ -571,8 +584,13 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommand {
Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }) Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash })
} }
Self::Public { from, to, amount, pin, key_path } => { Self::Public {
from,
to,
amount,
pin,
key_path,
} => {
let from: AccountId = from.parse().unwrap(); let from: AccountId = from.parse().unwrap();
let to: AccountId = to.parse().unwrap(); let to: AccountId = to.parse().unwrap();

View File

@ -26,6 +26,10 @@ pub enum PinataProgramAgnosticSubcommand {
/// To account label (alternative to --to). /// To account label (alternative to --to).
#[arg(long, conflicts_with = "to")] #[arg(long, conflicts_with = "to")]
to_label: Option<String>, to_label: Option<String>,
#[arg(long, conflicts_with = "to", conflicts_with = "to_label")]
pin: Option<String>,
#[arg(long, conflicts_with = "to", conflicts_with = "to_label")]
key_path: Option<String>,
}, },
} }
@ -35,15 +39,19 @@ impl WalletSubcommand for PinataProgramAgnosticSubcommand {
wallet_core: &mut WalletCore, wallet_core: &mut WalletCore,
) -> Result<SubcommandReturnValue> { ) -> Result<SubcommandReturnValue> {
let underlying_subcommand = match self { let underlying_subcommand = match self {
Self::Claim { to, to_label } => { Self::Claim { to, to_label , pin, key_path} => {
let to = resolve_id_or_label( let to = resolve_id_or_label(
to, to,
to_label, to_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&pin,
&key_path,
)?; )?;
let (to, to_addr_privacy) = parse_addr_with_privacy_prefix(&to)?; let (to, to_addr_privacy) = parse_addr_with_privacy_prefix(&to)?;
// TODO: (Marvin) does privacy get marked correctly?
match to_addr_privacy { match to_addr_privacy {
AccountPrivacyKind::Public => { AccountPrivacyKind::Public => {
PinataProgramSubcommand::Public(PinataProgramSubcommandPublic::Claim { PinataProgramSubcommand::Public(PinataProgramSubcommandPublic::Claim {

View File

@ -76,6 +76,10 @@ pub enum TokenProgramAgnosticSubcommand {
/// amount - amount of balance to move. /// amount - amount of balance to move.
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
#[arg(long, conflicts_with = "from", conflicts_with = "from_label")]
from_pin: Option<String>,
#[arg(long, conflicts_with = "from", conflicts_with = "from_label")]
from_key_path: Option<String>,
}, },
/// Burn tokens on `holder`, modify `definition`. /// Burn tokens on `holder`, modify `definition`.
/// ///
@ -107,6 +111,10 @@ pub enum TokenProgramAgnosticSubcommand {
/// amount - amount of balance to burn. /// amount - amount of balance to burn.
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
#[arg(long, conflicts_with = "holder", conflicts_with = "holder_label")]
holder_pin: Option<String>,
#[arg(long, conflicts_with = "holder", conflicts_with = "holder_label")]
holder_key_path: Option<String>,
}, },
/// Mint tokens on `holder`, modify `definition`. /// Mint tokens on `holder`, modify `definition`.
/// ///
@ -142,6 +150,10 @@ pub enum TokenProgramAgnosticSubcommand {
/// amount - amount of balance to mint. /// amount - amount of balance to mint.
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
#[arg(long, conflicts_with = "holder", conflicts_with = "holder_label")]
holder_pin: Option<String>,
#[arg(long, conflicts_with = "holder", conflicts_with = "holder_label")]
holder_key_path: Option<String>,
}, },
} }
@ -164,12 +176,16 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
definition_account_label, definition_account_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let supply_account_id = resolve_id_or_label( let supply_account_id = resolve_id_or_label(
supply_account_id, supply_account_id,
supply_account_label, supply_account_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let (definition_account_id, definition_addr_privacy) = let (definition_account_id, definition_addr_privacy) =
parse_addr_with_privacy_prefix(&definition_account_id)?; parse_addr_with_privacy_prefix(&definition_account_id)?;
@ -229,12 +245,16 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
to_npk, to_npk,
to_vpk, to_vpk,
amount, amount,
from_pin,
from_key_path
} => { } => {
let from = resolve_id_or_label( let from = resolve_id_or_label(
from, from,
from_label, from_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&from_pin,
&from_key_path,
)?; )?;
let to = match (to, to_label) { let to = match (to, to_label) {
(v, None) => v, (v, None) => v,
@ -264,7 +284,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
(Some(to), None, None) => { (Some(to), None, None) => {
let (from, from_privacy) = parse_addr_with_privacy_prefix(&from)?; let (from, from_privacy) = parse_addr_with_privacy_prefix(&from)?;
let (to, to_privacy) = parse_addr_with_privacy_prefix(&to)?; let (to, to_privacy) = parse_addr_with_privacy_prefix(&to)?;
// TODO: (Marvin) return here
match (from_privacy, to_privacy) { match (from_privacy, to_privacy) {
(AccountPrivacyKind::Public, AccountPrivacyKind::Public) => { (AccountPrivacyKind::Public, AccountPrivacyKind::Public) => {
TokenProgramSubcommand::Public( TokenProgramSubcommand::Public(
@ -336,24 +356,30 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
holder, holder,
holder_label, holder_label,
amount, amount,
holder_pin,
holder_key_path,
} => { } => {
let definition = resolve_id_or_label( let definition = resolve_id_or_label(
definition, definition,
definition_label, definition_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let holder = resolve_id_or_label( let holder = resolve_id_or_label(
holder, holder,
holder_label, holder_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&holder_pin,
&holder_key_path,
)?; )?;
let underlying_subcommand = { let underlying_subcommand = {
let (definition, definition_privacy) = let (definition, definition_privacy) =
parse_addr_with_privacy_prefix(&definition)?; parse_addr_with_privacy_prefix(&definition)?;
let (holder, holder_privacy) = parse_addr_with_privacy_prefix(&holder)?; let (holder, holder_privacy) = parse_addr_with_privacy_prefix(&holder)?;
// TODO Marvin return here
match (definition_privacy, holder_privacy) { match (definition_privacy, holder_privacy) {
(AccountPrivacyKind::Public, AccountPrivacyKind::Public) => { (AccountPrivacyKind::Public, AccountPrivacyKind::Public) => {
TokenProgramSubcommand::Public( TokenProgramSubcommand::Public(
@ -404,24 +430,26 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
holder_npk, holder_npk,
holder_vpk, holder_vpk,
amount, amount,
holder_pin,
holder_key_path
} => { } => {
let definition = resolve_id_or_label( let definition = resolve_id_or_label(
definition, definition,
definition_label, definition_label,
&wallet_core.storage.labels, &wallet_core.storage.labels,
&wallet_core.storage.user_data, &wallet_core.storage.user_data,
&None,
&None,
)?; )?;
let holder = match (holder, holder_label) { let holder = Some(resolve_id_or_label(
(v, None) => v, holder.clone(),
(None, Some(label)) => Some(resolve_account_label( holder_label.clone(),
&label, &wallet_core.storage.labels,
&wallet_core.storage.labels, &wallet_core.storage.user_data,
&wallet_core.storage.user_data, &holder_pin,
)?), &holder_key_path,
(Some(_), Some(_)) => { )?);
anyhow::bail!("Provide only one of --holder or --holder-label") //TODO return here (Marvin)
}
};
let underlying_subcommand = match (holder, holder_npk, holder_vpk) { let underlying_subcommand = match (holder, holder_npk, holder_vpk) {
(None, None, None) => { (None, None, None) => {
anyhow::bail!( anyhow::bail!(

View File

@ -8,6 +8,8 @@ use nssa_core::account::Nonce;
use rand::{RngCore as _, rngs::OsRng}; use rand::{RngCore as _, rngs::OsRng};
use serde::Serialize; use serde::Serialize;
use testnet_initial_state::{PrivateAccountPrivateInitialData, PublicAccountPrivateInitialData}; use testnet_initial_state::{PrivateAccountPrivateInitialData, PublicAccountPrivateInitialData};
use keycard_wallet::KeycardWallet;
use crate::{ use crate::{
HOME_DIR_ENV_VAR, HOME_DIR_ENV_VAR,
@ -60,10 +62,13 @@ pub fn resolve_id_or_label(
label: Option<String>, label: Option<String>,
labels: &HashMap<String, Label>, labels: &HashMap<String, Label>,
user_data: &NSSAUserData, user_data: &NSSAUserData,
pin: &Option<String>,
key_path: &Option<String>,
) -> Result<String> { ) -> Result<String> {
match (id, label) { match (id, label, pin) {
(Some(id), None) => Ok(id), (Some(id), None, None) => Ok(id),
(None, Some(label)) => resolve_account_label(&label, labels, user_data), (None, Some(label), None) => resolve_account_label(&label, labels, user_data),
(None, None, Some(pin)) => Ok(KeycardWallet::get_account_id_for_path_with_connect(pin, key_path.as_ref().expect("TODO")).to_string()),
_ => anyhow::bail!("provide exactly one of account id or account label"), _ => anyhow::bail!("provide exactly one of account id or account label"),
} }
} }

View File

@ -16,13 +16,14 @@ use chain_storage::WalletChainStore;
use common::{HashType, transaction::NSSATransaction}; use common::{HashType, transaction::NSSATransaction};
use config::WalletConfig; use config::WalletConfig;
use key_protocol::key_management::key_tree::{chain_index::ChainIndex, traits::KeyNode as _}; use key_protocol::key_management::key_tree::{chain_index::ChainIndex, traits::KeyNode as _};
use keycard_wallet::KeycardWallet;
use log::info; use log::info;
use nssa::{ use nssa::{
PublicKey, Account, AccountId, PrivacyPreservingTransaction, PublicKey, Signature,
Account, AccountId, PrivacyPreservingTransaction, Signature, privacy_preserving_transaction::{ privacy_preserving_transaction::{
circuit::{ProgramWithDependencies, Proof}, circuit::{ProgramWithDependencies, Proof},
message::EncryptedAccountData, message::EncryptedAccountData,
} },
}; };
use nssa_core::{ use nssa_core::{
Commitment, MembershipProof, SharedSecretKey, account::Nonce, program::InstructionData, Commitment, MembershipProof, SharedSecretKey, account::Nonce, program::InstructionData,
@ -32,7 +33,9 @@ use sequencer_service_rpc::{RpcClient as _, SequencerClient, SequencerClientBuil
use tokio::io::AsyncWriteExt as _; use tokio::io::AsyncWriteExt as _;
use crate::{ use crate::{
cli::keycard_wallet::KeycardWallet, config::{PersistentStorage, WalletConfigOverrides}, helperfunctions::produce_data_for_storage, poller::TxPoller config::{PersistentStorage, WalletConfigOverrides},
helperfunctions::produce_data_for_storage,
poller::TxPoller,
}; };
pub mod chain_storage; pub mod chain_storage;
@ -587,23 +590,28 @@ impl WalletCore {
message: &nssa::privacy_preserving_transaction::Message, message: &nssa::privacy_preserving_transaction::Message,
proof: Proof, proof: Proof,
pin: &String, pin: &String,
key_paths: &[String] key_paths: &[String],
) -> Result<nssa::privacy_preserving_transaction::witness_set::WitnessSet, ExecutionFailureKind> ) -> Result<nssa::privacy_preserving_transaction::witness_set::WitnessSet, ExecutionFailureKind>
{ {
let mut signatures = Vec::<Signature>::new(); let mut signatures = Vec::<Signature>::new();
let mut public_keys = Vec::<PublicKey>::new(); let mut public_keys = Vec::<PublicKey>::new();
let message_bytes: [u8; 32] = { let message_bytes: [u8; 32] = {
let v = message.to_bytes(); let v = message.to_bytes();
let mut bytes = [0_u8; 32]; let mut bytes = [0_u8; 32];
let len = v.len().min(32); let len = v.len().min(32);
bytes[..len].copy_from_slice(&v[..len]); bytes[..len].copy_from_slice(&v[..len]);
bytes bytes
}; };
for path in key_paths.iter() { for path in key_paths.iter() {
public_keys.push( KeycardWallet::get_public_key_for_path_with_connect(&pin, &path)); public_keys.push(KeycardWallet::get_public_key_for_path_with_connect(
signatures.push( KeycardWallet::sign_message_for_path_with_connection(&pin, &path, &message_bytes).expect("Expect a valid signature")); &pin, &path,
));
signatures.push(
KeycardWallet::sign_message_for_path_with_connect(&pin, &path, &message_bytes)
.expect("Expect a valid signature"),
);
} }
Ok( Ok(

View File

@ -1,17 +1,14 @@
use common::{HashType, transaction::NSSATransaction}; use common::{HashType, transaction::NSSATransaction};
use keycard_wallet::KeycardWallet;
use nssa::{ use nssa::{
AccountId, PublicTransaction, AccountId, PublicTransaction,
program::Program, program::Program,
public_transaction::{Message, WitnessSet}, public_transaction::{Message, WitnessSet},
}; };
use pyo3::Python;
use sequencer_service_rpc::RpcClient as _; use sequencer_service_rpc::RpcClient as _;
use super::NativeTokenTransfer; use super::NativeTokenTransfer;
use crate::{ use crate::{ExecutionFailureKind, WalletCore};
ExecutionFailureKind, WalletCore,
cli::{keycard_wallet::KeycardWallet, python_path},
};
impl NativeTokenTransfer<'_> { impl NativeTokenTransfer<'_> {
pub async fn send_public_transfer( pub async fn send_public_transfer(
@ -59,21 +56,22 @@ impl NativeTokenTransfer<'_> {
Message::try_new(program_id, account_ids, nonces, balance_to_move).unwrap(); Message::try_new(program_id, account_ids, nonces, balance_to_move).unwrap();
let witness_set = if pin.is_none() { let witness_set = if pin.is_none() {
WalletCore::sign_public_message(self.0, &message, &sign_ids) WalletCore::sign_public_message(self.0, &message, &sign_ids)
.expect("Expect a valid signature") .expect("Expect a valid signature")
} else { } else {
// TODO: maybe the issue? (Marvin)
let message_bytes: [u8; 32] = { let pub_key = KeycardWallet::get_public_key_for_path_with_connect(
let v = message.to_bytes(); &pin.as_ref().expect("TODO"),
let mut bytes = [0_u8; 32]; &key_path.as_ref().expect("TODO"),
let len = v.len().min(32); );
bytes[..len].copy_from_slice(&v[..len]); let signature = KeycardWallet::sign_message_for_path_with_connect(
bytes &pin.as_ref().expect("TODO"),
}; &key_path.as_ref().expect("TODO"),
let pub_key = KeycardWallet::get_public_key_for_path_with_connect(&pin.as_ref().expect("TODO"), &key_path.as_ref().expect("TODO")); &message.hash_message(),
let signature = KeycardWallet::sign_message_for_path_with_connection(&pin.as_ref().expect("TODO"), &key_path.as_ref().expect("TODO"), &message_bytes).expect("Expect valid signature"); )
WitnessSet::from_list(&[signature], &[pub_key]) .expect("Expect valid signature");
}; WitnessSet::from_list(&[signature], &[pub_key])
};
let tx = PublicTransaction::new(message, witness_set); let tx = PublicTransaction::new(message, witness_set);
@ -102,16 +100,8 @@ impl NativeTokenTransfer<'_> {
let instruction: u128 = 0; let instruction: u128 = 0;
let account_ids = vec![from]; let account_ids = vec![from];
let program_id = Program::authenticated_transfer_program().id(); let program_id = Program::authenticated_transfer_program().id();
let message = Message::try_new(program_id, account_ids, nonces, instruction).unwrap(); let message = Message::try_new(program_id, account_ids, nonces, instruction).expect("Expect a valid Message");
// (Marvin): This really needs to be the ChainIndex
// But, I cannot change that due to Default Accounts.
// Instead, I had introduced a "NEW" sign...which I do not see...
// Correction: I did not need a specific function. Rather, I use `from_list` to combine
// public and signatures together for a WitnessSet.
// The tricky part is that I NEED to do everything with chain-codes... This won't look nice,
// but is feasible.
let witness_set = if pin.is_none() { let witness_set = if pin.is_none() {
let signing_key = self.0.storage.user_data.get_pub_account_signing_key(from); let signing_key = self.0.storage.user_data.get_pub_account_signing_key(from);
@ -121,42 +111,18 @@ impl NativeTokenTransfer<'_> {
WitnessSet::for_message(&message, &[signing_key]) WitnessSet::for_message(&message, &[signing_key])
} else { } else {
let witness_set = Python::with_gil(|py| { let pub_key = KeycardWallet::get_public_key_for_path_with_connect(
python_path::add_python_path(py).expect("keycard_wallet.py not found"); pin.as_ref().expect("TODO"),
key_path.as_ref().expect("TODO"),
);
let wallet = KeycardWallet::new(py).expect("Expect keycard wallet"); let signature = KeycardWallet::sign_message_for_path_with_connect(
pin.as_ref().as_ref().expect("TODO"),
let is_connected = wallet key_path.as_ref().expect("TODO"),
.setup_communication(py, pin.as_ref().expect("TODO")) &message.hash_message(),
.expect("Expect a Boolean."); )
.expect("Expect a valid Signature.");
if is_connected { WitnessSet::from_list(&[signature], &[pub_key])
println!("\u{2705} Keycard is now connected to wallet.");
} else {
println!("\u{274c} Keycard is not connected to wallet.");
}
// TODO: maybe the issue? (Marvin)
let message: [u8; 32] = {
let v = message.to_bytes();
let mut bytes = [0_u8; 32];
let len = v.len().min(32);
bytes[..len].copy_from_slice(&v[..len]);
bytes
};
let pub_key = wallet
.get_public_key_for_path(py, key_path.as_ref().expect("TODO"))
.expect("Expect a valid public key");
let signature = wallet
.sign_message_for_path(py, key_path.as_ref().expect("TODO"), &message)
.expect("TODO");
let _ = wallet.disconnect(py);
WitnessSet::from_list(&[signature], &[pub_key])
});
witness_set
}; };
let tx = PublicTransaction::new(message, witness_set); let tx = PublicTransaction::new(message, witness_set);

View File

@ -10,7 +10,7 @@ python3 -m pip install pyaes
cd python cd python
git clone --branch lee-schnorr --single-branch https://github.com/bitgamma/keycard-py.git # git clone --branch lee-schnorr --single-branch https://github.com/bitgamma/keycard-py.git
cd keycard-py cd keycard-py
python3 -m venv venv python3 -m venv venv
source venv/bin/activate source venv/bin/activate