{
+ let additional_utxo_infos = BTreeMap::from_iter([(
+ PoolOrTokenId::PoolId(pool_id),
+ UtxoAdditionalInfo::PoolInfo { staker_balance },
+ )]);
self.for_account_rw_unlocked_and_check_tx_custom_error(
account_index,
- |account, db_tx| {
+ &additional_utxo_infos,
+ |account: &mut Account<::K>, db_tx| {
account.decommission_stake_pool(
db_tx,
pool_id,
- pool_balance,
+ staker_balance,
output_address,
current_fee_rate,
)
@@ -1732,22 +1811,26 @@ where
&mut self,
account_index: U31,
pool_id: PoolId,
- pool_balance: Amount,
+ staker_balance: Amount,
output_address: Option,
current_fee_rate: FeeRate,
) -> WalletResult {
+ let additional_utxo_infos = BTreeMap::from_iter([(
+ PoolOrTokenId::PoolId(pool_id),
+ UtxoAdditionalInfo::PoolInfo { staker_balance },
+ )]);
self.for_account_rw_unlocked(
account_index,
|account, db_tx, chain_config, signer_provider| {
let request = account.decommission_stake_pool_request(
db_tx,
pool_id,
- pool_balance,
+ staker_balance,
output_address,
current_fee_rate,
)?;
- let ptx = request.into_partially_signed_tx()?;
+ let ptx = request.into_partially_signed_tx(&additional_utxo_infos)?;
let mut signer =
signer_provider.provide(Arc::new(chain_config.clone()), account_index);
@@ -1768,41 +1851,39 @@ where
htlc: HashedTimelockContract,
current_fee_rate: FeeRate,
consolidate_fee_rate: FeeRate,
+ additional_utxo_infos: &BTreeMap,
) -> WalletResult {
let latest_median_time = self.latest_median_time;
- self.for_account_rw_unlocked_and_check_tx(account_index, |account, db_tx| {
- account.create_htlc_tx(
- db_tx,
- output_value,
- htlc,
- latest_median_time,
- CurrentFeeRate {
- current_fee_rate,
- consolidate_fee_rate,
- },
- )
- })
+ self.for_account_rw_unlocked_and_check_tx(
+ account_index,
+ additional_utxo_infos,
+ |account, db_tx| {
+ account.create_htlc_tx(
+ db_tx,
+ output_value,
+ htlc,
+ latest_median_time,
+ CurrentFeeRate {
+ current_fee_rate,
+ consolidate_fee_rate,
+ },
+ )
+ },
+ )
}
pub fn sign_raw_transaction(
&mut self,
account_index: U31,
- tx: TransactionToSign,
+ ptx: PartiallySignedTransaction,
) -> WalletResult<(
PartiallySignedTransaction,
Vec,
Vec,
)> {
- let latest_median_time = self.latest_median_time;
self.for_account_rw_unlocked(
account_index,
|account, db_tx, chain_config, signer_provider| {
- let ptx = match tx {
- TransactionToSign::Partial(ptx) => ptx,
- TransactionToSign::Tx(tx) => {
- account.tx_to_partially_signed_tx(tx, latest_median_time)?
- }
- };
let mut signer =
signer_provider.provide(Arc::new(chain_config.clone()), account_index);
@@ -1997,6 +2078,18 @@ where
}
}
+fn to_token_additional_info(
+ token_info: &UnconfirmedTokenInfo,
+) -> BTreeMap {
+ BTreeMap::from_iter([(
+ PoolOrTokenId::TokenId(token_info.token_id()),
+ UtxoAdditionalInfo::TokenInfo(TokenAdditionalInfo {
+ num_decimals: token_info.num_decimals(),
+ ticker: token_info.token_ticker().to_vec(),
+ }),
+ )])
+}
+
impl Wallet
where
B: storage::Backend + 'static,
@@ -2035,17 +2128,21 @@ where
stake_pool_arguments: StakePoolDataArguments,
) -> WalletResult {
let latest_median_time = self.latest_median_time;
- self.for_account_rw_unlocked_and_check_tx(account_index, |account, db_tx| {
- account.create_stake_pool_tx(
- db_tx,
- stake_pool_arguments,
- latest_median_time,
- CurrentFeeRate {
- current_fee_rate,
- consolidate_fee_rate,
- },
- )
- })
+ self.for_account_rw_unlocked_and_check_tx(
+ account_index,
+ &BTreeMap::new(),
+ |account, db_tx| {
+ account.create_stake_pool_tx(
+ db_tx,
+ stake_pool_arguments,
+ latest_median_time,
+ CurrentFeeRate {
+ current_fee_rate,
+ consolidate_fee_rate,
+ },
+ )
+ },
+ )
}
pub fn get_pos_gen_block_data(
&self,
diff --git a/wallet/src/wallet/tests.rs b/wallet/src/wallet/tests.rs
index 6958280a8d..d7be41b0fe 100644
--- a/wallet/src/wallet/tests.rs
+++ b/wallet/src/wallet/tests.rs
@@ -54,6 +54,10 @@ use test_utils::random::{make_seedable_rng, Seed};
use wallet_storage::{schema, WalletStorageEncryptionRead};
use wallet_types::{
account_info::DEFAULT_ACCOUNT_INDEX,
+ partially_signed_transaction::{
+ PartiallySignedTransaction, PartiallySignedTransactionCreationError, UtxoAdditionalInfo,
+ UtxoWithAdditionalInfo,
+ },
seed_phrase::{PassPhrase, StoreSeedPhrase},
utxo_types::{UtxoState, UtxoType},
};
@@ -994,6 +998,7 @@ fn wallet_accounts_creation() {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
@@ -1153,6 +1158,7 @@ fn locked_wallet_cant_sign_transaction(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
),
Err(WalletError::DatabaseError(
wallet_storage::Error::WalletLocked
@@ -1170,6 +1176,7 @@ fn locked_wallet_cant_sign_transaction(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
} else {
@@ -1199,6 +1206,7 @@ fn locked_wallet_cant_sign_transaction(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
}
@@ -1226,6 +1234,7 @@ fn wallet_get_transaction(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
@@ -1285,6 +1294,7 @@ fn wallet_list_mainchain_transactions(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
@@ -1307,6 +1317,7 @@ fn wallet_list_mainchain_transactions(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
let spend_from_tx_id = tx.transaction().get_id();
@@ -1361,6 +1372,7 @@ fn wallet_transaction_with_fees(#[case] seed: Seed) {
BTreeMap::new(),
very_big_feerate,
very_big_feerate,
+ &BTreeMap::new(),
)
.unwrap_err();
@@ -1388,6 +1400,7 @@ fn wallet_transaction_with_fees(#[case] seed: Seed) {
BTreeMap::new(),
feerate,
feerate,
+ &BTreeMap::new(),
)
.unwrap();
@@ -1474,6 +1487,7 @@ fn spend_from_user_specified_utxos(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap_err();
assert_eq!(err, WalletError::CannotFindUtxo(missing_utxo.clone()));
@@ -1487,7 +1501,7 @@ fn spend_from_user_specified_utxos(#[case] seed: Seed) {
let selected_utxos = utxos
.iter()
- .map(|(outpoint, _, _)| outpoint)
+ .map(|(outpoint, _)| outpoint)
.take(rng.gen_range(1..utxos.len()))
.cloned()
.collect_vec();
@@ -1500,6 +1514,7 @@ fn spend_from_user_specified_utxos(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
@@ -1537,6 +1552,7 @@ fn spend_from_user_specified_utxos(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap_err();
@@ -1619,7 +1635,7 @@ fn create_stake_pool_and_list_pool_ids(#[case] seed: Seed) {
)
.unwrap();
assert_eq!(create_stake_pool_utxos.len(), 1);
- let (_, output, _) = create_stake_pool_utxos.pop().unwrap();
+ let (_, output) = create_stake_pool_utxos.pop().unwrap();
match output {
TxOutput::CreateStakePool(id, data) => {
assert_eq!(id, *pool_id);
@@ -1767,6 +1783,7 @@ fn send_to_unknown_delegation(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
@@ -1901,6 +1918,7 @@ fn create_spend_from_delegations(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
@@ -2088,10 +2106,12 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
let amount_fraction = (block1_amount.into_atoms() - NETWORK_FEE) / 10;
let mut token_amount_to_issue = Amount::from_atoms(rng.gen_range(1..amount_fraction));
+ let mut number_of_decimals = rng.gen_range(1..18);
+ let token_ticker = "XXXX".as_bytes().to_vec();
let (issued_token_id, token_issuance_transaction) = if issue_fungible_token {
let token_issuance = TokenIssuanceV1 {
- token_ticker: "XXXX".as_bytes().to_vec(),
- number_of_decimals: rng.gen_range(1..18),
+ token_ticker: token_ticker.clone(),
+ number_of_decimals,
metadata_uri: "http://uri".as_bytes().to_vec(),
total_supply: common::chain::tokens::TokenTotalSupply::Unlimited,
authority: address2.as_object().clone(),
@@ -2128,7 +2148,7 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
.unwrap();
let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info).unwrap();
let mint_transaction = wallet
.mint_tokens(
DEFAULT_ACCOUNT_INDEX,
@@ -2145,6 +2165,7 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
vec![token_issuance_transaction, mint_transaction],
)
} else {
+ number_of_decimals = 0;
token_amount_to_issue = Amount::from_atoms(1);
let (issued_token_id, token_issuance_transaction) = wallet
.issue_new_nft(
@@ -2154,7 +2175,7 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
creator: None,
name: "Name".as_bytes().to_vec(),
description: "SomeNFT".as_bytes().to_vec(),
- ticker: "XXXX".as_bytes().to_vec(),
+ ticker: token_ticker.clone(),
icon_uri: DataOrNoVec::from(None),
additional_metadata_uri: DataOrNoVec::from(None),
media_uri: DataOrNoVec::from(None),
@@ -2199,6 +2220,13 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
Destination::PublicKeyHash(some_other_address),
);
+ let additional_info = BTreeMap::from_iter([(
+ PoolOrTokenId::TokenId(*token_id),
+ UtxoAdditionalInfo::TokenInfo(TokenAdditionalInfo {
+ num_decimals: number_of_decimals,
+ ticker: token_ticker.clone(),
+ }),
+ )]);
let transfer_tokens_transaction = wallet
.create_transaction_to_addresses(
DEFAULT_ACCOUNT_INDEX,
@@ -2207,6 +2235,7 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &additional_info,
)
.unwrap();
wallet
@@ -2260,6 +2289,7 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &additional_info,
)
.err()
.unwrap();
@@ -2304,13 +2334,15 @@ fn check_tokens_v0_are_ignored(#[case] seed: Seed) {
assert_eq!(coin_balance, block1_amount);
let address2 = wallet.get_new_address(DEFAULT_ACCOUNT_INDEX).unwrap().1;
+ let token_ticker = "XXXX".as_bytes().to_vec();
+ let number_of_decimals = rng.gen_range(1..18);
let result = wallet.create_transaction_to_addresses(
DEFAULT_ACCOUNT_INDEX,
[TxOutput::Transfer(
OutputValue::TokenV0(Box::new(TokenData::TokenIssuance(Box::new(
TokenIssuanceV0 {
- token_ticker: "XXXX".as_bytes().to_vec(),
- number_of_decimals: rng.gen_range(1..18),
+ token_ticker,
+ number_of_decimals,
metadata_uri: "http://uri".as_bytes().to_vec(),
amount_to_issue: Amount::from_atoms(rng.gen_range(1..10000)),
},
@@ -2321,6 +2353,7 @@ fn check_tokens_v0_are_ignored(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
);
matches!(
@@ -2400,8 +2433,9 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
token_issuance.authority,
);
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
let amount_to_mint = Amount::from_atoms(rng.gen_range(1..=fixed_max_amount.into_atoms()));
let mint_tx = wallet
@@ -2417,8 +2451,9 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
let _ = create_block(&chain_config, &mut wallet, vec![mint_tx], block2_amount, 2);
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
let freeze_tx = wallet
.freeze_token(
@@ -2432,8 +2467,9 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
wallet.add_unconfirmed_tx(freeze_tx.clone(), &WalletEventsNoOp).unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.check_can_freeze().unwrap_err(),
@@ -2459,8 +2495,9 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
wallet.add_unconfirmed_tx(unfreeze_tx.clone(), &WalletEventsNoOp).unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
unconfirmed_token_info.check_can_freeze().unwrap();
assert_eq!(
@@ -2478,8 +2515,9 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
.abandon_transaction(DEFAULT_ACCOUNT_INDEX, freeze_tx.transaction().get_id())
.unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
unconfirmed_token_info.check_can_freeze().unwrap();
assert_eq!(
@@ -2500,8 +2538,9 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
3,
);
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -2532,6 +2571,13 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
Destination::PublicKeyHash(some_other_address),
);
+ let additional_info = BTreeMap::from_iter([(
+ PoolOrTokenId::TokenId(issued_token_id),
+ UtxoAdditionalInfo::TokenInfo(TokenAdditionalInfo {
+ num_decimals: unconfirmed_token_info.num_decimals(),
+ ticker: unconfirmed_token_info.token_ticker().to_vec(),
+ }),
+ )]);
let transfer_tokens_transaction = wallet
.create_transaction_to_addresses(
DEFAULT_ACCOUNT_INDEX,
@@ -2540,6 +2586,7 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &additional_info,
)
.unwrap();
@@ -2548,8 +2595,9 @@ fn freeze_and_unfreeze_tokens(#[case] seed: Seed) {
.unwrap();
wallet.add_unconfirmed_tx(freeze_tx.clone(), &WalletEventsNoOp).unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.check_can_freeze().unwrap_err(),
@@ -2683,8 +2731,9 @@ fn change_token_supply_fixed(#[case] seed: Seed) {
token_issuance.authority,
);
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.authority().unwrap(),
@@ -2715,8 +2764,9 @@ fn change_token_supply_fixed(#[case] seed: Seed) {
wallet.add_unconfirmed_tx(mint_transaction.clone(), &WalletEventsNoOp).unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
// Try to mint more then the fixed maximum
let leftover = (fixed_max_amount - token_amount_to_mint).unwrap();
@@ -2761,8 +2811,9 @@ fn change_token_supply_fixed(#[case] seed: Seed) {
)
.unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -2784,8 +2835,9 @@ fn change_token_supply_fixed(#[case] seed: Seed) {
);
token_info.circulating_supply = unconfirmed_token_info.current_supply().unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -2828,8 +2880,9 @@ fn change_token_supply_fixed(#[case] seed: Seed) {
wallet
.add_unconfirmed_tx(unmint_transaction.clone(), &WalletEventsNoOp)
.unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
let _ = create_block(
&chain_config,
@@ -2840,8 +2893,9 @@ fn change_token_supply_fixed(#[case] seed: Seed) {
);
token_info.circulating_supply = unconfirmed_token_info.current_supply().unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -2931,8 +2985,9 @@ fn change_token_supply_unlimited(#[case] seed: Seed) {
token_issuance.authority,
);
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.authority().unwrap(),
@@ -2962,8 +3017,9 @@ fn change_token_supply_unlimited(#[case] seed: Seed) {
.unwrap();
wallet.add_unconfirmed_tx(mint_transaction.clone(), &WalletEventsNoOp).unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
let _ = create_block(
&chain_config,
@@ -2974,8 +3030,9 @@ fn change_token_supply_unlimited(#[case] seed: Seed) {
);
token_info.circulating_supply = unconfirmed_token_info.current_supply().unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -3017,8 +3074,9 @@ fn change_token_supply_unlimited(#[case] seed: Seed) {
wallet
.add_unconfirmed_tx(unmint_transaction.clone(), &WalletEventsNoOp)
.unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
let _ = create_block(
&chain_config,
@@ -3029,8 +3087,9 @@ fn change_token_supply_unlimited(#[case] seed: Seed) {
);
token_info.circulating_supply = unconfirmed_token_info.current_supply().unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -3120,8 +3179,9 @@ fn change_and_lock_token_supply_lockable(#[case] seed: Seed) {
token_issuance.authority,
);
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.authority().unwrap(),
@@ -3150,8 +3210,9 @@ fn change_and_lock_token_supply_lockable(#[case] seed: Seed) {
)
.unwrap();
wallet.add_unconfirmed_tx(mint_transaction.clone(), &WalletEventsNoOp).unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
let _ = create_block(
&chain_config,
@@ -3162,8 +3223,9 @@ fn change_and_lock_token_supply_lockable(#[case] seed: Seed) {
);
token_info.circulating_supply = unconfirmed_token_info.current_supply().unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -3206,8 +3268,9 @@ fn change_and_lock_token_supply_lockable(#[case] seed: Seed) {
wallet
.add_unconfirmed_tx(unmint_transaction.clone(), &WalletEventsNoOp)
.unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
let _ = create_block(
&chain_config,
@@ -3218,8 +3281,9 @@ fn change_and_lock_token_supply_lockable(#[case] seed: Seed) {
);
token_info.circulating_supply = unconfirmed_token_info.current_supply().unwrap();
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -3250,8 +3314,9 @@ fn change_and_lock_token_supply_lockable(#[case] seed: Seed) {
);
token_info.is_locked = true;
- let unconfirmed_token_info =
- wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
+ let unconfirmed_token_info = wallet
+ .get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, token_info.clone())
+ .unwrap();
assert_eq!(
unconfirmed_token_info.get_next_nonce().unwrap(),
@@ -3369,6 +3434,7 @@ fn lock_then_transfer(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
wallet
@@ -3490,6 +3556,7 @@ fn wallet_multiple_transactions_in_single_block(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
wallet.add_unconfirmed_tx(transaction.clone(), &WalletEventsNoOp).unwrap();
@@ -3581,6 +3648,7 @@ fn wallet_scan_multiple_transactions_from_mempool(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
@@ -3616,6 +3684,7 @@ fn wallet_scan_multiple_transactions_from_mempool(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
wallet.add_unconfirmed_tx(transaction.clone(), &WalletEventsNoOp).unwrap();
@@ -3655,6 +3724,7 @@ fn wallet_scan_multiple_transactions_from_mempool(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap_err();
assert_eq!(
@@ -3681,6 +3751,7 @@ fn wallet_scan_multiple_transactions_from_mempool(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
wallet.add_unconfirmed_tx(transaction.clone(), &WalletEventsNoOp).unwrap();
@@ -3765,6 +3836,7 @@ fn wallet_abandone_transactions(#[case] seed: Seed) {
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
wallet
@@ -4082,7 +4154,7 @@ fn decommission_pool_request_wrong_account(#[case] seed: Seed) {
assert!(!decommission_partial_tx.all_signatures_available());
matches!(
decommission_partial_tx.into_signed_tx().unwrap_err(),
- TransactionCreationError::FailedToConvertPartiallySignedTx(_)
+ PartiallySignedTransactionCreationError::FailedToConvertPartiallySignedTx(_)
);
}
@@ -4103,7 +4175,8 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
// Generate a new block which sends reward to the wallet
let block1_amount = Amount::from_atoms(rng.gen_range(NETWORK_FEE + 100..NETWORK_FEE + 10000));
- let _ = create_block(&chain_config, &mut wallet, vec![], block1_amount, 0);
+ let (addr, _) = create_block(&chain_config, &mut wallet, vec![], block1_amount, 0);
+ let utxo = make_address_output(addr.clone(), block1_amount);
let pool_ids = wallet.get_pool_ids(acc_0_index, WalletPoolsFilter::All).unwrap();
assert!(pool_ids.is_empty());
@@ -4134,8 +4207,19 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
// remove the signatures and try to sign it again
let tx = stake_pool_transaction.transaction().clone();
+ let inps = tx.inputs().len();
+ let outs = tx.outputs().len();
+ let ptx = PartiallySignedTransaction::new(
+ tx,
+ vec![None; inps],
+ vec![Some(UtxoWithAdditionalInfo::new(utxo, None))],
+ vec![Some(addr.into_object())],
+ None,
+ vec![None; outs],
+ )
+ .unwrap();
let stake_pool_transaction = wallet
- .sign_raw_transaction(acc_0_index, TransactionToSign::Tx(tx))
+ .sign_raw_transaction(acc_0_index, ptx)
.unwrap()
.0
.into_signed_tx()
@@ -4167,20 +4251,14 @@ fn sign_decommission_pool_request_between_accounts(#[case] seed: Seed) {
// Try to sign decommission request with wrong account
let sign_from_acc0_res = wallet
- .sign_raw_transaction(
- acc_0_index,
- TransactionToSign::Partial(decommission_partial_tx.clone()),
- )
+ .sign_raw_transaction(acc_0_index, decommission_partial_tx.clone())
.unwrap()
.0;
// the tx is still not fully signed
assert!(!sign_from_acc0_res.all_signatures_available());
let signed_tx = wallet
- .sign_raw_transaction(
- acc_1_index,
- TransactionToSign::Partial(decommission_partial_tx),
- )
+ .sign_raw_transaction(acc_1_index, decommission_partial_tx)
.unwrap()
.0
.into_signed_tx()
@@ -4263,10 +4341,7 @@ fn sign_decommission_pool_request_cold_wallet(#[case] seed: Seed) {
// sign the tx with cold wallet
let partially_signed_transaction = cold_wallet
- .sign_raw_transaction(
- DEFAULT_ACCOUNT_INDEX,
- TransactionToSign::Partial(decommission_partial_tx),
- )
+ .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, decommission_partial_tx)
.unwrap()
.0;
assert!(partially_signed_transaction.all_signatures_available());
@@ -4274,10 +4349,7 @@ fn sign_decommission_pool_request_cold_wallet(#[case] seed: Seed) {
// sign it with the hot wallet should leave the signatures in place even if it can't find the
// destinations for the inputs
let partially_signed_transaction = hot_wallet
- .sign_raw_transaction(
- DEFAULT_ACCOUNT_INDEX,
- TransactionToSign::Partial(partially_signed_transaction),
- )
+ .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, partially_signed_transaction)
.unwrap()
.0;
assert!(partially_signed_transaction.all_signatures_available());
@@ -4432,15 +4504,13 @@ fn sign_send_request_cold_wallet(#[case] seed: Seed) {
[(Currency::Coin, cold_wallet_address.clone())].into(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
// Try to sign request with the hot wallet
let tx = hot_wallet
- .sign_raw_transaction(
- DEFAULT_ACCOUNT_INDEX,
- TransactionToSign::Partial(send_req.clone()),
- )
+ .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, send_req.clone())
.unwrap()
.0;
// the tx is not fully signed
@@ -4448,7 +4518,7 @@ fn sign_send_request_cold_wallet(#[case] seed: Seed) {
// sign the tx with cold wallet
let signed_tx = cold_wallet
- .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, TransactionToSign::Partial(send_req))
+ .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, send_req)
.unwrap()
.0
.into_signed_tx()
@@ -4488,7 +4558,7 @@ fn sign_send_request_cold_wallet(#[case] seed: Seed) {
.unwrap();
assert_eq!(utxos.len(), 1);
- let (_, output, _) = utxos.pop().unwrap();
+ let (_, output) = utxos.pop().unwrap();
matches!(output, TxOutput::Transfer(OutputValue::Coin(value), dest)
if value == balance && dest == cold_wallet_address.into_object());
@@ -4537,6 +4607,7 @@ fn test_not_exhaustion_of_keys(#[case] seed: Seed) {
[].into(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
}
@@ -4670,41 +4741,40 @@ fn test_add_standalone_multisig(#[case] seed: Seed) {
)],
)
.unwrap();
+ let outs = tx.outputs().len();
+ let spend_multisig_tx = PartiallySignedTransaction::new(
+ spend_multisig_tx,
+ vec![None; 1],
+ vec![Some(UtxoWithAdditionalInfo::new(tx.outputs()[0].clone(), None))],
+ vec![Some(multisig_address.as_object().clone())],
+ None,
+ vec![None; outs],
+ )
+ .unwrap();
// sign it with wallet1
- let (ptx, _, statuses) = wallet1
- .sign_raw_transaction(
- DEFAULT_ACCOUNT_INDEX,
- TransactionToSign::Tx(spend_multisig_tx),
- )
- .unwrap();
+ let (ptx, _, statuses) =
+ wallet1.sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, spend_multisig_tx).unwrap();
// check it is still not fully signed
assert!(ptx.all_signatures_available());
assert!(!statuses.iter().all(|s| *s == SignatureStatus::FullySigned));
// try to sign it with wallet1 again
- let (ptx, _, statuses) = wallet1
- .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, TransactionToSign::Partial(ptx))
- .unwrap();
+ let (ptx, _, statuses) = wallet1.sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, ptx).unwrap();
// check it is still not fully signed
assert!(ptx.all_signatures_available());
assert!(!statuses.iter().all(|s| *s == SignatureStatus::FullySigned));
// try to sign it with wallet2 but wallet2 does not have the multisig added as standalone
- let ptx = wallet2
- .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, TransactionToSign::Partial(ptx))
- .unwrap()
- .0;
+ let ptx = wallet2.sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, ptx).unwrap().0;
// add it to wallet2 as well
wallet2.add_standalone_multisig(DEFAULT_ACCOUNT_INDEX, challenge, None).unwrap();
// now we can sign it
- let (ptx, _, statuses) = wallet2
- .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, TransactionToSign::Partial(ptx))
- .unwrap();
+ let (ptx, _, statuses) = wallet2.sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, ptx).unwrap();
// now it is fully signed
assert!(ptx.all_signatures_available());
@@ -4772,6 +4842,7 @@ fn create_htlc_and_spend(#[case] seed: Seed) {
htlc.clone(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
let create_htlc_tx_id = create_htlc_tx.transaction().get_id();
@@ -4807,7 +4878,7 @@ fn create_htlc_and_spend(#[case] seed: Seed) {
)
.unwrap();
assert_eq!(wallet2_utxos.len(), 1);
- let (_, output, _) = wallet2_utxos.pop().unwrap();
+ let (_, output) = wallet2_utxos.pop().unwrap();
match output {
TxOutput::Htlc(actual_output_value, actual_htlc) => {
assert_eq!(actual_output_value, output_value);
@@ -4823,19 +4894,25 @@ fn create_htlc_and_spend(#[case] seed: Seed) {
vec![TxOutput::Transfer(output_value, address2.into_object())],
)
.unwrap();
- let spend_utxos = vec![create_htlc_tx.transaction().outputs().first().cloned()];
+ let spend_utxos = vec![create_htlc_tx
+ .transaction()
+ .outputs()
+ .first()
+ .cloned()
+ .map(|out| UtxoWithAdditionalInfo::new(out, None))];
+ let outs = create_htlc_tx.outputs().len();
let spend_ptx = PartiallySignedTransaction::new(
spend_tx,
vec![None],
spend_utxos,
vec![Some(spend_key.into_object())],
Some(vec![Some(secret)]),
+ vec![None; outs],
)
.unwrap();
- let (spend_ptx, _, new_statuses) = wallet2
- .sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, TransactionToSign::Partial(spend_ptx))
- .unwrap();
+ let (spend_ptx, _, new_statuses) =
+ wallet2.sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, spend_ptx).unwrap();
assert_eq!(vec![SignatureStatus::FullySigned], new_statuses);
let spend_tx = spend_ptx.into_signed_tx().unwrap();
@@ -4911,6 +4988,7 @@ fn create_htlc_and_refund(#[case] seed: Seed) {
htlc.clone(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
+ &BTreeMap::new(),
)
.unwrap();
let create_htlc_tx_id = create_htlc_tx.transaction().get_id();
@@ -4921,13 +4999,20 @@ fn create_htlc_and_refund(#[case] seed: Seed) {
vec![TxOutput::Transfer(output_value, address1.into_object())],
)
.unwrap();
- let refund_utxos = vec![create_htlc_tx.transaction().outputs().first().cloned()];
+ let refund_utxos = vec![create_htlc_tx
+ .transaction()
+ .outputs()
+ .first()
+ .cloned()
+ .map(|out| UtxoWithAdditionalInfo::new(out, None))];
+ let outs = create_htlc_tx.outputs().len();
let refund_ptx = PartiallySignedTransaction::new(
refund_tx,
vec![None],
refund_utxos,
vec![Some(refund_key)],
None,
+ vec![None; outs],
)
.unwrap();
@@ -4963,12 +5048,8 @@ fn create_htlc_and_refund(#[case] seed: Seed) {
.unwrap();
assert_eq!(wallet2_multisig_utxos.len(), 1);
- let (refund_ptx, prev_statuses, new_statuses) = wallet2
- .sign_raw_transaction(
- DEFAULT_ACCOUNT_INDEX,
- TransactionToSign::Partial(refund_ptx),
- )
- .unwrap();
+ let (refund_ptx, prev_statuses, new_statuses) =
+ wallet2.sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, refund_ptx).unwrap();
assert_eq!(vec![SignatureStatus::NotSigned], prev_statuses);
assert_eq!(
@@ -4979,12 +5060,8 @@ fn create_htlc_and_refund(#[case] seed: Seed) {
new_statuses
);
- let (refund_ptx, prev_statuses, new_statuses) = wallet1
- .sign_raw_transaction(
- DEFAULT_ACCOUNT_INDEX,
- TransactionToSign::Partial(refund_ptx),
- )
- .unwrap();
+ let (refund_ptx, prev_statuses, new_statuses) =
+ wallet1.sign_raw_transaction(DEFAULT_ACCOUNT_INDEX, refund_ptx).unwrap();
assert_eq!(
vec![SignatureStatus::PartialMultisig {
required_signatures: 2,
diff --git a/wallet/types/Cargo.toml b/wallet/types/Cargo.toml
index a1141ddf60..90d5761755 100644
--- a/wallet/types/Cargo.toml
+++ b/wallet/types/Cargo.toml
@@ -10,6 +10,7 @@ rust-version.workspace = true
[dependencies]
common = { path = "../../common/" }
crypto = { path = "../../crypto/" }
+tx-verifier = { path = "../../chainstate/tx-verifier" }
rpc-description = { path = "../../rpc/description" }
randomness = { path = "../../randomness" }
serialization = { path = "../../serialization" }
diff --git a/wallet/types/src/lib.rs b/wallet/types/src/lib.rs
index 8c050b2fd1..8e5cf2b401 100644
--- a/wallet/types/src/lib.rs
+++ b/wallet/types/src/lib.rs
@@ -17,6 +17,7 @@ pub mod account_id;
pub mod account_info;
pub mod chain_info;
pub mod keys;
+pub mod partially_signed_transaction;
pub mod seed_phrase;
pub mod signature_status;
pub mod utxo_types;
diff --git a/common/src/chain/transaction/partially_signed_transaction.rs b/wallet/types/src/partially_signed_transaction.rs
similarity index 50%
rename from common/src/chain/transaction/partially_signed_transaction.rs
rename to wallet/types/src/partially_signed_transaction.rs
index 3b1e585099..87fea03ee5 100644
--- a/common/src/chain/transaction/partially_signed_transaction.rs
+++ b/wallet/types/src/partially_signed_transaction.rs
@@ -13,53 +13,128 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use super::{
- htlc::HtlcSecret,
- signature::{inputsig::InputWitness, Signable, Transactable},
- Destination, Transaction, TxOutput,
+use common::{
+ chain::{
+ htlc::HtlcSecret,
+ signature::{inputsig::InputWitness, Signable, Transactable},
+ Destination, SignedTransaction, Transaction, TransactionCreationError, TxInput, TxOutput,
+ },
+ primitives::Amount,
};
-use crate::chain::{SignedTransaction, TransactionCreationError, TxInput};
use serialization::{Decode, Encode};
+use thiserror::Error;
+use tx_verifier::input_check::signature_only_check::SignatureOnlyVerifiable;
use utils::ensure;
+#[derive(Error, Debug, Clone, PartialEq, Eq)]
+pub enum PartiallySignedTransactionCreationError {
+ #[error("Failed to convert partially signed tx to signed")]
+ FailedToConvertPartiallySignedTx(PartiallySignedTransaction),
+ #[error("The number of output additional infos does not match the number of outputs")]
+ InvalidOutputAdditionalInfoCount,
+ #[error("Failed to create transaction: {0}")]
+ TxCreationError(#[from] TransactionCreationError),
+ #[error("The number of input utxos does not match the number of inputs")]
+ InvalidInputUtxosCount,
+ #[error("The number of destinations does not match the number of inputs")]
+ InvalidDestinationsCount,
+ #[error("The number of htlc secrets does not match the number of inputs")]
+ InvalidHtlcSecretsCount,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Encode, Decode)]
+pub struct TokenAdditionalInfo {
+ pub num_decimals: u8,
+ pub ticker: Vec,
+}
+
+/// Additional info for UTXOs
+#[derive(Debug, Eq, PartialEq, Clone, Encode, Decode)]
+pub enum UtxoAdditionalInfo {
+ TokenInfo(TokenAdditionalInfo),
+ PoolInfo {
+ staker_balance: Amount,
+ },
+ AnyoneCanTake {
+ ask: Option,
+ give: Option,
+ },
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Encode, Decode)]
+pub struct UtxoWithAdditionalInfo {
+ pub utxo: TxOutput,
+ pub additional_info: Option,
+}
+
+impl UtxoWithAdditionalInfo {
+ pub fn new(utxo: TxOutput, additional_info: Option) -> Self {
+ Self {
+ utxo,
+ additional_info,
+ }
+ }
+}
+
#[derive(Debug, Eq, PartialEq, Clone, Encode, Decode)]
pub struct PartiallySignedTransaction {
tx: Transaction,
witnesses: Vec