diff --git a/.circleci/config.yml b/.circleci/config.yml index 8e7245369..023da9251 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -39,6 +39,16 @@ jobs: - codecov/upload: file: coverage.html + test_js: + machine: + image: circleci/classic:201808-01 + steps: + - checkout + # js tests do not need to in docker, however nodejs crashes + # while running mocha when not using image above (not OOM). + # above image needs newer go so docker is used. + - run: docker-compose run burrow make npm_install test_js + test_integration: machine: image: circleci/classic:201808-01 @@ -90,6 +100,10 @@ workflows: filters: <<: *tags_filters + - test_js: + filters: + <<: *tags_filters + - build_docker: filters: # tags filters and branch filters are applied disjunctively, so we @@ -101,6 +115,7 @@ workflows: requires: - test - test_integration + - test_js filters: branches: only: develop @@ -109,6 +124,7 @@ workflows: requires: - test - test_integration + - test_js filters: <<: *tags_filters branches: diff --git a/.gitignore b/.gitignore index d086be907..e0afbb022 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ commit_hash.txt tests/keys/ .output.json -vendor/ \ No newline at end of file +vendor/ +node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e0a3ed00..3b98e80ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # [Hyperledger Burrow](https://github.com/hyperledger/burrow) Changelog -## [Unreleased] +## [0.28.1] - 2019-08-21 +### Fixed +- [Vent] Log for _vent_log insert now faithfully captures what is being inserted +- [Vent] Remove arbitrary 100 character limits on system table text fields + +### Added +- [JS] Burrow.js now included in Burrow repo and tested with Burrow CI! Future burrow.js releases will now match version of Burrow. ## [0.28.0] - 2019-08-14 @@ -541,7 +547,7 @@ This release marks the start of Eris-DB as the full permissioned blockchain node - [Blockchain] Fix getBlocks to respect block height cap. -[Unreleased]: https://github.com/hyperledger/burrow/compare/v0.28.0...HEAD +[0.28.1]: https://github.com/hyperledger/burrow/compare/v0.28.0...v0.28.1 [0.28.0]: https://github.com/hyperledger/burrow/compare/v0.27.0...v0.28.0 [0.27.0]: https://github.com/hyperledger/burrow/compare/v0.26.2...v0.27.0 [0.26.2]: https://github.com/hyperledger/burrow/compare/v0.26.1...v0.26.2 diff --git a/Makefile b/Makefile index ef158c612..175517765 100644 --- a/Makefile +++ b/Makefile @@ -174,6 +174,17 @@ solidity: $(SOLIDITY_GO_FILES) .PHONY: solang solang: $(SOLANG_GO_FILES) +# node/js +# +# Install dependency +.PHONY: npm_install +npm_install: + npm install + +.PHONY: test_js +test_js: bin/solc build_burrow + ./tests/scripts/bin_wrapper.sh npm test + # Test .PHONY: test diff --git a/NOTES.md b/NOTES.md index fc4b0a62a..011cfdf4b 100644 --- a/NOTES.md +++ b/NOTES.md @@ -1,21 +1,7 @@ -### Changed -- [State] IterateStreamEvents now takes inclusive start and end points (end used to be exclusive) avoid bug-prone conversion -- [Dump] Improved structure and API -- [Dump] Default to JSON output and use protobuf for binary output - ### Fixed -- [Dump] Fix dump missing events emitted at end height provided -- [Dump] EVM events were not dumped if no height was provided to burrow dump remote commandline -- [RPC/Info] Fix panic in /names and implement properly - now accepts a 'regex' parameter which is a regular expression to match names. Empty for all names. -- [Configure] burrow configure flags --separate-genesis-doc and --pool now work together +- [Vent] Log for _vent_log insert now faithfully captures what is being inserted +- [Vent] Remove arbitrary 100 character limits on system table text fields ### Added -- [State] Burrow now remembers contact ABIs (which describe how to pack bits when calling contracts) - burrow deploy and vent will both use chain-hosted ABI if they are available -- [State] Bond and unbond transactions are now implement to allow validators to transfer native token into validator power. -- [Dump] Better tests, mock, and benchmarks - suitable for profiling IAVL -- [Events] Filters now support OR connective -- [Vent] Projection filters can now have filters longer than 100 characters. -- [Vent] Falls back to local ABI -- [CLI/RPC] Contracts now hold metadata, including contract name, source file, and function names - +- [JS] Burrow.js now included in Burrow repo and tested with Burrow CI! Future burrow.js releases will now match version of Burrow. diff --git a/README.md b/README.md index 97a4d3660..ab037c674 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Hyperledger Burrow +# [Hyperledger Burrow](https://hyperledger.github.io/burrow) [![version](https://img.shields.io/github/tag/hyperledger/burrow.svg)](https://github.com/hyperledger/burrow/releases/latest) [![GoDoc](https://godoc.org/github.com/burrow?status.png)](https://godoc.org/github.com/hyperledger/burrow) @@ -13,7 +13,7 @@ Branch | Linux Hyperledger Burrow is a permissioned Ethereum smart-contract blockchain node. It executes Ethereum EVM smart contract code (usually written in [Solidity](https://solidity.readthedocs.io)) on a permissioned virtual machine. Burrow provides transaction finality and high transaction throughput on a proof-of-stake [Tendermint](https://tendermint.com) consensus engine. -![burrow logo](docs/assets/images/burrow.png) +![burrow logo](docs/assets/burrow.png) ## What is Burrow @@ -26,6 +26,10 @@ Hyperledger Burrow is a permissioned blockchain node that executes smart contrac - **Application Binary Interface (ABI):** Transactions need to be formulated in a binary format that can be processed by the blockchain node. Current tooling provides functionality to compile, deploy and link solidity smart contracts and formulate transactions to call smart contracts on the chain. - **API Gateway:** Burrow exposes REST and JSON-RPC endpoints to interact with the blockchain network and the application state through broadcasting transactions, or querying the current state of the application. Websockets allow subscribing to events, which is particularly valuable as the consensus engine and smart contract application can give unambiguously finalised results to transactions within one blocktime of about one second. +## JavaScript Client + +There is a [JavaScript API](https://github.com/hyperledger/burrow/tree/develop/js) + ## Project Roadmap Project information generally updated on a quarterly basis can be found on the [Hyperledger Burrow Wiki](https://wiki.hyperledger.org/display/burrow). diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 281627497..ace629217 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -1,18 +1,18 @@ -## Minimum requirements +# Installation -Requirement|Notes ----|--- -Go version | Go1.11 or higher +## Binary -## Installation +Download a binary from our list of [releases](https://github.com/hyperledger/burrow/releases) +and copy it to a suitable location. -- [Install go](https://golang.org/doc/install) version 1.11 or above and have `$GOPATH` set + +## Source + +[Install Go](https://golang.org/doc/install) (Version >= 1.11) and set `$GOPATH`. ``` go get github.com/hyperledger/burrow cd $GOPATH/src/github.com/hyperledger/burrow -# We need to force enable module support to build from within GOPATH (our protobuf build depends on path, otherwise any checkout location should work) -export GO111MODULE=on make build ``` @@ -20,3 +20,21 @@ This will build the `burrow` binary and put it in the `bin/` directory. It can b You can also install `burrow` into `$BIN_PATH/bin` with `make install`, where `$BIN_PATH` defaults to `$HOME/go/bin` if not set in environment. + + +## Docker + +Each release is also tagged and pushed to [Docker Hub](https://hub.docker.com/r/hyperledger/burrow). +This can act as a direct replacement for the burrow binary, for example the following commands are equivalent: + +```bash +burrow spec -v4 +docker run hyperledger/burrow spec -v4 +``` + +Note: ensure to mount local volumes for secrets / configurations when running a container to prevent data loss. + +## Kubernetes + +Use our official [helm charts](https://github.com/helm/charts/tree/master/stable/burrow) to configure and run +a burrow chain in your cluster. \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 15d0abbbd..1618b605a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,9 +2,9 @@ Hyperledger Burrow is a permissioned Ethereum smart-contract blockchain node. It executes Ethereum EVM smart contract code (usually written in [Solidity](https://solidity.readthedocs.io)) on a permissioned virtual machine. Burrow provides transaction finality and high transaction throughput on a proof-of-stake [Tendermint](https://tendermint.com) consensus engine. -![burrow logo](assets/images/burrow.png) +![burrow logo](assets/burrow.png) -## What is Burrow +## What is Burrow? Hyperledger Burrow is a permissioned blockchain node that executes smart contract code following the Ethereum specification. Burrow is built for a multi-chain universe with application specific optimization in mind. Burrow as a node is constructed out of three main components: the consensus engine, the permissioned Ethereum virtual machine and the rpc gateway. More specifically Burrow consists of the following: diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 2598a6a08..8363c87de 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -1,15 +1,20 @@ - Burrow - [Introduction](README.md) - [Installation](INSTALL.md) + - [JS API](js-api.md) + +- Transactions + - [Bond / Unbond](txs/bond.md) + - Tutorials - - [Single Node](quickstart/single-full-node.md) - - [Send Transactions](quickstart/send-transactions.md) - - [Deploy Contracts](quickstart/deploy-contracts.md) - - [Multiple Validators](quickstart/multiple-validators.md) - - [Add Validators](quickstart/bonding-validators.md) - - [Seed Nodes](quickstart/seed-nodes.md) - - [Dump-Restore](quickstart/dump-restore.md) - - [Kubernetes](https://github.com/helm/charts/tree/master/stable/burrow) + - [Single Node](tutorials/1-run-full-node.md) + - [Send Transactions](tutorials/2-send-transactions.md) + - [Deploy Contracts](tutorials/3-deploy-contracts.md) + - [Multiple Validators](tutorials/4-multiple-validators.md) + - [Bonding](tutorials/5-bonding-validators.md) + - [Seed Nodes](tutorials/6-seed-nodes.md) + - [Dump / Restore](tutorials/7-dump-restore.md) + - Reference - [Genesis](reference/genesis.md) - [Logging](reference/logging.md) diff --git a/docs/assets/images/burrow.png b/docs/assets/burrow.png similarity index 100% rename from docs/assets/images/burrow.png rename to docs/assets/burrow.png diff --git a/docs/assets/adr-1/burrow-logo.png b/docs/assets/logo.png similarity index 100% rename from docs/assets/adr-1/burrow-logo.png rename to docs/assets/logo.png diff --git a/docs/index.html b/docs/index.html index ae986d73c..5ce369952 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,9 +2,9 @@ - Document + Hyperledger Burrow - + @@ -14,8 +14,10 @@ window.$docsify = { name: 'Hyperledger Burrow', repo: 'https://github.com/hyperledger/burrow', + auto2top: true, loadSidebar: true, - subMaxLevel: 2 + subMaxLevel: 2, + themeColor: '#3FBB86' } diff --git a/docs/js-api.md b/docs/js-api.md new file mode 100644 index 000000000..b58083d5c --- /dev/null +++ b/docs/js-api.md @@ -0,0 +1,523 @@ +# JS API + +Burrow has a JavaScript API for communicating with a [Hyperledger Burrow](https://github.com/hyperledger/burrow) server, which implements the GRPC spec. + +## Prerequisites + +- Burrow version 0.20 or higher +- Node.js version 7 or higher + +You can check the installed version of Node.js with the command: + +```bash +$ node --version +``` + +If your distribution of Linux has a version older than 6 then you can update it. + +## Install + +``` bash +$ npm install @monax/burrow +``` + +## Usage + +You will need to know the : of the burrow instance you wish to connect to. If running locally this will be 'localhost' and the default port, which is '10997'. DO NOT INCLUDE A PROTOCOL. + +The main class is `Burrow`. A standard `Burrow` instance is created like this: + +```JavaScript +const monax = require('@monax/burrow'); +var burrowURL = ":"; // localhost:10997 if running locally on default port +var account = 'ABCDEF01234567890123'; // address of the account to use for signing, hex string representation +var options = {objectReturn: true}; +var burrow = monax.createInstance(burrowURL, account, options); +``` + +The parameters for `createInstance` is the server URL as a string or as an object `{host:, port:}`. An account in the form of a hex-encoded address must be provided. + +> Note: the instance of burrow you are connecting to must have the associated key (if you want local signing you should be running a local node of burrow. Other local signing options might be made available at a later point). + +And finally an optional options object. Allowed options are: + +* objectReturn: If True, communicating with contracts an object returns an object of the form: `{values:{...}, raw:[]}` where the values objects attempts to name the returns based on the abi and the raw is the decoded array of return values. If False just the array of decoded return values is returned. + + +## API Reference + +There are bindings for all the GRPC methods. All functions are on the form `function(param1, param2, ... [, callback])`, where the callback is a function on the form `function(error, data)`. The `data` object is the same as you would get by calling the corresponding RPC method directly. If no callback is provided, a promise will be returned instead. If calling a response streaming GRPC call, the callback is not optional and will be called with `data` anytime it is recieved. + +The structure of the library is such that there are lower-level access to the GRPC services and higher level wrappers of these services. The structure of the library is outlined below + +### Burrow + +The table below links to the reference schema for either the protobuf files governing the component or the Javascript interface. + +| Component Name | Accessor | +| :----------- | :--------------- | +| Transactions | [Burrow.transact](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpctransact.proto) | +| Queries | [Burrow.query](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcquery.proto) | +| EventStream | [Burrow.eventStream](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto) | +| Events | [Burrow.events](https://github.com/hyperledger/burrow/blob/develop/lib/events.js) | +| NameReg | [Burrow.namereg](https://github.com/hyperledger/burrow/blob/develop/lib/namereg.js) | + +| Contracts | [Burrow.contracts](https://github.com/hyperledger/burrow/blob/develop/lib/contractManager.js) | + +### GRPC Access Components + +Burrow provides access to three GRPC services; Transactions, Queries, and ExecutionEvents in the form of automatically generated code endpoints. Below details how to access these methods and links to the request and return objects defined in the protobuf specs. The format for all calls is `function(object[, callback])` The callback is optional for non-streaming endpoints in which case a promise will be returned. + +#### Sending Funds and Creating Accounts + +In Burrow an account must already exist in order to be used as a input account (the sender of a transaction). An account can be created once the chain is running (accounts at genesis can be described in the genesis document in the accounts section) in the following ways: + +1. Issuing a `SendTx` to the address to be created (see below) - where the input account must have both the `Send` and `CreateAccount` permission. +2. Sending value to the address to created from a smart contract using the CALL opcode - where the caller contract must have the `CreateAccount` permission. +3. Issuing a `GovTx` where accounts can be created/updated in bulk provided the input has the `Root` permission. + +The conventional way to create an new account to use as an input for transactions is the following: + +First create a key - you will want to create an account for which you have access to the private key controlling that account (as defined by the address of the public key): + +```shell +# Create a new key against the key store of a locally running Burrow (or burrow keys standalone server): +$ address=$(burrow keys gen -n --name NewKey) + +# The address will be printed to stdout so the above captures it in $address, you can also list named keys: +$ burrow keys list +Address:"6075EADD0C7A33EE6153F3FA1B21E4D80045FCE2" KeyName:"NewKey" +``` + +Note creating the key _does not_ create the account - it just generates a key pair in your local key store (it is not in anyway known the blockchain network). + +Now we would like to use a `SendTx` to create the address, here's how to do that in Javscript: + +```javascript +// Using account and burrow defined in snippet from [Usage](#usage) + +// Address we want to create +var addressToCreate = "6075EADD0C7A33EE6153F3FA1B21E4D80045FCE2" + +// The amount we send is arbitrary +var amount = 20 + +burrow.transact.SendTxSync( + { + Inputs: [{ + Address: Buffer.from(account, 'hex'), + Amount: amount + }], + Outputs: [{ + Address: Buffer.from(addressToCreate, 'hex'), + Amount: amount + }] + }) + .then(txe => console.log(txe)) + .catch(err => console.error(err)) +``` + +The return `txe` (short for `TxExecution`) logged to the console in the `then` block contains the history and fingerprint of the `SendTx` execution. You can see an example of this in [basic app](../example/basic-app/app.js). + +#### NameReg access + +Here is an example of usage in setting and getting a name: + +```javascript +var setPayload = { + Input: { + Address: Buffer.from(account,'hex'), + Amount: 50000 + }, + Name: "DOUG", + Data: "Marmot", + Fee: 5000 +} + +var getPayload = {Name: "DOUG"} + +// Using a callback +burrow.transact.NameTxSync(setPayload, function(error, data){ + if (error) throw error; // or something more sensible + // data object contains detailed information of the transaction execution. + + // Get a name this time using a promise + burrow.query.GetName(getPayload) + .then((data) => {console.log(data);}) // should print "Marmot" + .catch((error)=> {throw error;}) +}) + +``` + +#### Transactions + +`burrow.transact` provides access to the burrow GRPC service `rpctransact`. As a GRPC wrapper all the endpoints take a data argument and an optional callback. The format of the data object is specified in the [rpctransact protobuf file](./protobuf/rpctransact.proto). A note on RPC naming, any method which ends in `Sync` will wait until the transaction generated is included in a block. Any `Async` method will return a receipt of the transaction immediately but does not guarantee it has been included. `Sim` methods request that the transaction be simulated and the result returned as if it had been executed. SIMULATED CALLS DO NOT GET COMMITTED AND DO NOT CHANGE STATE. + +| Method | Passed | Returns | +| :----- | :--------- | :---- | +| burrow.transact.BroadcastTxSync | [TxEnvelopeParam](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpctransact.proto#L74-L79) | [TxExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L34-L56) | +| burrow.transact.BroadcastTxASync | [TxEnvelopeParam](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpctransact.proto#L74-L79) | [Receipt](https://github.com/hyperledger/burrow/blob/develop/protobuf/txs.proto#L38-L47) | +| burrow.transact.SignTx | [TxEnvelopeParam](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpctransact.proto#L74-L79) | [TxEnvelope](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpctransact.proto#L70-L72) | +| burrow.transact.FormulateTx | [PayloadParam](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpctransact.proto#L64-L68) | [TxEnvelope](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpctransact.proto#L70-L72) | +| burrow.transact.CallTxSync | [CallTx](https://github.com/hyperledger/burrow/blob/develop/protobuf/payload.proto#L53-L66) | [TxExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L34-L56) | +| burrow.transact.CallTxAsync | [CallTx](https://github.com/hyperledger/burrow/blob/develop/protobuf/payload.proto#L53-L66) | [Receipt](https://github.com/hyperledger/burrow/blob/develop/protobuf/txs.proto#L38-L47) | +| burrow.transact.CallTxSim | [CallTx](https://github.com/hyperledger/burrow/blob/develop/protobuf/payload.proto#L53-L66) | [TxExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L34-L56) | +| burrow.transact.SendTxSync | [SendTx](https://github.com/hyperledger/burrow/blob/develop/protobuf/payload.proto#L69-L76) | [TxExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L34-L56) | +| burrow.transact.SendTxAsync | [SendTx](https://github.com/hyperledger/burrow/blob/develop/protobuf/payload.proto#L69-L76) | [Receipt](https://github.com/hyperledger/burrow/blob/develop/protobuf/txs.proto#L38-L47) | +| burrow.transact.NameTxSync | [NameTx](https://github.com/hyperledger/burrow/blob/develop/protobuf/payload.proto#L88-L98) | [TxExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L34-L56) | +| burrow.transact.NameTxAsync | [NameTx](https://github.com/hyperledger/burrow/blob/develop/protobuf/payload.proto#L88-L98) | [Receipt](https://github.com/hyperledger/burrow/blob/develop/protobuf/txs.proto#L38-L47) | + + +#### Queries + +`Burrow.query` provides access to the burrow GRPC service `rpcquery`. As a GRPC wrapper all the endpoints take a data argument and an optional callback. The format of the data object is specified in the [protobuf files](https://github.com/hyperledger/burrow/tree/develop/js/protobuf). Note that "STREAM" functions take a callback `function(error, data)` which is mandatory and is called any time data is returned. For list Accounts the queryable tags are Address, PublicKey, Sequence, Balance, Code, Permissions (Case sensitive). As an example you can get all accounts with a balance greater than 1000 by `burrow.query.ListAccounts('Balance > 1000', callback)`. Multiple tag criteria can be combined using 'AND' and 'OR' for an example of a combined query see [here](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L87). Similarly for ListNames, the avaible tags are Name, Data, Owner and Exires (once again case sensitive) use is identical to List accounts. + +| Method | Passed | Returns | Notes | +| :----- | :--------- | :---- | :------- | +| burrow.query.GetAccount | [GetAccountParam](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcquery.proto#L25-L27) | [ConcreteAccount](https://github.com/hyperledger/burrow/blob/develop/protobuf/acm.proto#L23-L31) | | +| burrow.query.ListAccounts | [ListAccountsParam](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcquery.proto#L29-L31) | [ConcreteAccount](https://github.com/hyperledger/burrow/blob/develop/protobuf/acm.proto#L23-L31) | STREAM | +| burrow.query.GetNameParam | [GetNameParam](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcquery.proto#L33-L35) | [Entry](https://github.com/hyperledger/burrow/blob/develop/protobuf/names.proto#L22-L32) | | +| burrow.query.ListNames | [ListNamesParam](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcquery.proto#L37-L39) | [Entry](https://github.com/hyperledger/burrow/blob/develop/protobuf/names.proto#L22-L32) | STREAM| + +#### EventStream + +NB: When listening to contract events it is easier to use the contract interface (described below) + +`Burrow.executionEvents` provides access to the burrow GRPC service `ExecutionEvents`. As a GRPC wrapper all the endpoints take a data argument and an optional callback. The format of the data object is specified in the [protobuf files](https://github.com/hyperledger/burrow/tree/develop/js/protobuf). Note that "STREAM" functions take a callback `function(error, data)` which is mandatory and is called any time data is returned. + +| Method | Passed | Returns | Notes | +| :----- | :--------- | :---- | :------- | +| burrow.executionEvents.GetBlock | [GetBlockRequest](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L37-L42) | [BlockExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L20-L27) | | +| burrow.executionEvents.GetBlocks | [BlocksRequest](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L51-L89) | [BlockExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L20-L27) | STREAM | +| burrow.executionEvents.GetTx | [GetTxRequest](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L44-L49) | [TxExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L34-L56) | | +| burrow.executionEvents.GetTxs | [BlocksRequest](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L51-L89) | [GetTxsResponse](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L96-L99) | STREAM | +| burrow.executionEvents.GetEvents | [BlocksRequest](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L51-L89) | [GetEventsResponse](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L91-L94) | STREAM | + + +*** + +### High-Level Components + +In addition to direct access to the grpc services, the burrow object also provides access to *three* higher level components which wrap the low level access for convenience. These are ```.namereg```, ```.events```, and ```.contracts```. All high level components use the account provided during creation of the burrow instance for constructing transactions. Component ```contracts``` is the most important of the three, as events and namereg are really just helpful wrappers. + + +#### 1. Namereg + +`burrow.namereg` is a convenience wrapper for setting and getting entries from the name registry. + +##### burrow.namereg.get +```burrow.namereg.get(name[,callback])``` + +Gets an entry stored at the name. It returns a promise if callback not provided. +###### Parameters +1. `String` - Name you wish to retrieve from the namereg +2. `function` - (optional) Function to call upon completion of form `function(error, data)`. +###### Returns +`Object` - The return data object is of the form: + +```javascript +{ + Name: (registered name) (string) + Owner: (address of name owner) (buffer) + Data: (stored data) (string) + Expires: (block at which entry expires) (int) +} +``` + +##### burrow.namereg.set +```burrow.namereg.set(name, data, lease[, callback])``` + +Sets an entry in the namereg. It returns a promise if callback not provided. +###### Parameters +1. `String` - The name you wish to register +2. `String` - The string data you wish to store at the registered name (longer string = larger fee) +3. `int` - The number of blocks to register the name for (more blocks = larger fee) +4. `function` - (optional) Function to call upon completion of form `function(error, data)`. +###### Returns +`TxExecution` - The return data object is a [TxExecution](https://github.com/hyperledger/burrow/blob/develop/protobuf/exec.proto#L34-L56). +###### Example + +```javascript +// Using a callback +burrow.namereg.set("DOUG", "Marmot", 5000, function(error, data){ + if (error) throw error; // or something more sensible + // data object contains detailed information of the transaction execution. + + // Get a name this time using a promise + burrow.namereg.get("DOUG") + .then((data) => {console.log(data);}) // Should print "Marmot" + .catch((error)=> {throw error;}) +}) +``` + +> Note: this example is nearly identical to the example above except that the objects are not explicitly constructed by you. + + + +#### 2. Events + +`burrow.events` contains convenience wrappers for streaming executionEvents. + +##### burrow.events.listen +```burrow.events.listen(query, options, callback)``` + +Listens to execution events which satisfy the filter query. +###### Parameters +1. `String` - a pegjs querystring for filtering the returned events see [here]() for grammar specification +2. `Object` - Currently unused. pass `{}` +3. `function` - Signature of `function(error, data)` mandatory +###### Returns +`GetEventsResponse` - The return data object is a [GetEventsResponse](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L91-L94) + + + +##### burrow.events.subContractEvents +```burrow.events.subContractEvents(address, signature, options, callback)``` + +Listens to EVM event executions from specific contract. +###### Parameters +1. `String` - hex string of the contract address of interest +2. `String` - event abi signature +3. `Object` - Currently unused. pass `{}` +4. `function` - Signature of `function(error, data)` mandatory. +###### Returns +`GetEventsResponse` - The return data object is a [GetEventsResponse](https://github.com/hyperledger/burrow/blob/develop/protobuf/rpcevents.proto#L91-L94) + + + +#### 3. Contracts + +`burrow.contracts` is arguably the most important component of the burrow it exposes two functions, `.deploy` and `.new` both of which return a Contract interface object (sometimes refered to as contract object). The difference between them is that `new` simply creates an interface to a contract and `deploy` will first create an instance and then deploy a copy of it to the blockchain. + + +##### burrow.contracts.deploy +```burrow.contracts.deploy(abi, bytecode, params... [, callback])``` + +Deploys a contract and returns a contract interface either to the callback or a promise once deploy is successful. It returns a promise if callback not provided. + +When the contract interface object is created via deploy, the default address is set to the address of the deployed contract (which can be accessed as contract.address). This interface object can still be used as a generic interface but care must be taken to use the `.at()` and `.atSim()` versions of functions. + +###### Parameters +1. `Object` - the object corresponding to the json ABI of the contract you wish to interface with. +2. `String` - Hex encoded string of bytecode of the contract to deploy +3. `params` - arguments to the constructor function (if there are any) +4. `function` - (optional) Format of `function(error, contract)` where contract is the contract interface object. +###### Returns +`Object` - The return data object is a contract interface, which refers to the contract which is deployed at `contract.address`. (This functionality used to be called `new`.) + +##### burrow.contracts.new +```burrow.contracts.address(address)``` + +Returns a new contract interface object, without having to pass in the ABI. The ABI is retrieved from burrow; the contract must have been deployed with burrow deploy 0.28.0 or later. + +###### Parameters +3. `String` - Hex encoded address of the default contract you want the interface to access +###### Returns +`Object` - The return data object is a contract interface. + +##### burrow.contracts.new +```burrow.contracts.new(abi, [bytecode[, address]])``` + +Returns a new contract interface object. All you really need to create an interface is the abi, however you can also include the bytecode of the contract. If you do so you can create new contracts of this type by calling `contract._constructor(...)` which will deploy a new contract and return its address. If you provide an address, then this will be the default contract address used however you can also omit this at be sure to use the `.at()` and `.atSim()` versions of functions. Also note you must provide bytecode is you wish to provide address, though bytecode argument can be null. + +###### Parameters +1. `Object` - the object corresponding to the json ABI of the contract you wish to interface with. +2. `String` - Hex encoded string of bytecode of the contract to deploy +3. `String` - (optional) Hex encoded address of the default contract you want the interface to access +###### Returns +`Object` - The return data object is a contract interface. + + +#### 3.1. Contract interface object + +The contract interface object allows for easy access of solidity contract function calls and subscription to events. When created, javascript functions for all functions specified in the abi are generated. All of these functions have the same form `Contract.functionname(params...[, callback])`, where `params` are the arguments to the contract constructor. Arguments of the "bytes" type should be properly hex encoded before passing, to avoid improper encoding. If a callback is not provided a promise is returned. + +> Note: if the burrow object was created with ```{objectReturn: True}``` the return from these function calls is formatted as `{values:{...}, raw:[]}` otherwise an array of decoded values is provided. The values object names the decoded values according to the abi spec, if a return value has no name it won't be included in the values object and must be retrieved from its position on the raw array. + + +In the case of a REVERT op-code being called in the contract function call, an error will be passed with the revert string as the `.message` field. These errors can be distinguished from other errors as the `.code` field will be `ERR_EXECUTION_REVERT`. + +In addition to the standard function call, there are three other forms: `contract.functionname.sim`, `contract.functionname.at`, `contract.functionname.atSim`. + + +##### contract.functionname.sim +```contract.functionname.sim(params... [, callback])``` + +The "Sim" forms will force a simulated call so that does not change state. Although, the data returned is identical to what would have been returned if the call had been submitted. Useful for querying data or checking if a transaction passes some tests. +###### Parameters +1. `params` - the arguments to the function (if there are any) +2. `function`- (optional) Function to call upon completion of form `function(error, data)`. + + + +##### contract.functionname.at +```contract.functionname.at(address, params... [, callback])``` + +The "at" forms allow you to specify which contract you wish to submit the transaction to. This allows you to use a single contract interface instance to access any contract with the same abi. Useful if for example there is a factory contract on the chain and you wish to connect to any of its children. The at forms MUST be used if a default address was not provided or created. +###### Parameters +1. `String` - Hex encoded address of the default contract you want the interface to access +2. `params` - the arguments to the function (if there are any) +3. `function`- (optional) Function to call upon completion of form `function(error, data)`. + + + +##### contract.functionname.atSim +```contract.functionname.at(address, params... [, callback])``` + + +###### Parameters +1. `String` - Hex encoded address of the default contract you want the interface to access +2. `params` - the arguments to the function (if there are any) +3. `function`- (optional) Function to call upon completion of form `function(error, data)` + + +##### contract._constructor +```contract._constructor(params... [, callback])``` + +Deploys a new contract from the same interface (no need to create a new interface object via .deploy). Once completed it will return the created contract's address. + + +###### Parameters +1. `params` - the arguments to the function (if there are any) +3. `function`- (optional) Function to call upon completion of form `function(error, data)`. +###### Returns +`String` - The return data String is the created contract's address. + + +#### 3.2. Encoding and Decoding Params + +Occassionally you may wish to encode the parameters to a function call but not actually make the call. The most common use of this is in forwarding contracts which take pre-encoded arguments along with function signature bytes and then call another function passing that data for specifying the call. + +The Contract interface object supports this use case through `Contract.functionname.encode(...args)` which will return a hex string with the encoded arguments. This functionality is also available through `Monax.utils.encode(abi, functionname, ...args)`. In addition the complement also exists, `Contract.functionname.decode(data)` will produce the return object as if the data was just returned from a call. + + +#### 3.3. Contract Events + +##### contract.eventname +```contract.eventname(callback)``` + +The contract interface object exposes subscription to Solidity events under event's name. + where the provided callback with be passed an error and data of the form: + +###### Parameters +1. `function` - Function to call upon completion of form `function(error, data)`. The data object has the following form: +``` +{ + event: [fulleventname], + address: [address of contract emitting event], + args: {argname: argvalue} +} +``` + + +##### contract.eventname.at +```contract.eventname.at(address, callback)``` + +Similarly to functions' contract it is possible to start listening to a non-default contract address. + +###### Parameters +1. `String` - hex string of the contract address of interest +2. `function` - Function to call upon completion of form `function(error, data)`. The data object has the following form: +``` +{ + event: [fulleventname], + address: [address of contract emitting event], + args: {argname: argvalue} +} +``` + + + + +### Example: + +The following contract is a simple contract which takes a "name" to the constructor and also has a function `getName` which returns the name. + +````solidity +pragma solidity ^0.4.18; +contract SimpleContract { + + string private name; + + function SimpleContract(string _newName) public { + name = _newName; + } + + function getName() public constant returns (string thename) { + return name; + } + +} +```` + +Here I provide an example of communicating to the contract above from start to finish: + +```javascript +const monax = require('@monax/burrow'); +const assert = require('assert'); + +var burrowURL = ":"; // localhost:10997 if running locally on default port +var account = 'ABCDEF01234567890123'; // address of the account to use for signing, hex string representation +var options = {objectReturn: false}; +var burrow = monax.createInstance(burrowURL, account, options); + +// Get the contractABIJSON from somewhere such as solc +var abi = json.parse(contractABIJSON) // Get the contractABIJSON from somewhere such as solc +var bytecode = contractBytecode // Get this from somewhere such as solc + + + +// I'm going to use new to create a contract interface followed by a double direct call to the _constructor to deploy two contracts +const contract = burrow.contracts.new(abi, bytecode); +return Promise.all( // Deployment of two contracts + [ + contract._constructor('contract1'), + contract._constructor('contract2') + ] +).then( ([address1, address2]) => { // Collection of contracts' addresses + console.log(address1 + " - contract1"); + console.log(address2 + " - contract2"); + return Promise.all( // Execution of getName functions + [ + contract.getName.at(address1), // Using the .at() to specify the second deployed contract + contract.getName.at(address2) + ] + ).then( ([name1, name2]) => { // Collection of contracts' names + console.log(address1 + " - " + name1); + assert.equal(name1, 'contract1'); + console.log(address2 + " - " + name2); + assert.equal(name2, 'contract2'); + }); +}); +``` + + + diff --git a/docs/js-design.md b/docs/js-design.md new file mode 100644 index 000000000..ed2d8fa33 --- /dev/null +++ b/docs/js-design.md @@ -0,0 +1,65 @@ +Hello unfortunate inheritor of the JS libs, + +Please forgive me, I did my best. This note is an attempt to explain the structure and decisions that led to burrow.js having the form it does. + +First the high level overview. Burrow.js is the javascript interface to connect to, and communicate with a burrow chain. Burrow exposes a GRPC interface which at the lowest level this library wraps. Burrow, if you are unaware, runs an EVM implementation which allows us to use solidity as the smart contract language. This choice however means that in order to be useful we need to format data being passed to the grpc endpoints to be packed according to the ABI of the contract in question. So the overarching goal of this library is to handle: + +1. Connecting to burrow +2. Allow the deployment of, or connection to contracts +3. Provide objects which have attached functions facilitating the ability to call contract functions from javascript and hide the intermediate steps +4. Allow listening to event coming from the chain as well as query non contract data from burrow (name registry for example) + + +## Connecting to Burrow + +The index.js file is what is loaded when burrow.js is required. It simply loads up the Burrow file which is responsible for actually creating connection objects to Burrow. It also for convenience exposes the createinstance function which returns the Burrow connection object and the utils file which simply contains some ease of use functions. There has been a push to remove some of these exposed util functions as it is felt that they shouldn’t be relied upon. However they have been inherited from the oldest versions of the js libraries so they have remained for the time being to avoid surprises from removing them. + +## lib/Burrow.js + +This is the main object for connecting to Burrow is here, along with a helpful creator function which returns it. Note that three things are needed for this, first a url for Burrow which if using the creator function can be either an object with host and port or just a string. An account which will be used by this connection for all calls to burrow that require them (including contract calls) and an options object which is solely used by the contract manager. + +During creation first the connection to the various GRPC services are set up, the Service object is a wrapper of the GRPC library that will bind copies of the grpc functions after they have been wrapped to tha same names as before. Its honestly a bit opaque and its main purpose is to make setting up listeners on streaming grpc channels easier. If you want to remove it, go for it, you will need to update the handling of all streaming endpoints in namereg, events etc. +The Burrow connection object exposes all of the low level GRPC functions (in case a user wants direct access to them) but also provides some high level interfaces as well. Namely to events, name registry and most usefully contracts. + +There is also the creation of a pipe object which might seem bizarre as it simply wraps other functions from the various services. The pipe is another old piece that has been left solely for ease of a feature that was discussed occasionally but never implemented. Namely that the JS libs we have implemented might be compatible with the main ethereum project. The idea was that if the pipe could serve as an interface from the contract manager to the lower level resources then another pipe could be written that would interface to different low level resources such as those connecting to ethereum. This work stalled though and never progressed. There also did not seem to be a huge need for that functionality. + +Events and namereg are both just wrappers of lower level services to ease calling them. + + + +## Contract manager + +Contracts are arguably the most important piece of the lib. In order to successfully make a call to an on chain contract a series of steps must be followed. First the ABI of the contract’s function you are calling is needed in order to properly format the arguments to the function in a byte string. Second the formatting must actually take place along with constructing the payload. formatting the data is actually performed by ethereum-js but in order to use it correctly, some pre-formatting of the arguments is required. The payload for the query is sent to burrow either to the “call” or “transact” endpoints of the burrow server. The server will process the payload and then send back the result which will often include return data which must then be processed into return objects and passed to the original caller either in a promise or a callback. + +Events are another important part of contracts but luckily much simpler. for events you simply pass a handler which will listen to the event stream of all events matching the pegjs query string. the data is similarly unpacked. + +Now for some more detail. All of the contract interfacing code is located in /lib/contracts however the so-called “contract manager” which operates as a contract object constructor is located at /lib/contractmanager.js. There are three files in /lib/contracts/, contract.js, function.js, and event.js. contract.js is the code that constructs the actual contract object that will often be passed around in the user code. + +Contract creation is handled by the contract manager (accessible to the user at burrow.contracts) which has two main functions, .new and .deploy. Contract objects should be thought of as interfaces to an abi type which will have a default contract address (sometimes) which calls and queries will go to, however as an interface it will also expose the ability to supply an address which will override the default if there is any. The idea is that if you have a bunch of contracts which all have the same abi, there is no reason you should need to create a new object for each contract on chain. This is particularly true for contract which come from contract factories as they will by definition all have the same abi. The difference between deploy and new then is simply what occurs before the contract object is returned. With deploy, bytecode for the contract is provided alongside the abi and a new contract is created on the chain first. A contract object is then created which points to this newly created contract by default. new on the other hand will not make any calls to the burrow and will just create a contract object immediately. This means deploy is asynchronous and new is synchronous. A default address can be provided to new which will then be used by future calls. + +You will notice some code here dedicated to “handlers” which are passed as an object with two named fields holding functions call and con. Their purpose is to process the return from either calls or contract creation (CONstructor) before being returned to the end user. Note that these handlers will be run after all function calls to that contract object, they also can be provided as an option to the burrow object creation or directly. If a per function handler is desired it was decided that this should be handled by simply using promise chaining for that particular function rather than attempt a complicated name matching procedure. + +contract.js as previously mentioned holds the contract object definition itself. During creation of a contract object, the abi and sometimes byte code is saved followed by dynamically adding the functions and events as callable objects by name. This is done in the addFunctionsToContract and addEventsToContract functions. Taking a look at the addFunctions functions we see that multiple objects are returned from a call to create a solidity function. the displayname and typename are only for the dynamic assignment of the function to the contract object, call, encode and decode are the meat of what will be attached. Call performs all the steps of encoding the data sending it to burrow and decoding the response. However due to the use of proxy contracts (contracts which can call other arbitrary contracts) it was important to be able to access the encoding and decoding functionalities on their own so the payload could be encoded and then sent to the proxy contract as an argument. + +These functions are bound to the contract object (so they can all use this. properties of the contract object such as the pipe and address). In addition there are multiple types of calls. for example two main types are calls (transactions) and simulated calls the difference being how burrow handles them. These cases are handled by providing a boolean indicating if the call should be simulated or not. If simulated no changes are made to the chain state. Since these have identical payload structures its easiest to simply provide different values to these functions. by default contract.functionname() will use the function abi’s .constant field to determine if the call should be simulated or not. in addition there are .at() forms which allow overwritingthe default address with a provided one. The object is then added to the contract under the displayname. + +A similar process is carried out for attaching events. + +We are almost done the hard bits. Just a bit further. + +Lets discuss the function.js file because it is probably by far the most messy file to consider. THe first several functions are intended to be “functional” in the sense that they take in data and return data without changing the original data. We have functions for constructing function names and signatures putting together the payload for burrow, and encoding and decoding the arguments to be passed as byte data. most of these should be self explanatory. they each serve a role without touching the pathway to burrow. the convert module is used to side step formatting issue that have been the bane of my existence since taking this over. my abiToBurrow and back functions are an attempt to be aware of what type of data it is supposed to be in order to correctly format it before passing it to burrow or ethereum-js. The endless debate has been the 0x prepended to byte and address strings. The short story is that ethereum-js expects hex strings to be 0x prepended or it will attempt asciitohex conversion which causes nightmares but manually prepending 0x to all the hex strings has been unpopular. so the convert module smooths over that. if it is a byte like argument convert will prepend with 0x. It assume you are sending proper hex and will not asciitohex convert for you. suck it up. this has proven the least controversial option. + +Anyways the Solidity function is the meat of the function.js. looking through it you will notice that its not the function that gets attached but rather a function which returns functions to get attached to the contract. encode and decode essentially route to the functional versions. and the call function does the full pathway. + +arguments are shifted into variables in order to handle the optional components. Then a promise is constructed which holds the whole pathway to burrow and back. inside the promise decisions are made on if this is a simulated call etc, a post processing callback function is created which will hand the decoding of returns along with processing of execution errors. then the payload is constructed, and the pipe of the contract this function is bound to will be called. The solidity function will either return the promise of it will resolve the promise into a callback is provided. this is a common pattern throughout. + +events is basically the same. so yeah. + +I think that covers most of it. Once again I’m sorry. I did my best + +88224646AB + +Long live the DOUG! + +Dennis + diff --git a/docs/quickstart/single-full-node.md b/docs/tutorials/1-run-full-node.md similarity index 80% rename from docs/quickstart/single-full-node.md rename to docs/tutorials/1-run-full-node.md index dedbbb5b3..90a8aff91 100644 --- a/docs/quickstart/single-full-node.md +++ b/docs/tutorials/1-run-full-node.md @@ -1,12 +1,7 @@ -# Set up a single full account node - -## Usage - -The end result will be a `burrow.toml` that will be read in from your current working directory when starting `burrow`. +# Configure & Run Burrow ## Configuration -### Configure Burrow The quick-and-dirty one-liner looks like: ```shell @@ -14,7 +9,7 @@ The quick-and-dirty one-liner looks like: burrow spec -p1 -f1 | burrow configure -s- > burrow.toml ``` -which translates into: +Which translates into: ```shell # This is a place we can store config files and burrow's working directory '.burrow' diff --git a/docs/quickstart/send-transactions.md b/docs/tutorials/2-send-transactions.md similarity index 100% rename from docs/quickstart/send-transactions.md rename to docs/tutorials/2-send-transactions.md diff --git a/docs/quickstart/deploy-contracts.md b/docs/tutorials/3-deploy-contracts.md similarity index 100% rename from docs/quickstart/deploy-contracts.md rename to docs/tutorials/3-deploy-contracts.md diff --git a/docs/quickstart/multiple-validators.md b/docs/tutorials/4-multiple-validators.md similarity index 100% rename from docs/quickstart/multiple-validators.md rename to docs/tutorials/4-multiple-validators.md diff --git a/docs/quickstart/bonding-validators.md b/docs/tutorials/5-bonding-validators.md similarity index 92% rename from docs/quickstart/bonding-validators.md rename to docs/tutorials/5-bonding-validators.md index 4a3c33130..8ed16ca7e 100644 --- a/docs/quickstart/bonding-validators.md +++ b/docs/tutorials/5-bonding-validators.md @@ -1,9 +1,5 @@ # Bonding Validators -As Burrow runs on Tendermint, it supports the notion of bonding validators. - -## Example - We need at least one validator to start the chain, so run the following to construct a genesis of two accounts with the `Bond` permission, one of which is pre-bonded: diff --git a/docs/quickstart/seed-nodes.md b/docs/tutorials/6-seed-nodes.md similarity index 96% rename from docs/quickstart/seed-nodes.md rename to docs/tutorials/6-seed-nodes.md index a55b7aedd..53d49406c 100644 --- a/docs/quickstart/seed-nodes.md +++ b/docs/tutorials/6-seed-nodes.md @@ -1,6 +1,6 @@ # Network with seed nodes -## What is a seed node +## What is a seed node? According to [Tendermint documentation](https://tendermint.com/docs/tendermint-core/using-tendermint.html#seed): >A seed node is a node who relays the addresses of other peers which they know diff --git a/docs/quickstart/dump-restore.md b/docs/tutorials/7-dump-restore.md similarity index 75% rename from docs/quickstart/dump-restore.md rename to docs/tutorials/7-dump-restore.md index c431ca843..a88939c97 100644 --- a/docs/quickstart/dump-restore.md +++ b/docs/tutorials/7-dump-restore.md @@ -1,9 +1,9 @@ -## Dump chain state and bring up a new chain with that state +# Dump / Restore Sometimes there are breaking changes in burrow. This provides a method for dumping an old chain, and restoring a new chain with that state. -# Dumping existing state +## Dumping existing state The `burrow dump` command connects to burrow node and retrieves the following: @@ -16,27 +16,33 @@ This can be dumped in json or go-amino format. The structure is described in (pr it saved in go-amino, but it can be saved in json format by specify `--json`. It is also possible to dump the state at a specific height using `--height`. -# Creating a new chain genesis with state +## Creating a new chain genesis with state So you will need the `.keys` directory of the old chain, the `genesis.json` (called genesis-original in the example below) from the old chain and the dump file (called `dump.json` here). -`burrow configure -m BurrowTestRestoreNode -n "Restored Chain" -g genesis-original.json -w genesis.json --restore-dump dump.json > burrow.toml` +```bash +burrow configure -m BurrowTestRestoreNode -n "Restored Chain" -g genesis-original.json -w genesis.json --restore-dump dump.json > burrow.toml +``` Note that the chain genesis will contain an `AppHash` specific to this restore file. -# Restart the chain with the state +## Restart the chain with the state This will populate the `.burrow` directory with the state. -`burrow restore dump.json` +```bash +burrow restore dump.json +``` This will create a block 0 with the restored state. Normally burrow chains start a height 1. -# Run the new chain +## Run the new chain Simply start `burrow` as you would normally. -`burrow start` +```bash +burrow start +``` Now burrow should start making blocks at 1 as usual. \ No newline at end of file diff --git a/docs/txs/bond.md b/docs/txs/bond.md new file mode 100644 index 000000000..b8bf0931d --- /dev/null +++ b/docs/txs/bond.md @@ -0,0 +1,32 @@ +# Bond / Unbond + +Burrow adopts the notion of Bonded Proof-of-Stake (BPoS). This means that in order to +participate in consensus, a node must give some value of its token as collateral. +The more token that is bonded, the higher the chance of 'mining' a block. + +## How it Works + +When starting a burrow node, we provide an address which links to an owned key-pair. +Each running node thus has an identity which may active in the validator set. Assuming we have +connected to a network, our node will replay state downloaded from its peers - from which we will +be able to discern any native token stored at our address. If this amount is non-negligible +we can submit a signed BondTx to be gossiped amongst the current validators who should include it +in a block. When executing this transaction against our global state, burrow will first check that the +input address has correctly signed the payload, that the respective account exists with the bonding +permission and has enough token to stake. If successful, then this will subtract the token from the +account and raise the new validators power - enabling it to vote and propose new blocks. The procedure +for unbonding is antithetical, diminishing the validator accounts power on success. + +One nuance with altering the validator set is to do with a concept we call the 'max flow'. +To prevent the validator pool changing too quickly over a single block whilst ensuring the +majority of validators are non-byzantine after the transition, we allow up to `ceil((t)/3) - 1` +to be changed where `t` is the current total validator power. + + +## Future Work + +Currently a validator must bond or unbond themselves directly - we enforce a strict relationship +that prohibits staking token to another account. Funds may be send to another account however, +and providing that also has permission to bond, then it may join the validator set. In the future we +hope to extend our model to allow for delegation, whereby any party with native token may stake it +against a running validator and receive a share of the rewards. \ No newline at end of file diff --git a/example/basic-app-website/.gitignore b/example/basic-app-website/.gitignore new file mode 100644 index 000000000..2badab3e7 --- /dev/null +++ b/example/basic-app-website/.gitignore @@ -0,0 +1,6 @@ +.keys +burrow.toml +genesis.json +account.json +deploy.output.json +bin diff --git a/example/basic-app-website/Makefile b/example/basic-app-website/Makefile new file mode 100644 index 000000000..f7b94a749 --- /dev/null +++ b/example/basic-app-website/Makefile @@ -0,0 +1,80 @@ +# +# basic-app is intended to provide an example end-to-end use of burrow and burrow module in a node.js app +# + + +# One of: Darwin_i386, Darwin_x86_64, Linux_i386, Linux_x86_64 +BURROW_ARCH := Linux_x86_64 +BURROW_VERSION := 0.27.0 +BURROW_RELEASE_URL := "https://github.com/hyperledger/burrow/releases/download/v${BURROW_VERSION}/burrow_${BURROW_VERSION}_${BURROW_ARCH}.tar.gz " +# Set to 'burrow' to use whatever is on PATH instead +BURROW_BIN := bin/burrow + +# +# Running the chain +# +# Make a simple single node chain +.PHONY: chain +chain: bin/burrow burrow.toml + +# Get the burrow binary +bin/burrow: + mkdir -p bin + curl -L ${BURROW_RELEASE_URL} | tar zx -C bin burrow + +# Generate the chain +burrow.toml genesis.json: + ${BURROW_BIN} spec --full-accounts 1 | ${BURROW_BIN} configure --genesis-spec=- --separate-genesis-doc=genesis.json > burrow.toml + +# Dump account information to file for app +account.json: genesis.json + jq '.Accounts[] | select(.Name == "Full_0")' genesis.json > account.json + +# Reset burrow state +.PHONY: reset_chain +reset_chain: + rm -rf .burrow + +# Remove burrow chain completely +.PHONY: remove_chain +remove_chain: + rm -rf burrow.toml genesis.json .keys .burrow + +# remake and reset chain +.PHONY: rechain +rechain: | remove_chain chain + +.PHONY: start_chain +start_chain: chain + ${BURROW_BIN} start -v0 + +.PHONY: restart +restart: | rechain start_chain + +# +# Deploying the contract +# +deploy.output.json: simplestorage.sol deploy.yaml account.json + ${BURROW_BIN} deploy --address $(shell jq '.Address' account.json) deploy.yaml + +.PHONY: delete_deploy +delete_deploy: + rm -rf deploy.output.json + +.PHONY: deploy +deploy: deploy.output.json + +.PHONY: redeploy +redeploy: | delete_deploy deploy.output.json + +# +# Running the app +# + +.PHONY: npm_install +npm_install: + npm install + +.PHONY: start_app +start_app: npm_install deploy + node app.js diff --git a/example/basic-app-website/README.md b/example/basic-app-website/README.md new file mode 100644 index 000000000..4df853efd --- /dev/null +++ b/example/basic-app-website/README.md @@ -0,0 +1,55 @@ +# Example basic-app (with website) + +Note that this example is the same as the the basic-app example, apart from step 3. + +This example contains an example solidity contract [simplestorage](simplestorage.sol) and a [node.js application](app.js) that interacts with the contract using [burrow](../../js/README.md). It also contains a [makefile](makefile) that will set up a single node chain, deploy the contract using `burrow deploy`. The node app configures itself to use the the single node chain my looking for [account.json](account.json) and [deploy.output.json](deploy.output.json) files that are emitted by `burrow deploy` and the makefile. + +The makefile provides some examples of using the `burrow` command line tooling and you are invited to modify it for your purposes. + +## Dependencies +To run the makefile you will need to have installed: + +- GNU Make +- Node.js (the `node` binary) +- npm (the node package manager) +- jq (the JSON tool) + +Burrow will be downloaded for you when using the makefile, but you may override `BURROW_BIN` and `BURROW_ARCH` in the makefile to change this behaviour. By default Burrow is downloaded for `Linux_x86_64. + +## Running the example + +All commands should be run from the same directory as this readme file. + +### Step one +Start the chain + +```shell +make start_chain +``` + +This will install burrow, create a new chain as necessary. + +If successful you will see continuous output in your terminal, you can shutdown Burrow by sending the interrupt signal with Ctrl-C, and restart it again with whatever state has accumulated with `make start_chain`. If you would like to destroy the existing chain and start completely fresh (including deleting keys) run `make rechain`. If you would like to keep existing keys and chain config run `make reset_chain`. + +You can redeploy the contract (to a new address) with `make redeploy`. The node app will then use this new contract by reading the address deploy.output.json. Be sure to do this if you wish to modify simplestorage.sol. + +### Step two +Leave burrow running and in a separate terminal start the app which runs a simple HTTP server with: + +```shell +make start_app +``` + +This will deploy the contract if necessary, install any node dependencies, and then start an expressjs server, which will run until interrupted. + +### Step three +Open a web browser and type: + +```shell + http://localhost:3000/ +``` + +You will see two buttons: +* Set Value - that allows you to change the value stored in the associated smart contract +* Get Value - that allows you to retrieve the value stored in the associated smart contract, which will be displayed underneath the button + diff --git a/example/basic-app-website/app.js b/example/basic-app-website/app.js new file mode 100644 index 000000000..4e2a04030 --- /dev/null +++ b/example/basic-app-website/app.js @@ -0,0 +1,96 @@ +const fs = require('fs') +const burrow = require('@monax/burrow') +const express = require('express') +const bodyParser = require('body-parser') + +// Burrow address +let chainURL = '127.0.0.1:10997' +const abiFile = 'bin/simplestorage.bin' +const deployFile = 'deploy.output.json' +const accountFile = 'account.json' + +// Port to run example on locally +const exampleAppPort = 3000 + +function slurp (file) { + return JSON.parse(fs.readFileSync(file, 'utf8')) +} + +// Grab the account file that is expected to have 'Address' field +let account = slurp(accountFile) +// Connect to running burrow chain using the account address to identify our input account and return values as an object +// using named returns where provided +let chain = burrow.createInstance(chainURL, account.Address, {objectReturn: true}) +// The ABI file produced by the solidity compiler (through burrow deploy) that acts as a manifest for our deployed contract +let abi = slurp(abiFile).Abi +// The deployment receipt written to disk by burrow deploy that contains the deployed address of the contract amongst other things +let deploy = slurp(deployFile) +// The contract we will call +let contractAddress = deploy.simplestorage +// A Javascript object that wraps our simplestorage contract and will handle translating Javascript calls to EVM invocations +let store = chain.contracts.new(abi, null, contractAddress) + +// For this example we use a simple router based on expressjs +const app = express() +// Apparently this needs to be its own module... +app.use(bodyParser.json()) +app.use(express.static('public')) +app.use(bodyParser.urlencoded({ extended: true })) +app.set('view engine', 'ejs') + +// Some helpers for parsing/validating input +let asInteger = value => new Promise((resolve, reject) => + (i => isNaN(i) ? reject(`${value} is ${typeof value} not integer`) : resolve(i))(parseInt(value))) + +let param = (obj, prop) => new Promise((resolve, reject) => + prop in obj ? resolve(obj[prop]) : reject(`expected key '${prop}' in ${JSON.stringify(obj)}`)) + +let handlerError = err => { console.log(err); return err.toString() } + +// We define some method endpoints +// Get the value from the contract by calling the Solidity 'get' method +app.get('/', (req, res) => store.get() + .then(ret => res.render('index', {valueIs: ret.values.value, error: null})) + .catch(err => res.send(handlerError(err)))) + +// this next get occurs when the user presses the get value button on the website +// Get the value from the contract by calling the Solidity 'get' method +app.get('/getValue', (req, res) => store.get() + .then(ret => res.render('index', {valueIs: ret.values.value, error: null})) + .catch(err => res.send(handlerError(err)))) + +// Sets the value by accepting a value in HTTP POST data and calling the Solidity 'set' method +app.post('/', (req, res) => param(req.body, 'valueNum') + .then(valueNum => asInteger(valueNum)) + .then(valueNum => store.set(valueNum)) + .then(ret => res.render('index', {valueIs: 'logged', error: null})) + + .catch(err => res.send(handlerError(err)))) + +// Sets a value by HTTP POSTing to the value you expect to be stored encoded in the URL - so that the value can be +// updated atomically +app.post('/:test', (req, res) => param(req.body, 'value') + .then(value => Promise.all([asInteger(req.params.test), asInteger(value)])) + .then(([test, value]) => store.testAndSet(test, value)) + .then(ret => res.send(ret.values)) + .catch(err => res.send(handlerError(err)))) + +const url = `http://127.0.0.1:${exampleAppPort}` + +// Listen for requests +app.listen(exampleAppPort, () => console.log(`Example app listening on ${url}... + +You may wish to try the following: +# Inspect current stored value + $ curl ${url} + +# Set the value to 2000 + $ curl -d '{"value": 2000}' -H "Content-Type: application/json" -X POST ${url} + +# Set the value via a testAndSet operation + $ curl -d '{"value": 30}' -H "Content-Type: application/json" -X POST ${url}/2000 + +# Attempt the same testAndSet which now fails since the value stored is no longer '2000' + $ curl -d '{"value": 30}' -H "Content-Type: application/json" -X POST ${url}/2000 + $ curl ${url} + `)) diff --git a/example/basic-app-website/deploy.yaml b/example/basic-app-website/deploy.yaml new file mode 100644 index 000000000..932279077 --- /dev/null +++ b/example/basic-app-website/deploy.yaml @@ -0,0 +1,29 @@ +jobs: + +- name: valueToSet + set: + val: 10 + +- name: simplestorage + deploy: + contract: simplestorage.sol + data: + - 0 + +- name: setStorage + call: + destination: $simplestorage + function: set + data: + - $valueToSet + +- name: queryStorage + query-contract: + destination: $simplestorage + function: get + +- name: assertStorage + assert: + key: $queryStorage + relation: eq + val: $valueToSet diff --git a/example/basic-app-website/package-lock.json b/example/basic-app-website/package-lock.json new file mode 100644 index 000000000..00f76c4ba --- /dev/null +++ b/example/basic-app-website/package-lock.json @@ -0,0 +1,1487 @@ +{ + "name": "basic-app", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@grpc/proto-loader": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.4.0.tgz", + "integrity": "sha512-Jm6o+75uWT7E6+lt8edg4J1F/9+BedOjaMgwE14pxS/AO43/0ZqK+rCLVVrXLoExwSAZvgvOD2B0ivy3Spsspw==", + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, + "@monax/burrow": { + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/@monax/burrow/-/burrow-0.24.3.tgz", + "integrity": "sha512-HVqPF+5KGkt+UkBj/Mn8JGEH6+7x67m/0TApBmvTdbbT6TG5IouzP4kP1pooo0e8RAGmxybPJMalZcReFDpAUw==", + "requires": { + "@grpc/proto-loader": "^0.4.0", + "crypto-js": "3.1.4", + "ethereumjs-abi": "^0.6.5", + "grpc": "^1.18.0", + "protobufjs": "^6.8.6" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" + }, + "@types/node": { + "version": "10.14.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.15.tgz", + "integrity": "sha512-CBR5avlLcu0YCILJiDIXeU2pTw7UK/NIxfC63m7d7CVamho1qDEzXKkOtEauQRPMy6MI8mLozth+JJkas7HY6g==" + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "~3" + }, + "dependencies": { + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + } + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "crypto-js": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.4.tgz", + "integrity": "sha1-IWTxbeLykVELZS10a84302SYMK0=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz", + "integrity": "sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==" + }, + "elliptic": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "requires": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "ethereumjs-util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.3", + "qs": "6.5.1", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.1", + "http-errors": "~1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "~2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "~1.6.15" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "grpc": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.22.2.tgz", + "integrity": "sha512-gaK59oAA5/mlOIn+hQO5JROPoAzsaGRpEMcrAayW5WGETS8QScpBoQ+XBxEWAAF0kbeGIELuGRCVEObKS1SLmw==", + "requires": { + "lodash.camelcase": "^4.3.0", + "lodash.clone": "^4.5.0", + "nan": "^2.13.2", + "node-pre-gyp": "^0.13.0", + "protobufjs": "^5.0.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.6", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true + } + } + }, + "node-pre-gyp": { + "version": "0.13.0", + "bundled": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true + }, + "protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "requires": { + "ascli": "~1", + "bytebuffer": "~5", + "glob": "^7.0.5", + "yargs": "^3.10.0" + } + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.7.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.1", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "4.4.10", + "bundled": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.5", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "requires": { + "mime-db": "~1.36.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "protobufjs": { + "version": "6.8.8", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", + "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + } + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.3.tgz", + "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", + "requires": { + "bn.js": "^4.11.1", + "safe-buffer": "^5.1.1" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "secp256k1": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.7.1.tgz", + "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", + "requires": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.4.1", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + } + } + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + } + } +} diff --git a/example/basic-app-website/package.json b/example/basic-app-website/package.json new file mode 100644 index 000000000..fedd4ceb8 --- /dev/null +++ b/example/basic-app-website/package.json @@ -0,0 +1,17 @@ +{ + "name": "basic-app", + "version": "1.0.0", + "description": "Simple end-to-end Burrow app", + "main": "app.js", + "scripts": { + "test": "node app.js" + }, + "author": "Silas Davis, website section added by Luke Riley", + "license": "Apache-2.0", + "dependencies": { + "@monax/burrow": "^0.24.3", + "body-parser": "^1.18.3", + "express": "^4.16.3", + "ejs": "^2.6.2" + } +} diff --git a/example/basic-app-website/public/css/style.css b/example/basic-app-website/public/css/style.css new file mode 100644 index 000000000..f9015ef92 --- /dev/null +++ b/example/basic-app-website/public/css/style.css @@ -0,0 +1,74 @@ +/* + Styles from this codepen: + https://codepen.io/official_naveen/pen/rgknI +*/ + +body { + width: 800px; + margin: 0 auto; + font-family: 'Open Sans', sans-serif; +} +.container { + width: 600px; + margin: 0 auto; +} +fieldset { + display: block; + -webkit-margin-start: 0px; + -webkit-margin-end: 0px; + -webkit-padding-before: 0em; + -webkit-padding-start: 0em; + -webkit-padding-end: 0em; + -webkit-padding-after: 0em; + border: 0px; + border-image-source: initial; + border-image-slice: initial; + border-image-width: initial; + border-image-outset: initial; + border-image-repeat: initial; + min-width: -webkit-min-content; + padding: 30px; +} +.ghost-input, p { + display: block; + font-weight:300; + width: 100%; + font-size: 25px; + border:0px; + outline: none; + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + color: #4b545f; + background: #fff; + font-family: Open Sans,Verdana; + padding: 10px 15px; + margin: 30px 0px; + -webkit-transition: all 0.1s ease-in-out; + -moz-transition: all 0.1s ease-in-out; + -ms-transition: all 0.1s ease-in-out; + -o-transition: all 0.1s ease-in-out; + transition: all 0.1s ease-in-out; +} +.ghost-input:focus { + border-bottom:1px solid #ddd; +} +.ghost-button { + background-color: transparent; + border:2px solid #ddd; + padding:10px 30px; + width: 100%; + min-width: 350px; + -webkit-transition: all 0.1s ease-in-out; + -moz-transition: all 0.1s ease-in-out; + -ms-transition: all 0.1s ease-in-out; + -o-transition: all 0.1s ease-in-out; + transition: all 0.1s ease-in-out; +} +.ghost-button:hover { + border:2px solid #515151; +} +p { + color: #E64A19; +} diff --git a/example/basic-app-website/simplestorage.sol b/example/basic-app-website/simplestorage.sol new file mode 100644 index 000000000..a5340eff0 --- /dev/null +++ b/example/basic-app-website/simplestorage.sol @@ -0,0 +1,28 @@ +pragma solidity >=0.0.0; + + +contract simplestorage { + uint public storedData; + + constructor(uint initVal) public { + storedData = initVal; + } + + function set(uint value) public { + storedData = value; + } + + function get() public view returns (uint value) { + return storedData; + } + + // Since transactions are executed atomically we can implement this concurrency primitive in Solidity with the + // desired behaviour + function testAndSet(uint expected, uint newValue) public returns (uint value, bool success) { + if (storedData == expected) { + storedData = newValue; + return (storedData, true); + } + return (storedData, false); + } +} diff --git a/example/basic-app-website/views/index.ejs b/example/basic-app-website/views/index.ejs new file mode 100644 index 000000000..c4cfb32e1 --- /dev/null +++ b/example/basic-app-website/views/index.ejs @@ -0,0 +1,32 @@ + + + + + + Test + + + + +
+
+
+ + +
+
+
+
+ +
+ <% if(valueIs !== null){ %> +

<%= valueIs %>

+ <% } %> + + <% if(valueIs !== null){ %> +

<%= error %>

+ <% } %> +
+
+ + diff --git a/example/basic-app/.gitignore b/example/basic-app/.gitignore new file mode 100644 index 000000000..2badab3e7 --- /dev/null +++ b/example/basic-app/.gitignore @@ -0,0 +1,6 @@ +.keys +burrow.toml +genesis.json +account.json +deploy.output.json +bin diff --git a/example/basic-app/Makefile b/example/basic-app/Makefile new file mode 100644 index 000000000..f7b94a749 --- /dev/null +++ b/example/basic-app/Makefile @@ -0,0 +1,80 @@ +# +# basic-app is intended to provide an example end-to-end use of burrow and burrow module in a node.js app +# + + +# One of: Darwin_i386, Darwin_x86_64, Linux_i386, Linux_x86_64 +BURROW_ARCH := Linux_x86_64 +BURROW_VERSION := 0.27.0 +BURROW_RELEASE_URL := "https://github.com/hyperledger/burrow/releases/download/v${BURROW_VERSION}/burrow_${BURROW_VERSION}_${BURROW_ARCH}.tar.gz " +# Set to 'burrow' to use whatever is on PATH instead +BURROW_BIN := bin/burrow + +# +# Running the chain +# +# Make a simple single node chain +.PHONY: chain +chain: bin/burrow burrow.toml + +# Get the burrow binary +bin/burrow: + mkdir -p bin + curl -L ${BURROW_RELEASE_URL} | tar zx -C bin burrow + +# Generate the chain +burrow.toml genesis.json: + ${BURROW_BIN} spec --full-accounts 1 | ${BURROW_BIN} configure --genesis-spec=- --separate-genesis-doc=genesis.json > burrow.toml + +# Dump account information to file for app +account.json: genesis.json + jq '.Accounts[] | select(.Name == "Full_0")' genesis.json > account.json + +# Reset burrow state +.PHONY: reset_chain +reset_chain: + rm -rf .burrow + +# Remove burrow chain completely +.PHONY: remove_chain +remove_chain: + rm -rf burrow.toml genesis.json .keys .burrow + +# remake and reset chain +.PHONY: rechain +rechain: | remove_chain chain + +.PHONY: start_chain +start_chain: chain + ${BURROW_BIN} start -v0 + +.PHONY: restart +restart: | rechain start_chain + +# +# Deploying the contract +# +deploy.output.json: simplestorage.sol deploy.yaml account.json + ${BURROW_BIN} deploy --address $(shell jq '.Address' account.json) deploy.yaml + +.PHONY: delete_deploy +delete_deploy: + rm -rf deploy.output.json + +.PHONY: deploy +deploy: deploy.output.json + +.PHONY: redeploy +redeploy: | delete_deploy deploy.output.json + +# +# Running the app +# + +.PHONY: npm_install +npm_install: + npm install + +.PHONY: start_app +start_app: npm_install deploy + node app.js diff --git a/example/basic-app/README.md b/example/basic-app/README.md new file mode 100644 index 000000000..57421cd5b --- /dev/null +++ b/example/basic-app/README.md @@ -0,0 +1,87 @@ +# Example basic-app + +This example contains an example solidity contract [simplestorage](simplestorage.sol) and a [node.js application](app.js) that interacts with the contract using [burrow module](../../js/README.md). It also contains a [makefile](makefile) that will set up a single node chain, deploy the contract using `burrow deploy`. The node app configures itself to use the the single node chain my looking for [account.json](account.json) and [deploy.output.json](deploy.output.json) files that are emitted by `burrow deploy` and the makefile. + +The makefile provides some examples of using the `burrow` command line tooling and you are invited to modify it for your purposes. + +## Dependencies +To run the makefile you will need to have installed: + +- GNU Make +- Node.js (the `node` binary) +- npm (the node package manager) +- jq (the JSON tool) + +Burrow will be downloaded for you when using the makefile, but you may override `BURROW_BIN` and `BURROW_ARCH` in the makefile to change this behaviour. By default Burrow is downloaded for `Linux_x86_64. + +## Running the example + +All commands should be run from the same directory as this readme file. + +### Step one +Start the chain + +```shell +make start_chain +``` + +This will install burrow, create a new chain as necessary. + +If successful you will see continuous output in your terminal, you can shutdown Burrow by sending the interrupt signal with Ctrl-C, and restart it again with whatever state has accumulated with `make start_chain`. If you would like to destroy the existing chain and start completely fresh (including deleting keys) run `make rechain`. If you would like to keep existing keys and chain config run `make reset_chain`. + +You can redeploy the contract (to a new address) with `make redeploy`. The node app will then use this new contract by reading the address deploy.output.json. Be sure to do this if you wish to modify simplestorage.sol. + +### Step two +Leave burrow running and in a separate terminal start the app which runs a simple HTTP server with: + +```shell +make start_app +``` + +This will deploy the contract if necessary, install any node dependencies, and then start an expressjs server, which will run until interrupted. + +### Step three +In a third terminal you may run the following commands that will call the Solidity smart contract using Javascript and burrow module: + +```shell +# Inspect current value + $ curl http://127.0.0.1:3000 + +# Set the value to 2000 + $ curl -d '{"value": 2000}' -H "Content-Type: application/json" -X POST http://127.0.0.1:3000 + +# Set the value via a testAndSet operation + $ curl -d '{"value": 30}' -H "Content-Type: application/json" -X POST http://127.0.0.1:3000/2000 + +# Attempt the same testAndSet which now fails since the value stored is no longer '2000' + $ curl -d '{"value": 30}' -H "Content-Type: application/json" -X POST http://127.0.0.1:3000/2000 + $ curl http://127.0.0.1:3000 +``` + +Note: [httpie](https://httpie.org/) is a useful tool that makes POSTing to JSON endpoints more succinct: + +```shell +# Inspect current value + $ http 127.0.0.1:3000 + +# Set the value to 2000 + $ http 127.0.0.1:3000 value=2000 + +# Set the value via a testAndSet operation + $ http 127.0.0.1:3000/2000 value=30 + +# Attempt the same testAndSet which now fails since the value stored is no longer '2000' + $ http 127.0.0.1:3000/2000 value=30 + $ http 127.0.0.1:3000 +``` + +## Additional endpoints + +### Sending value and creating accounts + +An endpoint is provided at `/send` for sending value from the default input account (defined in account.json after making the chain) that can be used with: + +```shell +# Send 1000 units of native token to D1293FE65A071A9DB539D64858F0A3D4BCAA2EBA + http :3000/send/D1293FE65A071A9DB539D64858F0A3D4BCAA2EBA amount=1000 +``` diff --git a/example/basic-app/app.js b/example/basic-app/app.js new file mode 100644 index 000000000..c71d5cffe --- /dev/null +++ b/example/basic-app/app.js @@ -0,0 +1,106 @@ +const fs = require('fs') +const burrow = require('@monax/burrow') +const express = require('express') +const bodyParser = require('body-parser') + +// Burrow address +let chainURL = '127.0.0.1:10997' +const abiFile = 'bin/simplestorage.bin' +const deployFile = 'deploy.output.json' +const accountFile = 'account.json' + +// Port to run example on locally +const exampleAppPort = 3000 + +function slurp (file) { + return JSON.parse(fs.readFileSync(file, 'utf8')) +} + +// Grab the account file that is expected to have 'Address' field +let account = slurp(accountFile) +// Connect to running burrow chain using the account address to identify our input account and return values as an object +// using named returns where provided +let chain = burrow.createInstance(chainURL, account.Address, {objectReturn: true}) +// The ABI file produced by the solidity compiler (through burrow deploy) that acts as a manifest for our deployed contract +let abi = slurp(abiFile).Abi +// The deployment receipt written to disk by burrow deploy that contains the deployed address of the contract amongst other things +let deploy = slurp(deployFile) +// The contract we will call +let contractAddress = deploy.simplestorage +// A Javascript object that wraps our simplestorage contract and will handle translating Javascript calls to EVM invocations +let store = chain.contracts.new(abi, null, contractAddress) + +// For this example we use a simple router based on expressjs +const app = express() +// Apparently this needs to be its own module... +app.use(bodyParser.json()) + +// Some helpers for parsing/validating input +let asInteger = value => new Promise((resolve, reject) => + (i => isNaN(i) ? reject(`${value} is ${typeof value} not integer`) : resolve(i))(parseInt(value))) + +let param = (obj, prop) => new Promise((resolve, reject) => + prop in obj ? resolve(obj[prop]) : reject(`expected key '${prop}' in ${JSON.stringify(obj)}`)) + +let handleError = err => { + console.log(err) + return err.toString() +} + +// We define some method endpoints +// Get the value from the contract by calling the Solidity 'get' method +app.get('/', (req, res) => store.get() + .then(ret => res.send(ret.values)) + .catch(err => res.send(handleError(err)))) + +// Sets the value by accepting a value in HTTP POST data and calling the Solidity 'set' method +app.post('/', (req, res) => param(req.body, 'value') + .then(value => asInteger(value)) + .then(value => store.set(value).then(() => value)) + .then(value => res.send({value: value, success: true})) + .catch(err => res.send(handleError(err)))) + +// Sets a value by HTTP POSTing to the value you expect to be stored encoded in the URL - so that the value can be +// updated atomically +app.post('/:test', (req, res) => param(req.body, 'value') + .then(value => Promise.all([asInteger(req.params.test), asInteger(value)])) + .then(([test, value]) => store.testAndSet(test, value)) + .then(ret => res.send(ret.values)) + .catch(err => res.send(handleError(err)))) + +// Send a little value to an account which has the effect of creating that account if it does not exist +app.post('/send/:recipient', (req, res) => param(req.body, 'amount') + .then(amount => + chain.transact.SendTxSync( + { + Inputs: [{ + Address: Buffer.from(account.Address, 'hex'), + Amount: amount + }], + Outputs: [{ + Address: Buffer.from(req.params.recipient, 'hex'), + Amount: amount + }] + })) + .then(txe => res.send({txHash: txe.TxHash.toString('hex'), success: true})) + .catch(err => res.send(handleError(err)))) + +const url = `http://127.0.0.1:${exampleAppPort}` + +// Listen for requests +app.listen(exampleAppPort, () => console.log(`Example app listening on ${url}... + +You may wish to try the following: +# Inspect current stored value + $ curl ${url} + +# Set the value to 2000 + $ curl -d '{"value": 2000}' -H "Content-Type: application/json" -X POST ${url} + +# Set the value via a testAndSet operation + $ curl -d '{"value": 30}' -H "Content-Type: application/json" -X POST ${url}/2000 + +# Attempt the same testAndSet which now fails since the value stored is no longer '2000' + $ curl -d '{"value": 30}' -H "Content-Type: application/json" -X POST ${url}/2000 + $ curl ${url} + `)) diff --git a/example/basic-app/deploy.yaml b/example/basic-app/deploy.yaml new file mode 100644 index 000000000..932279077 --- /dev/null +++ b/example/basic-app/deploy.yaml @@ -0,0 +1,29 @@ +jobs: + +- name: valueToSet + set: + val: 10 + +- name: simplestorage + deploy: + contract: simplestorage.sol + data: + - 0 + +- name: setStorage + call: + destination: $simplestorage + function: set + data: + - $valueToSet + +- name: queryStorage + query-contract: + destination: $simplestorage + function: get + +- name: assertStorage + assert: + key: $queryStorage + relation: eq + val: $valueToSet diff --git a/example/basic-app/package-lock.json b/example/basic-app/package-lock.json new file mode 100644 index 000000000..2df08c3a3 --- /dev/null +++ b/example/basic-app/package-lock.json @@ -0,0 +1,1410 @@ +{ + "name": "basic-app", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@grpc/proto-loader": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.4.0.tgz", + "integrity": "sha512-Jm6o+75uWT7E6+lt8edg4J1F/9+BedOjaMgwE14pxS/AO43/0ZqK+rCLVVrXLoExwSAZvgvOD2B0ivy3Spsspw==", + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, + "@monax/burrow": { + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/@monax/burrow/-/burrow-0.24.3.tgz", + "integrity": "sha512-HVqPF+5KGkt+UkBj/Mn8JGEH6+7x67m/0TApBmvTdbbT6TG5IouzP4kP1pooo0e8RAGmxybPJMalZcReFDpAUw==", + "requires": { + "@grpc/proto-loader": "^0.4.0", + "crypto-js": "3.1.4", + "ethereumjs-abi": "^0.6.5", + "grpc": "^1.18.0", + "protobufjs": "^6.8.6" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" + }, + "@types/node": { + "version": "10.14.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.15.tgz", + "integrity": "sha512-CBR5avlLcu0YCILJiDIXeU2pTw7UK/NIxfC63m7d7CVamho1qDEzXKkOtEauQRPMy6MI8mLozth+JJkas7HY6g==" + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "~3" + }, + "dependencies": { + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + } + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "crypto-js": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.4.tgz", + "integrity": "sha1-IWTxbeLykVELZS10a84302SYMK0=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "elliptic": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "ethereumjs-abi": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", + "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "requires": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "ethereumjs-util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "grpc": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.22.2.tgz", + "integrity": "sha512-gaK59oAA5/mlOIn+hQO5JROPoAzsaGRpEMcrAayW5WGETS8QScpBoQ+XBxEWAAF0kbeGIELuGRCVEObKS1SLmw==", + "requires": { + "lodash.camelcase": "^4.3.0", + "lodash.clone": "^4.5.0", + "nan": "^2.13.2", + "node-pre-gyp": "^0.13.0", + "protobufjs": "^5.0.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.6", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true + } + } + }, + "node-pre-gyp": { + "version": "0.13.0", + "bundled": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true + }, + "protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "requires": { + "ascli": "~1", + "bytebuffer": "~5", + "glob": "^7.0.5", + "yargs": "^3.10.0" + } + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.7.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.1", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "4.4.10", + "bundled": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.5", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "requires": { + "mime-db": "~1.36.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "protobufjs": { + "version": "6.8.8", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", + "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + } + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.3.tgz", + "integrity": "sha512-l6YVrI7+d2vpW6D6rS05x2Xrmq8oW7v3pieZOJKBEdjuTF4Kz/iwk55Zyh1Zaz+KOB2kC8+2jZlp2u9L4tTzCQ==", + "requires": { + "bn.js": "^4.11.1", + "safe-buffer": "^5.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "secp256k1": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.7.1.tgz", + "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", + "requires": { + "bindings": "^1.5.0", + "bip66": "^1.1.5", + "bn.js": "^4.11.8", + "create-hash": "^1.2.0", + "drbg.js": "^1.0.1", + "elliptic": "^6.4.1", + "nan": "^2.14.0", + "safe-buffer": "^5.1.2" + } + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + } + } +} diff --git a/example/basic-app/package.json b/example/basic-app/package.json new file mode 100644 index 000000000..f406fcaaa --- /dev/null +++ b/example/basic-app/package.json @@ -0,0 +1,16 @@ +{ + "name": "basic-app", + "version": "1.0.0", + "description": "Simple end-to-end Burrow app", + "main": "app.js", + "scripts": { + "test": "node app.js" + }, + "author": "Silas Davis", + "license": "Apache-2.0", + "dependencies": { + "@monax/burrow": "^0.24.3", + "body-parser": "^1.18.3", + "express": "^4.16.4" + } +} diff --git a/example/basic-app/simplestorage.sol b/example/basic-app/simplestorage.sol new file mode 100644 index 000000000..a5da7bd5a --- /dev/null +++ b/example/basic-app/simplestorage.sol @@ -0,0 +1,27 @@ +pragma solidity >=0.0.0; + +contract simplestorage { + uint public storedData; + + constructor(uint initVal) public { + storedData = initVal; + } + + function set(uint value) public { + storedData = value; + } + + function get() public view returns (uint value) { + return storedData; + } + + // Since transactions are executed atomically we can implement this concurrency primitive in Solidity with the + // desired behaviour + function testAndSet(uint expected, uint newValue) public returns (uint value, bool success) { + if (storedData == expected) { + storedData = newValue; + return (storedData, true); + } + return (storedData, false); + } +} diff --git a/js/README.md b/js/README.md new file mode 100644 index 000000000..ca5e17f47 --- /dev/null +++ b/js/README.md @@ -0,0 +1,13 @@ +# @monax/burrow (Alpha) + +This is a JavaScript API for communicating with a [Hyperledger Burrow](https://github.com/hyperledger/burrow) server, which implements the GRPC spec. + +[![npm version][npm-image]][npm-url] + +## New Library + +Previously our client libs were broken into two components `@monax/legacy-db.js` and `@monax/legacy-contract.js`. These have both been replaced by this library `@monax/burrow`. This upgrade was part of a major re-write on the back-end and as such ONLY `@monax/burrow` SHOULD BE USED WITH BURROW VERSIONS GREATER THAN 0.20.0. There is NO BACKWARDS COMPATIBILITY of this lib with versions of burrow less than 0.20.0. There will be a short guide below for upgrading existing applications to new burrow versions. + +## Version compatibility + +This lib's version is pegged to burrow's version on the minor. So @monax/burrow at version X.Y.^ will work with burrow version X.Y.^ where ^ means latest patch version. The patch version numbering will not always correspond. If you are having difficulties getting this lib to work with a burrow release please first make sure you have the latest patch version of each. \ No newline at end of file diff --git a/js/index.js b/js/index.js new file mode 100644 index 000000000..c47f3410e --- /dev/null +++ b/js/index.js @@ -0,0 +1,17 @@ +/** + * @file index.js + * @fileOverview Index file for the Burrow javascript API. This file contains a factory method + * for creating a new Burrow instance. + * @author Andreas Olofsson + * @module index + */ +'use strict' + +var Burrow = require('./lib/Burrow') +var utils = require('./lib/utils/utils') + +module.exports = { + createInstance: Burrow.createInstance, + Burrow: Burrow, + utils: utils +} diff --git a/js/lib/Burrow.js b/js/lib/Burrow.js new file mode 100644 index 000000000..7b1606c38 --- /dev/null +++ b/js/lib/Burrow.js @@ -0,0 +1,59 @@ +/** + * @file Burrow.js + * @fileOverview Factory module for the Burrow class. + * @author Dennis Mckinnon + * @module Burrow + */ + +'use strict' + +var Service = require('./service') +var events = require('./events.js') + +var Pipe = require('./pipe') +var ContractManager = require('./contractManager') +var Namereg = require('./namereg') + +/** + * Create a new instance of the Burrow class. + * + * @param {string} URL - URL of Burrow instance. + * @returns {Burrow} - A new instance of the Burrow class. + */ +exports.createInstance = function (URL, account, options) { + URL = (typeof URL === 'string' ? URL : URL.host + ':' + URL.port) + return new Burrow(URL, account, options) +} + +/** + * The main class. + * + * @param {string} URL - URL of Burrow instance. + * @constructor + */ +function Burrow (URL, account, options) { + this.URL = URL + this.tag = options.tag + + if (!account) { + this.readonly = true + this.account = null + } else { + this.readonly = false + this.account = account + } + + this.executionEvents = Service('rpcevents.proto', 'rpcevents', 'ExecutionEvents', URL) + + this.transact = Service('rpctransact.proto', 'rpctransact', 'Transact', URL) + this.query = Service('rpcquery.proto', 'rpcquery', 'Query', URL) + + // This is the execution events streaming service running on top of the raw streaming function. + this.events = events(this) + + // Contracts stuff running on top of grpc + this.pipe = new Pipe(this) + this.contracts = new ContractManager(this, options) + + this.namereg = new Namereg(this) +} diff --git a/js/lib/contractManager.js b/js/lib/contractManager.js new file mode 100644 index 000000000..873194444 --- /dev/null +++ b/js/lib/contractManager.js @@ -0,0 +1,112 @@ +/** + * @file contractManager.js + * @author Dennis Mckinnon + * @date 2018 + * @module contracts + */ + +var Contract = require('./contracts/contract') + +var defaultHandlers = { + call: function (result) { + // console.log(result) + return result.raw + }, + con: function (result) { + // console.log(result) + return result.contractAddress + } +} + +var nullHandler = function (result) { return result } + +function ContractManager (burrow, options) { + options = Object.assign({ objectReturn: false }, options) + var handlers = Object.assign({}, defaultHandlers, options.handlers) + this.burrow = burrow + this.handlers = handlers + + // As of 0.25.0 change the default handler to use nullhandler by default + if (options.objectReturn) { + this.handlers.call = nullHandler + } else { + console.log('DEPRECATION WARNING. As of 0.25.0 the default behaviour of contract calls will be to return the full result object (instead of an array of arguments)') + console.log('If you wish to keep this behaviour after 0.25.0 you can recreate it by using a handler function for calls.') + console.log('This can be done by passing {handlers: {call: function(result){return result.raw}} as an option to burrow object creation (new burrow(URL, account, options))') + } +} + +/** + * Should be called to create new contract on a blockchain + * + * @method new + * @param {Object} abi object (required) + * @param {string} byteCode - Hex encoded bytecode of contact + * @param {*} [contract] constructor param1 (optional) + * @param {*} [contract] constructor param2 (optional) + * @param {Function} callback (optional) + * @param {Object} Handlers (optional) + * @returns {Contract} returns a promise if no callback provided + */ +ContractManager.prototype.deploy = function () { + // parse arguments + var callback = null + var handlers = Object.assign({}, this.handlers) + + var args = Array.prototype.slice.call(arguments) + if (args[args.length - 1] instanceof Object) { + handlers = Object.assign(handlers, args.pop()) + } + + if (args[args.length - 1] instanceof Function) { + callback = args.pop() + } + + // TODO just pass in the bytecode and set it don't do this merging + var abi = args.shift() + var byteCode = args.shift() + + var contract = new Contract(abi, null, byteCode, this.burrow, handlers) + var P = contract._constructor.apply(contract, args).then((address) => { contract.address = address; return contract }) + + if (callback) { + P.then((contract) => { return callback(null, contract) }) + .catch((err) => { return callback(err) }) + } else { + return P.then(() => { return contract }) + } +} + +/** + * Creates a contract object interface from an abi + * + * @method new + * @param {Object} abi - abi object for contract + * @param {string} byteCode - Hex encoded bytecode of contact [can be null] + * @param {string} address - default contract address [can be null] + * @returns {Contract} returns contract interface object + */ +ContractManager.prototype.new = function (abi, byteCode, address, handlers) { + handlers = Object.assign({}, this.handlers, handlers) + return new Contract(abi, address, byteCode, this.burrow, handlers) +} + +/** + * Creates a contract object interface from an address without ABI. + * The contract must be deployed using a recent burrow deploy which registers + * metadata. + * + * @method address + * @param {string} address - default contract address [can be null] + * @returns {Contract} returns contract interface object + */ +ContractManager.prototype.address = function (address, handlers) { + handlers = Object.assign({}, this.handlers, handlers) + return this.burrow.query.GetMetadata({ Address: Buffer.from(address, 'hex') }) + .then((data) => { + const abi = JSON.parse(data.Metadata).Abi + return this.burrow.contracts.new(abi, null, address, handlers) + }) +} + +module.exports = ContractManager diff --git a/js/lib/contracts/contract.js b/js/lib/contracts/contract.js new file mode 100644 index 000000000..8e844003e --- /dev/null +++ b/js/lib/contracts/contract.js @@ -0,0 +1,95 @@ +'use strict' + +var SolidityEvent = require('./event') +var SolidityFunction = require('./function') + +/** + * The contract type. This class is instantiated internally through the factory. + * + * @method Contract + * @param {Array} abi + * @param {string} address + * @param {pipe} pipe; + * @param {Function} outputFormatter - the output formatter. + */ +var Contract = function (abi, address, code, burrow, handlers) { + this.address = address + this.abi = abi + this.code = code + this.burrow = burrow + this.handlers = handlers + + addFunctionsToContract(this) + addEventsToContract(this) +} + +/** + * Should be called to add functions to contract object + * + * @method addFunctionsToContract + * @param {Contract} contract + * @param {Array} abi + * TODO + * @param {function} pipe - The pipe (added internally). + * @param {function} outputFormatter - the output formatter (added internally). + */ + +var addFunctionsToContract = function (contract) { + contract.abi.filter(function (json) { + return (json.type === 'function' || json.type === 'constructor') + }).forEach(function (json) { + let {displayName, typeName, call, encode, decode} = SolidityFunction(json) + + if (json.type === 'constructor') { + contract._constructor = call.bind(contract, false, contract.handlers.con, '') + } else { + // bind the function call to the contract, specify if call or transact is desired + var execute = call.bind(contract, json.constant, contract.handlers.call, null) + execute.sim = call.bind(contract, true, contract.handlers.call, null) + // These allow the interface to be used for a generic contract of this type + execute.at = call.bind(contract, json.constant, contract.handlers.call) + execute.atSim = call.bind(contract, true, contract.handlers.call) + + execute.encode = encode.bind(contract) + execute.decode = decode.bind(contract) + + // Attach to the contract object + if (!contract[displayName]) { + contract[displayName] = execute + } + contract[displayName][typeName] = execute + } + }) + + // Not every abi has a constructor specification. + // If it doesn't we force a _constructor with null abi + if (!contract._constructor) { + let {call} = SolidityFunction(null) + contract._constructor = call.bind(contract, false, contract.handlers.con, '') + } +} + +/** + * Should be called to add events to contract object + * + * @method addEventsToContract + * @param {Contract} contract + * @param {Array} abi + */ +var addEventsToContract = function (contract) { + contract.abi.filter(function (json) { + return json.type === 'event' + }).forEach(function (json) { + let {displayName, typeName, call} = SolidityEvent(json) + + var execute = call.bind(contract, null) + execute.once = call.bind(contract, null) + execute.at = call.bind(contract) + if (!contract[displayName]) { + contract[displayName] = execute + } + contract[displayName][typeName] = call.bind(contract) + }) +} + +module.exports = Contract diff --git a/js/lib/contracts/event.js b/js/lib/contracts/event.js new file mode 100644 index 000000000..04a43493e --- /dev/null +++ b/js/lib/contracts/event.js @@ -0,0 +1,79 @@ +var utils = require('../utils/utils') +var coder = require('ethereumjs-abi') +var convert = require('../utils/convert') +var sha3 = require('../utils/sha3') + +/** + * This prototype should be used to create event filters + */ + +var types = function (abi, indexed) { + return abi.inputs.filter(function (i) { + return i.indexed === indexed + }).map(function (i) { + return i.type + }) +} +/** + * Should be used to decode indexed params and options + * + * @method decode + * @param {Object} data + * @return {Object} result object with decoded indexed && not indexed params + */ +var decode = function (abi, data) { + var argTopics = abi.anonymous ? data.Topics : data.Topics.slice(1) + var indexedParamsABI = types(abi, true) + var nonIndexedParamsABI = types(abi, false) + var indexedData = Buffer.concat(argTopics) + var indexedParams = convert.abiToBurrow(indexedParamsABI, coder.rawDecode(indexedParamsABI, indexedData)) + + // var notIndexedData = data.Data.slice(2) + var nonIndexedParams = convert.abiToBurrow(nonIndexedParamsABI, coder.rawDecode(nonIndexedParamsABI, data.Data)) + + // var result = formatters.outputLogFormatter(data); + var result = {} + result.event = utils.transformToFullName(abi) + result.address = data.Address + + result.args = abi.inputs.reduce(function (acc, current) { + acc[current.name] = current.indexed ? indexedParams.shift() : nonIndexedParams.shift() + return acc + }, {}) + + return result +} + +var SolidityEvent = function (abi) { + var name = utils.transformToFullName(abi) + var displayName = utils.extractDisplayName(name) + var typeName = utils.extractTypeName(name) + var signature = sha3(name) + + var call = function (address, callback) { + address = address || this.address + if (!callback) { throw new Error('Can not subscribe to an event without a callback') }; + + return this.burrow.pipe.eventSub(address, signature, (error, event) => { + if (error) return callback(error) + + try { + var decoded = decode(abi, event.Log) + } catch (error) { + return callback(error) + } + + const converted = Object.assign( + {}, + decoded, + {args: decoded.args} + ) + + return callback(null, converted) + }) + } + + return {displayName, typeName, call} +} + +module.exports = SolidityEvent diff --git a/js/lib/contracts/function.js b/js/lib/contracts/function.js new file mode 100644 index 000000000..c44eae642 --- /dev/null +++ b/js/lib/contracts/function.js @@ -0,0 +1,192 @@ +var utils = require('../utils/utils') +var convert = require('../utils/convert') +// var formatters = require('./formatters'); +var sha3 = require('../utils/sha3') +var coder = require('ethereumjs-abi') + +var config = require('../utils/config') +var ZERO_ADDRESS = Buffer.from('0000000000000000000000000000000000000000', 'hex') + +var functionSig = function (abi) { + var name = utils.transformToFullName(abi) + return sha3(name).slice(0, 8) +} + +var types = function (args) { + return args.map(function (arg) { + return arg.type + }) +} + +var txPayload = function (data, account, address) { + var payload = {} + + payload.Input = {Address: Buffer.from(account || ZERO_ADDRESS, 'hex'), Amount: 0} + payload.Address = address ? Buffer.from(address, 'hex') : null + payload.GasLimit = config.DEFAULT_GAS + payload.Fee = 0 + payload.Data = Buffer.from(data, 'hex') + + return payload +} + +var encodeF = function (abi, args, bytecode) { + if (abi) { + var abiInputs = types(abi.inputs) + args = convert.burrowToAbi(abiInputs, args) // If abi is passed, convert values accordingly + } + + // If bytecode provided then this is a creation call, bytecode goes first + if (bytecode) { + var data = bytecode + if (abi) data += convert.bytesTB(coder.rawEncode(abiInputs, args)) + return data + } else { + return functionSig(abi) + convert.bytesTB(coder.rawEncode(abiInputs, args)) + } +} + +var decodeF = function (abi, output) { + if (!output) { + return + } + + var outputs = abi.outputs + var outputTypes = types(outputs) + + // Decode raw bytes to arguments + var raw = convert.abiToBurrow(outputTypes, coder.rawDecode(outputTypes, Buffer.from(output, 'hex'))) + + // If an object is wanted, + var result = {raw: raw.slice()} + + var args = outputs.reduce(function (acc, current) { + var value = raw.shift() + if (current.name) { + acc[current.name] = value + } + return acc + }, {}) + + result.values = args + + return result +} + +/** + * Calls a contract function. + * + * @method call + * @param {...Object} Contract function arguments + * @param {function} + * @return {String} output bytes + */ +var SolidityFunction = function (abi) { + var isCon = (abi == null || abi.type === 'constructor') + var name + var displayName + var typeName + + if (!isCon) { + name = utils.transformToFullName(abi) + displayName = utils.extractDisplayName(name) + typeName = utils.extractTypeName(name) + } + + // It might seem weird to include copies of the functions in here and above + // My reason is the code above can be used "functionally" whereas this version + // Uses implicit attributes of this object. + // I want to keep them separate in the case that we want to move all the functional + // components together and maybe even... write tests for them (gasp!) + var encode = function () { + var args = Array.prototype.slice.call(arguments) + return encodeF(abi, args, isCon ? this.code : null) + } + + var decode = function (data) { + return decodeF(abi, data, this.objectReturn) + } + + var call = function () { + var args = Array.prototype.slice.call(arguments) + var isSim = args.shift() + var handler = args.shift() || function (result) { return result } + var address = args.shift() || this.address + + if (isCon) { address = null } + + var callback + if (utils.isFunction(args[args.length - 1])) { callback = args.pop() }; + + var self = this + + var P = new Promise(function (resolve, reject) { + if (address == null && !isCon) reject(new Error('Address not provided to call')) + if (abi != null && abi.inputs.length !== args.length) reject(new Error('Insufficient arguments passed to function: ' + (isCon ? 'constructor' : name))) + // Post process the return + var post = function (error, result) { + if (error) return reject(error) + + // Handle execution reversions + if (result.Exception && result.Exception.Code === 16) { + // Decode error message if there is one otherwise default + if (result.Result.Return.length === 0) { + error = new Error('Execution Reverted') + } else { + // Strip first 4 bytes(function signature) the decode as a string + error = new Error(coder.rawDecode(['string'], result.Result.Return.slice(4))[0]) + } + error.code = 'ERR_EXECUTION_REVERT' + return reject(error) + } + + // Unpack return arguments + var returnObj = {} + if (!isCon) { + try { + returnObj = decodeF(abi, result.Result.Return, self.objectReturn) + } catch (e) { + return reject(e) + } + } + + // Meta Data (address, caller, height, etc) + returnObj.contractAddress = result.Receipt.ContractAddress.toString('hex').toUpperCase() + returnObj.height = result.Header.Height + returnObj.index = result.Header.Index + returnObj.hash = result.Header.TxHash.toString('hex').toUpperCase() + returnObj.type = result.Header.TxType + returnObj.result = result.Result + returnObj.tx = result.Envelope + returnObj.caller = convert.recApply(result.Envelope.Signatories, convert.bytesTB) + + return resolve(returnObj) + } + + // Decide if to make a "call" or a "transaction" + // For the moment we need to use the burrowtoweb3 function to prefix bytes with 0x + // otherwise the coder will give an error with bugnumber not a number + // TODO investigate if other libs or an updated lib will fix this + // var data = encodeF(abi, utils.burrowToWeb3(args), isCon ? self.code : null) + var data = encodeF(abi, args, isCon ? self.code : null) + var payload = txPayload(data, self.burrow.account || ZERO_ADDRESS, address) + + if (isSim) { + self.burrow.pipe.call(payload, post) + } else { + self.burrow.pipe.transact(payload, post) + } + }) + + if (callback) { + P.then(handler).then((result) => { return callback(null, result) }) + .catch((err) => { return callback(err) }) + } else { + return P.then(handler) + } + } + + return {displayName, typeName, call, encode, decode} +} + +module.exports = SolidityFunction diff --git a/js/lib/events.js b/js/lib/events.js new file mode 100644 index 000000000..c100cb282 --- /dev/null +++ b/js/lib/events.js @@ -0,0 +1,37 @@ +'use strict' + +function Events (burrow) { + this.burrow = burrow +} + +module.exports = function (burrow) { + return new Events(burrow) +} + +Events.prototype.listen = function (Query, options, callback) { + // TODO Construct blockrange from options + var BlockRange = { + Start: { + Type: 3, + Index: 0 + }, + End: { + Type: 4, + Index: 0 + } + } + + return this.burrow.executionEvents.Events({ BlockRange, Query }, function (err, data) { + if (err) { + return callback(err) + } + for (var i = 0; i < data.Events.length; i++) { + callback(null, data.Events[i]) + }; + }) +} + +Events.prototype.subContractEvents = function (address, signature, options, callback) { + var filter = "EventType = 'LogEvent' AND Address = '" + address.toUpperCase() + "'" + " AND Log0 = '" + signature.toUpperCase() + "'" + return this.listen(filter, {}, callback) +} diff --git a/js/lib/namereg.js b/js/lib/namereg.js new file mode 100644 index 000000000..bacbf6f6b --- /dev/null +++ b/js/lib/namereg.js @@ -0,0 +1,21 @@ +'use strict' + +function Namereg (burrow) { + this.burrow = burrow +} + +Namereg.prototype.set = function (name, data, lease, callback) { + var payload = {} + payload.Input = { Address: Buffer.from(this.burrow.account, 'hex'), Amount: 50000 } + payload.Name = name + payload.Data = data + payload.Fee = 5000// 1 * lease * (data.length + 32); + return this.burrow.transact.NameTxSync(payload, callback) +} + +Namereg.prototype.get = function (name, callback) { + var payload = { Name: name } + return this.burrow.query.GetName(payload, callback) +} + +module.exports = Namereg diff --git a/js/lib/pipe.js b/js/lib/pipe.js new file mode 100644 index 000000000..bbc272ed8 --- /dev/null +++ b/js/lib/pipe.js @@ -0,0 +1,63 @@ +/** + * @file dev_pipe.js + * @fileOverview Base class for the dev-pipe. + * @author Andreas Olofsson + * @module pipe/dev_pipe + */ +'use strict' + +/** + * Constructor for the Pipe class. + * + * @type {Pipe} + */ +module.exports = Pipe + +/** + * DevPipe transacts using the unsafe private-key transactions. + * + * @param {*} burrow - the burrow object. + * @param {string} accounts - the private key to use when sending transactions. NOTE: This means a private key + * will be passed over the net, so it should only be used when developing, or if it's 100% certain that the + * Burrow server and this script runs on the same machine, or communication is secure. The recommended way + * will be to call a signing function on the client side, like in a browser plugin. + * + * @constructor + */ +function Pipe (burrow) { + this.burrow = burrow +} + +/** + * Used to send a transaction. + * @param {module:solidity/function~TxPayload} txPayload - The payload object. + * @param callback - The error-first callback. The 'data' param is a contract address in the case of a + * create transactions, otherwise it's the return value. + */ +Pipe.prototype.transact = function (txPayload, callback) { + this.burrow.transact.CallTxSync(txPayload, callback) +} + +/** + * Used to do a call. + * @param {module:solidity/function~TxPayload} txPayload - The payload object. + * @param callback - The error-first callback. + */ +Pipe.prototype.call = function (txPayload, callback) { + this.burrow.transact.CallTxSim(txPayload, callback) +} + +/** + * Used to subscribe to Solidity events from a given account. + * + * @param {string} accountAddress - the address of the account. + * @param {function} createCallback - error-first callback. The data object is the EventSub object. + * @param {function} eventCallback - error-first callback. The data object is a solidity event object. + */ +Pipe.prototype.eventSub = function (accountAddress, signature, callback) { + return this.burrow.events.subContractEvents(accountAddress, signature, {}, callback) +} + +Pipe.prototype.burrow = function () { + return this.burrow +} diff --git a/js/lib/service.js b/js/lib/service.js new file mode 100644 index 000000000..c831cde74 --- /dev/null +++ b/js/lib/service.js @@ -0,0 +1,103 @@ +'use strict' + +var protoLoader = require('@grpc/proto-loader') +var grpc = require('grpc') +var protobuf = require('protobufjs') +var path = require('path') + +const PROTO_PATH = path.join(__dirname, '../../protobuf/') +const GITHUB_PATH = path.join(PROTO_PATH, 'github.com/') + +const options = { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + includeDirs: [PROTO_PATH, GITHUB_PATH] +} + +function removeNested (object) { + if (!object) return + + var newObject = {} + + for (var key in object) { + if (key === 'nested') { + return removeNested(object.nested) + } + + if (typeof object[key] === 'object' && object[key].constructor === Object) { + newObject[key] = removeNested(object[key]) + } else { + newObject[key] = object[key] + } + } + return newObject +} + +function wrapGRPC (name) { + return function (params, callback) { + // Fetch requestType and ResponseType + var pName = this.packageName + var sName = this.serviceName + + var reqStream = this.pbJSON[pName][sName].methods[name].requestStream + var resStream = this.pbJSON[pName][sName].methods[name].responseStream + + if (reqStream) { + throw new Error("Can't call a requestStream method") + } + + if (resStream) { + if (!callback) throw new Error('Callback not provided') + + var call = this.client[name](params) + call.on('data', (data) => { + callback(null, data) + }) + call.on('error', (error) => { + callback(error) + }) + // Return a function that will close the stream when called + return () => { + console.log('WARNING: stream closing is not implemented') + } + } else { + // Make call through client + var P = new Promise((resolve, reject) => { + this.client[name](params, function (err, result) { + if (err) return reject(err) + resolve(result) + }) + }) + if (callback) { + return P.then((result) => { callback(null, result) }).catch((err) => { callback(err) }) + } else { + return P + } + } + } +} + +function Service (filePath, packageName, serviceName, URL) { + this.URL = URL + this.packageName = packageName + this.serviceName = serviceName + + filePath = PROTO_PATH + filePath + var protoPackage = protoLoader.loadSync(filePath, options) + + this.service = grpc.loadPackageDefinition(protoPackage) + this.pbJSON = removeNested(protobuf.loadSync(filePath).toJSON()) + + this.client = new this.service[packageName][serviceName](URL, grpc.credentials.createInsecure()) + + for (var method in this.pbJSON[packageName][serviceName].methods) { + this[method] = wrapGRPC(method).bind(this) + } +} + +module.exports = function (file, packageName, serviceName, URL) { + return new Service(file, packageName, serviceName, URL) +} diff --git a/js/lib/test.js b/js/lib/test.js new file mode 100644 index 000000000..d2c8de56e --- /dev/null +++ b/js/lib/test.js @@ -0,0 +1,76 @@ +'use strict' + +const Burrow = require('..') +const url = require('url') +const Solidity = require('solc') + +const blockchainUrl = (urlObj) => { + var envUrl = {} + if (process.env.BURROW_GRPC_PORT) envUrl.port = process.env.BURROW_GRPC_PORT + if (process.env.BURROW_HOST) envUrl.hostname = process.env.BURROW_HOST + + urlObj = Object.assign({ port: '20997', hostname: '127.0.0.1' }, envUrl, urlObj) + return url.format(urlObj) +} + +// Convenience function to compile Solidity code in tests. +const compile = (source, name) => { + const compiled = Solidity.compile(source, 1) + if (compiled.errors) { + throw new Error(compiled.errors) + } + const contract = compiled.contracts[name] + const abi = JSON.parse(contract.interface) + const bytecode = contract.bytecode + + return { abi, bytecode } +} + +// Return a contract manager in the test harness. +const Test = (options) => { + options = options || {} + const urlString = (typeof options.url === 'string' ? options.url : blockchainUrl(options.url)) + delete options.url + let account + let burrow + + return { + before: (burrowOptions, callback) => + function () { + if (typeof burrowOptions === 'function') { + callback = burrowOptions + burrowOptions = {} + } + if (!burrowOptions) burrowOptions = {} + + try { + account = JSON.parse(process.env.account) + } catch (err) { + return Promise.reject(new Error('Could not parse required account JSON: ' + process.env.account + ' Make sure you are passing a valid account json string as an env var account=\'{accountdata}\'')) + } + + // Options overrules defaults + // burrowOptions = Object.assign(burrowOptions, options) + + burrow = Burrow.createInstance(urlString, account.address, burrowOptions) + + if (callback) { + return callback(burrow) // eslint-disable-line + } + }, + + it: (callback) => + function () { + return callback(burrow) // eslint-disable-line + }, + + after: () => + function () { + } + } +} + +module.exports = { + compile, + Test +} diff --git a/js/lib/utils/config.js b/js/lib/utils/config.js new file mode 100644 index 000000000..146854965 --- /dev/null +++ b/js/lib/utils/config.js @@ -0,0 +1,10 @@ + +/** @file config.js + * @author Dennis Mckinnon + * @date 2019 + * @module utils/config + */ + +module.exports = { + DEFAULT_GAS: 1111111111 +} diff --git a/js/lib/utils/convert.js b/js/lib/utils/convert.js new file mode 100644 index 000000000..dfe04cf0b --- /dev/null +++ b/js/lib/utils/convert.js @@ -0,0 +1,84 @@ + +var recApply = function (arg, func) { + let newArg + if (Array.isArray(arg)) { + newArg = [] + for (var i = 0; i < arg.length; i++) { + newArg.push(recApply(arg[i], func)) + }; + } else { + newArg = func(arg) + } + return newArg +} + +var addressTB = function (arg) { + return arg.toUpperCase() +} + +var addressTA = function (arg) { + if (!/^0x/i.test(arg)) { + return '0x' + arg + } + return arg +} + +var bytesTB = function (arg) { + return arg.toString('hex').toUpperCase() +} + +var bytesTA = function (arg) { + if (typeof (arg) === 'string' && /^0x/i.test(arg)) { + arg = arg.slice(2) + } + return Buffer.from(arg, 'hex') + // if (!/^0x/i.test(arg)) { + // return '0x' + arg + // } + // return arg +} + +var numberTB = function (arg) { + return arg.toNumber() +} + +var abiToBurrow = function (puts, args) { + var out = [] + for (var i = 0; i < puts.length; i++) { + if (/address/i.test(puts[i])) { + out.push(recApply(args[i], addressTB)) + } else if (/bytes/i.test(puts[i])) { + out.push(recApply(args[i], bytesTB)) + } else if (/int/i.test(puts[i])) { + out.push(recApply(args[i], numberTB)) + } else { + out.push(args[i]) + } + }; + return out +} + +var burrowToAbi = function (puts, args) { + var out = [] + for (var i = 0; i < puts.length; i++) { + if (/address/i.test(puts[i])) { + out.push(recApply(args[i], addressTA)) + } else if (/bytes/i.test(puts[i])) { + out.push(recApply(args[i], bytesTA)) + } else { + out.push(args[i]) + } + }; + return out +} + +module.exports = { + abiToBurrow: abiToBurrow, + burrowToAbi: burrowToAbi, + addressTA: addressTA, + addressTB: addressTB, + bytesTA: bytesTA, + bytesTB: bytesTB, + numberTB: numberTB, + recApply: recApply +} diff --git a/js/lib/utils/sha3.js b/js/lib/utils/sha3.js new file mode 100644 index 000000000..c74ac50b4 --- /dev/null +++ b/js/lib/utils/sha3.js @@ -0,0 +1,23 @@ +/** + * @file sha3.js + * @author Marek Kotewicz + * @author Andreas Olofsson + * @date 2015 + * @module utils/sha3 + */ +var utils = require('./utils') +var sha3 = require('crypto-js/sha3') + +module.exports = function (str, isNew) { + if (str.substr(0, 2) === '0x' && !isNew) { + console.warn('requirement of using web3.fromAscii before sha3 is deprecated') + console.warn('new usage: \'web3.sha3("hello")\'') + console.warn('see https://github.com/ethereum/web3.js/pull/205') + console.warn('if you need to hash hex value, you can do \'sha3("0xfff", true)\'') + str = utils.toAscii(str) + } + + return sha3(str, { + outputLength: 256 + }).toString().toUpperCase() +} diff --git a/js/lib/utils/utils.js b/js/lib/utils/utils.js new file mode 100644 index 000000000..6d79aab36 --- /dev/null +++ b/js/lib/utils/utils.js @@ -0,0 +1,66 @@ +/** + * @file utils.js + * @author Marek Kotewicz + * @author Andreas Olofsson + * @date 2015 + * @module utils/utils + */ + +/** + * Should be used to create full function/event name from json abi + * + * @method transformToFullName + * @param {Object} json - json-abi + * @return {String} full fnction/event name + */ +var transformToFullName = function (json) { + if (json.name.indexOf('(') !== -1) { + return json.name + } + + var typeName = json.inputs.map(function (i) { + return i.type + }).join() + return json.name + '(' + typeName + ')' +} + +/** + * Should be called to get display name of contract function + * + * @method extractDisplayName + * @param {String} name of function/event + * @returns {String} display name for function/event eg. multiply(uint256) -> multiply + */ +var extractDisplayName = function (name) { + var length = name.indexOf('(') + return length !== -1 ? name.substr(0, length) : name +} + +/** + * + * @param {String} name - the name. + * @returns {String} overloaded part of function/event name + */ +var extractTypeName = function (name) { + /// TODO: make it invulnerable + var length = name.indexOf('(') + return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : '' +} + +/** + * Returns true if object is function, otherwise false + * + * @method isFunction + * @param {Object} object - object to test + * @return {Boolean} + */ +var isFunction = function (object) { + return typeof object === 'function' +} + +module.exports = { + transformToFullName: transformToFullName, + extractDisplayName: extractDisplayName, + extractTypeName: extractTypeName, + isFunction: isFunction +} diff --git a/js/test/#17/index.js b/js/test/#17/index.js new file mode 100644 index 000000000..1f4eeb34e --- /dev/null +++ b/js/test/#17/index.js @@ -0,0 +1,54 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#17', function () { + before(Test.before({handlers: {call: function (result) { return {super: result.values, man: result.raw} }}})) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#17 Testing Per-contract handler overwriting', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Test { + + function getAddress() public view returns (address) { + return this; + } + + function getNumber() public pure returns (uint) { + return 100; + } + + function getCombination() public view returns (uint _number, address _address, string _saying, bytes32 _randomBytes) { + _number = 100; + _address = this; + _saying = "hello moto"; + _randomBytes = 0xDEADBEEFFEEDFACE; + } + + } + ` + let address + const {abi, bytecode} = test.compile(source, ':Test') + return burrow.contracts.deploy(abi, bytecode, {call: function (result) { return {values: result.values, raw: result.raw} }}).then((contract) => { + address = contract.address + return contract.getCombination() + }).then((returnObject) => { + const expected = { + values: { + _number: 100, + _address: address, + _saying: 'hello moto', + _randomBytes: '000000000000000000000000000000000000000000000000DEADBEEFFEEDFACE' + }, + raw: [100, address, 'hello moto', '000000000000000000000000000000000000000000000000DEADBEEFFEEDFACE'] + } + assert.deepEqual(returnObject, expected) + }) + })) +}) diff --git a/js/test/#175/index.js b/js/test/#175/index.js new file mode 100644 index 000000000..3265a9f22 --- /dev/null +++ b/js/test/#175/index.js @@ -0,0 +1,44 @@ +'use strict' + +const test = require('../../lib/test') +const assert = require('assert') + +const Test = test.Test() + +describe('#175', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#175', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Contract { + string thename; + constructor(string newName) public { + thename = newName; + } + function getName() public view returns (string name) { + return thename; + } + } + ` + var contract + let A2 + + const {abi, bytecode} = test.compile(source, ':Contract') + return burrow.contracts.deploy(abi, bytecode, 'contract1').then((C) => { + contract = C + return contract._constructor('contract2') + }).then((address) => { + A2 = address + return Promise.all( + [contract.getName(), // Note using the default address from the deploy + contract.getName.at(A2)]) // Using the .at() to specify the second deployed contract + }).then(([result1, result2]) => { + assert.equal(result1[0], 'contract1') + assert.equal(result2[0], 'contract2') + }) + })) +}) diff --git a/js/test/#21/index.js b/js/test/#21/index.js new file mode 100644 index 000000000..732a530ce --- /dev/null +++ b/js/test/#21/index.js @@ -0,0 +1,60 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('issue #21', function () { + this.timeout(10 * 1000) + let contract + + before(Test.before(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract c { + function getBytes() public pure returns (byte[10]){ + byte[10] memory b; + string memory s = "hello"; + bytes memory sb = bytes(s); + + uint k = 0; + for (uint i = 0; i < sb.length; i++) b[k++] = sb[i]; + b[9] = 0xff; + return b; + } + + function deeper() public pure returns (byte[12][100] s, uint count) { + count = 42; + return (s, count); + } + } + ` + + const {abi, bytecode} = test.compile(source, ':c') + return burrow.contracts.deploy(abi, bytecode).then((c) => { + contract = c + }) + })) + + after(Test.after()) + + it('gets the static byte array decoded properly', Test.it(function () { + return contract.getBytes() + .then((bytes) => { + assert.deepEqual( + bytes, + [['68', '65', '6C', '6C', '6F', '00', '00', '00', '00', 'FF']] + ) + }) + })) + + it('returns multiple values correctly from a function', + Test.it(function () { + return contract.deeper() + .then((values) => { + assert.equal(Number(values[1]), 42) + }) + }) + ) +}) diff --git a/js/test/#38/index.js b/js/test/#38/index.js new file mode 100644 index 000000000..d7ae1848c --- /dev/null +++ b/js/test/#38/index.js @@ -0,0 +1,41 @@ +'use strict' + +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#38', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#38', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Contract { + event Event(); + + function emit() public { + emit Event(); + } + } + ` + const {abi, bytecode} = test.compile(source, ':Contract') + return burrow.contracts.deploy(abi, bytecode).then((contract) => { + const secondContract = burrow.contracts.new(abi, null, contract.address) + + return new Promise((resolve, reject) => { + secondContract.Event.once(function (error, event) { + if (error) { + reject(error) + } else { + resolve(event) + } + }) + + secondContract.emit() + }) + }) + })) +}) diff --git a/js/test/#42/index.js b/js/test/#42/index.js new file mode 100644 index 000000000..a5f1a0759 --- /dev/null +++ b/js/test/#42/index.js @@ -0,0 +1,54 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#42', function () { + before(Test.before({handlers: {call: function (result) { return {values: result.values, raw: result.raw} }}})) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#42', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Test { + + function getAddress() public view returns (address) { + return this; + } + + function getNumber() public pure returns (uint) { + return 100; + } + + function getCombination() public view returns (uint _number, address _address, string _saying, bytes32 _randomBytes) { + _number = 100; + _address = this; + _saying = "hello moto"; + _randomBytes = 0xDEADBEEFFEEDFACE; + } + + } + ` + let address + const {abi, bytecode} = test.compile(source, ':Test') + return burrow.contracts.deploy(abi, bytecode).then((contract) => { + address = contract.address + return contract.getCombination() + }).then((returnObject) => { + const expected = { + values: { + _number: 100, + _address: address, + _saying: 'hello moto', + _randomBytes: '000000000000000000000000000000000000000000000000DEADBEEFFEEDFACE' + }, + raw: [100, address, 'hello moto', '000000000000000000000000000000000000000000000000DEADBEEFFEEDFACE'] + } + assert.deepEqual(returnObject, expected) + }) + })) +}) diff --git a/js/test/#44/index.js b/js/test/#44/index.js new file mode 100644 index 000000000..98a8cb2e0 --- /dev/null +++ b/js/test/#44/index.js @@ -0,0 +1,37 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#44', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(60 * 1000) + + it('#44', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract SimpleStorage { + address storedData; + + function set(address x) public { + storedData = x; + } + + function get() public constant returns (address retVal) { + return storedData; + } + } + ` + const {abi, bytecode} = test.compile(source, ':SimpleStorage') + return burrow.contracts.deploy(abi, bytecode).then((contract) => + contract.set('88977A37D05A4FE86D09E88C88A49C2FCF7D6D8F') + .then(() => contract.get()) + ).then((value) => { + assert.equal(value, '88977A37D05A4FE86D09E88C88A49C2FCF7D6D8F') + }) + })) +}) diff --git a/js/test/#45/index.js b/js/test/#45/index.js new file mode 100644 index 000000000..0690b041c --- /dev/null +++ b/js/test/#45/index.js @@ -0,0 +1,67 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#45', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('nottherealbatman', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Test { + string _name; + + function add(int a, int b) public pure returns (int sum) { + sum = a + b; + } + + function setName(string newname) public { + _name = newname; + } + + function getName() public view returns (string) { + return _name; + } + } + ` + const {abi, bytecode} = test.compile(source, ':Test') + return burrow.contracts.deploy(abi, bytecode).then((contract) => + contract.setName('Batman') + .then(() => contract.getName()) + ).then((value) => { + assert.equal(value, 'Batman') + }) + })) + + it('rguikers', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Test { + + function getAddress() public view returns (address) { + return this; + } + + function getNumber() public pure returns (uint) { + return 100; + } + + } + ` + + const {abi, bytecode} = test.compile(source, ':Test') + return burrow.contracts.deploy(abi, bytecode).then((contract) => + Promise.all([contract.getAddress(), contract.getNumber()]) + .then(([address, number]) => { + assert.equal(address[0].length, 40) + assert.equal(number[0], 100) + }) + ) + })) +}) diff --git a/js/test/#46/index.js b/js/test/#46/index.js new file mode 100644 index 000000000..1ccfa9ce5 --- /dev/null +++ b/js/test/#46/index.js @@ -0,0 +1,43 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#46', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#46', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Test{ + + string _name; + + function setName(string newname) public { + _name = newname; + } + + function getNameConstant() public view returns (string) { + return _name; + } + + function getName() public view returns (string) { + return _name; + } + } + ` + + const {abi, bytecode} = test.compile(source, ':Test') + return burrow.contracts.deploy(abi, bytecode) + .then((contract) => contract.setName('Batman') + .then(() => Promise.all([contract.getNameConstant(), contract.getName()]))) + .then(([constant, nonConstant]) => { + assert.equal(constant[0], nonConstant[0]) + }) + })) +}) diff --git a/js/test/#47/index.js b/js/test/#47/index.js new file mode 100644 index 000000000..2247de3ce --- /dev/null +++ b/js/test/#47/index.js @@ -0,0 +1,38 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#47', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#47', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Test{ + string _withSpace = " Pieter"; + string _withoutSpace = "Pieter"; + + function getWithSpaceConstant() public constant returns (string) { + return _withSpace; + } + + function getWithoutSpaceConstant () public constant returns (string) { + return _withoutSpace; + } + } + ` + const {abi, bytecode} = test.compile(source, ':Test') + return burrow.contracts.deploy(abi, bytecode) + .then((contract) => Promise.all([contract.getWithSpaceConstant(), contract.getWithoutSpaceConstant()])) + .then(([withSpace, withoutSpace]) => { + assert.equal(withSpace, ' Pieter') + assert.equal(withoutSpace, 'Pieter') + }) + })) +}) diff --git a/js/test/#48/index.js b/js/test/#48/index.js new file mode 100644 index 000000000..abd8741b2 --- /dev/null +++ b/js/test/#48/index.js @@ -0,0 +1,42 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#48', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#48', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Test { + + function getAddress() public view returns (address) { + return this; + } + + function getNumber() public pure returns (uint) { + return 100; + } + + function getCombination() public view returns (uint _number, address _address) { + _number = 100; + _address = this; + } + + } + ` + const {abi, bytecode} = test.compile(source, ':Test') + return burrow.contracts.deploy(abi, bytecode) + .then((contract) => contract.getCombination()) + .then(([number, address]) => { + assert.equal(number, 100) + assert.equal(address.length, 40) + }) + })) +}) diff --git a/js/test/#50/index.js b/js/test/#50/index.js new file mode 100644 index 000000000..7a137f61b --- /dev/null +++ b/js/test/#50/index.js @@ -0,0 +1,37 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#50', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#50', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract SimpleStorage { + uint storedData; + + function set(uint x) public { + storedData = x; + } + + function get() public view returns (uint retVal) { + return storedData; + } + } + ` + const {abi, bytecode} = test.compile(source, ':SimpleStorage') + return burrow.contracts.deploy(abi, bytecode) + .then((contract) => contract.set(42) + .then(() => contract.get.call()) + ).then((value) => { + assert.equal(value, 42) + }) + })) +}) diff --git a/js/test/#61/index.js b/js/test/#61/index.js new file mode 100644 index 000000000..80a46315f --- /dev/null +++ b/js/test/#61/index.js @@ -0,0 +1,36 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#61', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#61', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract SimpleStorage { + address storedData; + + constructor(address x) public { + storedData = x; + } + + function get() public constant returns (address retVal) { + return storedData; + } + } + ` + const {abi, bytecode} = test.compile(source, ':SimpleStorage') + return burrow.contracts.deploy(abi, bytecode, '88977A37D05A4FE86D09E88C88A49C2FCF7D6D8F') + .then((contract) => contract.get()) + .then((value) => { + assert.equal(value, '88977A37D05A4FE86D09E88C88A49C2FCF7D6D8F') + }) + })) +}) diff --git a/js/test/#81/index.js b/js/test/#81/index.js new file mode 100644 index 000000000..26b16e626 --- /dev/null +++ b/js/test/#81/index.js @@ -0,0 +1,85 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('#81', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('listens to an event from a contract', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Contract { + event Pay( + address originator, + address beneficiary, + int amount, + string servicename, + string alias, + string providername, + bytes32 randomBytes + ); + + function emit() public { + emit Pay( + 0x88977a37D05a4FE86d09E88c88a49C2fCF7d6d8F, + 0x721584fa4f1B9f51950018073A8E5ECF47f2d3b8, + 1, + "Energy", + "wasmachine", + "Eneco", + 0xDEADFEEDBEEFFACE + ); + } + } + ` + + const {abi, bytecode} = test.compile(source, ':Contract') + return burrow.contracts.deploy(abi, bytecode) + .then((contract) => { + return new Promise((resolve, reject) => { + contract.Pay((error, {args}) => { + if (error) { + reject(error) + } else { + try { + const actual = Object.assign( + {}, + args, + {amount: Number(args.amount)} + ) + + assert.deepEqual( + actual, + { + originator: '88977A37D05A4FE86D09E88C88A49C2FCF7D6D8F', + beneficiary: '721584FA4F1B9F51950018073A8E5ECF47F2D3B8', + amount: 1, + + servicename: 'Energy', + + alias: 'wasmachine', + + providername: 'Eneco', + + randomBytes: '000000000000000000000000000000000000000000000000DEADFEEDBEEFFACE' + } + ) + } catch (exception) { + reject(exception) + } + + resolve() + } + }) + + contract.emit() + }) + }) + })) +}) diff --git a/js/test/Abis/index.js b/js/test/Abis/index.js new file mode 100644 index 000000000..e76dca5ef --- /dev/null +++ b/js/test/Abis/index.js @@ -0,0 +1,31 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('Abi', function () { + this.timeout(10 * 1000) + let burrow + + before(Test.before(function (_burrow) { + burrow = _burrow + })) + + after(Test.after()) + + it('Call contract via burrow side Abi', Test.it(function () { + return burrow.namereg.get('random') + .then((data) => { + let address = data.Data + return burrow.contracts.address(address) + }) + .then((contract) => { + return contract.getRandomNumber() + }) + .then((data) => { + assert.equal(data[0], 55) + }) + })) +}) diff --git a/js/test/Functional/index.js b/js/test/Functional/index.js new file mode 100644 index 000000000..12df9f52e --- /dev/null +++ b/js/test/Functional/index.js @@ -0,0 +1,69 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('Functional Contract Usage', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('#Constructor usage', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Test { + address storedData; + constructor(address x) public { + storedData = x; + } + + function getAddress() public view returns (address) { + return this; + } + + function getNumber() public pure returns (uint) { + return 100; + } + + function getCombination() public view returns (uint _number, address _address, string _saying, bytes32 _randomBytes, address _stored) { + _number = 100; + _address = this; + _saying = "hello moto"; + _randomBytes = 0xDEADBEEFFEEDFACE; + _stored = storedData; + } + + } + ` + const {abi, bytecode} = test.compile(source, ':Test') + const contract = burrow.contracts.new(abi, bytecode) + + let A1 + let A2 + + assert.equal(contract.address, null) + + // Use the _contructor method to creat two contracts + return Promise.all( + [contract._constructor('88977A37D05A4FE86D09E88C88A49C2FCF7D6D8F'), + contract._constructor('ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEF0123')]) + .then(([address1, address2]) => { + assert.equal(contract.address, null) + A1 = address1 + A2 = address2 + + return Promise.all( + [contract.getCombination.at(A1), + contract.getCombination.at(A2)]) + }) + .then(([object1, object2]) => { + const expected1 = [100, A1, 'hello moto', '000000000000000000000000000000000000000000000000DEADBEEFFEEDFACE', '88977A37D05A4FE86D09E88C88A49C2FCF7D6D8F'] + const expected2 = [100, A2, 'hello moto', '000000000000000000000000000000000000000000000000DEADBEEFFEEDFACE', 'ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEF0123'] + assert.deepEqual(object1, expected1) + assert.deepEqual(object2, expected2) + }) + })) +}) diff --git a/js/test/HTTP/index.js b/js/test/HTTP/index.js new file mode 100644 index 000000000..719c71be5 --- /dev/null +++ b/js/test/HTTP/index.js @@ -0,0 +1,37 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('HTTP', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('sets and gets a value from a contract', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract SimpleStorage { + uint storedData; + + function set(uint x) public { + storedData = x; + } + + function get() constant public returns (uint retVal) { + return storedData; + } + } + ` + const {abi, bytecode} = test.compile(source, ':SimpleStorage') + return burrow.contracts.deploy(abi, bytecode) + .then((contract) => contract.set(42) + .then(() => contract.get()) + ).then((value) => { + assert.equal(value, 42) + }) + })) +}) diff --git a/js/test/Inf-Loop/index.js b/js/test/Inf-Loop/index.js new file mode 100644 index 000000000..450c60ae9 --- /dev/null +++ b/js/test/Inf-Loop/index.js @@ -0,0 +1,51 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe.skip('Really Long Loop', function () { + this.timeout(10 * 1000) + let contract + + before(Test.before(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract main { + function test() public returns (string) { + c sub = new c(); + return sub.getString(); + } + } + contract c { + string s = "secret"; + uint n = 0; + function getString() public returns (string){ + for (uint i = 0; i < 10000000000000; i++) { + n += 1; + } + return s; + } + } + ` + + const {abi, bytecode} = test.compile(source, ':main') + return burrow.contracts.deploy(abi, bytecode).then((c) => { + contract = c + }) + })) + + after(Test.after()) + + it('It catches a revert when gas runs out', + Test.it(function () { + return contract.test() + .then((str) => { + throw new Error('Did not catch revert error') + }).catch((err) => { + assert.equal(err.code, 'ERR_EXECUTION_REVERT') + }) + }) + ) +}) diff --git a/js/test/Namereg/index.js b/js/test/Namereg/index.js new file mode 100644 index 000000000..67f4b6337 --- /dev/null +++ b/js/test/Namereg/index.js @@ -0,0 +1,27 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('Namereg', function () { + this.timeout(10 * 1000) + let burrow + + before(Test.before(function (_burrow) { + burrow = _burrow + })) + + after(Test.after()) + + it('Sets and gets a name correctly', Test.it(function () { + return burrow.namereg.set('DOUG', 'ABCDEF0123456789', 20) + .then(() => { + return burrow.namereg.get('DOUG') + .then((data) => { + assert.equal(data.Data, 'ABCDEF0123456789') + }) + }) + })) +}) diff --git a/js/test/README.md b/js/test/README.md new file mode 100644 index 000000000..c5a73b703 --- /dev/null +++ b/js/test/README.md @@ -0,0 +1,127 @@ +# Test Framework + +Specialized functions are available in `lib/test.js` to make testing interactions with the Burrow server easier. The general idea is that the JavaScript library interacting with the Burrow server is very complex so we reduce the complexity by decoupling their interactions with each other. The decoupling is achieved by replacing either the client or the server (at different times) with a _test vector_ that simulates its behavior. The test vector is an automatic recording of the conversation between the two. + +We replace this: + +``` +client <-> server +(complex) (complex) +``` + +with this: + +``` +client <-> test vector <-> server +(complex) (simple) (complex) +``` + +so that the client can be tested in isolation: + +``` +client <-> test vector +(complex) (simple) +``` + +and the server can be tested in isolation: + +``` +test vector <-> server +(simple) (complex) +``` + +For more background on this technique see [Integrated Tests Are A Scam](https://vimeo.com/80533536). + +## Usage in Tests + +A standard [Mocha](https://mochajs.org/) test file structure looks like this: + +```JavaScript +'use strict' + +const assert = require('assert') + +before(function () { + // Set up artifacts for testing. +}) + +after(function () { + // Clean up test artifacts. +}) + +it(`description of the test`, function () { + // Compute results. + assert.equal(results, expectations) +}) +``` + +The `test` library will do all of the heavy lifting of creating a blockchain and making it possible to record and playback the test vector if you structure your code like this: + +```JavaScript +'use strict' + +const assert = require('assert') +const Promise = require('bluebird') +const test = require('../../lib/test') + +const vector = test.Vector() + +describe('HTTP', function () { + before(vector.before(__dirname, {protocol: 'http:'})) + after(vector.after()) + + this.timeout(10 * 1000) + + it('sets and gets a value from a contract', vector.it(function (manager) { + const source = ` + contract SimpleStorage { + uint storedData; + + function set(uint x) { + storedData = x; + } + + function get() constant returns (uint retVal) { + return storedData; + } + } + ` + + return test.compile(manager, source, 'SimpleStorage').then((contract) => + Promise.fromCallback((callback) => + contract.set(42, callback) + ).then(() => + Promise.fromCallback((callback) => + contract.get(callback) + ) + ) + ).then((value) => { + assert.equal(value, 42) + }) + })) +}) +``` + +Notice that the callback passed to `vector.it` is called with the `manager` object. + +## Commands + +Tests written like this can then be used by the following commands: + +To test the library against pre-recorded vectors: + +``` +npm test +``` + +To test the library against Burrow while automatically recording vectors: + +``` +TEST=record npm test +``` + +To test Burrow against pre-recorded vectors without exercising the client: + +``` +TEST=server npm test +``` diff --git a/js/test/REVERT/index.js b/js/test/REVERT/index.js new file mode 100644 index 000000000..7b4c710fd --- /dev/null +++ b/js/test/REVERT/index.js @@ -0,0 +1,53 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('REVERT constant', function () { + this.timeout(10 * 1000) + let contract + + before(Test.before(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract c { + string s = "secret"; + function getString(uint key) public constant returns (string){ + if (key != 42){ + revert("Did not pass correct key"); + } else { + return s; + } + } + } + ` + + const {abi, bytecode} = test.compile(source, ':c') + return burrow.contracts.deploy(abi, bytecode).then((c) => { + contract = c + }) + })) + + after(Test.after()) + + it('gets the string when revert not called', Test.it(function () { + return contract.getString(42) + .then((str) => { + assert.equal(str, 'secret') + }) + })) + + it('It catches a revert with the revert string', + Test.it(function () { + return contract.getString(1) + .then((str) => { + throw new Error('Did not catch revert error') + }).catch((err) => { + assert.equal(err.code, 'ERR_EXECUTION_REVERT') + assert.equal(err.message, 'Did not pass correct key') + }) + }) + ) +}) diff --git a/js/test/REVERT2/index.js b/js/test/REVERT2/index.js new file mode 100644 index 000000000..d9578fafb --- /dev/null +++ b/js/test/REVERT2/index.js @@ -0,0 +1,55 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('REVERT non-constant', function () { + this.timeout(10 * 1000) + let contract + + before(Test.before(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract c { + string s = "secret"; + uint n = 0; + function getString(uint key) public returns (string){ + if (key != 42){ + revert("Did not pass correct key"); + } else { + n = n + 1; + return s; + } + } + } + ` + + const {abi, bytecode} = test.compile(source, ':c') + return burrow.contracts.deploy(abi, bytecode).then((c) => { + contract = c + }) + })) + + after(Test.after()) + + it('gets the string when revert not called', Test.it(function () { + return contract.getString(42) + .then((str) => { + assert.equal(str, 'secret') + }) + })) + + it('It catches a revert with the revert string', + Test.it(function () { + return contract.getString(1) + .then((str) => { + throw new Error('Did not catch revert error') + }).catch((err) => { + assert.equal(err.code, 'ERR_EXECUTION_REVERT') + assert.equal(err.message, 'Did not pass correct key') + }) + }) + ) +}) diff --git a/js/test/REVERT3/index.js b/js/test/REVERT3/index.js new file mode 100644 index 000000000..764bc2311 --- /dev/null +++ b/js/test/REVERT3/index.js @@ -0,0 +1,47 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('REVERT non-constant', function () { + this.timeout(100 * 1000) + let contract + + before(Test.before(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract c { + string s = "secret"; + uint n = 0; + function getString(uint key) public returns (string){ + if (key != 42){ + revert(); + } else { + n = n + 1; + return s; + } + } + } + ` + + const {abi, bytecode} = test.compile(source, ':c') + return burrow.contracts.deploy(abi, bytecode).then((c) => { + contract = c + }) + })) + + after(Test.after()) + + it('It catches a revert with the revert string', + Test.it(function () { + return contract.getString(1) + .then((str) => { + throw new Error('Did not catch revert error') + }).catch((err) => { + assert.equal(err.code, 'ERR_EXECUTION_REVERT') + }) + }) + ) +}) diff --git a/js/test/event/index.js b/js/test/event/index.js new file mode 100644 index 000000000..7723dd663 --- /dev/null +++ b/js/test/event/index.js @@ -0,0 +1,57 @@ +'use strict' + +const assert = require('assert') +const test = require('../../lib/test') + +const Test = test.Test() + +describe('event', function () { + before(Test.before()) + after(Test.after()) + + this.timeout(10 * 1000) + + it('listens to an event from a contract', Test.it(function (burrow) { + const source = ` + pragma solidity ^0.4.21; + contract Contract { + event Event( + address from + ); + + function emit() public { + emit Event(msg.sender); + } + } + ` + const {abi, bytecode} = test.compile(source, ':Contract') + return burrow.contracts.deploy(abi, bytecode) + .then((contract) => { + let count = 0 + + return new Promise((resolve, reject) => { + contract.Event( + (error, event) => { + if (error) { + reject(error) + } else { + try { + assert.equal(event.args.from.length, 40) + } catch (exception) { + reject(exception) + } + + count++ + + if (count === 2) { + resolve() + } + } + }) + + contract.emit() + contract.emit() + }) + }) + })) +}) diff --git a/js/test/get_set_smoke_test/GetSet.sol b/js/test/get_set_smoke_test/GetSet.sol new file mode 100644 index 000000000..a6d2e12d6 --- /dev/null +++ b/js/test/get_set_smoke_test/GetSet.sol @@ -0,0 +1,54 @@ +pragma solidity ^0.4.21; + +contract GetSet { + + uint uintfield; + bytes32 bytesfield; + string stringfield; + bool boolfield; + + function testExist() public pure returns (uint output){ + return 1; + } + + function setUint(uint input) public { + uintfield = input; + return; + } + + function getUint() public constant returns (uint output){ + output = uintfield; + return; + } + + function setBytes(bytes32 input) public { + bytesfield = input; + return; + } + + function getBytes() public constant returns (bytes32 output){ + output = bytesfield; + return; + } + + function setString(string input) public { + stringfield = input; + return; + } + + function getString() public constant returns (string output){ + output = stringfield; + return; + } + + function setBool(bool input) public { + boolfield = input; + return; + } + + function getBool() public constant returns (bool output){ + output = boolfield; + return; + } + +} \ No newline at end of file diff --git a/js/test/get_set_smoke_test/index.js b/js/test/get_set_smoke_test/index.js new file mode 100644 index 000000000..43f7da329 --- /dev/null +++ b/js/test/get_set_smoke_test/index.js @@ -0,0 +1,92 @@ +const path = require('path') +const assert = require('assert') +const fs = require('fs-extra') + +const test = require('../../lib/test') + +const Test = test.Test() + +const sourcePath = './GetSet.sol' + +const source = fs.readFileSync(path.join(__dirname, sourcePath)).toString() +const {abi, bytecode} = test.compile(source, ':GetSet') + +const testUint = 42 +const testBytes = 'DEADBEEF00000000000000000000000000000000000000000000000000000000' +const testString = 'Hello World!' +const testBool = true + +let TestContract + +// Create a factory for the contract with the JSON interface 'myAbi'. + +describe('Setting and Getting Values:', function () { + this.timeout(10 * 1000) + + before(Test.before((burrow) => { + return burrow.contracts.deploy(abi, bytecode).then((contract) => { + TestContract = contract + }) + })) + after(Test.after()) + + it('Uint', Test.it(function (burrow) { + return new Promise((resolve, reject) => { + TestContract.setUint(testUint, function (err) { + if (err) { reject(err) } + + TestContract.getUint(function (err, output) { + if (err) { reject(err) } + + assert.equal(output[0], testUint) + resolve() + }) + }) + }) + })) + + it('Bool', Test.it(function (burrow) { + return new Promise((resolve, reject) => { + TestContract.setBool(testBool, function (err) { + if (err) { reject(err) } + + TestContract.getBool(function (err, output) { + if (err) { reject(err) } + + assert.equal(output[0], testBool) + resolve() + }) + }) + }) + })) + + it('Bytes', Test.it(function (burrow) { + return new Promise((resolve, reject) => { + TestContract.setBytes(testBytes, function (err) { + if (err) { reject(err) } + + TestContract.getBytes(function (err, output) { + if (err) { reject(err) } + + assert.equal(output[0], testBytes) + resolve() + }) + }) + }) + })) + + it('String', Test.it(function (burrow) { + return new Promise((resolve, reject) => { + TestContract.setString(testString, function (err) { + if (err) { reject(err) } + + TestContract.getString(function (err, output) { + if (err) { reject(err) } + + assert.equal(output[0], testString) + resolve() + }) + }) + }) + })) +}) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..820ba1252 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3761 @@ +{ + "name": "@monax/burrow", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@grpc/proto-loader": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.4.0.tgz", + "integrity": "sha512-Jm6o+75uWT7E6+lt8edg4J1F/9+BedOjaMgwE14pxS/AO43/0ZqK+rCLVVrXLoExwSAZvgvOD2B0ivy3Spsspw==", + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", + "integrity": "sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==" + }, + "@types/node": { + "version": "10.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.2.tgz", + "integrity": "sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==" + }, + "acorn": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-escapes": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz", + "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==", + "dev": true, + "requires": { + "type-fest": "^0.5.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bindings": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz", + "integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew==" + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-sha3": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.4.tgz", + "integrity": "sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY=", + "requires": { + "js-sha3": "^0.6.1", + "safe-buffer": "^5.1.1" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "~3" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "create-hash": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-js": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.4.tgz", + "integrity": "sha1-IWTxbeLykVELZS10a84302SYMK0=" + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "debug-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "^2.0.5", + "object-keys": "^1.0.8" + } + }, + "deglob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-3.1.0.tgz", + "integrity": "sha512-al10l5QAYaM/PeuXkAr1Y9AQz0LCtWsnJG23pIgh44hDxHFOj36l6qvhfjnIWBYwZOqM1fXUFV9tkjL7JPdGvw==", + "dev": true, + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^5.0.0", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + } + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "^1.1.1", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.1.0.tgz", + "integrity": "sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^6.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + } + } + }, + "eslint-config-standard": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-13.0.1.tgz", + "integrity": "sha512-zLKp4QOgq6JFgRm1dDCVv1Iu0P5uZ4v5Wa4DTOkg2RFMxdCX/9Qf7lz9ezRj2dBRa955cWQF/O/LWEiYWAHbTw==", + "dev": true + }, + "eslint-config-standard-jsx": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-7.0.0.tgz", + "integrity": "sha512-OiKOF3MFVmWOCVfsi8GHlVorOEiBsPzAnUhM3c6HML94O2krbdQ/eMABySHgHHOIBYRls9sR9I3lo6O0vXhVEg==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-es": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz", + "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==", + "dev": true, + "requires": { + "eslint-utils": "^1.3.0", + "regexpp": "^2.0.1" + } + }, + "eslint-plugin-import": { + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.11.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + } + } + }, + "eslint-plugin-node": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-9.1.0.tgz", + "integrity": "sha512-ZwQYGm6EoV2cfLpE1wxJWsfnKUIXfM/KM09/TlorkukgCAwmkgajEJnPCmyzoFPQQkmvo5DrW/nyKutNIw36Mw==", + "dev": true, + "requires": { + "eslint-plugin-es": "^1.4.0", + "eslint-utils": "^1.3.1", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true + }, + "eslint-plugin-react": { + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz", + "integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.1.0", + "object.entries": "^1.1.0", + "object.fromentries": "^2.0.0", + "object.values": "^1.1.0", + "prop-types": "^15.7.2", + "resolve": "^1.10.1" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } + } + }, + "eslint-plugin-standard": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz", + "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", + "dev": true + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz", + "integrity": "sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.0.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.0.0.tgz", + "integrity": "sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "ethereumjs-abi": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz", + "integrity": "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=", + "requires": { + "bn.js": "^4.10.0", + "ethereumjs-util": "^4.3.0" + } + }, + "ethereumjs-util": { + "version": "4.5.0", + "resolved": "http://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", + "requires": { + "bn.js": "^4.8.0", + "create-hash": "^1.1.2", + "keccakjs": "^0.2.0", + "rlp": "^2.0.0", + "secp256k1": "^3.0.1" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz", + "integrity": "sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", + "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "grpc": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.18.0.tgz", + "integrity": "sha512-M0K67Zhv2ZzCjrTbQvjWgYFPB929L+qAVnbNgXepbfO5kJxUYc30dP8m8vb+o8QdahLHAeYfIqRoIzZRcCB98Q==", + "requires": { + "lodash.camelcase": "^4.3.0", + "lodash.clone": "^4.5.0", + "nan": "^2.0.0", + "node-pre-gyp": "^0.12.0", + "protobufjs": "^5.0.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.1", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true + }, + "npm-packlist": { + "version": "1.1.12", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "requires": { + "ascli": "~1", + "bytebuffer": "~5", + "glob": "^7.0.5", + "yargs": "^3.10.0" + } + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inquirer": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.1.tgz", + "integrity": "sha512-uxNHBeQhRXIoHWTSNYUFhQVrHYFThIt6IVo2fFmSe8aBwdR3/w6b58hJpiL/fMukFkvGzjg+hSxFtwvVmKZmXw==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz", + "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^5.2.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-sha3": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.6.1.tgz", + "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA=" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsx-ast-utils": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz", + "integrity": "sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "object.assign": "^4.1.0" + } + }, + "keccakjs": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.3.tgz", + "integrity": "sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg==", + "requires": { + "browserify-sha3": "^0.0.4", + "sha3": "^1.2.2" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", + "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + } + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", + "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + } + }, + "yargs-parser": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nan": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + } + } + }, + "object.fromentries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", + "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.11.0", + "function-bind": "^1.1.1", + "has": "^1.0.1" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", + "dev": true + }, + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "pkg-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", + "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", + "dev": true, + "requires": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "protobufjs": { + "version": "6.8.8", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", + "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + }, + "dependencies": { + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "react-is": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz", + "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.1.tgz", + "integrity": "sha512-nqB/qy+YjXdp/zj1CjCiDwfLMBPv/XFDol0ir/7O/+Ix90++rvi+QoK1CDJcn8JoqCu2WrPPeRucu4qyIDzALg==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, + "rxjs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", + "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "secp256k1": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.2.tgz", + "integrity": "sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ==", + "requires": { + "bindings": "^1.2.1", + "bip66": "^1.1.3", + "bn.js": "^4.11.3", + "create-hash": "^1.1.2", + "drbg.js": "^1.0.1", + "elliptic": "^6.2.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "sha3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", + "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", + "requires": { + "nan": "2.10.0" + }, + "dependencies": { + "nan": { + "version": "2.10.0", + "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "solc": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.24.tgz", + "integrity": "sha512-2xd7Cf1HeVwrIb6Bu1cwY2/TaLRodrppCq3l7rhLimFQgmxptXhTC3+/wesVLpB09F1A2kZgvbMOgH7wvhFnBQ==", + "dev": true, + "requires": { + "fs-extra": "^0.30.0", + "memorystream": "^0.3.1", + "require-from-string": "^1.1.0", + "semver": "^5.3.0", + "yargs": "^4.7.1" + }, + "dependencies": { + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "dev": true + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "dev": true, + "requires": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + } + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "standard": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/standard/-/standard-13.1.0.tgz", + "integrity": "sha512-h3NaMzsa88+/xtjXCMvdn6EWWdlodsI/HvtsQF+EGwrF9kVNwNha9TkFABU6bSBoNfC79YDyIAq9ekxOMBFkuw==", + "dev": true, + "requires": { + "eslint": "~6.1.0", + "eslint-config-standard": "13.0.1", + "eslint-config-standard-jsx": "7.0.0", + "eslint-plugin-import": "~2.18.0", + "eslint-plugin-node": "~9.1.0", + "eslint-plugin-promise": "~4.2.1", + "eslint-plugin-react": "~7.14.2", + "eslint-plugin-standard": "~4.0.0", + "standard-engine": "~11.0.1" + } + }, + "standard-engine": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-11.0.1.tgz", + "integrity": "sha512-WZQ5PpEDfRzPFk+H9xvKVQPQIxKnAQB2cb2Au4NyTCtdw5R0pyMBUZLbPXyFjnlhe8Ae+zfNrWU4m6H5b7cEAg==", + "dev": true, + "requires": { + "deglob": "^3.0.0", + "get-stdin": "^7.0.0", + "minimist": "^1.1.0", + "pkg-conf": "^3.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", + "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", + "dev": true + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..b4fc69862 --- /dev/null +++ b/package.json @@ -0,0 +1,72 @@ +{ + "name": "@monax/burrow", + "description": "Javascript library that calls a Hyperledger Burrow server over rpc.", + "main": "./index.js", + "author": { + "name": "Dennis Mckinnon" + }, + "files": [ + "js", + "protobuf" + ], + "bugs": { + "url": "https://github.com/hyperledger/burrow/issues" + }, + "dependencies": { + "@grpc/proto-loader": "^0.4.0", + "crypto-js": "3.1.4", + "ethereumjs-abi": "^0.6.5", + "grpc": "^1.18.0", + "protobufjs": "^6.8.6" + }, + "devDependencies": { + "fs-extra": "^7.0.1", + "mocha": "6.2.0", + "solc": "0.4.24", + "standard": "13.1.0" + }, + "engines": { + "node": ">=6" + }, + "homepage": "https://github.com/hyperledger/burrow/", + "keywords": [ + "Burrow", + "Hyperledger", + "Monax" + ], + "license": "Apache-2.0", + "maintainers": [ + { + "name": "Silas Davis", + "email": "silas@monax.io" + }, + { + "name": "Sean Young", + "email": "sean.young@monax.io" + }, + { + "name": "Greg Hill", + "email": "greg.hill@monax.io" + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/hyperledger/burrow.git" + }, + "scripts": { + "precommit": "standard --fix js/**/*.js", + "pretest": "standard --fix js/**/*.js", + "test": "./tests/js/js.sh" + }, + "standard": { + "globals": [ + "after", + "afterEach", + "before", + "beforeEach", + "describe", + "it", + "run" + ] + } +} diff --git a/project/history.go b/project/history.go index 88df02b2f..a00c1a13e 100644 --- a/project/history.go +++ b/project/history.go @@ -48,8 +48,14 @@ func FullVersion() string { // release tagging script: ./scripts/tag_release.sh var History relic.ImmutableHistory = relic.NewHistory("Hyperledger Burrow", "https://github.com/hyperledger/burrow"). MustDeclareReleases( - "", - ``, + "0.28.1 - 2019-08-21", + `### Fixed +- [Vent] Log for _vent_log insert now faithfully captures what is being inserted +- [Vent] Remove arbitrary 100 character limits on system table text fields + +### Added +- [JS] Burrow.js now included in Burrow repo and tested with Burrow CI! Future burrow.js releases will now match version of Burrow. +`, "0.28.0 - 2019-08-14", `### Changed - [State] IterateStreamEvents now takes inclusive start and end points (end used to be exclusive) avoid bug-prone conversion diff --git a/scripts/release.sh b/scripts/release.sh index 50f47965d..33f016cd5 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -15,6 +15,13 @@ function release { echo ${DOCKER_PASS} | docker login --username ${DOCKER_USER} --password-stdin docker tag ${DOCKER_REPO}:${tag#v} ${DOCKER_REPO}:latest docker push ${DOCKER_REPO} + + # Disable publishing npm module until ci is set up properly + #git config --global user.email "billings@monax.io" + #npm-cli-login + #npm version from-git + #npm publish --access public . + echo "Building and pushing binaries" [[ -e "$notes" ]] && goreleaser --release-notes "$notes" || goreleaser } diff --git a/tests/js/deploy.yaml b/tests/js/deploy.yaml new file mode 100644 index 000000000..840ac0100 --- /dev/null +++ b/tests/js/deploy.yaml @@ -0,0 +1,12 @@ +jobs: + +- name: randomDeploy + deploy: + contract: random.sol + +- name: randomRegister + register: + name: random + data: $randomDeploy + amount: 5000 + fee: 2000 diff --git a/tests/burrow.js.sh b/tests/js/js.sh similarity index 67% rename from tests/burrow.js.sh rename to tests/js/js.sh index 65501b0b5..432bea388 100755 --- a/tests/burrow.js.sh +++ b/tests/js/js.sh @@ -16,17 +16,20 @@ # run_pkgs_tests.sh [appXX] -export script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -source "$script_dir/test_runner.sh" +export jsscript_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source "$jsscript_dir/../test_runner.sh" -export js_dir="${script_dir}/../burrow.js" +export js_dir="${script_dir}/../js" perform_js_tests(){ + cd "$jsscript_dir" + # First deploy a solidity file using burrow deploy so it has metadata + $burrow_bin deploy --chain=$BURROW_HOST:$BURROW_GRPC_PORT -a $key1_addr deploy.yaml cd "$js_dir" test_account="{\"address\": \"$key1_addr\"}" echo "Using test account:" - echo "$test_account" + echo $test_account account="$test_account" mocha --bail --exit --recursive ${1} test_exit=$? } @@ -38,7 +41,7 @@ burrowjs_tests() { test_setup trap test_teardown EXIT - echo "Running burrow.js tests..." + echo "Running js tests..." perform_js_tests "$1" } diff --git a/tests/js/random.sol b/tests/js/random.sol new file mode 100644 index 000000000..ed3cca635 --- /dev/null +++ b/tests/js/random.sol @@ -0,0 +1,7 @@ +pragma solidity >=0.0.0; + +contract random { + function getRandomNumber() public pure returns (uint) { + return 55; + } +} diff --git a/vent/sqldb/sqldb.go b/vent/sqldb/sqldb.go index b59ca1322..edf5123aa 100644 --- a/vent/sqldb/sqldb.go +++ b/vent/sqldb/sqldb.go @@ -316,11 +316,11 @@ func (db *SQLDB) SetBlock(chainID string, eventTables types.EventTables, eventDa } defer logStmt.Close() - var safeTable string + var tableName string loop: // for each table in the block - for en, table := range eventTables { - safeTable = safe(table.Name) + for _, table := range eventTables { + tableName = safe(table.Name) dataRows := eventData.Tables[table.Name] // for Each Row for _, row := range dataRows { @@ -349,17 +349,17 @@ loop: break loop // exits from all loops -> continue in close log stmt } - query := queryVal.Query + sqlQuery := queryVal.Query // Perform row action - db.Log.InfoMsg("msg", "action", row.Action, "query", query, "value", queryVal.Values) - if _, err = tx.Exec(query, queryVal.Pointers...); err != nil { + db.Log.InfoMsg("msg", "action", row.Action, "query", sqlQuery, "value", queryVal.Values) + if _, err = tx.Exec(sqlQuery, queryVal.Pointers...); err != nil { db.Log.InfoMsg(fmt.Sprintf("error performing %s on row", row.Action), "err", err, "value", queryVal.Values) break loop // exits from all loops -> continue in close log stmt } // Marshal the rowData map - jsonData, err := getJSON(row.RowData) + rowData, err := getJSON(row.RowData) if err != nil { db.Log.InfoMsg("error marshaling rowData", "err", err, "value", fmt.Sprintf("%v", row.RowData)) break loop // exits from all loops -> continue in close log stmt @@ -374,11 +374,22 @@ loop: eventName, _ := row.RowData[db.Columns.EventName].(string) // Insert in log - db.Log.InfoMsg("INSERT LOG", "action", "INSERT", "query", logQuery, "value", - fmt.Sprintf("chainid = %s tableName = %s eventName = %s block = %d", chainID, safeTable, en, eventData.BlockHeight)) - - if _, err = logStmt.Exec(chainID, safeTable, eventName, row.EventClass.GetFilter(), eventData.BlockHeight, txHash, - row.Action, jsonData, query, sqlValues); err != nil { + db.Log.InfoMsg("INSERT LOG", + "log_query", logQuery, + "chain_id", chainID, + "table_name", tableName, + "event_name", eventName, + "event_filter", row.EventClass.GetFilter(), + "block_height", eventData.BlockHeight, + "tx_hash", txHash, + "row_action", row.Action, + "row_data", rowData, + "sql_query", sqlQuery, + "sql_values", sqlValues, + ) + + if _, err = logStmt.Exec(chainID, tableName, eventName, row.EventClass.GetFilter(), eventData.BlockHeight, txHash, + row.Action, rowData, sqlQuery, sqlValues); err != nil { db.Log.InfoMsg("Error inserting into log", "err", err) break loop // exits from all loops -> continue in close log stmt } @@ -405,7 +416,7 @@ loop: // Table does not exists if db.DBAdapter.ErrorEquals(err, types.SQLErrorTypeUndefinedTable) { - db.Log.InfoMsg("Table not found", "value", safeTable) + db.Log.InfoMsg("Table not found", "value", tableName) //Synchronize DB if err = db.SynchronizeDB(chainID, eventTables); err != nil { return err @@ -416,7 +427,7 @@ loop: // Columns do not match if db.DBAdapter.ErrorEquals(err, types.SQLErrorTypeUndefinedColumn) { - db.Log.InfoMsg("Column not found", "value", safeTable) + db.Log.InfoMsg("Column not found", "value", tableName) //Synchronize DB if err = db.SynchronizeDB(chainID, eventTables); err != nil { return err diff --git a/vent/sqldb/system_tables.go b/vent/sqldb/system_tables.go index 295d056b6..69786185f 100644 --- a/vent/sqldb/system_tables.go +++ b/vent/sqldb/system_tables.go @@ -17,23 +17,20 @@ func (db *SQLDB) systemTablesDefinition() types.EventTables { Primary: true, }, { - Name: columns.ChainID, - Type: types.SQLColumnTypeVarchar, - Length: 100, + Name: columns.ChainID, + Type: types.SQLColumnTypeVarchar, }, { Name: columns.TimeStamp, Type: types.SQLColumnTypeTimeStamp, }, { - Name: columns.TableName, - Type: types.SQLColumnTypeVarchar, - Length: 100, + Name: columns.TableName, + Type: types.SQLColumnTypeVarchar, }, { - Name: columns.EventName, - Type: types.SQLColumnTypeVarchar, - Length: 100, + Name: columns.EventName, + Type: types.SQLColumnTypeVarchar, }, { Name: columns.EventFilter, @@ -42,9 +39,8 @@ func (db *SQLDB) systemTablesDefinition() types.EventTables { // We use varchar for height - there is no uint64 type though numeric could have been used. We obtain the // maximum height by maxing over the serial ID type { - Name: columns.Height, - Type: types.SQLColumnTypeVarchar, - Length: 100, + Name: columns.Height, + Type: types.SQLColumnTypeVarchar, }, { Name: columns.TxHash, @@ -54,7 +50,7 @@ func (db *SQLDB) systemTablesDefinition() types.EventTables { { Name: columns.Action, Type: types.SQLColumnTypeVarchar, - Length: 20, + Length: 50, }, { Name: columns.DataRow, @@ -77,34 +73,28 @@ func (db *SQLDB) systemTablesDefinition() types.EventTables { { Name: columns.TableName, Type: types.SQLColumnTypeVarchar, - Length: 100, Primary: true, }, { Name: columns.ColumnName, Type: types.SQLColumnTypeVarchar, - Length: 100, Primary: true, }, { - Name: columns.ColumnType, - Type: types.SQLColumnTypeInt, - Length: 0, + Name: columns.ColumnType, + Type: types.SQLColumnTypeInt, }, { - Name: columns.ColumnLength, - Type: types.SQLColumnTypeInt, - Length: 0, + Name: columns.ColumnLength, + Type: types.SQLColumnTypeInt, }, { - Name: columns.PrimaryKey, - Type: types.SQLColumnTypeInt, - Length: 0, + Name: columns.PrimaryKey, + Type: types.SQLColumnTypeInt, }, { - Name: columns.ColumnOrder, - Type: types.SQLColumnTypeInt, - Length: 0, + Name: columns.ColumnOrder, + Type: types.SQLColumnTypeInt, }, }, }, @@ -114,13 +104,11 @@ func (db *SQLDB) systemTablesDefinition() types.EventTables { { Name: columns.ChainID, Type: types.SQLColumnTypeVarchar, - Length: 100, Primary: true, }, { - Name: columns.BurrowVersion, - Type: types.SQLColumnTypeVarchar, - Length: 100, + Name: columns.BurrowVersion, + Type: types.SQLColumnTypeVarchar, }, { Name: columns.Height,