diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index e9a2301a8..50dbbc2e8 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -34,6 +34,7 @@ jobs: # Workaround for some `yarn` nonsense, see: # https://github.com/yarnpkg/yarn/issues/6312#issuecomment-429685210 + - run: rustup target add wasm32-unknown-unknown - run: yarn install --network-concurrency 1 - run: yarn build:prod - run: yarn test:e2e diff --git a/test/e2e/.gitignore b/test/e2e/.gitignore index d8dea8c98..b2c0d97d4 100644 --- a/test/e2e/.gitignore +++ b/test/e2e/.gitignore @@ -4,3 +4,4 @@ yarn.lock contract-*.txt .soroban wasms/specs/*.json +test-contracts \ No newline at end of file diff --git a/test/e2e/initialize.sh b/test/e2e/initialize.sh index 740a90ac7..ae453bbb9 100755 --- a/test/e2e/initialize.sh +++ b/test/e2e/initialize.sh @@ -42,3 +42,55 @@ if [[ "$NETWORK_STATUS" != "healthy" ]]; then fi $soroban keys generate $SOROBAN_ACCOUNT + +# retrieve the contracts using soroban contract init then build them if they dont already exist +# Define directory and WASM file paths +target_dir="$dirname/test-contracts/target/wasm32-unknown-unknown/release" +contracts_dir="$dirname/test-contracts" +repo_url="https://github.com/stellar/soroban-examples.git" +wasm_files=( + "soroban_custom_types_contract.wasm" + "soroban_atomic_swap_contract.wasm" + "soroban_token_contract.wasm" + "soroban_increment_contract.wasm" + "hello_world.wasm" +) + +get_remote_git_hash() { + git ls-remote "$repo_url" HEAD | cut -f1 +} + +# Get the current git hash +current_hash=$(get_remote_git_hash) + +# Check if a stored hash exists +hash_file="$contracts_dir/.last_build_hash" +if [ -f "$hash_file" ]; then + stored_hash=$(cat "$hash_file") +else + stored_hash="" +fi + +# Check if all WASM files exist and if the git hash has changed +all_exist=true +for wasm_file in "${wasm_files[@]}"; do + if [ ! -f "$target_dir/$wasm_file" ]; then + all_exist=false + break + fi +done + +# If any WASM file is missing or the git hash has changed, initialize and build the contracts +if [ "$all_exist" = false ] || [ "$current_hash" != "$stored_hash" ]; then + echo "WASM files are missing or contracts have been updated. Initializing and building contracts..." + # Initialize contracts + $soroban contract init "$dirname/test-contracts" --with-example increment custom_types atomic_swap token + + # Change directory to test-contracts and build the contracts + cd "$dirname/test-contracts" || { echo "Failed to change directory!"; exit 1; } + $soroban contract build + # Save git hash to file + echo "$current_hash" > "$hash_file" +else + echo "All WASM files are present and up to date." +fi diff --git a/test/e2e/src/test-contract-client-constructor.js b/test/e2e/src/test-contract-client-constructor.js index c0eb015c8..79479ba6c 100644 --- a/test/e2e/src/test-contract-client-constructor.js +++ b/test/e2e/src/test-contract-client-constructor.js @@ -92,15 +92,15 @@ async function clientForFromTest(contractId, publicKey, keypair) { describe("Client", function () { before(async function () { const { client, keypair, contractId } = - await clientFromConstructor("customTypes"); + await clientFromConstructor("helloWorld"); const publicKey = keypair.publicKey(); const addr = Address.fromString(publicKey); this.context = { client, publicKey, addr, contractId, keypair }; }); - it("can be constructed with `new Client`", async function () { - const { result } = await this.context.client.hello({ hello: "tests" }); - expect(result).to.equal("tests"); + it("can be constructed with `new Client`", async function() { + const { result } = await this.context.client.hello({ to: "tests" }); + expect(result).to.deep.equal(["Hello", "tests"]); }); it("can be constructed with `from`", async function () { diff --git a/test/e2e/src/test-custom-types.js b/test/e2e/src/test-custom-types.js index b5c253653..14ecfdce6 100644 --- a/test/e2e/src/test-custom-types.js +++ b/test/e2e/src/test-custom-types.js @@ -16,20 +16,43 @@ describe("Custom Types Tests", function () { ).to.equal("tests"); }); - it("view method with empty keypair", async function () { + it("view method with empty keypair", async function() { const { client: client2 } = await clientFor("customTypes", { keypair: undefined, - contractId: this.context.contractId, + contractId: this.context.contractId }); - expect((await client2.hello({ hello: "anonymous" })).result).to.equal( - "anonymous", - ); + expect((await client2.i32_({ i32_: 1 })).result).to.equal(1); + }); + + it("should increment the counter correctly", async function() { + const { result: startingBalance } = await this.context.client.get_count(); + const inc = await this.context.client.inc(); + const incrementResponse = await inc.signAndSend(); + expect(incrementResponse.result).to.equal(startingBalance + 1); + expect(startingBalance).to.equal(0); // Assuming the counter starts at 0 + const { result: newBalance } = await this.context.client.get_count(); + expect(newBalance).to.equal(startingBalance + 1); + }); + + it("should accept only options object for methods with no arguments", async function() { + const inc = await this.context.client.inc({ simulate: false }); + expect(inc.simulation).to.be.undefined; }); it("woid", async function () { expect((await this.context.client.woid()).result).to.be.null; }); + it("should authenticate the user correctly", async function() { + const { result } = await this.context.client.auth({ addr: this.context.publicKey, world: "lol" }); + expect(result).to.equal(this.context.publicKey); + }); + + it("should authenticate the user correctly", async function() { + const { result } = await this.context.client.auth({ addr: this.context.publicKey, world: "lol" }); + expect(result).to.equal(this.context.publicKey); + }); + it("u32_fail_on_even", async function () { let response = await this.context.client.u32_fail_on_even({ u32_: 1 }); expect(response.result).to.deep.equal(new contract.Ok(1)); diff --git a/test/e2e/src/test-hello-world.js b/test/e2e/src/test-hello-world.js deleted file mode 100644 index ac74a4629..000000000 --- a/test/e2e/src/test-hello-world.js +++ /dev/null @@ -1,34 +0,0 @@ -const { expect } = require("chai"); -const { clientFor } = require("./util"); - -describe("helloWorld client", function () { - it("should return properly formed hello response", async function () { - const { client } = await clientFor("helloWorld"); - const response = await client.hello({ world: "tests" }); - expect(response.result).to.deep.equal(["Hello", "tests"]); - }); - - it("should authenticate the user correctly", async function () { - const { client, keypair } = await clientFor("helloWorld"); - const publicKey = keypair.publicKey(); - const { result } = await client.auth({ addr: publicKey, world: "lol" }); - expect(result).to.equal(publicKey); - }); - - it("should increment the counter correctly", async function () { - const { client } = await clientFor("helloWorld"); - const { result: startingBalance } = await client.get_count(); - const inc = await client.inc(); - const incrementResponse = await inc.signAndSend(); - expect(incrementResponse.result).to.equal(startingBalance + 1); - expect(startingBalance).to.equal(0); // Assuming the counter starts at 0 - const { result: newBalance } = await client.get_count(); - expect(newBalance).to.equal(startingBalance + 1); - }); - - it("should accept only options object for methods with no arguments", async function () { - const { client } = await clientFor("helloWorld"); - const inc = await client.inc({ simulate: false }); - expect(inc.simulation).to.be.undefined; - }); -}); diff --git a/test/e2e/src/test-methods-as-args.js b/test/e2e/src/test-methods-as-args.js index 3308e907d..97cf096c8 100644 --- a/test/e2e/src/test-methods-as-args.js +++ b/test/e2e/src/test-methods-as-args.js @@ -9,7 +9,7 @@ function callMethod(method, args) { describe("methods-as-args", function () { it("should pass methods as arguments and have them still work", async function () { const { client } = await clientFor("helloWorld"); - const { result } = await callMethod(client.hello, { world: "tests" }); + const { result } = await callMethod(client.hello, { to: "tests" }); expect(result).to.deep.equal(["Hello", "tests"]); }); }); diff --git a/test/e2e/src/util.js b/test/e2e/src/util.js index 6d760c976..5e8980173 100644 --- a/test/e2e/src/util.js +++ b/test/e2e/src/util.js @@ -1,6 +1,7 @@ const { spawnSync } = require("node:child_process"); const { contract, Keypair } = require("../../.."); +const basePath = `${__dirname}/../test-contracts/target/wasm32-unknown-unknown/release`; const contracts = { customTypes: { hash: spawnSync( @@ -9,11 +10,11 @@ const contracts = { "contract", "install", "--wasm", - `${__dirname}/../wasms/test_custom_types.wasm`, + `${basePath}/soroban_custom_types_contract.wasm`, ], { shell: true, encoding: "utf8" }, ).stdout.trim(), - path: `${__dirname}/../wasms/test_custom_types.wasm`, + path: `${basePath}/soroban_custom_types_contract.wasm`, }, helloWorld: { hash: spawnSync( @@ -22,19 +23,37 @@ const contracts = { "contract", "install", "--wasm", - `${__dirname}/../wasms/test_hello_world.wasm`, + `${basePath}/hello_world.wasm`, ], { shell: true, encoding: "utf8" }, ).stdout.trim(), - path: `${__dirname}/../wasms/test_hello_world.wasm`, + path: `${basePath}/hello_world.wasm`, + }, + increment: { + hash: spawnSync( + "./target/bin/soroban", + [ + "contract", + "install", + "--wasm", + `${basePath}/soroban_increment_contract.wasm`, + ], + { shell: true, encoding: "utf8" }, + ).stdout.trim(), + path: `${basePath}/soroban_increment_contract.wasm`, }, swap: { hash: spawnSync( "./target/bin/soroban", - ["contract", "install", "--wasm", `${__dirname}/../wasms/test_swap.wasm`], + [ + "contract", + "install", + "--wasm", + `${basePath}/soroban_atomic_swap_contract.wasm`, + ], { shell: true, encoding: "utf8" }, ).stdout.trim(), - path: `${__dirname}/../wasms/test_swap.wasm`, + path: `${basePath}/soroban_atomic_swap_contract.wasm`, }, token: { hash: spawnSync( @@ -43,11 +62,11 @@ const contracts = { "contract", "install", "--wasm", - `${__dirname}/../wasms/test_token.wasm`, + `${basePath}/soroban_token_contract.wasm`, ], { shell: true, encoding: "utf8" }, ).stdout.trim(), - path: `${__dirname}/../wasms/test_token.wasm`, + path: `${basePath}/soroban_token_contract.wasm`, }, }; module.exports.contracts = contracts; @@ -65,7 +84,7 @@ module.exports.friendbotUrl = friendbotUrl; async function generateFundedKeypair() { const keypair = Keypair.random(); - await fetch(`${friendbotUrl}/friendbot?addr=${keypair.publicKey()}`); + await fetch(friendbotUrl === 'https://friendbot.stellar.org' ? `${friendbotUrl}/?addr=${keypair.publicKey()}` : `${friendbotUrl}/friendbot?addr=${keypair.publicKey()}`); return keypair; } module.exports.generateFundedKeypair = generateFundedKeypair;