Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Tezos Infra Module #922

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions packages/cli/src/__tests__/e2e/infra.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,4 +462,73 @@ describe("e2e tests for infra command", () => {
);
});
});

describe("Default modules", () => {

test("Tezos", async () => {
process.env = {
...process.env,
TEZOS_POLYWRAP_PORT: "2000",
TEZOS_POLYWRAP_BLOCK_TIME: "5",
TEZOS_POLYWRAP_PROTOCOL: "hangzhou"
};

await runW3CLI(
[
"infra",
"up",
"--modules=tezos",
"--verbose"
],
getTestCaseDir(3),
);

await waitForPorts([
{ port: 2000, expected: true }
]);

await runW3CLI(
[
"infra",
"down",
"--modules=tezos",
"--verbose"
],
getTestCaseDir(3),
);
})

test("Ethereum, Ens, IPFS", async () => {
process.env = {
...process.env,
IPFS_PORT: "5001",
ETHEREUM_PORT: "8545",
};

await runW3CLI(
[
"infra",
"up",
"--modules=eth-ens-ipfs",
"--verbose"
],
getTestCaseDir(3),
);

await waitForPorts([
{ port: 5001, expected: true },
{ port: 8545, expected: true }
]);

await runW3CLI(
[
"infra",
"down",
"--modules=eth-ens-ipfs",
"--verbose"
],
getTestCaseDir(3),
);
})
})
})
16 changes: 16 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM oxheadalpha/flextesa:20211221

LABEL vendor=Blockwatch\ Data\ Inc \
maintainer="3sky <[email protected]>" \
name="blockwatch/flextesa" \
cx.bwd.arch="x86_64" \
cx.bwd.os="linux" \
cx.bwd.build-version=$BUILD_VERSION \
cx.bwd.build-date=$BUILD_DATE \
cx.bwd.build-id=$BUILD_ID

COPY ./tezos-test-env.sh /usr/bin/tezos-test-env.sh
RUN chmod 777 /usr/bin/tezos-test-env.sh && adduser -D -g '' tez
USER tez
ENTRYPOINT ["/bin/sh", "-c", "/usr/bin/tezos-test-env.sh startup"]
EXPOSE 20000
5 changes: 5 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Tezos Test Env

Tezos Test Environment for testing Polywrappers.

Documentation: https://blockwatch.gitbook.io/polywrap-tezos/creating-wrappers/test-environment
7 changes: 7 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/cmds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const CMDS = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@namesty I'm confused by how these js modules get used, as I don't see them referenced in the docker-compose.yaml or Dockerfile.

Are they useful to users in some way? If so, how can they access them? Is this something common you think we should do (bundle helper scripts w/ the infra modules)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they do seem unrelated, I'll remove them

up: `docker-compose up --detach`,
down: `docker-compose down`,
accounts: `docker container exec TEZOS_POLYWRAP_SANDBOX "/bin/sh" tezos-test-env.sh accounts`
}

module.exports = CMDS
10 changes: 10 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require("dotenv").config({ path: `${__dirname}/.env` });

const Config = {
PORT: process.env.TEZOS_POLYWRAP_PORT || 20000,
BLOCK_TIME: process.env.TEZOS_POLYWRAP_BLOCK_TIME || 3,
PLATFORM: process.env.TEZOS_POLYWRAP_PLATFORM || 'linux/arm64',
PROTOCOL: process.env.TEZOS_POLYWRAP_PROTOCOL || 'Hangzhou'
}

module.exports = Config
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: "3.9"

services:
tezos-node:
build: .
container_name: TEZOS_POLYWRAP_SANDBOX
platform: '${TEZOS_POLYWRAP_PLATFORM}'
ports:
- '${TEZOS_POLYWRAP_PORT}:20000'
environment:
- TEZOS_POLYWRAP_BLOCK_TIME=${TEZOS_POLYWRAP_BLOCK_TIME}
networks:
- tezos-node-test-env

networks:
tezos-node-test-env:
40 changes: 40 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
declare module '@blockwatch-cc/tezos-test-env' {
interface Node {
url: string
protocol: string
}

interface DeployResponse {
storageLimit: number
gasLimit: number
contractAddress: string
storageSize: number
consumedGas: number
fee: number
hash: string
}

interface Account {
name: string
publicKey: string
address: string
secretKey: string
}

interface UpResponse {
node: Node
accounts: Account[]
}

interface ContractInfo {
code: string
init?: string | object
storage?: unknown
}

function up(quiet?: boolean): Promise<UpResponse>
function down(quiet?: boolean): Promise<void>
function sleep(timeout: number): Promise<void>
function deployContract(account: Account, contractInfo: ContractInfo, confirmations?: number): Promise<DeployResponse>
}

108 changes: 108 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
const { exec } = require('child_process')

const cmds = require('./cmds')
const { PORT, PROTOCOL } = require('./config')
const { getClient, getSigner } = require('./taquito')

