Skip to content

Commit

Permalink
Accept Sway-native types directly and without wrappers (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
digorithm authored Mar 31, 2022
1 parent 542d4c3 commit faa128b
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 33 deletions.
40 changes: 12 additions & 28 deletions fuels-abigen-macro/tests/harness.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use fuel_tx::{AssetId, Receipt, Salt};
use fuel_tx::{AssetId, ContractId, Receipt, Salt};
use fuels_abigen_macro::abigen;
use fuels_contract::contract::Contract;
use fuels_contract::errors::Error;
Expand Down Expand Up @@ -1101,11 +1101,11 @@ async fn test_large_return_data() {
// First `value` is from `CallResponse`.
// Second `value` is from Sway `ContractId` type.
assert_eq!(
res.value.value,
[
res.value,
ContractId::from([
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
]
])
);
}

Expand Down Expand Up @@ -1319,20 +1319,15 @@ async fn test_amount_and_asset_forwarding() {
let id = Contract::deploy(&compiled, &provider, &wallet, TxParameters::default())
.await
.unwrap();
let target = testfuelcoincontract_mod::ContractId { value: id.into() };
let asset_id = testfuelcoincontract_mod::ContractId { value: id.into() };

let instance = TestFuelCoinContract::new(id.to_string(), provider.clone(), wallet.clone());

let mut balance_result = instance
.get_balance(target.clone(), asset_id.clone())
.call()
.await
.unwrap();
let mut balance_result = instance.get_balance(id, id).call().await.unwrap();
assert_eq!(balance_result.value, 0);

instance.mint_coins(5_000_000).call().await.unwrap();

balance_result = instance.get_balance(target, asset_id).call().await.unwrap();
balance_result = instance.get_balance(id, id).call().await.unwrap();
assert_eq!(balance_result.value, 5_000_000);

let tx_params = TxParameters::new(None, Some(1_000_000), None);
Expand All @@ -1358,30 +1353,19 @@ async fn test_amount_and_asset_forwarding() {
assert!(call_response.is_some());

assert_eq!(call_response.unwrap().amount().unwrap(), 1_000_000);
assert_eq!(
call_response.unwrap().asset_id().unwrap(),
&AssetId::from(NATIVE_ASSET_ID)
);
assert_eq!(call_response.unwrap().asset_id().unwrap(), &NATIVE_ASSET_ID);

// Trying to forward `amount` of a different asset_id.
// Currently, if we use this asset_id in the forwarding, the VM will
// return `AssetIdNotFound` if amount is larger than 0.
let asset: [u8; 32] = id.clone().into();
let address = wallet.address();

// withdraw some tokens to wallet
let c_id = testfuelcoincontract_mod::ContractId { value: id.into() };
let address = wallet.address();
let address = testfuelcoincontract_mod::Address {
value: address.into(),
};
instance
.transfer_coins_to_output(1_000_000, c_id, address)
.transfer_coins_to_output(1_000_000, id, address)
.append_variable_outputs(1)
.call()
.await
.unwrap();

let call_params = CallParameters::new(Some(0), Some(AssetId::from(asset)));
let call_params = CallParameters::new(Some(0), Some(AssetId::from(*id)));
let tx_params = TxParameters::new(None, Some(1_000_000), None);

let response = instance
Expand All @@ -1404,7 +1388,7 @@ async fn test_amount_and_asset_forwarding() {
assert_eq!(call_response.unwrap().amount().unwrap(), 0);
assert_eq!(
call_response.unwrap().asset_id().unwrap(),
&AssetId::from(asset)
&AssetId::from(*id)
);
}

Expand Down
15 changes: 10 additions & 5 deletions fuels-core/src/code_gen/abigen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,24 +111,22 @@ impl Abigen {
} else {
(
quote! {
// aliasing to `FuelContractId` to prevent conflicts between
// `fuel_tx::ContractId` and user-defined structs named `ContractId`.
use fuel_tx::ContractId as FuelContractId;
use fuel_tx::{ContractId, Address};
use fuels_contract::contract::{Contract, ContractCall};
use fuels_signers::{provider::Provider, LocalWallet};
use std::str::FromStr;
},
quote! {
pub struct #name {
contract_id: FuelContractId,
contract_id: ContractId,
provider: Provider,
wallet: LocalWallet
}

impl #name {
pub fn new(contract_id: String, provider: Provider, wallet: LocalWallet)
-> Self {
let contract_id = FuelContractId::from_str(&contract_id).unwrap();
let contract_id = ContractId::from_str(&contract_id).unwrap();
Self{ contract_id, provider, wallet }
}
#contract_functions
Expand Down Expand Up @@ -180,6 +178,13 @@ impl Abigen {
let mut seen_struct: Vec<&str> = vec![];

for prop in self.custom_structs.values() {
// Skip custom type generation if the custom type is a Sway-native type.
// This means ABI methods receiving or returning a Sway-native type
// can receive or return that native type directly.
if prop.type_field.contains("ContractId") || prop.type_field.contains("Address") {
continue;
}

if !seen_struct.contains(&prop.type_field.as_str()) {
structs.extend(expand_internal_struct(prop)?);
seen_struct.push(&prop.type_field);
Expand Down
23 changes: 23 additions & 0 deletions fuels-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,29 @@ impl<T: Tokenizable> Detokenize for T {
}
}

impl Detokenize for fuel_tx::ContractId {
fn from_tokens(t: Vec<Token>) -> std::result::Result<Self, InvalidOutputType>
where
Self: Sized,
{
if let Token::Struct(tokens) = &t[0] {
if let Token::B256(id) = &tokens[0] {
Ok(fuel_tx::ContractId::from(*id))
} else {
Err(InvalidOutputType(format!(
"Expected `b256`, got {:?}",
tokens[0]
)))
}
} else {
Err(InvalidOutputType(format!(
"Expected `ContractId`, got {:?}",
t
)))
}
}
}

/// Converts a u8 to a right aligned array of 8 bytes.
pub fn pad_u8(value: &u8) -> ByteArray {
let mut padded = ByteArray::default();
Expand Down

0 comments on commit faa128b

Please sign in to comment.