Skip to content

Commit

Permalink
Small improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
perekopskiy committed Jun 7, 2021
1 parent 41ec905 commit e241d67
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 176 deletions.
2 changes: 1 addition & 1 deletion docker/zk-environment/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ ENV RUSTUP_HOME=/usr/local/rustup \
PATH=/usr/local/cargo/bin:$PATH
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y
RUN cargo install diesel_cli --no-default-features --features postgres
RUN cargo install sqlx-cli
RUN cargo install --version=0.5.2 sqlx-cli

# Install `solc`
RUN curl -LO https://github.com/ethereum/solidity/releases/download/v0.5.16/solc-static-linux
Expand Down
9 changes: 0 additions & 9 deletions docs/setup-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,6 @@ Required by `binaryen` to build C++ sources. In order to speed it up, you might
sudo apt-get install cmake clang lld
```

## `aglio` and `dredd`

`aglio` is required for api documentation building. `dredd` is required for api documentation testing.

```bash
yarn global add aglio
yarn global add dredd
```

## Environment

Edit the lines below and add them to your shell profile file (e.g. `~/.bash_profile`):
Expand Down
159 changes: 159 additions & 0 deletions infrastructure/api-docs/src/compile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import * as fs from 'fs';
import * as path from 'path';
import * as handlebars from 'handlebars';
import * as zksync from 'zksync';
import * as ethers from 'ethers';

export function getDirPath() {
return path.join(process.env.ZKSYNC_HOME as string, 'infrastructure/api-docs');
}

function pasteAllFilesInOne() {
let template = handlebars.compile(fs.readFileSync(path.join(getDirPath(), 'blueprint/template.apib'), 'utf-8'), {
noEscape: true
});

let replaceObject: any = {};

const groupsFiles = fs.readdirSync(path.join(getDirPath(), 'blueprint/groups'));
for (let file of groupsFiles) {
const data = fs.readFileSync(path.join(getDirPath(), 'blueprint/groups', file), 'utf-8');
replaceObject[file.replace('.apib', '') + 'Endpoints'] = data;
}

const typesFiles = fs.readdirSync(path.join(getDirPath(), 'blueprint/types'));
for (const file of typesFiles) {
const data = fs.readFileSync(path.join(getDirPath(), 'blueprint/types', file), 'utf-8');
replaceObject[file.replace('.apib', '') + 'Types'] = data;
}

return template(replaceObject);
}

async function compileCommon() {
const data = pasteAllFilesInOne();
let template = handlebars.compile(data, { noEscape: true });

let replaceObject: any = await getHashesAndSignatures();
replaceObject['isResultNullable'] = '{{isResultNullable}}';

return template(replaceObject);
}

async function setupWallet() {
const pathToConfig = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant/eth.json`);
const config = fs.readFileSync(pathToConfig, {
encoding: 'utf-8'
});
const ethTestConfig = JSON.parse(config);
let web3Url = (process.env.ETH_CLIENT_WEB3_URL as string).split(',')[0];
const ethProvider = new ethers.providers.JsonRpcProvider(web3Url);
ethProvider.pollingInterval = 100;
const syncProvider = await zksync.getDefaultRestProvider('localhost');
const ethWallet = ethers.Wallet.fromMnemonic(ethTestConfig.test_mnemonic as string, "m/44'/60'/0'/0/0").connect(
ethProvider
);

const syncWallet = await zksync.Wallet.fromEthSigner(ethWallet, syncProvider);

const depositHandle = await syncWallet.depositToSyncFromEthereum({
depositTo: syncWallet.address(),
token: 'ETH',
amount: syncWallet.provider.tokenSet.parseToken('ETH', '1000')
});
await depositHandle.awaitReceipt();

if (!(await syncWallet.isSigningKeySet())) {
const changePubkeyHandle = await syncWallet.setSigningKey({
feeToken: 'ETH',
ethAuthType: 'ECDSA'
});
await changePubkeyHandle.awaitReceipt();
}

return syncWallet;
}

interface Parameters {
txHash: string;
txBatchHash: string;
address: string;
accountId: number;
pubKey: string;
l2Signature: string;
ethereumSignature: string;
}

