Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add account details endpoint #248

Merged
merged 20 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ args = ["-rf", "miden-node"]
description = "Clone or update miden-node repository and clean up files"
script_runner = "bash"
script = [
'if [ -d miden-node ]; then cd miden-node && git pull ; else git clone --branch next https://github.com/0xPolygonMiden/miden-node.git && cd miden-node; fi',
'if [ -d miden-node ]; then cd miden-node && git checkout next && git pull origin next; else git clone --branch next https://github.com/0xPolygonMiden/miden-node.git && cd miden-node; fi',
'rm -rf miden-store.sqlite3 miden-store.sqlite3-wal miden-store.sqlite3-shm',
'cargo run --bin $NODE_BINARY --features $NODE_FEATURES_TESTING -- make-genesis --inputs-path node/genesis.toml --force'
]
Expand Down
1 change: 1 addition & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
large-error-threshold = 256
too-many-arguments-threshold = 8
61 changes: 49 additions & 12 deletions src/cli/account.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fs, path::PathBuf};

use clap::Parser;
use clap::{Parser, ValueEnum};
use comfy_table::{presets, Attribute, Cell, ContentArrangement, Table};
use miden_client::{
client::{accounts, rpc::NodeRpcClient, Client},
Expand Down Expand Up @@ -61,9 +61,15 @@ pub enum AccountCmd {
#[clap()]
pub enum AccountTemplate {
/// Creates a basic account (Regular account with immutable code)
BasicImmutable,
BasicImmutable {
#[clap(short, long, value_enum, default_value_t = AccountStorageMode::OffChain)]
storage_mode: AccountStorageMode,
},
/// Creates a basic account (Regular account with mutable code)
BasicMutable,
BasicMutable {
#[clap(short, long, value_enum, default_value_t = AccountStorageMode::OffChain)]
storage_mode: AccountStorageMode,
},
/// Creates a faucet for fungible tokens
FungibleFaucet {
#[clap(short, long)]
Expand All @@ -72,9 +78,35 @@ pub enum AccountTemplate {
decimals: u8,
#[clap(short, long)]
max_supply: u64,
#[clap(short, long, value_enum, default_value_t = AccountStorageMode::OffChain)]
storage_mode: AccountStorageMode,
},
/// Creates a faucet for non-fungible tokens
NonFungibleFaucet,
NonFungibleFaucet {
#[clap(short, long, value_enum, default_value_t = AccountStorageMode::OffChain)]
storage_mode: AccountStorageMode,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can add this to the AccountCmd::New since it's common to all variants.

},
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum AccountStorageMode {
OffChain,
OnChain,
}

impl From<AccountStorageMode> for accounts::AccountStorageMode {
fn from(value: AccountStorageMode) -> Self {
match value {
AccountStorageMode::OffChain => accounts::AccountStorageMode::Local,
AccountStorageMode::OnChain => accounts::AccountStorageMode::OnChain,
}
}
}

impl From<&AccountStorageMode> for accounts::AccountStorageMode {
fn from(value: &AccountStorageMode) -> Self {
accounts::AccountStorageMode::from(*value)
}
Comment on lines +93 to +110
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a TODO to review these struct's names (and maybe the local vs offchain terms)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! added it here and in the client/accounts.rs one

}

impl AccountCmd {
Expand All @@ -88,26 +120,31 @@ impl AccountCmd {
},
AccountCmd::New { template } => {
let client_template = match template {
AccountTemplate::BasicImmutable => accounts::AccountTemplate::BasicWallet {
mutable_code: false,
storage_mode: accounts::AccountStorageMode::Local,
AccountTemplate::BasicImmutable { storage_mode } => {
accounts::AccountTemplate::BasicWallet {
mutable_code: false,
storage_mode: storage_mode.into(),
}
},
AccountTemplate::BasicMutable => accounts::AccountTemplate::BasicWallet {
mutable_code: true,
storage_mode: accounts::AccountStorageMode::Local,
AccountTemplate::BasicMutable { storage_mode } => {
accounts::AccountTemplate::BasicWallet {
mutable_code: true,
storage_mode: storage_mode.into(),
}
},
AccountTemplate::FungibleFaucet {
token_symbol,
decimals,
max_supply,
storage_mode,
} => accounts::AccountTemplate::FungibleFaucet {
token_symbol: TokenSymbol::new(token_symbol)
.map_err(|err| format!("error: token symbol is invalid: {}", err))?,
decimals: *decimals,
max_supply: *max_supply,
storage_mode: accounts::AccountStorageMode::Local,
storage_mode: storage_mode.into(),
},
AccountTemplate::NonFungibleFaucet => todo!(),
AccountTemplate::NonFungibleFaucet { storage_mode: _ } => todo!(),
};
let (_new_account, _account_seed) = client.new_account(client_template)?;
},
Expand Down
29 changes: 13 additions & 16 deletions src/client/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,21 @@ pub enum AccountTemplate {
},
}

#[derive(Debug, Clone, Copy)]
pub enum AccountStorageMode {
Local,
OnChain,
}

impl From<AccountStorageMode> for AccountStorageType {
fn from(mode: AccountStorageMode) -> Self {
match mode {
AccountStorageMode::Local => AccountStorageType::OffChain,
AccountStorageMode::OnChain => AccountStorageType::OnChain,
}
}
}

impl<N: NodeRpcClient, R: FeltRng, S: Store> Client<N, R, S> {
// ACCOUNT CREATION
// --------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -108,20 +118,11 @@ impl<N: NodeRpcClient, R: FeltRng, S: Store> Client<N, R, S> {
}

/// Creates a new regular account and saves it in the store along with its seed and auth data
///
/// # Panics
///
/// If the passed [AccountStorageMode] is [AccountStorageMode::OnChain], this function panics
/// since this feature is not currently supported on Miden
fn new_basic_wallet(
&mut self,
mutable_code: bool,
account_storage_mode: AccountStorageMode,
) -> Result<(Account, Word), ClientError> {
if let AccountStorageMode::OnChain = account_storage_mode {
todo!("Recording the account on chain is not supported yet");
}

// TODO: This should be initialized with_rng
let key_pair = SecretKey::new();

Expand All @@ -138,14 +139,14 @@ impl<N: NodeRpcClient, R: FeltRng, S: Store> Client<N, R, S> {
init_seed,
auth_scheme,
AccountType::RegularAccountImmutableCode,
AccountStorageType::OffChain,
account_storage_mode.into(),
)
} else {
miden_lib::accounts::wallets::create_basic_wallet(
init_seed,
auth_scheme,
AccountType::RegularAccountUpdatableCode,
AccountStorageType::OffChain,
account_storage_mode.into(),
)
}?;

Expand All @@ -160,10 +161,6 @@ impl<N: NodeRpcClient, R: FeltRng, S: Store> Client<N, R, S> {
max_supply: u64,
account_storage_mode: AccountStorageMode,
) -> Result<(Account, Word), ClientError> {
if let AccountStorageMode::OnChain = account_storage_mode {
todo!("On-chain accounts are not supported yet");
}

// TODO: This should be initialized with_rng
let key_pair = SecretKey::new();

Expand All @@ -181,7 +178,7 @@ impl<N: NodeRpcClient, R: FeltRng, S: Store> Client<N, R, S> {
decimals,
Felt::try_from(max_supply.to_le_bytes().as_slice())
.expect("u64 can be safely converted to a field element"),
AccountStorageType::OffChain,
account_storage_mode.into(),
auth_scheme,
)?;

Expand Down
9 changes: 8 additions & 1 deletion src/client/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::fmt;

use async_trait::async_trait;
use miden_objects::{
accounts::AccountId,
accounts::{Account, AccountId},
crypto::merkle::{MerklePath, MmrDelta},
notes::{NoteId, NoteMetadata},
transaction::ProvenTransaction,
Expand Down Expand Up @@ -56,6 +56,11 @@ pub trait NodeRpcClient {
note_tags: &[u16],
nullifiers_tags: &[u16],
) -> Result<StateSyncInfo, NodeRpcClientError>;

async fn get_account_update(
&mut self,
account_id: AccountId,
) -> Result<Option<Account>, NodeRpcClientError>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the return type should be Account instead of Option<Account> for this. I believe the node will return an error if the account is not found so an Account is always expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went for Option since it's what the response comes with so I expected that there will eventually be some use for the summary but no details case. In any way we can take another look at it in the future and keep it simple for now

}

// STATE SYNC INFO
Expand Down Expand Up @@ -130,6 +135,7 @@ impl CommittedNote {
//
#[derive(Debug)]
pub enum NodeRpcClientEndpoint {
GetAccountDetails,
GetBlockHeaderByNumber,
SyncState,
SubmitProvenTx,
Expand All @@ -141,6 +147,7 @@ impl fmt::Display for NodeRpcClientEndpoint {
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match self {
NodeRpcClientEndpoint::GetAccountDetails => write!(f, "get_account_details"),
NodeRpcClientEndpoint::GetBlockHeaderByNumber => {
write!(f, "get_block_header_by_number")
},
Expand Down
37 changes: 35 additions & 2 deletions src/client/rpc/tonic_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ use miden_node_proto::{
errors::ConversionError,
generated::{
requests::{
GetBlockHeaderByNumberRequest, SubmitProvenTransactionRequest, SyncStateRequest,
GetAccountDetailsRequest, GetBlockHeaderByNumberRequest,
SubmitProvenTransactionRequest, SyncStateRequest,
},
responses::SyncStateResponse,
rpc::api_client::ApiClient,
},
};
use miden_objects::{
accounts::AccountId,
accounts::{Account, AccountId},
notes::{NoteId, NoteMetadata, NoteType},
transaction::ProvenTransaction,
utils::Deserializable,
BlockHeader, Digest,
};
use miden_tx::utils::Serializable;
Expand Down Expand Up @@ -127,6 +129,37 @@ impl NodeRpcClient for TonicRpcClient {
})?;
response.into_inner().try_into()
}

/// TODO: fill description
async fn get_account_update(
&mut self,
account_id: AccountId,
) -> Result<Option<Account>, NodeRpcClientError> {
debug_assert!(account_id.is_on_chain());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be an error instead of a panic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed!


let account_id = account_id.into();
let request = GetAccountDetailsRequest {
account_id: Some(account_id),
};

let rpc_api = self.rpc_api().await?;

let response = rpc_api.get_account_details(request).await.map_err(|err| {
NodeRpcClientError::RequestError(
NodeRpcClientEndpoint::GetAccountDetails.to_string(),
err.to_string(),
)
})?;
let response = response.into_inner();
// TODO: remove unwrap and use proper handling
let account_info = response.account.unwrap();
let details = account_info
.details
.map(|details| Account::read_from_bytes(&details))
.transpose()?;

Ok(details)
}
}

// STATE SYNC INFO CONVERSION
Expand Down
Loading
Loading