diff --git a/package.json b/package.json index 61211590..314e9845 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@stellar/wallet-sdk", - "version": "0.7.0-rc.0", + "version": "0.8.0", "description": "Libraries to help you write Stellar-enabled wallets in Javascript", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -67,7 +67,7 @@ "prettier": "^1.17.0", "regenerator-runtime": "^0.13.3", "sinon": "^7.3.1", - "stellar-sdk": "^9.0.1", + "stellar-sdk": "^10.4.0", "terser-webpack-plugin": "^2.3.0", "ts-loader": "^6.2.1", "tsc-watch": "^2.1.2", diff --git a/src/KeyManagerPlugins.ts b/src/KeyManagerPlugins.ts index d23ecc08..b9967937 100644 --- a/src/KeyManagerPlugins.ts +++ b/src/KeyManagerPlugins.ts @@ -1,9 +1,11 @@ +import { BrowserStorageKeyStore } from "./plugins/BrowserStorageKeyStore"; import { IdentityEncrypter } from "./plugins/IdentityEncrypter"; import { LocalStorageKeyStore } from "./plugins/LocalStorageKeyStore"; import { MemoryKeyStore } from "./plugins/MemoryKeyStore"; import { ScryptEncrypter } from "./plugins/ScryptEncrypter"; export const KeyManagerPlugins: any = { + BrowserStorageKeyStore, IdentityEncrypter, MemoryKeyStore, LocalStorageKeyStore, diff --git a/src/plugins/BrowserStorageFacade.ts b/src/plugins/BrowserStorageFacade.ts new file mode 100644 index 00000000..85bde54b --- /dev/null +++ b/src/plugins/BrowserStorageFacade.ts @@ -0,0 +1,92 @@ +import { EncryptedKey } from "../types"; + +export interface BrowserStorageConfigParams { + prefix?: string; + storage: { + get: (key?: string | string[] | {}) => Promise<{}>; + remove: (key: string | string[]) => Promise; + set: (items: {}) => Promise<{}>; + }; +} + +const PREFIX = "stellarkeys"; + +/** + * Facade for `BrowserStorageKeyStore` encapsulating the access to the actual + * browser storage + */ +export class BrowserStorageFacade { + private storage: Storage | null; + private prefix: string; + + constructor() { + this.storage = null; + this.prefix = PREFIX; + } + + public configure(params: BrowserStorageConfigParams) { + Object.assign(this, params); + } + + public async hasKey(id: string) { + this.check(); + + return this.storage !== null + ? !!Object.keys(await this.storage.get(`${this.prefix}:${id}`)).length + : null; + } + + public async getKey(id: string) { + this.check(); + const key = `${this.prefix}:${id}`; + const itemObj = this.storage !== null ? await this.storage.get(key) : null; + + const item = itemObj[key]; + return item || null; + } + + public setKey(id: string, key: EncryptedKey) { + this.check(); + return this.storage !== null + ? this.storage.set({ [`${this.prefix}:${id}`]: { ...key } }) + : null; + } + + public removeKey(id: string) { + this.check(); + return this.storage !== null + ? this.storage.remove(`${this.prefix}:${id}`) + : null; + } + + public async getAllKeys() { + this.check(); + const regexp = RegExp(`^${PREFIX}\\:(.*)`); + const keys: EncryptedKey[] = []; + + if (this.storage !== null) { + const storageObj = await this.storage.get(null); + const storageKeys = Object.keys(storageObj); + for (const storageKey of storageKeys) { + const raw_id = storageKey; + if (raw_id !== null && regexp.test(raw_id)) { + const key = await this.getKey(regexp.exec(raw_id)![1]); + if (key !== null) { + keys.push(key); + } + } + } + } + return keys; + } + + private check() { + if (this.storage === null) { + throw new Error("A storage object must have been set"); + } + if (this.prefix === "") { + throw new Error("A non-empty prefix must have been set"); + } + return this.storage !== null && this.prefix !== ""; + } +} diff --git a/src/plugins/BrowserStorageKeyStore.test.ts b/src/plugins/BrowserStorageKeyStore.test.ts new file mode 100644 index 00000000..d0420c8b --- /dev/null +++ b/src/plugins/BrowserStorageKeyStore.test.ts @@ -0,0 +1,97 @@ +import sinon from "sinon"; + +import { EncryptedKey } from "../types"; +import { BrowserStorageKeyStore } from "./BrowserStorageKeyStore"; + +// tslint:disable-next-line +describe("BrowserStorageKeyStore", function() { + let clock: sinon.SinonFakeTimers; + let testStore: BrowserStorageKeyStore; + const encryptedKey: EncryptedKey = { + id: "PURIFIER", + encryptedBlob: "BLOB", + encrypterName: "Test", + salt: "SLFKJSDLKFJLSKDJFLKSJD", + }; + const keyMetadata = { + id: "PURIFIER", + }; + const chrome = { + storage: { + local: { + get: (_key?: string | string[] | {}) => Promise.resolve({}), + set: (_items: {}) => Promise.resolve({}), + remove: (_key: string | string[]) => Promise.resolve(), + }, + }, + }; + + beforeEach(() => { + clock = sinon.useFakeTimers(666); + testStore = new BrowserStorageKeyStore(); + + testStore.configure({ storage: chrome.storage.local }); + }); + + afterEach(() => { + clock.restore(); + sinon.restore(); + }); + + it("properly stores keys", async () => { + const chromeStorageLocalGetStub = sinon.stub(chrome.storage.local, "get"); + + /* first call returns empty to confirm keystore + doesn't already exist before storing */ + chromeStorageLocalGetStub.onCall(0).returns(Promise.resolve({})); + const testMetadata = await testStore.storeKeys([encryptedKey]); + + expect(testMetadata).toEqual([keyMetadata]); + + // subsequent calls return the keystore as expected + chromeStorageLocalGetStub.returns( + Promise.resolve({ [`stellarkeys:${encryptedKey.id}`]: encryptedKey }), + ); + const allKeys = await testStore.loadAllKeys(); + + expect(allKeys).toEqual([{ ...encryptedKey, ...keyMetadata }]); + }); + + it("properly deletes keys", async () => { + const chromeStorageLocalGetStub = sinon.stub(chrome.storage.local, "get"); + + /* first call returns empty to confirm keystore + doesn't already exist before storing */ + chromeStorageLocalGetStub.onCall(0).returns(Promise.resolve({})); + await testStore.storeKeys([encryptedKey]); + + // subsequent calls return the keystore as expected + chromeStorageLocalGetStub.returns( + Promise.resolve({ [`stellarkeys:${encryptedKey.id}`]: encryptedKey }), + ); + + const allKeys = await testStore.loadAllKeys(); + + expect(allKeys).toEqual([{ ...encryptedKey, ...keyMetadata }]); + + const removalMetadata = await testStore.removeKey("PURIFIER"); + chromeStorageLocalGetStub.returns(Promise.resolve({})); + + expect(removalMetadata).toEqual(keyMetadata); + const noKeys = await testStore.loadAllKeys(); + + expect(noKeys).toEqual([]); + }); + + it("passes PluginTesting", () => { + /* + TODO: + this test cannot currently be run because we + don't have an adequate way to stub chrome.local.storage yet */ + // testKeyStore(testStore) + // .then(() => { + // done(); + // }) + // .catch(done); + }); +}); diff --git a/src/plugins/BrowserStorageKeyStore.ts b/src/plugins/BrowserStorageKeyStore.ts new file mode 100644 index 00000000..210d0e1e --- /dev/null +++ b/src/plugins/BrowserStorageKeyStore.ts @@ -0,0 +1,126 @@ +import { getKeyMetadata } from "../helpers/getKeyMetadata"; +import { EncryptedKey, KeyMetadata, KeyStore } from "../types"; +import { + BrowserStorageConfigParams, + BrowserStorageFacade, +} from "./BrowserStorageFacade"; + +/** + * KeyStore for Chrome and Firefox browser storage API: + * https://developer.chrome.com/docs/extensions/reference/storage/. + * Once instantiated and configured, pass it to the `KeyManager` contructor to + * handle the storage of encrypted keys. + * ```js + * const browserKeyStore = new KeyManagerPlugins.BrowserStorageKeyStore(); + * browserKeyStore.configure({ storage: chrome.storage.local }); + * const keyManager = new KeyManager({ + * keyStore: browserKeyStore + * }); + * ``` + */ +export class BrowserStorageKeyStore implements KeyStore { + public name: string; + private keyStore: BrowserStorageFacade; + + constructor() { + this.name = "BrowserStorageKeyStore"; + this.keyStore = new BrowserStorageFacade(); + } + + /** + * The configuration is where the storage engine is set up and configured. + * It must follow the Storage interface : + * https://developer.chrome.com/docs/extensions/reference/storage/). + * This is mostly for use with Chrome and Firefox storage in addition to + * libraries that shim this (for ex: webextension-polyfill) + * @param {BrowserStorageConfigParams} params A configuration object. + * @param {Storage} params.storage The Storage instance. Required. + * @param {string} [params.prefix] The prefix for the names in the storage. + * @return {Promise} + */ + public configure(params: BrowserStorageConfigParams) { + try { + this.keyStore.configure(params); + return Promise.resolve(); + } catch (e) { + return Promise.reject(e); + } + } + + public async storeKeys(keys: EncryptedKey[]) { + // We can't store keys if they're already there + const usedKeys: EncryptedKey[] = []; + + for (const encryptedKey of keys) { + const hasKey = await this.keyStore.hasKey(encryptedKey.id); + if (hasKey) { + usedKeys.push(encryptedKey); + } + } + + if (usedKeys.length) { + return Promise.reject( + `Some keys were already stored in the keystore: ${usedKeys + .map((k) => k.id) + .join(", ")}`, + ); + } + + const keysMetadata: KeyMetadata[] = []; + + for (const encryptedKey of keys) { + this.keyStore.setKey(encryptedKey.id, encryptedKey); + keysMetadata.push(getKeyMetadata(encryptedKey)); + } + + return Promise.resolve(keysMetadata); + } + + public updateKeys(keys: EncryptedKey[]) { + // we can't update keys if they're already stored + const invalidKeys: EncryptedKey[] = keys.filter( + async (encryptedKey: EncryptedKey) => + !(await this.keyStore.hasKey(encryptedKey.id)), + ); + + if (invalidKeys.length) { + return Promise.reject( + `Some keys couldn't be found in the keystore: ${invalidKeys + .map((k) => k.id) + .join(", ")}`, + ); + } + + const keysMetadata = keys.map((encryptedKey: EncryptedKey) => { + this.keyStore.setKey(encryptedKey.id, encryptedKey); + return getKeyMetadata(encryptedKey); + }); + + return Promise.resolve(keysMetadata); + } + + public async loadKey(id: string) { + const key = await this.keyStore.getKey(id); + if (!key) { + return Promise.reject(id); + } + return Promise.resolve(key); + } + + public async removeKey(id: string) { + if (!this.keyStore.hasKey(id)) { + return Promise.reject(id); + } + + const key = await this.keyStore.getKey(id); + const metadata: KeyMetadata = getKeyMetadata(key); + this.keyStore.removeKey(id); + + return Promise.resolve(metadata); + } + + public async loadAllKeys() { + const keys = await this.keyStore.getAllKeys(); + return Promise.resolve(keys); + } +} diff --git a/yarn.lock b/yarn.lock index dc17e3c1..8f6313b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -899,6 +899,13 @@ dependencies: type-detect "4.0.8" +"@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.7.0": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.5.tgz#e280c94c95f206dcfd5aca00a43f2156b758c764" + integrity sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA== + dependencies: + type-detect "4.0.8" + "@sinonjs/formatio@^3.1.0", "@sinonjs/formatio@^3.2.1": version "3.2.1" resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.1.tgz#52310f2f9bcbc67bdac18c94ad4901b95fde267e" @@ -925,6 +932,15 @@ array-from "^2.1.1" lodash "^4.17.11" +"@sinonjs/samsam@^3.3.3": + version "3.3.3" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.3.tgz#46682efd9967b259b81136b9f120fd54585feb4a" + integrity sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ== + dependencies: + "@sinonjs/commons" "^1.3.0" + array-from "^2.1.1" + lodash "^4.17.15" + "@sinonjs/text-encoding@^0.7.1": version "0.7.1" resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" @@ -983,6 +999,14 @@ dependencies: "@babel/types" "^7.3.0" +"@types/chrome@*": + version "0.0.202" + resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.202.tgz#ecc6747cc797b6b8427cbb5d9723c91dfc8bd3f4" + integrity sha512-Oc4daL9sFS+9MToVZPLMBxR7PxsEdod0b8wOY11lRr06GJp43MORvHeDyMD8QzeRGT6HI13oaYAe2PBgvALc4w== + dependencies: + "@types/filesystem" "*" + "@types/har-format" "*" + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -993,6 +1017,18 @@ resolved "https://registry.yarnpkg.com/@types/eventsource/-/eventsource-1.1.2.tgz#079ab4213e844e56f7384aec620e1163dab692b3" integrity sha512-4AKWJ6tvEU4fk0770oAK4Z0lQUuSnc5ljHTcYZhQtdP7XMDKKvegGUC6xGD8+4+F+svZKAzlxbKnuGWfgMtgVA== +"@types/filesystem@*": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.32.tgz#307df7cc084a2293c3c1a31151b178063e0a8edf" + integrity sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ== + dependencies: + "@types/filewriter" "*" + +"@types/filewriter@*": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.29.tgz#a48795ecadf957f6c0d10e0c34af86c098fa5bee" + integrity sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ== + "@types/fs-extra@^5.0.3": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1" @@ -1016,6 +1052,11 @@ dependencies: handlebars "*" +"@types/har-format@*": + version "1.2.9" + resolved "https://registry.yarnpkg.com/@types/har-format/-/har-format-1.2.9.tgz#b9b3a9bfc33a078e7d898a00b09662910577f4a4" + integrity sha512-rffW6MhQ9yoa75bdNi+rjZBAvu2HhehWJXlhuWXnWdENeuKe82wUgAwxYOb7KRKKmxYN+D/iRKd2NDQMLqlUmg== + "@types/highlight.js@^9.12.3": version "9.12.3" resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca" @@ -1100,11 +1141,31 @@ "@types/glob" "*" "@types/node" "*" +"@types/sinon-chrome@^2.2.11": + version "2.2.11" + resolved "https://registry.yarnpkg.com/@types/sinon-chrome/-/sinon-chrome-2.2.11.tgz#b931fc55dd0e8fbbf9ce603d040f587f40fbe37b" + integrity sha512-hmpjlIDwIi8LLYdzZMh9+oj6k4mM7hD3dEC2a5vzYbNvIEIqDLxED8WhfroqLzLHLYV3ni5N1fLOEF0fmaFpqA== + dependencies: + "@types/chrome" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "10.0.13" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.13.tgz#60a7a87a70d9372d0b7b38cc03e825f46981fb83" + integrity sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ== + dependencies: + "@types/sinonjs__fake-timers" "*" + "@types/sinon@^7.0.11": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-7.0.11.tgz#6f28f005a36e779b7db0f1359b9fb9eef72aae88" integrity sha512-6ee09Ugx6GyEr0opUIakmxIWFNmqYPjkqa3/BuxCBokA0klsOLPgMD5K4q40lH7/yZVuJVzOfQpd7pipwjngkQ== +"@types/sinonjs__fake-timers@*": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" + integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -1547,12 +1608,12 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -axios@0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== +axios@0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" + integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== dependencies: - follow-redirects "^1.10.0" + follow-redirects "^1.14.7" babel-jest@^24.5.0, babel-jest@^24.7.1: version "24.7.1" @@ -2758,12 +2819,10 @@ events@^3.2.0: resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== -eventsource@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" - integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ== - dependencies: - original "^1.0.0" +eventsource@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.2.tgz#bc75ae1c60209e7cb1541231980460343eaea7c2" + integrity sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" @@ -2995,10 +3054,10 @@ fn-name@~2.0.1: resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc= -follow-redirects@^1.10.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" - integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg== +follow-redirects@^1.14.7: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== for-in@^1.0.2: version "1.0.2" @@ -4568,16 +4627,16 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= +lodash@^4.16.3, lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.5: version "4.17.19" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - log-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" @@ -4611,6 +4670,18 @@ lolex@^3.1.0: resolved "https://registry.yarnpkg.com/lolex/-/lolex-3.1.0.tgz#1a7feb2fefd75b3e3a7f79f0e110d9476e294434" integrity sha512-zFo5MgCJ0rZ7gQg69S4pqBsLURbFw11X68C18OcJjJQbqaXm2NoTrGl1IMM3TIz0/BnN1tIs2tzmmqvCsOMMjw== +lolex@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.2.0.tgz#ddbd7f6213ca1ea5826901ab1222b65d714b3cd7" + integrity sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg== + +lolex@^5.0.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.2.tgz#953694d098ce7c07bc5ed6d0e42bc6c0c6d5a367" + integrity sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A== + dependencies: + "@sinonjs/commons" "^1.7.0" + long@^2.2.3: version "2.4.0" resolved "https://registry.yarnpkg.com/long/-/long-2.4.0.tgz#9fa180bb1d9500cdc29c4156766a1995e1f4524f" @@ -4951,11 +5022,6 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -nan@^2.14.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - nan@^2.9.2: version "2.13.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" @@ -5013,6 +5079,17 @@ nise@^1.4.10: lolex "^2.3.2" path-to-regexp "^1.7.0" +nise@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.3.tgz#9d2cfe37d44f57317766c6e9408a359c5d3ac1f7" + integrity sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ== + dependencies: + "@sinonjs/formatio" "^3.2.1" + "@sinonjs/text-encoding" "^0.7.1" + just-extend "^4.0.2" + lolex "^5.0.1" + path-to-regexp "^1.7.0" + no-case@^2.2.0, no-case@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" @@ -5030,10 +5107,10 @@ node-fetch@2.6.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== -node-gyp-build@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.0.tgz#3bc3dd7dd4aafecaf64a2e3729e785bc3cdea565" - integrity sha512-rGLv++nK20BG8gc0MzzcYe1Nl3p3mtwJ74Q2QD0HTEDKZ6NvOFSelY6s2QBPWIHRR8h7hpad0LiwajfClBJfNg== +node-gyp-build@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" + integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== node-int64@^0.4.0: version "0.4.0" @@ -5281,13 +5358,6 @@ optionator@^0.8.1: type-check "~0.3.2" wordwrap "~1.0.0" -original@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" - integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== - dependencies: - url-parse "^1.4.3" - os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" @@ -5784,11 +5854,6 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= -querystringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" - integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -6037,11 +6102,6 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -6308,6 +6368,28 @@ simple-git@^1.85.0: dependencies: debug "^4.0.1" +sinon-chrome@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/sinon-chrome/-/sinon-chrome-3.0.1.tgz#9fb14c230fa0959cb280f9f589e9eda8ccfda1d9" + integrity sha512-NTEFhyuiWEMnRmIqldUiA2DhKn2EqnZxyEk5Ez5rBXj+Nl54aJ0MEmF4wjltrxecxd8zlNLxyE0HyLabev9JsQ== + dependencies: + lodash "^4.16.3" + sinon "^7.2.3" + urijs "^1.18.2" + +sinon@^7.2.3: + version "7.5.0" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.5.0.tgz#e9488ea466070ea908fd44a3d6478fd4923c67ec" + integrity sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q== + dependencies: + "@sinonjs/commons" "^1.4.0" + "@sinonjs/formatio" "^3.2.1" + "@sinonjs/samsam" "^3.3.3" + diff "^3.5.0" + lolex "^4.2.0" + nise "^1.5.2" + supports-color "^5.5.0" + sinon@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.3.1.tgz#e8276522104e6c08d1cb52a907270b0e316655c4" @@ -6378,14 +6460,12 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sodium-native@^2.3.0: - version "2.4.6" - resolved "https://registry.yarnpkg.com/sodium-native/-/sodium-native-2.4.6.tgz#8a8173095e8cf4f997de393a2ba106c34870cac2" - integrity sha512-Ro9lhTjot8M01nwKLXiqLSmjR7B8o+Wg4HmJUjEShw/q6XPlNMzjPkA1VJKaMH8SO8fJ/sggAKVwreTaFszS2Q== +sodium-native@^3.3.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/sodium-native/-/sodium-native-3.4.1.tgz#44616c07ccecea15195f553af88b3e574b659741" + integrity sha512-PaNN/roiFWzVVTL6OqjzYct38NSXewdl2wz8SRB51Br/MLIJPrbM3XexhVWkq7D3UWMysfrhKVf1v1phZq6MeQ== dependencies: - ini "^1.3.5" - nan "^2.14.0" - node-gyp-build "^4.1.0" + node-gyp-build "^4.3.0" source-list-map@^2.0.0: version "2.0.1" @@ -6542,10 +6622,10 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= -stellar-base@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/stellar-base/-/stellar-base-6.0.4.tgz#2b44ef6434e52cbfca103ff9349f16fca806557e" - integrity sha512-zYoo4sjeF3mX9L/m/VF5qySpKdmGi+1c8Q58dB+wRNSLZMYssx7cplONuFMZpcCDukSdFNx+8mjyZdPuy7j1tA== +stellar-base@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/stellar-base/-/stellar-base-8.2.1.tgz#9d4259760ce61bc232e1045273cb2424a9950cb3" + integrity sha512-rtTrAxkKq+ppE88xJSqEt9Lsp9bjpx3n0jn5QdqsWHvuo6EQ4yd1ODZe3P7ueEPyMfillc2BIZEV+p4Y9ndJQA== dependencies: base32.js "^0.1.0" bignumber.js "^4.0.0" @@ -6553,27 +6633,27 @@ stellar-base@^6.0.4: js-xdr "^1.1.3" lodash "^4.17.21" sha.js "^2.3.6" - tweetnacl "^1.0.0" + tweetnacl "^1.0.3" optionalDependencies: - sodium-native "^2.3.0" + sodium-native "^3.3.0" -stellar-sdk@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/stellar-sdk/-/stellar-sdk-9.0.1.tgz#f0d920def0b395c9c240d6e399a1c63b107b3bd1" - integrity sha512-hHRlCAjX5NPEXAmUtIu0BU0F7Mm8qtTCldXgb2mXosfHz8o/vu7lYy/08FjEav925TlsS51HSu2MN0+qHnYkjQ== +stellar-sdk@^10.1.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/stellar-sdk/-/stellar-sdk-10.4.0.tgz#9b0a5c2406a7f19d7710da6268c0ccd149698c65" + integrity sha512-dx2CuTLaYKEY1b0HMxjsQQ0o+7hrmukT/idO/IH4FsZ8NVMKjbN4xADjzYx3VbNtHNi8MDWRBMWIY8aNR2o4Ew== dependencies: "@types/eventsource" "^1.1.2" "@types/node" ">= 8" "@types/randombytes" "^2.0.0" "@types/urijs" "^1.19.6" - axios "0.21.1" + axios "0.25.0" bignumber.js "^4.0.0" detect-node "^2.0.4" es6-promise "^4.2.4" - eventsource "^1.0.7" + eventsource "^1.1.1" lodash "^4.17.21" randombytes "^2.1.0" - stellar-base "^6.0.4" + stellar-base "^8.2.1" toml "^2.3.0" tslib "^1.10.0" urijs "^1.19.1" @@ -7048,7 +7128,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -tweetnacl@^1.0.0, tweetnacl@^1.0.1: +tweetnacl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.1.tgz#2594d42da73cd036bd0d2a54683dd35a6b55ca17" integrity sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A== @@ -7210,6 +7290,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urijs@^1.18.2: + version "1.19.11" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" + integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== + urijs@^1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.1.tgz#5b0ff530c0cbde8386f6342235ba5ca6e995d25a" @@ -7220,14 +7305,6 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url-parse@^1.4.3: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"