feat(cli-wallet): divide configurator and applicatoin

closes #3; #9;
This commit is contained in:
Wanseob Lim
2020-05-23 03:37:19 +09:00
parent 88afb3bd0d
commit be052d05f5
33 changed files with 798 additions and 253 deletions

View File

@@ -6,12 +6,12 @@ RUN apk add --no-cache --virtual .gyp \
&& npm install -g truffle ganache-cli \
&& apk del .gyp
WORKDIR /proj
COPY ./packages/contracts/package.json /proj/package.json
COPY ./package.json /proj/package.json
RUN npm install
COPY ./packages/contracts/contracts /proj/contracts
COPY ./packages/contracts/utils /proj/utils
COPY ./packages/contracts/migrations /proj/migrations
COPY ./packages/contracts/truffle-config.js /proj/truffle-config.js
COPY ./contracts /proj/contracts
COPY ./utils /proj/utils
COPY ./migrations /proj/migrations
COPY ./truffle-config.js /proj/truffle-config.js
RUN truffle compile
EXPOSE 5000
RUN ganache-cli --db=/data -i 20200406 -p 5000 --deterministic --host 0.0.0.0 & sleep 5 && truffle migrate --network integrationtest

View File

@@ -66,6 +66,7 @@
"@types/fs-extra": "^8.1.0",
"@types/hdkey": "^0.7.1",
"@types/jest": "^24.0.23",
"@types/node-fetch": "^2.5.7",
"@types/node-schedule": "^1.3.0",
"@types/pino": "^6.0.0",
"@types/prompts": "^2.0.8",

View File

@@ -11,7 +11,7 @@
"~zk-wizard": "dist"
},
"bin": {
"cli-wallet": "dist/index.js"
"cli-wallet": "dist/cli.js"
},
"keywords": [
"cli"
@@ -28,8 +28,9 @@
"test:ci": "jest --coverage --ci --reporters='jest-junit'",
"coverage": "jest --coverage",
"coverage:show": "live-server coverage",
"dev": "ts-node src/index.ts --ws ws://localhost:5000 -f",
"start": "node dist/index.js"
"dev": "ts-node src/cli.ts -f --ws ws://localhost:5000 --coordinator http://localhost:8888",
"dev:config": "ts-node src/cli.ts --config wallet.json",
"start": "node dist/cli.js"
},
"dependencies": {
"@nano-sql/adapter-leveldb": "^2.0.5",
@@ -54,6 +55,7 @@
"tar": "^6.0.2",
"web3": "^1.2.6",
"web3-core": "^1.2.6",
"web3-utils": "^1.2.6",
"web3-eth-contract": "^1.2.6",
"yargs": "^15.3.1"
},

View File

@@ -0,0 +1,24 @@
import { PromptApp } from '@zkopru/utils'
import { ZkAccount } from '@zkopru/account'
import { ZkWallet } from '../zk-wallet'
export enum AppMenu {
TOP_MENU,
ACCOUNT_DETAIL,
DEPOSIT_ETHER,
EXIT,
}
export interface Context {
menu: AppMenu
account?: ZkAccount
}
export default abstract class App extends PromptApp<Context, ZkWallet> {
zkWallet: ZkWallet
constructor(zkWallet: ZkWallet, onCancel: () => Promise<void>) {
super(zkWallet, onCancel)
this.zkWallet = zkWallet
}
}

View File

@@ -0,0 +1,26 @@
import { ZkWallet } from '../zk-wallet'
import { AppMenu, Context } from './app'
import TopMenu from './menus/top-menus'
export async function runCliApp(
zkWallet: ZkWallet,
onError?: () => Promise<void>,
): Promise<void> {
const defaultOnCancel = () => {
process.exit()
}
const onCancel = onError || defaultOnCancel
let context: Context = {
menu: AppMenu.TOP_MENU,
}
const menus = {}
menus[AppMenu.TOP_MENU] = new TopMenu(zkWallet, onCancel)
while (context.menu !== AppMenu.EXIT) {
const menu = menus[context.menu]
if (menu) {
context = await menu.run(context)
} else {
break
}
}
}

View File

@@ -0,0 +1,31 @@
import chalk from 'chalk'
import App, { AppMenu, Context } from '../app'
const { goTo, print } = App
export default class AccountDetail extends App {
static code = AppMenu.ACCOUNT_DETAIL
// eslint-disable-next-line class-methods-use-this
async run(context: Context): Promise<Context> {
if (!context.account) throw Error('Acocunt is not set')
const spendables = await this.zkWallet.getSpendables(context.account)
print(chalk.greenBright)(
`Ether: ${spendables.eth.divn(18).toString()} Ether`,
)
const { choice } = await this.ask({
type: 'select',
name: 'choice',
initial: 0,
message: 'What do you want to do?',
choices: [
{ title: 'Go to top menu', value: AppMenu.TOP_MENU },
{
title: 'Deposit Ether to the zkopru network',
value: AppMenu.DEPOSIT_ETHER,
},
],
})
return { ...goTo(context, choice) }
}
}

View File

