Skip to content

Commit

Permalink
build: switch to new AhaLabs/soroban-test-contracts
Browse files Browse the repository at this point in the history
also:

- switch to `stellar` instead of `soroban`
- use latest cli version
- this version fixes a problem that some of the tests were working
  around, so they were removed
  • Loading branch information
chadoh committed Sep 25, 2024
1 parent c0deaa1 commit 17ab168
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 222 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
6 changes: 3 additions & 3 deletions .env
Original file line number Diff line number Diff line change
@@ -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"
49 changes: 25 additions & 24 deletions test/e2e/initialize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,50 +14,51 @@ 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
echo "Network is not healthy (not running?), exiting"
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
Expand All @@ -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
Expand All @@ -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
Expand Down
44 changes: 15 additions & 29 deletions test/e2e/src/test-contract-client-constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const {
networkPassphrase,
rpcUrl,
generateFundedKeypair,
run,
} = require("./util");
const { Address, contract } = require("../../..");

Expand All @@ -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,
Expand Down Expand Up @@ -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 () {
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/src/test-methods-as-args.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
});
});
67 changes: 21 additions & 46 deletions test/e2e/src/test-non-invoker-signing-by-contracts.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
});
});
92 changes: 0 additions & 92 deletions test/e2e/src/test-swap.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Loading

0 comments on commit 17ab168

Please sign in to comment.