mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-07 15:53:14 +00:00
fix: cli full refactor
This commit is contained in:
parent
b3e4b9a8ca
commit
5840f9b779
@ -8,3 +8,5 @@ pub mod transaction;
|
|||||||
//TODO: Compile only for tests
|
//TODO: Compile only for tests
|
||||||
pub mod test_utils;
|
pub mod test_utils;
|
||||||
pub type HashType = [u8; 32];
|
pub type HashType = [u8; 32];
|
||||||
|
|
||||||
|
pub const PINATA_BASE58: &str = "EfQhKQAkX2FJiwNii2WFQsGndjvF1Mzd7RuVe7QdPLw7";
|
||||||
|
|||||||
@ -43,11 +43,11 @@ pub const TIME_TO_WAIT_FOR_BLOCK_SECONDS: u64 = 12;
|
|||||||
pub const NSSA_PROGRAM_FOR_TEST_DATA_CHANGER: &[u8] = include_bytes!("data_changer.bin");
|
pub const NSSA_PROGRAM_FOR_TEST_DATA_CHANGER: &[u8] = include_bytes!("data_changer.bin");
|
||||||
|
|
||||||
fn make_public_account_input_from_str(addr: &str) -> String {
|
fn make_public_account_input_from_str(addr: &str) -> String {
|
||||||
format!("Public/{addr:?}")
|
format!("Public/{addr}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_private_account_input_from_str(addr: &str) -> String {
|
fn make_private_account_input_from_str(addr: &str) -> String {
|
||||||
format!("Private/{addr:?}")
|
format!("Private/{addr}")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
@ -92,7 +92,7 @@ pub async fn post_test(residual: (ServerHandle, JoinHandle<Result<()>>, TempDir)
|
|||||||
seq_http_server_handle.stop(true).await;
|
seq_http_server_handle.stop(true).await;
|
||||||
|
|
||||||
let wallet_home = wallet::helperfunctions::get_home().unwrap();
|
let wallet_home = wallet::helperfunctions::get_home().unwrap();
|
||||||
let persistent_data_home = wallet_home.join("curr_accounts.json");
|
let persistent_data_home = wallet_home.join("storage.json");
|
||||||
|
|
||||||
//Removing persistent accounts after run to not affect other executions
|
//Removing persistent accounts after run to not affect other executions
|
||||||
//Not necessary an error, if fails as there is tests for failure scenario
|
//Not necessary an error, if fails as there is tests for failure scenario
|
||||||
@ -163,3 +163,20 @@ async fn verify_commitment_is_in_state(
|
|||||||
Ok(Some(_))
|
Ok(Some(_))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{make_private_account_input_from_str, make_public_account_input_from_str};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn correct_addr_from_prefix() {
|
||||||
|
let addr1 = "cafecafe";
|
||||||
|
let addr2 = "deadbeaf";
|
||||||
|
|
||||||
|
let addr1_pub = make_public_account_input_from_str(addr1);
|
||||||
|
let addr2_priv = make_private_account_input_from_str(addr2);
|
||||||
|
|
||||||
|
assert_eq!(addr1_pub, "Public/cafecafe".to_string());
|
||||||
|
assert_eq!(addr2_priv, "Private/deadbeaf".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,25 +1,21 @@
|
|||||||
use std::{collections::HashMap, path::PathBuf, pin::Pin, time::Duration};
|
use std::{collections::HashMap, path::PathBuf, pin::Pin, time::Duration};
|
||||||
|
|
||||||
use common::sequencer_client::SequencerClient;
|
use common::{PINATA_BASE58, sequencer_client::SequencerClient};
|
||||||
use log::info;
|
use log::info;
|
||||||
use nssa::{Address, ProgramDeploymentTransaction, program::Program};
|
use nssa::{Address, ProgramDeploymentTransaction, program::Program};
|
||||||
use nssa_core::{NullifierPublicKey, encryption::shared_key_derivation::Secp256k1Point};
|
use nssa_core::{NullifierPublicKey, encryption::shared_key_derivation::Secp256k1Point};
|
||||||
use wallet::{
|
use wallet::{
|
||||||
Command, SubcommandReturnValue, WalletCore,
|
Command, SubcommandReturnValue, WalletCore,
|
||||||
cli::{
|
cli::{
|
||||||
account::{AccountSubcommand, FetchSubcommand, NewSubcommand},
|
account::{AccountSubcommand, NewSubcommand},
|
||||||
native_token_transfer_program::AuthTransferSubcommand,
|
native_token_transfer_program::AuthTransferSubcommand,
|
||||||
pinata_program::{
|
pinata_program::PinataProgramAgnosticSubcommand,
|
||||||
PinataProgramSubcommand, PinataProgramSubcommandPrivate, PinataProgramSubcommandPublic,
|
|
||||||
},
|
|
||||||
token_program::TokenProgramAgnosticSubcommand,
|
token_program::TokenProgramAgnosticSubcommand,
|
||||||
},
|
},
|
||||||
config::PersistentAccountData,
|
config::{PersistentAccountData, PersistentStorage},
|
||||||
helperfunctions::{fetch_config, fetch_persistent_accounts},
|
helperfunctions::{fetch_config, fetch_persistent_storage},
|
||||||
};
|
};
|
||||||
|
|
||||||
use sequencer_core::sequencer_store::PINATA_BASE58;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ACC_RECEIVER, ACC_RECEIVER_PRIVATE, ACC_SENDER, ACC_SENDER_PRIVATE,
|
ACC_RECEIVER, ACC_RECEIVER_PRIVATE, ACC_SENDER, ACC_SENDER_PRIVATE,
|
||||||
NSSA_PROGRAM_FOR_TEST_DATA_CHANGER, TIME_TO_WAIT_FOR_BLOCK_SECONDS,
|
NSSA_PROGRAM_FOR_TEST_DATA_CHANGER, TIME_TO_WAIT_FOR_BLOCK_SECONDS,
|
||||||
@ -83,7 +79,10 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
|
|
||||||
wallet::execute_subcommand(command).await.unwrap();
|
wallet::execute_subcommand(command).await.unwrap();
|
||||||
|
|
||||||
let persistent_accounts = fetch_persistent_accounts().await.unwrap();
|
let PersistentStorage {
|
||||||
|
accounts: persistent_accounts,
|
||||||
|
last_synced_block: _,
|
||||||
|
} = fetch_persistent_storage().await.unwrap();
|
||||||
|
|
||||||
let mut new_persistent_account_addr = String::new();
|
let mut new_persistent_account_addr = String::new();
|
||||||
|
|
||||||
@ -290,7 +289,10 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let persistent_accounts = fetch_persistent_accounts().await.unwrap();
|
let PersistentStorage {
|
||||||
|
accounts: persistent_accounts,
|
||||||
|
last_synced_block: _,
|
||||||
|
} = fetch_persistent_storage().await.unwrap();
|
||||||
|
|
||||||
let mut new_persistent_accounts_addr = Vec::new();
|
let mut new_persistent_accounts_addr = Vec::new();
|
||||||
|
|
||||||
@ -668,7 +670,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
amount: 7,
|
amount: 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
|
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash: _ } =
|
||||||
wallet::execute_subcommand(Command::Token(subcommand))
|
wallet::execute_subcommand(Command::Token(subcommand))
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -679,11 +681,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
info!("Waiting for next block creation");
|
info!("Waiting for next block creation");
|
||||||
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;
|
||||||
|
|
||||||
let command = Command::Account(AccountSubcommand::Fetch(FetchSubcommand::PrivateAccount {
|
let command = Command::Account(AccountSubcommand::SyncPrivate {});
|
||||||
tx_hash,
|
|
||||||
acc_addr: recipient_addr.to_string(),
|
|
||||||
output_id: 1,
|
|
||||||
}));
|
|
||||||
|
|
||||||
wallet::execute_subcommand(command).await.unwrap();
|
wallet::execute_subcommand(command).await.unwrap();
|
||||||
|
|
||||||
@ -1096,11 +1094,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
|
|
||||||
let tx = fetch_privacy_preserving_tx(&seq_client, tx_hash.clone()).await;
|
let tx = fetch_privacy_preserving_tx(&seq_client, tx_hash.clone()).await;
|
||||||
|
|
||||||
let command = Command::Account(AccountSubcommand::Fetch(FetchSubcommand::PrivateAccount {
|
let command = Command::Account(AccountSubcommand::SyncPrivate {});
|
||||||
tx_hash,
|
|
||||||
acc_addr: to_addr.to_string(),
|
|
||||||
output_id: 1,
|
|
||||||
}));
|
|
||||||
wallet::execute_subcommand(command).await.unwrap();
|
wallet::execute_subcommand(command).await.unwrap();
|
||||||
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config)
|
let wallet_storage = WalletCore::start_from_config_update_chain(wallet_config)
|
||||||
.await
|
.await
|
||||||
@ -1335,13 +1329,10 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
let pinata_addr = PINATA_BASE58;
|
let pinata_addr = PINATA_BASE58;
|
||||||
let pinata_prize = 150;
|
let pinata_prize = 150;
|
||||||
let solution = 989106;
|
let solution = 989106;
|
||||||
let command = Command::Pinata(PinataProgramSubcommand::Public(
|
let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim {
|
||||||
PinataProgramSubcommandPublic::Claim {
|
to_addr: make_public_account_input_from_str(ACC_SENDER),
|
||||||
pinata_addr: pinata_addr.to_string(),
|
solution,
|
||||||
winner_addr: ACC_SENDER.to_string(),
|
});
|
||||||
solution,
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
let wallet_config = fetch_config().await.unwrap();
|
let wallet_config = fetch_config().await.unwrap();
|
||||||
|
|
||||||
@ -1427,14 +1418,18 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
#[nssa_integration_test]
|
#[nssa_integration_test]
|
||||||
pub async fn test_authenticated_transfer_initialize_function() {
|
pub async fn test_authenticated_transfer_initialize_function() {
|
||||||
info!("test initialize account for authenticated transfer");
|
info!("test initialize account for authenticated transfer");
|
||||||
let command = Command::AuthenticatedTransferInitializePublicAccount {};
|
let command = Command::Account(AccountSubcommand::New(NewSubcommand::Public {}));
|
||||||
|
|
||||||
let SubcommandReturnValue::RegisterAccount { addr } =
|
let SubcommandReturnValue::RegisterAccount { addr } =
|
||||||
wallet::execute_subcommand(command).await.unwrap()
|
wallet::execute_subcommand(command).await.unwrap()
|
||||||
else {
|
else {
|
||||||
panic!("Error creating account");
|
panic!("Error creating account");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let command = Command::AuthTransfer(AuthTransferSubcommand::Init {
|
||||||
|
addr: addr.to_string(),
|
||||||
|
});
|
||||||
|
wallet::execute_subcommand(command).await.unwrap();
|
||||||
|
|
||||||
info!("Checking correct execution");
|
info!("Checking correct execution");
|
||||||
let wallet_config = fetch_config().await.unwrap();
|
let wallet_config = fetch_config().await.unwrap();
|
||||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||||
@ -1463,13 +1458,10 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
let pinata_prize = 150;
|
let pinata_prize = 150;
|
||||||
let solution = 989106;
|
let solution = 989106;
|
||||||
|
|
||||||
let command = Command::Pinata(PinataProgramSubcommand::Private(
|
let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim {
|
||||||
PinataProgramSubcommandPrivate::ClaimPrivateOwned {
|
to_addr: make_private_account_input_from_str(ACC_SENDER_PRIVATE),
|
||||||
pinata_addr: pinata_addr.to_string(),
|
solution,
|
||||||
winner_addr: ACC_SENDER_PRIVATE.to_string(),
|
});
|
||||||
solution,
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
let wallet_config = fetch_config().await.unwrap();
|
let wallet_config = fetch_config().await.unwrap();
|
||||||
|
|
||||||
@ -1481,7 +1473,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.balance;
|
.balance;
|
||||||
|
|
||||||
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash } =
|
let SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash: _ } =
|
||||||
wallet::execute_subcommand(command).await.unwrap()
|
wallet::execute_subcommand(command).await.unwrap()
|
||||||
else {
|
else {
|
||||||
panic!("invalid subcommand return value");
|
panic!("invalid subcommand return value");
|
||||||
@ -1497,11 +1489,7 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.balance;
|
.balance;
|
||||||
|
|
||||||
let command = Command::Account(AccountSubcommand::Fetch(FetchSubcommand::PrivateAccount {
|
let command = Command::Account(AccountSubcommand::SyncPrivate {});
|
||||||
tx_hash: tx_hash.clone(),
|
|
||||||
acc_addr: ACC_SENDER_PRIVATE.to_string(),
|
|
||||||
output_id: 0,
|
|
||||||
}));
|
|
||||||
wallet::execute_subcommand(command).await.unwrap();
|
wallet::execute_subcommand(command).await.unwrap();
|
||||||
|
|
||||||
let wallet_config = fetch_config().await.unwrap();
|
let wallet_config = fetch_config().await.unwrap();
|
||||||
@ -1538,13 +1526,10 @@ pub fn prepare_function_map() -> HashMap<String, TestFunction> {
|
|||||||
panic!("invalid subcommand return value");
|
panic!("invalid subcommand return value");
|
||||||
};
|
};
|
||||||
|
|
||||||
let command = Command::Pinata(PinataProgramSubcommand::Private(
|
let command = Command::Pinata(PinataProgramAgnosticSubcommand::Claim {
|
||||||
PinataProgramSubcommandPrivate::ClaimPrivateOwned {
|
to_addr: make_private_account_input_from_str(&winner_addr.to_string()),
|
||||||
pinata_addr: pinata_addr.to_string(),
|
solution,
|
||||||
winner_addr: winner_addr.to_string(),
|
});
|
||||||
solution,
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
let wallet_config = fetch_config().await.unwrap();
|
let wallet_config = fetch_config().await.unwrap();
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,6 @@ use crate::config::AccountInitialData;
|
|||||||
|
|
||||||
pub mod block_store;
|
pub mod block_store;
|
||||||
|
|
||||||
pub const PINATA_BASE58: &str = "EfQhKQAkX2FJiwNii2WFQsGndjvF1Mzd7RuVe7QdPLw7";
|
|
||||||
|
|
||||||
pub struct SequecerChainStore {
|
pub struct SequecerChainStore {
|
||||||
pub state: nssa::V02State,
|
pub state: nssa::V02State,
|
||||||
pub block_store: SequecerBlockStore,
|
pub block_store: SequecerBlockStore,
|
||||||
@ -35,6 +33,8 @@ impl SequecerChainStore {
|
|||||||
|
|
||||||
#[cfg(feature = "testnet")]
|
#[cfg(feature = "testnet")]
|
||||||
let state = {
|
let state = {
|
||||||
|
use common::PINATA_BASE58;
|
||||||
|
|
||||||
let mut this =
|
let mut this =
|
||||||
nssa::V02State::new_with_genesis_accounts(&init_accs, initial_commitments);
|
nssa::V02State::new_with_genesis_accounts(&init_accs, initial_commitments);
|
||||||
this.add_pinata_program(PINATA_BASE58.parse().unwrap());
|
this.add_pinata_program(PINATA_BASE58.parse().unwrap());
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use base58::ToBase58;
|
use base58::ToBase58;
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
use common::transaction::NSSATransaction;
|
|
||||||
use nssa::{Address, program::Program};
|
use nssa::{Address, program::Program};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -9,6 +8,7 @@ use crate::{
|
|||||||
SubcommandReturnValue, WalletCore,
|
SubcommandReturnValue, WalletCore,
|
||||||
cli::WalletSubcommand,
|
cli::WalletSubcommand,
|
||||||
helperfunctions::{AddressPrivacyKind, HumanReadableAccount, parse_addr_with_privacy_prefix},
|
helperfunctions::{AddressPrivacyKind, HumanReadableAccount, parse_addr_with_privacy_prefix},
|
||||||
|
parse_block_range,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TOKEN_DEFINITION_TYPE: u8 = 0;
|
const TOKEN_DEFINITION_TYPE: u8 = 0;
|
||||||
@ -76,9 +76,6 @@ pub enum AccountSubcommand {
|
|||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
addr: String,
|
addr: String,
|
||||||
},
|
},
|
||||||
///Fetch
|
|
||||||
#[command(subcommand)]
|
|
||||||
Fetch(FetchSubcommand),
|
|
||||||
///New
|
///New
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
New(NewSubcommand),
|
New(NewSubcommand),
|
||||||
@ -86,28 +83,6 @@ pub enum AccountSubcommand {
|
|||||||
SyncPrivate {},
|
SyncPrivate {},
|
||||||
}
|
}
|
||||||
|
|
||||||
///Represents generic getter CLI subcommand
|
|
||||||
#[derive(Subcommand, Debug, Clone)]
|
|
||||||
pub enum FetchSubcommand {
|
|
||||||
///Fetch transaction by `hash`
|
|
||||||
Tx {
|
|
||||||
#[arg(short, long)]
|
|
||||||
tx_hash: String,
|
|
||||||
},
|
|
||||||
///Claim account `acc_addr` generated in transaction `tx_hash`, using secret `sh_secret` at ciphertext id `ciph_id`
|
|
||||||
PrivateAccount {
|
|
||||||
///tx_hash - valid 32 byte hex string
|
|
||||||
#[arg(long)]
|
|
||||||
tx_hash: String,
|
|
||||||
///acc_addr - valid 32 byte hex string
|
|
||||||
#[arg(long)]
|
|
||||||
acc_addr: String,
|
|
||||||
///output_id - id of the output in the transaction
|
|
||||||
#[arg(long)]
|
|
||||||
output_id: usize,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
///Represents generic register CLI subcommand
|
///Represents generic register CLI subcommand
|
||||||
#[derive(Subcommand, Debug, Clone)]
|
#[derive(Subcommand, Debug, Clone)]
|
||||||
pub enum NewSubcommand {
|
pub enum NewSubcommand {
|
||||||
@ -117,74 +92,6 @@ pub enum NewSubcommand {
|
|||||||
Private {},
|
Private {},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WalletSubcommand for FetchSubcommand {
|
|
||||||
async fn handle_subcommand(
|
|
||||||
self,
|
|
||||||
wallet_core: &mut WalletCore,
|
|
||||||
) -> Result<SubcommandReturnValue> {
|
|
||||||
match self {
|
|
||||||
FetchSubcommand::Tx { tx_hash } => {
|
|
||||||
let tx_obj = wallet_core
|
|
||||||
.sequencer_client
|
|
||||||
.get_transaction_by_hash(tx_hash)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
println!("Transaction object {tx_obj:#?}");
|
|
||||||
|
|
||||||
Ok(SubcommandReturnValue::Empty)
|
|
||||||
}
|
|
||||||
FetchSubcommand::PrivateAccount {
|
|
||||||
tx_hash,
|
|
||||||
acc_addr,
|
|
||||||
output_id: ciph_id,
|
|
||||||
} => {
|
|
||||||
let acc_addr: Address = acc_addr.parse().unwrap();
|
|
||||||
|
|
||||||
let account_key_chain = wallet_core
|
|
||||||
.storage
|
|
||||||
.user_data
|
|
||||||
.user_private_accounts
|
|
||||||
.get(&acc_addr);
|
|
||||||
|
|
||||||
let Some((account_key_chain, _)) = account_key_chain else {
|
|
||||||
anyhow::bail!("Account not found");
|
|
||||||
};
|
|
||||||
|
|
||||||
let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?;
|
|
||||||
|
|
||||||
if let NSSATransaction::PrivacyPreserving(tx) = transfer_tx {
|
|
||||||
let to_ebc = tx.message.encrypted_private_post_states[ciph_id].clone();
|
|
||||||
let to_comm = tx.message.new_commitments[ciph_id].clone();
|
|
||||||
let shared_secret =
|
|
||||||
account_key_chain.calculate_shared_secret_receiver(to_ebc.epk);
|
|
||||||
|
|
||||||
let res_acc_to = nssa_core::EncryptionScheme::decrypt(
|
|
||||||
&to_ebc.ciphertext,
|
|
||||||
&shared_secret,
|
|
||||||
&to_comm,
|
|
||||||
ciph_id as u32,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("RES acc to {res_acc_to:#?}");
|
|
||||||
|
|
||||||
println!("Transaction data is {:?}", tx.message);
|
|
||||||
|
|
||||||
wallet_core
|
|
||||||
.storage
|
|
||||||
.insert_private_account_data(acc_addr, res_acc_to);
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
|
||||||
|
|
||||||
Ok(SubcommandReturnValue::Empty)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WalletSubcommand for NewSubcommand {
|
impl WalletSubcommand for NewSubcommand {
|
||||||
async fn handle_subcommand(
|
async fn handle_subcommand(
|
||||||
self,
|
self,
|
||||||
@ -196,7 +103,7 @@ impl WalletSubcommand for NewSubcommand {
|
|||||||
|
|
||||||
println!("Generated new account with addr {addr}");
|
println!("Generated new account with addr {addr}");
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -221,7 +128,7 @@ impl WalletSubcommand for NewSubcommand {
|
|||||||
hex::encode(key.incoming_viewing_public_key.to_bytes())
|
hex::encode(key.incoming_viewing_public_key.to_bytes())
|
||||||
);
|
);
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -287,6 +194,8 @@ impl WalletSubcommand for AccountSubcommand {
|
|||||||
AccountSubcommand::Get { raw, addr } => {
|
AccountSubcommand::Get { raw, addr } => {
|
||||||
let (addr, addr_kind) = parse_addr_with_privacy_prefix(&addr)?;
|
let (addr, addr_kind) = parse_addr_with_privacy_prefix(&addr)?;
|
||||||
|
|
||||||
|
let addr = addr.parse()?;
|
||||||
|
|
||||||
let account = match addr_kind {
|
let account = match addr_kind {
|
||||||
AddressPrivacyKind::Public => wallet_core.get_account_public(addr).await?,
|
AddressPrivacyKind::Public => wallet_core.get_account_public(addr).await?,
|
||||||
AddressPrivacyKind::Private => wallet_core
|
AddressPrivacyKind::Private => wallet_core
|
||||||
@ -333,14 +242,39 @@ impl WalletSubcommand for AccountSubcommand {
|
|||||||
|
|
||||||
Ok(SubcommandReturnValue::Empty)
|
Ok(SubcommandReturnValue::Empty)
|
||||||
}
|
}
|
||||||
AccountSubcommand::Fetch(fetch_subcommand) => {
|
|
||||||
fetch_subcommand.handle_subcommand(wallet_core).await
|
|
||||||
}
|
|
||||||
AccountSubcommand::New(new_subcommand) => {
|
AccountSubcommand::New(new_subcommand) => {
|
||||||
new_subcommand.handle_subcommand(wallet_core).await
|
new_subcommand.handle_subcommand(wallet_core).await
|
||||||
}
|
}
|
||||||
AccountSubcommand::SyncPrivate {} => {
|
AccountSubcommand::SyncPrivate {} => {
|
||||||
todo!();
|
let last_synced_block = wallet_core.last_synced_block;
|
||||||
|
let curr_last_block = wallet_core
|
||||||
|
.sequencer_client
|
||||||
|
.get_last_block()
|
||||||
|
.await?
|
||||||
|
.last_block;
|
||||||
|
|
||||||
|
if !wallet_core
|
||||||
|
.storage
|
||||||
|
.user_data
|
||||||
|
.user_private_accounts
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
|
parse_block_range(
|
||||||
|
last_synced_block,
|
||||||
|
curr_last_block,
|
||||||
|
wallet_core.sequencer_client.clone(),
|
||||||
|
wallet_core,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
wallet_core.last_synced_block = curr_last_block;
|
||||||
|
|
||||||
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
|
println!("Stored persistent data at {path:#?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(SubcommandReturnValue::SyncedToBlock(curr_last_block))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,11 +60,13 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
|||||||
|
|
||||||
println!("Transaction data is {transfer_tx:?}");
|
println!("Transaction data is {transfer_tx:?}");
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
}
|
}
|
||||||
AddressPrivacyKind::Private => {
|
AddressPrivacyKind::Private => {
|
||||||
|
let addr = addr.parse()?;
|
||||||
|
|
||||||
let (res, [secret]) = wallet_core
|
let (res, [secret]) = wallet_core
|
||||||
.register_account_under_authenticated_transfers_programs_private(addr)
|
.register_account_under_authenticated_transfers_programs_private(addr)
|
||||||
.await?;
|
.await?;
|
||||||
@ -85,7 +87,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
}
|
}
|
||||||
@ -120,33 +122,29 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
|||||||
|
|
||||||
match (from_privacy, to_privacy) {
|
match (from_privacy, to_privacy) {
|
||||||
(AddressPrivacyKind::Public, AddressPrivacyKind::Public) => {
|
(AddressPrivacyKind::Public, AddressPrivacyKind::Public) => {
|
||||||
NativeTokenTransferProgramSubcommand::Public {
|
NativeTokenTransferProgramSubcommand::Public { from, to, amount }
|
||||||
from: from.to_string(),
|
|
||||||
to: to.to_string(),
|
|
||||||
amount,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
(AddressPrivacyKind::Private, AddressPrivacyKind::Private) => {
|
(AddressPrivacyKind::Private, AddressPrivacyKind::Private) => {
|
||||||
NativeTokenTransferProgramSubcommand::Private(
|
NativeTokenTransferProgramSubcommand::Private(
|
||||||
NativeTokenTransferProgramSubcommandPrivate::PrivateOwned {
|
NativeTokenTransferProgramSubcommandPrivate::PrivateOwned {
|
||||||
from: from.to_string(),
|
from,
|
||||||
to: to.to_string(),
|
to,
|
||||||
amount,
|
amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(AddressPrivacyKind::Private, AddressPrivacyKind::Public) => {
|
(AddressPrivacyKind::Private, AddressPrivacyKind::Public) => {
|
||||||
NativeTokenTransferProgramSubcommand::Deshielded {
|
NativeTokenTransferProgramSubcommand::Deshielded {
|
||||||
from: from.to_string(),
|
from,
|
||||||
to: to.to_string(),
|
to,
|
||||||
amount,
|
amount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(AddressPrivacyKind::Public, AddressPrivacyKind::Private) => {
|
(AddressPrivacyKind::Public, AddressPrivacyKind::Private) => {
|
||||||
NativeTokenTransferProgramSubcommand::Shielded(
|
NativeTokenTransferProgramSubcommand::Shielded(
|
||||||
NativeTokenTransferProgramSubcommandShielded::ShieldedOwned {
|
NativeTokenTransferProgramSubcommandShielded::ShieldedOwned {
|
||||||
from: from.to_string(),
|
from,
|
||||||
to: to.to_string(),
|
to,
|
||||||
amount,
|
amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -160,7 +158,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
|||||||
AddressPrivacyKind::Private => {
|
AddressPrivacyKind::Private => {
|
||||||
NativeTokenTransferProgramSubcommand::Private(
|
NativeTokenTransferProgramSubcommand::Private(
|
||||||
NativeTokenTransferProgramSubcommandPrivate::PrivateForeign {
|
NativeTokenTransferProgramSubcommandPrivate::PrivateForeign {
|
||||||
from: from.to_string(),
|
from,
|
||||||
to_npk,
|
to_npk,
|
||||||
to_ipk,
|
to_ipk,
|
||||||
amount,
|
amount,
|
||||||
@ -170,7 +168,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
|
|||||||
AddressPrivacyKind::Public => {
|
AddressPrivacyKind::Public => {
|
||||||
NativeTokenTransferProgramSubcommand::Shielded(
|
NativeTokenTransferProgramSubcommand::Shielded(
|
||||||
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
|
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
|
||||||
from: from.to_string(),
|
from,
|
||||||
to_npk,
|
to_npk,
|
||||||
to_ipk,
|
to_ipk,
|
||||||
amount,
|
amount,
|
||||||
@ -340,7 +338,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -384,7 +382,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -434,7 +432,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -467,7 +465,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
|
|||||||
|
|
||||||
let tx_hash = res.tx_hash;
|
let tx_hash = res.tx_hash;
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -513,7 +511,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommand {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -533,7 +531,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommand {
|
|||||||
|
|
||||||
println!("Transaction data is {transfer_tx:?}");
|
println!("Transaction data is {transfer_tx:?}");
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,59 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
use common::transaction::NSSATransaction;
|
use common::{PINATA_BASE58, transaction::NSSATransaction};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::{SubcommandReturnValue, WalletCore, cli::WalletSubcommand};
|
use crate::{
|
||||||
|
SubcommandReturnValue, WalletCore,
|
||||||
|
cli::WalletSubcommand,
|
||||||
|
helperfunctions::{AddressPrivacyKind, parse_addr_with_privacy_prefix},
|
||||||
|
};
|
||||||
|
|
||||||
|
///Represents generic CLI subcommand for a wallet working with pinata program
|
||||||
|
#[derive(Subcommand, Debug, Clone)]
|
||||||
|
pub enum PinataProgramAgnosticSubcommand {
|
||||||
|
///Claim
|
||||||
|
Claim {
|
||||||
|
///to_addr - valid 32 byte base58 string
|
||||||
|
#[arg(long)]
|
||||||
|
to_addr: String,
|
||||||
|
///solution - solution to pinata challenge
|
||||||
|
#[arg(long)]
|
||||||
|
solution: u128,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WalletSubcommand for PinataProgramAgnosticSubcommand {
|
||||||
|
async fn handle_subcommand(
|
||||||
|
self,
|
||||||
|
wallet_core: &mut WalletCore,
|
||||||
|
) -> Result<SubcommandReturnValue> {
|
||||||
|
let underlying_subcommand = match self {
|
||||||
|
PinataProgramAgnosticSubcommand::Claim { to_addr, solution } => {
|
||||||
|
let (to_addr, to_addr_privacy) = parse_addr_with_privacy_prefix(&to_addr)?;
|
||||||
|
|
||||||
|
match to_addr_privacy {
|
||||||
|
AddressPrivacyKind::Public => {
|
||||||
|
PinataProgramSubcommand::Public(PinataProgramSubcommandPublic::Claim {
|
||||||
|
pinata_addr: PINATA_BASE58.to_string(),
|
||||||
|
winner_addr: to_addr,
|
||||||
|
solution,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
AddressPrivacyKind::Private => PinataProgramSubcommand::Private(
|
||||||
|
PinataProgramSubcommandPrivate::ClaimPrivateOwned {
|
||||||
|
pinata_addr: PINATA_BASE58.to_string(),
|
||||||
|
winner_addr: to_addr,
|
||||||
|
solution,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
underlying_subcommand.handle_subcommand(wallet_core).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///Represents generic CLI subcommand for a wallet working with pinata program
|
///Represents generic CLI subcommand for a wallet working with pinata program
|
||||||
#[derive(Subcommand, Debug, Clone)]
|
#[derive(Subcommand, Debug, Clone)]
|
||||||
@ -131,7 +181,7 @@ impl WalletSubcommand for PinataProgramSubcommandPrivate {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
|
|||||||
@ -64,8 +64,8 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
|||||||
(AddressPrivacyKind::Public, AddressPrivacyKind::Public) => {
|
(AddressPrivacyKind::Public, AddressPrivacyKind::Public) => {
|
||||||
TokenProgramSubcommand::Public(
|
TokenProgramSubcommand::Public(
|
||||||
TokenProgramSubcommandPublic::CreateNewToken {
|
TokenProgramSubcommandPublic::CreateNewToken {
|
||||||
definition_addr: definition_addr.to_string(),
|
definition_addr,
|
||||||
supply_addr: supply_addr.to_string(),
|
supply_addr,
|
||||||
name,
|
name,
|
||||||
total_supply,
|
total_supply,
|
||||||
},
|
},
|
||||||
@ -74,18 +74,20 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
|||||||
(AddressPrivacyKind::Public, AddressPrivacyKind::Private) => {
|
(AddressPrivacyKind::Public, AddressPrivacyKind::Private) => {
|
||||||
TokenProgramSubcommand::Private(
|
TokenProgramSubcommand::Private(
|
||||||
TokenProgramSubcommandPrivate::CreateNewTokenPrivateOwned {
|
TokenProgramSubcommandPrivate::CreateNewTokenPrivateOwned {
|
||||||
definition_addr: definition_addr.to_string(),
|
definition_addr,
|
||||||
supply_addr: supply_addr.to_string(),
|
supply_addr,
|
||||||
name,
|
name,
|
||||||
total_supply,
|
total_supply,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(AddressPrivacyKind::Private, AddressPrivacyKind::Private) => {
|
(AddressPrivacyKind::Private, AddressPrivacyKind::Private) => {
|
||||||
todo!();
|
//ToDo: maybe implement this one. It is not immediately clear why definition should be private.
|
||||||
|
anyhow::bail!("Unavailable privacy pairing")
|
||||||
}
|
}
|
||||||
(AddressPrivacyKind::Private, AddressPrivacyKind::Public) => {
|
(AddressPrivacyKind::Private, AddressPrivacyKind::Public) => {
|
||||||
todo!();
|
//Probably valid. If definition is not public, but supply is it is very suspicious.
|
||||||
|
anyhow::bail!("Unavailable privacy pairing")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,8 +122,8 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
|||||||
(AddressPrivacyKind::Public, AddressPrivacyKind::Public) => {
|
(AddressPrivacyKind::Public, AddressPrivacyKind::Public) => {
|
||||||
TokenProgramSubcommand::Public(
|
TokenProgramSubcommand::Public(
|
||||||
TokenProgramSubcommandPublic::TransferToken {
|
TokenProgramSubcommandPublic::TransferToken {
|
||||||
sender_addr: from.to_string(),
|
sender_addr: from,
|
||||||
recipient_addr: to.to_string(),
|
recipient_addr: to,
|
||||||
balance_to_move: amount,
|
balance_to_move: amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -129,8 +131,8 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
|||||||
(AddressPrivacyKind::Private, AddressPrivacyKind::Private) => {
|
(AddressPrivacyKind::Private, AddressPrivacyKind::Private) => {
|
||||||
TokenProgramSubcommand::Private(
|
TokenProgramSubcommand::Private(
|
||||||
TokenProgramSubcommandPrivate::TransferTokenPrivateOwned {
|
TokenProgramSubcommandPrivate::TransferTokenPrivateOwned {
|
||||||
sender_addr: from.to_string(),
|
sender_addr: from,
|
||||||
recipient_addr: to.to_string(),
|
recipient_addr: to,
|
||||||
balance_to_move: amount,
|
balance_to_move: amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -138,8 +140,8 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
|||||||
(AddressPrivacyKind::Private, AddressPrivacyKind::Public) => {
|
(AddressPrivacyKind::Private, AddressPrivacyKind::Public) => {
|
||||||
TokenProgramSubcommand::Deshielded(
|
TokenProgramSubcommand::Deshielded(
|
||||||
TokenProgramSubcommandDeshielded::TransferTokenDeshielded {
|
TokenProgramSubcommandDeshielded::TransferTokenDeshielded {
|
||||||
sender_addr: from.to_string(),
|
sender_addr: from,
|
||||||
recipient_addr: to.to_string(),
|
recipient_addr: to,
|
||||||
balance_to_move: amount,
|
balance_to_move: amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -147,8 +149,8 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
|||||||
(AddressPrivacyKind::Public, AddressPrivacyKind::Private) => {
|
(AddressPrivacyKind::Public, AddressPrivacyKind::Private) => {
|
||||||
TokenProgramSubcommand::Shielded(
|
TokenProgramSubcommand::Shielded(
|
||||||
TokenProgramSubcommandShielded::TransferTokenShieldedOwned {
|
TokenProgramSubcommandShielded::TransferTokenShieldedOwned {
|
||||||
sender_addr: from.to_string(),
|
sender_addr: from,
|
||||||
recipient_addr: to.to_string(),
|
recipient_addr: to,
|
||||||
balance_to_move: amount,
|
balance_to_move: amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -161,7 +163,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
|||||||
match from_privacy {
|
match from_privacy {
|
||||||
AddressPrivacyKind::Private => TokenProgramSubcommand::Private(
|
AddressPrivacyKind::Private => TokenProgramSubcommand::Private(
|
||||||
TokenProgramSubcommandPrivate::TransferTokenPrivateForeign {
|
TokenProgramSubcommandPrivate::TransferTokenPrivateForeign {
|
||||||
sender_addr: from.to_string(),
|
sender_addr: from,
|
||||||
recipient_npk: to_npk,
|
recipient_npk: to_npk,
|
||||||
recipient_ipk: to_ipk,
|
recipient_ipk: to_ipk,
|
||||||
balance_to_move: amount,
|
balance_to_move: amount,
|
||||||
@ -169,7 +171,7 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
|
|||||||
),
|
),
|
||||||
AddressPrivacyKind::Public => TokenProgramSubcommand::Shielded(
|
AddressPrivacyKind::Public => TokenProgramSubcommand::Shielded(
|
||||||
TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
|
TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
|
||||||
sender_addr: from.to_string(),
|
sender_addr: from,
|
||||||
recipient_npk: to_npk,
|
recipient_npk: to_npk,
|
||||||
recipient_ipk: to_ipk,
|
recipient_ipk: to_ipk,
|
||||||
balance_to_move: amount,
|
balance_to_move: amount,
|
||||||
@ -401,7 +403,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -458,7 +460,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -508,7 +510,7 @@ impl WalletSubcommand for TokenProgramSubcommandPrivate {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -556,7 +558,7 @@ impl WalletSubcommand for TokenProgramSubcommandDeshielded {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -611,7 +613,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
|
|||||||
println!("Transaction data is {:?}", tx.message);
|
println!("Transaction data is {:?}", tx.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
@ -665,7 +667,7 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
let path = wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
println!("Stored persistent accounts at {path:#?}");
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,12 @@ pub enum PersistentAccountData {
|
|||||||
Private(PersistentAccountDataPrivate),
|
Private(PersistentAccountDataPrivate),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct PersistentStorage {
|
||||||
|
pub accounts: Vec<PersistentAccountData>,
|
||||||
|
pub last_synced_block: u64,
|
||||||
|
}
|
||||||
|
|
||||||
impl InitialAccountData {
|
impl InitialAccountData {
|
||||||
pub fn address(&self) -> nssa::Address {
|
pub fn address(&self) -> nssa::Address {
|
||||||
match &self {
|
match &self {
|
||||||
|
|||||||
@ -12,8 +12,7 @@ use serde::Serialize;
|
|||||||
use crate::{
|
use crate::{
|
||||||
HOME_DIR_ENV_VAR,
|
HOME_DIR_ENV_VAR,
|
||||||
config::{
|
config::{
|
||||||
PersistentAccountData, PersistentAccountDataPrivate, PersistentAccountDataPublic,
|
PersistentAccountDataPrivate, PersistentAccountDataPublic, PersistentStorage, WalletConfig,
|
||||||
WalletConfig,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,21 +29,24 @@ pub async fn fetch_config() -> Result<WalletConfig> {
|
|||||||
Ok(serde_json::from_slice(&config_contents)?)
|
Ok(serde_json::from_slice(&config_contents)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch list of accounts stored at `NSSA_WALLET_HOME_DIR/curr_accounts.json`
|
/// Fetch data stored at `NSSA_WALLET_HOME_DIR/storage.json`
|
||||||
///
|
///
|
||||||
/// If file not present, it is considered as empty list of persistent accounts
|
/// If file not present, it is considered as empty list of persistent accounts
|
||||||
pub async fn fetch_persistent_accounts() -> Result<Vec<PersistentAccountData>> {
|
pub async fn fetch_persistent_storage() -> Result<PersistentStorage> {
|
||||||
let home = get_home()?;
|
let home = get_home()?;
|
||||||
let accs_path = home.join("curr_accounts.json");
|
let accs_path = home.join("storage.json");
|
||||||
let mut persistent_accounts_content = vec![];
|
let mut storage_content = vec![];
|
||||||
|
|
||||||
match tokio::fs::File::open(accs_path).await {
|
match tokio::fs::File::open(accs_path).await {
|
||||||
Ok(mut file) => {
|
Ok(mut file) => {
|
||||||
file.read_to_end(&mut persistent_accounts_content).await?;
|
file.read_to_end(&mut storage_content).await?;
|
||||||
Ok(serde_json::from_slice(&persistent_accounts_content)?)
|
Ok(serde_json::from_slice(&storage_content)?)
|
||||||
}
|
}
|
||||||
Err(err) => match err.kind() {
|
Err(err) => match err.kind() {
|
||||||
std::io::ErrorKind::NotFound => Ok(vec![]),
|
std::io::ErrorKind::NotFound => Ok(PersistentStorage {
|
||||||
|
accounts: vec![],
|
||||||
|
last_synced_block: 0,
|
||||||
|
}),
|
||||||
_ => {
|
_ => {
|
||||||
anyhow::bail!("IO error {err:#?}");
|
anyhow::bail!("IO error {err:#?}");
|
||||||
}
|
}
|
||||||
@ -52,8 +54,11 @@ pub async fn fetch_persistent_accounts() -> Result<Vec<PersistentAccountData>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produces a list of accounts for storage
|
/// Produces data for storage
|
||||||
pub fn produce_data_for_storage(user_data: &NSSAUserData) -> Vec<PersistentAccountData> {
|
pub fn produce_data_for_storage(
|
||||||
|
user_data: &NSSAUserData,
|
||||||
|
last_synced_block: u64,
|
||||||
|
) -> PersistentStorage {
|
||||||
let mut vec_for_storage = vec![];
|
let mut vec_for_storage = vec![];
|
||||||
|
|
||||||
for (addr, key) in &user_data.pub_account_signing_keys {
|
for (addr, key) in &user_data.pub_account_signing_keys {
|
||||||
@ -77,7 +82,10 @@ pub fn produce_data_for_storage(user_data: &NSSAUserData) -> Vec<PersistentAccou
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec_for_storage
|
PersistentStorage {
|
||||||
|
accounts: vec_for_storage,
|
||||||
|
last_synced_block,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn produce_random_nonces(size: usize) -> Vec<Nonce> {
|
pub(crate) fn produce_random_nonces(size: usize) -> Vec<Nonce> {
|
||||||
|
|||||||
@ -20,15 +20,18 @@ use clap::{Parser, Subcommand};
|
|||||||
use nssa_core::{Commitment, MembershipProof};
|
use nssa_core::{Commitment, MembershipProof};
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
use crate::cli::{
|
use crate::{
|
||||||
WalletSubcommand, account::AccountSubcommand, chain::ChainSubcommand,
|
cli::{
|
||||||
native_token_transfer_program::AuthTransferSubcommand, pinata_program::PinataProgramSubcommand,
|
WalletSubcommand, account::AccountSubcommand, chain::ChainSubcommand,
|
||||||
token_program::TokenProgramAgnosticSubcommand,
|
native_token_transfer_program::AuthTransferSubcommand,
|
||||||
|
pinata_program::PinataProgramAgnosticSubcommand,
|
||||||
|
token_program::TokenProgramAgnosticSubcommand,
|
||||||
|
},
|
||||||
|
config::PersistentStorage,
|
||||||
|
helperfunctions::fetch_persistent_storage,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
helperfunctions::{
|
helperfunctions::{fetch_config, get_home, produce_data_for_storage},
|
||||||
fetch_config, fetch_persistent_accounts, get_home, produce_data_for_storage,
|
|
||||||
},
|
|
||||||
poller::TxPoller,
|
poller::TxPoller,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,6 +51,7 @@ pub struct WalletCore {
|
|||||||
pub storage: WalletChainStore,
|
pub storage: WalletChainStore,
|
||||||
pub poller: TxPoller,
|
pub poller: TxPoller,
|
||||||
pub sequencer_client: Arc<SequencerClient>,
|
pub sequencer_client: Arc<SequencerClient>,
|
||||||
|
pub last_synced_block: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WalletCore {
|
impl WalletCore {
|
||||||
@ -57,7 +61,10 @@ impl WalletCore {
|
|||||||
|
|
||||||
let mut storage = WalletChainStore::new(config)?;
|
let mut storage = WalletChainStore::new(config)?;
|
||||||
|
|
||||||
let persistent_accounts = fetch_persistent_accounts().await?;
|
let PersistentStorage {
|
||||||
|
accounts: persistent_accounts,
|
||||||
|
last_synced_block,
|
||||||
|
} = fetch_persistent_storage().await?;
|
||||||
for pers_acc_data in persistent_accounts {
|
for pers_acc_data in persistent_accounts {
|
||||||
storage.insert_account_data(pers_acc_data);
|
storage.insert_account_data(pers_acc_data);
|
||||||
}
|
}
|
||||||
@ -66,23 +73,24 @@ impl WalletCore {
|
|||||||
storage,
|
storage,
|
||||||
poller: tx_poller,
|
poller: tx_poller,
|
||||||
sequencer_client: client.clone(),
|
sequencer_client: client.clone(),
|
||||||
|
last_synced_block,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
///Store persistent accounts at home
|
///Store persistent data at home
|
||||||
pub async fn store_persistent_accounts(&self) -> Result<PathBuf> {
|
pub async fn store_persistent_data(&self) -> Result<PathBuf> {
|
||||||
let home = get_home()?;
|
let home = get_home()?;
|
||||||
let accs_path = home.join("curr_accounts.json");
|
let storage_path = home.join("storage.json");
|
||||||
|
|
||||||
let data = produce_data_for_storage(&self.storage.user_data);
|
let data = produce_data_for_storage(&self.storage.user_data, self.last_synced_block);
|
||||||
let accs = serde_json::to_vec_pretty(&data)?;
|
let storage = serde_json::to_vec_pretty(&data)?;
|
||||||
|
|
||||||
let mut accs_file = tokio::fs::File::create(accs_path.as_path()).await?;
|
let mut storage_file = tokio::fs::File::create(storage_path.as_path()).await?;
|
||||||
accs_file.write_all(&accs).await?;
|
storage_file.write_all(&storage).await?;
|
||||||
|
|
||||||
info!("Stored accounts data at {accs_path:#?}");
|
info!("Stored data at {storage_path:#?}");
|
||||||
|
|
||||||
Ok(accs_path)
|
Ok(storage_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_new_account_public(&mut self) -> Address {
|
pub fn create_new_account_public(&mut self) -> Address {
|
||||||
@ -201,11 +209,10 @@ pub enum Command {
|
|||||||
Account(AccountSubcommand),
|
Account(AccountSubcommand),
|
||||||
///Pinata command
|
///Pinata command
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
Pinata(PinataProgramSubcommand),
|
Pinata(PinataProgramAgnosticSubcommand),
|
||||||
///Token command
|
///Token command
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
Token(TokenProgramAgnosticSubcommand),
|
Token(TokenProgramAgnosticSubcommand),
|
||||||
AuthenticatedTransferInitializePublicAccount {},
|
|
||||||
// Check the wallet can connect to the node and builtin local programs
|
// Check the wallet can connect to the node and builtin local programs
|
||||||
// match the remote versions
|
// match the remote versions
|
||||||
CheckHealth {},
|
CheckHealth {},
|
||||||
@ -229,6 +236,7 @@ pub enum SubcommandReturnValue {
|
|||||||
RegisterAccount { addr: nssa::Address },
|
RegisterAccount { addr: nssa::Address },
|
||||||
Account(nssa::Account),
|
Account(nssa::Account),
|
||||||
Empty,
|
Empty,
|
||||||
|
SyncedToBlock(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValue> {
|
pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValue> {
|
||||||
@ -284,25 +292,6 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
|||||||
|
|
||||||
SubcommandReturnValue::Empty
|
SubcommandReturnValue::Empty
|
||||||
}
|
}
|
||||||
Command::AuthenticatedTransferInitializePublicAccount {} => {
|
|
||||||
let addr = wallet_core.create_new_account_public();
|
|
||||||
|
|
||||||
println!("Generated new account with addr {addr}");
|
|
||||||
|
|
||||||
let path = wallet_core.store_persistent_accounts().await?;
|
|
||||||
|
|
||||||
println!("Stored persistent accounts at {path:#?}");
|
|
||||||
|
|
||||||
let res = wallet_core
|
|
||||||
.register_account_under_authenticated_transfers_programs(addr)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
println!("Results of tx send is {res:#?}");
|
|
||||||
|
|
||||||
let _transfer_tx = wallet_core.poll_native_token_transfer(res.tx_hash).await?;
|
|
||||||
|
|
||||||
SubcommandReturnValue::RegisterAccount { addr }
|
|
||||||
}
|
|
||||||
Command::Token(token_subcommand) => {
|
Command::Token(token_subcommand) => {
|
||||||
token_subcommand.handle_subcommand(&mut wallet_core).await?
|
token_subcommand.handle_subcommand(&mut wallet_core).await?
|
||||||
}
|
}
|
||||||
@ -311,6 +300,80 @@ pub async fn execute_subcommand(command: Command) -> Result<SubcommandReturnValu
|
|||||||
Ok(subcommand_ret)
|
Ok(subcommand_ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn parse_block_range(
|
||||||
|
start: u64,
|
||||||
|
stop: u64,
|
||||||
|
seq_client: Arc<SequencerClient>,
|
||||||
|
wallet_core: &mut WalletCore,
|
||||||
|
) -> Result<()> {
|
||||||
|
for block_id in start..(stop + 1) {
|
||||||
|
let block =
|
||||||
|
borsh::from_slice::<HashableBlockData>(&seq_client.get_block(block_id).await?.block)?;
|
||||||
|
|
||||||
|
for tx in block.transactions {
|
||||||
|
let nssa_tx = NSSATransaction::try_from(&tx)?;
|
||||||
|
|
||||||
|
if let NSSATransaction::PrivacyPreserving(tx) = nssa_tx {
|
||||||
|
let mut affected_accounts = vec![];
|
||||||
|
|
||||||
|
for (acc_addr, (key_chain, _)) in
|
||||||
|
&wallet_core.storage.user_data.user_private_accounts
|
||||||
|
{
|
||||||
|
let view_tag = EncryptedAccountData::compute_view_tag(
|
||||||
|
key_chain.nullifer_public_key.clone(),
|
||||||
|
key_chain.incoming_viewing_public_key.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
for (ciph_id, encrypted_data) in tx
|
||||||
|
.message()
|
||||||
|
.encrypted_private_post_states
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if encrypted_data.view_tag == view_tag {
|
||||||
|
let ciphertext = &encrypted_data.ciphertext;
|
||||||
|
let commitment = &tx.message.new_commitments[ciph_id];
|
||||||
|
let shared_secret = key_chain
|
||||||
|
.calculate_shared_secret_receiver(encrypted_data.epk.clone());
|
||||||
|
|
||||||
|
let res_acc = nssa_core::EncryptionScheme::decrypt(
|
||||||
|
ciphertext,
|
||||||
|
&shared_secret,
|
||||||
|
commitment,
|
||||||
|
ciph_id as u32,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(res_acc) = res_acc {
|
||||||
|
println!(
|
||||||
|
"Received new account for addr {acc_addr:#?} with account object {res_acc:#?}"
|
||||||
|
);
|
||||||
|
|
||||||
|
affected_accounts.push((*acc_addr, res_acc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (affected_addr, new_acc) in affected_accounts {
|
||||||
|
wallet_core
|
||||||
|
.storage
|
||||||
|
.insert_private_account_data(affected_addr, new_acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet_core.last_synced_block = block_id;
|
||||||
|
wallet_core.store_persistent_data().await?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Block at id {block_id} with timestamp {} parsed",
|
||||||
|
block.timestamp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn execute_continious_run() -> Result<()> {
|
pub async fn execute_continious_run() -> Result<()> {
|
||||||
let config = fetch_config().await?;
|
let config = fetch_config().await?;
|
||||||
let seq_client = Arc::new(SequencerClient::new(config.sequencer_addr.clone())?);
|
let seq_client = Arc::new(SequencerClient::new(config.sequencer_addr.clone())?);
|
||||||
@ -320,70 +383,13 @@ pub async fn execute_continious_run() -> Result<()> {
|
|||||||
let mut curr_last_block = latest_block_num;
|
let mut curr_last_block = latest_block_num;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
for block_id in curr_last_block..(latest_block_num + 1) {
|
parse_block_range(
|
||||||
let block = borsh::from_slice::<HashableBlockData>(
|
curr_last_block,
|
||||||
&seq_client.get_block(block_id).await?.block,
|
latest_block_num,
|
||||||
)?;
|
seq_client.clone(),
|
||||||
|
&mut wallet_core,
|
||||||
for tx in block.transactions {
|
)
|
||||||
let nssa_tx = NSSATransaction::try_from(&tx)?;
|
.await?;
|
||||||
|
|
||||||
if let NSSATransaction::PrivacyPreserving(tx) = nssa_tx {
|
|
||||||
let mut affected_accounts = vec![];
|
|
||||||
|
|
||||||
for (acc_addr, (key_chain, _)) in
|
|
||||||
&wallet_core.storage.user_data.user_private_accounts
|
|
||||||
{
|
|
||||||
let view_tag = EncryptedAccountData::compute_view_tag(
|
|
||||||
key_chain.nullifer_public_key.clone(),
|
|
||||||
key_chain.incoming_viewing_public_key.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
for (ciph_id, encrypted_data) in tx
|
|
||||||
.message()
|
|
||||||
.encrypted_private_post_states
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
{
|
|
||||||
if encrypted_data.view_tag == view_tag {
|
|
||||||
let ciphertext = &encrypted_data.ciphertext;
|
|
||||||
let commitment = &tx.message.new_commitments[ciph_id];
|
|
||||||
let shared_secret = key_chain
|
|
||||||
.calculate_shared_secret_receiver(encrypted_data.epk.clone());
|
|
||||||
|
|
||||||
let res_acc = nssa_core::EncryptionScheme::decrypt(
|
|
||||||
ciphertext,
|
|
||||||
&shared_secret,
|
|
||||||
commitment,
|
|
||||||
ciph_id as u32,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(res_acc) = res_acc {
|
|
||||||
println!(
|
|
||||||
"Received new account for addr {acc_addr:#?} with account object {res_acc:#?}"
|
|
||||||
);
|
|
||||||
|
|
||||||
affected_accounts.push((*acc_addr, res_acc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (affected_addr, new_acc) in affected_accounts {
|
|
||||||
wallet_core
|
|
||||||
.storage
|
|
||||||
.insert_private_account_data(affected_addr, new_acc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wallet_core.store_persistent_accounts().await?;
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Block at id {block_id} with timestamp {} parsed",
|
|
||||||
block.timestamp
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
curr_last_block = latest_block_num + 1;
|
curr_last_block = latest_block_num + 1;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user