Skip to content

Commit

Permalink
Add restricted and implicit address types (#1229)
Browse files Browse the repository at this point in the history
* Add restricted and implicit address types

* comments and derive

* nit

Co-authored-by: Thibault Martinez <[email protected]>

* no_std

* Split out ImplicitAccountCreationAddress

* Split out Restricted

* Rename to RestrictedAddress

* Tests in tests

* Update restricted address and remove Copy derives

* fix bech32 tests

* Clippy

* Apply suggestions from code review

* remove clones

* little cleanup

* Nit

* Split and clean tests

* PR suggestions

* Refactor address capabilities

* Use prefixed box for capabilities

* renames

* clippy

* docs

* Remove Result/Option

* Update sdk/src/client/utils.rs

Co-authored-by: /alex/ <[email protected]>

* Revert some stuff

* Missed changes

* PR suggestions and no_std

---------

Co-authored-by: Thibault Martinez <[email protected]>
Co-authored-by: /alex/ <[email protected]>
  • Loading branch information
3 people authored Oct 10, 2023
1 parent 83c1d97 commit 9fb7b8c
Show file tree
Hide file tree
Showing 107 changed files with 1,064 additions and 403 deletions.
2 changes: 1 addition & 1 deletion bindings/core/src/method_handler/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{method::AccountMethod, Response, Result};
pub(crate) async fn call_account_method_internal(account: &Account, method: AccountMethod) -> Result<Response> {
let response = match method {
AccountMethod::Addresses => {
let addresses = account.addresses().await?;
let addresses = account.addresses().await;
Response::Addresses(addresses)
}
AccountMethod::AddressesWithUnspentOutputs => {
Expand Down
2 changes: 1 addition & 1 deletion bindings/core/src/method_handler/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result<Response
UtilsMethod::HexPublicKeyToBech32Address { hex, bech32_hrp } => {
Response::Bech32Address(hex_public_key_to_bech32_address(&hex, bech32_hrp)?)
}
UtilsMethod::ParseBech32Address { address } => Response::ParsedBech32Address(Address::from(address.inner())),
UtilsMethod::ParseBech32Address { address } => Response::ParsedBech32Address(address.into_inner()),
UtilsMethod::IsAddressValid { address } => Response::Bool(Address::is_valid_bech32(&address)),
UtilsMethod::GenerateMnemonic => Response::GeneratedMnemonic(Client::generate_mnemonic()?.to_string()),
UtilsMethod::MnemonicToHexSeed { mnemonic } => {
Expand Down
4 changes: 3 additions & 1 deletion bindings/core/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ async fn utils() -> Result<()> {

let bech32_address =
Bech32Address::try_from_str("rms1qpllaj0pyveqfkwxmnngz2c488hfdtmfrj3wfkgxtk4gtyrax0jaxzt70zy")?;
let method = UtilsMethod::Bech32ToHex { bech32: bech32_address };
let method = UtilsMethod::Bech32ToHex {
bech32: bech32_address.clone(),
};

let response = call_utils_method(method);
match response {
Expand Down
6 changes: 3 additions & 3 deletions cli/src/command/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ impl FromStr for TransactionSelector {

/// `addresses` command
pub async fn addresses_command(account: &Account) -> Result<(), Error> {
let addresses = account.addresses().await?;
let addresses = account.addresses().await;

if addresses.is_empty() {
println_log_info!("No addresses found");
Expand Down Expand Up @@ -547,8 +547,8 @@ pub async fn faucet_command(
let address = if let Some(address) = address {
address
} else {
match account.addresses().await?.last() {
Some(address) => *address.address(),
match account.addresses().await.into_iter().rev().next() {
Some(address) => address.into_bech32(),
None => return Err(Error::NoAddressForFaucet),
}
};
Expand Down
9 changes: 5 additions & 4 deletions sdk/examples/client/02_address_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,20 @@ async fn main() -> Result<()> {
let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?;

// Generate the first address
let addresses = secret_manager
let first_address = secret_manager
.generate_ed25519_addresses(
GetAddressesOptions::from_client(&client)
.await?
.with_account_index(0)
.with_range(0..1),
)
.await?;
.await?[0]
.clone();

// Get output ids of outputs that can be controlled by this address without further unlock constraints
let output_ids_response = client
.basic_output_ids([
QueryParameter::Address(addresses[0]),
QueryParameter::Address(first_address.clone()),
QueryParameter::HasExpiration(false),
QueryParameter::HasTimelock(false),
QueryParameter::HasStorageDepositReturn(false),
Expand All @@ -65,7 +66,7 @@ async fn main() -> Result<()> {

println!(
"Outputs controlled by {} have: {:?}i and native tokens:\n{:#?}",
addresses[0],
first_address,
total_amount,
total_native_tokens.finish_vec()?
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async fn main() -> Result<()> {
// Get output IDs of account outputs that can be controlled by this address.
let output_ids_response = client
.account_output_ids([
QueryParameter::Governor(address),
QueryParameter::Governor(address.clone()),
QueryParameter::StateController(address),
])
.await?;
Expand Down
6 changes: 3 additions & 3 deletions sdk/examples/client/output/build_account_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ async fn main() -> Result<()> {
// Account id needs to be null the first time
let account_output = AccountOutputBuilder::new_with_minimum_storage_deposit(rent_structure, AccountId::null())
.with_state_metadata(metadata)
.add_feature(SenderFeature::new(address))
.add_feature(SenderFeature::new(address.clone()))
.add_feature(MetadataFeature::new(metadata)?)
.add_immutable_feature(IssuerFeature::new(address))
.add_immutable_feature(IssuerFeature::new(address.clone()))
.add_immutable_feature(MetadataFeature::new(metadata)?)
.add_unlock_condition(StateControllerAddressUnlockCondition::new(address))
.add_unlock_condition(StateControllerAddressUnlockCondition::new(address.clone()))
.add_unlock_condition(GovernorAddressUnlockCondition::new(address))
.finish_output(token_supply)?;

Expand Down
8 changes: 4 additions & 4 deletions sdk/examples/client/output/build_basic_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ async fn main() -> Result<()> {
.unwrap_or("rms1qpllaj0pyveqfkwxmnngz2c488hfdtmfrj3wfkgxtk4gtyrax0jaxzt70zy".to_string());
let address = Address::try_from_bech32(address)?;

let basic_output_builder =
BasicOutputBuilder::new_with_amount(1_000_000).add_unlock_condition(AddressUnlockCondition::new(address));
let basic_output_builder = BasicOutputBuilder::new_with_amount(1_000_000)
.add_unlock_condition(AddressUnlockCondition::new(address.clone()));

let outputs = [
// most simple output
Expand All @@ -58,15 +58,15 @@ async fn main() -> Result<()> {
basic_output_builder
.clone()
.add_unlock_condition(StorageDepositReturnUnlockCondition::new(
address,
address.clone(),
1_000_000,
token_supply,
)?)
.finish_output(token_supply)?,
// with expiration
basic_output_builder
.clone()
.add_unlock_condition(ExpirationUnlockCondition::new(address, 1)?)
.add_unlock_condition(ExpirationUnlockCondition::new(address.clone(), 1)?)
.finish_output(token_supply)?,
// with timelock
basic_output_builder
Expand Down
4 changes: 2 additions & 2 deletions sdk/examples/client/output/build_nft_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ async fn main() -> Result<()> {

// NftId needs to be null the first time
let nft_output = NftOutputBuilder::new_with_minimum_storage_deposit(rent_structure, NftId::null())
.add_unlock_condition(AddressUnlockCondition::new(address))
.add_feature(SenderFeature::new(address))
.add_unlock_condition(AddressUnlockCondition::new(address.clone()))
.add_feature(SenderFeature::new(address.clone()))
.add_feature(MetadataFeature::new(MUTABLE_METADATA)?)
.add_feature(TagFeature::new(TAG)?)
.add_immutable_feature(IssuerFeature::new(address))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ async fn main() -> Result<()> {
println!("ADDRESSES:");
let explorer_url = std::env::var("EXPLORER_URL").ok();
let prepended = explorer_url.map(|url| format!("{url}/addr/")).unwrap_or_default();
for address in account.addresses().await? {
for address in account.addresses().await {
println!(" - {prepended}{}", address.address());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async fn main() -> Result<()> {
println!("OUTPUT #{i}");
println!(
"- address: {:?}\n- amount: {:?}\n- native tokens: {:?}",
output_data.address.to_bech32_unchecked("rms"),
output_data.address.clone().to_bech32_unchecked("rms"),
output_data.output.amount(),
output_data.output.native_tokens()
)
Expand Down Expand Up @@ -85,7 +85,7 @@ async fn main() -> Result<()> {
println!("OUTPUT #{i}");
println!(
"- address: {:?}\n- amount: {:?}\n- native tokens: {:?}",
output_data.address.to_bech32_unchecked("rms"),
output_data.address.clone().to_bech32_unchecked("rms"),
output_data.output.amount(),
output_data.output.native_tokens()
)
Expand Down
4 changes: 2 additions & 2 deletions sdk/examples/how_tos/accounts_and_addresses/create_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ async fn main() -> Result<()> {
let address_url = explorer_url.map(|url| format!("{url}/addr/")).unwrap_or_default();

println!("Current addresses:");
for address in account.addresses().await? {
for address in account.addresses().await {
println!(" - {address_url}{}", address.address());
}

Expand All @@ -45,7 +45,7 @@ async fn main() -> Result<()> {
.generate_ed25519_addresses(NUM_ADDRESSES_TO_GENERATE, None)
.await?;
println!("Generated {} new addresses:", new_addresses.len());
let account_addresses = account.addresses().await?;
let account_addresses = account.addresses().await;
for new_address in new_addresses.iter() {
assert!(account_addresses.contains(new_address));
println!(" - {address_url}{}", new_address.address());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async fn main() -> Result<()> {
.await?;
let account = wallet.get_account("Alice").await?;

for address in account.addresses().await? {
for address in account.addresses().await {
println!("{}", address.address());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ async fn main() -> Result<()> {
MintNftParams::new()
.with_immutable_metadata(get_immutable_metadata(index).to_bytes())
// The NFT address from the NFT we minted in mint_issuer_nft example
.with_issuer(issuer)
.with_issuer(issuer.clone())
})
.collect::<Vec<_>>();

Expand Down
10 changes: 5 additions & 5 deletions sdk/examples/how_tos/nfts/mint_nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ async fn main() -> Result<()> {
account.sync(None).await?;

// We send from the first address in the account.
let sender_address = *account.addresses().await?[0].address();
let sender_address = account.first_address_bech32().await;

// Set the stronghold password
wallet
Expand All @@ -66,10 +66,10 @@ async fn main() -> Result<()> {

let nft_params = [MintNftParams::new()
.try_with_address(NFT1_OWNER_ADDRESS)?
.try_with_sender(sender_address)?
.try_with_sender(sender_address.clone())?
.with_metadata(NFT1_METADATA.as_bytes().to_vec())
.with_tag(NFT1_TAG.as_bytes().to_vec())
.try_with_issuer(sender_address)?
.try_with_issuer(sender_address.clone())?
.with_immutable_metadata(metadata.to_bytes())];

let transaction = account.mint_nfts(nft_params, None).await?;
Expand All @@ -91,8 +91,8 @@ async fn main() -> Result<()> {
let outputs = [
// address of the owner of the NFT
NftOutputBuilder::new_with_amount(NFT2_AMOUNT, NftId::null())
.add_unlock_condition(AddressUnlockCondition::new(sender_address))
.add_feature(SenderFeature::new(sender_address))
.add_unlock_condition(AddressUnlockCondition::new(sender_address.clone()))
.add_feature(SenderFeature::new(sender_address.clone()))
.add_immutable_feature(IssuerFeature::new(sender_address))
.finish_output(token_supply)?,
];
Expand Down
4 changes: 2 additions & 2 deletions sdk/examples/how_tos/outputs/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ async fn main() -> Result<()> {
let address = Address::try_from_bech32("rms1qpllaj0pyveqfkwxmnngz2c488hfdtmfrj3wfkgxtk4gtyrax0jaxzt70zy")?;

let nft_output_builder = NftOutputBuilder::new_with_minimum_storage_deposit(rent_structure, NftId::null())
.add_unlock_condition(AddressUnlockCondition::new(address));
.add_unlock_condition(AddressUnlockCondition::new(address.clone()));

let outputs = [
// with sender feature
nft_output_builder
.clone()
.add_feature(SenderFeature::new(address))
.add_feature(SenderFeature::new(address.clone()))
.finish_output(token_supply)?,
// with issuer feature
nft_output_builder
Expand Down
8 changes: 4 additions & 4 deletions sdk/examples/how_tos/outputs/unlock_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async fn main() -> Result<()> {
let token_scheme = TokenScheme::Simple(SimpleTokenScheme::new(50, 0, 100)?);

let basic_output_builder = BasicOutputBuilder::new_with_minimum_storage_deposit(rent_structure)
.add_unlock_condition(AddressUnlockCondition::new(address));
.add_unlock_condition(AddressUnlockCondition::new(address.clone()));
let account_output_builder =
AccountOutputBuilder::new_with_minimum_storage_deposit(rent_structure, AccountId::null());
let foundry_output_builder =
Expand All @@ -56,7 +56,7 @@ async fn main() -> Result<()> {
basic_output_builder
.clone()
.add_unlock_condition(StorageDepositReturnUnlockCondition::new(
address,
address.clone(),
1000000,
token_supply,
)?)
Expand All @@ -68,11 +68,11 @@ async fn main() -> Result<()> {
.finish_output(token_supply)?,
// with expiration unlock condition
basic_output_builder
.add_unlock_condition(ExpirationUnlockCondition::new(address, 1)?)
.add_unlock_condition(ExpirationUnlockCondition::new(address.clone(), 1)?)
.finish_output(token_supply)?,
// with governor and state controller unlock condition
account_output_builder
.add_unlock_condition(GovernorAddressUnlockCondition::new(address))
.add_unlock_condition(GovernorAddressUnlockCondition::new(address.clone()))
.add_unlock_condition(StateControllerAddressUnlockCondition::new(address))
.finish_output(token_supply)?,
// with immutable account unlock condition
Expand Down
2 changes: 1 addition & 1 deletion sdk/examples/how_tos/simple_transaction/request_funds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async fn main() -> Result<()> {
let balance = account.sync(None).await?;
println!("Account synced");

let addresses = account.addresses().await?;
let addresses = account.addresses().await;

let funds_before = balance.base_coin().available();
println!("Current available funds: {funds_before}");
Expand Down
6 changes: 3 additions & 3 deletions sdk/examples/wallet/17_check_unlock_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ async fn main() -> Result<()> {

let account_addresses = account
.addresses()
.await?
.await
.into_iter()
.map(|a| *a.address())
.map(|a| a.into_bech32())
.collect::<Vec<Bech32Address>>();

println!("ADDRESSES:\n{:#?}", account_addresses);

let output = BasicOutputBuilder::new_with_amount(AMOUNT)
.add_unlock_condition(AddressUnlockCondition::new(*account_addresses[0].as_ref()))
.add_unlock_condition(AddressUnlockCondition::new(account_addresses[0].as_ref().clone()))
.finish_output(account.client().get_token_supply().await?)?;

let controlled_by_account = if let [UnlockCondition::Address(address_unlock_condition)] = output
Expand Down
2 changes: 1 addition & 1 deletion sdk/examples/wallet/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ async fn main() -> Result<()> {

println!("New available funds: {}", balance.base_coin().available());

let addresses = account2.addresses().await?;
let addresses = account2.addresses().await;
println!("Number of addresses in {alias2}'s account: {}", addresses.len());
println!("{alias2}'s base coin balance:\n{:#?}", balance.base_coin());

Expand Down
2 changes: 1 addition & 1 deletion sdk/examples/wallet/background_syncing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async fn main() -> Result<()> {

// Get or create new account
let account = wallet.get_or_create_account("Alice").await?;
let addresses = account.addresses().await?;
let addresses = account.addresses().await;

// Manually sync to ensure we have the correct funds to start with
let balance = account.sync(None).await?;
Expand Down
2 changes: 1 addition & 1 deletion sdk/examples/wallet/getting_started.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async fn main() -> Result<()> {
.finish()
.await?;

let first_address = &account.addresses().await?[0];
let first_address = &account.addresses().await[0];
println!("{}", first_address.address());

Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async fn main() -> Result<()> {
async fn write_addresses_to_file(account: &Account) -> Result<()> {
use tokio::io::AsyncWriteExt;

let addresses = account.addresses().await?;
let addresses = account.addresses().await;
let json = serde_json::to_string_pretty(&addresses)?;
let mut file = tokio::io::BufWriter::new(tokio::fs::File::create(ADDRESSES_FILE_PATH).await?);
println!("example.addresses.json:\n{json}");
Expand Down
5 changes: 3 additions & 2 deletions sdk/examples/wallet/spammer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async fn main() -> Result<()> {
.await?;
let account = wallet.get_or_create_account(ACCOUNT_ALIAS).await?;

let recv_address = *account.addresses().await?[0].address();
let recv_address = account.first_address_bech32().await;
println!("Recv address: {}", recv_address);

// Ensure there are enough available funds for spamming.
Expand All @@ -71,7 +71,7 @@ async fn main() -> Result<()> {
println!("Creating unspent outputs...");

let transaction = account
.send_with_params(vec![SendParams::new(SEND_AMOUNT, recv_address)?; 127], None)
.send_with_params(vec![SendParams::new(SEND_AMOUNT, recv_address.clone())?; 127], None)
.await?;
wait_for_inclusion(&transaction.transaction_id, &account).await?;

Expand All @@ -87,6 +87,7 @@ async fn main() -> Result<()> {

for n in 0..num_simultaneous_txs {
let account_clone = account.clone();
let recv_address = recv_address.clone();

tasks.spawn(async move {
println!("Thread {n}: sending {SEND_AMOUNT} coins to own address");
Expand Down
Loading

0 comments on commit 9fb7b8c

Please sign in to comment.