diff --git a/.cargo/config.toml b/.cargo/config.toml index 6b275527a..0b09c4f04 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,7 +1,7 @@ # paths = ["/path/to/override"] # path dependency overrides [alias] # command aliases -install_soroban = "install --version 21.0.0-rc.1 --root ./target soroban-cli --debug" +install_stellar = "install --version 21.5.0 --root ./target stellar-cli --debug" # b = "build --target wasm32-unknown-unknown --release" # c = "check" # t = "test" diff --git a/.env b/.env index 6516b6c9c..efc8a0743 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -SOROBAN_NETWORK_PASSPHRASE="Standalone Network ; February 2017" -SOROBAN_RPC_URL="http://localhost:8000/soroban/rpc" -SOROBAN_ACCOUNT="me" +STELLAR_NETWORK_PASSPHRASE="Standalone Network ; February 2017" +STELLAR_RPC_URL="http://localhost:8000/soroban/rpc" +STELLAR_ACCOUNT="me" FRIENDBOT_URL="http://localhost:8000/friendbot" diff --git a/test/e2e/initialize.sh b/test/e2e/initialize.sh index ae453bbb9..9bb1e6b53 100755 --- a/test/e2e/initialize.sh +++ b/test/e2e/initialize.sh @@ -14,26 +14,26 @@ dirname="$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" echo "###################### Initializing e2e tests ########################" -soroban="$dirname/../../target/bin/soroban" -if [[ -f "$soroban" ]]; then - current=$($soroban --version | head -n 1 | cut -d ' ' -f 2) +stellar=$(realpath "$dirname/../../target/bin/stellar") +if [[ -f "$stellar" ]]; then + current=$($stellar --version | head -n 1 | cut -d ' ' -f 2) desired=$(cat .cargo/config.toml | grep -oE -- "--version\s+\S+" | awk '{print $2}') if [[ "$current" != "$desired" ]]; then - echo "Current pinned soroban binary: $current. Desired: $desired. Building soroban binary." - (cd "$dirname/../.." && cargo install_soroban) + echo "Current pinned stellar binary: $current. Desired: $desired. Building stellar binary." + (cd "$dirname/../.." && cargo install_stellar) else - echo "Using soroban binary from ./target/bin" + echo "Using stellar binary from ./target/bin" fi else - echo "Building pinned soroban binary" - (cd "$dirname/../.." && cargo install_soroban) + echo "Building pinned stellar binary" + (cd "$dirname/../.." && cargo install_stellar) fi -NETWORK_STATUS=$(curl -s -X POST "$SOROBAN_RPC_URL" -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", "id": 8675309, "method": "getHealth" }' | sed -n 's/.*"status":\s*"\([^"]*\)".*/\1/p') +NETWORK_STATUS=$(curl -s -X POST "$STELLAR_RPC_URL" -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", "id": 8675309, "method": "getHealth" }' | sed -n 's/.*"status":\s*"\([^"]*\)".*/\1/p') echo Network -echo " RPC: $SOROBAN_RPC_URL" -echo " Passphrase: \"$SOROBAN_NETWORK_PASSPHRASE\"" +echo " RPC: $STELLAR_RPC_URL" +echo " Passphrase: \"$STELLAR_NETWORK_PASSPHRASE\"" echo " Status: $NETWORK_STATUS" if [[ "$NETWORK_STATUS" != "healthy" ]]; then @@ -41,23 +41,24 @@ if [[ "$NETWORK_STATUS" != "healthy" ]]; then exit 1 fi -$soroban keys generate $SOROBAN_ACCOUNT +$stellar keys generate $STELLAR_ACCOUNT -# retrieve the contracts using soroban contract init then build them if they dont already exist +# retrieve the contracts using stellar 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" +test_examples_repo="https://github.com/AhaLabs/soroban-test-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" + "custom_types.wasm" + "atomic_swap.wasm" + "token.wasm" + "increment.wasm" + "needs_a_signature.wasm" + "this_one_signs.wasm" ) get_remote_git_hash() { - git ls-remote "$repo_url" HEAD | cut -f1 + git ls-remote "$test_examples_repo" HEAD | cut -f1 } # Get the current git hash @@ -75,7 +76,7 @@ fi all_exist=true for wasm_file in "${wasm_files[@]}"; do if [ ! -f "$target_dir/$wasm_file" ]; then - all_exist=false + all_exist=false break fi done @@ -84,11 +85,11 @@ done 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 - + npx degit --force AhaLabs/soroban-test-examples "$dirname/test-contracts" + # Change directory to test-contracts and build the contracts cd "$dirname/test-contracts" || { echo "Failed to change directory!"; exit 1; } - $soroban contract build + $stellar contract build # Save git hash to file echo "$current_hash" > "$hash_file" else diff --git a/test/e2e/src/test-contract-client-constructor.js b/test/e2e/src/test-contract-client-constructor.js index 50344791f..e7c408093 100644 --- a/test/e2e/src/test-contract-client-constructor.js +++ b/test/e2e/src/test-contract-client-constructor.js @@ -5,6 +5,7 @@ const { networkPassphrase, rpcUrl, generateFundedKeypair, + run, } = require("./util"); const { Address, contract } = require("../../.."); @@ -15,47 +16,32 @@ async function clientFromConstructor( if (!contracts[name]) { throw new Error( `Contract ${name} not found. ` + - `Pick one of: ${Object.keys(contracts).join(", ")}`, + `Pick one of: ${Object.keys(contracts).join()}`, ); } keypair = await keypair; // eslint-disable-line no-param-reassign const wallet = contract.basicNodeSigner(keypair, networkPassphrase); const { path } = contracts[name]; - const xdr = JSON.parse( - spawnSync( - "./target/bin/soroban", - ["contract", "inspect", "--wasm", path, "--output", "xdr-base64-array"], - { shell: true, encoding: "utf8" }, - ).stdout.trim(), - ); + const inspected = run( + `./target/bin/stellar contract inspect --wasm ${path} --output xdr-base64-array`, + ).stdout; + const xdr = JSON.parse(inspected); const spec = new contract.Spec(xdr); let wasmHash = contracts[name].hash; if (!wasmHash) { - wasmHash = spawnSync( - "./target/bin/soroban", - ["contract", "install", "--wasm", path], - { shell: true, encoding: "utf8" }, - ).stdout.trim(); + wasmHash = run( + `./target/bin/stellar contract install --wasm ${path}`, + ).stdout; } // TODO: do this with js-stellar-sdk, instead of shelling out to the CLI contractId = contractId ?? - spawnSync( - "./target/bin/soroban", - [ - // eslint-disable-line no-param-reassign - "contract", - "deploy", - "--source", - keypair.secret(), - "--wasm-hash", - wasmHash, - ], - { shell: true, encoding: "utf8" }, - ).stdout.trim(); + run( + `./target/bin/stellar contract deploy --source ${keypair.secret()} --wasm-hash ${wasmHash}`, + ).stdout; const client = new contract.Client(spec, { networkPassphrase, @@ -92,15 +78,15 @@ async function clientForFromTest(contractId, publicKey, keypair) { describe("Client", function () { before(async function () { const { client, keypair, contractId } = - await clientFromConstructor("helloWorld"); + await clientFromConstructor("customTypes"); 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({ to: "tests" }); - expect(result).to.deep.equal(["Hello", "tests"]); + const { result } = await this.context.client.hello({ hello: "tests" }); + expect(result).to.equal("tests"); }); it("can be constructed with `from`", async function () { diff --git a/test/e2e/src/test-methods-as-args.js b/test/e2e/src/test-methods-as-args.js index 97cf096c8..0d7007766 100644 --- a/test/e2e/src/test-methods-as-args.js +++ b/test/e2e/src/test-methods-as-args.js @@ -8,8 +8,8 @@ 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, { to: "tests" }); - expect(result).to.deep.equal(["Hello", "tests"]); + const { client } = await clientFor("customTypes"); + const { result } = await callMethod(client.hello, { hello: "tests" }); + expect(result).to.equal("tests"); }); }); diff --git a/test/e2e/src/test-non-invoker-signing-by-contracts.js b/test/e2e/src/test-non-invoker-signing-by-contracts.js index 03857ec09..71a407847 100644 --- a/test/e2e/src/test-non-invoker-signing-by-contracts.js +++ b/test/e2e/src/test-non-invoker-signing-by-contracts.js @@ -1,5 +1,10 @@ const { expect } = require("chai"); -const { clientFor, networkPassphrase, run, generateFundedKeypair } = require("./util"); +const { + clientFor, + networkPassphrase, + run, + generateFundedKeypair, +} = require("./util"); const { Asset, Operation, Horizon, TransactionBuilder } = require("../../.."); // A bug was reported for a SAC contract on testnet with contract ID @@ -21,59 +26,29 @@ const { Asset, Operation, Horizon, TransactionBuilder } = require("../../.."); // const rpcUrl = "https://soroban-testnet.stellar.org"; before(async function () { - const { contractId: admin, keypair } = await clientFor('stellar_asset_admin'); - const { client: wrapper, contractId: wrapperId } = await clientFor('stellar_asset_wrapper', { keypair }); - - const horizonAccount = await generateFundedKeypair(); - - const horizon = new Horizon.Server('http://localhost:8000', { - allowHttp: true, + const { contractId: doesSigning, keypair } = await clientFor("doesSigning"); + const { client: needsSignature } = await clientFor("needsSignature", { + keypair, }); - const account = await horizon.loadAccount(horizonAccount.publicKey()); - console.log('ACCOUNT LOADED!', { account }) - let establishTrustline = new TransactionBuilder(account, { - fee: 100, - networkPassphrase, - }) - .addOperation( - Operation.changeTrust({ - asset: new Asset('FAKE', keypair.publicKey()), - limit: "1000", - }) - ) - .setTimeout(100) - .build(); - establishTrustline.sign(horizonAccount); - const establishTrustlineResult = await horizon.submitTransaction(establishTrustline); - console.log('TRUSTLINE ESTABLISHED!', { establishTrustlineResult }) - - const token = run(`stellar contract asset deploy --asset FAKE:${keypair.publicKey()} --source ${keypair.secret()}`).stdout; - const setAdminResult = run(`stellar contract invoke --id ${token} --source ${keypair.secret()} -- set_admin --new_admin ${wrapperId}`); - - const init = await wrapper.init({ admin, token }); - const { result: initResult } = await init.signAndSend(); - console.log('INITIALIZED!', { admin, token, wrapperId, setAdminResult, initResult, establishTrustlineResult }) - - const tx = await wrapper.mint({ + const tx = await needsSignature.hello({ to: keypair.publicKey(), - amount: "100", - }) - // console.log(tx.simulationData()) - // console.log(tx.toJSON()) + sign_with: doesSigning, + }); this.context = { tx }; }); describe("needsNonInvokerSigningBy", function () { it("does not assume stellar accounts", async function () { - console.log('WE TESTIN NOW', this.context.tx, this.context.tx.needsNonInvokerSigningBy()) - expect(this.context.tx.needsNonInvokerSigningBy()[0]).to.match(/^C[0-9A-Z]{55}$/); + expect(this.context.tx.needsNonInvokerSigningBy()[0]).to.match( + /^C[0-9A-Z]{55}$/, + ); }); }); -// describe("sign", function () { -// it("doesn't throw error for nonInvokerSigningBy contract", async function () { -// const tx = await this.context.tx.sign({ force: true }); -// expect(tx).to.not.be.false; -// }); -// }); +describe("sign", function () { + it("doesn't throw error for nonInvokerSigningBy contract", async function () { + const tx = await this.context.tx.sign({ force: true }); + expect(tx).to.not.be.false; + }); +}); diff --git a/test/e2e/src/test-swap.js b/test/e2e/src/test-swap.js index b46a4eec0..6d6167319 100644 --- a/test/e2e/src/test-swap.js +++ b/test/e2e/src/test-swap.js @@ -99,98 +99,6 @@ describe("Swap Contract Tests", function () { }); }); - it("modified & re-simulated transactions show updated data", async function () { - const tx = await this.context.swapContractAsRoot.swap({ - a: this.context.alice.publicKey(), - b: this.context.bob.publicKey(), - token_a: this.context.tokenAId, - token_b: this.context.tokenBId, - amount_a: amountAToSwap, - min_a_for_b: amountAToSwap, - amount_b: amountBToSwap, - min_b_for_a: amountBToSwap, - }); - await tx.signAuthEntries({ - publicKey: this.context.alice.publicKey(), - ...contract.basicNodeSigner(this.context.alice, networkPassphrase), - }); - await tx.signAuthEntries({ - publicKey: this.context.bob.publicKey(), - ...contract.basicNodeSigner(this.context.bob, networkPassphrase), - }); - - const originalResourceFee = Number( - tx.simulationData.transactionData.resourceFee(), - ); - const bumpedResourceFee = originalResourceFee + 10000; - - tx.raw = TransactionBuilder.cloneFrom(tx.built, { - fee: tx.built.fee, - sorobanData: new SorobanDataBuilder( - tx.simulationData.transactionData.toXDR(), - ) - .setResourceFee( - xdr.Int64.fromString(bumpedResourceFee.toString()).toBigInt(), - ) - .build(), - }); - - await tx.simulate(); - - const newSimulatedResourceFee = Number( - tx.simulationData.transactionData.resourceFee(), - ); - - expect(originalResourceFee).to.not.equal(newSimulatedResourceFee); - expect(newSimulatedResourceFee).to.be.greaterThan(bumpedResourceFee); - }); - - it("modified & re-simulated transactions show updated data", async function () { - const tx = await this.context.swapContractAsRoot.swap({ - a: this.context.alice.publicKey(), - b: this.context.bob.publicKey(), - token_a: this.context.tokenAId, - token_b: this.context.tokenBId, - amount_a: amountAToSwap, - min_a_for_b: amountAToSwap, - amount_b: amountBToSwap, - min_b_for_a: amountBToSwap, - }); - await tx.signAuthEntries({ - publicKey: this.context.alice.publicKey(), - ...contract.basicNodeSigner(this.context.alice, networkPassphrase), - }); - await tx.signAuthEntries({ - publicKey: this.context.bob.publicKey(), - ...contract.basicNodeSigner(this.context.bob, networkPassphrase), - }); - - const originalResourceFee = Number( - tx.simulationData.transactionData.resourceFee(), - ); - const bumpedResourceFee = originalResourceFee + 10000; - - tx.raw = TransactionBuilder.cloneFrom(tx.built, { - fee: tx.built.fee, - sorobanData: new SorobanDataBuilder( - tx.simulationData.transactionData.toXDR(), - ) - .setResourceFee( - xdr.Int64.fromString(bumpedResourceFee.toString()).toBigInt(), - ) - .build(), - }); - - await tx.simulate(); - - const newSimulatedResourceFee = Number( - tx.simulationData.transactionData.resourceFee(), - ); - - expect(originalResourceFee).to.not.equal(newSimulatedResourceFee); - expect(newSimulatedResourceFee).to.be.greaterThan(bumpedResourceFee); - }); - it("alice swaps bob 10 A for 1 B", async function () { const tx = await this.context.swapContractAsRoot.swap({ a: this.context.alice.publicKey(), diff --git a/test/e2e/src/util.js b/test/e2e/src/util.js index c48159456..1a2ae145f 100644 --- a/test/e2e/src/util.js +++ b/test/e2e/src/util.js @@ -1,7 +1,8 @@ const { spawnSync } = require("node:child_process"); const { contract, Keypair } = require("../../.."); +const path = require("node:path"); -/* +/* * Run a Bash command, returning stdout, stderr, and status code. */ function run(command) { @@ -15,37 +16,44 @@ function run(command) { } module.exports.run = run; -const soroban = './target/bin/soroban'; -const basePath = `${__dirname}/../test-contracts/target/wasm32-unknown-unknown/release`; +const stellar = "./target/bin/stellar"; +const basePath = path.resolve( + `${__dirname}/../test-contracts/target/wasm32-unknown-unknown/release`, +); const contracts = { customTypes: { - hash: run(`${soroban} contract install --wasm ${basePath}/soroban_custom_types_contract.wasm`).stdout, - path: `${basePath}/soroban_custom_types_contract.wasm`, - }, - helloWorld: { - hash: run(`${soroban} install --wasm ${basePath}/hello_world.wasm`).stdout, - path: `${basePath}/hello_world.wasm`, + hash: run( + `${stellar} contract install --wasm ${basePath}/custom_types.wasm`, + ).stdout, + path: `${basePath}/custom_types.wasm`, }, increment: { - hash: run(`${soroban} contract install --wasm ${basePath}/soroban_increment_contract.wasm`).stdout, - path: `${basePath}/soroban_increment_contract.wasm`, + hash: run(`${stellar} contract install --wasm ${basePath}/increment.wasm`) + .stdout, + path: `${basePath}/increment.wasm`, }, swap: { - hash: run(`${soroban} contract install --wasm ${basePath}/soroban_atomic_swap_contract.wasm`).stdout, - path: `${basePath}/soroban_atomic_swap_contract.wasm`, + hash: run(`${stellar} contract install --wasm ${basePath}/atomic_swap.wasm`) + .stdout, + path: `${basePath}/atomic_swap.wasm`, }, token: { - hash: run(`${soroban} contract install --wasm ${basePath}/soroban_token_contract.wasm`).stdout, - path: `${basePath}/soroban_token_contract.wasm`, + hash: run(`${stellar} contract install --wasm ${basePath}/token.wasm`) + .stdout, + path: `${basePath}/token.wasm`, }, - stellar_asset_wrapper: { - hash: run(`${soroban} contract install --wasm ${__dirname}/../wasms/stellar_asset_wrapper.wasm`).stdout, - path: `${__dirname}/../wasms/stellar_asset_wrapper.wasm`, + needsSignature: { + hash: run( + `${stellar} contract install --wasm ${basePath}/needs_a_signature.wasm`, + ).stdout, + path: `${basePath}/needs_a_signature.wasm`, + }, + doesSigning: { + hash: run( + `${stellar} contract install --wasm ${basePath}/this_one_signs.wasm`, + ).stdout, + path: `${basePath}/this_one_signs.wasm`, }, - stellar_asset_admin: { - hash: run(`${soroban} contract install --wasm ${__dirname}/../wasms/stellar_asset_admin.wasm`).stdout, - path: `${__dirname}/../wasms/stellar_asset_admin.wasm`, - } }; module.exports.contracts = contracts; @@ -93,13 +101,17 @@ async function clientFor(name, { keypair, contractId } = {}) { let wasmHash = contracts[name].hash; if (!wasmHash) { - wasmHash = run(`${soroban} contract install --wasm ${contracts[name].path}`).stdout; + wasmHash = run( + `${stellar} contract install --wasm ${contracts[name].path}`, + ).stdout; } // TODO: do this with js-stellar-sdk, instead of shelling out to the CLI contractId = contractId ?? - run(`${soroban} contract deploy --source ${internalKeypair.secret()} --wasm-hash ${wasmHash}`).stdout; + run( + `${stellar} contract deploy --source ${internalKeypair.secret()} --wasm-hash ${wasmHash}`, + ).stdout; const client = await contract.Client.fromWasmHash( wasmHash,