fix: suggestions fix

This commit is contained in:
Pravdyvy 2025-12-22 04:42:32 +02:00
parent d427d49c65
commit 4f15237446
6 changed files with 240 additions and 242 deletions

View File

@ -36,7 +36,7 @@ impl Message {
program_id: ProgramId,
account_ids: Vec<AccountId>,
nonces: Vec<Nonce>,
instruction_data: Vec<u32>,
instruction_data: InstructionData,
) -> Self {
Self {
program_id,

View File

@ -3,70 +3,15 @@ use base58::ToBase58;
use clap::Subcommand;
use itertools::Itertools as _;
use key_protocol::key_management::key_tree::chain_index::ChainIndex;
use nssa::{Account, AccountId, program::Program};
use nssa::{Account, program::Program};
use serde::Serialize;
use crate::{
WalletCore,
TokenDefinition, TokenHolding, WalletCore,
cli::{SubcommandReturnValue, WalletSubcommand},
helperfunctions::{AccountPrivacyKind, HumanReadableAccount, parse_addr_with_privacy_prefix},
};
const TOKEN_DEFINITION_TYPE: u8 = 0;
const TOKEN_DEFINITION_DATA_SIZE: usize = 23;
const TOKEN_HOLDING_TYPE: u8 = 1;
const TOKEN_HOLDING_DATA_SIZE: usize = 49;
struct TokenDefinition {
#[allow(unused)]
account_type: u8,
name: [u8; 6],
total_supply: u128,
}
pub struct TokenHolding {
#[allow(unused)]
account_type: u8,
pub definition_id: AccountId,
balance: u128,
}
impl TokenDefinition {
fn parse(data: &[u8]) -> Option<Self> {
if data.len() != TOKEN_DEFINITION_DATA_SIZE || data[0] != TOKEN_DEFINITION_TYPE {
None
} else {
let account_type = data[0];
let name = data[1..7].try_into().unwrap();
let total_supply = u128::from_le_bytes(data[7..].try_into().unwrap());
Some(Self {
account_type,
name,
total_supply,
})
}
}
}
impl TokenHolding {
pub fn parse(data: &[u8]) -> Option<Self> {
if data.len() != TOKEN_HOLDING_DATA_SIZE || data[0] != TOKEN_HOLDING_TYPE {
None
} else {
let account_type = data[0];
let definition_id = AccountId::new(data[1..33].try_into().unwrap());
let balance = u128::from_le_bytes(data[33..].try_into().unwrap());
Some(Self {
definition_id,
balance,
account_type,
})
}
}
}
/// Represents generic chain CLI subcommand
#[derive(Subcommand, Debug, Clone)]
pub enum AccountSubcommand {

View File

@ -6,7 +6,7 @@ use crate::{
WalletCore,
cli::{SubcommandReturnValue, WalletSubcommand},
helperfunctions::{AccountPrivacyKind, parse_addr_with_privacy_prefix},
program_facades::amm::AMM,
program_facades::amm::Amm,
};
/// Represents generic CLI subcommand for a wallet working with amm program
@ -32,7 +32,7 @@ pub enum AmmProgramAgnosticSubcommand {
#[arg(long)]
balance_b: u128,
},
/// Swap with variable privacy
/// Swap
///
/// The account associated with swapping token must be owned
///
@ -52,7 +52,7 @@ pub enum AmmProgramAgnosticSubcommand {
#[arg(long)]
token_definition: String,
},
/// Add liquidity with variable privacy
/// Add liquidity
///
/// user_holding_a and user_holding_b must be owned.
///
@ -74,7 +74,7 @@ pub enum AmmProgramAgnosticSubcommand {
#[arg(long)]
max_amount_b: u128,
},
/// Remove liquidity with variable privacy
/// Remove liquidity
///
/// user_holding_lp must be owned.
///
@ -132,8 +132,8 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
AccountPrivacyKind::Public,
AccountPrivacyKind::Public,
) => {
AMM(wallet_core)
.send_new_amm_definition(
Amm(wallet_core)
.send_new_definition(
user_holding_a,
user_holding_b,
user_holding_lp,
@ -146,7 +146,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
}
_ => {
// ToDo: Implement after private multi-chain calls is available
anyhow::bail!("Only public execution allowed for AMM calls");
anyhow::bail!("Only public execution allowed for Amm calls");
}
}
}
@ -167,7 +167,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
match (user_holding_a_privacy, user_holding_b_privacy) {
(AccountPrivacyKind::Public, AccountPrivacyKind::Public) => {
AMM(wallet_core)
Amm(wallet_core)
.send_swap(
user_holding_a,
user_holding_b,
@ -181,7 +181,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
}
_ => {
// ToDo: Implement after private multi-chain calls is available
anyhow::bail!("Only public execution allowed for AMM calls");
anyhow::bail!("Only public execution allowed for Amm calls");
}
}
}
@ -214,8 +214,8 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
AccountPrivacyKind::Public,
AccountPrivacyKind::Public,
) => {
AMM(wallet_core)
.send_add_liq(
Amm(wallet_core)
.send_add_liquidity(
user_holding_a,
user_holding_b,
user_holding_lp,
@ -229,7 +229,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
}
_ => {
// ToDo: Implement after private multi-chain calls is available
anyhow::bail!("Only public execution allowed for AMM calls");
anyhow::bail!("Only public execution allowed for Amm calls");
}
}
}
@ -262,8 +262,8 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
AccountPrivacyKind::Public,
AccountPrivacyKind::Public,
) => {
AMM(wallet_core)
.send_remove_liq(
Amm(wallet_core)
.send_remove_liquidity(
user_holding_a,
user_holding_b,
user_holding_lp,
@ -277,7 +277,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
}
_ => {
// ToDo: Implement after private multi-chain calls is available
anyhow::bail!("Only public execution allowed for AMM calls");
anyhow::bail!("Only public execution allowed for Amm calls");
}
}
}

