Skip to content

Commit

Permalink
add additional token info for utxos in partially signed tx
Browse files Browse the repository at this point in the history
  • Loading branch information
OBorce committed Aug 15, 2024
1 parent 562eea0 commit 51a9d60
Show file tree
Hide file tree
Showing 10 changed files with 564 additions and 247 deletions.
20 changes: 20 additions & 0 deletions common/src/chain/tokens/tokens_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,23 @@ pub fn is_token_or_nft_issuance(output: &TxOutput) -> bool {
TxOutput::IssueFungibleToken(_) | TxOutput::IssueNft(_, _, _) => true,
}
}

pub fn get_token_id_for_tx_output(output: &TxOutput, inputs: &[TxInput]) -> Option<TokenId> {
match output {
TxOutput::Transfer(v, _) | TxOutput::LockThenTransfer(v, _, _) | TxOutput::Burn(v) => {
match v {
OutputValue::Coin(_) | OutputValue::TokenV0(_) => None,
OutputValue::TokenV1(token_id, _) => Some(*token_id),
}
}
TxOutput::CreateStakePool(_, _)
| TxOutput::ProduceBlockFromStake(_, _)
| TxOutput::CreateDelegationId(_, _)
| TxOutput::DelegateStaking(_, _)
| TxOutput::DataDeposit(_)
| TxOutput::Htlc(_, _)
| TxOutput::IssueFungibleToken(_)
| TxOutput::AnyoneCanTake(_) => None,
TxOutput::IssueNft(_, _, _) => make_token_id(inputs),
}
}
4 changes: 4 additions & 0 deletions rpc/types/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ impl RpcString {
self.0
}

pub fn as_bytes(&self) -> &[u8] {
&self.0
}

