diff --git a/.env.example b/.env.example
index 638679f8..96eb2f48 100644
--- a/.env.example
+++ b/.env.example
@@ -5,4 +5,6 @@ DISABLE_SHOCK_ENCRYPTION=false
CACHE_HEADERS_MANDATORY=true
SHOCK_CACHE=true
TRUSTED_KEYS=true
-LOCAL_TUNNEL_SERVER=http://tunnel.example.com
\ No newline at end of file
+LOCAL_TUNNEL_SERVER=http://tunnel.example.com
+TORRENT_SEED_URL=https://webtorrent.shock.network
+TORRENT_SEED_TOKEN=jibberish
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 00000000..6461deec
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+*.ts
diff --git a/.eslintrc.json b/.eslintrc.json
index dd2485bf..252f73b1 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -88,7 +88,10 @@
// I am now convinced TODO comments closer to the relevant code are better
// than GH issues. Especially when it only concerns a single function /
// routine.
- "no-warning-comments": "off"
+ "no-warning-comments": "off",
+
+ // broken
+ "sort-imports": "off"
},
"parser": "babel-eslint",
"env": {
diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml
new file mode 100644
index 00000000..26e292c4
--- /dev/null
+++ b/.github/workflows/version.yml
@@ -0,0 +1,36 @@
+name: Bump "package.json" Version
+
+on:
+ release:
+ types: [prereleased, released]
+
+jobs:
+ version-bump:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ with:
+ persist-credentials: false
+ fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
+ - name: Get the last API TAG and current version in package.json
+ run: |
+ export RELEASE_TAG=$(git describe --tags --abbrev=0) && \
+ echo "VERSION=${RELEASE_TAG}" >> $GITHUB_ENV
+
+ export API_TAG=$(cat ./package.json | jq -r '.version')
+
+ echo $(if [ "$API_TAG" = "$RELEASE_TAG" ]; then echo "UPGRADEABLE=false"; else echo "UPGRADEABLE=true"; fi) >> $GITHUB_ENV
+
+ - name: Update and Commit files
+ if: ${{ env.UPGRADEABLE == 'true' }}
+ run: |
+ cat ./package.json | jq -r --arg API_TAG "${{ env.VERSION }}" '.version = $API_TAG' | tee a.json && mv a.json package.json
+ git config --local user.email "actions@shock.network"
+ git config --local user.name "Version Update Action"
+ git commit -m "version upgraded to ${{ env.VERSION }}" -a
+ - name: Push changes
+ if: ${{ env.UPGRADEABLE == 'true' }}
+ uses: ad-m/github-push-action@master
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ branch: master
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 5171a933..38a20598 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,7 @@
{
"eslint.enable": true,
"typescript.tsdk": "node_modules/typescript/lib",
- "debug.node.autoAttach": "on"
+ "debug.node.autoAttach": "on",
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
}
diff --git a/.vscode/snippets.code-snippets b/.vscode/snippets.code-snippets
new file mode 100644
index 00000000..53bd01c5
--- /dev/null
+++ b/.vscode/snippets.code-snippets
@@ -0,0 +1,33 @@
+{
+ // Place your api workspace snippets here. Each snippet is defined under a
+ // snippet name and has a scope, prefix, body and description. Add comma
+ // separated ids of the languages where the snippet is applicable in the scope
+ // field. If scope is left empty or omitted, the snippet gets applied to all
+ // languages. The prefix is what is used to trigger the snippet and the body
+ // will be expanded and inserted. Possible variables are: $1, $2 for tab
+ // stops, $0 for the final cursor position, and ${1:label}, ${2:another} for
+ // placeholders. Placeholders with the same ids are connected. Example: "Print
+ // to console": {"scope": "javascript,typescript", "prefix": "log", "body":
+ // ["console.log('$1');", "$2"
+ // ],
+ // "description": "Log output to console"
+ // }
+
+ "Route Body": {
+ "body": [
+ "try {",
+ " return res.json({",
+ "",
+ " })",
+ "} catch (e) {",
+ " console.log(e)",
+ " return res.status(500).json({",
+ " errorMessage: e.message",
+ " })",
+ "}"
+ ],
+ "description": "Route Body",
+ "prefix": "rbody",
+ "scope": "javascript"
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index c7dcc9c1..c3cde0d8 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
ShockAPI
-
+
[](http://makeapullrequest.com)
[](https://t.me/Shockwallet)
[](https://twitter.com/shockbtc)
diff --git a/config/defaults.js b/config/defaults.js
index 7341dd50..a44376f4 100644
--- a/config/defaults.js
+++ b/config/defaults.js
@@ -35,6 +35,7 @@ module.exports = (mainnet = false) => {
maxNumRoutesToQuery: 20,
lndProto: parsePath(`${__dirname}/rpc.proto`),
routerProto: parsePath(`${__dirname}/router.proto`),
+ invoicesProto: parsePath(`${__dirname}/invoices.proto`),
walletUnlockerProto: parsePath(`${__dirname}/walletunlocker.proto`),
lndHost: "localhost:10009",
lndCertPath: parsePath(`${lndDirectory}/tls.cert`),
diff --git a/config/invoices.proto b/config/invoices.proto
new file mode 100644
index 00000000..df52b8c8
--- /dev/null
+++ b/config/invoices.proto
@@ -0,0 +1,122 @@
+syntax = "proto3";
+
+import "rpc.proto";
+
+package invoicesrpc;
+
+option go_package = "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc";
+
+// Invoices is a service that can be used to create, accept, settle and cancel
+// invoices.
+service Invoices {
+ /*
+ SubscribeSingleInvoice returns a uni-directional stream (server -> client)
+ to notify the client of state transitions of the specified invoice.
+ Initially the current invoice state is always sent out.
+ */
+ rpc SubscribeSingleInvoice (SubscribeSingleInvoiceRequest)
+ returns (stream lnrpc.Invoice);
+
+ /*
+ CancelInvoice cancels a currently open invoice. If the invoice is already
+ canceled, this call will succeed. If the invoice is already settled, it will
+ fail.
+ */
+ rpc CancelInvoice (CancelInvoiceMsg) returns (CancelInvoiceResp);
+
+ /*
+ AddHoldInvoice creates a hold invoice. It ties the invoice to the hash
+ supplied in the request.
+ */
+ rpc AddHoldInvoice (AddHoldInvoiceRequest) returns (AddHoldInvoiceResp);
+
+ /*
+ SettleInvoice settles an accepted invoice. If the invoice is already
+ settled, this call will succeed.
+ */
+ rpc SettleInvoice (SettleInvoiceMsg) returns (SettleInvoiceResp);
+}
+
+message CancelInvoiceMsg {
+ // Hash corresponding to the (hold) invoice to cancel.
+ bytes payment_hash = 1;
+}
+message CancelInvoiceResp {
+}
+
+message AddHoldInvoiceRequest {
+ /*
+ An optional memo to attach along with the invoice. Used for record keeping
+ purposes for the invoice's creator, and will also be set in the description
+ field of the encoded payment request if the description_hash field is not
+ being used.
+ */
+ string memo = 1;
+
+ // The hash of the preimage
+ bytes hash = 2;
+
+ /*
+ The value of this invoice in satoshis
+
+ The fields value and value_msat are mutually exclusive.
+ */
+ int64 value = 3;
+
+ /*
+ The value of this invoice in millisatoshis
+
+ The fields value and value_msat are mutually exclusive.
+ */
+ int64 value_msat = 10;
+
+ /*
+ Hash (SHA-256) of a description of the payment. Used if the description of
+ payment (memo) is too long to naturally fit within the description field
+ of an encoded payment request.
+ */
+ bytes description_hash = 4;
+
+ // Payment request expiry time in seconds. Default is 3600 (1 hour).
+ int64 expiry = 5;
+
+ // Fallback on-chain address.
+ string fallback_addr = 6;
+
+ // Delta to use for the time-lock of the CLTV extended to the final hop.
+ uint64 cltv_expiry = 7;
+
+ /*
+ Route hints that can each be individually used to assist in reaching the
+ invoice's destination.
+ */
+ repeated lnrpc.RouteHint route_hints = 8;
+
+ // Whether this invoice should include routing hints for private channels.
+ bool private = 9;
+}
+
+message AddHoldInvoiceResp {
+ /*
+ A bare-bones invoice for a payment within the Lightning Network. With the
+ details of the invoice, the sender has all the data necessary to send a
+ payment to the recipient.
+ */
+ string payment_request = 1;
+}
+
+message SettleInvoiceMsg {
+ // Externally discovered pre-image that should be used to settle the hold
+ // invoice.
+ bytes preimage = 1;
+}
+
+message SettleInvoiceResp {
+}
+
+message SubscribeSingleInvoiceRequest {
+ reserved 1;
+
+ // Hash corresponding to the (hold) invoice to subscribe to.
+ bytes r_hash = 2;
+}
diff --git a/package.json b/package.json
index 24409ce2..608bb8d1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "shockapi",
- "version": "1.0.0",
+ "version": "2021.1.04",
"description": "",
"main": "src/server.js",
"scripts": {
@@ -11,13 +11,16 @@
"test:watch": "jest --no-cache --watch",
"typecheck": "tsc",
"lint": "eslint \"services/gunDB/**/*.js\"",
- "format": "prettier --write \"./**/*.js\""
+ "format": "prettier --write \"./**/*.js\"",
+ "test:gun": "ts-node src/__gun__tests__/*.ts && rimraf -rf GUN-TEST-*"
},
"author": "",
"license": "ISC",
"dependencies": {
- "@grpc/proto-loader": "^0.5.1",
- "axios": "^0.20.0",
+ "@grpc/grpc-js": "^1.2.2",
+ "@grpc/proto-loader": "^0.5.5",
+ "assert-never": "^1.2.1",
+ "axios": "^0.21.1",
"basic-auth": "^2.0.0",
"big.js": "^5.2.2",
"bitcore-lib": "^0.15.0",
@@ -31,7 +34,7 @@
"debug": "^3.1.0",
"dotenv": "^8.1.0",
"express": "^4.14.1",
- "express-session": "^1.15.1",
+ "express-session": "^1.17.1",
"google-proto-files": "^1.0.3",
"graphviz": "0.0.8",
"grpc": "1.24.4",
@@ -42,15 +45,16 @@
"localtunnel": "git://github.com/shocknet/localtunnel#40cc2c2a46b05da2217bf2e20da11a5343a5cce7",
"lodash": "^4.17.20",
"method-override": "^2.3.7",
+ "node-fetch": "^2.6.1",
"node-persist": "^3.1.0",
"promise": "^8.1.0",
"qrcode-terminal": "^0.12.0",
"ramda": "^0.27.1",
"request": "^2.88.2",
- "request-promise": "^4.2.2",
+ "request-promise": "^4.2.6",
"response-time": "^2.3.2",
"shelljs": "^0.8.2",
- "shock-common": "17.x.x",
+ "shock-common": "32.0.0",
"socket.io": "2.1.1",
"text-encoding": "^0.7.0",
"tingodb": "^0.6.1",
@@ -58,7 +62,7 @@
"winston-daily-rotate-file": "^4.5.0"
},
"devDependencies": {
- "@babel/plugin-proposal-class-properties": "^7.5.5",
+ "@babel/plugin-proposal-class-properties": "^7.12.1",
"@types/bluebird": "^3.5.32",
"@types/dotenv": "^6.1.1",
"@types/express": "^4.17.1",
@@ -66,10 +70,12 @@
"@types/jest": "^24.0.18",
"@types/jsonwebtoken": "^8.3.7",
"@types/lodash": "^4.14.141",
+ "@types/node-fetch": "^2.5.8",
"@types/ramda": "types/npm-ramda#dist",
+ "@types/react": "16.x.x",
"@types/socket.io": "^2.1.11",
"@types/uuid": "^3.4.5",
- "babel-eslint": "^10.0.3",
+ "babel-eslint": "^10.1.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"eslint": "^6.6.0",
"eslint-config-prettier": "^6.5.0",
@@ -80,8 +86,10 @@
"lint-staged": "^10.2.2",
"nodemon": "^1.19.3",
"prettier": "^1.18.2",
+ "rimraf": "^3.0.2",
+ "ts-node": "^9.1.1",
"ts-type": "^1.2.16",
- "typescript": "^4.0.2"
+ "typescript": "latest"
},
"lint-staged": {
"*.js": [
diff --git a/services/coordinates.js b/services/coordinates.js
new file mode 100644
index 00000000..ac212256
--- /dev/null
+++ b/services/coordinates.js
@@ -0,0 +1,63 @@
+/**
+ * @format
+ */
+
+const Common = require('shock-common')
+const mapValues = require('lodash/mapValues')
+const pickBy = require('lodash/pickBy')
+const Bluebird = require('bluebird')
+const Logger = require('winston')
+const Key = require('../services/gunDB/contact-api/key')
+
+const { getUser, getMySecret, mySEA } = require('./gunDB/Mediator')
+
+/**
+ * @param {string} coordID
+ * @param {Common.Coordinate} data
+ * @returns {Promise}
+ */
+export const writeCoordinate = async (coordID, data) => {
+ if (coordID !== data.id) {
+ throw new Error('CoordID must be equal to data.id')
+ }
+
+ try {
+ /**
+ * Because there are optional properties, typescript can also allow them
+ * to be specified but with a value of `undefined`. Filter out these.
+ * @type {Record}
+ */
+ const sanitizedData = pickBy(data, v => typeof v !== 'undefined')
+
+ const encData = await Bluebird.props(
+ mapValues(sanitizedData, v => {
+ return mySEA.encrypt(v, getMySecret())
+ })
+ )
+
+ getUser()
+ .get(Key.COORDINATES)
+ .get(coordID)
+ .put(encData, ack => {
+ if (ack.err && typeof ack.err !== 'number') {
+ Logger.info(
+ `Error writting corrdinate, coordinate id: ${coordID}, data: ${JSON.stringify(
+ data,
+ null,
+ 2
+ )}`
+ )
+ Logger.error(ack.err)
+ }
+ })
+ } catch (e) {
+ Logger.info(
+ `Error writing coordinate, coordinate id: ${coordID}, data: ${JSON.stringify(
+ data,
+ null,
+ 2
+ )}`
+ )
+ Logger.error(e.message)
+ }
+}
diff --git a/services/gunDB/Mediator/index.js b/services/gunDB/Mediator/index.js
index e4aba797..eddb2466 100644
--- a/services/gunDB/Mediator/index.js
+++ b/services/gunDB/Mediator/index.js
@@ -26,23 +26,13 @@ const SEAx = require('gun/sea')
/** @type {import('../contact-api/SimpleGUN').ISEA} */
const mySEA = {}
-const $$__SHOCKWALLET__MSG__ = '$$__SHOCKWALLET__MSG__'
+// Avoid this: https://github.com/amark/gun/issues/804 and any other issues
const $$__SHOCKWALLET__ENCRYPTED__ = '$$_SHOCKWALLET__ENCRYPTED__'
+const $$__SHOCKWALLET__MSG__ = '$$__SHOCKWALLET__MSG__'
+const $$__SHOCKWALLET__NUMBER__ = '$$__SHOCKWALLET__NUMBER__'
+const $$__SHOCKWALLET__BOOLEAN__ = '$$__SHOCKWALLET__BOOLEAN__'
mySEA.encrypt = (msg, secret) => {
- if (typeof msg !== 'string') {
- throw new TypeError(
- 'mySEA.encrypt() -> expected msg to be an string instead got: ' +
- typeof msg
- )
- }
-
- if (msg.length === 0) {
- throw new TypeError(
- 'mySEA.encrypt() -> expected msg to be a populated string'
- )
- }
-
if (typeof secret !== 'string') {
throw new TypeError(
`mySEA.encrypt() -> expected secret to be a an string, args: |msg| -- ${JSON.stringify(
@@ -57,15 +47,35 @@ mySEA.encrypt = (msg, secret) => {
)
}
- // Avoid this: https://github.com/amark/gun/issues/804 and any other issues
- const sanitizedMsg = $$__SHOCKWALLET__MSG__ + msg
+ let strToEncode = ''
- return SEAx.encrypt(sanitizedMsg, secret).then(encMsg => {
+ if (typeof msg === 'string') {
+ if (msg.length === 0) {
+ throw new TypeError(
+ 'mySEA.encrypt() -> expected msg to be a populated string'
+ )
+ }
+
+ strToEncode = $$__SHOCKWALLET__MSG__ + msg
+ } else if (typeof msg === 'boolean') {
+ strToEncode = $$__SHOCKWALLET__BOOLEAN__ + msg
+ } else if (typeof msg === 'number') {
+ strToEncode = $$__SHOCKWALLET__NUMBER__ + msg
+ } else {
+ throw new TypeError('mySea.encrypt() -> Not a valid msg type.')
+ }
+
+ return SEAx.encrypt(strToEncode, secret).then(encMsg => {
return $$__SHOCKWALLET__ENCRYPTED__ + encMsg
})
}
-mySEA.decrypt = (encMsg, secret) => {
+/**
+ * @param {string} encMsg
+ * @param {string} secret
+ * @returns {Promise}
+ */
+const decryptBase = (encMsg, secret) => {
if (typeof encMsg !== 'string') {
throw new TypeError(
'mySEA.encrypt() -> expected encMsg to be an string instead got: ' +
@@ -104,10 +114,41 @@ mySEA.decrypt = (encMsg, secret) => {
throw new TypeError('Could not decrypt')
}
- return decodedMsg.slice($$__SHOCKWALLET__MSG__.length)
+ if (decodedMsg.startsWith($$__SHOCKWALLET__MSG__)) {
+ return decodedMsg.slice($$__SHOCKWALLET__MSG__.length)
+ } else if (decodedMsg.startsWith($$__SHOCKWALLET__BOOLEAN__)) {
+ const dec = decodedMsg.slice($$__SHOCKWALLET__BOOLEAN__.length)
+ if (dec === 'true') {
+ return true
+ } else if (dec === 'false') {
+ return false
+ }
+ throw new Error('Could not decrypt boolean value.')
+ } else if (decodedMsg.startsWith($$__SHOCKWALLET__NUMBER__)) {
+ return Number(decodedMsg.slice($$__SHOCKWALLET__NUMBER__.length))
+ }
+
+ throw new TypeError(
+ `mySea.encrypt() -> Unexpected type of prefix found inside decrypted value, first 20 characters: ${decodedMsg.slice(
+ 0,
+ 20
+ )}`
+ )
})
}
+mySEA.decrypt = (encMsg, secret) => {
+ return decryptBase(encMsg, secret)
+}
+
+mySEA.decryptNumber = (encMsg, secret) => {
+ return decryptBase(encMsg, secret)
+}
+
+mySEA.decryptBoolean = (encMsg, secret) => {
+ return decryptBase(encMsg, secret)
+}
+
mySEA.secret = async (recipientOrSenderEpub, recipientOrSenderSEA) => {
if (typeof recipientOrSenderEpub !== 'string') {
throw new TypeError(
@@ -273,7 +314,7 @@ const authenticate = async (alias, pass, __user) => {
// clock skew
await new Promise(res => setTimeout(res, 2000))
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
_user.get(Key.FOLLOWS).put(
{
unused: null
@@ -286,7 +327,7 @@ const authenticate = async (alias, pass, __user) => {
}
}
)
- })
+ }))
return ack.sea.pub
} else {
@@ -304,7 +345,7 @@ const authenticate = async (alias, pass, __user) => {
// clock skew
await new Promise(res => setTimeout(res, 2000))
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
_user.get(Key.FOLLOWS).put(
{
unused: null
@@ -317,7 +358,7 @@ const authenticate = async (alias, pass, __user) => {
}
}
)
- })
+ }))
// move this to a subscription; implement off() ? todo
API.Jobs.onAcceptedRequests(_user, mySEA)
@@ -363,7 +404,7 @@ const authenticate = async (alias, pass, __user) => {
await new Promise(res => setTimeout(res, 5000))
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
_user.get(Key.FOLLOWS).put(
{
unused: null
@@ -376,7 +417,7 @@ const authenticate = async (alias, pass, __user) => {
}
}
)
- })
+ }))
API.Jobs.onAcceptedRequests(_user, mySEA)
API.Jobs.onOrders(_user, gun, mySEA)
diff --git a/services/gunDB/contact-api/SimpleGUN.ts b/services/gunDB/contact-api/SimpleGUN.ts
index 6d04fdf7..fee7b196 100644
--- a/services/gunDB/contact-api/SimpleGUN.ts
+++ b/services/gunDB/contact-api/SimpleGUN.ts
@@ -120,8 +120,19 @@ export interface UserGUNNode extends GUNNode {
}
export interface ISEA {
- encrypt(message: string, senderSecret: string): Promise
+ encrypt(
+ message: string | number | boolean,
+ senderSecret: string
+ ): Promise
decrypt(encryptedMessage: string, recipientSecret: string): Promise
+ decryptNumber(
+ encryptedMessage: string,
+ recipientSecret: string
+ ): Promise
+ decryptBoolean(
+ encryptedMessage: string,
+ recipientSecret: string
+ ): Promise
secret(
recipientOrSenderEpub: string,
recipientOrSenderUserPair: UserPair
diff --git a/services/gunDB/contact-api/actions.js b/services/gunDB/contact-api/actions.js
index f784cfe5..e1fd403b 100644
--- a/services/gunDB/contact-api/actions.js
+++ b/services/gunDB/contact-api/actions.js
@@ -11,7 +11,8 @@ const { ErrorCode } = Constants
const {
sendPaymentV2Invoice,
- decodePayReq
+ decodePayReq,
+ myLNDPub
} = require('../../../utils/lightningServices/v2')
/**
@@ -21,6 +22,7 @@ const {
const Getters = require('./getters')
const Key = require('./key')
const Utils = require('./utils')
+const { writeCoordinate } = require('../../coordinates')
/**
* @typedef {import('./SimpleGUN').GUNNode} GUNNode
@@ -98,7 +100,7 @@ const __createOutgoingFeed = async (withPublicKey, user, SEA) => {
timestamp: Date.now()
}
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.OUTGOINGS)
.get(newOutgoingFeedID)
@@ -111,14 +113,14 @@ const __createOutgoingFeed = async (withPublicKey, user, SEA) => {
res()
}
})
- })
+ }))
const encryptedForMeNewOutgoingFeedID = await SEA.encrypt(
newOutgoingFeedID,
mySecret
)
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.RECIPIENT_TO_OUTGOING)
.get(withPublicKey)
@@ -129,7 +131,7 @@ const __createOutgoingFeed = async (withPublicKey, user, SEA) => {
res()
}
})
- })
+ }))
outgoingFeedID = newOutgoingFeedID
}
@@ -235,7 +237,7 @@ const acceptRequest = async (
const mySecret = require('../Mediator').getMySecret()
const encryptedForMeIncomingID = await SEA.encrypt(incomingID, mySecret)
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.USER_TO_INCOMING)
.get(senderPublicKey)
@@ -246,7 +248,7 @@ const acceptRequest = async (
res()
}
})
- })
+ }))
////////////////////////////////////////////////////////////////////////////
// NOTE: perform non-reversable actions before destructive actions
@@ -259,7 +261,7 @@ const acceptRequest = async (
ourSecret
)
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
gun
.get(Key.HANDSHAKE_NODES)
.get(handshakeAddress)
@@ -276,7 +278,7 @@ const acceptRequest = async (
}
}
)
- })
+ }))
}
/**
@@ -285,7 +287,7 @@ const acceptRequest = async (
* @param {UserGUNNode} userNode
*/
const authenticate = (user, pass, userNode) =>
- new Promise((resolve, reject) => {
+ /** @type {Promise} */ (new Promise((resolve, reject) => {
if (typeof user !== 'string') {
throw new TypeError('expected user to be of type string')
}
@@ -315,7 +317,7 @@ const authenticate = (user, pass, userNode) =>
resolve()
}
})
- })
+ }))
/**
* @param {string} publicKey
@@ -347,7 +349,7 @@ const generateHandshakeAddress = async () => {
const address = uuidv1()
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
user.get(Key.CURRENT_HANDSHAKE_ADDRESS).put(address, ack => {
if (ack.err && typeof ack.err !== 'number') {
rej(new Error(ack.err))
@@ -355,9 +357,9 @@ const generateHandshakeAddress = async () => {
res()
}
})
- })
+ }))
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
gun
.get(Key.HANDSHAKE_NODES)
.get(address)
@@ -368,7 +370,7 @@ const generateHandshakeAddress = async () => {
res()
}
})
- })
+ }))
}
/**
@@ -385,7 +387,7 @@ const cleanup = async pub => {
const promises = []
promises.push(
- new Promise((res, rej) => {
+ /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.USER_TO_INCOMING)
.get(pub)
@@ -396,11 +398,11 @@ const cleanup = async pub => {
res()
}
})
- })
+ }))
)
promises.push(
- new Promise((res, rej) => {
+ /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.RECIPIENT_TO_OUTGOING)
.get(pub)
@@ -411,11 +413,11 @@ const cleanup = async pub => {
res()
}
})
- })
+ }))
)
promises.push(
- new Promise((res, rej) => {
+ /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.USER_TO_LAST_REQUEST_SENT)
.get(pub)
@@ -426,12 +428,12 @@ const cleanup = async pub => {
res()
}
})
- })
+ }))
)
if (outGoingID) {
promises.push(
- new Promise((res, rej) => {
+ /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.OUTGOINGS)
.get(outGoingID)
@@ -442,7 +444,7 @@ const cleanup = async pub => {
res()
}
})
- })
+ }))
)
}
@@ -616,7 +618,7 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => {
})
})
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.USER_TO_LAST_REQUEST_SENT)
.get(recipientPublicKey)
@@ -627,7 +629,7 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => {
res()
}
})
- })
+ }))
// This needs to come before the write to sent requests. Because that write
// triggers Jobs.onAcceptedRequests and it in turn reads from request-to-user
@@ -642,7 +644,7 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => {
timestamp
}
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
//@ts-ignore
user.get(Key.STORED_REQS).set(storedReq, ack => {
if (ack.err && typeof ack.err !== 'number') {
@@ -655,7 +657,7 @@ const sendHandshakeRequest = async (recipientPublicKey, gun, user, SEA) => {
res()
}
})
- })
+ }))
}
/**
@@ -922,6 +924,7 @@ const sendHRWithInitialMsg = async (
* @typedef {object} SpontPaymentOptions
* @prop {Common.Schema.OrderTargetType} type
* @prop {string=} postID
+ * @prop {string=} ackInfo
*/
/**
@@ -940,7 +943,7 @@ const sendSpontaneousPayment = async (
amount,
memo,
feeLimit,
- opts = { type: 'user' }
+ opts = { type: 'spontaneousPayment' }
) => {
try {
const SEA = require('../Mediator').mySEA
@@ -965,8 +968,8 @@ const sendSpontaneousPayment = async (
targetType: opts.type
}
- if (opts.type === 'post') {
- order.postID = opts.postID
+ if (opts.type === 'tip') {
+ order.ackInfo = opts.postID
}
logger.info(JSON.stringify(order))
@@ -1074,6 +1077,32 @@ const sendSpontaneousPayment = async (
payment_request: orderResponse.response
})
+ await writeCoordinate(payment.payment_hash, {
+ id: payment.payment_hash,
+ type: (() => {
+ if (opts.type === 'tip') {
+ return 'tip'
+ } else if (opts.type === 'spontaneousPayment') {
+ return 'spontaneousPayment'
+ } else if (opts.type === 'contentReveal') {
+ return 'other' // TODO
+ } else if (opts.type === 'other') {
+ return 'other' // TODO
+ } else if (opts.type === 'torrentSeed') {
+ return 'other' // TODO
+ }
+ // ensures we handle all possible types
+ /** @type {never} */
+ const assertNever = opts.type
+
+ return assertNever && opts.type // please TS
+ })(),
+ amount: Number(payment.value_sat),
+ inbound: false,
+ timestamp: Date.now(),
+ toLndPub: await myLNDPub()
+ })
+
return payment
} catch (e) {
logger.error('Error inside sendPayment()')
@@ -1125,7 +1154,7 @@ const generateOrderAddress = user =>
* @returns {Promise}
*/
const setBio = (bio, user) =>
- new Promise((resolve, reject) => {
+ /** @type {Promise} */ (new Promise((resolve, reject) => {
if (!user.is) {
throw new Error(ErrorCode.NOT_AUTH)
}
@@ -1149,7 +1178,7 @@ const setBio = (bio, user) =>
resolve()
}
})
- }).then(
+ })).then(
() =>
new Promise((resolve, reject) => {
user
@@ -1233,7 +1262,7 @@ const disconnect = async pub => {
* @returns {Promise}
*/
const setLastSeenApp = () =>
- new Promise((res, rej) => {
+ /** @type {Promise} */ (new Promise((res, rej) => {
require('../Mediator')
.getUser()
.get(Key.LAST_SEEN_APP)
@@ -1244,7 +1273,7 @@ const setLastSeenApp = () =>
res()
}
})
- }).then(
+ })).then(
() =>
new Promise((res, rej) => {
require('../Mediator')
@@ -1268,14 +1297,14 @@ const setLastSeenApp = () =>
* @returns {Promise<[string, Common.Schema.RawPost]>}
*/
const createPostNew = async (tags, title, content) => {
+ const SEA = require('../Mediator').mySEA
/** @type {Common.Schema.RawPost} */
const newPost = {
date: Date.now(),
status: 'publish',
tags: tags.join('-'),
title,
- contentItems: {},
- tipCounter: 0
+ contentItems: {}
}
content.forEach(c => {
@@ -1284,6 +1313,23 @@ const createPostNew = async (tags, title, content) => {
newPost.contentItems[uuid] = c
})
+ const mySecret = require('../Mediator').getMySecret()
+
+ await Common.Utils.asyncForEach(content, async c => {
+ // @ts-expect-error
+ const uuid = Gun.text.random()
+ newPost.contentItems[uuid] = c
+ if (
+ (c.type === 'image/embedded' || c.type === 'video/embedded') &&
+ c.isPrivate
+ ) {
+ const encryptedMagnet = await SEA.encrypt(c.magnetURI, mySecret)
+ newPost.contentItems[uuid] = { ...c, magnetURI: encryptedMagnet }
+ } else {
+ newPost.contentItems[uuid] = c
+ }
+ })
+
/** @type {string} */
const postID = await Common.makePromise((res, rej) => {
const _n = require('../Mediator')
@@ -1365,7 +1411,7 @@ const createPost = async (tags, title, content) => {
pageIdx = Number(pageIdx + 1).toString()
}
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
require('../Mediator')
.getUser()
.get(Key.WALL)
@@ -1386,7 +1432,7 @@ const createPost = async (tags, title, content) => {
res()
}
)
- })
+ }))
const [postID, newPost] = await createPostNew(tags, title, content)
@@ -1412,7 +1458,7 @@ const createPost = async (tags, title, content) => {
})
if (shouldBeNewPage || numOfPages === 0) {
- await new Promise(res => {
+ await /** @type {Promise} */ (new Promise(res => {
require('../Mediator')
.getUser()
.get(Key.WALL)
@@ -1424,7 +1470,7 @@ const createPost = async (tags, title, content) => {
res()
})
- })
+ }))
}
const loadedPost = await new Promise(res => {
@@ -1467,7 +1513,7 @@ const createPost = async (tags, title, content) => {
* @returns {Promise}
*/
const deletePost = async (postId, page) => {
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
require('../Mediator')
.getUser()
.get(Key.WALL)
@@ -1482,15 +1528,15 @@ const deletePost = async (postId, page) => {
res()
}
})
- })
+ }))
}
/**
* @param {string} publicKey
* @param {boolean} isPrivate Will overwrite previous private status.
- * @returns {Promise}
+ * @returns {Promise}
*/
-const follow = (publicKey, isPrivate) => {
+const follow = async (publicKey, isPrivate) => {
/** @type {import('shock-common').Schema.Follow} */
const newFollow = {
private: isPrivate,
@@ -1498,7 +1544,7 @@ const follow = (publicKey, isPrivate) => {
user: publicKey
}
- return new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
require('../Mediator')
.getUser()
.get(Key.FOLLOWS)
@@ -1511,7 +1557,7 @@ const follow = (publicKey, isPrivate) => {
res()
}
})
- })
+ }))
}
/**
@@ -1543,7 +1589,7 @@ const initWall = async () => {
const promises = []
promises.push(
- new Promise((res, rej) => {
+ /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.WALL)
.get(Key.NUM_OF_PAGES)
@@ -1554,11 +1600,11 @@ const initWall = async () => {
res()
}
})
- })
+ }))
)
promises.push(
- new Promise((res, rej) => {
+ /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.WALL)
.get(Key.PAGES)
@@ -1576,11 +1622,11 @@ const initWall = async () => {
}
}
)
- })
+ }))
)
promises.push(
- new Promise((res, rej) => {
+ /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.WALL)
.get(Key.PAGES)
@@ -1593,7 +1639,7 @@ const initWall = async () => {
res()
}
})
- })
+ }))
)
await Promise.all(promises)
diff --git a/services/gunDB/contact-api/jobs/onAcceptedRequests.js b/services/gunDB/contact-api/jobs/onAcceptedRequests.js
index ba9cad5a..255cc107 100644
--- a/services/gunDB/contact-api/jobs/onAcceptedRequests.js
+++ b/services/gunDB/contact-api/jobs/onAcceptedRequests.js
@@ -92,7 +92,7 @@ const onAcceptedRequests = (user, SEA) => {
const recipientEpub = await Utils.pubToEpub(recipientPub)
const ourSecret = await SEA.secret(recipientEpub, user._.sea)
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
gun
.get(Key.HANDSHAKE_NODES)
.get(requestAddress)
@@ -151,7 +151,7 @@ const onAcceptedRequests = (user, SEA) => {
mySecret
)
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.USER_TO_INCOMING)
.get(recipientPub)
@@ -162,9 +162,9 @@ const onAcceptedRequests = (user, SEA) => {
res()
}
})
- })
+ }))
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
user
.get(Key.STORED_REQS)
.get(id)
@@ -175,12 +175,12 @@ const onAcceptedRequests = (user, SEA) => {
res()
}
})
- })
+ }))
// ensure this listeners gets called at least once
res()
})
- })
+ }))
} catch (err) {
logger.warn(`Jobs.onAcceptedRequests() -> ${err.message}`)
logger.error(err)
diff --git a/services/gunDB/contact-api/jobs/onOrders.js b/services/gunDB/contact-api/jobs/onOrders.js
index 3a73dd73..ad757ccc 100644
--- a/services/gunDB/contact-api/jobs/onOrders.js
+++ b/services/gunDB/contact-api/jobs/onOrders.js
@@ -1,21 +1,29 @@
/**
* @format
*/
-
-const { performance } = require('perf_hooks')
+// @ts-check
const logger = require('winston')
const isFinite = require('lodash/isFinite')
const isNumber = require('lodash/isNumber')
const isNaN = require('lodash/isNaN')
+const Common = require('shock-common')
const {
Constants: { ErrorCode },
Schema
-} = require('shock-common')
+} = Common
+const { assertNever } = require('assert-never')
+const crypto = require('crypto')
+const fetch = require('node-fetch')
const LightningServices = require('../../../../utils/lightningServices')
-
+const {
+ addInvoice,
+ myLNDPub
+} = require('../../../../utils/lightningServices/v2')
+const { writeCoordinate } = require('../../../coordinates')
const Key = require('../key')
const Utils = require('../utils')
+const { gunUUID } = require('../../../../utils')
const getUser = () => require('../../Mediator').getUser()
@@ -55,28 +63,6 @@ const ordersProcessed = new Set()
let currentOrderAddr = ''
-/**
- * @param {InvoiceRequest} invoiceReq
- * @returns {Promise}
- */
-const _addInvoice = invoiceReq =>
- new Promise((resolve, rej) => {
- const {
- services: { lightning }
- } = LightningServices
-
- lightning.addInvoice(invoiceReq, (
- /** @type {any} */ error,
- /** @type {InvoiceResponse} */ response
- ) => {
- if (error) {
- rej(error)
- } else {
- resolve(response)
- }
- })
- })
-
/**
* @param {string} addr
* @param {ISEA} SEA
@@ -103,8 +89,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
return
}
- const listenerStartTime = performance.now()
-
ordersProcessed.add(orderID)
logger.info(
@@ -113,8 +97,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
)} -- addr: ${addr}`
)
- const orderAnswerStartTime = performance.now()
-
const alreadyAnswered = await getUser()
.get(Key.ORDER_TO_RESPONSE)
.get(orderID)
@@ -125,12 +107,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
return
}
- const orderAnswerEndTime = performance.now() - orderAnswerStartTime
-
- logger.info(`[PERF] Order Already Answered: ${orderAnswerEndTime}ms`)
-
- const decryptStartTime = performance.now()
-
const senderEpub = await Utils.pubToEpub(order.from)
const secret = await SEA.secret(senderEpub, getUser()._.sea)
@@ -139,10 +115,6 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
SEA.decrypt(order.memo, secret)
])
- const decryptEndTime = performance.now() - decryptStartTime
-
- logger.info(`[PERF] Decrypt invoice info: ${decryptEndTime}ms`)
-
const amount = Number(decryptedAmount)
if (!isNumber(amount)) {
@@ -174,26 +146,19 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
`onOrders() -> Will now create an invoice : ${JSON.stringify(invoiceReq)}`
)
- const invoiceStartTime = performance.now()
-
- const invoice = await _addInvoice(invoiceReq)
-
- const invoiceEndTime = performance.now() - invoiceStartTime
-
- logger.info(`[PERF] LND Invoice created in ${invoiceEndTime}ms`)
+ const invoice = await addInvoice(
+ invoiceReq.value,
+ invoiceReq.memo,
+ true,
+ invoiceReq.expiry
+ )
logger.info(
'onOrders() -> Successfully created the invoice, will now encrypt it'
)
- const invoiceEncryptStartTime = performance.now()
-
const encInvoice = await SEA.encrypt(invoice.payment_request, secret)
- const invoiceEncryptEndTime = performance.now() - invoiceEncryptStartTime
-
- logger.info(`[PERF] Invoice encrypted in ${invoiceEncryptEndTime}ms`)
-
logger.info(
`onOrders() -> Will now place the encrypted invoice in order to response usergraph: ${addr}`
)
@@ -204,9 +169,7 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
type: 'invoice'
}
- const invoicePutStartTime = performance.now()
-
- await new Promise((res, rej) => {
+ await /** @type {Promise} */ (new Promise((res, rej) => {
getUser()
.get(Key.ORDER_TO_RESPONSE)
.get(orderID)
@@ -222,34 +185,231 @@ const listenerForAddr = (addr, SEA) => async (order, orderID) => {
res()
}
})
+ }))
+
+ // invoices should be settled right away so we can rely on this single
+ // subscription instead of life-long all invoices subscription
+ if (order.targetType === 'tip') {
+ const { ackInfo } = order
+ if (!Common.isPopulatedString(ackInfo)) {
+ throw new TypeError(`ackInfo(postID) not a a populated string`)
+ }
+ }
+
+ // A post tip order lifecycle is short enough that we can do it like this.
+ const stream = LightningServices.invoices.subscribeSingleInvoice({
+ r_hash: invoice.r_hash
})
- const invoicePutEndTime = performance.now() - invoicePutStartTime
-
- logger.info(`[PERF] Added invoice to GunDB in ${invoicePutEndTime}ms`)
-
- const listenerEndTime = performance.now() - listenerStartTime
-
- logger.info(`[PERF] Invoice generation completed in ${listenerEndTime}ms`)
-
- const hash = invoice.r_hash.toString('base64')
-
- if (order.targetType === 'post') {
- /** @type {TipPaymentStatus} */
- const paymentStatus = {
- hash,
- state: 'OPEN',
- targetType: order.targetType,
- postID: order.postID
- }
- getUser()
- .get(Key.TIPS_PAYMENT_STATUS)
- .get(hash)
- // @ts-ignore
- .put(paymentStatus, response => {
- console.log(response)
- })
+ /** @type {Common.Coordinate} */
+ const coord = {
+ amount,
+ id: invoice.r_hash.toString(),
+ inbound: true,
+ timestamp: Date.now(),
+ type: 'invoice',
+ invoiceMemo: memo,
+ fromGunPub: order.from,
+ toGunPub: getUser()._.sea.pub,
+ toLndPub: await myLNDPub()
}
+
+ if (order.targetType === 'tip') {
+ coord.type = 'tip'
+ } else {
+ coord.type = 'spontaneousPayment'
+ }
+
+ /**
+ * @param {Common.InvoiceWhenListed} invoice
+ */
+ const onData = async invoice => {
+ if (invoice.settled) {
+ writeCoordinate(invoice.r_hash.toString(), coord)
+
+ if (order.targetType === 'tip') {
+ getUser()
+ .get('postToTipCount')
+ // CAST: Checked above.
+ .get(/** @type {string} */ (order.ackInfo))
+ .set(null) // each item in the set is a tip
+ } else if (order.targetType === 'contentReveal') {
+ // -----------------------------------------
+ logger.debug('Content Reveal')
+
+ //assuming digital product that only requires to be unlocked
+ const postID = order.ackInfo
+
+ if (!Common.isPopulatedString(postID)) {
+ logger.error(`Invalid post ID`)
+ logger.error(postID)
+ return
+ }
+
+ // TODO: do this reactively
+ const selectedPost = await new Promise(res => {
+ getUser()
+ .get(Key.POSTS_NEW)
+ .get(postID)
+ .load(res)
+ })
+
+ logger.debug(selectedPost)
+
+ if (Common.isPost(selectedPost)) {
+ logger.error('Post id provided does not correspond to a valid post')
+ return
+ }
+
+ /**
+ * @type {Record}
+ */
+ const contentsToSend = {}
+ const mySecret = require('../../Mediator').getMySecret()
+ logger.debug('SECRET OK')
+ let privateFound = false
+ await Common.Utils.asyncForEach(
+ Object.entries(selectedPost.contentItems),
+ async ([contentID, item]) => {
+ if (
+ item.type !== 'image/embedded' &&
+ item.type !== 'video/embedded'
+ ) {
+ return //only visual content can be private
+ }
+ if (!item.isPrivate) {
+ return
+ }
+ privateFound = true
+ const decrypted = await SEA.decrypt(item.magnetURI, mySecret)
+ contentsToSend[contentID] = decrypted
+ }
+ )
+ if (!privateFound) {
+ logger.error(`Post provided does not contain private content`)
+ return
+ }
+ const ackData = { unlockedContents: contentsToSend }
+ const toSend = JSON.stringify(ackData)
+ const encrypted = await SEA.encrypt(toSend, secret)
+ const ordResponse = {
+ type: 'orderAck',
+ response: encrypted
+ }
+ logger.debug('RES READY')
+
+ const uuid = gunUUID()
+ orderResponse.ackNode = uuid
+
+ await /** @type {Promise} */ (new Promise((res, rej) => {
+ getUser()
+ .get(Key.ORDER_TO_RESPONSE)
+ .get(uuid)
+ .put(ordResponse, ack => {
+ if (ack.err && typeof ack.err !== 'number') {
+ rej(
+ new Error(
+ `Error saving encrypted orderAck to order to response usergraph: ${ack}`
+ )
+ )
+ } else {
+ res()
+ }
+ })
+ }))
+ logger.debug('RES SENT CONTENT')
+
+ // ----------------------------------------------------------------------------------
+ } else if (order.targetType === 'spontaneousPayment') {
+ // no action required
+ } else if (order.targetType === 'torrentSeed') {
+ logger.debug('TORRENT')
+ const numberOfTokens = Number(order.ackInfo)
+ if (isNaN(numberOfTokens)) {
+ logger.error('ackInfo provided is not a valid number')
+ return
+ }
+ const seedUrl = process.env.TORRENT_SEED_URL
+ const seedToken = process.env.TORRENT_SEED_TOKEN
+ if (!seedUrl || !seedToken) {
+ logger.error('torrentSeed service not available')
+ return
+ }
+ logger.debug('SEED URL OK')
+ const tokens = Array(numberOfTokens)
+ for (let i = 0; i < numberOfTokens; i++) {
+ tokens[i] = crypto.randomBytes(32).toString('hex')
+ }
+ /**@param {string} token */
+ const enrollToken = async token => {
+ const reqData = {
+ seed_token: seedToken,
+ wallet_token: token
+ }
+ // @ts-expect-error TODO
+ const res = await fetch(`${seedUrl}/api/enroll_token`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(reqData)
+ })
+ if (res.status !== 200) {
+ throw new Error('torrentSeed service currently not available')
+ }
+ }
+ await Promise.all(tokens.map(enrollToken))
+ logger.debug('RES SEED OK')
+ const ackData = { seedUrl, tokens }
+ const toSend = JSON.stringify(ackData)
+ const encrypted = await SEA.encrypt(toSend, secret)
+ const serviceResponse = {
+ type: 'orderAck',
+ response: encrypted
+ }
+ console.log('RES SEED SENT')
+
+ const uuid = gunUUID()
+ orderResponse.ackNode = uuid
+
+ await /** @type {Promise} */ (new Promise((res, rej) => {
+ getUser()
+ .get(Key.ORDER_TO_RESPONSE)
+ .get(uuid)
+ .put(serviceResponse, ack => {
+ if (ack.err && typeof ack.err !== 'number') {
+ rej(
+ new Error(
+ `Error saving encrypted orderAck to order to response usergraph: ${ack}`
+ )
+ )
+ } else {
+ res()
+ }
+ })
+ }))
+ logger.debug('RES SENT SEED')
+ } else if (order.targetType === 'other') {
+ // TODO
+ } else {
+ assertNever(order.targetType)
+ }
+
+ stream.off()
+ }
+ }
+
+ stream.on('data', onData)
+
+ stream.on('status', (/** @type {any} */ status) => {
+ logger.info(`Post tip, post: ${order.ackInfo}, invoice status:`, status)
+ })
+ stream.on('end', () => {
+ logger.warn(`Post tip, post: ${order.ackInfo}, invoice stream ended`)
+ })
+ stream.on('error', (/** @type {any} */ e) => {
+ logger.warn(`Post tip, post: ${order.ackInfo}, error:`, e)
+ })
} catch (err) {
logger.error(
`error inside onOrders, orderAddr: ${addr}, orderID: ${orderID}, order: ${JSON.stringify(
diff --git a/services/gunDB/contact-api/key.js b/services/gunDB/contact-api/key.js
index ece0c1ed..210fae06 100644
--- a/services/gunDB/contact-api/key.js
+++ b/services/gunDB/contact-api/key.js
@@ -59,8 +59,8 @@ exports.POSTS = 'posts'
// Tips counter for posts
exports.TOTAL_TIPS = 'totalTips'
-exports.TIPS_PAYMENT_STATUS = 'tipsPaymentStatus'
-
exports.PROFILE_BINARY = 'profileBinary'
exports.POSTS_NEW = 'posts'
+
+exports.COORDINATES = 'coordinates'
diff --git a/services/gunDB/contact-api/utils/index.js b/services/gunDB/contact-api/utils/index.js
index bcab3105..3af89742 100644
--- a/services/gunDB/contact-api/utils/index.js
+++ b/services/gunDB/contact-api/utils/index.js
@@ -212,29 +212,19 @@ const tryAndWait = async (promGen, shouldRetry = () => false) => {
*/
const pubToEpub = async pub => {
try {
- const epub = await tryAndWait(async gun => {
- const _epub = await CommonUtils.makePromise(res => {
- gun
+ const epub = await timeout10(
+ CommonUtils.makePromise(res => {
+ require('../../Mediator/index')
+ .getGun()
.user(pub)
.get('epub')
- .once(
- data => {
+ .on(data => {
+ if (typeof data === 'string') {
res(data)
- },
- {
- wait: 1000
}
- )
+ })
})
-
- if (typeof _epub !== 'string') {
- throw new TypeError(
- `Expected gun.user(pub).get(epub) to be an string. Instead got: ${typeof _epub}`
- )
- }
-
- return _epub
- })
+ )
return epub
} catch (err) {
diff --git a/services/lnd/lightning.js b/services/lnd/lightning.js
index caf232f2..18237d44 100644
--- a/services/lnd/lightning.js
+++ b/services/lnd/lightning.js
@@ -1,5 +1,5 @@
const Path = require("path");
-const grpc = require("grpc");
+const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");
const logger = require("winston");
const fs = require("../../utils/fs");
@@ -10,6 +10,7 @@ const errorConstants = require("../../constants/errors");
* @typedef LightningConfig
* @prop {string} lnrpcProtoPath
* @prop {string} routerProtoPath
+ * @prop {string} invoicesProtoPath
* @prop {string} walletUnlockerProtoPath
* @prop {string} lndHost
* @prop {string} lndCertPath
@@ -21,6 +22,7 @@ const errorConstants = require("../../constants/errors");
* @prop {any} lightning
* @prop {any} walletUnlocker
* @prop {any} router
+ * @prop {any} invoices
*/
/**
@@ -30,10 +32,11 @@ const errorConstants = require("../../constants/errors");
module.exports = async ({
lnrpcProtoPath,
routerProtoPath,
+ invoicesProtoPath,
walletUnlockerProtoPath,
- lndHost,
- lndCertPath,
- macaroonPath
+ lndHost,
+ lndCertPath,
+ macaroonPath
}) => {
try {
process.env.GRPC_SSL_CIPHER_SUITES = "HIGH+ECDSA";
@@ -46,9 +49,15 @@ module.exports = async ({
includeDirs: ["node_modules/google-proto-files", "proto", Path.resolve(__dirname, "../../config")]
}
- const [lnrpcProto, routerProto, walletUnlockerProto] = await Promise.all([protoLoader.load(lnrpcProtoPath, protoLoaderConfig), protoLoader.load(routerProtoPath, protoLoaderConfig), protoLoader.load(walletUnlockerProtoPath, protoLoaderConfig)]);
+ const [lnrpcProto, routerProto, walletUnlockerProto, invoicesProto] = await Promise.all([
+ protoLoader.load(lnrpcProtoPath, protoLoaderConfig),
+ protoLoader.load(routerProtoPath, protoLoaderConfig),
+ protoLoader.load(walletUnlockerProtoPath, protoLoaderConfig),
+ protoLoader.load(invoicesProtoPath, protoLoaderConfig)
+ ]);
const { lnrpc } = grpc.loadPackageDefinition(lnrpcProto);
const { routerrpc } = grpc.loadPackageDefinition(routerProto);
+ const { invoicesrpc } = grpc.loadPackageDefinition(invoicesProto);
const { lnrpc: walletunlockerrpc } = grpc.loadPackageDefinition(walletUnlockerProto);
const getCredentials = async () => {
@@ -93,11 +102,13 @@ module.exports = async ({
const walletUnlocker = new walletunlockerrpc.WalletUnlocker(lndHost, credentials);
// @ts-ignore
const router = new routerrpc.Router(lndHost, credentials);
-
+ // @ts-ignore
+ const invoices = new invoicesrpc.Invoices(lndHost, credentials);
return {
lightning,
walletUnlocker,
- router
+ router,
+ invoices
};
}
diff --git a/services/lnd/lnd.js b/services/lnd/lnd.js
deleted file mode 100644
index da5ffe51..00000000
--- a/services/lnd/lnd.js
+++ /dev/null
@@ -1,80 +0,0 @@
-// app/lnd.js
-
-const logger = require("winston");
-
-// TODO
-module.exports = function(lightning) {
- const module = {};
-
- const invoiceListeners = [];
-
- let lndInvoicesStream = null;
-
- const openLndInvoicesStream = function() {
- if (lndInvoicesStream) {
- logger.debug("Lnd invoices subscription stream already opened.");
- } else {
- logger.debug("Opening lnd invoices subscription stream...");
- lndInvoicesStream = lightning.subscribeInvoices({});
- logger.debug("Lnd invoices subscription stream opened.");
- lndInvoicesStream.on("data", function(data) {
- logger.debug("SubscribeInvoices Data", data);
- for (let i = 0; i < invoiceListeners.length; i++) {
- try {
- invoiceListeners[i].dataReceived(data);
- } catch (err) {
- logger.warn(err);
- }
- }
- });
- lndInvoicesStream.on("end", function() {
- logger.debug("SubscribeInvoices End");
- lndInvoicesStream = null;
- openLndInvoicesStream(); // try opening stream again
- });
- lndInvoicesStream.on("error", function(err) {
- logger.debug("SubscribeInvoices Error", err);
- });
- lndInvoicesStream.on("status", function(status) {
- logger.debug("SubscribeInvoices Status", status);
- if (status.code == 14) {
- // Unavailable
- lndInvoicesStream = null;
- openLndInvoicesStream(); // try opening stream again
- }
- });
- }
- };
-
- // register invoice listener
- module.registerInvoiceListener = function(listener) {
- invoiceListeners.push(listener);
- logger.debug(
- "New lnd invoice listener registered, " +
- invoiceListeners.length +
- " listening now"
- );
- };
-
- // unregister invoice listener
- module.unregisterInvoiceListener = function(listener) {
- invoiceListeners.splice(invoiceListeners.indexOf(listener), 1);
- logger.debug(
- "Lnd invoice listener unregistered, " +
- invoiceListeners.length +
- " still listening"
- );
- };
-
- // open lnd invoices stream on start
- openLndInvoicesStream();
-
- // check every minute that lnd invoices stream is still opened
- setInterval(function() {
- if (!lndInvoicesStream) {
- openLndInvoicesStream();
- }
- }, 60 * 1000);
-
- return module;
-};
diff --git a/src/__gun__tests__/mySea.ts b/src/__gun__tests__/mySea.ts
new file mode 100644
index 00000000..f2f2af21
--- /dev/null
+++ b/src/__gun__tests__/mySea.ts
@@ -0,0 +1,109 @@
+/**
+ * @format
+ */
+import Gun from 'gun'
+import uuid from 'uuid/v1'
+
+import { mySEA } from '../../services/gunDB/Mediator'
+import { UserGUNNode } from '../../services/gunDB/contact-api/SimpleGUN'
+
+const setupUser = async (): Promise<[UserGUNNode]> => {
+ const gun = Gun({
+ file: 'GUN-TEST-' + uuid()
+ })
+
+ const user = (gun.user() as unknown) as UserGUNNode
+
+ await new Promise((res, rej) => {
+ user.create('testAlias-' + uuid(), 'testPass', ack => {
+ if (typeof ack.err === 'string') {
+ rej(new Error(ack.err))
+ } else {
+ res()
+ }
+ })
+ })
+
+ return [user]
+}
+
+const encryptsDecryptsStrings = async () => {
+ const [user] = await setupUser()
+
+ const stringMessage = 'Lorem ipsum dolor'
+
+ const sec = await mySEA.secret(user._.sea.epub, user._.sea)
+ const encrypted = await mySEA.encrypt(stringMessage, sec)
+ const decrypted = await mySEA.decrypt(encrypted, sec)
+
+ if (decrypted !== stringMessage) {
+ throw new Error()
+ }
+}
+
+const encryptsDecryptsBooleans = async () => {
+ const [user] = await setupUser()
+
+ const truth = true
+ const lie = false
+
+ const sec = await mySEA.secret(user._.sea.epub, user._.sea)
+
+ const encryptedTruth = await mySEA.encrypt(truth, sec)
+ const decryptedTruth = await mySEA.decryptBoolean(encryptedTruth, sec)
+
+ if (decryptedTruth !== truth) {
+ throw new Error()
+ }
+
+ const encryptedLie = await mySEA.encrypt(lie, sec)
+ const decryptedLie = await mySEA.decryptBoolean(encryptedLie, sec)
+
+ if (decryptedLie !== lie) {
+ throw new Error(
+ `Expected false got: ${decryptedLie} - ${typeof decryptedLie}`
+ )
+ }
+}
+
+const encryptsDecryptsNumbers = async () => {
+ const [user] = await setupUser()
+
+ const number = Math.random() * 999999
+
+ const sec = await mySEA.secret(user._.sea.epub, user._.sea)
+ const encrypted = await mySEA.encrypt(number, sec)
+ const decrypted = await mySEA.decryptNumber(encrypted, sec)
+
+ if (decrypted !== number) {
+ throw new Error()
+ }
+}
+
+const encryptsDecryptsZero = async () => {
+ const [user] = await setupUser()
+
+ const zero = 0
+
+ const sec = await mySEA.secret(user._.sea.epub, user._.sea)
+ const encrypted = await mySEA.encrypt(zero, sec)
+ const decrypted = await mySEA.decryptNumber(encrypted, sec)
+
+ if (decrypted !== zero) {
+ throw new Error()
+ }
+}
+
+const runAllTests = async () => {
+ await encryptsDecryptsStrings()
+ await encryptsDecryptsBooleans()
+ await encryptsDecryptsNumbers()
+ await encryptsDecryptsZero()
+
+ console.log('\n--------------------------------')
+ console.log('All tests ran successfully')
+ console.log('--------------------------------\n')
+ process.exit(0)
+}
+
+runAllTests()
diff --git a/src/routes.js b/src/routes.js
index 2fd43091..a79b5eb7 100644
--- a/src/routes.js
+++ b/src/routes.js
@@ -30,12 +30,7 @@ const {
const GunActions = require('../services/gunDB/contact-api/actions')
const GunGetters = require('../services/gunDB/contact-api/getters')
const GunKey = require('../services/gunDB/contact-api/key')
-const {
- sendPaymentV2Keysend,
- sendPaymentV2Invoice,
- listPayments
-} = require('../utils/lightningServices/v2')
-const { startTipStatusJob } = require('../utils/lndJobs')
+const LV2 = require('../utils/lightningServices/v2')
const GunWriteRPC = require('../services/gunDB/rpc')
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10
@@ -690,7 +685,6 @@ module.exports = async (
}
onNewChannelBackup()
- startTipStatusJob()
res.json({
authorization: token,
@@ -1026,30 +1020,15 @@ module.exports = async (
)
})
// get lnd chan info
- app.post('/api/lnd/getchaninfo', (req, res) => {
- const { lightning } = LightningServices.services
-
- lightning.getChanInfo(
- { chan_id: req.body.chan_id },
- async (err, response) => {
- if (err) {
- logger.debug('GetChanInfo Error:', err)
- const health = await checkHealth()
- if (health.LNDStatus.success) {
- res.status(400)
- res.json({
- field: 'getChanInfo',
- errorMessage: sanitizeLNDError(err.message)
- })
- } else {
- res.status(500)
- res.json({ errorMessage: 'LND is down' })
- }
- }
- logger.debug('GetChanInfo:', response)
- res.json(response)
- }
- )
+ app.post('/api/lnd/getchaninfo', async (req, res) => {
+ try {
+ return res.json(await LV2.getChanInfo(req.body.chan_id))
+ } catch (e) {
+ console.log(e)
+ return res.status(500).json({
+ errorMessage: e.message
+ })
+ }
})
app.get('/api/lnd/getnetworkinfo', (req, res) => {
@@ -1074,47 +1053,30 @@ module.exports = async (
})
// get lnd node active channels list
- app.get('/api/lnd/listpeers', (req, res) => {
- const { lightning } = LightningServices.services
- lightning.listPeers({}, async (err, response) => {
- if (err) {
- logger.debug('ListPeers Error:', err)
- const health = await checkHealth()
- if (health.LNDStatus.success) {
- res.status(400).json({
- field: 'listPeers',
- errorMessage: sanitizeLNDError(err.message)
- })
- } else {
- res.status(500)
- res.json({ errorMessage: 'LND is down' })
- }
- }
- logger.debug('ListPeers:', response)
- res.json(response)
- })
+ app.get('/api/lnd/listpeers', async (req, res) => {
+ try {
+ return res.json({
+ peers: await LV2.listPeers(req.body.latestError)
+ })
+ } catch (e) {
+ console.log(e)
+ return res.status(500).json({
+ errorMessage: e.message
+ })
+ }
})
// newaddress
- app.post('/api/lnd/newaddress', (req, res) => {
- const { lightning } = LightningServices.services
- lightning.newAddress({ type: req.body.type }, async (err, response) => {
- if (err) {
- logger.debug('NewAddress Error:', err)
- const health = await checkHealth()
- if (health.LNDStatus.success) {
- res.status(400).json({
- field: 'newAddress',
- errorMessage: sanitizeLNDError(err.message)
- })
- } else {
- res.status(500)
- res.json({ errorMessage: 'LND is down' })
- }
- }
- logger.debug('NewAddress:', response)
- res.json(response)
- })
+ app.post('/api/lnd/newaddress', async (req, res) => {
+ try {
+ return res.json({
+ address: await LV2.newAddress(req.body.type)
+ })
+ } catch (e) {
+ return res.status(500).json({
+ errorMessage: e.message
+ })
+ }
})
// connect peer to lnd node
@@ -1159,47 +1121,28 @@ module.exports = async (
})
// get lnd node opened channels list
- app.get('/api/lnd/listchannels', (req, res) => {
- const { lightning } = LightningServices.services
- lightning.listChannels({}, async (err, response) => {
- if (err) {
- logger.debug('ListChannels Error:', err)
- const health = await checkHealth()
- if (health.LNDStatus.success) {
- res.status(400).json({
- field: 'listChannels',
- errorMessage: sanitizeLNDError(err.message)
- })
- } else {
- res.status(500)
- res.json({ errorMessage: 'LND is down' })
- }
- }
- logger.debug('ListChannels:', response)
- res.json(response)
- })
+ app.get('/api/lnd/listchannels', async (_, res) => {
+ try {
+ return res.json({
+ channels: await LV2.listChannels()
+ })
+ } catch (e) {
+ console.log(e)
+ return res.status(500).json({
+ errorMessage: e.message
+ })
+ }
})
- // get lnd node pending channels list
- app.get('/api/lnd/pendingchannels', (req, res) => {
- const { lightning } = LightningServices.services
- lightning.pendingChannels({}, async (err, response) => {
- if (err) {
- logger.debug('PendingChannels Error:', err)
- const health = await checkHealth()
- if (health.LNDStatus.success) {
- res.status(400).json({
- field: 'pendingChannels',
- errorMessage: sanitizeLNDError(err.message)
- })
- } else {
- res.status(500)
- res.json({ errorMessage: 'LND is down' })
- }
- }
- logger.debug('PendingChannels:', response)
- res.json(response)
- })
+ app.get('/api/lnd/pendingchannels', async (req, res) => {
+ try {
+ return res.json(await LV2.pendingChannels())
+ } catch (e) {
+ console.log(e)
+ return res.status(500).json({
+ errorMessage: e.message
+ })
+ }
})
app.get('/api/lnd/unifiedTrx', (req, res) => {
@@ -1249,12 +1192,35 @@ module.exports = async (
app.post('/api/lnd/unifiedTrx', async (req, res) => {
try {
- const { type, amt, to, memo, feeLimit, postID } = req.body
+ const { type, amt, to, memo, feeLimit, postID, ackInfo } = req.body
- if (type !== 'spont' && type !== 'post') {
+ if (
+ type !== 'spont' &&
+ type !== 'post' &&
+ type !== 'spontaneousPayment' &&
+ type !== 'tip' &&
+ type !== 'torrentSeed' &&
+ type !== 'contentReveal' &&
+ type !== 'other'
+ ) {
return res.status(415).json({
field: 'type',
- errorMessage: `Only 'spont' and 'post' payments supported via this endpoint for now.`
+ errorMessage: `Only 'spontaneousPayment'| 'tip' | 'torrentSeed' | 'contentReveal' | 'other' payments supported via this endpoint for now.`
+ })
+ }
+
+ const typesThatShouldContainAckInfo = [
+ 'tip',
+ 'torrentSeed',
+ 'contentReveal'
+ ]
+
+ const shouldContainAckInfo = typesThatShouldContainAckInfo.includes(type)
+
+ if (shouldContainAckInfo && !Common.isPopulatedString(ackInfo)) {
+ return res.status(400).json({
+ field: 'ackInfo',
+ errorMessage: `Transactions of type ${typesThatShouldContainAckInfo} should contain an ackInfo field.`
})
}
@@ -1298,7 +1264,8 @@ module.exports = async (
return res.status(200).json(
await GunActions.sendSpontaneousPayment(to, amt, memo, feeLimit, {
type,
- postID
+ postID,
+ ackInfo
})
)
} catch (e) {
@@ -1377,7 +1344,7 @@ module.exports = async (
}
return res.status(200).json(
- await listPayments({
+ await LV2.listPayments({
include_incomplete,
index_offset,
max_payments,
@@ -1664,7 +1631,7 @@ module.exports = async (
})
}
- const payment = await sendPaymentV2Keysend({
+ const payment = await LV2.sendPaymentV2Keysend({
amt,
dest,
feeLimit,
@@ -1677,7 +1644,7 @@ module.exports = async (
}
const { payreq } = req.body
- const payment = await sendPaymentV2Invoice({
+ const payment = await LV2.sendPaymentV2Invoice({
feeLimit,
payment_request: payreq,
amt: req.body.amt,
@@ -1766,64 +1733,32 @@ module.exports = async (
})
// addinvoice
- app.post('/api/lnd/addinvoice', (req, res) => {
- const { lightning } = LightningServices.services
- const invoiceRequest = { memo: req.body.memo, private: true }
- if (req.body.value) {
- invoiceRequest.value = req.body.value
- }
- if (req.body.expiry) {
- invoiceRequest.expiry = req.body.expiry
- }
- lightning.addInvoice(invoiceRequest, async (err, newInvoice) => {
- if (err) {
- logger.debug('AddInvoice Error:', err)
- const health = await checkHealth()
- if (health.LNDStatus.success) {
- res.status(400).json({
- field: 'addInvoice',
- errorMessage: sanitizeLNDError(err.message)
- })
- } else {
- res.status(500)
- res.json({ errorMessage: 'LND is down' })
+ app.post('/api/lnd/addinvoice', async (req, res) => {
+ const { expiry, value, memo } = req.body
+ const addInvoiceRes = await LV2.addInvoice(value, memo, true, expiry)
+
+ if (value) {
+ const channelsList = await LV2.listChannels({ active_only: true })
+ let remoteBalance = Big(0)
+ channelsList.forEach(element => {
+ const remB = Big(element.remote_balance)
+ if (remB.gt(remoteBalance)) {
+ remoteBalance = remB
}
- return err
- }
- logger.debug('AddInvoice:', newInvoice)
- if (req.body.value) {
- logger.debug('AddInvoice liquidity check:')
- lightning.listChannels({ active_only: true }, async (err, response) => {
- if (err) {
- logger.debug('ListChannels Error:', err)
- const health = await checkHealth()
- if (health.LNDStatus.success) {
- res.status(400).json({
- field: 'listChannels',
- errorMessage: sanitizeLNDError(err.message)
- })
- } else {
- res.status(500)
- res.json({ errorMessage: 'LND is down' })
- }
- }
- logger.debug('ListChannels:', response)
- const channelsList = response.channels
- let remoteBalance = Big(0)
- channelsList.forEach(element => {
- const remB = Big(element.remote_balance)
- if (remB.gt(remoteBalance)) {
- remoteBalance = remB
- }
- })
- newInvoice.liquidityCheck = remoteBalance > req.body.value
- //newInvoice.remoteBalance = remoteBalance
- res.json(newInvoice)
- })
- } else {
- res.json(newInvoice)
- }
- })
+ })
+
+ addInvoiceRes.liquidityCheck = remoteBalance > value
+ //newInvoice.remoteBalance = remoteBalance
+ }
+
+ try {
+ return res.json(addInvoiceRes)
+ } catch (e) {
+ console.log(e)
+ return res.status(500).json({
+ errorMessage: e.message
+ })
+ }
})
// signmessage
@@ -1882,7 +1817,8 @@ module.exports = async (
const sendCoinsRequest = {
addr: req.body.addr,
amount: req.body.amount,
- sat_per_byte: req.body.satPerByte
+ sat_per_byte: req.body.satPerByte,
+ send_all: req.body.send_all === true
}
logger.debug('SendCoins', sendCoinsRequest)
lightning.sendCoins(sendCoinsRequest, async (err, response) => {
@@ -1960,23 +1896,25 @@ module.exports = async (
)
})
- app.post('/api/lnd/listunspent', (req, res) => {
- const { lightning } = LightningServices.services
- const { minConfirmations = 3, maxConfirmations = 6 } = req.body
- lightning.listUnspent(
- {
- min_confs: minConfirmations,
- max_confs: maxConfirmations
- },
- (err, unspent) => {
- if (err) {
- return handleError(res, err)
- }
- logger.debug('ListUnspent:', unspent)
- res.json(unspent)
- }
- )
- })
+ const listunspent = async (req, res) => {
+ try {
+ return res.status(200).json({
+ utxos: await LV2.listUnspent(
+ req.body.minConfirmations,
+ req.body.maxConfirmations
+ )
+ })
+ } catch (e) {
+ return res.status(500).json({
+ errorMessage: e.message
+ })
+ }
+ }
+
+ app.get('/api/lnd/listunspent', listunspent)
+
+ // TODO: should be GET
+ app.post('/api/lnd/listunspent', listunspent)
app.get('/api/lnd/transactions', (req, res) => {
const { lightning } = LightningServices.services
diff --git a/src/server.js b/src/server.js
index 6e514a98..4917bcd1 100644
--- a/src/server.js
+++ b/src/server.js
@@ -167,10 +167,6 @@ const server = program => {
await LightningServices.init()
}
- // init lnd module =================
- const lnd = require('../services/lnd/lnd')(
- LightningServices.services.lightning
- )
await new Promise((resolve, reject) => {
LightningServices.services.lightning.getInfo({}, (err, res) => {
if (err && err.code !== 12) {
diff --git a/src/sockets.js b/src/sockets.js
index 54537af8..f1a90196 100644
--- a/src/sockets.js
+++ b/src/sockets.js
@@ -66,66 +66,6 @@ module.exports = (
}
}
- const parseJSON = data => {
- try {
- if (typeof data === 'string') {
- return JSON.parse(data)
- }
-
- return data
- } catch (err) {
- return data
- }
- }
-
- const decryptEvent = ({ eventName, data, socket }) => {
- try {
- const deviceId = socket.handshake.query['x-shockwallet-device-id']
- if (Encryption.isNonEncrypted(eventName)) {
- return data
- }
-
- if (!data) {
- return data
- }
-
- const parsedData = parseJSON(data)
-
- if (!deviceId) {
- throw {
- field: 'deviceId',
- message: 'Please specify a device ID'
- }
- }
-
- if (!Encryption.isAuthorizedDevice({ deviceId })) {
- throw {
- field: 'deviceId',
- message: 'Please exchange keys with the API before using the socket'
- }
- }
-
- const decryptedKey = Encryption.decryptKey({
- deviceId,
- message: parsedData.encryptedKey
- })
- const decryptedMessage = Encryption.decryptMessage({
- message: parsedData.encryptedData,
- key: decryptedKey,
- iv: parsedData.iv
- })
- const decryptedData = JSON.parse(decryptedMessage)
- return decryptedData
- } catch (err) {
- logger.error(
- `[SOCKET] An error has occurred while decrypting an event (${eventName}):`,
- err
- )
-
- return socket.emit('encryption:error', err)
- }
- }
-
const onNewInvoice = (socket, subID) => {
const { lightning } = LightningServices.services
logger.warn('Subscribing to invoices socket...' + subID)
@@ -677,7 +617,7 @@ module.exports = (
}
/**
- * @param {Common.Schema.SimpleReceivedRequest[]} receivedReqs
+ * @param {ReadonlyArray} receivedReqs
*/
const onReceivedReqs = receivedReqs => {
const processed = receivedReqs.map(({ id, requestorPK, timestamp }) => {
diff --git a/utils/index.js b/utils/index.js
index 90e80eee..516d762a 100644
--- a/utils/index.js
+++ b/utils/index.js
@@ -1,9 +1,21 @@
/**
* @format
*/
+const Gun = require('gun')
const { asyncFilter } = require('./helpers')
-module.exports = {
- asyncFilter
+/**
+ * @returns {string}
+ */
+const gunUUID = () => {
+ // @ts-expect-error Not typed
+ const uuid = Gun.Text.random()
+
+ return uuid
+}
+
+module.exports = {
+ asyncFilter,
+ gunUUID
}
diff --git a/utils/lightningServices/lightning-services.js b/utils/lightningServices/lightning-services.js
index a0631f1b..71ef98d9 100644
--- a/utils/lightningServices/lightning-services.js
+++ b/utils/lightningServices/lightning-services.js
@@ -18,6 +18,7 @@ const lnrpc = require('../../services/lnd/lightning')
* @prop {string} macaroonPath
* @prop {string} lndProto
* @prop {string} routerProto
+ * @prop {string} invoicesProto
* @prop {string} walletUnlockerProto
*/
@@ -73,6 +74,13 @@ class LightningServices {
}
}
+ /**
+ * @returns {import('./types').Services}
+ */
+ getServices() {
+ return this.services
+ }
+
get servicesData() {
return this.lnServicesData
}
@@ -119,6 +127,7 @@ class LightningServices {
const lnServices = await lnrpc({
lnrpcProtoPath: this.defaults.lndProto,
routerProtoPath: this.defaults.routerProto,
+ invoicesProtoPath: this.defaults.invoicesProto,
walletUnlockerProtoPath: this.defaults.walletUnlockerProto,
lndHost,
lndCertPath,
@@ -127,10 +136,11 @@ class LightningServices {
if (!lnServices) {
throw new Error(`Could not init lnServices`)
}
- const { lightning, walletUnlocker, router } = lnServices
+ const { lightning, walletUnlocker, router, invoices } = lnServices
this.lightning = lightning
this.walletUnlocker = walletUnlocker
this.router = router
+ this.invoices = invoices
this.lnServicesData = {
lndProto: this.defaults.lndProto,
lndHost,
diff --git a/utils/lightningServices/types.ts b/utils/lightningServices/types.ts
index f8e77d81..ca0d034f 100644
--- a/utils/lightningServices/types.ts
+++ b/utils/lightningServices/types.ts
@@ -1,6 +1,7 @@
/**
* @format
*/
+import * as Common from 'shock-common'
export interface PaymentV2 {
payment_hash: string
@@ -106,3 +107,90 @@ export interface SendPaymentInvoiceParams {
payment_request: string
timeoutSeconds?: number
}
+
+type StreamListener = (data: any) => void
+
+/**
+ * Caution: Not all methods return an stream.
+ */
+interface LightningStream {
+ on(ev: 'data' | 'end' | 'error' | 'status', listener: StreamListener): void
+}
+
+type LightningCB = (err: Error, data: Record) => void
+
+type LightningMethod = (
+ args: Record,
+ cb?: LightningCB
+) => LightningStream
+
+/**
+ * Makes it easier for code calling services.
+ */
+export interface Services {
+ lightning: Record
+ walletUnlocker: Record
+ router: Record
+}
+
+export interface ListChannelsReq {
+ active_only: boolean
+ inactive_only: boolean
+ public_only: boolean
+ private_only: boolean
+ /**
+ * Filters the response for channels with a target peer's pubkey. If peer is
+ * empty, all channels will be returned.
+ */
+ peer: Common.Bytes
+}
+
+/**
+ * https://api.lightning.community/#pendingchannels
+ */
+export interface PendingChannelsRes {
+ /**
+ * The balance in satoshis encumbered in pending channels.
+ */
+ total_limbo_balance: string
+ /**
+ * Channels pending opening.
+ */
+ pending_open_channels: Common.PendingOpenChannel[]
+ /**
+ * Channels pending force closing.
+ */
+ pending_force_closing_channels: Common.ForceClosedChannel[]
+ /**
+ * Channels waiting for closing tx to confirm.
+ */
+ waiting_close_channels: Common.WaitingCloseChannel[]
+}
+
+/**
+ * https://github.com/lightningnetwork/lnd/blob/daf7c8a85420fc67fffa18fa5f7d08c2040946e4/lnrpc/rpc.proto#L2948
+ */
+export interface AddInvoiceRes {
+ /**
+ *
+ */
+ r_hash: Common.Bytes
+ /**
+ * A bare-bones invoice for a payment within the Lightning Network. With the
+ * details of the invoice, the sender has all the data necessary to send a
+ * payment to the recipient.
+ */
+ payment_request: string
+ /**
+ * The "add" index of this invoice. Each newly created invoice will increment
+ * this index making it monotonically increasing. Callers to the
+ * SubscribeInvoices call can use this to instantly get notified of all added
+ * invoices with an add_index greater than this one.
+ */
+ add_index: string
+ /**
+ * The payment address of the generated invoice. This value should be used in
+ * all payments for this invoice as we require it for end to end security.
+ */
+ payment_addr: Common.Bytes
+}
diff --git a/utils/lightningServices/v2.js b/utils/lightningServices/v2.js
index 34f42f44..45a03a52 100644
--- a/utils/lightningServices/v2.js
+++ b/utils/lightningServices/v2.js
@@ -6,6 +6,8 @@ const logger = require('winston')
const Common = require('shock-common')
const Ramda = require('ramda')
+const { writeCoordinate } = require('../../services/coordinates')
+
const lightningServices = require('./lightning-services')
/**
* @typedef {import('./types').PaymentV2} PaymentV2
@@ -213,12 +215,50 @@ const isValidSendPaymentInvoiceParams = sendPaymentInvoiceParams => {
return true
}
+/**
+ * @param {string} payReq
+ * @returns {Promise}
+ */
+const decodePayReq = payReq =>
+ Common.Utils.makePromise((res, rej) => {
+ lightningServices.lightning.decodePayReq(
+ { pay_req: payReq },
+ /**
+ * @param {{ message: any; }} err
+ * @param {any} paymentRequest
+ */
+ (err, paymentRequest) => {
+ if (err) {
+ rej(new Error(err.message))
+ } else {
+ res(paymentRequest)
+ }
+ }
+ )
+ })
+
+/**
+ * @returns {Promise}
+ */
+const myLNDPub = () =>
+ Common.makePromise((res, rej) => {
+ const { lightning } = lightningServices.getServices()
+
+ lightning.getInfo({}, (err, data) => {
+ if (err) {
+ rej(new Error(err.message))
+ } else {
+ res(data.identity_pubkey)
+ }
+ })
+ })
+
/**
* aklssjdklasd
* @param {SendPaymentV2Request} sendPaymentRequest
* @returns {Promise}
*/
-const sendPaymentV2 = sendPaymentRequest => {
+const sendPaymentV2 = async sendPaymentRequest => {
const {
services: { router }
} = lightningServices
@@ -229,7 +269,10 @@ const sendPaymentV2 = sendPaymentRequest => {
)
}
- return new Promise((res, rej) => {
+ /**
+ * @type {import("./types").PaymentV2}
+ */
+ const paymentV2 = await Common.makePromise((res, rej) => {
const stream = router.sendPaymentV2(sendPaymentRequest)
stream.on(
@@ -268,6 +311,33 @@ const sendPaymentV2 = sendPaymentRequest => {
}
)
})
+
+ /** @type {Common.Coordinate} */
+ const coord = {
+ amount: Number(paymentV2.value_sat),
+ id: paymentV2.payment_hash,
+ inbound: false,
+ timestamp: Date.now(),
+ toLndPub: await myLNDPub(),
+ fromLndPub: undefined,
+ invoiceMemo: undefined,
+ type: 'payment'
+ }
+
+ if (sendPaymentRequest.payment_request) {
+ const invoice = await decodePayReq(sendPaymentRequest.payment_request)
+
+ coord.invoiceMemo = invoice.description
+ coord.toLndPub = invoice.destination
+ }
+
+ if (sendPaymentRequest.dest) {
+ coord.toLndPub = sendPaymentRequest.dest.toString('base64')
+ }
+
+ await writeCoordinate(paymentV2.payment_hash, coord)
+
+ return paymentV2
}
/**
@@ -381,22 +451,169 @@ const listPayments = req => {
}
/**
- * @param {string} payReq
- * @returns {Promise}
+ * @param {0|1} type
+ * @returns {Promise}
*/
-const decodePayReq = payReq =>
- Common.Utils.makePromise((res, rej) => {
- lightningServices.lightning.decodePayReq(
- { pay_req: payReq },
- /**
- * @param {{ message: any; }} err
- * @param {any} paymentRequest
- */
- (err, paymentRequest) => {
+const newAddress = (type = 0) => {
+ const { lightning } = lightningServices.getServices()
+
+ return Common.Utils.makePromise((res, rej) => {
+ lightning.newAddress({ type }, (err, response) => {
+ if (err) {
+ rej(new Error(err.message))
+ } else {
+ res(response.address)
+ }
+ })
+ })
+}
+
+/**
+ * @param {number} minConfs
+ * @param {number} maxConfs
+ * @returns {Promise}
+ */
+const listUnspent = (minConfs = 3, maxConfs = 6) =>
+ Common.makePromise((res, rej) => {
+ const { lightning } = lightningServices.getServices()
+
+ lightning.listUnspent(
+ {
+ min_confs: minConfs,
+ max_confs: maxConfs
+ },
+ (err, unspent) => {
if (err) {
rej(new Error(err.message))
} else {
- res(paymentRequest)
+ res(unspent.utxos)
+ }
+ }
+ )
+ })
+
+/**
+ * @typedef {import('./types').ListChannelsReq} ListChannelsReq
+ */
+
+/**
+ * @param {ListChannelsReq} req
+ * @returns {Promise}
+ */
+const listChannels = req =>
+ Common.makePromise((res, rej) => {
+ const { lightning } = lightningServices.getServices()
+
+ lightning.listChannels(req, (err, resp) => {
+ if (err) {
+ rej(new Error(err.message))
+ } else {
+ res(resp.channels)
+ }
+ })
+ })
+
+/**
+ * https://api.lightning.community/#getchaninfo
+ * @param {string} chanID
+ * @returns {Promise}
+ */
+const getChanInfo = chanID =>
+ Common.makePromise((res, rej) => {
+ const { lightning } = lightningServices.getServices()
+
+ lightning.getChanInfo(
+ {
+ chan_id: chanID
+ },
+ (err, resp) => {
+ if (err) {
+ rej(new Error(err.message))
+ } else {
+ // Needs cast because typescript refuses to assign Record
+ // to an actual object :shrugs
+ res(/** @type {Common.ChannelEdge} */ (resp))
+ }
+ }
+ )
+ })
+
+/**
+ * https://api.lightning.community/#listpeers
+ * @param {boolean=} latestError If true, only the last error that our peer sent
+ * us will be returned with the peer's information, rather than the full set of
+ * historic errors we have stored.
+ * @returns {Promise}
+ */
+const listPeers = latestError =>
+ Common.makePromise((res, rej) => {
+ const { lightning } = lightningServices.getServices()
+
+ lightning.listPeers(
+ {
+ latest_error: latestError
+ },
+ (err, resp) => {
+ if (err) {
+ rej(new Error(err.message))
+ } else {
+ res(resp.peers)
+ }
+ }
+ )
+ })
+
+/**
+ * @typedef {import('./types').PendingChannelsRes} PendingChannelsRes
+ */
+
+/**
+ * @returns {Promise}
+ */
+const pendingChannels = () =>
+ Common.makePromise((res, rej) => {
+ const { lightning } = lightningServices.getServices()
+
+ lightning.pendingChannels({}, (err, resp) => {
+ if (err) {
+ rej(new Error(err.message))
+ } else {
+ // Needs cast because typescript refuses to assign Record
+ // to an actual object :shrugs
+ res(/** @type {PendingChannelsRes} */ (resp))
+ }
+ })
+ })
+
+/**
+ * @typedef {import('./types').AddInvoiceRes} AddInvoiceRes
+ */
+/**
+ * https://api.lightning.community/#addinvoice
+ * @param {number} value
+ * @param {string=} memo
+ * @param {boolean=} confidential Alias for `private`.
+ * @param {number=} expiry
+ * @returns {Promise}
+ */
+const addInvoice = (value, memo = '', confidential = true, expiry = 180) =>
+ Common.makePromise((res, rej) => {
+ const { lightning } = lightningServices.getServices()
+
+ lightning.addInvoice(
+ {
+ value,
+ memo,
+ private: confidential,
+ expiry
+ },
+ (err, resp) => {
+ if (err) {
+ rej(new Error(err.message))
+ } else {
+ // Needs cast because typescript refuses to assign Record
+ // to an actual object :shrugs
+ res(/** @type {AddInvoiceRes} */ (resp))
}
}
)
@@ -406,5 +623,13 @@ module.exports = {
sendPaymentV2Keysend,
sendPaymentV2Invoice,
listPayments,
- decodePayReq
+ decodePayReq,
+ newAddress,
+ listUnspent,
+ listChannels,
+ getChanInfo,
+ listPeers,
+ pendingChannels,
+ addInvoice,
+ myLNDPub
}
diff --git a/utils/lndJobs.js b/utils/lndJobs.js
deleted file mode 100644
index 0c5791f2..00000000
--- a/utils/lndJobs.js
+++ /dev/null
@@ -1,211 +0,0 @@
-/**
- * @prettier
- */
-const Logger = require('winston')
-const { wait } = require('./helpers')
-const Key = require('../services/gunDB/contact-api/key')
-const { getUser } = require('../services/gunDB/Mediator')
-const LightningServices = require('./lightningServices')
-
-const ERROR_TRIES_THRESHOLD = 3
-const ERROR_TRIES_DELAY = 500
-const INVOICE_STATE = {
- OPEN: 'OPEN',
- SETTLED: 'SETTLED',
- CANCELLED: 'CANCELLED',
- ACCEPTED: 'ACCEPTED'
-}
-
-const _lookupInvoice = hash =>
- new Promise((resolve, reject) => {
- const { lightning } = LightningServices.services
- lightning.lookupInvoice({ r_hash: hash }, (err, response) => {
- if (err) {
- Logger.error(
- '[TIP] An error has occurred while trying to lookup invoice:',
- err,
- '\nInvoice Hash:',
- hash
- )
- reject(err)
- return
- }
-
- Logger.info('[TIP] Invoice lookup result:', response)
- resolve(response)
- })
- })
-
-const _getPostTipInfo = ({ postID }) =>
- new Promise((resolve, reject) => {
- getUser()
- .get(Key.POSTS_NEW)
- .get(postID)
- .once(post => {
- if (post && post.date) {
- const { tipCounter, tipValue } = post
- resolve({
- tipCounter: typeof tipCounter === 'number' ? tipCounter : 0,
- tipValue: typeof tipValue === 'number' ? tipValue : 0
- })
- return
- }
-
- resolve(post)
- })
- })
-
-const _incrementPost = ({ postID, orderAmount }) =>
- new Promise((resolve, reject) => {
- const parsedAmount = parseFloat(orderAmount)
-
- if (typeof parsedAmount !== 'number') {
- reject(new Error('Invalid order amount specified'))
- return
- }
-
- Logger.info('[POST TIP] Getting Post Tip Values...')
-
- return _getPostTipInfo({ postID })
- .then(({ tipValue, tipCounter }) => {
- const updatedTip = {
- tipCounter: tipCounter + 1,
- tipValue: tipValue + parsedAmount
- }
-
- getUser()
- .get(Key.POSTS_NEW)
- .get(postID)
- .put(updatedTip, () => {
- Logger.info('[POST TIP] Successfully updated Post tip info')
- resolve(updatedTip)
- })
- })
- .catch(err => {
- Logger.error(err)
- reject(err)
- })
- })
-
-const _updateTipData = (invoiceHash, data) =>
- new Promise((resolve, reject) => {
- try {
- getUser()
- .get(Key.TIPS_PAYMENT_STATUS)
- .get(invoiceHash)
- .put(data, tip => {
- if (tip === undefined) {
- reject(new Error('Tip update failed'))
- return
- }
-
- console.log(tip)
-
- resolve(tip)
- })
- } catch (err) {
- Logger.error('An error has occurred while updating tip^data')
- throw err
- }
- })
-
-const _getTipData = (invoiceHash, tries = 0) =>
- new Promise((resolve, reject) => {
- if (tries >= ERROR_TRIES_THRESHOLD) {
- reject(new Error('Malformed data'))
- return
- }
-
- getUser()
- .get(Key.TIPS_PAYMENT_STATUS)
- .get(invoiceHash)
- .once(async tip => {
- try {
- if (tip === undefined) {
- await wait(ERROR_TRIES_DELAY)
- const tip = await _getTipData(invoiceHash, tries + 1)
-
- if (tip) {
- resolve(tip)
- return
- }
-
- reject(new Error('Malformed data'))
- return
- }
-
- resolve(tip)
- } catch (err) {
- reject(err)
- }
- })
- })
-
-const executeTipAction = (tip, invoice) => {
- if (invoice.state !== INVOICE_STATE.SETTLED) {
- return
- }
-
- // Execute actions once invoice is settled
- Logger.info('Invoice settled!', invoice)
-
- if (tip.targetType === 'post') {
- _incrementPost({
- postID: tip.postID,
- orderAmount: invoice.amt_paid_sat
- })
- }
-}
-
-const updateUnverifiedTips = () => {
- getUser()
- .get(Key.TIPS_PAYMENT_STATUS)
- .map()
- .once(async (tip, id) => {
- try {
- if (
- !tip ||
- tip.state !== INVOICE_STATE.OPEN ||
- (tip._errorCount && tip._errorCount >= ERROR_TRIES_THRESHOLD)
- ) {
- return
- }
- Logger.info('Unverified invoice found!', tip)
- const invoice = await _lookupInvoice(tip.hash)
- Logger.info('Invoice located:', invoice)
- if (invoice.state !== tip.state) {
- await _updateTipData(id, { state: invoice.state })
-
- // Actions to be executed when the tip's state is updated
- executeTipAction(tip, invoice)
- }
- } catch (err) {
- Logger.error('[TIP] An error has occurred while updating invoice', err)
- const errorCount = tip._errorCount ? tip._errorCount : 0
- _updateTipData(id, {
- _errorCount: errorCount + 1
- })
- }
- })
-}
-
-const startTipStatusJob = () => {
- const { lightning } = LightningServices.services
- const stream = lightning.subscribeInvoices({})
- updateUnverifiedTips()
- stream.on('data', async invoice => {
- const hash = invoice.r_hash.toString('base64')
- const tip = await _getTipData(hash)
- if (tip.state !== invoice.state) {
- await _updateTipData(hash, { state: invoice.state })
- executeTipAction(tip, invoice)
- }
- })
- stream.on('error', err => {
- Logger.error('Tip Job error' + err.details)
- })
-}
-
-module.exports = {
- startTipStatusJob
-}
diff --git a/yarn.lock b/yarn.lock
index 5e7e8649..a66b0444 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,12 +2,12 @@
# yarn lockfile v1
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5":
- version "7.5.5"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
- integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11", "@babel/code-frame@^7.5.5":
+ version "7.12.11"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
+ integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
dependencies:
- "@babel/highlight" "^7.0.0"
+ "@babel/highlight" "^7.10.4"
"@babel/core@^7.1.0":
version "7.6.2"
@@ -29,6 +29,15 @@
semver "^5.4.1"
source-map "^0.5.0"
+"@babel/generator@^7.12.11":
+ version "7.12.11"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af"
+ integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==
+ dependencies:
+ "@babel/types" "^7.12.11"
+ jsesc "^2.5.1"
+ source-map "^0.5.0"
+
"@babel/generator@^7.4.0", "@babel/generator@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03"
@@ -39,79 +48,101 @@
lodash "^4.17.13"
source-map "^0.5.0"
-"@babel/generator@^7.6.3":
- version "7.6.4"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.4.tgz#a4f8437287bf9671b07f483b76e3bb731bc97671"
- integrity sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w==
+"@babel/helper-create-class-features-plugin@^7.12.1":
+ version "7.12.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e"
+ integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==
dependencies:
- "@babel/types" "^7.6.3"
- jsesc "^2.5.1"
- lodash "^4.17.13"
- source-map "^0.5.0"
+ "@babel/helper-function-name" "^7.10.4"
+ "@babel/helper-member-expression-to-functions" "^7.12.1"
+ "@babel/helper-optimise-call-expression" "^7.10.4"
+ "@babel/helper-replace-supers" "^7.12.1"
+ "@babel/helper-split-export-declaration" "^7.10.4"
-"@babel/helper-create-class-features-plugin@^7.5.5":
- version "7.6.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.6.0.tgz#769711acca889be371e9bc2eb68641d55218021f"
- integrity sha512-O1QWBko4fzGju6VoVvrZg0RROCVifcLxiApnGP3OWfWzvxRZFCoBD81K5ur5e3bVY2Vf/5rIJm8cqPKn8HUJng==
+"@babel/helper-function-name@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a"
+ integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==
dependencies:
- "@babel/helper-function-name" "^7.1.0"
- "@babel/helper-member-expression-to-functions" "^7.5.5"
- "@babel/helper-optimise-call-expression" "^7.0.0"
- "@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-replace-supers" "^7.5.5"
- "@babel/helper-split-export-declaration" "^7.4.4"
+ "@babel/helper-get-function-arity" "^7.10.4"
+ "@babel/template" "^7.10.4"
+ "@babel/types" "^7.10.4"
-"@babel/helper-function-name@^7.1.0":
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53"
- integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==
+"@babel/helper-function-name@^7.12.11":
+ version "7.12.11"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42"
+ integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==
dependencies:
- "@babel/helper-get-function-arity" "^7.0.0"
- "@babel/template" "^7.1.0"
- "@babel/types" "^7.0.0"
+ "@babel/helper-get-function-arity" "^7.12.10"
+ "@babel/template" "^7.12.7"
+ "@babel/types" "^7.12.11"
-"@babel/helper-get-function-arity@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3"
- integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==
+"@babel/helper-get-function-arity@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2"
+ integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==
dependencies:
- "@babel/types" "^7.0.0"
+ "@babel/types" "^7.10.4"
-"@babel/helper-member-expression-to-functions@^7.5.5":
- version "7.5.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590"
- integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==
+"@babel/helper-get-function-arity@^7.12.10":
+ version "7.12.10"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf"
+ integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==
dependencies:
- "@babel/types" "^7.5.5"
+ "@babel/types" "^7.12.10"
-"@babel/helper-optimise-call-expression@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5"
- integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==
+"@babel/helper-member-expression-to-functions@^7.12.1":
+ version "7.12.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c"
+ integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ==
dependencies:
- "@babel/types" "^7.0.0"
+ "@babel/types" "^7.12.1"
-"@babel/helper-plugin-utils@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
- integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==
-
-"@babel/helper-replace-supers@^7.5.5":
- version "7.5.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2"
- integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==
+"@babel/helper-optimise-call-expression@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673"
+ integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==
dependencies:
- "@babel/helper-member-expression-to-functions" "^7.5.5"
- "@babel/helper-optimise-call-expression" "^7.0.0"
- "@babel/traverse" "^7.5.5"
- "@babel/types" "^7.5.5"
+ "@babel/types" "^7.10.4"
-"@babel/helper-split-export-declaration@^7.4.4":
- version "7.4.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677"
- integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375"
+ integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==
+
+"@babel/helper-replace-supers@^7.12.1":
+ version "7.12.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9"
+ integrity sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==
dependencies:
- "@babel/types" "^7.4.4"
+ "@babel/helper-member-expression-to-functions" "^7.12.1"
+ "@babel/helper-optimise-call-expression" "^7.10.4"
+ "@babel/traverse" "^7.12.5"
+ "@babel/types" "^7.12.5"
+
+"@babel/helper-split-export-declaration@^7.10.4":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f"
+ integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==
+ dependencies:
+ "@babel/types" "^7.11.0"
+
+"@babel/helper-split-export-declaration@^7.12.11":
+ version "7.12.11"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a"
+ integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==
+ dependencies:
+ "@babel/types" "^7.12.11"
+
+"@babel/helper-validator-identifier@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
+ integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
+
+"@babel/helper-validator-identifier@^7.12.11":
+ version "7.12.11"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
+ integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
"@babel/helpers@^7.6.2":
version "7.6.2"
@@ -122,32 +153,27 @@
"@babel/traverse" "^7.6.2"
"@babel/types" "^7.6.0"
-"@babel/highlight@^7.0.0":
- version "7.5.0"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540"
- integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==
+"@babel/highlight@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
+ integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
dependencies:
+ "@babel/helper-validator-identifier" "^7.10.4"
chalk "^2.0.0"
- esutils "^2.0.2"
js-tokens "^4.0.0"
-"@babel/parser@^7.0.0", "@babel/parser@^7.6.3":
- version "7.6.4"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81"
- integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==
+"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2", "@babel/parser@^7.7.0":
+ version "7.12.11"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79"
+ integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==
-"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2":
- version "7.6.2"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1"
- integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==
-
-"@babel/plugin-proposal-class-properties@^7.5.5":
- version "7.5.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4"
- integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A==
+"@babel/plugin-proposal-class-properties@^7.12.1":
+ version "7.12.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de"
+ integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==
dependencies:
- "@babel/helper-create-class-features-plugin" "^7.5.5"
- "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-create-class-features-plugin" "^7.12.1"
+ "@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-object-rest-spread@^7.0.0":
version "7.2.0"
@@ -157,13 +183,31 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/runtime@^7.6.3":
- version "7.11.2"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
- integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
+ version "7.12.18"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.18.tgz#af137bd7e7d9705a412b3caaf991fe6aaa97831b"
+ integrity sha512-BogPQ7ciE6SYAUPtlm9tWbgI9+2AgqSam6QivMgXgAT+fKbgppaj4ZX15MHeLC1PVF5sNk70huBu20XxWOs8Cg==
dependencies:
regenerator-runtime "^0.13.4"
-"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.6.0":
+"@babel/template@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
+ integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/parser" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+"@babel/template@^7.12.7":
+ version "7.12.7"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc"
+ integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/parser" "^7.12.7"
+ "@babel/types" "^7.12.7"
+
+"@babel/template@^7.4.0", "@babel/template@^7.6.0":
version "7.6.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6"
integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==
@@ -172,52 +216,28 @@
"@babel/parser" "^7.6.0"
"@babel/types" "^7.6.0"
-"@babel/traverse@^7.0.0":
- version "7.6.3"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9"
- integrity sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw==
+"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.5", "@babel/traverse@^7.4.3", "@babel/traverse@^7.6.2", "@babel/traverse@^7.7.0":
+ version "7.12.12"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376"
+ integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==
dependencies:
- "@babel/code-frame" "^7.5.5"
- "@babel/generator" "^7.6.3"
- "@babel/helper-function-name" "^7.1.0"
- "@babel/helper-split-export-declaration" "^7.4.4"
- "@babel/parser" "^7.6.3"
- "@babel/types" "^7.6.3"
+ "@babel/code-frame" "^7.12.11"
+ "@babel/generator" "^7.12.11"
+ "@babel/helper-function-name" "^7.12.11"
+ "@babel/helper-split-export-declaration" "^7.12.11"
+ "@babel/parser" "^7.12.11"
+ "@babel/types" "^7.12.12"
debug "^4.1.0"
globals "^11.1.0"
- lodash "^4.17.13"
+ lodash "^4.17.19"
-"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2":
- version "7.6.2"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c"
- integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==
+"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.6.0", "@babel/types@^7.7.0":
+ version "7.12.12"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299"
+ integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==
dependencies:
- "@babel/code-frame" "^7.5.5"
- "@babel/generator" "^7.6.2"
- "@babel/helper-function-name" "^7.1.0"
- "@babel/helper-split-export-declaration" "^7.4.4"
- "@babel/parser" "^7.6.2"
- "@babel/types" "^7.6.0"
- debug "^4.1.0"
- globals "^11.1.0"
- lodash "^4.17.13"
-
-"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0":
- version "7.6.1"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648"
- integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==
- dependencies:
- esutils "^2.0.2"
- lodash "^4.17.13"
- to-fast-properties "^2.0.0"
-
-"@babel/types@^7.6.3":
- version "7.6.3"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09"
- integrity sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==
- dependencies:
- esutils "^2.0.2"
- lodash "^4.17.13"
+ "@babel/helper-validator-identifier" "^7.12.11"
+ lodash "^4.17.19"
to-fast-properties "^2.0.0"
"@cnakazawa/watch@^1.0.3":
@@ -237,10 +257,19 @@
enabled "2.0.x"
kuler "^2.0.0"
-"@grpc/proto-loader@^0.5.1":
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.2.tgz#c84f83be962f518bc303ca2d5e6ef2239439786c"
- integrity sha512-eBKD/FPxQoY1x6QONW2nBd54QUEyzcFP9FenujmoeDPy1rutVSHki1s/wR68F6O1QfCNDx+ayBH1O2CVNMzyyw==
+"@grpc/grpc-js@^1.2.2":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.2.2.tgz#ee4a7417fe15a686a8e369c36ec4c80678445c67"
+ integrity sha512-iK/T984Ni6VnmlQK/LJdUk+VsXSaYIWkgzJ0LyOcxN2SowAmoRjG28kS7B1ui/q/MAv42iM3051WBt5QorFxmg==
+ dependencies:
+ "@types/node" "^12.12.47"
+ google-auth-library "^6.1.1"
+ semver "^6.2.0"
+
+"@grpc/proto-loader@^0.5.5":
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.5.tgz#6725e7a1827bdf8e92e29fbf4e9ef0203c0906a9"
+ integrity sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==
dependencies:
lodash.camelcase "^4.3.0"
protobufjs "^6.8.6"
@@ -693,6 +722,14 @@
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==
+"@types/node-fetch@^2.5.8":
+ version "2.5.8"
+ resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb"
+ integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==
+ dependencies:
+ "@types/node" "*"
+ form-data "^3.0.0"
+
"@types/node@*":
version "12.7.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.4.tgz#64db61e0359eb5a8d99b55e05c729f130a678b04"
@@ -703,11 +740,21 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.17.tgz#b96d4dd3e427382482848948041d3754d40fd5ce"
integrity sha512-p/sGgiPaathCfOtqu2fx5Mu1bcjuP8ALFg4xpGgNkcin7LwRyzUKniEHBKdcE1RPsenq5JVPIpMTJSygLboygQ==
+"@types/node@^12.12.47":
+ version "12.19.8"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.8.tgz#efd6d1a90525519fc608c9db16c8a78f7693a978"
+ integrity sha512-D4k2kNi0URNBxIRCb1khTnkWNHv8KSL1owPmS/K5e5t8B2GzMReY7AsJIY1BnP5KdlgC4rj9jk2IkDMasIE7xg==
+
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
+"@types/prop-types@*":
+ version "15.7.3"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
+ integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
+
"@types/pvutils@*":
version "0.0.2"
resolved "https://registry.npmjs.org/@types/pvutils/-/pvutils-0.0.2.tgz#e21684962cfa58ac920fd576d90556032dc86009"
@@ -722,6 +769,14 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
+"@types/react@16.x.x":
+ version "16.14.2"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.2.tgz#85dcc0947d0645349923c04ccef6018a1ab7538c"
+ integrity sha512-BzzcAlyDxXl2nANlabtT4thtvbbnhee8hMmH/CcJrISDBVcJS1iOsP1f0OAgSdGE0MsY9tqcrb9YoZcOFv9dbQ==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^3.0.2"
+
"@types/serve-static@*":
version "1.13.3"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1"
@@ -789,6 +844,13 @@ abbrev@1:
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+abort-controller@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
+ integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
+ dependencies:
+ event-target-shim "^5.0.0"
+
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
@@ -840,6 +902,13 @@ after@0.8.2:
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
+agent-base@6:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+ integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
+ dependencies:
+ debug "4"
+
aggregate-error@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0"
@@ -965,6 +1034,11 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.6"
+arg@^4.1.0:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
+ integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
+
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -1007,6 +1081,11 @@ arraybuffer.slice@~0.0.7:
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
+arrify@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
+ integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
+
asap@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
@@ -1034,6 +1113,11 @@ asn1js@^2.0.26:
dependencies:
pvutils latest
+assert-never@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe"
+ integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==
+
assert-plus@1.0.0, assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
@@ -1097,10 +1181,10 @@ axios@0.19.0:
follow-redirects "1.5.10"
is-buffer "^2.0.2"
-axios@^0.20.0:
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd"
- integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==
+axios@^0.21.1:
+ version "0.21.1"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
+ integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
dependencies:
follow-redirects "^1.10.0"
@@ -1113,15 +1197,15 @@ babel-code-frame@^6.26.0:
esutils "^2.0.2"
js-tokens "^3.0.2"
-babel-eslint@^10.0.3:
- version "10.0.3"
- resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a"
- integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==
+babel-eslint@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
+ integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==
dependencies:
"@babel/code-frame" "^7.0.0"
- "@babel/parser" "^7.0.0"
- "@babel/traverse" "^7.0.0"
- "@babel/types" "^7.0.0"
+ "@babel/parser" "^7.7.0"
+ "@babel/traverse" "^7.7.0"
+ "@babel/types" "^7.7.0"
eslint-visitor-keys "^1.0.0"
resolve "^1.12.0"
@@ -1264,6 +1348,11 @@ base64-js@^1.0.2:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
+base64-js@^1.3.0:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+ integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
base64id@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
@@ -1308,6 +1397,11 @@ big.js@^5.2.2:
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+bignumber.js@^9.0.0:
+ version "9.0.1"
+ resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5"
+ integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==
+
binary-extensions@^1.0.0:
version "1.13.1"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
@@ -1330,12 +1424,7 @@ blob@0.0.5:
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==
-bluebird@^3.5.0:
- version "3.5.5"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
- integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
-
-bluebird@^3.7.2:
+bluebird@^3.5.0, bluebird@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
@@ -1752,7 +1841,7 @@ colour@~0.7.1:
resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778"
integrity sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=
-combined-stream@^1.0.6, combined-stream@~1.0.6:
+combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@@ -1916,6 +2005,11 @@ create-error-class@^3.0.0:
dependencies:
capture-stack-trace "^1.0.0"
+create-require@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
+ integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
+
cross-spawn@^5.0.1:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
@@ -1962,6 +2056,11 @@ cssstyle@^1.0.0:
dependencies:
cssom "0.3.x"
+csstype@^3.0.2:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.6.tgz#865d0b5833d7d8d40f4e5b8a6d76aea3de4725ef"
+ integrity sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==
+
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -1985,7 +2084,14 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8:
dependencies:
ms "2.0.0"
-debug@4.1.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
+ integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
+ dependencies:
+ ms "2.1.2"
+
+debug@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
@@ -2107,6 +2213,11 @@ diff-sequences@^24.9.0:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
+diff@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
+ integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
+
doctrine@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
@@ -2146,7 +2257,7 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
-ecdsa-sig-formatter@1.0.11:
+ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
@@ -2478,6 +2589,11 @@ etag@~1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
+event-target-shim@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
+ integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
+
exec-sh@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b"
@@ -2554,18 +2670,18 @@ expect@^24.9.0:
jest-message-util "^24.9.0"
jest-regex-util "^24.9.0"
-express-session@^1.15.1:
- version "1.16.2"
- resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.16.2.tgz#59f36d7770e94872d19b163b6708a2d16aa6848c"
- integrity sha512-oy0sRsdw6n93E9wpCNWKRnSsxYnSDX9Dnr9mhZgqUEEorzcq5nshGYSZ4ZReHFhKQ80WI5iVUUSPW7u3GaKauw==
+express-session@^1.17.1:
+ version "1.17.1"
+ resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.1.tgz#36ecbc7034566d38c8509885c044d461c11bf357"
+ integrity sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==
dependencies:
- cookie "0.3.1"
+ cookie "0.4.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "~2.0.0"
on-headers "~1.0.2"
parseurl "~1.3.3"
- safe-buffer "5.1.2"
+ safe-buffer "5.2.0"
uid-safe "~2.1.5"
express@^4.14.1:
@@ -2619,7 +2735,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
-extend@~3.0.2:
+extend@^3.0.2, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
@@ -2687,6 +2803,11 @@ fast-safe-stringify@^2.0.4:
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
+fast-text-encoding@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53"
+ integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==
+
fb-watchman@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
@@ -2820,6 +2941,15 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+form-data@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
+ integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@@ -2909,6 +3039,11 @@ gcp-metadata@^4.2.0:
gaxios "^4.0.0"
json-bigint "^1.0.0"
+get-caller-file@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
+ integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
+
get-caller-file@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
@@ -2999,6 +3134,28 @@ globals@^9.18.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
+google-auth-library@^6.1.1:
+ version "6.1.3"
+ resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.1.3.tgz#39d868140b70d0c4b32c6f6d8f4ccc1400d84dca"
+ integrity sha512-m9mwvY3GWbr7ZYEbl61isWmk+fvTmOt0YNUfPOUY2VH8K5pZlAIWJjxEi0PqR3OjMretyiQLI6GURMrPSwHQ2g==
+ dependencies:
+ arrify "^2.0.0"
+ base64-js "^1.3.0"
+ ecdsa-sig-formatter "^1.0.11"
+ fast-text-encoding "^1.0.0"
+ gaxios "^4.0.0"
+ gcp-metadata "^4.2.0"
+ gtoken "^5.0.4"
+ jws "^4.0.0"
+ lru-cache "^6.0.0"
+
+google-p12-pem@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.0.3.tgz#673ac3a75d3903a87f05878f3c75e06fc151669e"
+ integrity sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==
+ dependencies:
+ node-forge "^0.10.0"
+
google-proto-files@^1.0.3:
version "1.1.0"
resolved "https://registry.yarnpkg.com/google-proto-files/-/google-proto-files-1.1.0.tgz#3d96148ddd07dd3facd016e5191966776c3f5897"
@@ -3053,6 +3210,16 @@ grpc@1.24.4:
node-pre-gyp "^0.16.0"
protobufjs "^5.0.3"
+gtoken@^5.0.4:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.1.0.tgz#4ba8d2fc9a8459098f76e7e8fd7beaa39fda9fe4"
+ integrity sha512-4d8N6Lk8TEAHl9vVoRVMh9BNOKWVgl2DdNtr3428O75r3QFrF/a5MMu851VmK0AA8+iSvbwRv69k5XnMLURGhg==
+ dependencies:
+ gaxios "^4.0.0"
+ google-p12-pem "^3.0.3"
+ jws "^4.0.0"
+ mime "^2.2.0"
+
"gun@git://github.com/amark/gun#97aa976c97e6219a9f93095d32c220dcd371ca62":
version "0.2020.520"
resolved "git://github.com/amark/gun#97aa976c97e6219a9f93095d32c220dcd371ca62"
@@ -3226,6 +3393,14 @@ http-signature@~1.2.0:
jsprim "^1.2.2"
sshpk "^1.7.0"
+https-proxy-agent@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
+ integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
+ dependencies:
+ agent-base "6"
+ debug "4"
+
human-signals@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
@@ -3349,9 +3524,9 @@ inherits@=2.0.1:
integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
ini@^1.3.4, ini@~1.3.0:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
- integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+ integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
inquirer@^7.0.0:
version "7.0.0"
@@ -4138,6 +4313,13 @@ jsesc@^2.5.1:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+json-bigint@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1"
+ integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==
+ dependencies:
+ bignumber.js "^9.0.0"
+
json-parse-better-errors@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@@ -4212,6 +4394,15 @@ jwa@^1.4.1:
ecdsa-sig-formatter "1.0.11"
safe-buffer "^5.0.1"
+jwa@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc"
+ integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==
+ dependencies:
+ buffer-equal-constant-time "1.0.1"
+ ecdsa-sig-formatter "1.0.11"
+ safe-buffer "^5.0.1"
+
jws@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
@@ -4220,6 +4411,14 @@ jws@^3.2.2:
jwa "^1.4.1"
safe-buffer "^5.0.1"
+jws@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4"
+ integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==
+ dependencies:
+ jwa "^2.0.0"
+ safe-buffer "^5.0.1"
+
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -4487,6 +4686,13 @@ lru-cache@^4.0.1:
pseudomap "^1.0.2"
yallist "^2.1.2"
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
make-dir@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
@@ -4502,6 +4708,11 @@ make-dir@^2.1.0:
pify "^4.0.1"
semver "^5.6.0"
+make-error@^1.1.1:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
+ integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
+
makeerror@1.0.x:
version "1.0.11"
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
@@ -4600,6 +4811,11 @@ mime@1.6.0:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+mime@^2.2.0:
+ version "2.4.6"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"
+ integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
+
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
@@ -4692,7 +4908,7 @@ ms@2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
-ms@^2.1.1:
+ms@2.1.2, ms@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
@@ -4762,6 +4978,16 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+node-fetch@^2.3.0, node-fetch@^2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
+ integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
+
+node-forge@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
+ integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
+
node-int64@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
@@ -4874,9 +5100,9 @@ normalize-path@^3.0.0:
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
normalizr@^3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/normalizr/-/normalizr-3.6.0.tgz#b8bbc4546ffe43c1c2200503041642915fcd3e1c"
- integrity sha512-25cd8DiDu+pL46KIaxtVVvvEPjGacJgv0yUg950evr62dQ/ks2JO1kf7+Vi5/rMFjaSTSTls7aCnmRlUSljtiA==
+ version "3.6.1"
+ resolved "https://registry.yarnpkg.com/normalizr/-/normalizr-3.6.1.tgz#d367ab840e031ff382141b8d81ce279292ff69fe"
+ integrity sha512-8iEmqXmPtll8PwbEFrbPoDxVw7MKnNvt3PZzR2Xvq9nggEEOgBlNICPXYzyZ4w4AkHUzCU998mdatER3n2VaMA==
npm-bundled@^1.0.1:
version "1.0.6"
@@ -5349,10 +5575,10 @@ progress@^2.0.0:
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
-promise@^8.0.1:
- version "8.0.3"
- resolved "https://registry.yarnpkg.com/promise/-/promise-8.0.3.tgz#f592e099c6cddc000d538ee7283bb190452b0bf6"
- integrity sha512-HeRDUL1RJiLhyA0/grn+PTShlBAcLuh/1BJGtrvjwbvRDCTLLMEz9rOGCV+R3vHY4MixIuoMEd9Yq/XvsTPcjw==
+promise@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e"
+ integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==
dependencies:
asap "~2.0.6"
@@ -5656,6 +5882,13 @@ request-promise-core@1.1.2:
dependencies:
lodash "^4.17.11"
+request-promise-core@1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
+ integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==
+ dependencies:
+ lodash "^4.17.19"
+
request-promise-native@^1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59"
@@ -5665,13 +5898,13 @@ request-promise-native@^1.0.5:
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
-request-promise@^4.2.2:
- version "4.2.4"
- resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.4.tgz#1c5ed0d71441e38ad58c7ce4ea4ea5b06d54b310"
- integrity sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==
+request-promise@^4.2.6:
+ version "4.2.6"
+ resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.6.tgz#7e7e5b9578630e6f598e3813c0f8eb342a27f0a2"
+ integrity sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==
dependencies:
bluebird "^3.5.0"
- request-promise-core "1.1.2"
+ request-promise-core "1.1.4"
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
@@ -5780,6 +6013,13 @@ rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
dependencies:
glob "^7.1.3"
+rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
rsvp@^4.8.4:
version "4.8.5"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
@@ -5811,6 +6051,11 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+safe-buffer@5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
+ integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
+
safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
@@ -5972,10 +6217,10 @@ shellwords@^0.1.1:
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
-shock-common@17.x.x:
- version "17.0.0"
- resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-17.0.0.tgz#9005e35338d58f5aab396ed2dbe6b241c60d5995"
- integrity sha512-OW0KsWaFf/8dq4W8z9047SZRXLi7OggGWrJeRhvw4b79d50uI3/7fXGmquoNXoEnVC8iDAFRjaC35hDSKg+mGA==
+shock-common@32.0.0:
+ version "32.0.0"
+ resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-32.0.0.tgz#bb7f70d7a572783c46aeae7420179935eb5096d4"
+ integrity sha512-1GorUFRpkRGXdKT9PImwnj2orpoJaESU/iD+rvL8sqFMLKazkW9LfLAcRwEWCvytWdKFJ35UO2gN49N8dPiRmA==
dependencies:
immer "^6.0.6"
lodash "^4.17.19"
@@ -6126,6 +6371,14 @@ source-map-resolve@^0.5.0:
source-map-url "^0.4.0"
urix "^0.1.0"
+source-map-support@^0.5.17:
+ version "0.5.19"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
+ integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
source-map-support@^0.5.6:
version "0.5.13"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
@@ -6605,6 +6858,18 @@ triple-beam@^1.2.0, triple-beam@^1.3.0:
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
+ts-node@^9.1.1:
+ version "9.1.1"
+ resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
+ integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
+ dependencies:
+ arg "^4.1.0"
+ create-require "^1.1.0"
+ diff "^4.0.1"
+ make-error "^1.1.1"
+ source-map-support "^0.5.17"
+ yn "3.1.1"
+
ts-toolbelt@^6.6.2:
version "6.7.7"
resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.7.7.tgz#4d7f34cafd519bf0f1d6da5a4b07889db6ba0184"
@@ -6694,10 +6959,10 @@ typescript-tuple@^2.2.1:
dependencies:
typescript-compare "^0.0.2"
-typescript@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2"
- integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==
+typescript@latest:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72"
+ integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==
uglify-js@^3.1.4:
version "3.10.2"
@@ -7123,6 +7388,11 @@ yallist@^3.0.0, yallist@^3.0.3:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
yaml@^1.7.2:
version "1.10.0"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
@@ -7169,3 +7439,8 @@ yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
+
+yn@3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
+ integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==