async function runCommand(command, quiet) {
if (!quiet) {
console.log(`> ${command}`)
}

return new Promise((resolve, reject) => {
const callback = (err, stdout, stderr) => {
if (err) {
reject(err)
} else {
if (!quiet) {
// the *entire* stdout and stderr (buffered)
console.log(`stdout: ${stdout}`)
console.log(`stderr: ${stderr}`)
}

resolve({stdout, stderr})
}
}

exec(command, { cwd: __dirname }, callback)
})
}

async function getAccounts(quiet) {
const { stderr } = await runCommand(cmds.accounts, quiet)
return parseAccounts(stderr)
}

async function up(quiet = true) {
await runCommand(cmds.up, quiet)

// get predefined funded accounts
const accounts = await getAccounts(quiet)

// wait for some seconds for containers to properly setup before resolving
// NB: fixes bug with failure to deploy contracts
await sleep(10000)

return Promise.resolve({
node: {
url: `http://localhost:${PORT}`,
protocol: PROTOCOL
},
accounts
})
}

async function sleep(timeout = 5000) {
await new Promise((resolve) => setTimeout(() => resolve(), timeout))
}

async function down(quiet = true) {
await runCommand(cmds.down, quiet)
// Sleep for a few seconds to make sure all services are torn down
await sleep()
}

async function deployContract(account, contractInfo, confirmation = 1) {
const { code, init, storage } = contractInfo
const client = getClient()
const signer = await getSigner(account.secretKey)
client.setSignerProvider(signer)
const operation = await client.contract.originate({
code,
init,
storage
});
await operation.confirmation(confirmation)
return {
storageLimit: operation.storageLimit,
gasLimit: operation.gasLimit,
contractAddress: operation.contractAddress,
storageSize: operation.storageSize,
consumedGas: operation.consumedGas,
fee: operation.fee,
hash: operation.hash,
revealStatus: operation.revealStatus
}
}

function parseAccounts(stream) {
const seperatedAccountStream = stream.split(/\n/gi)
const accounts = seperatedAccountStream.reduce((accumulator, account) => {
if (account === '') return accumulator
const splits = account.split(',')
accumulator.push({
name: splits[0],
publicKey: splits[1],
address: splits[2],
secretKey: splits[3].split(':')[1]
})
return accumulator
}, [])
return accounts
}

module.exports = {
up,
down,
deployContract
}
20 changes: 20 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@blockwatch-cc/tezos-test-env",
"version": "0.0.1-prealpha.63",
"description": "Tezos Polywrapper Test Environment",
"main": "index.js",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/blockwatch-cc/polywrap-tezos"
},
"scripts": {
"test:env:up": "node script.js up",
"test:env:down": "node script.js down"
},
"dependencies": {
"dotenv": "10.0.0",
"@taquito/taquito": "11.2.0",
"@taquito/signer": "11.2.0"
}
}
18 changes: 18 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const { up, down } = require('./index')

switch (process.argv[2]) {
case 'up':
up().catch((err) => {
console.log(err)
process.exit(1)
})
break
case 'down':
down().catch((err) => {
console.log(err)
process.exit(1)
})
break
default:
console.log('> ', 'Invalid command.')
}
18 changes: 18 additions & 0 deletions packages/cli/src/lib/defaults/infra-modules/tezos/taquito.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const { TezosToolkit } = require('@taquito/taquito')
const { InMemorySigner } = require('@taquito/signer')

const { PORT } = require('./config')

function getClient() {
const Tezos = new TezosToolkit(`http://localhost:${PORT}`)
return Tezos
}

async function getSigner(secretKey) {
return await InMemorySigner.fromSecretKey(secretKey)
}

module.exports = {
getClient,
getSigner
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/sh

# declare enviroment variables with default values
BLOCK_TIME=${TEZOS_POLYWRAP_BLOCK_TIME:-5}
PROTOCOL="${TEZOS_POLYWRAP_PROTOCOL:-Hangzhou}"
ROOT_PATH="${TEZOS_POLYWRAP_ROOT_PATH:-/tmp/mini-net}"

export bob="$(flextesa key bob)"
export alice="$(flextesa key alice)"

# flextesa startup script
startup() {
echo "starting tezos node with protocol ${PROTOCOL} ...."
flextesa mini-net \
--root "$ROOT_PATH" --size 3 "$@" \
--set-history-mode N000:archive \
--number-of-b 1 \
--balance-of-bootstrap-accounts tez:100_000_000 \
--time-b "$BLOCK_TIME" \
--add-bootstrap-account="$bob@2_000_000_000_000" \
--add-bootstrap-account="$alice@2_000_000_000_000" \
--no-daemons-for=bob \
--no-daemons-for=alice \
--until-level 200_000_000 \
--protocol-kind "$PROTOCOL"
}

# get bootstrapped accounts
accounts() {
cat >&2 <<EOF
$(echo $bob)
$(echo $alice)
EOF
}

"$@"
Loading