Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial interface for contract calls #9

Merged
merged 5 commits into from Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions fuels-abigen-macro/Cargo.toml
Expand Up @@ -12,13 +12,18 @@ proc-macro = true
[dependencies]
anyhow = "1"
bytes = { version = "1.0.1", features = ["serde"] }
forc = { git = "ssh://git@github.com/FuelLabs/sway.git", features = ["test", "util"], default-features = false }
fuel-asm = { git = "ssh://git@github.com/FuelLabs/fuel-asm.git", features = ["serde-types"] }
fuel-types = {git = "ssh://git@github.com/FuelLabs/fuel-types.git"}
fuels-rs = {path = "../fuels-rs"}
fuel-tx = { git = "ssh://git@github.com/FuelLabs/fuel-tx.git" }
fuel-vm = { git = "ssh://git@github.com/FuelLabs/fuel-vm.git" }
hex = { version = "0.4.3", default-features = false, features = ["std"] }
Inflector = "0.11"
itertools = "0.10.1"
proc-macro2 = "1.0"
quote = "1.0"
rand = "0.8"
regex = "1.5.4"
serde = { version = "1.0.124", default-features = false, features = ["derive"] }
serde_json = { version = "1.0.64", default-features = true }
Expand Down
158 changes: 93 additions & 65 deletions fuels-abigen-macro/tests/harness.rs
@@ -1,11 +1,11 @@
use fuel_tx::Salt;
use fuels_abigen_macro::abigen;
use fuels_rs::contract::Contract;
use fuels_rs::tokens::Token;
use rand::rngs::StdRng;
use rand::{Rng, SeedableRng};
use sha2::{Digest, Sha256};

const MOCK_CONTRACT_ADDRESS: &'static str =
"e50103684750e4916cd9825b14cf7e6763ffcc6523a9e0af63de93dbd6e3d736";