async function getHashesAndSignatures() {
let syncWallet = await setupWallet();

const handle = await syncWallet.syncTransfer({ to: syncWallet.address(), token: 'ETH', amount: 0 });
await handle.awaitReceipt();
const txHash = handle.txHash;

const batch = await syncWallet
.batchBuilder()
.addTransfer({ to: syncWallet.address(), token: 'ETH', amount: 0 })
.build('ETH');
let txs = [];
for (const signedTx of batch.txs) {
txs.push(signedTx.tx);
}

const submitBatchResponse = await (syncWallet.provider as zksync.RestProvider).submitTxsBatchNew(
txs,
batch.signature
);
await syncWallet.provider.notifyTransaction(submitBatchResponse.transactionHashes[0], 'COMMIT');
const txBatchHash = submitBatchResponse.batchHash;

const signedTransfer = await syncWallet.signSyncTransfer({
to: '0xD3c62D2F7b6d4A63577F2415E55A6Aa6E1DbB9CA',
token: 'ETH',
amount: '17500000000000000',
fee: '12000000000000000000',
nonce: 12123,
validFrom: 0,
validUntil: 1239213821
});
const address = syncWallet.address();
const accountId = (await syncWallet.getAccountId())!;
const pubKey = signedTransfer.tx.signature!.pubKey;
const l2Signature = signedTransfer.tx.signature!.signature;
const ethereumSignature = signedTransfer.ethereumSignature!.signature;

let result: Parameters = {
txHash,
txBatchHash,
address,
accountId,
pubKey,
l2Signature,
ethereumSignature
};
return result;
}

export async function compileApibForDocumentation() {
const before = await compileCommon();
let template = handlebars.compile(before, { noEscape: true });

let replaceObject: any = {};
replaceObject['isResultNullable'] = ', nullable';

const after = template(replaceObject);

fs.writeFileSync(path.join(getDirPath(), 'blueprint/documentation.apib'), after);
}

export async function compileApibForTest() {
const before = await compileCommon();
let template = handlebars.compile(before, { noEscape: true });

let replaceObject: any = {};
replaceObject['isResultNullable'] = '';

const after = template(replaceObject);

fs.writeFileSync(path.join(getDirPath(), 'blueprint/test.apib'), after);
}
180 changes: 17 additions & 163 deletions infrastructure/api-docs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,168 +1,9 @@
import { Command, program } from 'commander';
import * as fs from 'fs';
import * as path from 'path';
import * as handlebars from 'handlebars';
import * as zksync from 'zksync';
import * as ethers from 'ethers';
import { compileApibForTest, compileApibForDocumentation, getDirPath } from './compile';
import { spawn } from './utils';

function getDirPath() {
return path.join(process.env.ZKSYNC_HOME as string, 'infrastructure/api-docs');
}

function pasteAllFilesInOne() {
let template = handlebars.compile(fs.readFileSync(path.join(getDirPath(), 'blueprint/template.apib'), 'utf-8'), {
noEscape: true
});

let replaceObject: any = {};

const groupsFiles = fs.readdirSync(path.join(getDirPath(), 'blueprint/groups'));
for (let file of groupsFiles) {
const data = fs.readFileSync(path.join(getDirPath(), 'blueprint/groups', file), 'utf-8');
replaceObject[file.replace('.apib', '') + 'Endpoints'] = data;
}

const typesFiles = fs.readdirSync(path.join(getDirPath(), 'blueprint/types'));
for (const file of typesFiles) {
const data = fs.readFileSync(path.join(getDirPath(), 'blueprint/types', file), 'utf-8');
replaceObject[file.replace('.apib', '') + 'Types'] = data;
}

return template(replaceObject);
}

async function compileCommon() {
const data = pasteAllFilesInOne();
let template = handlebars.compile(data, { noEscape: true });

let replaceObject: any = await getHashesAndSignatures();
replaceObject['isResultNullable'] = '{{isResultNullable}}';

return template(replaceObject);
}