pub fn try_into_string(self) -> Result<String, (Self, std::str::Utf8Error)> {
String::from_utf8(self.0).map_err(|e| {
let err = e.utf8_error();
Expand Down
16 changes: 8 additions & 8 deletions wallet/src/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ impl<K: AccountKeyChains> Account<K> {
)?;

let fees = request.get_fees();
let ptx = request.into_partially_signed_tx()?;
let ptx = request.into_partially_signed_tx(&BTreeMap::new())?;

Ok((ptx, fees))
}
Expand Down Expand Up @@ -835,7 +835,7 @@ impl<K: AccountKeyChains> Account<K> {

pub fn get_token_unconfirmed_info(
&self,
token_info: &RPCFungibleTokenInfo,
token_info: RPCFungibleTokenInfo,
) -> WalletResult<UnconfirmedTokenInfo> {
self.output_cache
.get_token_unconfirmed_info(token_info, |destination: &Destination| {
Expand Down Expand Up @@ -911,7 +911,7 @@ impl<K: AccountKeyChains> Account<K> {
median_time: BlockTimestamp,
fee_rate: CurrentFeeRate,
) -> WalletResult<SendRequest> {
let token_id = *token_info.token_id();
let token_id = token_info.token_id();
let outputs = make_mint_token_outputs(token_id, amount, address);

token_info.check_can_mint(amount)?;
Expand All @@ -938,7 +938,7 @@ impl<K: AccountKeyChains> Account<K> {
median_time: BlockTimestamp,
fee_rate: CurrentFeeRate,
) -> WalletResult<SendRequest> {
let token_id = *token_info.token_id();
let token_id = token_info.token_id();
let outputs = make_unmint_token_outputs(token_id, amount);

token_info.check_can_unmint(amount)?;
Expand All @@ -964,7 +964,7 @@ impl<K: AccountKeyChains> Account<K> {
median_time: BlockTimestamp,
fee_rate: CurrentFeeRate,
) -> WalletResult<SendRequest> {
let token_id = *token_info.token_id();
let token_id = token_info.token_id();
token_info.check_can_lock()?;

let nonce = token_info.get_next_nonce()?;
Expand Down Expand Up @@ -994,7 +994,7 @@ impl<K: AccountKeyChains> Account<K> {
let nonce = token_info.get_next_nonce()?;
let tx_input = TxInput::AccountCommand(
nonce,
AccountCommand::FreezeToken(*token_info.token_id(), is_token_unfreezable),
AccountCommand::FreezeToken(token_info.token_id(), is_token_unfreezable),
);
let authority = token_info.authority()?.clone();

Expand All @@ -1019,7 +1019,7 @@ impl<K: AccountKeyChains> Account<K> {

let nonce = token_info.get_next_nonce()?;
let tx_input =
TxInput::AccountCommand(nonce, AccountCommand::UnfreezeToken(*token_info.token_id()));
TxInput::AccountCommand(nonce, AccountCommand::UnfreezeToken(token_info.token_id()));
let authority = token_info.authority()?.clone();

self.change_token_supply_transaction(
Expand All @@ -1045,7 +1045,7 @@ impl<K: AccountKeyChains> Account<K> {
let nonce = token_info.get_next_nonce()?;
let tx_input = TxInput::AccountCommand(
nonce,
AccountCommand::ChangeTokenAuthority(*token_info.token_id(), new_authority),
AccountCommand::ChangeTokenAuthority(token_info.token_id(), new_authority),
);
let authority = token_info.authority()?.clone();

Expand Down
114 changes: 70 additions & 44 deletions wallet/src/account/output_cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ use common::{
output_value::OutputValue,
stakelock::StakePoolData,
tokens::{
is_token_or_nft_issuance, make_token_id, IsTokenFreezable, IsTokenUnfreezable,
RPCFungibleTokenInfo, RPCIsTokenFrozen, RPCTokenTotalSupply, TokenId, TokenIssuance,
TokenTotalSupply,
get_token_id_for_tx_output, make_token_id, IsTokenFreezable, IsTokenUnfreezable,
RPCFungibleTokenInfo, RPCIsTokenFrozen, RPCNonFungibleTokenInfo, RPCTokenTotalSupply,
TokenId, TokenIssuance, TokenTotalSupply,
},
AccountCommand, AccountNonce, AccountSpending, DelegationId, Destination, GenBlock,
OutPointSourceId, PoolId, Transaction, TxInput, TxOutput, UtxoOutPoint,
Expand Down Expand Up @@ -265,111 +265,133 @@ pub struct FungibleTokenInfo {
authority: Destination,
}

/// Token info from the Node + any unconfirmed Txs from this wallet
pub enum UnconfirmedTokenInfo {
OwnFungibleToken(TokenId, FungibleTokenInfo),
FungibleToken(TokenId, TokenFreezableState),
NonFungibleToken(TokenId),
/// Token info owned by this wallet
OwnFungibleToken(TokenId, FungibleTokenInfo, RPCFungibleTokenInfo),
/// Token info not owned by this wallet
FungibleToken(TokenId, TokenFreezableState, RPCFungibleTokenInfo),
/// NFT info
NonFungibleToken(TokenId, Box<RPCNonFungibleTokenInfo>),
}

impl UnconfirmedTokenInfo {
pub fn token_id(&self) -> &TokenId {
pub fn token_id(&self) -> TokenId {
match self {
Self::OwnFungibleToken(token_id, _)
| Self::FungibleToken(token_id, _)
| Self::NonFungibleToken(token_id) => token_id,
Self::OwnFungibleToken(token_id, _, _)
| Self::FungibleToken(token_id, _, _)
| Self::NonFungibleToken(token_id, _) => *token_id,
}
}

pub fn num_decimals(&self) -> u8 {
match self {
Self::OwnFungibleToken(_, _, info) | Self::FungibleToken(_, _, info) => {
info.number_of_decimals
}
Self::NonFungibleToken(_, _) => 0,
}
}

pub fn token_ticker(&self) -> &[u8] {
match self {
Self::OwnFungibleToken(_, _, info) | Self::FungibleToken(_, _, info) => {
info.token_ticker.as_bytes()
}
Self::NonFungibleToken(_, info) => info.metadata.ticker.as_bytes(),
}
}

pub fn check_can_be_used(&self) -> WalletResult<()> {
match self {
Self::OwnFungibleToken(_, state) => state.frozen.check_can_be_used(),
Self::FungibleToken(_, state) => state.check_can_be_used(),
Self::NonFungibleToken(_) => Ok(()),
Self::OwnFungibleToken(_, state, _) => state.frozen.check_can_be_used(),
Self::FungibleToken(_, state, _) => state.check_can_be_used(),
Self::NonFungibleToken(_, _) => Ok(()),
}
}

pub fn check_can_freeze(&self) -> WalletResult<()> {
match self {
Self::OwnFungibleToken(_, state) => state.frozen.check_can_freeze(),
Self::FungibleToken(token_id, _) => {
Self::OwnFungibleToken(_, state, _) => state.frozen.check_can_freeze(),
Self::FungibleToken(token_id, _, _) => {
Err(WalletError::CannotChangeNotOwnedToken(*token_id))
}
Self::NonFungibleToken(token_id) => {
Self::NonFungibleToken(token_id, _) => {
Err(WalletError::CannotChangeNonFungibleToken(*token_id))
}
}
}

pub fn check_can_unfreeze(&self) -> WalletResult<()> {
match self {
Self::OwnFungibleToken(_, state) => state.frozen.check_can_unfreeze(),
Self::FungibleToken(token_id, _) => {
Self::OwnFungibleToken(_, state, _) => state.frozen.check_can_unfreeze(),
Self::FungibleToken(token_id, _, _) => {
Err(WalletError::CannotChangeNotOwnedToken(*token_id))
}
Self::NonFungibleToken(token_id) => {
Self::NonFungibleToken(token_id, _) => {
Err(WalletError::CannotChangeNonFungibleToken(*token_id))
}
}
}

pub fn get_next_nonce(&self) -> WalletResult<AccountNonce> {
match self {
Self::OwnFungibleToken(token_id, state) => state
Self::OwnFungibleToken(token_id, state, _) => state
.last_nonce
.map_or(Some(AccountNonce::new(0)), |nonce| nonce.increment())
.ok_or(WalletError::TokenIssuanceNonceOverflow(*token_id)),
Self::FungibleToken(token_id, _) => {
Self::FungibleToken(token_id, _, _) => {
Err(WalletError::CannotChangeNotOwnedToken(*token_id))
}
Self::NonFungibleToken(token_id) => {
Self::NonFungibleToken(token_id, _) => {
Err(WalletError::CannotChangeNonFungibleToken(*token_id))
}
}
}

pub fn authority(&self) -> WalletResult<&Destination> {
match self {
Self::OwnFungibleToken(_, state) => Ok(&state.authority),
Self::FungibleToken(token_id, _) => {
Self::OwnFungibleToken(_, state, _) => Ok(&state.authority),
Self::FungibleToken(token_id, _, _) => {
Err(WalletError::CannotChangeNotOwnedToken(*token_id))
}
Self::NonFungibleToken(token_id) => {
Self::NonFungibleToken(token_id, _) => {
Err(WalletError::CannotChangeNonFungibleToken(*token_id))
}
}
}

pub fn check_can_mint(&self, amount: Amount) -> WalletResult<()> {
match self {
Self::OwnFungibleToken(_, state) => state.total_supply.check_can_mint(amount),
Self::FungibleToken(token_id, _) => {
Self::OwnFungibleToken(_, state, _) => state.total_supply.check_can_mint(amount),
Self::FungibleToken(token_id, _, _) => {
Err(WalletError::CannotChangeNotOwnedToken(*token_id))
}
Self::NonFungibleToken(token_id) => {
Self::NonFungibleToken(token_id, _) => {
Err(WalletError::CannotChangeNonFungibleToken(*token_id))
}
}
}

pub fn check_can_unmint(&self, amount: Amount) -> WalletResult<()> {
match self {
Self::OwnFungibleToken(_, state) => state.total_supply.check_can_unmint(amount),
Self::FungibleToken(token_id, _) => {
Self::OwnFungibleToken(_, state, _) => state.total_supply.check_can_unmint(amount),
Self::FungibleToken(token_id, _, _) => {
Err(WalletError::CannotChangeNotOwnedToken(*token_id))
}
Self::NonFungibleToken(token_id) => {
Self::NonFungibleToken(token_id, _) => {
Err(WalletError::CannotChangeNonFungibleToken(*token_id))
}
}
}

pub fn check_can_lock(&self) -> WalletResult<()> {
match self {
Self::OwnFungibleToken(_, state) => state.total_supply.check_can_lock(),
Self::FungibleToken(token_id, _) => {
Self::OwnFungibleToken(_, state, _) => state.total_supply.check_can_lock(),
Self::FungibleToken(token_id, _, _) => {
Err(WalletError::CannotChangeNotOwnedToken(*token_id))
}
Self::NonFungibleToken(token_id) => {
Self::NonFungibleToken(token_id, _) => {
Err(WalletError::CannotChangeNonFungibleToken(*token_id))
}
}
Expand All @@ -378,9 +400,9 @@ impl UnconfirmedTokenInfo {
#[cfg(test)]
pub fn current_supply(&self) -> Option<Amount> {
match self {
Self::OwnFungibleToken(_, state) => Some(state.total_supply.current_supply()),
Self::FungibleToken(_, _) => None,
Self::NonFungibleToken(_) => None,
Self::OwnFungibleToken(_, state, _) => Some(state.total_supply.current_supply()),
Self::FungibleToken(_, _, _) => None,
Self::NonFungibleToken(_, _) => None,
}
}
}
Expand Down Expand Up @@ -596,7 +618,7 @@ impl OutputCache {

pub fn get_token_unconfirmed_info<F: Fn(&Destination) -> bool>(
&self,
token_info: &RPCFungibleTokenInfo,
token_info: RPCFungibleTokenInfo,
is_mine: F,
) -> WalletResult<UnconfirmedTokenInfo> {
let token_data = match self.token_issuance.get(&token_info.token_id) {
Expand All @@ -605,6 +627,7 @@ impl OutputCache {
return Ok(UnconfirmedTokenInfo::FungibleToken(
token_info.token_id,
token_info.frozen.into(),
token_info,
));
}
token_data
Expand All @@ -614,6 +637,7 @@ impl OutputCache {
return Ok(UnconfirmedTokenInfo::FungibleToken(
token_info.token_id,
token_info.frozen.into(),
token_info,
));
}
};
Expand Down Expand Up @@ -646,6 +670,7 @@ impl OutputCache {
total_supply,
authority: token_data.authority.clone(),
},
token_info,
))
}

Expand Down Expand Up @@ -1112,9 +1137,9 @@ impl OutputCache {
);

let token_id = match tx {
WalletTx::Tx(tx_data) => is_token_or_nft_issuance(output)
.then_some(make_token_id(tx_data.get_transaction().inputs()))
.flatten(),
WalletTx::Tx(tx_data) => {
get_token_id_for_tx_output(output, tx_data.get_transaction().inputs())
}
WalletTx::Block(_) => None,
};

Expand Down Expand Up @@ -1182,9 +1207,10 @@ impl OutputCache {
})
.map(move |(output, outpoint)| {
let token_id = match tx {
WalletTx::Tx(tx_data) => is_token_or_nft_issuance(output)
.then_some(make_token_id(tx_data.get_transaction().inputs()))
.flatten(),
WalletTx::Tx(tx_data) => get_token_id_for_tx_output(
output,
tx_data.get_transaction().inputs(),
),
WalletTx::Block(_) => None,
};
(outpoint, (output, token_id))
Expand Down
Loading

0 comments on commit 51a9d60

Please sign in to comment.