diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c9fcb4..e4e87110 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - changed: Use rates V3 for transactions with pluginId/tokenId - fixed: Moonpay by adding Revolut payment type - fixed: Use v2 rates API +- changed: Changelly reporting revised ## 0.2.0 diff --git a/package.json b/package.json index 68c9fe68..89219f63 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "@types/node": "^14.0.22", - "api-changelly": "git://github.com/changelly/api-changelly.git#8e350f3", + "scrypt-js": "^3.0.1", "axios": "^0.21.2", "biggystring": "^4.1.3", "body-parser": "^1.19.0", diff --git a/src/partners/changelly.ts b/src/partners/changelly.ts index 74734a90..40893f0e 100644 --- a/src/partners/changelly.ts +++ b/src/partners/changelly.ts @@ -1,180 +1,251 @@ -import Changelly from 'api-changelly/lib.js' -import { asArray, asNumber, asObject, asString, asUnknown } from 'cleaners' +import { + asArray, + asMaybe, + asNumber, + asObject, + asOptional, + asString, + asUnknown, + asValue +} from 'cleaners' +import fetch from 'node-fetch' +import { syncScrypt } from 'scrypt-js' -import { PartnerPlugin, PluginParams, PluginResult, StandardTx } from '../types' -import { datelog, safeParseFloat } from '../util' +import { + EDGE_APP_START_DATE, + PartnerPlugin, + PluginParams, + PluginResult, + StandardTx, + Status +} from '../types' +import { datelog, safeParseFloat, snooze } from '../util' + +const CHANGELLY_URL = 'https://api-relay.changelly.com/'; + +const SCRYPT_SALT = Uint8Array.from([ + 0xb5, 0x86, 0x5f, 0xfb, 0x9f, 0xa7, 0xb3, 0xbf, 0xe4, 0xb2, 0x38, 0x4d, + 0x47, 0xce, 0x83, 0x1e, 0xe2, 0x2a, 0x4a, 0x9d, 0x5c, 0x34, 0xc7, 0xef, + 0x7d, 0x21, 0x46, 0x7c, 0xc7, 0x58, 0xf8, 0x1b +]) +const SCRYPT_N = 16384 +const SCRYPT_R = 1 +const SCRYPT_P = 1 +const SCRYPT_DKLEN = 32 + +function deriveUserId(username: string): string { + const usernameBytes = Buffer.from(username, 'utf8') + const derived = syncScrypt( + usernameBytes, + SCRYPT_SALT, + SCRYPT_N, + SCRYPT_R, + SCRYPT_P, + SCRYPT_DKLEN + ) + return Buffer.from(derived).toString('base64') +} + +// #region Cleaners + +const asChangellyPluginParams = asObject({ + settings: asObject({ + latestIsoDate: asOptional(asString, EDGE_APP_START_DATE) + }), + apiKeys: asObject({ + changellyUsername: asOptional(asString) + }) +}) + +const asChangellyStatus = asMaybe( + asValue( + 'finished', + 'waiting', + 'confirming', + 'exchanging', + 'sending', + 'failed', + 'refunded', + 'expired' + ), + 'other' +) const asChangellyTx = asObject({ id: asString, - payinHash: asString, - payoutHash: asString, - payinAddress: asString, + status: asChangellyStatus, + payinHash: asOptional(asString), + payoutHash: asOptional(asString), + payinAddress: asOptional(asString), currencyFrom: asString, amountFrom: asString, - payoutAddress: asString, + payoutAddress: asOptional(asString), currencyTo: asString, amountTo: asString, createdAt: asNumber }) -const asChangellyRawTx = asObject({ - status: asString +const asChangellyRpcResult = asObject({ + result: asArray(asUnknown) }) -const asChangellyResult = asObject({ - result: asArray(asUnknown) +const asChangellyRpcError = asObject({ + error: asObject({ + code: asNumber, + message: asString + }) }) -const MAX_ATTEMPTS = 3 -const LIMIT = 300 -const TIMEOUT = 20000 -const QUERY_LOOKBACK = 60 * 60 * 24 * 5 // 5 days - -async function getTransactionsPromised( - changellySDK: any, - limit: number, - offset: number, - currencyFrom: string | undefined, - address: string | undefined, - extraId: string | undefined -): Promise> { - let promise - let attempt = 1 - while (true) { - const changellyFetch = new Promise((resolve, reject) => { - changellySDK.getTransactions( - limit, - offset, - currencyFrom, - address, - extraId, - (err, data) => { - if (err != null) { - resolve(err.code) - } else { - resolve(data) - } - } - ) - }) +// #endregion + +type ChangellyTx = ReturnType +type ChangellyStatus = ReturnType + +const statusMap: { [key in ChangellyStatus]: Status } = { + finished: 'complete', + waiting: 'pending', + confirming: 'processing', + exchanging: 'processing', + sending: 'processing', + failed: 'other', + refunded: 'refunded', + expired: 'expired', + other: 'other' +} + +const MAX_RETRIES = 5 +const LIMIT = 50 +const QUERY_LOOKBACK = 1000 * 60 * 60 * 24 * 5 // 5 days - const timeoutTest = new Promise((resolve, reject) => { - setTimeout(resolve, TIMEOUT, 'ETIMEDOUT') - }) +async function changellyRpc( + username: string, + userId: string, + method: string, + params: Record +): Promise { + const ts = Date.now() + const body = JSON.stringify({ + jsonrpc: '2.0', + id: `${method}:${userId}`, + method, + params + }) - promise = await Promise.race([changellyFetch, timeoutTest]) - if (promise === 'ETIMEDOUT' && attempt <= MAX_ATTEMPTS) { - datelog(`Changelly request timed out. Retry attempt: ${attempt}`) - attempt++ - continue + const response = await fetch(CHANGELLY_URL, { + method: 'POST', + body, + headers: { + 'Content-Type': 'application/json', + 'X-Auth': Buffer.from( + [username, userId, ts].join(':') + ).toString('base64') } - break + }) + + if (!response.ok) { + const text = await response.text() + throw new Error(`Changelly HTTP ${response.status}: ${text}`) + } + + const json = await response.json() + + const maybeError = asMaybe(asChangellyRpcError)(json) + if (maybeError != null) { + throw new Error( + `Changelly RPC error ${maybeError.error.code}: ${maybeError.error.message}` + ) } - return promise + + return json } -export async function queryChangelly( +export const queryChangelly = async ( pluginParams: PluginParams -): Promise { - let changellySDK - let latestTimeStamp = 0 - let offset = 0 - let firstAttempt = false - if (typeof pluginParams.settings.latestTimeStamp === 'number') { - latestTimeStamp = pluginParams.settings.latestTimeStamp - } - if ( - typeof pluginParams.settings.firstAttempt === 'undefined' || - pluginParams.settings.firstAttempt === true - ) { - firstAttempt = true - } - if (typeof pluginParams.settings.offset === 'number' && firstAttempt) { - offset = pluginParams.settings.offset - } - if ( - typeof pluginParams.apiKeys.changellyApiKey === 'string' && - typeof pluginParams.apiKeys.changellyApiSecret === 'string' - ) { - changellySDK = new Changelly( - pluginParams.apiKeys.changellyApiKey, - pluginParams.apiKeys.changellyApiSecret - ) - } else { - return { - settings: { - latestTimeStamp: latestTimeStamp - }, - transactions: [] - } +): Promise => { + const { settings, apiKeys } = asChangellyPluginParams(pluginParams) + let { changellyUsername } = apiKeys + let { latestIsoDate } = settings + + if (changellyUsername == null) { + changellyUsername = 'edge-app'; + // return { settings: { latestIsoDate }, transactions: [] } } + const userId = deriveUserId(changellyUsername) const standardTxs: StandardTx[] = [] - let newLatestTimeStamp = latestTimeStamp - let done = false - try { - while (!done) { + let previousTimestamp = new Date(latestIsoDate).getTime() - QUERY_LOOKBACK + if (previousTimestamp < 0) previousTimestamp = 0 + const previousLatestTimestamp = Math.floor(previousTimestamp / 1000) + + let offset = 0 + let retry = 0 + while (true) { + try { datelog(`Query changelly offset: ${offset}`) - const result = await getTransactionsPromised( - changellySDK, - LIMIT, - offset, - undefined, - undefined, - undefined + const result = await changellyRpc( + changellyUsername, + userId, + 'getTransactions', + { limit: LIMIT, offset } ) - const txs = asChangellyResult(result).result + const txs = asChangellyRpcResult(result).result + if (txs.length === 0) { datelog(`Changelly done at offset ${offset}`) - firstAttempt = false break } + + let reachedLookback = false for (const rawTx of txs) { - if (asChangellyRawTx(rawTx).status === 'finished') { - const standardTx = processChangellyTx(rawTx) - standardTxs.push(standardTx) - if (standardTx.timestamp > newLatestTimeStamp) { - newLatestTimeStamp = standardTx.timestamp - } - if ( - standardTx.timestamp < latestTimeStamp - QUERY_LOOKBACK && - !done && - !firstAttempt - ) { - datelog( - `Changelly done: date ${ - standardTx.timestamp - } < ${latestTimeStamp - QUERY_LOOKBACK}` - ) - done = true - } + const standardTx = processChangellyTx(rawTx) + standardTxs.push(standardTx) + if (standardTx.isoDate > latestIsoDate) { + latestIsoDate = standardTx.isoDate + } + if (standardTx.timestamp < previousLatestTimestamp) { + reachedLookback = true } } - offset += LIMIT + + if (reachedLookback) { + datelog(`Changelly reached lookback at offset ${offset}`) + break + } + + offset += txs.length + retry = 0 + } catch (e) { + datelog(e) + retry++ + if (retry <= MAX_RETRIES) { + datelog(`Snoozing ${5 * retry}s`) + await snooze(5000 * retry) + } else { + break + } } - } catch (e) { - datelog(e) } - const out = { - settings: { latestTimeStamp: newLatestTimeStamp, firstAttempt, offset }, + + const out: PluginResult = { + settings: { latestIsoDate }, transactions: standardTxs } return out } export const changelly: PartnerPlugin = { - // queryFunc will take PluginSettings as arg and return PluginResult queryFunc: queryChangelly, - // results in a PluginResult pluginName: 'Changelly', pluginId: 'changelly' } export function processChangellyTx(rawTx: unknown): StandardTx { - const tx = asChangellyTx(rawTx) + const tx: ChangellyTx = asChangellyTx(rawTx) + const date = new Date(tx.createdAt / 1000) + const timestamp = tx.createdAt const standardTx: StandardTx = { - status: 'complete', + status: statusMap[tx.status], orderId: tx.id, countryCode: null, depositTxid: tx.payinHash, @@ -194,8 +265,8 @@ export function processChangellyTx(rawTx: unknown): StandardTx { payoutEvmChainId: undefined, payoutTokenId: undefined, payoutAmount: safeParseFloat(tx.amountTo), - timestamp: tx.createdAt, - isoDate: new Date(tx.createdAt * 1000).toISOString(), + timestamp, + isoDate: date.toISOString(), usdValue: -1, rawTx } diff --git a/yarn.lock b/yarn.lock index d7baa4bc..6266a5b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1057,11 +1057,6 @@ resolved "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz" integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA== -"@types/node@^10.3.5": - version "10.17.28" - resolved "https://registry.npmjs.org/@types/node/-/node-10.17.28.tgz" - integrity sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ== - "@types/node@^12.12.6": version "12.12.54" resolved "https://registry.npmjs.org/@types/node/-/node-12.12.54.tgz" @@ -1254,14 +1249,6 @@ resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== -JSONStream@^1.3.1: - version "1.3.5" - resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz" - integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - abortcontroller-polyfill@^1.1.9: version "1.7.5" resolved "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz" @@ -1290,11 +1277,6 @@ acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== -after@0.8.2: - version "0.8.2" - resolved "https://registry.npmjs.org/after/-/after-0.8.2.tgz" - integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= - agent-base@^6.0.2: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" @@ -1385,13 +1367,6 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -"api-changelly@git://github.com/changelly/api-changelly.git#8e350f3": - version "1.0.0" - resolved "git+ssh://git@github.com/changelly/api-changelly.git#8e350f381d6fd725d6bae02692da8b9456f4451b" - dependencies: - jayson "^2.0.1" - socket.io-client "^1.4.6" - argparse@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" @@ -1481,11 +1456,6 @@ arraybuffer.prototype.slice@^1.0.2: is-array-buffer "^3.0.2" is-shared-array-buffer "^1.0.2" -arraybuffer.slice@0.0.6: - version "0.0.6" - resolved "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz" - integrity sha1-8zshWfBTKj8xB6JywMz70a0peco= - asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" @@ -1593,11 +1563,6 @@ babel-runtime@^6.26.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz" - integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= - balanced-match@^0.4.2: version "0.4.2" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" @@ -1615,11 +1580,6 @@ base-x@^3.0.2, base-x@^3.0.8: dependencies: safe-buffer "^5.0.1" -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz" - integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= - base64-js@^1.0.2: version "1.3.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz" @@ -1632,13 +1592,6 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz" - integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= - dependencies: - callsite "1.0.0" - biggystring@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/biggystring/-/biggystring-4.1.3.tgz#9a7d6e79e82781ecd1504aac30a1a815f073adcc" @@ -1661,11 +1614,6 @@ blakejs@^1.1.0: resolved "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz" integrity sha1-ad+S75U6qIylGjLfarHFShVfx6U= -blob@0.0.4: - version "0.0.4" - resolved "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz" - integrity sha1-vPEwUspURj8w+fx+lbmkdjCpSSE= - bluebird@^3.5.0: version "3.7.2" resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" @@ -1891,11 +1839,6 @@ call-bound@^1.0.2: call-bind-apply-helpers "^1.0.1" get-intrinsic "^1.2.6" -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" - integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= - callsites@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" @@ -2100,7 +2043,7 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.12.2, commander@^2.20.0: +commander@^2.20.0: version "2.20.3" resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -2130,26 +2073,6 @@ compare-versions@^3.6.0: resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz" integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz" - integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= - -component-emitter@1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz" - integrity sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM= - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz" - integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= - concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -2446,20 +2369,6 @@ date-fns@^2.16.1: resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz" integrity sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ== -debug@2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - integrity sha1-+HBX6ZWxofauaklgZkE3vFbwOdo= - dependencies: - ms "0.7.1" - -debug@2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz" - integrity sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w= - dependencies: - ms "0.7.2" - debug@2.6.9, debug@^2.2.0: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" @@ -2763,36 +2672,6 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -engine.io-client@~1.8.4: - version "1.8.5" - resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.5.tgz" - integrity sha512-AYTgHyeVUPitsseqjoedjhYJapNVoSPShbZ+tEUX9/73jgZ/Z3sUlJf9oYgdEBBdVhupUpUqSxH0kBCXlQnmZg== - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "2.3.3" - engine.io-parser "1.3.2" - has-cors "1.1.0" - indexof "0.0.1" - parsejson "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~1.1.5" - xmlhttprequest-ssl "1.5.3" - yeast "0.1.2" - -engine.io-parser@1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz" - integrity sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo= - dependencies: - after "0.8.2" - arraybuffer.slice "0.0.6" - base64-arraybuffer "0.1.5" - blob "0.0.4" - has-binary "0.1.7" - wtf-8 "1.0.0" - enquirer@^2.3.5: version "2.3.6" resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" @@ -2990,18 +2869,6 @@ es6-object-assign@^1.1.0: resolved "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz" integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - es6-symbol@^3.1.1, es6-symbol@~3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" @@ -3462,11 +3329,6 @@ extsprintf@^1.2.0: resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -eyes@^0.1.8: - version "0.1.8" - resolved "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" @@ -3964,18 +3826,6 @@ has-bigints@^1.0.2: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== -has-binary@0.1.7: - version "0.1.7" - resolved "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz" - integrity sha1-aOYesWIQyVRaClzOBqhzkS/h5ow= - dependencies: - isarray "0.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz" - integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" @@ -4230,11 +4080,6 @@ indent-string@^4.0.0: resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - inflight@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" @@ -4629,20 +4474,6 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" -jayson@^2.0.1: - version "2.1.2" - resolved "https://registry.npmjs.org/jayson/-/jayson-2.1.2.tgz" - integrity sha512-2GejcQnEV35KYTXoBvzALIDdO/1oyEIoJHBnaJFhJhcurv0x2JqUXQW6xlDUhcNOpN9t+d2w+JGA6vOphb+5mg== - dependencies: - "@types/node" "^10.3.5" - JSONStream "^1.3.1" - commander "^2.12.2" - es6-promisify "^5.0.0" - eyes "^0.1.8" - json-stringify-safe "^5.0.1" - lodash "^4.17.11" - uuid "^3.2.1" - js-sha3@0.5.7, js-sha3@^0.5.7: version "0.5.7" resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz" @@ -4700,16 +4531,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@3.3.2: - version "3.3.2" - resolved "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz" - integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= - json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -4729,11 +4555,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz" - integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= - jsprim@^1.2.2: version "1.4.1" resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz" @@ -4942,7 +4763,7 @@ lodash.throttle@^4.1.1: resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz" integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= -lodash@^4.17.11, lodash@^4.17.5, lodash@~4.17.4: +lodash@^4.17.5, lodash@~4.17.4: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5220,16 +5041,6 @@ mock-fs@^4.1.0: resolved "https://registry.npmjs.org/mock-fs/-/mock-fs-4.12.0.tgz" integrity sha512-/P/HtrlvBxY4o/PzXY9cCNBrdylDNxg7gnrv2sMNxj+UJ2m8jSpl0/A6fuJeNAWr99ZvGWH8XCbE0vmnM5KupQ== -ms@0.7.1: - version "0.7.1" - resolved "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= - -ms@0.7.2: - version "0.7.2" - resolved "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" - integrity sha1-riXPJRKziFodldfwN4aNhDESR2U= - ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" @@ -5507,11 +5318,6 @@ object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1 resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz" - integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= - object-inspect@^1.11.0, object-inspect@^1.9.0: version "1.12.0" resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz" @@ -5665,11 +5471,6 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" -options@>=0.0.5: - version "0.0.6" - resolved "https://registry.npmjs.org/options/-/options-0.0.6.tgz" - integrity sha1-7CLTEoBrtT5zF3Pnza788cZDEo8= - ordered-binary@^1.2.4: version "1.4.0" resolved "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.4.0.tgz" @@ -5803,27 +5604,6 @@ parse-json@^5.0.0: json-parse-better-errors "^1.0.1" lines-and-columns "^1.1.6" -parsejson@0.0.3: - version "0.0.3" - resolved "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz" - integrity sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs= - dependencies: - better-assert "~1.0.0" - -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz" - integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= - dependencies: - better-assert "~1.0.0" - -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz" - integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= - dependencies: - better-assert "~1.0.0" - parseurl@~1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" @@ -6854,33 +6634,6 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -socket.io-client@^1.4.6: - version "1.7.4" - resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.4.tgz" - integrity sha1-7J+CA1btme9tNX8HVtZIcXvdQoE= - dependencies: - backo2 "1.0.2" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "2.3.3" - engine.io-client "~1.8.4" - has-binary "0.1.7" - indexof "0.0.1" - object-component "0.0.3" - parseuri "0.0.5" - socket.io-parser "2.3.1" - to-array "0.1.4" - -socket.io-parser@2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz" - integrity sha1-3VMgJRA85Clpcya+/WQAX8/ltKA= - dependencies: - component-emitter "1.1.2" - debug "2.2.0" - isarray "0.0.1" - json3 "3.3.2" - source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" @@ -7259,7 +7012,7 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" -"through@>=2.2.7 <3", through@^2.3.8: +through@^2.3.8: version "2.3.8" resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -7284,11 +7037,6 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3: resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" - integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= - to-readable-stream@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" @@ -7474,11 +7222,6 @@ typescript@^4.8.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -ultron@1.0.x: - version "1.0.2" - resolved "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz" - integrity sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po= - ultron@~1.1.0: version "1.1.1" resolved "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz" @@ -7624,7 +7367,7 @@ uuid@3.3.2: resolved "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -uuid@^3.2.1, uuid@^3.3.2: +uuid@^3.3.2: version "3.4.0" resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -8066,19 +7809,6 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@~1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz" - integrity sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w== - dependencies: - options ">=0.0.5" - ultron "1.0.x" - -wtf-8@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz" - integrity sha1-OS2LotDxw00e4tYw8V0O+2jhBIo= - xhr-request-promise@^0.1.2: version "0.1.3" resolved "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz" @@ -8116,11 +7846,6 @@ xhr@^2.0.4, xhr@^2.3.3: parse-headers "^2.0.0" xtend "^4.0.0" -xmlhttprequest-ssl@1.5.3: - version "1.5.3" - resolved "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz" - integrity sha1-GFqIjATspGw+QHDZn3tJ3jUomS0= - xtend@^4.0.0, xtend@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" @@ -8194,11 +7919,6 @@ yavent@^0.1.3: resolved "https://registry.yarnpkg.com/yavent/-/yavent-0.1.4.tgz#b5ddbd01ff7351a8dee51025609e3bd924090733" integrity sha512-8N18drD5IWdqwFkvDmYmJdRFj9LCuoTMqKMCBa/mYAnDOZNDrW4itJwHGXQMY7TgeK8SmR75Hg5dds1/hRf9iQ== -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"