@@ -1,15 +1,14 @@
import chalk from 'chalk'
import { ZkAccount } from '@zkopru/account'
import App, { Context, Menu } from '../app'
import App, { AppMenu, Context } from '../app'
const { goTo } = App
export default class SelectAccount extends App {
export default class TopMenu extends App {
static code = AppMenu.TOP_MENU
// eslint-disable-next-line class-methods-use-this
async run(context: Context): Promise<Context> {
if (!context.wallet) {
throw Error(chalk.red('Wallet is not loaded'))
}
const accounts: ZkAccount[] = await context.wallet.retrieveAccounts()
const accounts: ZkAccount[] = await this.zkWallet.wallet.retrieveAccounts()
const { idx } = await this.ask({
type: 'select',
name: 'idx',
@@ -27,10 +26,11 @@ export default class SelectAccount extends App {
})
switch (idx) {
case -1:
return { ...goTo(context, Menu.EXIT) }
return { ...goTo(context, AppMenu.EXIT) }
default:
this.zkWallet.setAccount(idx)
return {
...goTo(context, Menu.ACCOUNT_DETAIL),
...goTo(context, AppMenu.ACCOUNT_DETAIL),
account: accounts[idx],
}
}

View File

@@ -0,0 +1,90 @@
#!/usr/bin/env node
/* eslint-disable no-case-declarations */
import yargs from 'yargs'
import fs from 'fs'
import { Config } from './configurator/configurator'
import { getZkWallet } from './configurator'
import { runCliApp } from './app'
const { argv }: { argv: Config } = yargs
.scriptName('zk-wizard')
.usage('$0 <command> [args]')
.options({
fullnode: {
type: 'boolean',
default: false,
alias: 'f',
describe: 'Run a full-node zkopru wallet',
},
develop: {
type: 'boolean',
default: false,
alias: 'd',
describe: 'Run a develop version',
},
networkId: {
type: 'number',
alias: 'n',
default: 1,
},
chainId: {
type: 'number',
alias: 'c',
default: 1,
},
address: {
type: 'string',
alias: 'a',
default: '0x7C728214be9A0049e6a86f2137ec61030D0AA964',
},
coordinator: {
type: 'string',
alias: 'r',
default: 'https://coordinator.zkopru.network',
},
websocket: {
type: 'string',
alias: 'ws',
default: 'ws://ws.zkopru.network',
},
keys: {
type: 'string',
default: 'keys',
describe: 'Path to store SNARK keys',
},
db: {
type: 'string',
default: 'db',
},
mnemonic: {
type: 'string',
default: undefined,
},
config: {
type: 'string',
describe: 'You can save cli-wallet configuration file',
},
})
.help()
const main = async () => {
let config: Config = argv
if (argv.config) {
config = {
...JSON.parse(fs.readFileSync(argv.config).toString('utf8')),
...argv,
}
if (!config.seedKeystore)
throw Error('You should setup the keystore in the config file')
}
console.log('config is ', config)
const zkWallet = await getZkWallet(config)
console.log('get zkwallet', zkWallet)
await runCliApp(zkWallet)
}
;(async () => {
await main()
})().catch(e => {
console.error(e)
})

View File

@@ -2,19 +2,26 @@ import Web3 from 'web3'
import { InanoSQLInstance } from '@nano-sql/core/lib/interfaces'
import { ZkOPRUNode, NetworkStatus } from '@zkopru/core'
import { ZkAccount, HDWallet } from '@zkopru/account'
import { ZkWizard } from '@zkopru/zk-wizard'
import { WebsocketProvider } from 'web3-core'
import { PromptApp } from '@zkopru/utils'
import { HDWalletSql } from '@zkopru/database'
import { ZkWallet } from '../zk-wallet'
export interface Config {
fullnode: boolean
develop: boolean
address: string
bootstrap: string
coordinator: string
websocket: string
keys: string
db: string
config?: string
mnemonic?: string
erc20?: string[]
erc721?: string[]
seedKeystore?: HDWalletSql
password?: string
accountNumber?: number
}
export enum Menu {
@@ -24,7 +31,7 @@ export enum Menu {
LOAD_DATABASE,
LOAD_HDWALLET,
CONFIG_TRACKING_ACCOUNT,
SELECT_ACCOUNT,
SAVE_CONFIG,
SHOW_UTXOS,
LOAD_NODE,
NODE_SYNC,
@@ -43,8 +50,10 @@ export interface Context {
wallet?: HDWallet
account?: ZkAccount
node?: ZkOPRUNode
wizard?: ZkWizard
accounts?: ZkAccount[]
zkWallet?: ZkWallet
passwordHash?: string
isInitialSetup?: boolean
}
export default abstract class App extends PromptApp<Context, Config> {}
export default abstract class Configurator extends PromptApp<Context, Config> {}

View File

@@ -0,0 +1,50 @@
#!/usr/bin/env node
/* eslint-disable no-case-declarations */
import { NetworkStatus } from '@zkopru/core'
import { Menu, Context, Config } from './configurator'
import Splash from './menus/splash'
import ConnectWeb3 from './menus/connect-web3'
import DownloadKeys from './menus/download-keys'
import LoadDatabase from './menus/load-database'
import LoadHDWallet from './menus/load-hdwallet'
import LoadNode from './menus/load-node'
import TrackingAccount from './menus/config-tracking-accounts'
import NodeSync from './menus/node-sync'
import SaveConfig from './menus/save-config'
import { ZkWallet } from '../zk-wallet'
const defaultOnCancel = () => {
process.exit()
}
export async function getZkWallet(
config: Config,
onError?: () => Promise<void>,
): Promise<ZkWallet> {
const onCancel = onError || defaultOnCancel
let context: Context = {
menu: Menu.SPLASH,
networkStatus: NetworkStatus.STOPPED,
}
const menus = {}
menus[Menu.SPLASH] = new Splash(config, onCancel)
menus[Menu.CONNECT_WEB3] = new ConnectWeb3(config, onCancel)
menus[Menu.DOWNLOAD_KEYS] = new DownloadKeys(config, onCancel)
menus[Menu.LOAD_DATABASE] = new LoadDatabase(config, onCancel)
menus[Menu.LOAD_HDWALLET] = new LoadHDWallet(config, onCancel)
menus[Menu.CONFIG_TRACKING_ACCOUNT] = new TrackingAccount(config, onCancel)
menus[Menu.LOAD_NODE] = new LoadNode(config, onCancel)
menus[Menu.NODE_SYNC] = new NodeSync(config, onCancel)
menus[Menu.SAVE_CONFIG] = new SaveConfig(config, onCancel)
while (context.menu !== Menu.EXIT) {
const menu = menus[context.menu]
if (menu) {
context = await menu.run(context)
} else {
break
}
}
if (!context.zkWallet) throw Error('Wallet is not configured')
return context.zkWallet
}

View File

@@ -1,18 +1,31 @@
import chalk from 'chalk'
import { ZkAccount } from '@zkopru/account'
import App, { Context, Menu } from '../app'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = App
const { print, goTo } = Configurator
export default class TrackingAccount extends Configurator {
static code = Menu.CONFIG_TRACKING_ACCOUNT
export default class TrackingAccount extends App {
async run(context: Context): Promise<Context> {
if (!context.wallet) {
throw Error(chalk.red('Wallet is not loaded'))
}
print(chalk.blue)('Configure accounts to keep tracking')
print(chalk.blue)('My account list')
if (this.config.accountNumber) {
await Promise.all(
Array(this.config.accountNumber).map((_, index) =>
context.wallet?.createAccount(index),
),
)
return { ...goTo(context, Menu.SAVE_CONFIG) }
}
const accounts: ZkAccount[] = await context.wallet.retrieveAccounts()
accounts.forEach((account, i) => print()(`${i}: ${account.address}`))
if (!context.isInitialSetup) {
return { ...goTo(context, Menu.SAVE_CONFIG), accounts }
}
const { idx } = await this.ask({
type: 'select',
name: 'idx',
@@ -35,7 +48,7 @@ export default class TrackingAccount extends App {
reRun = await this.run(context)
return reRun
case 1:
return { ...goTo(context, Menu.LOAD_NODE), accounts }
return { ...goTo(context, Menu.SAVE_CONFIG), accounts }
default:
return { ...goTo(context, Menu.EXIT), accounts }
}

View File

@@ -1,15 +1,20 @@
import chalk from 'chalk'
import Web3 from 'web3'
import App, { Context, Menu } from '../app'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = App
const { print, goTo } = Configurator
export default class ConnectWeb3 extends Configurator {
static code = Menu.CONNECT_WEB3
export default class ConnectWeb3 extends App {
async run(context: Context): Promise<Context> {
print(chalk.blue)('Connecting to the Ethereum network')
const provider = new Web3.providers.WebsocketProvider(this.config.websocket, {
reconnect: { auto: true },
})
const provider = new Web3.providers.WebsocketProvider(
this.config.websocket,
{
reconnect: { auto: true },
},
)
const web3 = new Web3(provider)
async function waitConnection() {
return new Promise<void>(res => {

View File

@@ -4,9 +4,9 @@ import fs from 'fs-extra'
import tar from 'tar'
import { SingleBar } from 'cli-progress'
import { https } from 'follow-redirects'
import App, { Context, Menu } from '../app'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = App
const { print, goTo } = Configurator
export const downloadKeys = async (url: string, path: string) => {
return new Promise((resolve, reject) => {
@@ -41,7 +41,9 @@ export const downloadKeys = async (url: string, path: string) => {
})
}
export default class DownloadKeys extends App {
export default class DownloadKeys extends Configurator {
static code = Menu.DOWNLOAD_KEYS
async run(context: Context): Promise<Context> {
print(chalk.blue)('Downloading keys')
const pwd = path.join(process.cwd(), this.config.keys)

View File

@@ -6,9 +6,9 @@ import { InanoSQLInstance, nSQL } from '@nano-sql/core'
import { schema, ChainConfig } from '@zkopru/database'
import { InanoSQLAdapter } from '@nano-sql/core/lib/interfaces'
import { L1Contract } from '@zkopru/core'
import App, { Context, Menu } from '../app'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = App
const { print, goTo } = Configurator
async function initDB({
name,
@@ -69,9 +69,7 @@ async function initDB({
})
.exec()) as ChainConfig[]
zkopruId = createResult[0].id
console.log('create result', createResult[0])
} else {
console.log('query result', queryResult[0])
zkopruId = queryResult[0].id
}
return {
@@ -80,7 +78,9 @@ async function initDB({
}
}
export default class LoadDatabase extends App {
export default class LoadDatabase extends Configurator {
static code = Menu.LOAD_DATABASE
async run(context: Context): Promise<Context> {
print(chalk.blue)('Loading database')
if (!context.web3) {

View File

@@ -2,11 +2,13 @@ import chalk from 'chalk'
import { HDWallet, ZkAccount } from '@zkopru/account'
import { validateMnemonic, wordlists } from 'bip39'
import { HDWalletSql } from '@zkopru/database'
import App, { Context, Menu } from '../app'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = App
const { print, goTo } = Configurator
export default class LoadHDWallet extends Configurator {
static code = Menu.LOAD_HDWALLET
export default class LoadHDWallet extends App {
async run(context: Context): Promise<Context> {
if (!context.db) {
throw Error('Database is not loaded')
@@ -16,8 +18,13 @@ export default class LoadHDWallet extends App {
}
const { web3, db } = context
const wallet = new HDWallet(web3, db)
const existingWallets = await wallet.list()
if (existingWallets.length === 0) {
let existingWallets!: HDWalletSql[]
if (!this.config.seedKeystore) {
existingWallets = await wallet.list()
}
const createNewWallet: boolean =
!this.config.seedKeystore && existingWallets.length === 0
if (createNewWallet) {
let mnemonic: string
if (this.config.mnemonic) {
print()('Using imported mnemonic words')
@@ -97,16 +104,29 @@ export default class LoadHDWallet extends App {
return result
}
}
const { password } = await this.ask({
type: 'password',
name: 'password',
message: 'Type password',
})
await wallet.init(mnemonic, password)
let confirmed = false
let confirmedPassword!: string
do {
const { password } = await this.ask({
type: 'password',
name: 'password',
message: 'password',
})
const { retyped } = await this.ask({
type: 'password',
name: 'retyped',
message: 'confirm password',
})
confirmed = password === retyped
confirmedPassword = password
} while (!confirmed)
await wallet.init(mnemonic, confirmedPassword)
}
} else {
let existing!: HDWalletSql
if (existingWallets.length === 1) {
if (this.config.seedKeystore) {
existing = this.config.seedKeystore
} else if (existingWallets.length === 1) {
existing = existingWallets[0] as HDWalletSql
} else if (existingWallets.length > 1) {
const { idx } = await this.ask({
@@ -127,11 +147,13 @@ export default class LoadHDWallet extends App {
}
existing = existingWallets[idx]
}
const { password } = await this.ask({
type: 'password',
name: 'password',
message: 'Type password',
})
const { password } = this.config.password
? this.config
: await this.ask({
type: 'password',
name: 'password',
message: 'Type password',
})
try {
await wallet.load(existing, password)
} catch (err) {
@@ -146,6 +168,10 @@ export default class LoadHDWallet extends App {
const account = await wallet.createAccount(0)
accounts = [account]
}
return { ...goTo(context, Menu.CONFIG_TRACKING_ACCOUNT), wallet }
return {
...goTo(context, Menu.CONFIG_TRACKING_ACCOUNT),
wallet,
isInitialSetup: createNewWallet,
}
}
}

View File

@@ -5,11 +5,13 @@ import {
LightNode,
HttpBootstrapHelper,
} from '@zkopru/core'
import App, { Context, Menu } from '../app'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = App
const { print, goTo } = Configurator
export default class LoadNode extends Configurator {
static code = Menu.LOAD_NODE
export default class LoadNode extends App {
// eslint-disable-next-line class-methods-use-this
async run(context: Context): Promise<Context> {
if (!context.provider) throw Error('Websocket provider does not exist')
@@ -19,7 +21,7 @@ export default class LoadNode extends App {
throw Error('Websocket provider is not connected')
let node: ZkOPRUNode
const { provider, db, accounts } = context
const { address, bootstrap } = this.config
const { address, coordinator: bootstrap } = this.config
if (this.config.fullnode) {
node = await FullNode.new({
provider,
@@ -47,7 +49,6 @@ export default class LoadNode extends App {
print(chalk.blue)(`Bootstrap light node from ${bootstrap}`)
await node.bootstrap()
}
node.startSync()
return { ...goTo(context, Menu.NODE_SYNC), node }
}
}

View File

@@ -1,14 +1,17 @@
import chalk from 'chalk'
import { NetworkStatus } from '@zkopru/core'
import App, { Context, Menu } from '../app'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = App
const { print, goTo } = Configurator
export default class NodeSync extends Configurator {
static code = Menu.NODE_SYNC
export default class NodeSync extends App {
// eslint-disable-next-line class-methods-use-this
async run(context: Context): Promise<Context> {
const { node } = context
if (!node) throw Error('ZKOPRU node is not defined')
print(chalk.blue)('Synchronizing... ')
return new Promise<Context>((res, rej) => {
node.synchronizer.on('status', (status: NetworkStatus) => {
switch (status) {
@@ -17,10 +20,10 @@ export default class NodeSync extends App {
break
case NetworkStatus.LIVE:
print(chalk.green)('ZKOPRU network is on live')
res(goTo(context, Menu.SELECT_ACCOUNT))
res(goTo(context, Menu.SAVE_CONFIG))
break
case NetworkStatus.ON_SYNCING:
print(chalk.green)('Synchronizing ZKOPRU network')
print(chalk.blue)('Synchronizing ZKOPRU network')
break
case NetworkStatus.FULLY_SYNCED:
print(chalk.green)('Synchronizing is fully synced')
@@ -35,6 +38,7 @@ export default class NodeSync extends App {
break
}
})
node.startSync()
})
}
}

View File

@@ -0,0 +1,71 @@
import chalk from 'chalk'
import path from 'path'
import fs from 'fs'
import { HDWalletSql } from '@zkopru/database'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = Configurator
export default class SaveConfig extends Configurator {
static code = Menu.SAVE_CONFIG
async run(context: Context): Promise<Context> {
if (!context.isInitialSetup) return { ...goTo(context, Menu.LOAD_NODE) }
const { save } = await this.ask({
type: 'confirm',
initial: true,
name: 'save',
message: 'Do you want to save this configuration?',
})
if (!save) {
return { ...goTo(context, Menu.LOAD_NODE) }
}
let exported = false
let seedKeystore!: HDWalletSql
if (!context.wallet) throw Error('Wallet is not configured')
do {
const { password } = await this.ask({
type: 'password',
name: 'password',
message: 'Type your password',
})
try {
seedKeystore = context.wallet.export(password)
exported = true
} catch (err) {
exported = false
}
} while (!exported)
let pathConfirmed = false
let configPath!: string
do {
const { filePath } = await this.ask({
type: 'text',
name: 'filePath',
initial: `${path.resolve(path.join('wallet.json'))}`,
message: 'Save to',
})
configPath = filePath
if (!fs.existsSync(filePath)) pathConfirmed = true
else {
const { overwrite } = await this.ask({
type: 'confirm',
initial: false,
name: 'overwrite',
message:
'You may overwrite exising config file. Do you want to overwrite?',
})
pathConfirmed = overwrite
}
} while (!pathConfirmed)
const newConfig = {
...this.config,
seedKeystore,
accountNumber: context.accounts?.length,
}
fs.writeFileSync(configPath, JSON.stringify(newConfig))
print(chalk.blue)('Successfully created wallet.json')
return { ...goTo(context, Menu.LOAD_NODE) }
}
}

View File

@@ -0,0 +1,18 @@
import chalk from 'chalk'
import figlet from 'figlet'
import Configurator, { Context, Menu } from '../configurator'
const { print, goTo } = Configurator
export default class Splash extends Configurator {
static code = Menu.SPLASH
// eslint-disable-next-line class-methods-use-this
async run(context: Context): Promise<Context> {
print(chalk.cyan)(figlet.textSync('ZK', 'Isometric3'))
print(chalk.cyan)(figlet.textSync('OPRU', 'Isometric3'))
print(chalk.cyan)('\n =========================')
print(chalk.cyan)(figlet.textSync('wallet', 'Small'))
return goTo(context, Menu.CONNECT_WEB3)
}
}

View File

@@ -1,104 +0,0 @@
#!/usr/bin/env node
/* eslint-disable no-case-declarations */
import yargs from 'yargs'
import { NetworkStatus } from '@zkopru/core'
import { Menu, Context, Config } from './app'
import Splash from './menus/splash'
import ConnectWeb3 from './menus/connect-web3'
import DownloadKeys from './menus/download-keys'
import LoadDatabase from './menus/load-database'
import LoadHDWallet from './menus/load-hdwallet'
import LoadNode from './menus/load-node'
import SelectAccount from './menus/select-account'
import TrackingAccount from './menus/config-tracking-accounts'
import NodeSync from './menus/node-sync'
const { argv }: { argv: Config } = yargs
.scriptName('zk-wizard')
.usage('$0 <command> [args]')
.options({
fullnode: {
type: 'boolean',
default: false,
alias: 'f',
describe: 'Run a full-node zkopru wallet',
},
develop: {
type: 'boolean',
default: false,
alias: 'd',
describe: 'Run a develop version',
},
networkId: {
type: 'number',
alias: 'n',
default: 1,
},
chainId: {
type: 'number',
alias: 'c',
default: 1,
},
address: {
type: 'string',
alias: 'a',
default: '0x7C728214be9A0049e6a86f2137ec61030D0AA964',
},
bootstrap: {
type: 'string',
alias: 'b',
default: 'https://bootstrap.zkopru.network',
},
websocket: {
type: 'string',
alias: 'ws',
default: 'ws://ws.zkopru.network',
},
keys: {
type: 'string',
default: 'keys',
describe: 'Path to store SNARK keys',
},
db: {
type: 'string',
default: 'db',
},
mnemonic: {
type: 'string',
default: undefined,
},
})
.help()
const onCancel = () => {
process.exit()
}
const main = async () => {
let app: Context = { menu: Menu.SPLASH, networkStatus: NetworkStatus.STOPPED }
const menus = {}
menus[Menu.SPLASH] = new Splash(argv, onCancel)
menus[Menu.CONNECT_WEB3] = new ConnectWeb3(argv, onCancel)
menus[Menu.DOWNLOAD_KEYS] = new DownloadKeys(argv, onCancel)
menus[Menu.LOAD_DATABASE] = new LoadDatabase(argv, onCancel)
menus[Menu.LOAD_HDWALLET] = new LoadHDWallet(argv, onCancel)
menus[Menu.CONFIG_TRACKING_ACCOUNT] = new TrackingAccount(argv, onCancel)
menus[Menu.LOAD_NODE] = new LoadNode(argv, onCancel)
menus[Menu.NODE_SYNC] = new NodeSync(argv, onCancel)
menus[Menu.SELECT_ACCOUNT] = new SelectAccount(argv, onCancel)
while (app.menu !== Menu.EXIT) {
const menu = menus[app.menu]
if (menu) {
app = await menu.run(app)
} else {
break
}
}
onCancel()
}
;(async () => {
await main()
})().catch(e => {
console.error(e)
})

View File

@@ -1,13 +0,0 @@
import chalk from 'chalk'
import figlet from 'figlet'
import App, { Context, Menu } from '../app'
const { print, goTo } = App
export default class Splash extends App {
// eslint-disable-next-line class-methods-use-this
async run(context: Context): Promise<Context> {
print(chalk.cyan)(figlet.textSync('ZKOPRU', 'Isometric3'))
return goTo(context, Menu.CONNECT_WEB3)
}
}

View File

@@ -0,0 +1,288 @@
import { Utxo, Note, UtxoStatus, Sum } from '@zkopru/transaction'
import { Field, F, Point } from '@zkopru/babyjubjub'
import { schema, UtxoSql } from '@zkopru/database'
import { InanoSQLInstance } from '@nano-sql/core'
import { HDWallet, ZkAccount } from '@zkopru/account'
import { ZkOPRUNode, L1Contract } from '@zkopru/core'
import { logger } from '@zkopru/utils'
export interface Balance {
eth: string
erc20: { [addr: string]: string }
erc721: { [addr: string]: string }
}
export class ZkWallet {
zkopruId: string
db: InanoSQLInstance
wallet: HDWallet
account: ZkAccount
node: ZkOPRUNode
accounts: ZkAccount[]
erc20: string[]
erc721: string[]
cached: {
layer1: {
balance?: Balance
nfts?: string[]
}
}
constructor({
zkopruId,
db,
wallet,
account,
node,
accounts,
erc20,
erc721,
}: {
zkopruId: string
db: InanoSQLInstance
wallet: HDWallet
account: ZkAccount
node: ZkOPRUNode
accounts: ZkAccount[]
erc20: string[]
erc721: string[]
}) {
this.zkopruId = zkopruId
this.db = db
this.wallet = wallet
this.node = node
this.accounts = accounts
this.account = account
this.erc20 = erc20
this.erc721 = erc721
this.cached = {
layer1: {},
}
}
setAccount(account: number | ZkAccount) {
if (typeof account === 'number') {
this.account = this.accounts[account]
} else {
this.account = account
}
}
async getSpendableUtxos(account: ZkAccount): Promise<Utxo[]> {
const utxoSqls: UtxoSql[] = (await this.db
.selectTable(schema.utxo.name)
.presetQuery('getSpendables', {
zkopru: this.zkopruId,
pubKeys: [account.pubKey.toHex()],
})
.exec()) as UtxoSql[]
const utxos: Utxo[] = []
utxoSqls.forEach(obj => {
if (!obj.eth) throw Error('should have Ether data')
if (!obj.pubKey) throw Error('should have pubkey data')
if (!(account.pubKey.toHex() === obj.pubKey))
throw Error('should have same pubkey')
if (!obj.salt) throw Error('should have salt data')
if (!(obj.status === UtxoStatus.NON_INCLUDED || obj.status === undefined))
throw Error('should have undefined status or NON_INCLUDED status')
let note!: Note
if (!obj.tokenAddr) {
note = Note.newEtherNote({
eth: obj.eth,
pubKey: account.pubKey,
salt: obj.salt,
})
} else if (obj.erc20Amount) {
note = Note.newERC20Note({
eth: obj.eth,
pubKey: account.pubKey,
salt: obj.salt,
tokenAddr: obj.tokenAddr,
erc20Amount: obj.erc20Amount,
})
} else if (obj.nft) {
note = Note.newNFTNote({
eth: obj.eth,
pubKey: account.pubKey,
salt: obj.salt,
tokenAddr: obj.tokenAddr,
nft: obj.nft,
})
} else {
throw Error('Not enough data to recover utxo')
}
utxos.push(Utxo.from(note))
})
return utxos
}
async getSpendables(account: ZkAccount): Promise<Sum> {
const utxos: Utxo[] = await this.getSpendableUtxos(account)
const assets = Sum.from(utxos)
return assets
}
async getLayer1Assets(
account: ZkAccount,
erc20Addrs?: string[],
erc721Addrs?: string[],
): Promise<Balance> {
const balance: Balance = {
eth: '0',
erc20: {},
erc721: {},
}
const promises: (() => Promise<void>)[] = []
const { web3 } = this.node.l1Contract
promises.push(async () => {
balance.eth = await web3.eth.getBalance(account.address)
})
if (erc20Addrs) {
promises.push(
...erc20Addrs.map(addr => async () => {
balance.erc20[addr] = await L1Contract.asIERC20(web3, addr)
.methods.balanceOf(account.address)
.call()
}),
)
}
if (erc721Addrs) {
promises.push(
...erc721Addrs.map(addr => async () => {
balance.erc721[addr] = await L1Contract.asIERC721(web3, addr)
.methods.balanceOf(account.address)
.call()
}),
)
}
await Promise.all(promises.map(task => task()))
this.cached.layer1.balance = balance
return balance
}
async listLayer1Nfts(
account: ZkAccount,
erc721Addr: string,
balance: number,
): Promise<string[]> {
const promises: (() => Promise<void>)[] = []
const nfts: string[] = []
const { web3 } = this.node.l1Contract
// 0x4f6ccce7 = tokenOfOwnerByIndex func sig
const supportEnumeration = await L1Contract.asIERC721(web3, erc721Addr)
.methods.supportsInterface('0x4f6ccce7')
.call()
if (supportEnumeration) {
promises.push(
...Array(balance)
.fill(0)
.map((_, i) => async () => {
nfts[i] = await L1Contract.asIERC721Enumerable(web3, erc721Addr)
.methods.tokenOfOwnerByIndex(account.address, i)
.call()
}),
)
await Promise.all(promises.map(task => task()))
return nfts
}
logger.error('It does not support tokenOfOwnerByIndex() interface')
return []
}
async depositEther(eth: F, fee: F, to?: Point) {
if (!this.cached.layer1.balance) {
logger.error('fetch balance first')
return
}
if (
Field.strictFrom(this.cached.layer1.balance.eth).lt(
Field.strictFrom(eth).add(Field.strictFrom(fee)),
)
) {
logger.error('Not enough Ether')
return
}
const note = Note.newEtherNote({
eth,
pubKey: to || this.account.pubKey,
})
await this.deposit(note, Field.strictFrom(fee))
}
async depositERC20(eth: F, addr: string, amount: F, fee: F, to?: Point) {
if (!this.cached.layer1.balance) {
logger.error('fetch balance first')
return
}
if (
Field.strictFrom(this.cached.layer1.balance.eth).lt(
Field.strictFrom(eth).add(Field.strictFrom(fee)),
)
) {
logger.error('Not enough Ether')
return
}
if (
Field.strictFrom(this.cached.layer1.balance.erc20[addr]).lt(
Field.strictFrom(amount),
)
) {
logger.error('Not enough ERC20 balance')
return
}
const note = Note.newERC20Note({
eth,
pubKey: to || this.account.pubKey,
tokenAddr: addr,
erc20Amount: amount,
})
await this.deposit(note, Field.strictFrom(fee))
}
async depositERC721(eth: F, addr: string, nft: F, fee: F, to?: Point) {
if (!this.cached.layer1.balance) {
logger.error('fetch balance first')
return
}
if (
Field.strictFrom(this.cached.layer1.balance.eth).lt(
Field.strictFrom(eth).add(Field.strictFrom(fee)),
)
) {
logger.error('Not enough Ether')
return
}
const note = Note.newNFTNote({
eth,
pubKey: to || this.account.pubKey,
tokenAddr: addr,
nft,
})
await this.deposit(note, Field.strictFrom(fee))
}
private async deposit(note: Note, fee: Field) {
await this.node.l1Contract.user.methods
.deposit(
note.eth.toString(),
note.salt.toString(),
note.tokenAddr.toHex(20),
note.erc20Amount.toString(),
note.nft.toString(),
[note.pubKey.x.toString(), note.pubKey.y.toString()],
fee.toString(),
)
.send({ from: this.account.address })
}
}

View File

@@ -0,0 +1 @@
{"_":[],"fullnode":true,"f":true,"develop":false,"d":false,"ws":"ws://localhost:5000","websocket":"ws://localhost:5000","coordinator":"http://localhost:8888","r":"http://localhost:8888","networkId":1,"n":1,"network-id":1,"chainId":1,"c":1,"chain-id":1,"address":"0x7C728214be9A0049e6a86f2137ec61030D0AA964","a":"0x7C728214be9A0049e6a86f2137ec61030D0AA964","keys":"keys","db":"db","$0":"zk-wizard","seedKeystore":{"ciphertext":"f34047785c14c5b1b87ce540c1bbd0bdb748f7ddf95fdf95d2d1e462de1dde98cf7815e280084111567fc3aac24225aa","iv":"188e2d6b2c7f7a6fecc9d850aa3a8914","algorithm":"aes-256-cbc","keylen":32,"kdf":"scrypt","kdfParams":{"N":16384,"r":8,"p":1},"salt":"9950f726377129f30ad64e5f56e5a4077765ecf433e677481f9ce141c474e011"},"accountNumber":3}

View File

@@ -6,6 +6,7 @@ export enum NodeType {
}
export interface L1Config {
genesisBlock: string
utxoTreeDepth: number
withdrawalTreeDepth: number
nullifierTreeDepth: number

135
yarn.lock
View File

@@ -1751,6 +1751,14 @@
dependencies:
"@types/node" "*"
"@types/node-fetch@^2.5.7":
version "2.5.7"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c"
integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==
dependencies:
"@types/node" "*"
form-data "^3.0.0"
"@types/node-schedule@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@types/node-schedule/-/node-schedule-1.3.0.tgz#100f69078e74d736d59433fc4634ff49d0a9142d"
@@ -1977,12 +1985,12 @@
mz "^2.5.0"
"@zkopru/account@file:packages/account":
version "0.0.1"
version "0.0.3"
dependencies:
"@nano-sql/core" "^2.3.7"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-account-0.0.1-e1de4d80-c9ad-4fa4-be7e-27258c76ffbc-1589800833134/node_modules/@zkopru/babyjubjub"
"@zkopru/database" "file:../../../.cache/yarn/v6/npm-@zkopru-account-0.0.1-e1de4d80-c9ad-4fa4-be7e-27258c76ffbc-1589800833134/node_modules/@zkopru/database"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-account-0.0.1-e1de4d80-c9ad-4fa4-be7e-27258c76ffbc-1589800833134/node_modules/@zkopru/utils"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-account-0.0.3-132ecf22-5630-4f2c-b161-56f1312ba6d5-1590065442516/node_modules/@zkopru/babyjubjub"
"@zkopru/database" "file:../../../.cache/yarn/v6/npm-@zkopru-account-0.0.3-132ecf22-5630-4f2c-b161-56f1312ba6d5-1590065442516/node_modules/@zkopru/database"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-account-0.0.3-132ecf22-5630-4f2c-b161-56f1312ba6d5-1590065442516/node_modules/@zkopru/utils"
bip39 "^3.0.2"
hdkey "^1.1.1"
web3 "^1.2.6"
@@ -1990,7 +1998,7 @@
web3-eth-accounts "^1.2.6"
"@zkopru/babyjubjub@file:packages/babyjubjub":
version "0.0.1"
version "0.0.3"
dependencies:
big-integer "^1.6.48"
blake-hash "^1.1.0"
@@ -2000,7 +2008,7 @@
web3-utils "^1.2.6"
"@zkopru/contracts@file:packages/contracts":
version "0.0.1"
version "0.0.3"
dependencies:
"@openzeppelin/contracts" "3.0.1"
bn.js "^5.1.1"
@@ -2009,40 +2017,47 @@
web3-eth-contract "^1.2.6"
"@zkopru/coordinator@file:packages/coordinator":
version "0.0.1"
version "0.0.3"
dependencies:
"@nano-sql/adapter-leveldb" "^2.0.5"
"@nano-sql/core" "^2.3.7"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.1-3ce2bec6-1446-49ac-99dd-428026d3955b-1589800833141/node_modules/@zkopru/babyjubjub"
"@zkopru/contracts" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.1-3ce2bec6-1446-49ac-99dd-428026d3955b-1589800833141/node_modules/@zkopru/contracts"
"@zkopru/core" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.1-3ce2bec6-1446-49ac-99dd-428026d3955b-1589800833141/node_modules/@zkopru/core"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.1-3ce2bec6-1446-49ac-99dd-428026d3955b-1589800833141/node_modules/@zkopru/transaction"
"@zkopru/tree" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.1-3ce2bec6-1446-49ac-99dd-428026d3955b-1589800833141/node_modules/@zkopru/tree"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.1-3ce2bec6-1446-49ac-99dd-428026d3955b-1589800833141/node_modules/@zkopru/utils"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.3-f3888ee5-d16d-41ce-9f6e-9121f9eec6f0-1590065442522/node_modules/@zkopru/babyjubjub"
"@zkopru/contracts" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.3-f3888ee5-d16d-41ce-9f6e-9121f9eec6f0-1590065442522/node_modules/@zkopru/contracts"
"@zkopru/core" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.3-f3888ee5-d16d-41ce-9f6e-9121f9eec6f0-1590065442522/node_modules/@zkopru/core"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.3-f3888ee5-d16d-41ce-9f6e-9121f9eec6f0-1590065442522/node_modules/@zkopru/transaction"
"@zkopru/tree" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.3-f3888ee5-d16d-41ce-9f6e-9121f9eec6f0-1590065442522/node_modules/@zkopru/tree"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-coordinator-0.0.3-f3888ee5-d16d-41ce-9f6e-9121f9eec6f0-1590065442522/node_modules/@zkopru/utils"
big-integer "^1.6.48"
bip39 "^3.0.2"
bn.js "^5.1.1"
chalk "^4.0.0"
express "^4.17.1"
figlet "^1.4.0"
fs-extra "^9.0.0"
node-schedule "^1.3.2"
prompts "^2.3.2"
snarkjs "^0.1.25"
web3 "^1.2.6"
web3-core "^1.2.6"
web3-core-subscriptions "^1.2.6"
web3-utils "^1.2.6"
yargs "^15.3.1"
"@zkopru/core@file:packages/core":
version "0.0.1"
version "0.0.3"
dependencies:
"@nano-sql/core" "^2.3.7"
"@zkopru/account" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.1-f8309e8c-f3ea-4803-9ea0-bed19efe6441-1589800833135/node_modules/@zkopru/account"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.1-f8309e8c-f3ea-4803-9ea0-bed19efe6441-1589800833135/node_modules/@zkopru/babyjubjub"
"@zkopru/contracts" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.1-f8309e8c-f3ea-4803-9ea0-bed19efe6441-1589800833135/node_modules/@zkopru/contracts"
"@zkopru/database" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.1-f8309e8c-f3ea-4803-9ea0-bed19efe6441-1589800833135/node_modules/@zkopru/database"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.1-f8309e8c-f3ea-4803-9ea0-bed19efe6441-1589800833135/node_modules/@zkopru/transaction"
"@zkopru/tree" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.1-f8309e8c-f3ea-4803-9ea0-bed19efe6441-1589800833135/node_modules/@zkopru/tree"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.1-f8309e8c-f3ea-4803-9ea0-bed19efe6441-1589800833135/node_modules/@zkopru/utils"
"@zkopru/account" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.3-5da0e665-6d69-4265-af8e-b7643cfa4617-1590065442517/node_modules/@zkopru/account"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.3-5da0e665-6d69-4265-af8e-b7643cfa4617-1590065442517/node_modules/@zkopru/babyjubjub"
"@zkopru/contracts" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.3-5da0e665-6d69-4265-af8e-b7643cfa4617-1590065442517/node_modules/@zkopru/contracts"
"@zkopru/database" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.3-5da0e665-6d69-4265-af8e-b7643cfa4617-1590065442517/node_modules/@zkopru/database"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.3-5da0e665-6d69-4265-af8e-b7643cfa4617-1590065442517/node_modules/@zkopru/transaction"
"@zkopru/tree" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.3-5da0e665-6d69-4265-af8e-b7643cfa4617-1590065442517/node_modules/@zkopru/tree"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-core-0.0.3-5da0e665-6d69-4265-af8e-b7643cfa4617-1590065442517/node_modules/@zkopru/utils"
async-lock "^1.2.2"
big-integer "^1.6.48"
bn.js "^5.1.1"
ffjavascript "^0.0.5"
ffjavascript "^0.1.3"
node-fetch "^2.6.0"
snarkjs "^0.1.27"
web3 "^1.2.6"
@@ -2052,21 +2067,21 @@
winston "^3.2.1"
"@zkopru/database@file:packages/database":
version "0.0.1"
version "0.0.3"
dependencies:
"@nano-sql/core" "^2.3.7"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-database-0.0.1-c751da18-83c5-4553-a2f7-54c90d36979b-1589800833133/node_modules/@zkopru/babyjubjub"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-database-0.0.1-c751da18-83c5-4553-a2f7-54c90d36979b-1589800833133/node_modules/@zkopru/transaction"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-database-0.0.3-489ad99f-0c3e-4978-835b-c11d462a9973-1590065442514/node_modules/@zkopru/babyjubjub"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-database-0.0.3-489ad99f-0c3e-4978-835b-c11d462a9973-1590065442514/node_modules/@zkopru/transaction"
big-integer "^1.6.48"
bn.js "^5.1.1"
web3-core "^1.2.6"
web3-utils "^1.2.6"
"@zkopru/transaction@file:packages/transaction":
version "0.0.1"
version "0.0.3"
dependencies:
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-transaction-0.0.1-e0ca32ce-cd72-46f3-ab27-5569d551cae8-1589800833136/node_modules/@zkopru/babyjubjub"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-transaction-0.0.1-e0ca32ce-cd72-46f3-ab27-5569d551cae8-1589800833136/node_modules/@zkopru/utils"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-transaction-0.0.3-32e1c6d2-df04-4b81-9977-7b5e7726659b-1590065442520/node_modules/@zkopru/babyjubjub"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-transaction-0.0.3-32e1c6d2-df04-4b81-9977-7b5e7726659b-1590065442520/node_modules/@zkopru/utils"
big-integer "^1.6.48"
chacha20 "^0.1.4"
circomlib "^0.1.1"
@@ -2074,12 +2089,12 @@
web3-utils "^1.2.6"
"@zkopru/tree@file:packages/tree":
version "0.0.1"
version "0.0.3"
dependencies:
"@nano-sql/core" "^2.3.7"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-tree-0.0.1-a9fd28c6-a902-485b-8e0b-4ab525a06023-1589800833140/node_modules/@zkopru/babyjubjub"
"@zkopru/database" "file:../../../.cache/yarn/v6/npm-@zkopru-tree-0.0.1-a9fd28c6-a902-485b-8e0b-4ab525a06023-1589800833140/node_modules/@zkopru/database"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-tree-0.0.1-a9fd28c6-a902-485b-8e0b-4ab525a06023-1589800833140/node_modules/@zkopru/transaction"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-tree-0.0.3-ca3686f8-c616-4f78-8978-2cb8f743662c-1590065442520/node_modules/@zkopru/babyjubjub"
"@zkopru/database" "file:../../../.cache/yarn/v6/npm-@zkopru-tree-0.0.3-ca3686f8-c616-4f78-8978-2cb8f743662c-1590065442520/node_modules/@zkopru/database"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-tree-0.0.3-ca3686f8-c616-4f78-8978-2cb8f743662c-1590065442520/node_modules/@zkopru/transaction"
async-lock "^1.2.2"
big-integer "^1.6.48"
bn.js "^5.1.1"
@@ -2087,7 +2102,7 @@
web3-utils "^1.2.6"
"@zkopru/utils@file:packages/utils":
version "0.0.1"
version "0.0.3"
dependencies:
bn.js "^5.1.1"
circom_runtime "^0.0.3"
@@ -2096,22 +2111,21 @@
node-docker-api "^1.1.22"
pino "^6.2.0"
pino-pretty "^4.0.0"
prompts "^2.3.2"
snarkjs "^0.1.25"
tar "^6.0.2"
web3-utils "^1.2.6"
"@zkopru/zk-wizard@file:packages/zk-wizard":
version "0.0.1"
version "0.0.3"
dependencies:
"@nano-sql/core" "^2.3.7"
"@zkopru/account" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.1-633e8abc-ca6e-494e-98ba-0ffb50370975-1589800833139/node_modules/@zkopru/account"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.1-633e8abc-ca6e-494e-98ba-0ffb50370975-1589800833139/node_modules/@zkopru/babyjubjub"
"@zkopru/contracts" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.1-633e8abc-ca6e-494e-98ba-0ffb50370975-1589800833139/node_modules/@zkopru/contracts"
"@zkopru/core" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.1-633e8abc-ca6e-494e-98ba-0ffb50370975-1589800833139/node_modules/@zkopru/core"
"@zkopru/database" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.1-633e8abc-ca6e-494e-98ba-0ffb50370975-1589800833139/node_modules/@zkopru/database"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.1-633e8abc-ca6e-494e-98ba-0ffb50370975-1589800833139/node_modules/@zkopru/transaction"
"@zkopru/tree" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.1-633e8abc-ca6e-494e-98ba-0ffb50370975-1589800833139/node_modules/@zkopru/tree"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.1-633e8abc-ca6e-494e-98ba-0ffb50370975-1589800833139/node_modules/@zkopru/utils"
"@zkopru/account" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.3-c6cf7392-2d60-4d29-852b-1b483ee54573-1590065442521/node_modules/@zkopru/account"
"@zkopru/babyjubjub" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.3-c6cf7392-2d60-4d29-852b-1b483ee54573-1590065442521/node_modules/@zkopru/babyjubjub"
"@zkopru/contracts" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.3-c6cf7392-2d60-4d29-852b-1b483ee54573-1590065442521/node_modules/@zkopru/contracts"
"@zkopru/core" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.3-c6cf7392-2d60-4d29-852b-1b483ee54573-1590065442521/node_modules/@zkopru/core"
"@zkopru/transaction" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.3-c6cf7392-2d60-4d29-852b-1b483ee54573-1590065442521/node_modules/@zkopru/transaction"
"@zkopru/tree" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.3-c6cf7392-2d60-4d29-852b-1b483ee54573-1590065442521/node_modules/@zkopru/tree"
"@zkopru/utils" "file:../../../.cache/yarn/v6/npm-@zkopru-zk-wizard-0.0.3-c6cf7392-2d60-4d29-852b-1b483ee54573-1590065442521/node_modules/@zkopru/utils"
big-integer "^1.6.48"
circom_runtime "^0.0.3"
ffjavascript "^0.1.2"
@@ -2158,14 +2172,6 @@ abstract-leveldown@^6.2.1:
level-supports "~1.0.0"
xtend "~4.0.0"
abstract-leveldown@~6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.1.1.tgz#f44bad5862d71c7b418110d7698ac25bedf24396"
integrity sha512-7fK/KySVqzKIomdhkSWzX4YBQhzkzEMbWSiaB6mSN9e+ZdV3KEeKxia/8xQzCkATA5xnnukdP88cFR0D2FsFXw==
dependencies:
level-concat-iterator "~2.0.0"
xtend "~4.0.0"
abstract-leveldown@~6.2.1:
version "6.2.3"
resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb"
@@ -3673,7 +3679,7 @@ columnify@^1.5.4:
strip-ansi "^3.0.0"
wcwidth "^1.0.0"
combined-stream@^1.0.6, combined-stream@~1.0.6:
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@@ -5523,13 +5529,6 @@ ffjavascript@0.1.2:
dependencies:
big-integer "^1.6.48"
ffjavascript@^0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.0.5.tgz#244d242b74299fef736b697ff4df9cda1a26fbbe"
integrity sha512-7je6PydOWLDUj3vU8JeCUgeezg4yrG/6qjlukQNuPHeeavnM4REcrN9LA2+xtqIMIPdx/wdUkPMQpixsz+CdIw==
dependencies:
big-integer "^1.6.48"
ffjavascript@^0.1.2, ffjavascript@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.1.3.tgz#75d5397f5da0af977d6f38b60301d4de25f17040"
@@ -5802,6 +5801,15 @@ form-data@^2.2.0:
combined-stream "^1.0.6"
mime-types "^2.1.12"
form-data@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682"
integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@@ -10919,15 +10927,6 @@ rlp@^2.2.3:
dependencies:
bn.js "^4.11.1"
rocksdb@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/rocksdb/-/rocksdb-4.1.0.tgz#79c2cb716ffb9b317bdb48f80d1985410179ecac"
integrity sha512-NtjezNMuxk9NsC1kGybZ8Y9eWKqAohug88xbtxCwb5n7MhDDgtKJuL7VYUk8s8Q9U4Mzolt026k3hD8eHtoUvQ==
dependencies:
abstract-leveldown "~6.1.1"
napi-macros "~2.0.0"
node-gyp-build "~4.1.0"
rsvp@^4.8.4:
version "4.8.5"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"