View File

@ -43,6 +43,60 @@ pub enum AccDecodeData {
Decode(nssa_core::SharedSecretKey, AccountId),
}
const TOKEN_DEFINITION_TYPE: u8 = 0;
const TOKEN_DEFINITION_DATA_SIZE: usize = 23;
const TOKEN_HOLDING_TYPE: u8 = 1;
const TOKEN_HOLDING_DATA_SIZE: usize = 49;
struct TokenDefinition {
#[allow(unused)]
account_type: u8,
name: [u8; 6],
total_supply: u128,
}
pub struct TokenHolding {
pub account_type: u8,
pub definition_id: AccountId,
pub balance: u128,
}
impl TokenDefinition {
fn parse(data: &[u8]) -> Option<Self> {
if data.len() != TOKEN_DEFINITION_DATA_SIZE || data[0] != TOKEN_DEFINITION_TYPE {
None
} else {
let account_type = data[0];
let name = data[1..7].try_into().unwrap();
let total_supply = u128::from_le_bytes(data[7..].try_into().unwrap());
Some(Self {
account_type,
name,
total_supply,
})
}
}
}
impl TokenHolding {
pub fn parse(data: &[u8]) -> Option<Self> {
if data.len() != TOKEN_HOLDING_DATA_SIZE || data[0] != TOKEN_HOLDING_TYPE {
None
} else {
let account_type = data[0];
let definition_id = AccountId::new(data[1..33].try_into().unwrap());
let balance = u128::from_le_bytes(data[33..].try_into().unwrap());
Some(Self {
definition_id,
balance,
account_type,
})
}
}
}
pub struct WalletCore {
pub storage: WalletChainStore,
pub poller: TxPoller,

View File

@ -1,19 +1,109 @@
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
use nssa::{AccountId, program::Program};
use nssa::{AccountId, ProgramId, program::Program};
use nssa_core::program::PdaSeed;
use crate::{
WalletCore,
cli::account::TokenHolding,
program_facades::{
OrphanHack49BytesInput, OrphanHack65BytesInput, compute_liquidity_token_pda,
compute_pool_pda, compute_vault_pda,
},
TokenHolding, WalletCore,
program_facades::{OrphanHack49BytesInput, OrphanHack65BytesInput},
};
pub struct AMM<'w>(pub &'w WalletCore);
fn compute_pool_pda(
amm_program_id: ProgramId,
definition_token_a_id: AccountId,
definition_token_b_id: AccountId,
) -> AccountId {
AccountId::from((
&amm_program_id,
&compute_pool_pda_seed(definition_token_a_id, definition_token_b_id),
))
}
impl AMM<'_> {
pub async fn send_new_amm_definition(
fn compute_pool_pda_seed(
definition_token_a_id: AccountId,
definition_token_b_id: AccountId,
) -> PdaSeed {
use risc0_zkvm::sha::{Impl, Sha256};
let mut i: usize = 0;
let (token_1, token_2) = loop {
if definition_token_a_id.value()[i] > definition_token_b_id.value()[i] {
let token_1 = definition_token_a_id;
let token_2 = definition_token_b_id;
break (token_1, token_2);
} else if definition_token_a_id.value()[i] < definition_token_b_id.value()[i] {
let token_1 = definition_token_b_id;
let token_2 = definition_token_a_id;
break (token_1, token_2);
}
if i == 32 {
panic!("Definitions match");
} else {
i += 1;
}
};
let mut bytes = [0; 64];
bytes[0..32].copy_from_slice(&token_1.to_bytes());
bytes[32..].copy_from_slice(&token_2.to_bytes());
PdaSeed::new(
Impl::hash_bytes(&bytes)
.as_bytes()
.try_into()
.expect("Hash output must be exactly 32 bytes long"),
)
}
fn compute_vault_pda(
amm_program_id: ProgramId,
pool_id: AccountId,
definition_token_id: AccountId,
) -> AccountId {
AccountId::from((
&amm_program_id,
&compute_vault_pda_seed(pool_id, definition_token_id),
))
}
fn compute_vault_pda_seed(pool_id: AccountId, definition_token_id: AccountId) -> PdaSeed {
use risc0_zkvm::sha::{Impl, Sha256};
let mut bytes = [0; 64];
bytes[0..32].copy_from_slice(&pool_id.to_bytes());
bytes[32..].copy_from_slice(&definition_token_id.to_bytes());
PdaSeed::new(
Impl::hash_bytes(&bytes)
.as_bytes()
.try_into()
.expect("Hash output must be exactly 32 bytes long"),
)
}
fn compute_liquidity_token_pda(amm_program_id: ProgramId, pool_id: AccountId) -> AccountId {
AccountId::from((&amm_program_id, &compute_liquidity_token_pda_seed(pool_id)))
}
fn compute_liquidity_token_pda_seed(pool_id: AccountId) -> PdaSeed {
use risc0_zkvm::sha::{Impl, Sha256};
let mut bytes = [0; 64];
bytes[0..32].copy_from_slice(&pool_id.to_bytes());
bytes[32..].copy_from_slice(&[0; 32]);
PdaSeed::new(
Impl::hash_bytes(&bytes)
.as_bytes()
.try_into()
.expect("Hash output must be exactly 32 bytes long"),
)
}
pub struct Amm<'w>(pub &'w WalletCore);
impl Amm<'_> {
pub async fn send_new_definition(
&self,
user_holding_a: AccountId,
user_holding_b: AccountId,
@ -25,12 +115,16 @@ impl AMM<'_> {
let amm_program_id = Program::amm().id();
let Ok(user_a_acc) = self.0.get_account_public(user_holding_a).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let Ok(user_b_acc) = self.0.get_account_public(user_holding_b).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let user_a_acc = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let user_b_acc = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let definition_token_a_id = TokenHolding::parse(&user_a_acc.data)
.ok_or(ExecutionFailureKind::AccountDataError(user_holding_a))?
@ -55,31 +149,25 @@ impl AMM<'_> {
user_holding_lp,
];
let Ok(nonces) = self
let nonces = self
.0
.get_accounts_nonces(vec![user_holding_a, user_holding_b])
.await
else {
return Err(ExecutionFailureKind::SequencerError);
};
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let Some(signing_key_a) = self
let signing_key_a = self
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_a)
else {
return Err(ExecutionFailureKind::KeyNotFoundError);
};
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let Some(signing_key_b) = self
let signing_key_b = self
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_b)
else {
return Err(ExecutionFailureKind::KeyNotFoundError);
};
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let message = nssa::public_transaction::Message::try_new(
program.id(),
@ -112,12 +200,16 @@ impl AMM<'_> {
let amm_program_id = Program::amm().id();
let Ok(user_a_acc) = self.0.get_account_public(user_holding_a).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let Ok(user_b_acc) = self.0.get_account_public(user_holding_b).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let user_a_acc = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let user_b_acc = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let definition_token_a_id = TokenHolding::parse(&user_a_acc.data)
.ok_or(ExecutionFailureKind::AccountDataError(user_holding_a))?
@ -166,18 +258,18 @@ impl AMM<'_> {
return Err(ExecutionFailureKind::AccountDataError(token_definition_id));
}
let Ok(nonces) = self.0.get_accounts_nonces(vec![account_id_auth]).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let nonces = self
.0
.get_accounts_nonces(vec![account_id_auth])
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let Some(signing_key) = self
let signing_key = self
.0
.storage
.user_data
.get_pub_account_signing_key(&account_id_auth)
else {
return Err(ExecutionFailureKind::KeyNotFoundError);
};
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let message = nssa::public_transaction::Message::try_new(
program.id(),
@ -195,7 +287,7 @@ impl AMM<'_> {
Ok(self.0.sequencer_client.send_tx_public(tx).await?)
}
pub async fn send_add_liq(
pub async fn send_add_liquidity(
&self,
user_holding_a: AccountId,
user_holding_b: AccountId,
@ -209,12 +301,16 @@ impl AMM<'_> {
let amm_program_id = Program::amm().id();
let Ok(user_a_acc) = self.0.get_account_public(user_holding_a).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let Ok(user_b_acc) = self.0.get_account_public(user_holding_b).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let user_a_acc = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let user_b_acc = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let definition_token_a_id = TokenHolding::parse(&user_a_acc.data)
.ok_or(ExecutionFailureKind::AccountDataError(user_holding_a))?
@ -239,31 +335,25 @@ impl AMM<'_> {
user_holding_lp,
];
let Ok(nonces) = self
let nonces = self
.0
.get_accounts_nonces(vec![user_holding_a, user_holding_b])
.await
else {
return Err(ExecutionFailureKind::SequencerError);
};
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let Some(signing_key_a) = self
let signing_key_a = self
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_a)
else {
return Err(ExecutionFailureKind::KeyNotFoundError);
};
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let Some(signing_key_b) = self
let signing_key_b = self
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_b)
else {
return Err(ExecutionFailureKind::KeyNotFoundError);
};
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let message = nssa::public_transaction::Message::try_new(
program.id(),
@ -283,7 +373,7 @@ impl AMM<'_> {
Ok(self.0.sequencer_client.send_tx_public(tx).await?)
}
pub async fn send_remove_liq(
pub async fn send_remove_liquidity(
&self,
user_holding_a: AccountId,
user_holding_b: AccountId,
@ -297,12 +387,16 @@ impl AMM<'_> {
let amm_program_id = Program::amm().id();
let Ok(user_a_acc) = self.0.get_account_public(user_holding_a).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let Ok(user_b_acc) = self.0.get_account_public(user_holding_b).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let user_a_acc = self
.0
.get_account_public(user_holding_a)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let user_b_acc = self
.0
.get_account_public(user_holding_b)
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let definition_token_a_id = TokenHolding::parse(&user_a_acc.data)
.ok_or(ExecutionFailureKind::AccountDataError(user_holding_a))?
@ -327,18 +421,18 @@ impl AMM<'_> {
user_holding_lp,
];
let Ok(nonces) = self.0.get_accounts_nonces(vec![user_holding_lp]).await else {
return Err(ExecutionFailureKind::SequencerError);
};
let nonces = self
.0
.get_accounts_nonces(vec![user_holding_lp])
.await
.map_err(|_| ExecutionFailureKind::SequencerError)?;
let Some(signing_key_lp) = self
let signing_key_lp = self
.0
.storage
.user_data
.get_pub_account_signing_key(&user_holding_lp)
else {
return Err(ExecutionFailureKind::KeyNotFoundError);
};
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let message = nssa::public_transaction::Message::try_new(
program.id(),

View File

@ -1,8 +1,6 @@
//! This module contains [`WalletCore`](crate::WalletCore) facades for interacting with various
//! on-chain programs.
use nssa::{AccountId, ProgramId};
use nssa_core::program::PdaSeed;
use serde::{Serialize, ser::SerializeSeq};
pub mod amm;
@ -10,99 +8,6 @@ pub mod native_token_transfer;
pub mod pinata;
pub mod token;
fn compute_pool_pda(
amm_program_id: ProgramId,
definition_token_a_id: AccountId,
definition_token_b_id: AccountId,
) -> AccountId {
AccountId::from((
&amm_program_id,
&compute_pool_pda_seed(definition_token_a_id, definition_token_b_id),
))
}
fn compute_pool_pda_seed(
definition_token_a_id: AccountId,
definition_token_b_id: AccountId,
) -> PdaSeed {
use risc0_zkvm::sha::{Impl, Sha256};
let mut i: usize = 0;
let (token_1, token_2) = loop {
if definition_token_a_id.value()[i] > definition_token_b_id.value()[i] {
let token_1 = definition_token_a_id;
let token_2 = definition_token_b_id;
break (token_1, token_2);
} else if definition_token_a_id.value()[i] < definition_token_b_id.value()[i] {
let token_1 = definition_token_b_id;
let token_2 = definition_token_a_id;
break (token_1, token_2);
}
if i == 32 {
panic!("Definitions match");
} else {
i += 1;
}
};
let mut bytes = [0; 64];
bytes[0..32].copy_from_slice(&token_1.to_bytes());
bytes[32..].copy_from_slice(&token_2.to_bytes());
PdaSeed::new(
Impl::hash_bytes(&bytes)
.as_bytes()
.try_into()
.expect("Hash output must be exactly 32 bytes long"),
)
}
fn compute_vault_pda(
amm_program_id: ProgramId,
pool_id: AccountId,
definition_token_id: AccountId,
) -> AccountId {
AccountId::from((
&amm_program_id,
&compute_vault_pda_seed(pool_id, definition_token_id),
))
}
fn compute_vault_pda_seed(pool_id: AccountId, definition_token_id: AccountId) -> PdaSeed {
use risc0_zkvm::sha::{Impl, Sha256};
let mut bytes = [0; 64];
bytes[0..32].copy_from_slice(&pool_id.to_bytes());
bytes[32..].copy_from_slice(&definition_token_id.to_bytes());
PdaSeed::new(
Impl::hash_bytes(&bytes)
.as_bytes()
.try_into()
.expect("Hash output must be exactly 32 bytes long"),
)
}
fn compute_liquidity_token_pda(amm_program_id: ProgramId, pool_id: AccountId) -> AccountId {
AccountId::from((&amm_program_id, &compute_liquidity_token_pda_seed(pool_id)))
}
fn compute_liquidity_token_pda_seed(pool_id: AccountId) -> PdaSeed {
use risc0_zkvm::sha::{Impl, Sha256};
let mut bytes = [0; 64];
bytes[0..32].copy_from_slice(&pool_id.to_bytes());
bytes[32..].copy_from_slice(&[0; 32]);
PdaSeed::new(
Impl::hash_bytes(&bytes)
.as_bytes()
.try_into()
.expect("Hash output must be exactly 32 bytes long"),
)
}
/// Why it is necessary:
///
/// Serialize implemented only for `[u8; N]` where `N<=32` and orphan rules would disallow custom