Skip to content

Commit

Permalink
bug: cannot fetch mint transactions (#1203)
Browse files Browse the repository at this point in the history
closes #1199 

Mint transactions can now be fetched through the `Provider`. Implemented
what made sense for `Mint`, left the rest as `unimplemented!`. Without
some hefty redesign don't see what other option is there but to violate
the LSP (L for Liskov).

Decided to wrap `Mint`, so that users may extract the id, outputs, etc,
without having to know about the various traits from fuel.

### Checklist
- [x] I have linked to any relevant issues.
- [ ] I have updated the documentation.
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added necessary labels.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.
  • Loading branch information
segfault-magnet authored Nov 17, 2023
1 parent 5793398 commit b2676a0
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 156 deletions.
3 changes: 1 addition & 2 deletions packages/fuels-code-gen/src/program_bindings/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ use itertools::Itertools;
use proc_macro2::{Ident, TokenStream};
use quote::quote;

use super::resolved_type::GenericType;
use crate::{
error::Result,
program_bindings::resolved_type::{ResolvedType, TypeResolver},
program_bindings::resolved_type::{GenericType, ResolvedType, TypeResolver},
utils::{self, safe_ident, TypePath},
};

Expand Down
3 changes: 1 addition & 2 deletions packages/fuels-core/src/codec/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ use std::{

use fuel_tx::{ContractId, Receipt};

use super::ABIDecoder;
use crate::{
codec::DecoderConfig,
codec::{ABIDecoder, DecoderConfig},
traits::{Parameterize, Tokenizable},
types::{
errors::{error, Error, Result},
Expand Down
3 changes: 2 additions & 1 deletion packages/fuels-core/src/types/transaction_builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,20 @@ use fuel_tx::{
use fuel_types::{bytes::padded_len_usize, canonical::Serialize, Bytes32, ChainId, Salt};
use zeroize::{Zeroize, ZeroizeOnDrop};

use super::{chain_info::ChainInfo, node_info::NodeInfo};
use crate::{
constants::{
BASE_ASSET_ID, DEFAULT_CREATE_WITNESS_LIMIT, DEFAULT_SCRIPT_WITNESS_LIMIT, WORD_SIZE,
},
offsets,
types::{
bech32::Bech32Address,
chain_info::ChainInfo,
coin::Coin,
coin_type::CoinType,
errors::{error, Result},
input::Input,
message::Message,
node_info::NodeInfo,
transaction::{
CreateTransaction, EstimablePredicates, ScriptTransaction, Transaction, TxPolicies,
},
Expand Down
3 changes: 1 addition & 2 deletions packages/fuels-core/src/types/wrappers/coin_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
use fuel_core_client::client::types::CoinType as ClientCoinType;
use fuel_types::AssetId;

use super::coin_type_id::CoinTypeId;
use crate::{
constants::BASE_ASSET_ID,
types::{bech32::Bech32Address, coin::Coin, message::Message},
types::{bech32::Bech32Address, coin::Coin, coin_type_id::CoinTypeId, message::Message},
};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down
203 changes: 55 additions & 148 deletions packages/fuels-core/src/types/wrappers/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::{collections::HashMap, fmt::Debug};

use fuel_tx::{
field::{
GasPrice, Inputs, Maturity, Outputs, Script as ScriptField, ScriptData, ScriptGasLimit,
Witnesses,
GasPrice, Inputs, Maturity, MintAmount, MintAssetId, Outputs, Script as ScriptField,
ScriptData, ScriptGasLimit, Witnesses,
},
input::{
coin::{CoinPredicate, CoinSigned},
Expand All @@ -12,7 +12,7 @@ use fuel_tx::{
},
},
Buildable, Bytes32, Cacheable, Chargeable, ConsensusParameters, Create, FormatValidityChecks,
Input, Output, Salt as FuelSalt, Script, StorageSlot, Transaction as FuelTransaction,
Input, Mint, Output, Salt as FuelSalt, Script, StorageSlot, Transaction as FuelTransaction,
TransactionFee, UniqueIdentifier, Witness,
};
use fuel_types::{AssetId, ChainId};
Expand All @@ -24,8 +24,56 @@ use crate::{
types::{bech32::Bech32Address, errors::error, Result},
};

#[derive(Default, Debug, Copy, Clone)]
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct MintTransaction {
tx: Box<Mint>,
}

impl From<MintTransaction> for FuelTransaction {
fn from(mint: MintTransaction) -> Self {
(*mint.tx).into()
}
}

impl From<MintTransaction> for Mint {
fn from(tx: MintTransaction) -> Self {
*tx.tx
}
}

impl From<Mint> for MintTransaction {
fn from(tx: Mint) -> Self {
Self { tx: Box::new(tx) }
}
}

impl MintTransaction {
pub fn check_without_signatures(
&self,
block_height: u32,
consensus_parameters: &ConsensusParameters,
) -> Result<()> {
Ok(self
.tx
.check_without_signatures(block_height.into(), consensus_parameters)?)
}
#[must_use]
pub fn id(&self, chain_id: ChainId) -> Bytes32 {
self.tx.id(&chain_id)
}

#[must_use]
pub fn mint_asset_id(&self) -> &AssetId {
self.tx.mint_asset_id()
}

#[must_use]
pub fn mint_amount(&self) -> u64 {
*self.tx.mint_amount()
}
}

#[derive(Default, Debug, Copy, Clone)]
//ANCHOR: tx_policies_struct
pub struct TxPolicies {
gas_price: Option<u64>,
Expand Down Expand Up @@ -101,12 +149,13 @@ impl TxPolicies {

use fuel_tx::field::{BytecodeLength, BytecodeWitnessIndex, Salt, StorageSlots};

use super::coin_type_id::CoinTypeId;
use crate::types::coin_type_id::CoinTypeId;

#[derive(Debug, Clone)]
pub enum TransactionType {
Script(ScriptTransaction),
Create(CreateTransaction),
Mint(MintTransaction),
}

pub trait EstimablePredicates {
Expand Down Expand Up @@ -171,149 +220,7 @@ impl From<TransactionType> for FuelTransaction {
match value {
TransactionType::Script(tx) => tx.into(),
TransactionType::Create(tx) => tx.into(),
}
}
}

impl EstimablePredicates for TransactionType {
fn estimate_predicates(&mut self, consensus_parameters: &ConsensusParameters) -> Result<()> {
match self {
TransactionType::Script(tx) => tx.estimate_predicates(consensus_parameters),
TransactionType::Create(tx) => tx.estimate_predicates(consensus_parameters),
}
}
}

impl GasValidation for TransactionType {
fn validate_gas(&self, min_gas_price: u64, gas_used: u64) -> Result<()> {
match self {
TransactionType::Script(tx) => tx.validate_gas(min_gas_price, gas_used),
TransactionType::Create(tx) => tx.validate_gas(min_gas_price, gas_used),
}
}
}

impl Transaction for TransactionType {
fn fee_checked_from_tx(
&self,
consensus_parameters: &ConsensusParameters,
) -> Option<TransactionFee> {
match self {
TransactionType::Script(tx) => tx.fee_checked_from_tx(consensus_parameters),
TransactionType::Create(tx) => tx.fee_checked_from_tx(consensus_parameters),
}
}

fn max_gas(&self, consensus_parameters: &ConsensusParameters) -> u64 {
match self {
TransactionType::Script(tx) => tx.max_gas(consensus_parameters),
TransactionType::Create(tx) => tx.max_gas(consensus_parameters),
}
}

fn check_without_signatures(
&self,
block_height: u32,
consensus_parameters: &ConsensusParameters,
) -> Result<()> {
match self {
TransactionType::Script(tx) => {
tx.check_without_signatures(block_height, consensus_parameters)
}
TransactionType::Create(tx) => {
tx.check_without_signatures(block_height, consensus_parameters)
}
}
}

fn id(&self, chain_id: ChainId) -> Bytes32 {
match self {
TransactionType::Script(tx) => tx.id(chain_id),
TransactionType::Create(tx) => tx.id(chain_id),
}
}

fn maturity(&self) -> u32 {
match self {
TransactionType::Script(tx) => tx.maturity(),
TransactionType::Create(tx) => tx.maturity(),
}
}

fn with_maturity(self, maturity: u32) -> Self {
match self {
TransactionType::Script(tx) => TransactionType::Script(tx.with_maturity(maturity)),
TransactionType::Create(tx) => TransactionType::Create(tx.with_maturity(maturity)),
}
}

fn gas_price(&self) -> u64 {
match self {
TransactionType::Script(tx) => tx.gas_price(),
TransactionType::Create(tx) => tx.gas_price(),
}
}

fn with_gas_price(self, gas_price: u64) -> Self {
match self {
TransactionType::Script(tx) => TransactionType::Script(tx.with_gas_price(gas_price)),
TransactionType::Create(tx) => TransactionType::Create(tx.with_gas_price(gas_price)),
}
}

fn metered_bytes_size(&self) -> usize {
match self {
TransactionType::Script(tx) => tx.metered_bytes_size(),
TransactionType::Create(tx) => tx.metered_bytes_size(),
}
}

fn inputs(&self) -> &Vec<Input> {
match self {
TransactionType::Script(tx) => tx.inputs(),
TransactionType::Create(tx) => tx.inputs(),
}
}

fn outputs(&self) -> &Vec<Output> {
match self {
TransactionType::Script(tx) => tx.outputs(),
TransactionType::Create(tx) => tx.outputs(),
}
}

fn witnesses(&self) -> &Vec<Witness> {
match self {
TransactionType::Script(tx) => tx.witnesses(),
TransactionType::Create(tx) => tx.witnesses(),
}
}

fn is_using_predicates(&self) -> bool {
match self {
TransactionType::Script(tx) => tx.is_using_predicates(),
TransactionType::Create(tx) => tx.is_using_predicates(),
}
}

fn precompute(&mut self, chain_id: &ChainId) -> Result<()> {
match self {
TransactionType::Script(tx) => tx.precompute(chain_id),
TransactionType::Create(tx) => tx.precompute(chain_id),
}
}

fn append_witness(&mut self, witness: Witness) -> usize {
match self {
TransactionType::Script(tx) => tx.append_witness(witness),
TransactionType::Create(tx) => tx.append_witness(witness),
}
}

fn used_coins(&self) -> HashMap<(Bech32Address, AssetId), Vec<CoinTypeId>> {
match self {
TransactionType::Script(tx) => tx.used_coins(),
TransactionType::Create(tx) => tx.used_coins(),
TransactionType::Mint(tx) => tx.into(),
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl From<ClientTransactionResponse> for TransactionResponse {
let transaction = match client_response.transaction {
Transaction::Script(tx) => TransactionType::Script(ScriptTransaction::from(tx)),
Transaction::Create(tx) => TransactionType::Create(CreateTransaction::from(tx)),
Transaction::Mint(_) => unimplemented!(),
Transaction::Mint(tx) => TransactionType::Mint(tx.into()),
};

Self {
Expand Down
39 changes: 39 additions & 0 deletions packages/fuels/tests/providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,45 @@ async fn test_cache_invalidation_on_await() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn can_fetch_mint_transactions() -> Result<()> {
setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "TestContract",
project = "packages/fuels/tests/contracts/contract_test"
)),
Deploy(
name = "contract_instance",
contract = "TestContract",
wallet = "wallet"
),
);

let provider = wallet.try_provider()?;

let transactions = provider
.get_transactions(PaginationRequest {
cursor: None,
results: 100,
direction: PageDirection::Forward,
})
.await?
.results;

// TODO: remove once (fuels-rs#1093)[https://github.com/FuelLabs/fuels-rs/issues/1093] is in
// until then the type is explicitly mentioned to check that we're reexporting it through fuels
let _: ::fuels::types::transaction::MintTransaction = transactions
.into_iter()
.find_map(|tx| match tx.transaction {
TransactionType::Mint(tx) => Some(tx),
_ => None,
})
.expect("Should have had at least one mint transaction");

Ok(())
}

#[tokio::test]
async fn test_build_with_provider() -> Result<()> {
let wallet = launch_provider_and_get_wallet().await?;
Expand Down

0 comments on commit b2676a0

Please sign in to comment.