Skip to content

Commit e40daf7

Browse files
calldelegationIGI-111sdankel
authored
feat: Add predicate and script templates (#5238)
## Description When DevRel creates more tutorials on predicates and scripts, it's not ideal to use the same template designed for contracts and ask developers to erase everything and start afresh. It's clearer to have developers use a template tailored for the respective program type. These templates are already compatible with existing `forc` commands like Predicate 1. `forc new --predicate MyPredicate` 2. `cargo generate --init fuellabs/sway templates/sway-predicate-test-rs --name MyPredicate` Script 1. `forc new --script MyScript` 2. `cargo generate --init fuellabs/sway templates/sway-script-test-rs --name MyScript` ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [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. --------- Co-authored-by: IGI-111 <igi-111@protonmail.com> Co-authored-by: Sophie Dankel <47993817+sdankel@users.noreply.github.com>
1 parent bf8d8a4 commit e40daf7

File tree

11 files changed

+181
-2
lines changed

11 files changed

+181
-2
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ jobs:
287287
crate: cargo-toml-lint
288288
version: '0.1'
289289
- name: Run Cargo.toml linter
290-
run: git ls-files | grep Cargo.toml$ | grep -v 'templates/sway-test-rs' | xargs --verbose -n 1 cargo-toml-lint
290+
run: git ls-files | grep Cargo.toml$ | grep -v 'templates/' | xargs --verbose -n 1 cargo-toml-lint
291291

292292
cargo-fmt-check:
293293
runs-on: ubuntu-latest

docs/book/src/testing/testing-with-rust.md

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ placeholder in the template. Otherwise, `cargo-generate` automatically converts
5151
With `--force`, this means that both `my_fuel_project` and `my-fuel-project` are valid project names,
5252
depending on your needs.
5353

54+
> _**Note**: `templates/sway-test-rs` can be replaced with `templates/sway-script-test-rs` or `templates/sway-predicate-test-rs` to generate a test
55+
> harness for scripts and predicates respectively.
56+
5457
If all goes well, the output should look as follows:
5558

5659
```console

templates/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# templates
22

33
A directory of useful templates for Sway developers, currently only home to the
4-
`sway-test-rs` `cargo generate` template for Sway + Rust integration testing.
4+
`sway-test-rs`, `sway-predicate-test-rs`, `sway-script-test-rs` `cargo generate` template for Sway + Rust integration testing.
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Rust + Sway integration testing
2+
3+
A cargo-generate template that makes it easy to initialise Rust integration
4+
testing within an existing Sway project.
5+
6+
This template is designed for Rust developers who wish to test integration of
7+
their Rust application and Sway code.
8+
9+
See the [Testing with Rust](https://docs.fuel.network/docs/sway/testing/testing-with-rust/) chapter of [the Sway
10+
Book](https://fuellabs.github.io/sway/master) for a thorough guide on how to
11+
use this template.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "{{project-name}}"
3+
description = "A cargo-generate template for Rust + Sway integration testing."
4+
version = "0.1.0"
5+
edition = "2021"
6+
authors = ["{{authors}}"]
7+
license = "Apache-2.0"
8+
9+
[dev-dependencies]
10+
fuels = { version = "0.53", features = ["fuel-core-lib"] }
11+
tokio = { version = "1.12", features = ["rt", "macros"] }
12+
13+
[[test]]
14+
harness = true
15+
name = "integration_tests"
16+
path = "tests/harness.rs"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Even though we don't need any custom configuration, the `cargo-generate.toml`
2+
# file is added to indicate the root of the default template within the
3+
# repository.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use fuels::{accounts::{predicate::Predicate}, prelude::*};
2+
3+
// Load abi from json
4+
abigen!(Predicate(
5+
name = "MyPredicate",
6+
abi = "out/debug/{{project-name}}-abi.json"
7+
));
8+
9+
async fn get_predicate_instance() -> (WalletUnlocked, Predicate) {
10+
let mut wallets = launch_custom_provider_and_get_wallets(
11+
WalletsConfig::new(
12+
Some(1), /* Single wallet */
13+
Some(1), /* Single coin (UTXO) */
14+
Some(1_000_000_000), /* Amount per coin */
15+
),
16+
None,
17+
None,
18+
)
19+
.await
20+
.unwrap();
21+
22+
let wallet = wallets.pop().unwrap();
23+
24+
let provider = wallet.provider().clone().unwrap();
25+
26+
let bin_path = "./out/debug/{{project-name}}.bin";
27+
28+
let instance: Predicate = Predicate::load_from(bin_path).unwrap().with_provider(provider.clone());
29+
30+
(wallet, instance)
31+
}
32+
33+
async fn check_balances(
34+
wallet: &WalletUnlocked,
35+
instance: &Predicate,
36+
expected_wallet_balance: Option<u64>,
37+
expected_predicate_balance: Option<u64>,
38+
) -> (u64, u64) {
39+
let wallet_bal = wallet.get_asset_balance(&AssetId::default()).await.unwrap();
40+
let predicate_bal = instance.get_asset_balance(&AssetId::default()).await.unwrap();
41+
42+
if let Some(expected) = expected_wallet_balance {
43+
assert_eq!(wallet_bal, expected);
44+
}
45+
46+
if let Some(expected) = expected_predicate_balance {
47+
assert_eq!(predicate_bal, expected);
48+
}
49+
50+
(wallet_bal, predicate_bal)
51+
}
52+
53+
#[tokio::test]
54+
async fn can_get_predicate_instance() {
55+
let (wallet, instance) = get_predicate_instance().await;
56+
let predicate_root = instance.address();
57+
58+
// Check balances before funding predicate
59+
check_balances(&wallet, &instance, Some(1_000_000_000u64), None).await;
60+
61+
// Fund predicate from wallet
62+
let _ = wallet.transfer(predicate_root, 1234, BASE_ASSET_ID, TxPolicies::default()).await;
63+
64+
// Check balances after funding predicate
65+
check_balances(&wallet, &instance, Some(999_998_766u64), Some(1234u64)).await;
66+
67+
let _ = instance.transfer(wallet.address(), 1234, BASE_ASSET_ID, TxPolicies::default()).await;
68+
69+
// Check balances after transfering funds out of predicate
70+
check_balances(&wallet, &instance, Some(1_000_000_000u64), Some(0u64)).await;
71+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Rust + Sway integration testing
2+
3+
A cargo-generate template that makes it easy to initialise Rust integration
4+
testing within an existing Sway project.
5+
6+
This template is designed for Rust developers who wish to test integration of
7+
their Rust application and Sway code.
8+
9+
See the [Testing with Rust](https://docs.fuel.network/docs/sway/testing/testing-with-rust/) chapter of [the Sway
10+
Book](https://fuellabs.github.io/sway/master) for a thorough guide on how to
11+
use this template.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "{{project-name}}"
3+
description = "A cargo-generate template for Rust + Sway integration testing."
4+
version = "0.1.0"
5+
edition = "2021"
6+
authors = ["{{authors}}"]
7+
license = "Apache-2.0"
8+
9+
[dev-dependencies]
10+
fuels = { version = "0.53", features = ["fuel-core-lib"] }
11+
tokio = { version = "1.12", features = ["rt", "macros"] }
12+
13+
[[test]]
14+
harness = true
15+
name = "integration_tests"
16+
path = "tests/harness.rs"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Even though we don't need any custom configuration, the `cargo-generate.toml`
2+
# file is added to indicate the root of the default template within the
3+
# repository.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use fuels::prelude::*;
2+
3+
// Load abi from json
4+
abigen!(Script(
5+
name = "MyScript",
6+
abi = "out/debug/{{project-name}}-abi.json"
7+
));
8+
9+
async fn get_script_instance() -> MyScript<WalletUnlocked> {
10+
// Launch a local network
11+
let mut wallets = launch_custom_provider_and_get_wallets(
12+
WalletsConfig::new(
13+
Some(1), /* Single wallet */
14+
Some(1), /* Single coin (UTXO) */
15+
Some(1_000_000_000), /* Amount per coin */
16+
),
17+
None,
18+
None,
19+
)
20+
.await;
21+
let wallet = wallets.pop().unwrap();
22+
23+
let bin_path = "./out/debug/{{project-name}}.bin";
24+
25+
let instance = MyScript::new(wallet.clone(), bin_path);
26+
27+
instance
28+
}
29+
30+
#[tokio::test]
31+
async fn can_get_script_instance() {
32+
const LUCKY_NUMBER: u64 = 777;
33+
let configurables = MyScriptConfigurables::new().with_SECRET_NUMBER(LUCKY_NUMBER.clone());
34+
35+
let instance = get_script_instance().await;
36+
37+
// Now you have an instance of your script
38+
let response = instance.with_configurables(configurables).main().call().await.unwrap();
39+
40+
assert_eq!(response.value, LUCKY_NUMBER);
41+
42+
// You can print logs from scripts to debug
43+
let logs = response.decode_logs();
44+
println!("{:?}", logs);
45+
}

0 commit comments

Comments
 (0)