├── .gitignore ├── .vscode └── launch.json ├── BitShovel.png ├── Dockerfile ├── README.md ├── _config.yml ├── bitshovel-production ├── bitshovel.js ├── docker-compose.yml ├── docs ├── BitShovel.fund.png ├── Docker.md └── getstarted.md ├── dummyapp.js ├── examples ├── listen.py ├── publish.go └── publish.py ├── misc ├── genWallet.js ├── requirements.txt ├── test.html ├── test.py └── when_transaction.py ├── nodemon.json ├── package-lock.json ├── package.json ├── shoveladdress.js ├── shovelbus.js ├── shovelcache.js ├── shovellisteners.js ├── shovelregistry.js ├── shovelwallet.js ├── test └── test.js └── utils.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Created by https://www.gitignore.io/api/node,sublimetext 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 23 | .grunt 24 | 25 | # node-waf configuration 26 | .lock-wscript 27 | 28 | # Compiled binary addons (http://nodejs.org/api/addons.html) 29 | build/Release 30 | 31 | # Dependency directory 32 | node_modules 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional REPL history 38 | .node_repl_history 39 | 40 | 41 | ### SublimeText ### 42 | # cache files for sublime text 43 | *.tmlanguage.cache 44 | *.tmPreferences.cache 45 | *.stTheme.cache 46 | 47 | # workspace files are user-specific 48 | *.sublime-workspace 49 | 50 | # project files should be checked into the repository, unless a significant 51 | # proportion of contributors will probably not be using SublimeText 52 | *.sublime-project 53 | 54 | # sftp configuration file 55 | sftp-config.json 56 | 57 | #IMPORTANT! 58 | wallet.json 59 | wallet.json.* 60 | 61 | nohup.out 62 | database/ 63 | get-pip.py 64 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceFolder}\\bitshovel.js" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /BitShovel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfoderick/bitshovel/bd7dc31bf60fa01b2b533954b1750fa2fa9be992/BitShovel.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Creates a Docker container for BitShovel service 2 | 3 | # IMAGE BUILD COMMANDS 4 | FROM ubuntu:18.04 5 | LABEL maintainer="dfoderick@gmail.com" 6 | 7 | # Update the OS and install any OS packages needed. 8 | RUN apt-get update 9 | RUN apt-get install -y sudo git curl nano gnupg 10 | 11 | # Install Node and NPM 12 | RUN curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh 13 | RUN bash nodesource_setup.sh 14 | RUN apt-get install -y nodejs build-essential 15 | 16 | # Create the user 'myuser' and add them to the sudo group. 17 | RUN useradd -ms /bin/bash myuser 18 | RUN adduser myuser sudo 19 | 20 | # Set password to 'password' change value below if you want a different password 21 | RUN echo myuser:password | chpasswd 22 | 23 | # Set the working directory to be the users home directory 24 | WORKDIR /home/myuser 25 | 26 | # Setup NPM for non-root global install 27 | # This fixes the most common conflicts between Mac and Linux development environments. 28 | RUN mkdir /home/myuser/.npm-global 29 | RUN chown -R myuser .npm-global 30 | RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/myuser/.profile 31 | RUN runuser -l myuser -c "npm config set prefix '~/.npm-global'" 32 | 33 | # Expose the port the API will be served on. 34 | #EXPOSE 3000 35 | 36 | # Switch to user account. 37 | USER myuser 38 | # Prep 'sudo' commands. 39 | RUN echo 'password' | sudo -S pwd 40 | 41 | # Clone the repository 42 | WORKDIR /home/myuser 43 | RUN git clone https://github.com/dfoderick/bitshovel 44 | WORKDIR /home/myuser/bitshovel 45 | 46 | # Install dependencies 47 | RUN npm install 48 | 49 | # Start the application. 50 | COPY bitshovel-production bitshovel-production 51 | CMD ["./bitshovel-production"] 52 | 53 | #Dummy app just to get the container running without exiting, for debugging. 54 | #You can then enter the container with command: docker exec -it /bin/bash 55 | #COPY dummyapp.js dummyapp.js 56 | #CMD ["node", "dummyapp.js"] 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Why use BitShovel for your blockchain apps? 3 | 4 | * Easily read and write messages to bitcoin in [any language](#examples) 5 | * Combines read and write operations into a single simple API 6 | * Builds on top of [unwriter]((https://github.com/unwriter)) [excellent libraries](https://github.com/21centurymotorcompany) 7 | * Easy to deploy using Docker 8 | * Provides a simple messaging infrastructure (pubsub, work queues, etc.) for all your applications 9 | * Compatible with event driven programming and microservices architectures 10 | * Additional application services will plug in to the messaging infrastructure with a simple Docker install 11 | 12 | ## What is BitShovel? 13 | BitShovel fully embraces the architecture [unwriter](https://github.com/unwriter) explains in [Bitsocket: The Realtime API for Bitcoin](https://www.yours.org/content/bitsocket--the-realtime-api-for-bitcoin-0c646d55c152) and recognizes a fundamental truth: *Bitcoin is the universal messaging system.* 14 | 15 | Think of BitShovel as a bitcoin application accelerator - a building block for Metanet. 16 | > Broadcast your message to bitcoin if you need any of the enhanced capabilities that bitcoin provides: 17 | > * You want to preserve an immutable audit trail of your message 18 | > * You need to transfer money with the transaction as a receipt 19 | > * To initiate a remote process or service 20 | 21 | > To communicate with a local applicaiton or if none of the enhanced services that bitcoin provides are needed then just broadcast the messate on the local bus. 22 | 23 | **It can be that simple!** 24 | 25 | BitShovel is not a library. It is a downloadable application service black box plug-in component that runs in a process on your local network. You communicate with BitShovel applications by sending it messages. A sequence of messages form a workflow of events. 26 | 27 | With BitShovel your apps can listen to events that happen on bitcoin. It can also kick off a remote workflow by sending a message to bitcoin. Your application is now a bot, an oracle, an autonomous agent, a smart contract, a living entity on bitcoin. 28 | 29 | ![BitShovel Architecture](BitShovel.png "BitShovel Architecture") 30 | 31 | The name BitShovel comes from its utility as a low level tool. 'Shoveling' is the term for scooping a message on one message bus and forwarding it onto another message bus. Sometimes the same action can be referred to as a bridge or an extender. 32 | 33 | ## Getting Started 34 | There is a [Getting Started with BitShovel Tutorial](docs/getstarted.md) which also serves as an installation guide. 35 | 36 | ## Install using Docker Compose 37 | ``` 38 | git clone https://github.com/dfoderick/bitshovel 39 | cd bitshovel 40 | ``` 41 | Run the following command *once* to build the docker image. 42 | ``` 43 | docker-compose build --no-cache 44 | ``` 45 | Thereafter, run the following command (notice the `no-recreate` option) so that your private keys in wallet.json will not get wiped out. 46 | ``` 47 | docker-compose up --no-recreate 48 | ``` 49 | To find out what docker containers are running use 50 | ``` 51 | docker ps 52 | ``` 53 | ## Configure your private keys 54 | > 55 | > *An Important Note on Private Keys!* 56 | > It is very easy to lose the private keys on a development server in Docker. Do not store a large amount of bitcoin in your wallet. Fund the wallet with small amounts and make backups of your private keys 57 | > 58 | 59 | If you want to write data to bitcoin then BitShovel will need private keys for your wallet. 60 | BitShovel will create a wallet.json by default when it starts up. You can either update 61 | the wallet.json file with your own private keys or you can fund the wallet that BitShovel 62 | generated. Use the following command (while BitShovel is running) to find out the wallet address to fund. 63 | ``` 64 | redis-cli GET bitshovel.wallet.address 65 | ``` 66 | The easiest way to fund the wallet is by using moneybutton to withdraw to the BitShovel address. 67 | https://www.moneybutton.com/test 68 | 69 | ## Create your app 70 | Any process that can read and write messages can now be a blockchain app. [See examples below](#examples). Test that your BitShovel instance is running using the command lines below and then get started writing apps. 71 | 72 | # Test BitShovel from command line 73 | To make testing from the command line easier make the following aliases. You can choose any alias that suits. 74 | ``` 75 | alias sub="redis-cli subscribe" 76 | alias pub="redis-cli publish" 77 | alias get="redis-cli get" 78 | ``` 79 | 80 | Open terminal and create a listener for bitcoin messages. Messages will scroll in this process. 81 | ``` 82 | sub bitshovel.watch 83 | ``` 84 | Open another terminal to control BitShovel and start pumping it with commands. 85 | This command will listen to all messages on the bitcoin network. 86 | ``` 87 | pub bitshovel.stream 'start streamname {"find":{}}' 88 | ``` 89 | Stop shovel from reading messages. 90 | ``` 91 | pub bitshovel.stream 'stop streamname' 92 | ``` 93 | For fun, lets listen to all the messages that BitShovel is creating. The following command will get your wallet address. 94 | ``` 95 | get bitshovel.wallet.address 96 | ``` 97 | Copy and paste it into the following command to listen for transactions on that address. 98 | ``` 99 | pub bitshovel.app 'start walletname PasteYourWalletAddressFromAbove' 100 | ``` 101 | Send a message to the bitcoin network - requires wallet to be funded and needs double quotes (for now). 102 | ``` 103 | pub bitshovel.send '"Hello from BitShovel!"' 104 | ``` 105 | After a few seconds delay the bitshovel.watch terminal should show the message that you just sent to bitcoin. 106 | 107 | You can also find the message on bitcoin explorer. 108 | https://bitgraph.network/explorer/ewogICJ2IjogMywKICAicSI6IHsKICAgICJmaW5kIjogeyAib3V0LmIwIjogeyAib3AiOiAxMDYgfSwgIm91dC5zMSI6IkhlbGxvIGZyb20gQml0U2hvdmVsISIgfSwKICAgICJwcm9qZWN0IjogeyAib3V0LiQiOiAxIH0KICB9Cn0= 109 | 110 | Query bitcoin for all messages using the demo string using the following query. 111 | ``` 112 | { 113 | "v": 3, 114 | "q": { 115 | "find": { "out.b0": { "op": 106 }, "out.s1":"Hello from BitShovel!" }, 116 | "project": { "out.$": 1 } 117 | } 118 | } 119 | ``` 120 | You could also search using searchbsv.com.. 121 | https://searchbsv.com/search?q=BitShovel 122 | 123 | 124 | You can also send a Bitquery query to BitShovel and it will replay the bitcoin messages on your local message bus. This query will get the last bitcoin message and publish it on your local bus. 125 | ``` 126 | pub bitshovel.query '{"find":{},"limit":1}' 127 | ``` 128 | 129 | # Bitshovel Events (aka Channels or Topics) 130 | * **bitshovel.watch** 131 | Subscribe to this event to get notified when a new bitcoin message appears on the local bus. 132 | * **bitshovel.send** 133 | Publish message to this channel to write to bitcoin 134 | * **bitshovel.stream** 135 | Start (Stop) listening to bitcoin messages. Pass it the Bitquery. Bitcoin messages that match the query filter will be forwarded to the local bus. 136 | * **bitshovel.query** 137 | Get historical transactions from the bitcoin network. Tx that match the query will be replayed on the local bus. 138 | * **bitshovel.wallet** 139 | Update the wallet to use a new private key 140 | * **bitshovel.app** 141 | Application level commands. Currently allows listening for messages for a single application (address) 142 | 143 | # Examples 144 | A Python program to send (write) to bitcoin. 145 | ``` 146 | import redis 147 | bus = redis.Redis() 148 | bus.publish("bitshovel.send",'"Hello from BitShovel! Python"') 149 | ``` 150 | A Python program to listen to bitcoin messages on the local bus. 151 | To see messages in this window you have to also tell BitShovel to watch for messages on bitcoin. 152 | e.g. ```pub bitshovel.stream 'start streamname {"find":{}}'``` 153 | ``` 154 | import redis 155 | bus = redis.Redis().pubsub() 156 | bitshovel_reader = bus.subscribe("bitshovel.watch") 157 | for message in bus.listen(): 158 | print(message) 159 | ``` 160 | A golang program to write to bitcoin. 161 | ``` 162 | package main 163 | import "github.com/go-redis/redis" 164 | import "log" 165 | func main() { 166 | client := redis.NewClient(&redis.Options{ 167 | Addr: "localhost:6379", 168 | Password: "", // no password set 169 | DB: 0, // use default DB 170 | }) 171 | _, err := client.Publish("bitshovel.send", "Hello from BitShovel! Go").Result() 172 | if err != nil { 173 | log.Fatal(err) 174 | } 175 | } 176 | ``` 177 | 178 | # Native install for Developers 179 | Normal users can run BitShovel using the Docker instruction above. Developers wishing to customize the app can install it natively to edit the source file. 180 | 181 | ## Install redis 182 | Install and run redis using 183 | ``` 184 | docker run --name bitshovel-redis -d redis 185 | ``` 186 | 187 | ## Get source code 188 | ``` 189 | git clone https://github.com/dfoderick/bitshovel 190 | cd bitshovel 191 | npm install 192 | ``` 193 | ## Run BitShovel server 194 | ``` 195 | node bitshovel.js 196 | ``` 197 | will respond with 'Connected to local bus...' 198 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /bitshovel-production: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export NODE_ENV=production 3 | npm start 4 | -------------------------------------------------------------------------------- /bitshovel.js: -------------------------------------------------------------------------------- 1 | //ALERT: This software is alpha. Use at your own risk, especially if using mainnet 2 | //Always, Always, Always protect your private key! 3 | 4 | //This the connection point between bitcoin and your local application 5 | //implemented with unwriter libraries for reading and writing to bitcoin 6 | 7 | const utils = require('./utils') 8 | const shovelwallet = require('./shovelwallet') 9 | const shoveladdress = require('./shoveladdress') 10 | const shovelcache = require('./shovelcache') 11 | //application registry 12 | const shovelregistry = require('./shovelregistry') 13 | //bitsocket listeners 14 | const shovellisteners = require('./shovellisteners') 15 | const localbus = require('./shovelbus') 16 | //for writing to bitcoin 17 | const datapay = require('datapay'); 18 | const fs = require('fs'); 19 | const axios = require('axios') 20 | 21 | const DEBUG = false 22 | 23 | //eventually these items will be configurable 24 | const BITDB_SOURCE = 'https://bitdb.network/q/' 25 | const BITDB_API_KEY = 'qrr6u2amzamlf7cay750j0fnd76fhhcpxgr2ekv2wg' 26 | 27 | //create a wallet if there is none 28 | if (!fs.existsSync(shovelwallet.walletFileName)) { 29 | shovelwallet.generateWallet(); 30 | } 31 | let wallet = require(`./${shovelwallet.walletFileName}`); 32 | 33 | function main () { 34 | localbus.start() 35 | shovelcache.start() 36 | shovelcache.storeWalletAddress(wallet.address); 37 | 38 | localbus.sub.on("message", function (channel, message) { 39 | try { 40 | console.log(`got message from local bus ${channel}: ${message}`); 41 | if (channel === localbus.CHANNEL_SEND) { 42 | //send the message to bitcoin 43 | shovelToBitcoin(message); 44 | } 45 | //example: bitshovel.stream start|stop name query 46 | if (channel === localbus.CHANNEL_STREAM) { 47 | const cmd = utils.parseCommand("stream", message) 48 | if (utils.isStart(cmd.action)) { 49 | //start listening to bitsocket messages 50 | //this will start broadcasting bitcoin tx on to your local bus 51 | console.log(`starting bitsocket listener ${message}`); 52 | startBitSocket(cmd); 53 | } 54 | if (utils.isStop(cmd.action)) { 55 | shovellisteners.close(cmd.name) 56 | } 57 | } 58 | if (channel === localbus.CHANNEL_APP) { 59 | //application (address) level command. Assumes an address is specified 60 | //bitsocket used cashaddr. will be converted to use legacy address soon 61 | const cmd = utils.parseCommand("app", message) 62 | console.log(cmd) 63 | if (utils.isStart(cmd.action)) { 64 | console.log(`starting app listener ${message}`); 65 | startBitSocket(cmd); 66 | } else if (utils.isStop(cmd.action)) { 67 | stopBitSocket(cmd); 68 | } else if (cmd.action === 'register') { 69 | registerApplication(cmd) 70 | } else { 71 | console.log(`unknown command ${cmd}`) 72 | } 73 | } 74 | if (channel === localbus.CHANNEL_QUERY) { 75 | const url = utils.urlString(BITDB_SOURCE, makeBitquery(JSON.parse(message))) 76 | getBitdb(url) 77 | } 78 | if (channel === localbus.CHANNEL_WALLET) { 79 | //store the private key in local wallet 80 | //TODO:should encrypt private key on the wire 81 | if (wallet.wif != message) { 82 | wallet = shovelwallet.generateWallet(message); 83 | shovelcache.storeWalletAddress(wallet.address); 84 | } 85 | } 86 | } 87 | catch (err) { 88 | console.error(err) 89 | } 90 | }) 91 | localbus.subscribeall() 92 | } 93 | 94 | main() 95 | 96 | function registerApplication(cmd) { 97 | //for now use the bitshovel wallet, in future probably want each app to have wallet 98 | localbus.pub.set(cmd.name, wallet.address, function(err) { 99 | if (err) { 100 | console.error(err) 101 | } 102 | }) 103 | //localbus_pub.hmset(CHANNEL_APP, cmd.name, wallet.address) 104 | //register the app in the app registry 105 | shovelregistry.register(cmd.name, wallet.address) 106 | } 107 | 108 | function getBitdb(url) { 109 | var header = { 110 | headers: { key: BITDB_API_KEY } 111 | } 112 | axios.get(url, header).then(function(r) { 113 | //console.log(`queried ${r.data.u.length} results`) 114 | //unconfirmed tx 115 | for (let item of r.data.u) { 116 | localbus.publish(JSON.stringify(item)) 117 | } 118 | //confirmed tx 119 | for (let item of r.data.c) { 120 | localbus.publish(JSON.stringify(item)) 121 | } 122 | }) 123 | } 124 | 125 | //start listening for bitcoin messages 126 | //example query... 127 | // {"v": 3, "q": { "find": {} }} 128 | function startBitSocket(cmd) { 129 | //let address = findAddressforApplication(cmd) 130 | let query = queryFromCommand(cmd) 131 | const listener = shovellisteners.listen(cmd.name, query) 132 | listener.bitsocket.onmessage = function(e) { 133 | //surprising that this works! function keeps the listener name in context when it fires 134 | console.log(listener.name); 135 | logTna(e); 136 | localbus.publish(e.data); 137 | } 138 | listener.bitsocket.onerror = function(err) { 139 | console.log(err); 140 | } 141 | } 142 | 143 | function logit(category, s) { 144 | console.log(`${category} ${s}`) 145 | } 146 | 147 | function logTna(tna) { 148 | console.log(tna); 149 | } 150 | 151 | function queryFromCommand(cmd) { 152 | if (cmd.command === "stream") { 153 | //parameter is the query 154 | return makeBitquery(JSON.parse(cmd.parameter)) 155 | } 156 | if (cmd.command === "app") { 157 | //parameter is the address to monitor 158 | address = findAddressforApplication(cmd) 159 | console.log(address) 160 | const qry = { 161 | "v": 3, 162 | "q": { 163 | "find": { 164 | "out.e.a": shoveladdress.toCashAddress(address) 165 | } 166 | } 167 | } 168 | return makeBitquery(qry) 169 | } 170 | //what to do? 171 | return cmd.parameter 172 | } 173 | 174 | //translate application alias to address 175 | function findAddressforApplication(cmd) { 176 | // (async () => { 177 | //if param was passed then use that as address 178 | if (cmd.parameter) { 179 | return cmd.parameter 180 | } 181 | //otherwise look up the app by name 182 | // await localbus_pub.hget(CHANNEL_APP, cmd.name, function (err, obj) { 183 | // if (obj) { 184 | // return obj 185 | // } 186 | // return cmd.name 187 | // }) 188 | if (shovelregistry.has(cmd.name)) { 189 | return shovelregistry.get(cmd.name) 190 | } 191 | return cmd.name 192 | // })() 193 | } 194 | 195 | //make a standard bitquery query 196 | //basically it will add any missing attributes to make it a standard query 197 | function makeBitquery(query) { 198 | let fullquery = query 199 | if (!query.hasOwnProperty("q")) { 200 | //assume that query is just the q attribute, fill in the rest 201 | fullquery = { 202 | "v": 3, 203 | "q": query 204 | } 205 | } 206 | return JSON.stringify(fullquery) 207 | } 208 | 209 | //write the message to bitcoin by creating a transaction 210 | function shovelToBitcoin(message) { 211 | //TODO: for now assume ascii text, later need to distinguish from hex string 212 | //console.log(`shoveling to bitcoin >${message}<`); 213 | let split = utils.splitString(message) 214 | console.log(split) 215 | 216 | if (!DEBUG) { 217 | datapay.send({ 218 | data: split, 219 | pay: { key: wallet.wif } 220 | }, function sendResult(err,txid) { 221 | if (err) { 222 | console.log(err); 223 | } 224 | if (txid) { 225 | console.log(`txid:${txid}`); 226 | } 227 | }); 228 | } 229 | //TODO:could raise event saying that tx was sent 230 | } 231 | 232 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Start BitShovel service with the command 'docker-compose up --no-recreate' 2 | # This will prevent docker from wiping the image and forcing it to create a new wallet 3 | 4 | version: '3' 5 | 6 | services: 7 | redis: 8 | image: redis:latest 9 | container_name: bitshovel-redis 10 | ports: 11 | - "127.0.0.1:6379:6379" 12 | #network_mode: host 13 | 14 | bitshovel: 15 | container_name: bitshovel-service 16 | build: . 17 | # links: 18 | # - redis 19 | network_mode: host 20 | -------------------------------------------------------------------------------- /docs/BitShovel.fund.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfoderick/bitshovel/bd7dc31bf60fa01b2b533954b1750fa2fa9be992/docs/BitShovel.fund.png -------------------------------------------------------------------------------- /docs/Docker.md: -------------------------------------------------------------------------------- 1 | # Dockerize your bitcoin apps 2 | Design your application in simple logical steps that can be deployed as components using "when-then" analysis. Plug in components can run anywhere on your network 3 | and are easily accessible with a simple command or API. 4 | Think of them as black boxes that are either localized to your network or applications that are accessible globally using the bitcoin network. 5 | If you want your app accessible from the local message bus then only listen to the local bus. 6 | If you want your app accessible from anywhere then listen to the bitcoin message bus. 7 | 8 | ## Example: Memo as a BitShovel plug in 9 | 10 | Read about the basics of setting up a Docker image here: 11 | 12 | https://docs.docker.com/docker-hub/#step-4-build-and-push-a-container-image-to-docker-hub-from-your-computer 13 | 14 | Create a Dockerfile for your app. You can use the following as an example. 15 | ``` 16 | FROM python:2 17 | ADD memo.py / 18 | RUN pip install redis 19 | CMD [ "python", "./memo.py" ] 20 | ``` 21 | Build it and test it locally. 22 | ``` 23 | docker build -t bitshovel-memo . 24 | docker run -network=host bitshovel-memo 25 | ``` 26 | When you are ready to publish your component then push it to Docker Hub. 27 | ``` 28 | docker login --username= 29 | docker images 30 | docker tag 0b8e7c334643 /bitshovel-memo:latest 31 | docker push /bitshovel-memo 32 | ``` 33 | Thereafter, anyone can download and run your component with just a single `docker run` command. 34 | ``` 35 | docker run -network=host dfoderick/bitshovel-memo 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/getstarted.md: -------------------------------------------------------------------------------- 1 | # Getting Started with BitShovel 2 | BitShovel is a tool that makes it easy to write bitcoin applications. 3 | 4 | Take a few minutes to [understand it](/README.md) if you don't know what it is. 5 | 6 | In this tutorial you will learn how to install BitShovel and use it to read and write to bitcoin using a few simple commands. 7 | 8 | # Dependencies 9 | You should have Docker installed as well as redis-cli (currently required for command line testing and demonstration) 10 | 11 | ### Step 1: Install BitShovel 12 | First you need a local message bus. Redis is nice and simple. Run it if you don't have it already. This may require sudo. 13 | ``` 14 | docker run -p 6379:6379 redis 15 | ``` 16 | Now for the hard part. Installing BitShovel! 17 | ``` 18 | docker run --network=host dfoderick/bitshovel:getstarted 19 | ``` 20 | BitShovel will download and start. You should see it respond with `Connected to local bus...` 21 | Hmmm. That was too easy. BitShovel is now installed and running. 22 | ### Step 2: Download the Memo.cash component 23 | The base implementation of BitShovel will read and write to bitcoin but it doesn't know about any application specific protocols like memo.cash. Open another terminal and run the following command to download and run a component that understands memo.cash messages. 24 | ``` 25 | docker run --network=host dfoderick/bitshovel-memo:getstarted 26 | ``` 27 | That's it! Now your shovel will know how to post to the memo.cash web site using bitcoin. In the near future there will be additional components that you can download just as easily to add functionality to your apps. And you can write your own custom components in any language. 28 | ### Step 3: Testing your installation and Funding your wallet 29 | Before we send messages to bitcoin, let's make life a bit easier on ourselves. Open yet another terminal and run the following commands (or put them in your Bash ~/.bashrc script). 30 | ``` 31 | alias sub="redis-cli subscribe" 32 | alias pub="redis-cli publish" 33 | alias get="redis-cli get" 34 | ``` 35 | BitShovel created a wallet when it started for the first time. To get the address for your wallet run 36 | ``` 37 | get bitshovel.wallet.address 38 | ``` 39 | Your wallet will need money so that it can send messages to bitcoin. There are at least 3 ways to get it funded. 40 | 41 | * The simplest way to fund your wallet is go to https://fund.fullcyclemining.com/ 42 | Enter the address from above. Select an amount (0.05 cents is plenty for testing) then slide the money button. Your payment information will show below when it is successful. 43 | ![BitShovel Fund](BitShovel.fund.png "BitShovel Fund") 44 | 45 | * If that doesn't work then fund the wallet using MoneyButton's test page. https://www.moneybutton.com/test 46 | 47 | * Alternatively, if you already have a wallet that is funded and you know the private key then you can tell BitShovel to use it instead. 48 | ``` 49 | pub bitshovel.wallet 50 | get bitshovel.wallet.address 51 | ``` 52 | Remember your address. You will listen to messages going to this address in the next step. 53 | ### Step 4: Listen for bitcoin messages 54 | At this point BitShovel is not doing anything. Lets tell it to listen for bitcoin messages on the local message bus. 55 | ``` 56 | sub bitshovel.watch 57 | ``` 58 | Not so interesting. It subscribes to the watch event and then just sits there. The terminal is waiting for bitcoin messages but there are not any messages locally yet. Leave that terminal window open and visible. 59 | Open another terminal window and run the following commands to get the last 3 messages from bitcoin. 60 | (Remember to run the alias commands if you did not put them in your startup script.) 61 | ``` 62 | alias pub="redis-cli publish" 63 | pub bitshovel.query '{"find":{},"limit":3}' 64 | ``` 65 | Better. Three bitcoin messages should scroll in the watch window. You are now streaming messages from bitcoin on to our local message bus. Next tell BitShovel to listen for messages that you will be sending in the next step. 66 | ``` 67 | pub bitshovel.app 'start walletname PasteYourWalletAddressFromAbove' 68 | ``` 69 | Again, this command does not display anthing. It tells BitShovel to sit and wait for someone to send something to your wallet address. That someone will be you in the next step. Let's move on... 70 | ### Step 5: Sending messages to bitcoin 71 | Finally, we can send a message to bitcoin! This command will create a transaction that contains an OP_RETURN. 72 | ``` 73 | pub bitshovel.send '"Hello from BitShovel!"' 74 | ``` 75 | The watch window that you set up in the previous step should show the transaction in a few seconds. Our UI is not so lovely at this point but we can console ourselves because we know there are many UI tools already that make for a great experience using bitcoin. Lets use some of them now. Search for the message you just sent using searchbsv.com. 76 | https://searchbsv.com/search?q=BitShovel 77 | 78 | It's there. Great! Next, we can make use of the Memo plugin. 79 | ``` 80 | pub memo.send "Test from BitShovel Memo" 81 | ``` 82 | Notice the difference? You used memo.send instead of bitshovel.send. The difference is that you sent it to the memo component - the memo component transformed the message according to the Memo protocol and then it forwarded your message to BitShovel which broadcast the message to bitcoin. Yeah! 83 | 84 | Log in to https://sv.memo.cash and find your message. Notice that your user name is just your address. Let's change that. 85 | ``` 86 | pub memo.send 'setname "BitShovel"' 87 | ``` 88 | That's better. Now publish a message with a topic. "BitShovel" is the topic and "Test Topic" is the message. 89 | ``` 90 | pub memo.send 'posttopic "BitShovel" "Test Topic"' 91 | ``` 92 | Refresh the Memo page to see the results. 93 | # Conclusion 94 | Pause for a moment and consider what you have learned in this tutorial. You have seen that with just a simple download and few commands you can read and write to bitcoin. 95 | * You can get notified whenever someone sends a message or payment to your wallet address. 96 | * You can do something intereting whenever that notification happens. 97 | * You can then send a message back to bitcoin in response. 98 | 99 | BitShovel makes it easy. 100 | -------------------------------------------------------------------------------- /dummyapp.js: -------------------------------------------------------------------------------- 1 | /* 2 | This is a dummy application that never exits. It keeps the Docker container 3 | alive so that a developer can enter the container and debug the real application. 4 | See Dockerfile for usage. 5 | */ 6 | 7 | "use strict" 8 | 9 | let i = 0 10 | 11 | setInterval(function() { 12 | i++ 13 | }, 30000) 14 | -------------------------------------------------------------------------------- /examples/listen.py: -------------------------------------------------------------------------------- 1 | import redis 2 | bus = redis.Redis().pubsub() 3 | bitshovel_reader = bus.subscribe("bitshovel.watch") 4 | 5 | for message in bus.listen(): 6 | print(message) 7 | -------------------------------------------------------------------------------- /examples/publish.go: -------------------------------------------------------------------------------- 1 | package main 2 | import "github.com/go-redis/redis" 3 | import "log" 4 | func main() { 5 | client := redis.NewClient(&redis.Options{ 6 | Addr: "localhost:6379", 7 | Password: "", // no password set 8 | DB: 0, // use default DB 9 | }) 10 | _, err := client.Publish("bitshovel.send", "Hello from BitShovel! Go").Result() 11 | if err != nil { 12 | log.Fatal(err) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/publish.py: -------------------------------------------------------------------------------- 1 | import redis 2 | bus = redis.Redis() 3 | bus.publish("bitshovel.send",'"Hello from BitShovel! Python"') 4 | -------------------------------------------------------------------------------- /misc/genWallet.js: -------------------------------------------------------------------------------- 1 | // generate a wallet.json file 2 | // remember to fund the wallet using the address generated 3 | // the easiest way to do that is go to https://www.moneybutton.com/test 4 | // and use withdraw button 5 | // then review the tx on a block explorer e.g. https://bchsvexplorer.com 6 | 7 | const bsv = require('bsv') 8 | const fs = require('fs'); 9 | 10 | var pk = bsv.PrivateKey() 11 | console.log(pk) 12 | var address = new bsv.Address(pk.publicKey, bsv.Networks.mainnet) 13 | console.log(address.toLegacyAddress()) 14 | 15 | wallet = { 16 | "wif": pk.toWIF(), 17 | "address": address.toLegacyAddress() 18 | } 19 | 20 | const sWallet = JSON.stringify(wallet, null, 2); 21 | console.log(sWallet) 22 | 23 | fs.writeFile('wallet.json', sWallet, 'utf8', function(err) { 24 | if(err) { 25 | return console.log(err); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /misc/requirements.txt: -------------------------------------------------------------------------------- 1 | sseclient-py 2 | requests 3 | -------------------------------------------------------------------------------- /misc/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /misc/test.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import base64 4 | import json 5 | import pprint 6 | import requests 7 | import redis 8 | 9 | from sseclient import SSEClient 10 | 11 | def with_requests(url): 12 | """Get a streaming response for the given event feed using requests.""" 13 | return requests.get(url, stream=True) 14 | 15 | r = redis.StrictRedis(host="localhost", port=6379, password="", decode_responses=True) 16 | query = {"v": 3, "q": { "find": {} }} 17 | #squery = json.dumps(query) 18 | squery = '{"v": 3, "q": { "find": {} }}' 19 | print(squery) 20 | b64 = base64.encodestring(squery) 21 | print(b64) 22 | url = 'https://bitsocket.org/s/'+b64 23 | response = with_requests(url) 24 | client = SSEClient(response) 25 | for event in client.events(): 26 | bsock = json.loads(event.data) 27 | r.publish("bitshovel.watch",event.data) 28 | print(bsock) 29 | #pprint.pprint(bsock) 30 | -------------------------------------------------------------------------------- /misc/when_transaction.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import base64 4 | import json 5 | import pprint 6 | import requests 7 | import redis 8 | import sseclient 9 | 10 | def with_requests(url): 11 | """Get a streaming response for the given event feed using requests.""" 12 | return requests.get(url, stream=True) 13 | 14 | r = redis.StrictRedis(host="localhost", port=6379, password="", decode_responses=True) 15 | query = {"v": 3, "q": { "find": {} }} 16 | b64 = base64.encodestring(json.dumps(query)) 17 | #print(b64) 18 | url = 'https://bitsocket.org/s/'+b64 19 | response = with_requests(url) 20 | client = sseclient.SSEClient(response) 21 | for event in client.events(): 22 | try: 23 | bsock = json.loads(event.data) 24 | #shovel the bitsocket tx to redis 25 | r.publish("bitshovel.watch",event.data) 26 | print(bsock["data"][0]["_id"]) 27 | #pprint.pprint(bsock) 28 | except Exception as ex: 29 | print(ex) 30 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "verbose": true, 3 | "ignore": ["wallet.json","wallet.json.*"] 4 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitshovel", 3 | "version": "0.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abbrev": { 8 | "version": "1.1.1", 9 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 10 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 11 | }, 12 | "ajv": { 13 | "version": "6.6.2", 14 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz", 15 | "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==", 16 | "requires": { 17 | "fast-deep-equal": "2.0.1", 18 | "fast-json-stable-stringify": "2.0.0", 19 | "json-schema-traverse": "0.4.1", 20 | "uri-js": "4.2.2" 21 | } 22 | }, 23 | "ansi-align": { 24 | "version": "2.0.0", 25 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", 26 | "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", 27 | "requires": { 28 | "string-width": "2.1.1" 29 | } 30 | }, 31 | "ansi-regex": { 32 | "version": "3.0.0", 33 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 34 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 35 | }, 36 | "ansi-styles": { 37 | "version": "3.2.1", 38 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 39 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 40 | "requires": { 41 | "color-convert": "1.9.3" 42 | } 43 | }, 44 | "anymatch": { 45 | "version": "2.0.0", 46 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", 47 | "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", 48 | "requires": { 49 | "micromatch": "3.1.10", 50 | "normalize-path": "2.1.1" 51 | } 52 | }, 53 | "arr-diff": { 54 | "version": "4.0.0", 55 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", 56 | "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" 57 | }, 58 | "arr-flatten": { 59 | "version": "1.1.0", 60 | "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", 61 | "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" 62 | }, 63 | "arr-union": { 64 | "version": "3.1.0", 65 | "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", 66 | "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" 67 | }, 68 | "array-unique": { 69 | "version": "0.3.2", 70 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", 71 | "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" 72 | }, 73 | "asn1": { 74 | "version": "0.2.4", 75 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 76 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 77 | "requires": { 78 | "safer-buffer": "2.1.2" 79 | } 80 | }, 81 | "assert-plus": { 82 | "version": "1.0.0", 83 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 84 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 85 | }, 86 | "assign-symbols": { 87 | "version": "1.0.0", 88 | "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", 89 | "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" 90 | }, 91 | "async-each": { 92 | "version": "1.0.1", 93 | "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", 94 | "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" 95 | }, 96 | "asynckit": { 97 | "version": "0.4.0", 98 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 99 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 100 | }, 101 | "atob": { 102 | "version": "2.1.2", 103 | "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", 104 | "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" 105 | }, 106 | "aws-sign2": { 107 | "version": "0.7.0", 108 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 109 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 110 | }, 111 | "aws4": { 112 | "version": "1.8.0", 113 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 114 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" 115 | }, 116 | "axios": { 117 | "version": "0.18.0", 118 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", 119 | "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", 120 | "requires": { 121 | "follow-redirects": "1.6.1", 122 | "is-buffer": "1.1.6" 123 | } 124 | }, 125 | "axo": { 126 | "version": "0.0.2", 127 | "resolved": "https://registry.npmjs.org/axo/-/axo-0.0.2.tgz", 128 | "integrity": "sha1-STVfu+qzhEm8ppahqsxGml7p/Uc=" 129 | }, 130 | "balanced-match": { 131 | "version": "1.0.0", 132 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 133 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 134 | }, 135 | "base": { 136 | "version": "0.11.2", 137 | "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", 138 | "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", 139 | "requires": { 140 | "cache-base": "1.0.1", 141 | "class-utils": "0.3.6", 142 | "component-emitter": "1.2.1", 143 | "define-property": "1.0.0", 144 | "isobject": "3.0.1", 145 | "mixin-deep": "1.3.1", 146 | "pascalcase": "0.1.1" 147 | }, 148 | "dependencies": { 149 | "define-property": { 150 | "version": "1.0.0", 151 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 152 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 153 | "requires": { 154 | "is-descriptor": "1.0.2" 155 | } 156 | }, 157 | "is-accessor-descriptor": { 158 | "version": "1.0.0", 159 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 160 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 161 | "requires": { 162 | "kind-of": "6.0.2" 163 | } 164 | }, 165 | "is-data-descriptor": { 166 | "version": "1.0.0", 167 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 168 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 169 | "requires": { 170 | "kind-of": "6.0.2" 171 | } 172 | }, 173 | "is-descriptor": { 174 | "version": "1.0.2", 175 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 176 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 177 | "requires": { 178 | "is-accessor-descriptor": "1.0.0", 179 | "is-data-descriptor": "1.0.0", 180 | "kind-of": "6.0.2" 181 | } 182 | } 183 | } 184 | }, 185 | "base-x": { 186 | "version": "3.0.5", 187 | "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.5.tgz", 188 | "integrity": "sha512-C3picSgzPSLE+jW3tcBzJoGwitOtazb5B+5YmAxZm2ybmTi9LNgAtDO/jjVEBZwHoXmDBZ9m/IELj3elJVRBcA==", 189 | "requires": { 190 | "safe-buffer": "5.1.2" 191 | } 192 | }, 193 | "bcrypt-pbkdf": { 194 | "version": "1.0.2", 195 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 196 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 197 | "requires": { 198 | "tweetnacl": "0.14.5" 199 | } 200 | }, 201 | "binary-extensions": { 202 | "version": "1.12.0", 203 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", 204 | "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==" 205 | }, 206 | "bitcore-explorers": { 207 | "version": "1.0.1", 208 | "resolved": "https://registry.npmjs.org/bitcore-explorers/-/bitcore-explorers-1.0.1.tgz", 209 | "integrity": "sha1-0Lw0u9cSlmSh+5uklwkRtdEOlNU=", 210 | "requires": { 211 | "bitcore-lib": "0.13.19", 212 | "browser-request": "0.3.3", 213 | "request": "2.88.0" 214 | } 215 | }, 216 | "bitcore-lib": { 217 | "version": "0.13.19", 218 | "resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-0.13.19.tgz", 219 | "integrity": "sha1-SK8em9oQBnwasWJjRyta3SAA89w=", 220 | "requires": { 221 | "bn.js": "2.0.4", 222 | "bs58": "2.0.0", 223 | "buffer-compare": "1.0.0", 224 | "elliptic": "3.0.3", 225 | "inherits": "2.0.1", 226 | "lodash": "3.10.1" 227 | }, 228 | "dependencies": { 229 | "bn.js": { 230 | "version": "2.0.4", 231 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-2.0.4.tgz", 232 | "integrity": "sha1-Igp81nf38b+pNif/QZN3b+eBlIA=" 233 | }, 234 | "bs58": { 235 | "version": "2.0.0", 236 | "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.0.tgz", 237 | "integrity": "sha1-crcTvtIjoKxRi72g484/SBfznrU=" 238 | }, 239 | "buffer-compare": { 240 | "version": "1.0.0", 241 | "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.0.0.tgz", 242 | "integrity": "sha1-rKp6lm6Y7un64Usxw5pfFY+zxKI=" 243 | }, 244 | "elliptic": { 245 | "version": "3.0.3", 246 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-3.0.3.tgz", 247 | "integrity": "sha1-hlybQgv75VAGuflp+XoNLESWZZU=", 248 | "requires": { 249 | "bn.js": "2.0.4", 250 | "brorand": "1.0.5", 251 | "hash.js": "1.0.3", 252 | "inherits": "2.0.1" 253 | }, 254 | "dependencies": { 255 | "brorand": { 256 | "version": "1.0.5", 257 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz", 258 | "integrity": "sha1-B7VMowKGq9Fxig4qgwgD79yb+gQ=" 259 | }, 260 | "hash.js": { 261 | "version": "1.0.3", 262 | "resolved": "http://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz", 263 | "integrity": "sha1-EzL/ABVsCg/92CNgE9B7d6BFFXM=", 264 | "requires": { 265 | "inherits": "2.0.1" 266 | } 267 | } 268 | } 269 | }, 270 | "inherits": { 271 | "version": "2.0.1", 272 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 273 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 274 | }, 275 | "lodash": { 276 | "version": "3.10.1", 277 | "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", 278 | "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" 279 | } 280 | } 281 | }, 282 | "bn.js": { 283 | "version": "4.11.8", 284 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", 285 | "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" 286 | }, 287 | "boxen": { 288 | "version": "1.3.0", 289 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", 290 | "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", 291 | "requires": { 292 | "ansi-align": "2.0.0", 293 | "camelcase": "4.1.0", 294 | "chalk": "2.4.1", 295 | "cli-boxes": "1.0.0", 296 | "string-width": "2.1.1", 297 | "term-size": "1.2.0", 298 | "widest-line": "2.0.1" 299 | } 300 | }, 301 | "brace-expansion": { 302 | "version": "1.1.11", 303 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 304 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 305 | "requires": { 306 | "balanced-match": "1.0.0", 307 | "concat-map": "0.0.1" 308 | } 309 | }, 310 | "braces": { 311 | "version": "2.3.2", 312 | "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", 313 | "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", 314 | "requires": { 315 | "arr-flatten": "1.1.0", 316 | "array-unique": "0.3.2", 317 | "extend-shallow": "2.0.1", 318 | "fill-range": "4.0.0", 319 | "isobject": "3.0.1", 320 | "repeat-element": "1.1.3", 321 | "snapdragon": "0.8.2", 322 | "snapdragon-node": "2.1.1", 323 | "split-string": "3.1.0", 324 | "to-regex": "3.0.2" 325 | }, 326 | "dependencies": { 327 | "extend-shallow": { 328 | "version": "2.0.1", 329 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 330 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 331 | "requires": { 332 | "is-extendable": "0.1.1" 333 | } 334 | } 335 | } 336 | }, 337 | "brorand": { 338 | "version": "1.1.0", 339 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", 340 | "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" 341 | }, 342 | "browser-request": { 343 | "version": "0.3.3", 344 | "resolved": "https://registry.npmjs.org/browser-request/-/browser-request-0.3.3.tgz", 345 | "integrity": "sha1-ns5bWsqJopkyJC4Yv5M975h2zBc=" 346 | }, 347 | "browser-stdout": { 348 | "version": "1.3.1", 349 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 350 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" 351 | }, 352 | "bs58": { 353 | "version": "4.0.1", 354 | "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", 355 | "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", 356 | "requires": { 357 | "base-x": "3.0.5" 358 | } 359 | }, 360 | "bsv": { 361 | "version": "0.20.3", 362 | "resolved": "https://registry.npmjs.org/bsv/-/bsv-0.20.3.tgz", 363 | "integrity": "sha512-emfNiQIfL0tF8FDGGH6vH+pdl8pl0pyn6Ix0u43FU6pAdiMy2ImdqeiwMjq8X0MHHXqTbLhNsd1OaqpQLZl/nA==", 364 | "requires": { 365 | "bn.js": "4.11.8", 366 | "bs58": "4.0.1", 367 | "buffer-compare": "1.1.1", 368 | "elliptic": "6.4.0", 369 | "inherits": "2.0.1", 370 | "lodash": "4.17.11" 371 | }, 372 | "dependencies": { 373 | "lodash": { 374 | "version": "4.17.11", 375 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", 376 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" 377 | } 378 | } 379 | }, 380 | "buffer-compare": { 381 | "version": "1.1.1", 382 | "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz", 383 | "integrity": "sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY=" 384 | }, 385 | "cache-base": { 386 | "version": "1.0.1", 387 | "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", 388 | "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", 389 | "requires": { 390 | "collection-visit": "1.0.0", 391 | "component-emitter": "1.2.1", 392 | "get-value": "2.0.6", 393 | "has-value": "1.0.0", 394 | "isobject": "3.0.1", 395 | "set-value": "2.0.0", 396 | "to-object-path": "0.3.0", 397 | "union-value": "1.0.0", 398 | "unset-value": "1.0.0" 399 | } 400 | }, 401 | "camelcase": { 402 | "version": "4.1.0", 403 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", 404 | "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" 405 | }, 406 | "capture-stack-trace": { 407 | "version": "1.0.1", 408 | "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", 409 | "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==" 410 | }, 411 | "caseless": { 412 | "version": "0.12.0", 413 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 414 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 415 | }, 416 | "chalk": { 417 | "version": "2.4.1", 418 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 419 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 420 | "requires": { 421 | "ansi-styles": "3.2.1", 422 | "escape-string-regexp": "1.0.5", 423 | "supports-color": "5.5.0" 424 | } 425 | }, 426 | "chokidar": { 427 | "version": "2.0.4", 428 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", 429 | "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", 430 | "requires": { 431 | "anymatch": "2.0.0", 432 | "async-each": "1.0.1", 433 | "braces": "2.3.2", 434 | "fsevents": "1.2.4", 435 | "glob-parent": "3.1.0", 436 | "inherits": "2.0.1", 437 | "is-binary-path": "1.0.1", 438 | "is-glob": "4.0.0", 439 | "lodash.debounce": "4.0.8", 440 | "normalize-path": "2.1.1", 441 | "path-is-absolute": "1.0.1", 442 | "readdirp": "2.2.1", 443 | "upath": "1.1.0" 444 | } 445 | }, 446 | "ci-info": { 447 | "version": "1.6.0", 448 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", 449 | "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==" 450 | }, 451 | "class-utils": { 452 | "version": "0.3.6", 453 | "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", 454 | "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", 455 | "requires": { 456 | "arr-union": "3.1.0", 457 | "define-property": "0.2.5", 458 | "isobject": "3.0.1", 459 | "static-extend": "0.1.2" 460 | }, 461 | "dependencies": { 462 | "define-property": { 463 | "version": "0.2.5", 464 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 465 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 466 | "requires": { 467 | "is-descriptor": "0.1.6" 468 | } 469 | } 470 | } 471 | }, 472 | "cli-boxes": { 473 | "version": "1.0.0", 474 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", 475 | "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" 476 | }, 477 | "collection-visit": { 478 | "version": "1.0.0", 479 | "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", 480 | "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", 481 | "requires": { 482 | "map-visit": "1.0.0", 483 | "object-visit": "1.0.1" 484 | } 485 | }, 486 | "color-convert": { 487 | "version": "1.9.3", 488 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 489 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 490 | "requires": { 491 | "color-name": "1.1.3" 492 | } 493 | }, 494 | "color-name": { 495 | "version": "1.1.3", 496 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 497 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 498 | }, 499 | "combined-stream": { 500 | "version": "1.0.7", 501 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", 502 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", 503 | "requires": { 504 | "delayed-stream": "1.0.0" 505 | } 506 | }, 507 | "commander": { 508 | "version": "2.15.1", 509 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", 510 | "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" 511 | }, 512 | "component-emitter": { 513 | "version": "1.2.1", 514 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 515 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 516 | }, 517 | "concat-map": { 518 | "version": "0.0.1", 519 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 520 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 521 | }, 522 | "configstore": { 523 | "version": "3.1.2", 524 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", 525 | "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", 526 | "requires": { 527 | "dot-prop": "4.2.0", 528 | "graceful-fs": "4.1.15", 529 | "make-dir": "1.3.0", 530 | "unique-string": "1.0.0", 531 | "write-file-atomic": "2.3.0", 532 | "xdg-basedir": "3.0.0" 533 | } 534 | }, 535 | "copy-descriptor": { 536 | "version": "0.1.1", 537 | "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", 538 | "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" 539 | }, 540 | "core-util-is": { 541 | "version": "1.0.2", 542 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 543 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 544 | }, 545 | "create-error-class": { 546 | "version": "3.0.2", 547 | "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", 548 | "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", 549 | "requires": { 550 | "capture-stack-trace": "1.0.1" 551 | } 552 | }, 553 | "cross-spawn": { 554 | "version": "5.1.0", 555 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 556 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", 557 | "requires": { 558 | "lru-cache": "4.1.5", 559 | "shebang-command": "1.2.0", 560 | "which": "1.3.1" 561 | } 562 | }, 563 | "crypto-random-string": { 564 | "version": "1.0.0", 565 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", 566 | "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" 567 | }, 568 | "dashdash": { 569 | "version": "1.14.1", 570 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 571 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 572 | "requires": { 573 | "assert-plus": "1.0.0" 574 | } 575 | }, 576 | "datapay": { 577 | "version": "0.0.3", 578 | "resolved": "https://registry.npmjs.org/datapay/-/datapay-0.0.3.tgz", 579 | "integrity": "sha512-++1foKR9Wkf+0w3jr47KXKQeDB4ZNB/EsPmpWACfV0iAeooTjxjjddoP32cTxJn92Y4JHZIPaBFUhbWoQTeSxw==", 580 | "requires": { 581 | "bitcore-explorers": "1.0.1", 582 | "bsv": "0.20.3", 583 | "mingo": "2.2.8" 584 | } 585 | }, 586 | "debug": { 587 | "version": "3.2.6", 588 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 589 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 590 | "requires": { 591 | "ms": "2.1.1" 592 | }, 593 | "dependencies": { 594 | "ms": { 595 | "version": "2.1.1", 596 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 597 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 598 | } 599 | } 600 | }, 601 | "decode-uri-component": { 602 | "version": "0.2.0", 603 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", 604 | "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" 605 | }, 606 | "deep-extend": { 607 | "version": "0.6.0", 608 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 609 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" 610 | }, 611 | "define-property": { 612 | "version": "2.0.2", 613 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", 614 | "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", 615 | "requires": { 616 | "is-descriptor": "1.0.2", 617 | "isobject": "3.0.1" 618 | }, 619 | "dependencies": { 620 | "is-accessor-descriptor": { 621 | "version": "1.0.0", 622 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 623 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 624 | "requires": { 625 | "kind-of": "6.0.2" 626 | } 627 | }, 628 | "is-data-descriptor": { 629 | "version": "1.0.0", 630 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 631 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 632 | "requires": { 633 | "kind-of": "6.0.2" 634 | } 635 | }, 636 | "is-descriptor": { 637 | "version": "1.0.2", 638 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 639 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 640 | "requires": { 641 | "is-accessor-descriptor": "1.0.0", 642 | "is-data-descriptor": "1.0.0", 643 | "kind-of": "6.0.2" 644 | } 645 | } 646 | } 647 | }, 648 | "delayed-stream": { 649 | "version": "1.0.0", 650 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 651 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 652 | }, 653 | "diff": { 654 | "version": "3.5.0", 655 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 656 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" 657 | }, 658 | "dot-prop": { 659 | "version": "4.2.0", 660 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", 661 | "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", 662 | "requires": { 663 | "is-obj": "1.0.1" 664 | } 665 | }, 666 | "double-ended-queue": { 667 | "version": "2.1.0-0", 668 | "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", 669 | "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" 670 | }, 671 | "duplexer3": { 672 | "version": "0.1.4", 673 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 674 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" 675 | }, 676 | "ecc-jsbn": { 677 | "version": "0.1.2", 678 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 679 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 680 | "requires": { 681 | "jsbn": "0.1.1", 682 | "safer-buffer": "2.1.2" 683 | } 684 | }, 685 | "elliptic": { 686 | "version": "6.4.0", 687 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", 688 | "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", 689 | "requires": { 690 | "bn.js": "4.11.8", 691 | "brorand": "1.1.0", 692 | "hash.js": "1.1.7", 693 | "hmac-drbg": "1.0.1", 694 | "inherits": "2.0.1", 695 | "minimalistic-assert": "1.0.1", 696 | "minimalistic-crypto-utils": "1.0.1" 697 | } 698 | }, 699 | "escape-string-regexp": { 700 | "version": "1.0.5", 701 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 702 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 703 | }, 704 | "eventemitter3": { 705 | "version": "2.0.3", 706 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", 707 | "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=" 708 | }, 709 | "eventsource": { 710 | "version": "1.0.7", 711 | "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", 712 | "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", 713 | "requires": { 714 | "original": "1.0.2" 715 | } 716 | }, 717 | "execa": { 718 | "version": "0.7.0", 719 | "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", 720 | "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", 721 | "requires": { 722 | "cross-spawn": "5.1.0", 723 | "get-stream": "3.0.0", 724 | "is-stream": "1.1.0", 725 | "npm-run-path": "2.0.2", 726 | "p-finally": "1.0.0", 727 | "signal-exit": "3.0.2", 728 | "strip-eof": "1.0.0" 729 | } 730 | }, 731 | "expand-brackets": { 732 | "version": "2.1.4", 733 | "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", 734 | "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", 735 | "requires": { 736 | "debug": "2.6.9", 737 | "define-property": "0.2.5", 738 | "extend-shallow": "2.0.1", 739 | "posix-character-classes": "0.1.1", 740 | "regex-not": "1.0.2", 741 | "snapdragon": "0.8.2", 742 | "to-regex": "3.0.2" 743 | }, 744 | "dependencies": { 745 | "debug": { 746 | "version": "2.6.9", 747 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 748 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 749 | "requires": { 750 | "ms": "2.0.0" 751 | } 752 | }, 753 | "define-property": { 754 | "version": "0.2.5", 755 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 756 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 757 | "requires": { 758 | "is-descriptor": "0.1.6" 759 | } 760 | }, 761 | "extend-shallow": { 762 | "version": "2.0.1", 763 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 764 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 765 | "requires": { 766 | "is-extendable": "0.1.1" 767 | } 768 | } 769 | } 770 | }, 771 | "extend": { 772 | "version": "3.0.2", 773 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 774 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 775 | }, 776 | "extend-shallow": { 777 | "version": "3.0.2", 778 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", 779 | "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", 780 | "requires": { 781 | "assign-symbols": "1.0.0", 782 | "is-extendable": "1.0.1" 783 | }, 784 | "dependencies": { 785 | "is-extendable": { 786 | "version": "1.0.1", 787 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", 788 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", 789 | "requires": { 790 | "is-plain-object": "2.0.4" 791 | } 792 | } 793 | } 794 | }, 795 | "extendible": { 796 | "version": "0.1.1", 797 | "resolved": "https://registry.npmjs.org/extendible/-/extendible-0.1.1.tgz", 798 | "integrity": "sha1-4qN+2HEp+0+VM+io11BiMKU5yQU=" 799 | }, 800 | "extglob": { 801 | "version": "2.0.4", 802 | "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", 803 | "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", 804 | "requires": { 805 | "array-unique": "0.3.2", 806 | "define-property": "1.0.0", 807 | "expand-brackets": "2.1.4", 808 | "extend-shallow": "2.0.1", 809 | "fragment-cache": "0.2.1", 810 | "regex-not": "1.0.2", 811 | "snapdragon": "0.8.2", 812 | "to-regex": "3.0.2" 813 | }, 814 | "dependencies": { 815 | "define-property": { 816 | "version": "1.0.0", 817 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 818 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 819 | "requires": { 820 | "is-descriptor": "1.0.2" 821 | } 822 | }, 823 | "extend-shallow": { 824 | "version": "2.0.1", 825 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 826 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 827 | "requires": { 828 | "is-extendable": "0.1.1" 829 | } 830 | }, 831 | "is-accessor-descriptor": { 832 | "version": "1.0.0", 833 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 834 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 835 | "requires": { 836 | "kind-of": "6.0.2" 837 | } 838 | }, 839 | "is-data-descriptor": { 840 | "version": "1.0.0", 841 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 842 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 843 | "requires": { 844 | "kind-of": "6.0.2" 845 | } 846 | }, 847 | "is-descriptor": { 848 | "version": "1.0.2", 849 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 850 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 851 | "requires": { 852 | "is-accessor-descriptor": "1.0.0", 853 | "is-data-descriptor": "1.0.0", 854 | "kind-of": "6.0.2" 855 | } 856 | } 857 | } 858 | }, 859 | "extsprintf": { 860 | "version": "1.3.0", 861 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 862 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 863 | }, 864 | "failure": { 865 | "version": "1.1.1", 866 | "resolved": "https://registry.npmjs.org/failure/-/failure-1.1.1.tgz", 867 | "integrity": "sha1-qOg9OxYC0kaL/2rU2QceAQO4Goc=" 868 | }, 869 | "fast-deep-equal": { 870 | "version": "2.0.1", 871 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 872 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" 873 | }, 874 | "fast-json-stable-stringify": { 875 | "version": "2.0.0", 876 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 877 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 878 | }, 879 | "fill-range": { 880 | "version": "4.0.0", 881 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", 882 | "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", 883 | "requires": { 884 | "extend-shallow": "2.0.1", 885 | "is-number": "3.0.0", 886 | "repeat-string": "1.6.1", 887 | "to-regex-range": "2.1.1" 888 | }, 889 | "dependencies": { 890 | "extend-shallow": { 891 | "version": "2.0.1", 892 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 893 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 894 | "requires": { 895 | "is-extendable": "0.1.1" 896 | } 897 | } 898 | } 899 | }, 900 | "follow-redirects": { 901 | "version": "1.6.1", 902 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", 903 | "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", 904 | "requires": { 905 | "debug": "3.1.0" 906 | }, 907 | "dependencies": { 908 | "debug": { 909 | "version": "3.1.0", 910 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 911 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 912 | "requires": { 913 | "ms": "2.0.0" 914 | } 915 | } 916 | } 917 | }, 918 | "for-in": { 919 | "version": "1.0.2", 920 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", 921 | "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" 922 | }, 923 | "forever-agent": { 924 | "version": "0.6.1", 925 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 926 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 927 | }, 928 | "form-data": { 929 | "version": "2.3.3", 930 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 931 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 932 | "requires": { 933 | "asynckit": "0.4.0", 934 | "combined-stream": "1.0.7", 935 | "mime-types": "2.1.21" 936 | } 937 | }, 938 | "fragment-cache": { 939 | "version": "0.2.1", 940 | "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", 941 | "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", 942 | "requires": { 943 | "map-cache": "0.2.2" 944 | } 945 | }, 946 | "fs.realpath": { 947 | "version": "1.0.0", 948 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 949 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 950 | }, 951 | "fsevents": { 952 | "version": "1.2.4", 953 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", 954 | "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", 955 | "optional": true, 956 | "requires": { 957 | "nan": "2.12.1", 958 | "node-pre-gyp": "0.10.0" 959 | }, 960 | "dependencies": { 961 | "abbrev": { 962 | "version": "1.1.1", 963 | "bundled": true, 964 | "optional": true 965 | }, 966 | "ansi-regex": { 967 | "version": "2.1.1", 968 | "bundled": true 969 | }, 970 | "aproba": { 971 | "version": "1.2.0", 972 | "bundled": true, 973 | "optional": true 974 | }, 975 | "are-we-there-yet": { 976 | "version": "1.1.4", 977 | "bundled": true, 978 | "optional": true, 979 | "requires": { 980 | "delegates": "1.0.0", 981 | "readable-stream": "2.3.6" 982 | } 983 | }, 984 | "balanced-match": { 985 | "version": "1.0.0", 986 | "bundled": true 987 | }, 988 | "brace-expansion": { 989 | "version": "1.1.11", 990 | "bundled": true, 991 | "requires": { 992 | "balanced-match": "1.0.0", 993 | "concat-map": "0.0.1" 994 | } 995 | }, 996 | "chownr": { 997 | "version": "1.0.1", 998 | "bundled": true, 999 | "optional": true 1000 | }, 1001 | "code-point-at": { 1002 | "version": "1.1.0", 1003 | "bundled": true 1004 | }, 1005 | "concat-map": { 1006 | "version": "0.0.1", 1007 | "bundled": true 1008 | }, 1009 | "console-control-strings": { 1010 | "version": "1.1.0", 1011 | "bundled": true 1012 | }, 1013 | "core-util-is": { 1014 | "version": "1.0.2", 1015 | "bundled": true, 1016 | "optional": true 1017 | }, 1018 | "debug": { 1019 | "version": "2.6.9", 1020 | "bundled": true, 1021 | "optional": true, 1022 | "requires": { 1023 | "ms": "2.0.0" 1024 | } 1025 | }, 1026 | "deep-extend": { 1027 | "version": "0.5.1", 1028 | "bundled": true, 1029 | "optional": true 1030 | }, 1031 | "delegates": { 1032 | "version": "1.0.0", 1033 | "bundled": true, 1034 | "optional": true 1035 | }, 1036 | "detect-libc": { 1037 | "version": "1.0.3", 1038 | "bundled": true, 1039 | "optional": true 1040 | }, 1041 | "fs-minipass": { 1042 | "version": "1.2.5", 1043 | "bundled": true, 1044 | "optional": true, 1045 | "requires": { 1046 | "minipass": "2.2.4" 1047 | } 1048 | }, 1049 | "fs.realpath": { 1050 | "version": "1.0.0", 1051 | "bundled": true, 1052 | "optional": true 1053 | }, 1054 | "gauge": { 1055 | "version": "2.7.4", 1056 | "bundled": true, 1057 | "optional": true, 1058 | "requires": { 1059 | "aproba": "1.2.0", 1060 | "console-control-strings": "1.1.0", 1061 | "has-unicode": "2.0.1", 1062 | "object-assign": "4.1.1", 1063 | "signal-exit": "3.0.2", 1064 | "string-width": "1.0.2", 1065 | "strip-ansi": "3.0.1", 1066 | "wide-align": "1.1.2" 1067 | } 1068 | }, 1069 | "glob": { 1070 | "version": "7.1.2", 1071 | "bundled": true, 1072 | "optional": true, 1073 | "requires": { 1074 | "fs.realpath": "1.0.0", 1075 | "inflight": "1.0.6", 1076 | "inherits": "2.0.3", 1077 | "minimatch": "3.0.4", 1078 | "once": "1.4.0", 1079 | "path-is-absolute": "1.0.1" 1080 | } 1081 | }, 1082 | "has-unicode": { 1083 | "version": "2.0.1", 1084 | "bundled": true, 1085 | "optional": true 1086 | }, 1087 | "iconv-lite": { 1088 | "version": "0.4.21", 1089 | "bundled": true, 1090 | "optional": true, 1091 | "requires": { 1092 | "safer-buffer": "2.1.2" 1093 | } 1094 | }, 1095 | "ignore-walk": { 1096 | "version": "3.0.1", 1097 | "bundled": true, 1098 | "optional": true, 1099 | "requires": { 1100 | "minimatch": "3.0.4" 1101 | } 1102 | }, 1103 | "inflight": { 1104 | "version": "1.0.6", 1105 | "bundled": true, 1106 | "optional": true, 1107 | "requires": { 1108 | "once": "1.4.0", 1109 | "wrappy": "1.0.2" 1110 | } 1111 | }, 1112 | "inherits": { 1113 | "version": "2.0.3", 1114 | "bundled": true 1115 | }, 1116 | "ini": { 1117 | "version": "1.3.5", 1118 | "bundled": true, 1119 | "optional": true 1120 | }, 1121 | "is-fullwidth-code-point": { 1122 | "version": "1.0.0", 1123 | "bundled": true, 1124 | "requires": { 1125 | "number-is-nan": "1.0.1" 1126 | } 1127 | }, 1128 | "isarray": { 1129 | "version": "1.0.0", 1130 | "bundled": true, 1131 | "optional": true 1132 | }, 1133 | "minimatch": { 1134 | "version": "3.0.4", 1135 | "bundled": true, 1136 | "requires": { 1137 | "brace-expansion": "1.1.11" 1138 | } 1139 | }, 1140 | "minimist": { 1141 | "version": "0.0.8", 1142 | "bundled": true 1143 | }, 1144 | "minipass": { 1145 | "version": "2.2.4", 1146 | "bundled": true, 1147 | "requires": { 1148 | "safe-buffer": "5.1.1", 1149 | "yallist": "3.0.2" 1150 | } 1151 | }, 1152 | "minizlib": { 1153 | "version": "1.1.0", 1154 | "bundled": true, 1155 | "optional": true, 1156 | "requires": { 1157 | "minipass": "2.2.4" 1158 | } 1159 | }, 1160 | "mkdirp": { 1161 | "version": "0.5.1", 1162 | "bundled": true, 1163 | "requires": { 1164 | "minimist": "0.0.8" 1165 | } 1166 | }, 1167 | "ms": { 1168 | "version": "2.0.0", 1169 | "bundled": true, 1170 | "optional": true 1171 | }, 1172 | "needle": { 1173 | "version": "2.2.0", 1174 | "bundled": true, 1175 | "optional": true, 1176 | "requires": { 1177 | "debug": "2.6.9", 1178 | "iconv-lite": "0.4.21", 1179 | "sax": "1.2.4" 1180 | } 1181 | }, 1182 | "node-pre-gyp": { 1183 | "version": "0.10.0", 1184 | "bundled": true, 1185 | "optional": true, 1186 | "requires": { 1187 | "detect-libc": "1.0.3", 1188 | "mkdirp": "0.5.1", 1189 | "needle": "2.2.0", 1190 | "nopt": "4.0.1", 1191 | "npm-packlist": "1.1.10", 1192 | "npmlog": "4.1.2", 1193 | "rc": "1.2.7", 1194 | "rimraf": "2.6.2", 1195 | "semver": "5.5.0", 1196 | "tar": "4.4.1" 1197 | } 1198 | }, 1199 | "nopt": { 1200 | "version": "4.0.1", 1201 | "bundled": true, 1202 | "optional": true, 1203 | "requires": { 1204 | "abbrev": "1.1.1", 1205 | "osenv": "0.1.5" 1206 | } 1207 | }, 1208 | "npm-bundled": { 1209 | "version": "1.0.3", 1210 | "bundled": true, 1211 | "optional": true 1212 | }, 1213 | "npm-packlist": { 1214 | "version": "1.1.10", 1215 | "bundled": true, 1216 | "optional": true, 1217 | "requires": { 1218 | "ignore-walk": "3.0.1", 1219 | "npm-bundled": "1.0.3" 1220 | } 1221 | }, 1222 | "npmlog": { 1223 | "version": "4.1.2", 1224 | "bundled": true, 1225 | "optional": true, 1226 | "requires": { 1227 | "are-we-there-yet": "1.1.4", 1228 | "console-control-strings": "1.1.0", 1229 | "gauge": "2.7.4", 1230 | "set-blocking": "2.0.0" 1231 | } 1232 | }, 1233 | "number-is-nan": { 1234 | "version": "1.0.1", 1235 | "bundled": true 1236 | }, 1237 | "object-assign": { 1238 | "version": "4.1.1", 1239 | "bundled": true, 1240 | "optional": true 1241 | }, 1242 | "once": { 1243 | "version": "1.4.0", 1244 | "bundled": true, 1245 | "requires": { 1246 | "wrappy": "1.0.2" 1247 | } 1248 | }, 1249 | "os-homedir": { 1250 | "version": "1.0.2", 1251 | "bundled": true, 1252 | "optional": true 1253 | }, 1254 | "os-tmpdir": { 1255 | "version": "1.0.2", 1256 | "bundled": true, 1257 | "optional": true 1258 | }, 1259 | "osenv": { 1260 | "version": "0.1.5", 1261 | "bundled": true, 1262 | "optional": true, 1263 | "requires": { 1264 | "os-homedir": "1.0.2", 1265 | "os-tmpdir": "1.0.2" 1266 | } 1267 | }, 1268 | "path-is-absolute": { 1269 | "version": "1.0.1", 1270 | "bundled": true, 1271 | "optional": true 1272 | }, 1273 | "process-nextick-args": { 1274 | "version": "2.0.0", 1275 | "bundled": true, 1276 | "optional": true 1277 | }, 1278 | "rc": { 1279 | "version": "1.2.7", 1280 | "bundled": true, 1281 | "optional": true, 1282 | "requires": { 1283 | "deep-extend": "0.5.1", 1284 | "ini": "1.3.5", 1285 | "minimist": "1.2.0", 1286 | "strip-json-comments": "2.0.1" 1287 | }, 1288 | "dependencies": { 1289 | "minimist": { 1290 | "version": "1.2.0", 1291 | "bundled": true, 1292 | "optional": true 1293 | } 1294 | } 1295 | }, 1296 | "readable-stream": { 1297 | "version": "2.3.6", 1298 | "bundled": true, 1299 | "optional": true, 1300 | "requires": { 1301 | "core-util-is": "1.0.2", 1302 | "inherits": "2.0.3", 1303 | "isarray": "1.0.0", 1304 | "process-nextick-args": "2.0.0", 1305 | "safe-buffer": "5.1.1", 1306 | "string_decoder": "1.1.1", 1307 | "util-deprecate": "1.0.2" 1308 | } 1309 | }, 1310 | "rimraf": { 1311 | "version": "2.6.2", 1312 | "bundled": true, 1313 | "optional": true, 1314 | "requires": { 1315 | "glob": "7.1.2" 1316 | } 1317 | }, 1318 | "safe-buffer": { 1319 | "version": "5.1.1", 1320 | "bundled": true 1321 | }, 1322 | "safer-buffer": { 1323 | "version": "2.1.2", 1324 | "bundled": true, 1325 | "optional": true 1326 | }, 1327 | "sax": { 1328 | "version": "1.2.4", 1329 | "bundled": true, 1330 | "optional": true 1331 | }, 1332 | "semver": { 1333 | "version": "5.5.0", 1334 | "bundled": true, 1335 | "optional": true 1336 | }, 1337 | "set-blocking": { 1338 | "version": "2.0.0", 1339 | "bundled": true, 1340 | "optional": true 1341 | }, 1342 | "signal-exit": { 1343 | "version": "3.0.2", 1344 | "bundled": true, 1345 | "optional": true 1346 | }, 1347 | "string-width": { 1348 | "version": "1.0.2", 1349 | "bundled": true, 1350 | "requires": { 1351 | "code-point-at": "1.1.0", 1352 | "is-fullwidth-code-point": "1.0.0", 1353 | "strip-ansi": "3.0.1" 1354 | } 1355 | }, 1356 | "string_decoder": { 1357 | "version": "1.1.1", 1358 | "bundled": true, 1359 | "optional": true, 1360 | "requires": { 1361 | "safe-buffer": "5.1.1" 1362 | } 1363 | }, 1364 | "strip-ansi": { 1365 | "version": "3.0.1", 1366 | "bundled": true, 1367 | "requires": { 1368 | "ansi-regex": "2.1.1" 1369 | } 1370 | }, 1371 | "strip-json-comments": { 1372 | "version": "2.0.1", 1373 | "bundled": true, 1374 | "optional": true 1375 | }, 1376 | "tar": { 1377 | "version": "4.4.1", 1378 | "bundled": true, 1379 | "optional": true, 1380 | "requires": { 1381 | "chownr": "1.0.1", 1382 | "fs-minipass": "1.2.5", 1383 | "minipass": "2.2.4", 1384 | "minizlib": "1.1.0", 1385 | "mkdirp": "0.5.1", 1386 | "safe-buffer": "5.1.1", 1387 | "yallist": "3.0.2" 1388 | } 1389 | }, 1390 | "util-deprecate": { 1391 | "version": "1.0.2", 1392 | "bundled": true, 1393 | "optional": true 1394 | }, 1395 | "wide-align": { 1396 | "version": "1.1.2", 1397 | "bundled": true, 1398 | "optional": true, 1399 | "requires": { 1400 | "string-width": "1.0.2" 1401 | } 1402 | }, 1403 | "wrappy": { 1404 | "version": "1.0.2", 1405 | "bundled": true 1406 | }, 1407 | "yallist": { 1408 | "version": "3.0.2", 1409 | "bundled": true 1410 | } 1411 | } 1412 | }, 1413 | "get-stream": { 1414 | "version": "3.0.0", 1415 | "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 1416 | "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" 1417 | }, 1418 | "get-value": { 1419 | "version": "2.0.6", 1420 | "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", 1421 | "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" 1422 | }, 1423 | "getpass": { 1424 | "version": "0.1.7", 1425 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 1426 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 1427 | "requires": { 1428 | "assert-plus": "1.0.0" 1429 | } 1430 | }, 1431 | "glob": { 1432 | "version": "7.1.2", 1433 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 1434 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 1435 | "requires": { 1436 | "fs.realpath": "1.0.0", 1437 | "inflight": "1.0.6", 1438 | "inherits": "2.0.1", 1439 | "minimatch": "3.0.4", 1440 | "once": "1.4.0", 1441 | "path-is-absolute": "1.0.1" 1442 | } 1443 | }, 1444 | "glob-parent": { 1445 | "version": "3.1.0", 1446 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", 1447 | "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", 1448 | "requires": { 1449 | "is-glob": "3.1.0", 1450 | "path-dirname": "1.0.2" 1451 | }, 1452 | "dependencies": { 1453 | "is-glob": { 1454 | "version": "3.1.0", 1455 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", 1456 | "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", 1457 | "requires": { 1458 | "is-extglob": "2.1.1" 1459 | } 1460 | } 1461 | } 1462 | }, 1463 | "global-dirs": { 1464 | "version": "0.1.1", 1465 | "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", 1466 | "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", 1467 | "requires": { 1468 | "ini": "1.3.5" 1469 | } 1470 | }, 1471 | "got": { 1472 | "version": "6.7.1", 1473 | "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", 1474 | "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", 1475 | "requires": { 1476 | "create-error-class": "3.0.2", 1477 | "duplexer3": "0.1.4", 1478 | "get-stream": "3.0.0", 1479 | "is-redirect": "1.0.0", 1480 | "is-retry-allowed": "1.1.0", 1481 | "is-stream": "1.1.0", 1482 | "lowercase-keys": "1.0.1", 1483 | "safe-buffer": "5.1.2", 1484 | "timed-out": "4.0.1", 1485 | "unzip-response": "2.0.1", 1486 | "url-parse-lax": "1.0.0" 1487 | } 1488 | }, 1489 | "graceful-fs": { 1490 | "version": "4.1.15", 1491 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", 1492 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" 1493 | }, 1494 | "growl": { 1495 | "version": "1.10.5", 1496 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 1497 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" 1498 | }, 1499 | "hang": { 1500 | "version": "1.0.0", 1501 | "resolved": "https://registry.npmjs.org/hang/-/hang-1.0.0.tgz", 1502 | "integrity": "sha1-ZwUIeYRENeAq4ECcT0VTxkOOHXE=" 1503 | }, 1504 | "har-schema": { 1505 | "version": "2.0.0", 1506 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 1507 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 1508 | }, 1509 | "har-validator": { 1510 | "version": "5.1.3", 1511 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 1512 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 1513 | "requires": { 1514 | "ajv": "6.6.2", 1515 | "har-schema": "2.0.0" 1516 | } 1517 | }, 1518 | "has-flag": { 1519 | "version": "3.0.0", 1520 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1521 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 1522 | }, 1523 | "has-value": { 1524 | "version": "1.0.0", 1525 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", 1526 | "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", 1527 | "requires": { 1528 | "get-value": "2.0.6", 1529 | "has-values": "1.0.0", 1530 | "isobject": "3.0.1" 1531 | } 1532 | }, 1533 | "has-values": { 1534 | "version": "1.0.0", 1535 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", 1536 | "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", 1537 | "requires": { 1538 | "is-number": "3.0.0", 1539 | "kind-of": "4.0.0" 1540 | }, 1541 | "dependencies": { 1542 | "kind-of": { 1543 | "version": "4.0.0", 1544 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", 1545 | "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", 1546 | "requires": { 1547 | "is-buffer": "1.1.6" 1548 | } 1549 | } 1550 | } 1551 | }, 1552 | "hash.js": { 1553 | "version": "1.1.7", 1554 | "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", 1555 | "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", 1556 | "requires": { 1557 | "inherits": "2.0.3", 1558 | "minimalistic-assert": "1.0.1" 1559 | }, 1560 | "dependencies": { 1561 | "inherits": { 1562 | "version": "2.0.3", 1563 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1564 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 1565 | } 1566 | } 1567 | }, 1568 | "he": { 1569 | "version": "1.1.1", 1570 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", 1571 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" 1572 | }, 1573 | "hmac-drbg": { 1574 | "version": "1.0.1", 1575 | "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", 1576 | "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", 1577 | "requires": { 1578 | "hash.js": "1.1.7", 1579 | "minimalistic-assert": "1.0.1", 1580 | "minimalistic-crypto-utils": "1.0.1" 1581 | } 1582 | }, 1583 | "http-signature": { 1584 | "version": "1.2.0", 1585 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 1586 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 1587 | "requires": { 1588 | "assert-plus": "1.0.0", 1589 | "jsprim": "1.4.1", 1590 | "sshpk": "1.16.0" 1591 | } 1592 | }, 1593 | "ignore-by-default": { 1594 | "version": "1.0.1", 1595 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 1596 | "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" 1597 | }, 1598 | "import-lazy": { 1599 | "version": "2.1.0", 1600 | "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", 1601 | "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" 1602 | }, 1603 | "imurmurhash": { 1604 | "version": "0.1.4", 1605 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1606 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" 1607 | }, 1608 | "inflight": { 1609 | "version": "1.0.6", 1610 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1611 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1612 | "requires": { 1613 | "once": "1.4.0", 1614 | "wrappy": "1.0.2" 1615 | } 1616 | }, 1617 | "inherits": { 1618 | "version": "2.0.1", 1619 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 1620 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 1621 | }, 1622 | "ini": { 1623 | "version": "1.3.5", 1624 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 1625 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" 1626 | }, 1627 | "is-accessor-descriptor": { 1628 | "version": "0.1.6", 1629 | "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", 1630 | "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", 1631 | "requires": { 1632 | "kind-of": "3.2.2" 1633 | }, 1634 | "dependencies": { 1635 | "kind-of": { 1636 | "version": "3.2.2", 1637 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1638 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1639 | "requires": { 1640 | "is-buffer": "1.1.6" 1641 | } 1642 | } 1643 | } 1644 | }, 1645 | "is-binary-path": { 1646 | "version": "1.0.1", 1647 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", 1648 | "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", 1649 | "requires": { 1650 | "binary-extensions": "1.12.0" 1651 | } 1652 | }, 1653 | "is-buffer": { 1654 | "version": "1.1.6", 1655 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 1656 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 1657 | }, 1658 | "is-ci": { 1659 | "version": "1.2.1", 1660 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", 1661 | "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", 1662 | "requires": { 1663 | "ci-info": "1.6.0" 1664 | } 1665 | }, 1666 | "is-data-descriptor": { 1667 | "version": "0.1.4", 1668 | "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", 1669 | "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", 1670 | "requires": { 1671 | "kind-of": "3.2.2" 1672 | }, 1673 | "dependencies": { 1674 | "kind-of": { 1675 | "version": "3.2.2", 1676 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1677 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1678 | "requires": { 1679 | "is-buffer": "1.1.6" 1680 | } 1681 | } 1682 | } 1683 | }, 1684 | "is-descriptor": { 1685 | "version": "0.1.6", 1686 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", 1687 | "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", 1688 | "requires": { 1689 | "is-accessor-descriptor": "0.1.6", 1690 | "is-data-descriptor": "0.1.4", 1691 | "kind-of": "5.1.0" 1692 | }, 1693 | "dependencies": { 1694 | "kind-of": { 1695 | "version": "5.1.0", 1696 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", 1697 | "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" 1698 | } 1699 | } 1700 | }, 1701 | "is-extendable": { 1702 | "version": "0.1.1", 1703 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 1704 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" 1705 | }, 1706 | "is-extglob": { 1707 | "version": "2.1.1", 1708 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1709 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" 1710 | }, 1711 | "is-fullwidth-code-point": { 1712 | "version": "2.0.0", 1713 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1714 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 1715 | }, 1716 | "is-glob": { 1717 | "version": "4.0.0", 1718 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", 1719 | "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", 1720 | "requires": { 1721 | "is-extglob": "2.1.1" 1722 | } 1723 | }, 1724 | "is-installed-globally": { 1725 | "version": "0.1.0", 1726 | "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", 1727 | "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", 1728 | "requires": { 1729 | "global-dirs": "0.1.1", 1730 | "is-path-inside": "1.0.1" 1731 | } 1732 | }, 1733 | "is-npm": { 1734 | "version": "1.0.0", 1735 | "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", 1736 | "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" 1737 | }, 1738 | "is-number": { 1739 | "version": "3.0.0", 1740 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", 1741 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", 1742 | "requires": { 1743 | "kind-of": "3.2.2" 1744 | }, 1745 | "dependencies": { 1746 | "kind-of": { 1747 | "version": "3.2.2", 1748 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1749 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1750 | "requires": { 1751 | "is-buffer": "1.1.6" 1752 | } 1753 | } 1754 | } 1755 | }, 1756 | "is-obj": { 1757 | "version": "1.0.1", 1758 | "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", 1759 | "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" 1760 | }, 1761 | "is-path-inside": { 1762 | "version": "1.0.1", 1763 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", 1764 | "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", 1765 | "requires": { 1766 | "path-is-inside": "1.0.2" 1767 | } 1768 | }, 1769 | "is-plain-object": { 1770 | "version": "2.0.4", 1771 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 1772 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 1773 | "requires": { 1774 | "isobject": "3.0.1" 1775 | } 1776 | }, 1777 | "is-redirect": { 1778 | "version": "1.0.0", 1779 | "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", 1780 | "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" 1781 | }, 1782 | "is-retry-allowed": { 1783 | "version": "1.1.0", 1784 | "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", 1785 | "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" 1786 | }, 1787 | "is-stream": { 1788 | "version": "1.1.0", 1789 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 1790 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 1791 | }, 1792 | "is-typedarray": { 1793 | "version": "1.0.0", 1794 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1795 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 1796 | }, 1797 | "is-windows": { 1798 | "version": "1.0.2", 1799 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", 1800 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" 1801 | }, 1802 | "isarray": { 1803 | "version": "1.0.0", 1804 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1805 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 1806 | }, 1807 | "isexe": { 1808 | "version": "2.0.0", 1809 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1810 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 1811 | }, 1812 | "isobject": { 1813 | "version": "3.0.1", 1814 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1815 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" 1816 | }, 1817 | "isstream": { 1818 | "version": "0.1.2", 1819 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 1820 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 1821 | }, 1822 | "jsbn": { 1823 | "version": "0.1.1", 1824 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1825 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 1826 | }, 1827 | "json-schema": { 1828 | "version": "0.2.3", 1829 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 1830 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 1831 | }, 1832 | "json-schema-traverse": { 1833 | "version": "0.4.1", 1834 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1835 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 1836 | }, 1837 | "json-stringify-safe": { 1838 | "version": "5.0.1", 1839 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1840 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 1841 | }, 1842 | "jsprim": { 1843 | "version": "1.4.1", 1844 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 1845 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 1846 | "requires": { 1847 | "assert-plus": "1.0.0", 1848 | "extsprintf": "1.3.0", 1849 | "json-schema": "0.2.3", 1850 | "verror": "1.10.0" 1851 | } 1852 | }, 1853 | "kind-of": { 1854 | "version": "6.0.2", 1855 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 1856 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" 1857 | }, 1858 | "latest-version": { 1859 | "version": "3.1.0", 1860 | "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", 1861 | "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", 1862 | "requires": { 1863 | "package-json": "4.0.1" 1864 | } 1865 | }, 1866 | "loads": { 1867 | "version": "0.0.4", 1868 | "resolved": "https://registry.npmjs.org/loads/-/loads-0.0.4.tgz", 1869 | "integrity": "sha1-l/MBY5fnDd/0gLgexjjO6iKgqZw=", 1870 | "requires": { 1871 | "failure": "1.1.1", 1872 | "one-time": "0.0.4", 1873 | "xhr-response": "1.0.1", 1874 | "xhr-status": "1.0.1" 1875 | } 1876 | }, 1877 | "lodash.debounce": { 1878 | "version": "4.0.8", 1879 | "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", 1880 | "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" 1881 | }, 1882 | "lowercase-keys": { 1883 | "version": "1.0.1", 1884 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 1885 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" 1886 | }, 1887 | "lru-cache": { 1888 | "version": "4.1.5", 1889 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 1890 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 1891 | "requires": { 1892 | "pseudomap": "1.0.2", 1893 | "yallist": "2.1.2" 1894 | } 1895 | }, 1896 | "make-dir": { 1897 | "version": "1.3.0", 1898 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", 1899 | "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", 1900 | "requires": { 1901 | "pify": "3.0.0" 1902 | } 1903 | }, 1904 | "map-cache": { 1905 | "version": "0.2.2", 1906 | "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", 1907 | "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" 1908 | }, 1909 | "map-visit": { 1910 | "version": "1.0.0", 1911 | "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", 1912 | "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", 1913 | "requires": { 1914 | "object-visit": "1.0.1" 1915 | } 1916 | }, 1917 | "micromatch": { 1918 | "version": "3.1.10", 1919 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", 1920 | "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", 1921 | "requires": { 1922 | "arr-diff": "4.0.0", 1923 | "array-unique": "0.3.2", 1924 | "braces": "2.3.2", 1925 | "define-property": "2.0.2", 1926 | "extend-shallow": "3.0.2", 1927 | "extglob": "2.0.4", 1928 | "fragment-cache": "0.2.1", 1929 | "kind-of": "6.0.2", 1930 | "nanomatch": "1.2.13", 1931 | "object.pick": "1.3.0", 1932 | "regex-not": "1.0.2", 1933 | "snapdragon": "0.8.2", 1934 | "to-regex": "3.0.2" 1935 | } 1936 | }, 1937 | "mime-db": { 1938 | "version": "1.37.0", 1939 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", 1940 | "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" 1941 | }, 1942 | "mime-types": { 1943 | "version": "2.1.21", 1944 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", 1945 | "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", 1946 | "requires": { 1947 | "mime-db": "1.37.0" 1948 | } 1949 | }, 1950 | "mingo": { 1951 | "version": "2.2.8", 1952 | "resolved": "https://registry.npmjs.org/mingo/-/mingo-2.2.8.tgz", 1953 | "integrity": "sha512-61ET/PK45Jm1yWfoiYL/9KBs/+66s4ctLJeMCnKgYJlrD46oqbIVnfm5RbDyqo9Gl19mzUUi4DDvTlMzirzKVw==" 1954 | }, 1955 | "minimalistic-assert": { 1956 | "version": "1.0.1", 1957 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 1958 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" 1959 | }, 1960 | "minimalistic-crypto-utils": { 1961 | "version": "1.0.1", 1962 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 1963 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" 1964 | }, 1965 | "minimatch": { 1966 | "version": "3.0.4", 1967 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1968 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1969 | "requires": { 1970 | "brace-expansion": "1.1.11" 1971 | } 1972 | }, 1973 | "minimist": { 1974 | "version": "1.2.0", 1975 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 1976 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 1977 | }, 1978 | "mixin-deep": { 1979 | "version": "1.3.1", 1980 | "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", 1981 | "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", 1982 | "requires": { 1983 | "for-in": "1.0.2", 1984 | "is-extendable": "1.0.1" 1985 | }, 1986 | "dependencies": { 1987 | "is-extendable": { 1988 | "version": "1.0.1", 1989 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", 1990 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", 1991 | "requires": { 1992 | "is-plain-object": "2.0.4" 1993 | } 1994 | } 1995 | } 1996 | }, 1997 | "mkdirp": { 1998 | "version": "0.5.1", 1999 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 2000 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 2001 | "requires": { 2002 | "minimist": "0.0.8" 2003 | }, 2004 | "dependencies": { 2005 | "minimist": { 2006 | "version": "0.0.8", 2007 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 2008 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 2009 | } 2010 | } 2011 | }, 2012 | "mocha": { 2013 | "version": "5.2.0", 2014 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", 2015 | "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", 2016 | "requires": { 2017 | "browser-stdout": "1.3.1", 2018 | "commander": "2.15.1", 2019 | "debug": "3.1.0", 2020 | "diff": "3.5.0", 2021 | "escape-string-regexp": "1.0.5", 2022 | "glob": "7.1.2", 2023 | "growl": "1.10.5", 2024 | "he": "1.1.1", 2025 | "minimatch": "3.0.4", 2026 | "mkdirp": "0.5.1", 2027 | "supports-color": "5.4.0" 2028 | }, 2029 | "dependencies": { 2030 | "debug": { 2031 | "version": "3.1.0", 2032 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 2033 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 2034 | "requires": { 2035 | "ms": "2.0.0" 2036 | } 2037 | }, 2038 | "supports-color": { 2039 | "version": "5.4.0", 2040 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 2041 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 2042 | "requires": { 2043 | "has-flag": "3.0.0" 2044 | } 2045 | } 2046 | } 2047 | }, 2048 | "ms": { 2049 | "version": "2.0.0", 2050 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2051 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 2052 | }, 2053 | "nan": { 2054 | "version": "2.12.1", 2055 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", 2056 | "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", 2057 | "optional": true 2058 | }, 2059 | "nanomatch": { 2060 | "version": "1.2.13", 2061 | "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", 2062 | "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", 2063 | "requires": { 2064 | "arr-diff": "4.0.0", 2065 | "array-unique": "0.3.2", 2066 | "define-property": "2.0.2", 2067 | "extend-shallow": "3.0.2", 2068 | "fragment-cache": "0.2.1", 2069 | "is-windows": "1.0.2", 2070 | "kind-of": "6.0.2", 2071 | "object.pick": "1.3.0", 2072 | "regex-not": "1.0.2", 2073 | "snapdragon": "0.8.2", 2074 | "to-regex": "3.0.2" 2075 | } 2076 | }, 2077 | "node-http-xhr": { 2078 | "version": "1.3.4", 2079 | "resolved": "https://registry.npmjs.org/node-http-xhr/-/node-http-xhr-1.3.4.tgz", 2080 | "integrity": "sha512-0bA08/2RKWxw6pMkOVd3KP+0F5+ifQLMMTDxrCgxlgkoU1N8DhCbCSAYEqpgaVYM2smvbVVewiXjW+8AyoLfxQ==" 2081 | }, 2082 | "nodemon": { 2083 | "version": "1.18.9", 2084 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.9.tgz", 2085 | "integrity": "sha512-oj/eEVTEI47pzYAjGkpcNw0xYwTl4XSTUQv2NPQI6PpN3b75PhpuYk3Vb3U80xHCyM2Jm+1j68ULHXl4OR3Afw==", 2086 | "requires": { 2087 | "chokidar": "2.0.4", 2088 | "debug": "3.2.6", 2089 | "ignore-by-default": "1.0.1", 2090 | "minimatch": "3.0.4", 2091 | "pstree.remy": "1.1.6", 2092 | "semver": "5.6.0", 2093 | "supports-color": "5.5.0", 2094 | "touch": "3.1.0", 2095 | "undefsafe": "2.0.2", 2096 | "update-notifier": "2.5.0" 2097 | } 2098 | }, 2099 | "nopt": { 2100 | "version": "1.0.10", 2101 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 2102 | "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", 2103 | "requires": { 2104 | "abbrev": "1.1.1" 2105 | } 2106 | }, 2107 | "normalize-path": { 2108 | "version": "2.1.1", 2109 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", 2110 | "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", 2111 | "requires": { 2112 | "remove-trailing-separator": "1.1.0" 2113 | } 2114 | }, 2115 | "npm-run-path": { 2116 | "version": "2.0.2", 2117 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 2118 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 2119 | "requires": { 2120 | "path-key": "2.0.1" 2121 | } 2122 | }, 2123 | "oauth-sign": { 2124 | "version": "0.9.0", 2125 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 2126 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 2127 | }, 2128 | "object-copy": { 2129 | "version": "0.1.0", 2130 | "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", 2131 | "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", 2132 | "requires": { 2133 | "copy-descriptor": "0.1.1", 2134 | "define-property": "0.2.5", 2135 | "kind-of": "3.2.2" 2136 | }, 2137 | "dependencies": { 2138 | "define-property": { 2139 | "version": "0.2.5", 2140 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2141 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2142 | "requires": { 2143 | "is-descriptor": "0.1.6" 2144 | } 2145 | }, 2146 | "kind-of": { 2147 | "version": "3.2.2", 2148 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 2149 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 2150 | "requires": { 2151 | "is-buffer": "1.1.6" 2152 | } 2153 | } 2154 | } 2155 | }, 2156 | "object-visit": { 2157 | "version": "1.0.1", 2158 | "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", 2159 | "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", 2160 | "requires": { 2161 | "isobject": "3.0.1" 2162 | } 2163 | }, 2164 | "object.pick": { 2165 | "version": "1.3.0", 2166 | "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", 2167 | "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", 2168 | "requires": { 2169 | "isobject": "3.0.1" 2170 | } 2171 | }, 2172 | "once": { 2173 | "version": "1.4.0", 2174 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2175 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2176 | "requires": { 2177 | "wrappy": "1.0.2" 2178 | } 2179 | }, 2180 | "one-time": { 2181 | "version": "0.0.4", 2182 | "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", 2183 | "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" 2184 | }, 2185 | "original": { 2186 | "version": "1.0.2", 2187 | "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", 2188 | "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", 2189 | "requires": { 2190 | "url-parse": "1.4.4" 2191 | } 2192 | }, 2193 | "p-finally": { 2194 | "version": "1.0.0", 2195 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 2196 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" 2197 | }, 2198 | "package-json": { 2199 | "version": "4.0.1", 2200 | "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", 2201 | "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", 2202 | "requires": { 2203 | "got": "6.7.1", 2204 | "registry-auth-token": "3.3.2", 2205 | "registry-url": "3.1.0", 2206 | "semver": "5.6.0" 2207 | } 2208 | }, 2209 | "pascalcase": { 2210 | "version": "0.1.1", 2211 | "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", 2212 | "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" 2213 | }, 2214 | "path-dirname": { 2215 | "version": "1.0.2", 2216 | "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", 2217 | "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" 2218 | }, 2219 | "path-is-absolute": { 2220 | "version": "1.0.1", 2221 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2222 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 2223 | }, 2224 | "path-is-inside": { 2225 | "version": "1.0.2", 2226 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 2227 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" 2228 | }, 2229 | "path-key": { 2230 | "version": "2.0.1", 2231 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 2232 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" 2233 | }, 2234 | "performance-now": { 2235 | "version": "2.1.0", 2236 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 2237 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 2238 | }, 2239 | "pify": { 2240 | "version": "3.0.0", 2241 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 2242 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" 2243 | }, 2244 | "posix-character-classes": { 2245 | "version": "0.1.1", 2246 | "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", 2247 | "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" 2248 | }, 2249 | "prepend-http": { 2250 | "version": "1.0.4", 2251 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", 2252 | "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" 2253 | }, 2254 | "process-nextick-args": { 2255 | "version": "2.0.0", 2256 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 2257 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" 2258 | }, 2259 | "pseudomap": { 2260 | "version": "1.0.2", 2261 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 2262 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" 2263 | }, 2264 | "psl": { 2265 | "version": "1.1.31", 2266 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", 2267 | "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" 2268 | }, 2269 | "pstree.remy": { 2270 | "version": "1.1.6", 2271 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.6.tgz", 2272 | "integrity": "sha512-NdF35+QsqD7EgNEI5mkI/X+UwaxVEbQaz9f4IooEmMUv6ZPmlTQYGjBPJGgrlzNdjSvIy4MWMg6Q6vCgBO2K+w==" 2273 | }, 2274 | "punycode": { 2275 | "version": "2.1.1", 2276 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 2277 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 2278 | }, 2279 | "qs": { 2280 | "version": "6.5.2", 2281 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 2282 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 2283 | }, 2284 | "querystringify": { 2285 | "version": "2.1.0", 2286 | "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", 2287 | "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==" 2288 | }, 2289 | "rc": { 2290 | "version": "1.2.8", 2291 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 2292 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 2293 | "requires": { 2294 | "deep-extend": "0.6.0", 2295 | "ini": "1.3.5", 2296 | "minimist": "1.2.0", 2297 | "strip-json-comments": "2.0.1" 2298 | } 2299 | }, 2300 | "readable-stream": { 2301 | "version": "2.3.6", 2302 | "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 2303 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 2304 | "requires": { 2305 | "core-util-is": "1.0.2", 2306 | "inherits": "2.0.3", 2307 | "isarray": "1.0.0", 2308 | "process-nextick-args": "2.0.0", 2309 | "safe-buffer": "5.1.2", 2310 | "string_decoder": "1.1.1", 2311 | "util-deprecate": "1.0.2" 2312 | }, 2313 | "dependencies": { 2314 | "inherits": { 2315 | "version": "2.0.3", 2316 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 2317 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 2318 | } 2319 | } 2320 | }, 2321 | "readdirp": { 2322 | "version": "2.2.1", 2323 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", 2324 | "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", 2325 | "requires": { 2326 | "graceful-fs": "4.1.15", 2327 | "micromatch": "3.1.10", 2328 | "readable-stream": "2.3.6" 2329 | } 2330 | }, 2331 | "redis": { 2332 | "version": "2.8.0", 2333 | "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", 2334 | "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", 2335 | "requires": { 2336 | "double-ended-queue": "2.1.0-0", 2337 | "redis-commands": "1.4.0", 2338 | "redis-parser": "2.6.0" 2339 | } 2340 | }, 2341 | "redis-commands": { 2342 | "version": "1.4.0", 2343 | "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", 2344 | "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==" 2345 | }, 2346 | "redis-parser": { 2347 | "version": "2.6.0", 2348 | "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", 2349 | "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" 2350 | }, 2351 | "regex-not": { 2352 | "version": "1.0.2", 2353 | "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", 2354 | "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", 2355 | "requires": { 2356 | "extend-shallow": "3.0.2", 2357 | "safe-regex": "1.1.0" 2358 | } 2359 | }, 2360 | "registry-auth-token": { 2361 | "version": "3.3.2", 2362 | "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", 2363 | "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", 2364 | "requires": { 2365 | "rc": "1.2.8", 2366 | "safe-buffer": "5.1.2" 2367 | } 2368 | }, 2369 | "registry-url": { 2370 | "version": "3.1.0", 2371 | "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", 2372 | "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", 2373 | "requires": { 2374 | "rc": "1.2.8" 2375 | } 2376 | }, 2377 | "remove-trailing-separator": { 2378 | "version": "1.1.0", 2379 | "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", 2380 | "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" 2381 | }, 2382 | "repeat-element": { 2383 | "version": "1.1.3", 2384 | "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", 2385 | "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" 2386 | }, 2387 | "repeat-string": { 2388 | "version": "1.6.1", 2389 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 2390 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 2391 | }, 2392 | "request": { 2393 | "version": "2.88.0", 2394 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 2395 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 2396 | "requires": { 2397 | "aws-sign2": "0.7.0", 2398 | "aws4": "1.8.0", 2399 | "caseless": "0.12.0", 2400 | "combined-stream": "1.0.7", 2401 | "extend": "3.0.2", 2402 | "forever-agent": "0.6.1", 2403 | "form-data": "2.3.3", 2404 | "har-validator": "5.1.3", 2405 | "http-signature": "1.2.0", 2406 | "is-typedarray": "1.0.0", 2407 | "isstream": "0.1.2", 2408 | "json-stringify-safe": "5.0.1", 2409 | "mime-types": "2.1.21", 2410 | "oauth-sign": "0.9.0", 2411 | "performance-now": "2.1.0", 2412 | "qs": "6.5.2", 2413 | "safe-buffer": "5.1.2", 2414 | "tough-cookie": "2.4.3", 2415 | "tunnel-agent": "0.6.0", 2416 | "uuid": "3.3.2" 2417 | } 2418 | }, 2419 | "requests": { 2420 | "version": "0.2.2", 2421 | "resolved": "https://registry.npmjs.org/requests/-/requests-0.2.2.tgz", 2422 | "integrity": "sha1-Dl7Af9hrSVvbS+2oabIVfsqJO00=", 2423 | "requires": { 2424 | "axo": "0.0.2", 2425 | "eventemitter3": "2.0.3", 2426 | "extendible": "0.1.1", 2427 | "hang": "1.0.0", 2428 | "loads": "0.0.4", 2429 | "node-http-xhr": "1.3.4", 2430 | "xhr-send": "1.0.0" 2431 | } 2432 | }, 2433 | "requires-port": { 2434 | "version": "1.0.0", 2435 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 2436 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" 2437 | }, 2438 | "resolve-url": { 2439 | "version": "0.2.1", 2440 | "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", 2441 | "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" 2442 | }, 2443 | "ret": { 2444 | "version": "0.1.15", 2445 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", 2446 | "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" 2447 | }, 2448 | "safe-buffer": { 2449 | "version": "5.1.2", 2450 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2451 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 2452 | }, 2453 | "safe-regex": { 2454 | "version": "1.1.0", 2455 | "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", 2456 | "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", 2457 | "requires": { 2458 | "ret": "0.1.15" 2459 | } 2460 | }, 2461 | "safer-buffer": { 2462 | "version": "2.1.2", 2463 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2464 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 2465 | }, 2466 | "semver": { 2467 | "version": "5.6.0", 2468 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", 2469 | "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" 2470 | }, 2471 | "semver-diff": { 2472 | "version": "2.1.0", 2473 | "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", 2474 | "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", 2475 | "requires": { 2476 | "semver": "5.6.0" 2477 | } 2478 | }, 2479 | "set-value": { 2480 | "version": "2.0.0", 2481 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", 2482 | "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", 2483 | "requires": { 2484 | "extend-shallow": "2.0.1", 2485 | "is-extendable": "0.1.1", 2486 | "is-plain-object": "2.0.4", 2487 | "split-string": "3.1.0" 2488 | }, 2489 | "dependencies": { 2490 | "extend-shallow": { 2491 | "version": "2.0.1", 2492 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2493 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2494 | "requires": { 2495 | "is-extendable": "0.1.1" 2496 | } 2497 | } 2498 | } 2499 | }, 2500 | "shebang-command": { 2501 | "version": "1.2.0", 2502 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 2503 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 2504 | "requires": { 2505 | "shebang-regex": "1.0.0" 2506 | } 2507 | }, 2508 | "shebang-regex": { 2509 | "version": "1.0.0", 2510 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 2511 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" 2512 | }, 2513 | "signal-exit": { 2514 | "version": "3.0.2", 2515 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 2516 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 2517 | }, 2518 | "snapdragon": { 2519 | "version": "0.8.2", 2520 | "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", 2521 | "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", 2522 | "requires": { 2523 | "base": "0.11.2", 2524 | "debug": "2.6.9", 2525 | "define-property": "0.2.5", 2526 | "extend-shallow": "2.0.1", 2527 | "map-cache": "0.2.2", 2528 | "source-map": "0.5.7", 2529 | "source-map-resolve": "0.5.2", 2530 | "use": "3.1.1" 2531 | }, 2532 | "dependencies": { 2533 | "debug": { 2534 | "version": "2.6.9", 2535 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 2536 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 2537 | "requires": { 2538 | "ms": "2.0.0" 2539 | } 2540 | }, 2541 | "define-property": { 2542 | "version": "0.2.5", 2543 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2544 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2545 | "requires": { 2546 | "is-descriptor": "0.1.6" 2547 | } 2548 | }, 2549 | "extend-shallow": { 2550 | "version": "2.0.1", 2551 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2552 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2553 | "requires": { 2554 | "is-extendable": "0.1.1" 2555 | } 2556 | } 2557 | } 2558 | }, 2559 | "snapdragon-node": { 2560 | "version": "2.1.1", 2561 | "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", 2562 | "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", 2563 | "requires": { 2564 | "define-property": "1.0.0", 2565 | "isobject": "3.0.1", 2566 | "snapdragon-util": "3.0.1" 2567 | }, 2568 | "dependencies": { 2569 | "define-property": { 2570 | "version": "1.0.0", 2571 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 2572 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 2573 | "requires": { 2574 | "is-descriptor": "1.0.2" 2575 | } 2576 | }, 2577 | "is-accessor-descriptor": { 2578 | "version": "1.0.0", 2579 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 2580 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 2581 | "requires": { 2582 | "kind-of": "6.0.2" 2583 | } 2584 | }, 2585 | "is-data-descriptor": { 2586 | "version": "1.0.0", 2587 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 2588 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 2589 | "requires": { 2590 | "kind-of": "6.0.2" 2591 | } 2592 | }, 2593 | "is-descriptor": { 2594 | "version": "1.0.2", 2595 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 2596 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 2597 | "requires": { 2598 | "is-accessor-descriptor": "1.0.0", 2599 | "is-data-descriptor": "1.0.0", 2600 | "kind-of": "6.0.2" 2601 | } 2602 | } 2603 | } 2604 | }, 2605 | "snapdragon-util": { 2606 | "version": "3.0.1", 2607 | "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", 2608 | "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", 2609 | "requires": { 2610 | "kind-of": "3.2.2" 2611 | }, 2612 | "dependencies": { 2613 | "kind-of": { 2614 | "version": "3.2.2", 2615 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 2616 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 2617 | "requires": { 2618 | "is-buffer": "1.1.6" 2619 | } 2620 | } 2621 | } 2622 | }, 2623 | "source-map": { 2624 | "version": "0.5.7", 2625 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 2626 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 2627 | }, 2628 | "source-map-resolve": { 2629 | "version": "0.5.2", 2630 | "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", 2631 | "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", 2632 | "requires": { 2633 | "atob": "2.1.2", 2634 | "decode-uri-component": "0.2.0", 2635 | "resolve-url": "0.2.1", 2636 | "source-map-url": "0.4.0", 2637 | "urix": "0.1.0" 2638 | } 2639 | }, 2640 | "source-map-url": { 2641 | "version": "0.4.0", 2642 | "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", 2643 | "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" 2644 | }, 2645 | "split-string": { 2646 | "version": "3.1.0", 2647 | "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", 2648 | "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", 2649 | "requires": { 2650 | "extend-shallow": "3.0.2" 2651 | } 2652 | }, 2653 | "sshpk": { 2654 | "version": "1.16.0", 2655 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz", 2656 | "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==", 2657 | "requires": { 2658 | "asn1": "0.2.4", 2659 | "assert-plus": "1.0.0", 2660 | "bcrypt-pbkdf": "1.0.2", 2661 | "dashdash": "1.14.1", 2662 | "ecc-jsbn": "0.1.2", 2663 | "getpass": "0.1.7", 2664 | "jsbn": "0.1.1", 2665 | "safer-buffer": "2.1.2", 2666 | "tweetnacl": "0.14.5" 2667 | } 2668 | }, 2669 | "static-extend": { 2670 | "version": "0.1.2", 2671 | "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", 2672 | "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", 2673 | "requires": { 2674 | "define-property": "0.2.5", 2675 | "object-copy": "0.1.0" 2676 | }, 2677 | "dependencies": { 2678 | "define-property": { 2679 | "version": "0.2.5", 2680 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2681 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2682 | "requires": { 2683 | "is-descriptor": "0.1.6" 2684 | } 2685 | } 2686 | } 2687 | }, 2688 | "string-width": { 2689 | "version": "2.1.1", 2690 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 2691 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 2692 | "requires": { 2693 | "is-fullwidth-code-point": "2.0.0", 2694 | "strip-ansi": "4.0.0" 2695 | } 2696 | }, 2697 | "string_decoder": { 2698 | "version": "1.1.1", 2699 | "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 2700 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 2701 | "requires": { 2702 | "safe-buffer": "5.1.2" 2703 | } 2704 | }, 2705 | "strip-ansi": { 2706 | "version": "4.0.0", 2707 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2708 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2709 | "requires": { 2710 | "ansi-regex": "3.0.0" 2711 | } 2712 | }, 2713 | "strip-eof": { 2714 | "version": "1.0.0", 2715 | "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 2716 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" 2717 | }, 2718 | "strip-json-comments": { 2719 | "version": "2.0.1", 2720 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 2721 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" 2722 | }, 2723 | "supports-color": { 2724 | "version": "5.5.0", 2725 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2726 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2727 | "requires": { 2728 | "has-flag": "3.0.0" 2729 | } 2730 | }, 2731 | "term-size": { 2732 | "version": "1.2.0", 2733 | "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", 2734 | "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", 2735 | "requires": { 2736 | "execa": "0.7.0" 2737 | } 2738 | }, 2739 | "timed-out": { 2740 | "version": "4.0.1", 2741 | "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", 2742 | "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" 2743 | }, 2744 | "to-object-path": { 2745 | "version": "0.3.0", 2746 | "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", 2747 | "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", 2748 | "requires": { 2749 | "kind-of": "3.2.2" 2750 | }, 2751 | "dependencies": { 2752 | "kind-of": { 2753 | "version": "3.2.2", 2754 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 2755 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 2756 | "requires": { 2757 | "is-buffer": "1.1.6" 2758 | } 2759 | } 2760 | } 2761 | }, 2762 | "to-regex": { 2763 | "version": "3.0.2", 2764 | "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", 2765 | "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", 2766 | "requires": { 2767 | "define-property": "2.0.2", 2768 | "extend-shallow": "3.0.2", 2769 | "regex-not": "1.0.2", 2770 | "safe-regex": "1.1.0" 2771 | } 2772 | }, 2773 | "to-regex-range": { 2774 | "version": "2.1.1", 2775 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", 2776 | "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", 2777 | "requires": { 2778 | "is-number": "3.0.0", 2779 | "repeat-string": "1.6.1" 2780 | } 2781 | }, 2782 | "touch": { 2783 | "version": "3.1.0", 2784 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 2785 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 2786 | "requires": { 2787 | "nopt": "1.0.10" 2788 | } 2789 | }, 2790 | "tough-cookie": { 2791 | "version": "2.4.3", 2792 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 2793 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 2794 | "requires": { 2795 | "psl": "1.1.31", 2796 | "punycode": "1.4.1" 2797 | }, 2798 | "dependencies": { 2799 | "punycode": { 2800 | "version": "1.4.1", 2801 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 2802 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 2803 | } 2804 | } 2805 | }, 2806 | "tunnel-agent": { 2807 | "version": "0.6.0", 2808 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 2809 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 2810 | "requires": { 2811 | "safe-buffer": "5.1.2" 2812 | } 2813 | }, 2814 | "tweetnacl": { 2815 | "version": "0.14.5", 2816 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 2817 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 2818 | }, 2819 | "undefsafe": { 2820 | "version": "2.0.2", 2821 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", 2822 | "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", 2823 | "requires": { 2824 | "debug": "2.6.9" 2825 | }, 2826 | "dependencies": { 2827 | "debug": { 2828 | "version": "2.6.9", 2829 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 2830 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 2831 | "requires": { 2832 | "ms": "2.0.0" 2833 | } 2834 | } 2835 | } 2836 | }, 2837 | "union-value": { 2838 | "version": "1.0.0", 2839 | "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", 2840 | "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", 2841 | "requires": { 2842 | "arr-union": "3.1.0", 2843 | "get-value": "2.0.6", 2844 | "is-extendable": "0.1.1", 2845 | "set-value": "0.4.3" 2846 | }, 2847 | "dependencies": { 2848 | "extend-shallow": { 2849 | "version": "2.0.1", 2850 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2851 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2852 | "requires": { 2853 | "is-extendable": "0.1.1" 2854 | } 2855 | }, 2856 | "set-value": { 2857 | "version": "0.4.3", 2858 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", 2859 | "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", 2860 | "requires": { 2861 | "extend-shallow": "2.0.1", 2862 | "is-extendable": "0.1.1", 2863 | "is-plain-object": "2.0.4", 2864 | "to-object-path": "0.3.0" 2865 | } 2866 | } 2867 | } 2868 | }, 2869 | "unique-string": { 2870 | "version": "1.0.0", 2871 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", 2872 | "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", 2873 | "requires": { 2874 | "crypto-random-string": "1.0.0" 2875 | } 2876 | }, 2877 | "unset-value": { 2878 | "version": "1.0.0", 2879 | "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", 2880 | "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", 2881 | "requires": { 2882 | "has-value": "0.3.1", 2883 | "isobject": "3.0.1" 2884 | }, 2885 | "dependencies": { 2886 | "has-value": { 2887 | "version": "0.3.1", 2888 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", 2889 | "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", 2890 | "requires": { 2891 | "get-value": "2.0.6", 2892 | "has-values": "0.1.4", 2893 | "isobject": "2.1.0" 2894 | }, 2895 | "dependencies": { 2896 | "isobject": { 2897 | "version": "2.1.0", 2898 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", 2899 | "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", 2900 | "requires": { 2901 | "isarray": "1.0.0" 2902 | } 2903 | } 2904 | } 2905 | }, 2906 | "has-values": { 2907 | "version": "0.1.4", 2908 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", 2909 | "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" 2910 | } 2911 | } 2912 | }, 2913 | "unzip-response": { 2914 | "version": "2.0.1", 2915 | "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", 2916 | "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" 2917 | }, 2918 | "upath": { 2919 | "version": "1.1.0", 2920 | "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", 2921 | "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==" 2922 | }, 2923 | "update-notifier": { 2924 | "version": "2.5.0", 2925 | "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", 2926 | "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", 2927 | "requires": { 2928 | "boxen": "1.3.0", 2929 | "chalk": "2.4.1", 2930 | "configstore": "3.1.2", 2931 | "import-lazy": "2.1.0", 2932 | "is-ci": "1.2.1", 2933 | "is-installed-globally": "0.1.0", 2934 | "is-npm": "1.0.0", 2935 | "latest-version": "3.1.0", 2936 | "semver-diff": "2.1.0", 2937 | "xdg-basedir": "3.0.0" 2938 | } 2939 | }, 2940 | "uri-js": { 2941 | "version": "4.2.2", 2942 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 2943 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 2944 | "requires": { 2945 | "punycode": "2.1.1" 2946 | } 2947 | }, 2948 | "urix": { 2949 | "version": "0.1.0", 2950 | "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", 2951 | "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" 2952 | }, 2953 | "url-parse": { 2954 | "version": "1.4.4", 2955 | "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", 2956 | "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", 2957 | "requires": { 2958 | "querystringify": "2.1.0", 2959 | "requires-port": "1.0.0" 2960 | } 2961 | }, 2962 | "url-parse-lax": { 2963 | "version": "1.0.0", 2964 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", 2965 | "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", 2966 | "requires": { 2967 | "prepend-http": "1.0.4" 2968 | } 2969 | }, 2970 | "use": { 2971 | "version": "3.1.1", 2972 | "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", 2973 | "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" 2974 | }, 2975 | "util-deprecate": { 2976 | "version": "1.0.2", 2977 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2978 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2979 | }, 2980 | "uuid": { 2981 | "version": "3.3.2", 2982 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 2983 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 2984 | }, 2985 | "verror": { 2986 | "version": "1.10.0", 2987 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 2988 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 2989 | "requires": { 2990 | "assert-plus": "1.0.0", 2991 | "core-util-is": "1.0.2", 2992 | "extsprintf": "1.3.0" 2993 | } 2994 | }, 2995 | "which": { 2996 | "version": "1.3.1", 2997 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 2998 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 2999 | "requires": { 3000 | "isexe": "2.0.0" 3001 | } 3002 | }, 3003 | "widest-line": { 3004 | "version": "2.0.1", 3005 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", 3006 | "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", 3007 | "requires": { 3008 | "string-width": "2.1.1" 3009 | } 3010 | }, 3011 | "wrappy": { 3012 | "version": "1.0.2", 3013 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 3014 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 3015 | }, 3016 | "write-file-atomic": { 3017 | "version": "2.3.0", 3018 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", 3019 | "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", 3020 | "requires": { 3021 | "graceful-fs": "4.1.15", 3022 | "imurmurhash": "0.1.4", 3023 | "signal-exit": "3.0.2" 3024 | } 3025 | }, 3026 | "xdg-basedir": { 3027 | "version": "3.0.0", 3028 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", 3029 | "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" 3030 | }, 3031 | "xhr-response": { 3032 | "version": "1.0.1", 3033 | "resolved": "https://registry.npmjs.org/xhr-response/-/xhr-response-1.0.1.tgz", 3034 | "integrity": "sha1-r/46CFRLpyGG5NxSzQImZx2Gc/4=" 3035 | }, 3036 | "xhr-send": { 3037 | "version": "1.0.0", 3038 | "resolved": "https://registry.npmjs.org/xhr-send/-/xhr-send-1.0.0.tgz", 3039 | "integrity": "sha1-GkDHPl2yAo7gj+kPXD1tx/eWqFQ=" 3040 | }, 3041 | "xhr-status": { 3042 | "version": "1.0.1", 3043 | "resolved": "https://registry.npmjs.org/xhr-status/-/xhr-status-1.0.1.tgz", 3044 | "integrity": "sha512-VF0WSqtmkf56OmF26LCWsWvRb1a+WYGdHDoQnPPCVUQTM8CVUAOBcUDsm7nP7SQcgEEdrvF4DmhEADuXdGieyw==" 3045 | }, 3046 | "yallist": { 3047 | "version": "2.1.2", 3048 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 3049 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" 3050 | } 3051 | } 3052 | } 3053 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitshovel", 3 | "version": "0.1.0", 4 | "description": "read and write to blockchain in any language instantly", 5 | "main": "bitshovel.js", 6 | "scripts": { 7 | "start": "node bitshovel.js", 8 | "dev": "./node_modules/.bin/nodemon bitshovel.js", 9 | "test": "node node_modules/mocha/bin/mocha" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/dfoderick/bitshovel.git" 14 | }, 15 | "author": "dfoderick", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/dfoderick/bitshovel/issues" 19 | }, 20 | "homepage": "https://github.com/dfoderick/bitshovel#readme", 21 | "dependencies": { 22 | "axios": "^0.18.0", 23 | "bsv": "^0.20.3", 24 | "datapay": "0.0.3", 25 | "eventsource": "^1.0.7", 26 | "mocha": "^5.2.0", 27 | "nodemon": "^1.18.9", 28 | "redis": "^2.8.0", 29 | "requests": "^0.2.2" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /shoveladdress.js: -------------------------------------------------------------------------------- 1 | const utils = require('./utils') 2 | const bsv = require('bsv') 3 | 4 | let toCashAddress = function toCashAddress(originalAddress) { 5 | const a = new bsv.Address(originalAddress) 6 | const ac = a.toCashAddress() 7 | return ac.replace("bitcoincash:","") 8 | } 9 | 10 | let toOriginalAddress = function toOriginalAddress(cashAddress) { 11 | return (new bsv.Address(cashAddress)).toLegacyAddress() 12 | } 13 | 14 | module.exports = { 15 | toCashAddress: toCashAddress, 16 | toOriginalAddress: toOriginalAddress 17 | } -------------------------------------------------------------------------------- /shovelbus.js: -------------------------------------------------------------------------------- 1 | //for now, redis is simplest message bus. later can support more brokers 2 | const utils = require('./utils') 3 | const redis = require('redis'); 4 | 5 | //local apps will watch/listen/subscribe to this channel 6 | const CHANNEL_READ = "bitshovel.watch"; 7 | //channel names for the local bus 8 | //messages on these channels will be tna format. See https://github.com/21centurymotorcompany/tna 9 | const CHANNEL_SEND = 'bitshovel.send'; 10 | //TODO: there could be one channel for commands, with command type as part of the message 11 | //manage wallet 12 | const CHANNEL_WALLET = 'bitshovel.wallet'; 13 | //const CHANNEL_ADDRESS = 'bitshovel.address'; 14 | //stream for bitsocket streams 15 | const CHANNEL_STREAM = 'bitshovel.stream'; 16 | //query for bitdb queries 17 | const CHANNEL_QUERY = 'bitshovel.query'; 18 | //bitshovel application command 19 | const CHANNEL_APP = 'bitshovel.app'; 20 | 21 | let thissub 22 | let thispub 23 | 24 | let sub = function sub() {return thissub} 25 | let pub = function pub() {return thispub} 26 | 27 | //set up connection to local message bus 28 | let start = function start() { 29 | thissub = redis.createClient(); 30 | //export the on method of sub!!! 31 | sub.on = thissub.on 32 | thispub = redis.createClient(); 33 | 34 | thissub.on("connect", function () { 35 | console.log("Connected to local bus"); 36 | }); 37 | 38 | thissub.on("subscribe", function (channel, message) { 39 | if (channel === CHANNEL_WALLET) { 40 | console.log(`Use message '${CHANNEL_WALLET}' to change wallet`); 41 | } 42 | if (channel === CHANNEL_STREAM) { 43 | console.log(`Use message '${CHANNEL_STREAM}' to stream live bitcoin messages`); 44 | } 45 | if (channel === CHANNEL_QUERY) { 46 | console.log(`Use message '${CHANNEL_QUERY}' to get historical bitcoin messages`); 47 | } 48 | if (channel === CHANNEL_APP) { 49 | console.log(`Use message '${CHANNEL_APP}' to control app functions`); 50 | } 51 | if (channel === CHANNEL_SEND) { 52 | console.log(`Use message '${CHANNEL_SEND}' to write to bitcoin (send bitcoin message)`); 53 | } 54 | }) 55 | 56 | } 57 | 58 | //subscribe to single channel 59 | let subscribe = function subscribe(channel) { 60 | thissub.subscribe(channel); 61 | } 62 | 63 | let subscribeall = function subscribeall() { 64 | subscribe(CHANNEL_STREAM); 65 | subscribe(CHANNEL_QUERY); 66 | subscribe(CHANNEL_SEND); 67 | subscribe(CHANNEL_APP); 68 | subscribe(CHANNEL_WALLET); 69 | } 70 | 71 | //shovel the bitcoin (bitsocket tna) message on to the local bus 72 | function publish(msg) { 73 | //announce to the local bus that a bitcoin tx has been broadcast 74 | thispub.publish(CHANNEL_READ, msg); 75 | } 76 | 77 | module.exports = { 78 | start: start, 79 | subscribeall: subscribeall, 80 | sub: sub, 81 | subscribe: subscribe, 82 | pub: pub, 83 | publish: publish, 84 | CHANNEL_WALLET: CHANNEL_WALLET, 85 | CHANNEL_STREAM: CHANNEL_STREAM, 86 | CHANNEL_QUERY: CHANNEL_QUERY, 87 | CHANNEL_APP: CHANNEL_APP, 88 | CHANNEL_SEND: CHANNEL_SEND 89 | } 90 | -------------------------------------------------------------------------------- /shovelcache.js: -------------------------------------------------------------------------------- 1 | const utils = require('./utils') 2 | const redis = require('redis'); 3 | 4 | //keys stored in redis 5 | const WALLET_ADDRESS_KEY = 'bitshovel.wallet.address'; 6 | const WALLET_PRIVATE_KEY = 'bitshovel.wallet.private'; 7 | 8 | let cache 9 | 10 | let start = function start() { 11 | cache = redis.createClient() 12 | } 13 | 14 | //store wallet address in redis 15 | let storeWalletAddress = function storeWalletAddress(address) { 16 | cache.set(WALLET_ADDRESS_KEY, address, function(err) { 17 | console.error(err) 18 | }) 19 | } 20 | 21 | module.exports = { 22 | start: start, 23 | storeWalletAddress: storeWalletAddress 24 | } -------------------------------------------------------------------------------- /shovellisteners.js: -------------------------------------------------------------------------------- 1 | //eventsource for listening to bitsocket streams 2 | const utils = require('./utils') 3 | const EventSource = require('eventsource'); 4 | const BITSOCKET_SOURCE = 'https://bitgraph.network/s/' 5 | 6 | //maintains list of active bitsocket listeners 7 | let BITSOCKET_LISTENERS = []; 8 | 9 | let listen = function listen (name, query) { 10 | const listener = { 11 | name : name, 12 | bitsocket : createEventSource(query) 13 | } 14 | BITSOCKET_LISTENERS.push(listener); 15 | return listener 16 | } 17 | 18 | function createEventSource(query) { 19 | console.log(query) 20 | const url = utils.urlString(BITSOCKET_SOURCE, query) 21 | return new EventSource(url) 22 | } 23 | 24 | //stop listening to bitsocket messages 25 | //this will shut down all bitcoin tx from broadcasting on your local bus 26 | //you can still send tx (using CHANNEL_SEND) 27 | let close = function close(name) { 28 | let soxlen = BITSOCKET_LISTENERS.length; 29 | while (soxlen--) { 30 | const listener = BITSOCKET_LISTENERS[soxlen]; 31 | if (listener.name === name) { 32 | console.log(`stopping bitsocket listener ${listener.name}`) 33 | listener.bitsocket.close(); 34 | BITSOCKET_LISTENERS.splice(soxlen, 1); 35 | } 36 | } 37 | } 38 | 39 | module.exports = { 40 | listen: listen, 41 | close: close 42 | } -------------------------------------------------------------------------------- /shovelregistry.js: -------------------------------------------------------------------------------- 1 | //application registry 2 | //hdwallet 3 | const utils = require('./utils') 4 | 5 | //TODO: could be handled by redis instead 6 | let APPS = {} 7 | 8 | let register = function register (appname, walletaddress) { 9 | APPS[appname] = walletaddress 10 | console.log(`registered ${appname} on ${walletaddress}`) 11 | } 12 | 13 | let has = function has(appname) { 14 | return APPS.hasOwnProperty(appname) 15 | } 16 | 17 | let get = function get(appname) { 18 | return APPS[appname] 19 | } 20 | 21 | module.exports = { 22 | APPS: APPS, 23 | register: register, 24 | has: has, 25 | get: get 26 | } -------------------------------------------------------------------------------- /shovelwallet.js: -------------------------------------------------------------------------------- 1 | const utils = require('./utils') 2 | const bsv = require('bsv') 3 | const fs = require('fs') 4 | 5 | const walletFileName = `wallet.json`; 6 | 7 | //example wallet.json 8 | // { 9 | // "wif":"private key", 10 | // "address": "optional address in legacy format" 11 | // } 12 | let generateWallet = function generateWallet(key) { 13 | let pk = null; 14 | if (key !== null && key !== undefined && key !== '') { 15 | pk = bsv.PrivateKey(key) 16 | } else { 17 | pk = bsv.PrivateKey() 18 | } 19 | const address = new bsv.Address(pk.publicKey, bsv.Networks.mainnet) 20 | console.log(`generated wallet with address ${address}`); 21 | 22 | const wallet = { 23 | "wif": pk.toWIF(), 24 | "address": address.toLegacyAddress() 25 | } 26 | return storeWallet(wallet) 27 | } 28 | 29 | let storeWallet = function storeWallet(wallet) { 30 | const sWallet = JSON.stringify(wallet, null, 2); 31 | backupWallet() 32 | fs.writeFileSync(walletFileName, sWallet, 'utf8', function(err) { 33 | if(err) { 34 | console.log(err); 35 | return 36 | } 37 | }); 38 | return wallet; 39 | } 40 | 41 | let backupWallet = function backupWallet() { 42 | if (fs.existsSync(walletFileName)) { 43 | let timestamp = (new Date()).toISOString() 44 | .replace(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).(\d{3})Z$/, '$1$2$3.$4$5$6.$7000000'); 45 | fs.renameSync(walletFileName, `${walletFileName}.${timestamp}`) 46 | } 47 | } 48 | 49 | module.exports = { 50 | walletFileName: walletFileName, 51 | generateWallet: generateWallet, 52 | storeWallet:storeWallet , 53 | backupWallet: backupWallet 54 | } 55 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const utils = require('../utils'); 3 | const shoveladdress = require('../shoveladdress'); 4 | const shovelcache = require('../shovelcache'); 5 | const shovelregistry = require('../shovelregistry'); 6 | const shovelwallet = require('../shovelwallet'); 7 | const shovelbus = require('../shovelbus'); 8 | 9 | describe('bitshovel', function() { 10 | describe('utils',function() { 11 | //command, action, name, parameter 12 | it('command stream', function(done) { 13 | let cmd = utils.parseCommand("stream","start streamname query") 14 | assert.equal(cmd.command, "stream") 15 | done() 16 | }) 17 | it('command filter', function(done) { 18 | let cmd = utils.parseCommand("test","start stream {\"find\":{}}") 19 | assert.equal(cmd.action, "start") 20 | assert.equal(cmd.name, "stream") 21 | assert.equal(cmd.parameter, "{\"find\":{}}") 22 | done() 23 | }) 24 | it('command with spaces', function(done) { 25 | let cmd = utils.parseCommand("test",'start stream "{this is one param}"') 26 | assert.equal(cmd.action, "start") 27 | assert.equal(cmd.name, "stream") 28 | assert.equal(cmd.parameter, "{this is one param}") 29 | done() 30 | }) 31 | it('isStart', function(done) { 32 | assert(utils.isStart('start')) 33 | assert(utils.isStart("START")) 34 | assert(utils.isStart('on')) 35 | assert(utils.isStart('stop') === false) 36 | done() 37 | }) 38 | it('isStop', function(done) { 39 | assert(utils.isStop('stop')) 40 | assert(utils.isStop("STOP")) 41 | assert(utils.isStop('off')) 42 | assert(utils.isStop('') === false) 43 | done() 44 | }) 45 | it('parse op_return with hex', function(done) { 46 | let pushdata = "\"BitShovel Test\"" 47 | let words = utils.splitString(`x0602 "${pushdata}"`) 48 | console.log(words) 49 | clean = utils.cleanQuotes(pushdata) 50 | console.log(clean) 51 | assert(words.length === 2) 52 | assert.equal(words[1], clean) 53 | done() 54 | }) 55 | // it('parse with internal quotes', function(done) { 56 | // let words = utils.splitString(`first "second \"data\""`) 57 | // console.log(words) 58 | // //assert(words.length === 2) 59 | // assert.equal(words[1], "second \"data\"") 60 | // done() 61 | // }) 62 | }) 63 | 64 | describe('address tests',function() { 65 | it('toCashAddress', function (done) { 66 | let cash = shoveladdress.toCashAddress('1N9zmDbiE2w7QT8oW524eD3BXdcQ8PpFgM') 67 | assert.equal(cash, 'qr5qut7whhqvh3ae8hl0y3tgveaa4s834uckgu0t49') 68 | done() 69 | }) 70 | it('toOriginalAddress', function (done) { 71 | let bitcoinaddress = shoveladdress.toOriginalAddress('qr5qut7whhqvh3ae8hl0y3tgveaa4s834uckgu0t49') 72 | assert.equal(bitcoinaddress, '1N9zmDbiE2w7QT8oW524eD3BXdcQ8PpFgM') 73 | done() 74 | }) 75 | }) 76 | 77 | describe('registry tests',function() { 78 | it('register', function (done) { 79 | let startcount = Object.keys(shovelregistry.APPS).length 80 | shovelregistry.register("testapp","anyaddress") 81 | assert.equal(Object.keys(shovelregistry.APPS).length, startcount + 1) 82 | done() 83 | }) 84 | it('has', function (done) { 85 | shovelregistry.register("testapp","anyaddress") 86 | assert.ok(shovelregistry.has("testapp")) 87 | done() 88 | }) 89 | it('get', function (done) { 90 | shovelregistry.register("testapp","anyaddress") 91 | assert.equal(shovelregistry.get("testapp"), 'anyaddress') 92 | done() 93 | }) 94 | }) 95 | 96 | describe('wallet tests',function() { 97 | it('generate wallet', function (done) { 98 | let wallet = shovelwallet.generateWallet() 99 | assert.equal(Object.keys(wallet).length, 2) 100 | assert(wallet.wif) 101 | assert(wallet.address) 102 | done() 103 | }) 104 | }) 105 | 106 | }) 107 | -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | let parseCommand = function parseCommand(command, msg) { 2 | const words = splitString(msg) 3 | console.log(words) 4 | return { 5 | "command": command, 6 | "action": words[0].toLowerCase(), 7 | "name": words[1].toLowerCase(), 8 | "parameter": words[2] 9 | } 10 | } 11 | 12 | let splitString = function splitString(s) { 13 | let clean = naiveClean(s) 14 | //finds the tokens in a string 15 | let matches = clean.match(/[\""].+?[\""]|[^ ]+/g) 16 | //console.log(matches) 17 | //but surrounding quotes are still there so remove 18 | if (matches) { 19 | for (var i=0, len=matches.length; i