Skip to content

Commit

Permalink
stop generating anything in initialize.sh
Browse files Browse the repository at this point in the history
just check that the network is running and the pinned binary is
installed.

ideally we wouldn't use the binary at all, but for now the tests are
still shelling out to the CLI, so it's worth keeping the pinning around
  • Loading branch information
chadoh committed Feb 26, 2024
1 parent 2e3ace4 commit 4959e4d
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 246 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SOROBAN_NETWORK_PASSPHRASE="Standalone Network ; February 2017"
SOROBAN_RPC_URL="http://localhost:8000/soroban/rpc"
SOROBAN_ACCOUNT="me"
FRIENDBOT_URL="http://localhost:8000/friendbot"
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"build:test": "tsc -p ./test/unit/tsconfig.json",
"build:browser": "webpack -c config/webpack.config.browser.js",
"build:docs": "cross-env NODE_ENV=docs yarn _babel",
"clean": "rm -rf lib/ dist/ coverage/ .nyc_output/ jsdoc/ test/e2e/.soroban test/e2e/contract-*.txt test/e2e/wasms/specs/*.json",
"clean": "rm -rf lib/ dist/ coverage/ .nyc_output/ jsdoc/ test/e2e/.soroban",
"docs": "yarn build:docs && jsdoc -c ./config/.jsdoc.json --verbose",
"test": "yarn build:test && yarn test:node && yarn test:integration && yarn test:browser",
"test:e2e": "./test/e2e/initialize.sh && ava",
Expand Down Expand Up @@ -138,7 +138,6 @@
"randombytes": "^2.1.0",
"sinon": "^17.0.1",
"sinon-chai": "^3.7.0",
"stellar-hd-wallet": "^0.0.10",
"taffydb": "^2.7.3",
"terser-webpack-plugin": "^5.3.10",
"ts-node": "^10.9.2",
Expand Down
71 changes: 3 additions & 68 deletions test/e2e/initialize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ dirname="$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

echo "###################### Initializing e2e tests ########################"

soroban="$dirname/../../target/bin/soroban"
if [[ -f "$soroban" ]]; then
echo "Using soroban binary from ./target/bin"
if [[ -f "$dirname/../../target/bin/soroban" ]]; then
echo "Tests will use soroban binary from ./target/bin"
else
echo "Building pinned soroban binary"
(cd "$dirname/../.." && cargo install_soroban)
Expand All @@ -34,68 +33,4 @@ if [[ "$NETWORK_STATUS" != "healthy" ]]; then
exit 1
fi

# Print command before executing, from https://stackoverflow.com/a/23342259/249801
# Discussion: https://github.com/stellar/soroban-tools/pull/1034#pullrequestreview-1690667116
exe() { echo"${@/eval/}" ; "$@" ; }