#[test]
fn compile_bindings_from_contract_file() {
// Generates the bindings from an ABI definition in a JSON file
Expand All @@ -16,7 +16,7 @@ fn compile_bindings_from_contract_file() {
);

// `SimpleContract` is the name of the contract
let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

// Calls the function defined in the JSON ABI.
// Note that this is type-safe, if the function does exist
Expand Down Expand Up @@ -71,7 +71,7 @@ fn compile_bindings_from_inline_contract() {
"#
);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_ints_returns_bool(42 as u32, 10 as u16);

Expand Down Expand Up @@ -111,7 +111,7 @@ fn compile_bindings_single_param() {
"#
);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_ints_returns_bool(42 as u32);

Expand Down Expand Up @@ -148,7 +148,7 @@ fn compile_bindings_array_input() {
"#
);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let input: Vec<u16> = vec![1, 2, 3, 4];
let contract_call = contract_instance.takes_array(input);
Expand Down Expand Up @@ -189,7 +189,7 @@ fn compile_bindings_bool_array_input() {
"#
);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let input: Vec<bool> = vec![true, false, true];
let contract_call = contract_instance.takes_array(input);
Expand Down Expand Up @@ -230,7 +230,7 @@ fn compile_bindings_byte_input() {
"#
);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_byte(10 as u8);

Expand Down Expand Up @@ -267,7 +267,7 @@ fn compile_bindings_string_input() {
"#
);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_string("This is a full sentence".into());

Expand Down Expand Up @@ -307,7 +307,7 @@ fn compile_bindings_b256_input() {
"#
);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let mut hasher = Sha256::new();
hasher.update("test string".as_bytes());
Expand Down Expand Up @@ -367,7 +367,7 @@ fn compile_bindings_struct_input() {
bar: true,
};

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_struct(input);

Expand Down Expand Up @@ -425,7 +425,7 @@ fn compile_bindings_nested_struct_input() {
inner_struct,
};

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_nested_struct(input);

Expand Down Expand Up @@ -472,7 +472,7 @@ fn compile_bindings_enum_input() {

let variant = MyEnum::X(42);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_enum(variant);

Expand All @@ -484,55 +484,6 @@ fn compile_bindings_enum_input() {
assert_eq!("000000009542a3c90000000000000000000000000000002a", encoded);
}

#[tokio::test]
async fn example_workflow() {
// This test case

// Generates the bindings from the an ABI definition inline.
// The generated bindings can be accessed through `MyContract`.
abigen!(
MyContract,
r#"
[
{
"type": "function",
"inputs": [
{
"name": "arg",
"type": "u32"
}
],
"name": "takes_int",
"outputs": [
]
}
]
"#
);

// Build the contract
let compiled = Contract::compile_sway_contract("tests/test_projects/contract_test").unwrap();

// Launch local network and deploy contract to testnet.
// Note that if `false` was passed to `stop_node`,
// `launch_and_deploy` would return a child process
// and we would be responsible for killing this process once
// we're done with testing.
// This is useful in case of long-lived local tests, spanning
// across different contracts being deployed and interacted with in
// the same session.
let (_, contract_id) = Contract::launch_and_deploy(compiled, true).await.unwrap();

println!("Contract deployed @ 0x{}", contract_id);

let contract_instance = MyContract::new(contract_id);

let _contract_call = contract_instance.takes_int(42 as u32);

// TODO: Send the actual transaction
// contract_call.send().await?;
}

#[test]
fn create_struct_from_decoded_tokens() {
// Generates the bindings from the an ABI definition inline.
Expand Down Expand Up @@ -577,7 +528,7 @@ fn create_struct_from_decoded_tokens() {
assert_eq!(10 as u8, struct_from_tokens.foo);
assert_eq!(true, struct_from_tokens.bar);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_struct(struct_from_tokens);

Expand Down Expand Up @@ -644,7 +595,7 @@ fn create_nested_struct_from_decoded_tokens() {
assert_eq!(10 as u16, nested_struct_from_tokens.x);
assert_eq!(true, nested_struct_from_tokens.inner_struct.a);

let contract_instance = SimpleContract::new(MOCK_CONTRACT_ADDRESS.into());
let contract_instance = SimpleContract::new(Default::default());

let contract_call = contract_instance.takes_nested_struct(nested_struct_from_tokens);

Expand All @@ -655,3 +606,80 @@ fn create_nested_struct_from_decoded_tokens() {

assert_eq!("00000000e8a04d9c000000000000000a0000000000000001", encoded);
}

#[tokio::test]
async fn example_workflow() {
let rng = &mut StdRng::seed_from_u64(2322u64);

// Generates the bindings from the an ABI definition inline.
// The generated bindings can be accessed through `MyContract`.
abigen!(
MyContract,
r#"
[
{
"type": "function",
"inputs": [
{
"name": "arg",
"type": "u64"
}
],
"name": "initialize",
"outputs": [
{
"name": "arg",
"type": "u64"
}
]
},
{
"type": "function",
"inputs": [
{
"name": "arg",
"type": "u64"
}
],
"name": "increment",
"outputs": [
{
"name": "arg",
"type": "u64"
}
]
}
]
"#
);

// Build the contract
let salt: [u8; 32] = rng.gen();
let salt = Salt::from(salt);
Comment on lines +690 to +691
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let salt: [u8; 32] = rng.gen();
let salt = Salt::from(salt);
let salt: Salt = rng.gen();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried that before doing the ugly way, was getting this:

image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will figure this out on the next PR I'll be submitting soon, need to merge this 😅.


let compiled =
Contract::compile_sway_contract("tests/test_projects/contract_test", salt).unwrap();

// Launch local network and deploy contract to testnet.
// Note that if `false` was passed to `stop_node`,
// `launch_and_deploy` would return a child process
// and we would be responsible for killing this process once
// we're done with testing.
// This is useful in case of long-lived local tests, spanning
// across different contracts being deployed and interacted with in
// the same session.
let (_, contract_id) = Contract::launch_and_deploy(&compiled, true).await.unwrap();

println!("Contract deployed @ {:x}", contract_id);

let contract_instance = MyContract::new(compiled);
adlerjohn marked this conversation as resolved.
Show resolved Hide resolved

let contract_call = contract_instance.initialize(42);

// Currently, contract calls are empty script calls.
// Soon it will be able to generate/craft the
// `script_data` on the fly and dynamically call a
// contract's function.
let res = contract_call.call().await.unwrap();
println!("res: {:?}\n", res);
}
Expand Up @@ -6,12 +6,12 @@ entry = "main.sw"


[dependencies]
std = { path = "../../../../stdlib" }
std = { path = "../stdlib" }
increment_abi = { path = "../library_test" }

[[tx-input]]
type = "Contract"
contract-id = "0xe50103684750e4916cd9825b14cf7e6763ffcc6523a9e0af63de93dbd6e3d736"
utxo-id = "0xeeb578f9e1ebfb5b78f8ff74352370c120bc8cacead1f5e4f9c74aafe0ca6bfd"
balance-root = "0xeeb578f9e1ebfb5b78f8ff74352370c120bc8cacead1f5e4f9c74aafe0ca6bfd"
state-root = "0xeeb578f9e1ebfb5b78f8ff74352370c120bc8cacead1f5e4f9c74aafe0ca6bfd"
state-root = "0xeeb578f9e1ebfb5b78f8ff74352370c120bc8cacead1f5e4f9c74aafe0ca6bfd"
adlerjohn marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,8 @@
[project]
author = "Alex Hansen"
license = "MIT"
name = "Fuel example project"


[dependencies]
std = { path = "../stdlib" }
@@ -0,0 +1,79 @@
script;
use std::ops::Ord;

struct Rgb {
red: u64,
green: u64,
blue: u64,
}


enum PrimaryColor {
Red : (),
Green : (),
Blue : ()
}

impl Ord for PrimaryColor {
fn gt(self, other: Self) -> bool {
asm(r1: self, r2: other, r3) {
gt r3 r1 r2;
r3: bool
}
}
fn lt(self, other: Self) -> bool {
asm(r1: self, r2: other, r3) {
lt r3 r1 r2;
r3: bool
}
}
fn eq(self, other: Self) -> bool {
asm(r1: self, r2: other, r3) {
eq r3 r1 r2;
r3: bool
}
}
}

impl Color for PrimaryColor {
// TODO: when we support match statements, change this to a match statement
fn rgb(self) -> Rgb {
if self == PrimaryColor::Red {
Rgb {
red: 255,
blue: 0,
green: 0,
}
}
else if self == PrimaryColor::Green {
Rgb {
red: 0,
blue: 0,
green: 255,
}
}
else if self == PrimaryColor::Blue {
Rgb {
red: 0,
blue: 255,
green: 0,
}
}
else {
Rgb {
red: 0,
blue: 0,
green: 0
}
}
}
}

fn main() {
let first_color = PrimaryColor::Green;
let rgb: Rgb = first_color.rgb();
}

trait Color {
fn rgb(self) -> Rgb;
}