async function setupWallet() {
const pathToConfig = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant/eth.json`);
const config = fs.readFileSync(pathToConfig, {
encoding: 'utf-8'
});
const ethTestConfig = JSON.parse(config);
let web3Url = (process.env.ETH_CLIENT_WEB3_URL as string).split(',')[0];
const ethProvider = new ethers.providers.JsonRpcProvider(web3Url);
ethProvider.pollingInterval = 100;
const syncProvider = await zksync.getDefaultRestProvider('localhost');
const ethWallet = ethers.Wallet.fromMnemonic(ethTestConfig.test_mnemonic as string, "m/44'/60'/0'/0/0").connect(
ethProvider
);

const syncWallet = await zksync.Wallet.fromEthSigner(ethWallet, syncProvider);

const depositHandle = await syncWallet.depositToSyncFromEthereum({
depositTo: syncWallet.address(),
token: 'ETH',
amount: syncWallet.provider.tokenSet.parseToken('ETH', '1000')
});
await depositHandle.awaitReceipt();

if (!(await syncWallet.isSigningKeySet())) {
const changePubkeyHandle = await syncWallet.setSigningKey({
feeToken: 'ETH',
ethAuthType: 'ECDSA'
});
await changePubkeyHandle.awaitReceipt();
}

return syncWallet;
}

interface Parameters {
txHash: string;
txBatchHash: string;
address: string;
accountId: number;
pubKey: string;
l2Signature: string;
ethereumSignature: string;
}

async function getHashesAndSignatures() {
let syncWallet = await setupWallet();

const handle = await syncWallet.syncTransfer({ to: syncWallet.address(), token: 'ETH', amount: 0 });
await handle.awaitReceipt();
const txHash = handle.txHash;

const batch = await syncWallet
.batchBuilder()
.addTransfer({ to: syncWallet.address(), token: 'ETH', amount: 0 })
.build('ETH');
let txs = [];
for (const signedTx of batch.txs) {
txs.push(signedTx.tx);
}

const submitBatchResponse = await (syncWallet.provider as zksync.RestProvider).submitTxsBatchNew(
txs,
batch.signature
);
await (syncWallet.provider as zksync.RestProvider).notifyAnyTransaction(
submitBatchResponse.transactionHashes[0],
'COMMIT'
);
const txBatchHash = submitBatchResponse.batchHash;

const signedTransfer = await syncWallet.signSyncTransfer({
to: '0xD3c62D2F7b6d4A63577F2415E55A6Aa6E1DbB9CA',
token: 'ETH',
amount: '17500000000000000',
fee: '12000000000000000000',
nonce: 12123,
validFrom: 0,
validUntil: 1239213821
});
const address = syncWallet.address();
const accountId = (await syncWallet.getAccountId())!;
const pubKey = signedTransfer.tx.signature!.pubKey;
const l2Signature = signedTransfer.tx.signature!.signature;
const ethereumSignature = signedTransfer.ethereumSignature!.signature;

let result: Parameters = {
txHash,
txBatchHash,
address,
accountId,
pubKey,
l2Signature,
ethereumSignature
};
return result;
}

async function compileApibForDocumentation() {
const before = await compileCommon();
let template = handlebars.compile(before, { noEscape: true });

let replaceObject: any = {};
replaceObject['isResultNullable'] = ', nullable';

const after = template(replaceObject);

fs.writeFileSync(path.join(getDirPath(), 'blueprint/documentation.apib'), after);
}

async function compileApibForTest() {
const before = await compileCommon();
let template = handlebars.compile(before, { noEscape: true });

let replaceObject: any = {};
replaceObject['isResultNullable'] = '';

const after = template(replaceObject);

fs.writeFileSync(path.join(getDirPath(), 'blueprint/test.apib'), after);
}

export const command = new Command('compile')
export const compile = new Command('compile')
.description('compile .apib files')
.option('--test', 'build test.apib')
.action(async (cmd: Command) => {
Expand All @@ -173,8 +14,21 @@ export const command = new Command('compile')
}
});

export const generateDocs = new Command('generate-docs')
.description('generate docs .html file')
.action(async (_cmd: Command) => {
const pathToApib = path.join(getDirPath(), 'blueprint/documentation.apib');
await spawn(`aglio -i ${pathToApib} -o index.html`);
});

export const test = new Command('test').description('test docs').action(async (_cmd: Command) => {
await spawn(`cd ${getDirPath()} && dredd`);
});

program.version('1.0.0').name('api-docs').description('api documentation tool');
program.addCommand(command);
program.addCommand(compile);
program.addCommand(generateDocs);
program.addCommand(test);

async function main() {
await program.parseAsync(process.argv);
Expand Down
14 changes: 14 additions & 0 deletions infrastructure/api-docs/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { spawn as _spawn } from 'child_process';

// executes a command in a new shell
// but pipes data to parent's stdout/stderr
export function spawn(command: string) {
command = command.replace(/\n/g, ' ');
const child = _spawn(command, { stdio: 'inherit', shell: true });
return new Promise((resolve, reject) => {
child.on('error', reject);
child.on('close', (code) => {
code == 0 ? resolve(code) : reject(`Child process exited with code ${code}`);
});
});
}
Loading

0 comments on commit e241d67

Please sign in to comment.