function fund_all() {
exe eval "$soroban keys generate root"
exe eval "$soroban keys generate alice"
exe eval "$soroban keys generate bob"
}
function install() {
exe eval "($soroban contract install --source root --wasm $dirname/$1 --ignore-checks) > $dirname/$2"
}
function deploy() {
exe eval "($soroban contract deploy --source root --wasm-hash $(cat $dirname/$1) --ignore-checks) > $dirname/$2"
}
function deploy_all() {
install wasms/test_custom_types.wasm contract-hash-custom-types.txt
install wasms/test_hello_world.wasm contract-hash-hello-world.txt
install wasms/test_swap.wasm contract-hash-swap.txt
install wasms/test_token.wasm contract-hash-token.txt
}
function initialize() {
exe eval "$soroban contract invoke --source root --id $(cat $dirname/$1) -- initialize --admin $($soroban keys address root) --decimal 0 --name 'Token $2' --symbol '$2'"
}
function initialize_all() {
initialize contract-id-token-a.txt A
initialize contract-id-token-b.txt B
}
function generate_spec() {
exe eval "$soroban contract inspect --wasm $dirname/wasms/$1.wasm --output xdr-base64-array > $dirname/wasms/specs/$1.json"
}
function generate_spec_all() {
generate_spec test_custom_types
generate_spec test_hello_world
generate_spec test_swap
generate_spec test_token
}
function mint() {
exe eval "$soroban contract invoke --source root --id $(cat $dirname/$1) -- mint --amount 2000000 --to $($soroban keys address $2)"
}
function mint_all() {
mint contract-id-token-a.txt alice
mint contract-id-token-b.txt bob
}
function check_specs() {
ls -l $dirname/wasms/specs/*.json 2> /dev/null | wc -l | xargs
}
function check_balance() {
ls -l $dirname/contract-id-*.txt 2> /dev/null | wc -l | xargs
if [ $? -eq 0 ]; then
return 0
fi
$soroban contract invoke --id $(cat $dirname/contract-id-token-$1.txt) -- balance --id $($soroban keys address $2) | xargs
}

if [ $(check_specs) == 4 ]; then
echo "Skipping initialization"
echo " specs generated: $(check_specs)"
echo "To re-initialize, delete generated files with 'yarn clean'"
exit 0
fi

fund_all
deploy_all
generate_spec_all
soroban keys generate $SOROBAN_ACCOUNT
42 changes: 26 additions & 16 deletions test/e2e/src/test-swap.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
const test = require('ava')
const { SorobanRpc } = require('../../..')
const { clientFor, alice, bob, root } = require('./util')
const { Keypair, SorobanRpc } = require('../../..')
const { clientFor } = require('./util')

const root = Keypair.random()
const alice = Keypair.random()
const bob = Keypair.random()

const amountAToSwap = 2n
const amountBToSwap = 1n
const alicePk = alice.keypair.publicKey()
const bobPk = bob.keypair.publicKey()
const alicePk = alice.publicKey()
const bobPk = bob.publicKey()

test.before(async t => {
const { client: tokenA, contractId: tokenAId } = await clientFor('token', { caller: root.keypair })
const { client: tokenB, contractId: tokenBId } = await clientFor('token', { caller: root.keypair })
const { client: swapContractAsRoot, contractId: swapId } = await clientFor('swap', { caller: root.keypair })

const { client: tokenA, contractId: tokenAId } = await clientFor('token', { keypair: root })
const { client: tokenB, contractId: tokenBId } = await clientFor('token', { keypair: root })
const { client: swapContractAsRoot, contractId: swapId } = await clientFor('swap', { keypair: root })
await (
await tokenA.initialize({ admin: root.keypair.publicKey(), decimal: 0, name: 'Token A', symbol: 'A' })
await tokenA.initialize({ admin: root.publicKey(), decimal: 0, name: 'Token A', symbol: 'A' })
).signAndSend()
await (
await tokenA.mint({ amount: 2000000n, to: alice.keypair.publicKey() })
await tokenA.mint({ amount: 2000000n, to: alicePk })
).signAndSend()

await (
await tokenB.initialize({ admin: root.keypair.publicKey(), decimal: 0, name: 'Token B', symbol: 'B' })
await tokenB.initialize({ admin: root.publicKey(), decimal: 0, name: 'Token B', symbol: 'B' })
).signAndSend()
await (
await tokenB.mint({ amount: 2000000n, to: bob.keypair.publicKey() })
await tokenB.mint({ amount: 2000000n, to: bobPk })
).signAndSend()

t.context = { swapContractAsRoot, swapId, tokenA, tokenB, tokenAId, tokenBId } // eslint-disable-line no-param-reassign
t.context = { // eslint-disable-line no-param-reassign
swapContractAsRoot,
swapId,
tokenA,
tokenAId,
tokenB,
tokenBId,
}
})

test('calling `signAndSend()` too soon throws descriptive error', async t => {
Expand Down Expand Up @@ -79,7 +89,7 @@ test('alice swaps bob 10 A for 1 B', async t => {
// root serializes & sends to alice
const jsonFromRoot = tx.toJSON()
const { client: clientAlice } = await clientFor('swap', {
caller: alice.keypair,
keypair: alice,
contractId: t.context.swapId,
})
const txAlice = clientAlice.txFromJSON(jsonFromRoot)
Expand All @@ -88,7 +98,7 @@ test('alice swaps bob 10 A for 1 B', async t => {
// alice serializes & sends to bob
const jsonFromAlice = txAlice.toJSON()
const { client: clientBob } = await clientFor('swap', {
caller: bob.keypair,
keypair: bob,
contractId: t.context.swapId,
})
const txBob = clientBob.txFromJSON(jsonFromAlice)
Expand All @@ -97,7 +107,7 @@ test('alice swaps bob 10 A for 1 B', async t => {
// bob serializes & sends back to root
const jsonFromBob = txBob.toJSON()
const { client: clientRoot } = await clientFor('swap', {
caller: root.keypair,
keypair: root,
contractId: t.context.swapId,
})
const txRoot = clientRoot.txFromJSON(jsonFromBob)
Expand Down
67 changes: 15 additions & 52 deletions test/e2e/src/util.js
Original file line number Diff line number Diff line change
@@ -1,90 +1,53 @@
const { spawnSync } = require('node:child_process')
const fs = require('node:fs')
const StellarHDWallet = require('stellar-hd-wallet')
const { Address, ContractSpec, Keypair, SorobanRpc } = require('../../..')
const helloWorldXdr = require('../wasms/specs/test_hello_world.json')
const swapXdr = require('../wasms/specs/test_swap.json')
const customTypesXdr = require('../wasms/specs/test_custom_types.json')
const tokenXdr = require('../wasms/specs/test_token.json')
const { ContractSpec, Keypair, SorobanRpc } = require('../../..')

const contracts = {
customTypes: {
hash: fs.readFileSync(`${__dirname}/../contract-hash-custom-types.txt`, "utf8").trim(),
xdr: customTypesXdr,
hash: spawnSync("./target/bin/soroban", ["contract", "install", "--wasm", `${__dirname}/../wasms/test_custom_types.wasm`], { shell: true, encoding: "utf8" }).stdout.trim(),
xdr: JSON.parse(spawnSync("./target/bin/soroban", ["contract", "inspect", "--wasm", `${__dirname}/../wasms/test_custom_types.wasm`, "--output", "xdr-base64-array"], { shell: true, encoding: "utf8" }).stdout.trim()),
},
helloWorld: {
hash: fs.readFileSync(`${__dirname}/../contract-hash-hello-world.txt`, "utf8").trim(),
xdr: helloWorldXdr,
hash: spawnSync("./target/bin/soroban", ["contract", "install", "--wasm", `${__dirname}/../wasms/test_hello_world.wasm`], { shell: true, encoding: "utf8" }).stdout.trim(),
xdr: JSON.parse(spawnSync("./target/bin/soroban", ["contract", "inspect", "--wasm", `${__dirname}/../wasms/test_hello_world.wasm`, "--output", "xdr-base64-array"], { shell: true, encoding: "utf8" }).stdout.trim()),
},
swap: {
hash: fs.readFileSync(`${__dirname}/../contract-hash-swap.txt`, "utf8").trim(),
xdr: swapXdr,
hash: spawnSync("./target/bin/soroban", ["contract", "install", "--wasm", `${__dirname}/../wasms/test_swap.wasm`], { shell: true, encoding: "utf8" }).stdout.trim(),
xdr: JSON.parse(spawnSync("./target/bin/soroban", ["contract", "inspect", "--wasm", `${__dirname}/../wasms/test_swap.wasm`, "--output", "xdr-base64-array"], { shell: true, encoding: "utf8" }).stdout.trim()),
},
token: {
hash: fs.readFileSync(`${__dirname}/../contract-hash-token.txt`, "utf8").trim(),
xdr: tokenXdr,
hash: spawnSync("./target/bin/soroban", ["contract", "install", "--wasm", `${__dirname}/../wasms/test_token.wasm`], { shell: true, encoding: "utf8" }).stdout.trim(),
xdr: JSON.parse(spawnSync("./target/bin/soroban", ["contract", "inspect", "--wasm", `${__dirname}/../wasms/test_token.wasm`, "--output", "xdr-base64-array"], { shell: true, encoding: "utf8" }).stdout.trim()),
},
};
module.exports.contracts = contracts

const rootKeypair = Keypair.fromSecret(spawnSync("./target/bin/soroban", ["keys", "show", "root"], { shell: true, encoding: "utf8" }).stdout.trim());
const aliceKeypair = Keypair.fromSecret(spawnSync("./target/bin/soroban", ["keys", "show", "alice"], { shell: true, encoding: "utf8" }).stdout.trim());
const bobKeypair = Keypair.fromSecret(spawnSync("./target/bin/soroban", ["keys", "show", "bob"], { shell: true, encoding: "utf8" }).stdout.trim());

const root = {
keypair: rootKeypair,
address: Address.fromString(rootKeypair.publicKey()),
}
module.exports.root = root

const alice = {
keypair: aliceKeypair,
address: Address.fromString(aliceKeypair.publicKey()),
}
module.exports.alice = alice

const bob = {
keypair: bobKeypair,
address: Address.fromString(bobKeypair.publicKey()),
}
module.exports.bob = bob

function generateKeypair() {
const mnemonic = StellarHDWallet.generateMnemonic()
const account = StellarHDWallet.fromMnemonic(mnemonic)
return account.getKeypair(0)
}
module.exports.generateKeypair = generateKeypair

const rpcUrl = process.env.SOROBAN_RPC_URL ?? "http://localhost:8000/soroban/rpc";
module.exports.rpcUrl = rpcUrl
const networkPassphrase = process.env.SOROBAN_NETWORK_PASSPHRASE ?? "Standalone Network ; February 2017";
module.exports.networkPassphrase = networkPassphrase
const friendbotUrl = process.env.SOROBAN_FRIENDBOT_URL ?? "http://localhost:8000/friendbot";
module.exports.friendbotUrl = friendbotUrl

module.exports.wallet = new SorobanRpc.ExampleNodeWallet(root.keypair, networkPassphrase)

/**
* Generates a ContractClient for the contract with the given name.
* Also generates a new account to use as as the caller of this contract. This
* Also generates a new account to use as as the keypair of this contract. This
* account is funded by friendbot. You can pass in an account to re-use the
* same account with multiple contract clients.
*
* By default, will re-deploy the contract every time. Pass in the same
* `contractId` again if you want to re-use the a contract instance.
*/
async function clientFor(contract, { caller = generateKeypair(), contractId } = {}) {
async function clientFor(contract, { keypair = Keypair.random(), contractId } = {}) {
if (!contracts[contract]) {
throw new Error(
`Contract ${contract} not found. ` +
`Pick one of: ${Object.keys(contracts).join(", ")}`
)
}

const publicKey = caller.publicKey();
const publicKey = keypair.publicKey();
await fetch(`${friendbotUrl}/friendbot?addr=${publicKey}`)
const wallet = new SorobanRpc.ExampleNodeWallet(caller, networkPassphrase)
const wallet = new SorobanRpc.ExampleNodeWallet(keypair, networkPassphrase)

const spec = new ContractSpec(contracts[contract].xdr)

Expand All @@ -98,7 +61,7 @@ async function clientFor(contract, { caller = generateKeypair(), contractId } =
"contract",
"deploy",
"--source",
caller.secret(),
keypair.secret(),
"--wasm-hash",
wasmHash,
], { shell: true, encoding: "utf8" }).stdout.trim();
Expand All @@ -110,7 +73,7 @@ async function clientFor(contract, { caller = generateKeypair(), contractId } =
wallet,
});
return {
caller,
keypair,
client,
contractId,
publicKey,
Expand Down
10 changes: 0 additions & 10 deletions test/e2e/wasms/specs/README.md

This file was deleted.

0 comments on commit 4959e4d

Please sign in to comment.