From 612f496857a1a1c733da33bc0f8a18cc91aa52df Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 29 Oct 2020 16:30:52 +0400 Subject: [PATCH 01/85] wip --- src/txs/index.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/txs/index.ts b/src/txs/index.ts index 9cedc677..2d9a00db 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -25,6 +25,19 @@ class TXs { } } + sendTransactions({ txs, params, requestId }: SendTransactionsArgs): void { + if (!txs || !txs.length) { + throw new Error('sendTransactionsWithParams: No transactions were passed'); + } + + const messagePayload = { + txs, + params, + }; + + this.#communicator.send(SDK_MESSAGES.SEND_TRANSACTIONS_V2, messagePayload, requestId); + } + public setTxServiceUrl(url: string): void { this.#txServiceUrl = url; } From 9840f975e158a6700c976bcb75724fa03cf1ce5d Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 29 Oct 2020 18:04:47 +0400 Subject: [PATCH 02/85] move sendTransaction to TXs class --- src/eth/index.ts | 6 +++--- src/sdk.test.ts | 12 ++++++------ src/sdk.ts | 17 ++--------------- src/txs/index.ts | 10 ++++++++-- src/types.ts | 1 - 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index b4034bb9..698c9edc 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -18,10 +18,10 @@ class Eth { public getBlockByNumber; public getTransactionByHash; public getTransactionReceipt; - private communicator; + #communicator: Communicator; constructor(communicator: Communicator) { - this.communicator = communicator; + this.#communicator = communicator; this.call = this.buildRequest<[TransactionConfig, string?], typeof RPC_CALLS.eth_call>({ call: RPC_CALLS.eth_call, formatters: [null, inputFormatters.defaultBlockParam], @@ -81,7 +81,7 @@ class Eth { params, }; - const message = this.communicator.send(SDK_MESSAGES.RPC_CALL, payload, args.requestId); + const message = this.#communicator.send(SDK_MESSAGES.RPC_CALL, payload, args.requestId); return message; }; diff --git a/src/sdk.test.ts b/src/sdk.test.ts index 0f55b6f0..9ee9ee7c 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -7,12 +7,12 @@ describe('Safe apps SDK', () => { describe('initSdk', () => { test('Should initialize with regExp', () => { sdkInstance = new SDK([/http:\/\/localhost:3000/]); - expect(sdkInstance.sendTransactions).not.toBeUndefined(); + expect(sdkInstance.txs.send).not.toBeUndefined(); }); test('Should initialize without regExp', () => { sdkInstance = new SDK([/http:\/\/localhost:3000/]); - expect(sdkInstance.sendTransactions).not.toBeUndefined(); + expect(sdkInstance.txs.send).not.toBeUndefined(); }); test('Should send initialization message', () => { @@ -32,7 +32,7 @@ describe('Safe apps SDK', () => { describe('sendTransactions', () => { test('Should throw an error when passing an empty array', () => { expect(() => { - sdkInstance.sendTransactions({ txs: [] }); + sdkInstance.txs.send({ txs: [] }); }).toThrow(); }); @@ -40,7 +40,7 @@ describe('Safe apps SDK', () => { const requestId = '1000'; const spy = jest.spyOn(window.parent, 'postMessage'); const txs = [{ to: 'address', value: '0', data: '0x' }]; - sdkInstance.sendTransactions({ txs, requestId }); + sdkInstance.txs.send({ txs, requestId }); expect(spy).toHaveBeenCalledWith( { messageId: SDK_MESSAGES.SEND_TRANSACTIONS_V2, data: { txs, params: undefined }, requestId }, '*', @@ -49,7 +49,7 @@ describe('Safe apps SDK', () => { test('Should return a message containing requestId', () => { const txs = [{ to: 'address', value: '0', data: '0x' }]; - sdkInstance.sendTransactions({ txs }); + sdkInstance.txs.send({ txs }); // expect(typeof request.requestId).toBe('number'); // expect(request.data).toEqual({ txs }); @@ -59,7 +59,7 @@ describe('Safe apps SDK', () => { const txs = [{ to: 'address', value: '0', data: '0x' }]; const requestId = 1234; const params = { safeTxGas: 5000 }; - sdkInstance.sendTransactions({ txs, params, requestId }); + sdkInstance.txs.send({ txs, params, requestId }); // expect(request.requestId).toBe(requestId); // expect(request.data).toEqual({ txs, params }); diff --git a/src/sdk.ts b/src/sdk.ts index c2e9d878..f6718ee1 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -1,4 +1,4 @@ -import { SendTransactionsArgs, Communicator } from './types'; +import { Communicator } from './types'; import InterfaceCommunicator, { SDK_MESSAGES } from './communication'; import { TXs } from './txs'; import { Eth } from './eth'; @@ -15,26 +15,13 @@ class SDK { this.#communicator = new InterfaceCommunicator(safeAppUrlsRegExp); this.eth = new Eth(this.#communicator); - this.txs = new TXs(); + this.txs = new TXs(this.#communicator); this.sendInitializationMessage(); } private sendInitializationMessage() { this.#communicator.send('SAFE_APP_SDK_INITIALIZED', undefined); } - - sendTransactions({ txs, params, requestId }: SendTransactionsArgs): void { - if (!txs || !txs.length) { - throw new Error('sendTransactionsWithParams: No transactions were passed'); - } - - const messagePayload = { - txs, - params, - }; - - this.#communicator.send(SDK_MESSAGES.SEND_TRANSACTIONS_V2, messagePayload, requestId); - } } export default SDK; diff --git a/src/txs/index.ts b/src/txs/index.ts index 2d9a00db..e39c4f0e 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -1,7 +1,13 @@ -import { TxServiceModel } from './../types'; +import { SDK_MESSAGES } from '../communication/messageIds'; +import { TxServiceModel, SendTransactionsArgs, Communicator } from '../types'; class TXs { #txServiceUrl: string | null = null; + #communicator: Communicator; + + constructor(communicator: Communicator) { + this.#communicator = communicator; + } async getBySafeTxHash(safeTxHash: string): Promise { if (!this.#txServiceUrl) { @@ -25,7 +31,7 @@ class TXs { } } - sendTransactions({ txs, params, requestId }: SendTransactionsArgs): void { + send({ txs, params, requestId }: SendTransactionsArgs): void { if (!txs || !txs.length) { throw new Error('sendTransactionsWithParams: No transactions were passed'); } diff --git a/src/types.ts b/src/types.ts index e3b272af..f011f77d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -50,7 +50,6 @@ export interface SendTransactionsArgs { requestId?: RequestId; } export interface SdkInstance { - sendTransactions: (args: SendTransactionsArgs) => void; txs: TXs; eth: Eth; } From a80b53a4b7ac462ab273b958047a0f49bbd8e8b2 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 2 Nov 2020 14:13:52 +0400 Subject: [PATCH 03/85] dep bump --- package.json | 2 +- yarn.lock | 62 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 11d9f38f..eadab217 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "eslint-plugin-prettier": "^3.1.4", "husky": "^4.3.0", "jest": "^26.6.1", - "lint-staged": "^10.5.0", + "lint-staged": "^10.5.1", "prettier": "^2.1.2", "rimraf": "^3.0.2", "ts-jest": "^26.4.3", diff --git a/yarn.lock b/yarn.lock index 560ef831..fa11ffe2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1470,10 +1470,10 @@ commander@^2.12.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.1.0.tgz#f8d722b78103141006b66f4c7ba1e97315ba75bc" - integrity sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA== +commander@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" + integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== compare-versions@^3.6.0: version "3.6.0" @@ -1607,6 +1607,13 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" +debug@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -2014,7 +2021,7 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^4.0.0, execa@^4.0.3: +execa@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== @@ -2029,6 +2036,21 @@ execa@^4.0.0, execa@^4.0.3: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -3387,20 +3409,20 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= -lint-staged@^10.5.0: - version "10.5.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.5.0.tgz#c923c2447a84c595874f3de696778736227e7a7a" - integrity sha512-gjC9+HGkBubOF+Yyoj9pd52Qfm/kYB+dRX1UOgWjHKvSDYl+VHkZXlBMlqSZa2cH3Kp5/uNL480sV6e2dTgXSg== +lint-staged@^10.5.1: + version "10.5.1" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.5.1.tgz#901e915c2360072dded0e7d752a0d9a49e079daa" + integrity sha512-fTkTGFtwFIJJzn/PbUO3RXyEBHIhbfYBE7+rJyLcOXabViaO/h6OslgeK6zpeUtzkDrzkgyAYDTLAwx6JzDTHw== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" - commander "^6.0.0" + commander "^6.2.0" cosmiconfig "^7.0.0" - debug "^4.1.1" + debug "^4.2.0" dedent "^0.7.0" enquirer "^2.3.6" - execa "^4.0.3" - listr2 "^2.6.0" + execa "^4.1.0" + listr2 "^3.2.2" log-symbols "^4.0.0" micromatch "^4.0.2" normalize-path "^3.0.0" @@ -3408,10 +3430,10 @@ lint-staged@^10.5.0: string-argv "0.3.1" stringify-object "^3.3.0" -listr2@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-2.6.2.tgz#4912eb01e1e2dd72ec37f3895a56bf2622d6f36a" - integrity sha512-6x6pKEMs8DSIpA/tixiYY2m/GcbgMplMVmhQAaLFxEtNSKLeWTGjtmU57xvv6QCm2XcqzyNXL/cTSVf4IChCRA== +listr2@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.2.2.tgz#d20feb75015e506992b55af40722ba1af168b8f1" + integrity sha512-AajqcZEUikF2ioph6PfH3dIuxJclhr3i3kHgTOP0xeXdWQohrvJAAmqVcV43/GI987HFY/vzT73jYXoa4esDHg== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" @@ -3419,7 +3441,7 @@ listr2@^2.6.0: indent-string "^4.0.0" log-update "^4.0.0" p-map "^4.0.0" - rxjs "^6.6.2" + rxjs "^6.6.3" through "^2.3.8" locate-path@^5.0.0: @@ -3610,7 +3632,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -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== @@ -4234,7 +4256,7 @@ run-parallel@^1.1.9: resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== -rxjs@^6.6.2: +rxjs@^6.6.3: version "6.6.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== From 379406eb8cd624d3a62803815b71a95435c1ef70 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 2 Nov 2020 16:23:01 +0400 Subject: [PATCH 04/85] promise based communicator wip --- src/communication/index.ts | 22 +++++------------ src/communication/messageIds.ts | 14 ----------- src/communication/methods.ts | 5 ++++ src/communication/utils.ts | 9 +++++++ src/sdk.ts | 4 +-- src/types.ts | 43 +++++++-------------------------- 6 files changed, 31 insertions(+), 66 deletions(-) delete mode 100644 src/communication/messageIds.ts create mode 100644 src/communication/methods.ts create mode 100644 src/communication/utils.ts diff --git a/src/communication/index.ts b/src/communication/index.ts index d195740f..c6b0cb5d 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,17 +1,10 @@ -import { - InterfaceMessageIds, - InterfaceMessageEvent, - SentSDKMessage, - SDKMessageIds, - SDKMessageToPayload, - RequestId, - InterfaceMessageToPayload, - Communicator, -} from '../types'; -import { INTERFACE_MESSAGES } from './messageIds'; +import { InterfaceMessageEvent, SentSDKMessage, RequestId, Communicator, Methods, MethodToParams } from '../types'; +import { METHODS } from './messageIds'; +import { generateRequestId } from './utils'; class InterfaceCommunicator implements Communicator { private allowedOrigins: RegExp[] = []; + private callbacks = {}; constructor(allowedOrigins: RegExp[]) { this.allowedOrigins = allowedOrigins; @@ -84,12 +77,9 @@ class InterfaceCommunicator implements Communicator { requestId?: RequestId, ): SentSDKMessage { if (!requestId) { - if (typeof window !== 'undefined') { - requestId = Math.trunc(window?.performance.now()); - } else { - requestId = Math.trunc(Date.now()); - } + requestId = generateRequestId(); } + const message = { messageId, requestId, diff --git a/src/communication/messageIds.ts b/src/communication/messageIds.ts deleted file mode 100644 index b1fec587..00000000 --- a/src/communication/messageIds.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const INTERFACE_MESSAGES = { - ENV_INFO: 'ENV_INFO', - ON_SAFE_INFO: 'ON_SAFE_INFO', - TRANSACTION_CONFIRMED: 'TRANSACTION_CONFIRMED', - TRANSACTION_REJECTED: 'TRANSACTION_REJECTED', - RPC_CALL_RESPONSE: 'RPC_CALL_RESPONSE', -} as const; - -export const SDK_MESSAGES = { - SAFE_APP_SDK_INITIALIZED: 'SAFE_APP_SDK_INITIALIZED', - SEND_TRANSACTIONS: 'SEND_TRANSACTIONS', - RPC_CALL: 'RPC_CALL', - SEND_TRANSACTIONS_V2: 'SEND_TRANSACTIONS_V2', -} as const; diff --git a/src/communication/methods.ts b/src/communication/methods.ts new file mode 100644 index 00000000..689726de --- /dev/null +++ b/src/communication/methods.ts @@ -0,0 +1,5 @@ +export const METHODS = { + getEnvInfo: 'getEnvInfo', + sendTransactions: 'sendTransactions', + rpcCall: 'rpcCall', +} as const; diff --git a/src/communication/utils.ts b/src/communication/utils.ts new file mode 100644 index 00000000..371a96d9 --- /dev/null +++ b/src/communication/utils.ts @@ -0,0 +1,9 @@ +const generateRequestId = (): number => { + if (typeof window !== 'undefined') { + return Math.trunc(window?.performance.now()); + } + + return Math.trunc(Date.now()); +}; + +export { generateRequestId }; diff --git a/src/sdk.ts b/src/sdk.ts index f6718ee1..b485ec3e 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -1,5 +1,5 @@ import { Communicator } from './types'; -import InterfaceCommunicator, { SDK_MESSAGES } from './communication'; +import InterfaceCommunicator from './communication'; import { TXs } from './txs'; import { Eth } from './eth'; @@ -20,7 +20,7 @@ class SDK { } private sendInitializationMessage() { - this.#communicator.send('SAFE_APP_SDK_INITIALIZED', undefined); + const response = await this.#communicator.send('getEnvInfo', undefined); } } diff --git a/src/types.ts b/src/types.ts index f011f77d..6211eb0c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -import { INTERFACE_MESSAGES, SDK_MESSAGES } from './communication/messageIds'; +import { METHODS } from './communication/messageIds'; import { RPC_CALLS } from './eth/constants'; import { TXs } from './txs'; import { Eth } from './eth'; @@ -69,41 +69,20 @@ export interface TxRejectionEvent { requestId: RequestId; } -export type InterfaceMessageIds = keyof typeof INTERFACE_MESSAGES; +export type Methods = keyof typeof METHODS; export interface InterfaceMessageEvent extends MessageEvent { data: { requestId: RequestId; - messageId: InterfaceMessageIds; - data: InterfaceMessageToPayload[InterfaceMessageIds]; + method: Methods; + params: MethodToParams[Methods]; }; } -export interface SDKMessageToPayload { - [SDK_MESSAGES.SAFE_APP_SDK_INITIALIZED]: undefined; - [SDK_MESSAGES.SEND_TRANSACTIONS]: Transaction[]; - [SDK_MESSAGES.RPC_CALL]: { - call: RpcCallNames; - params: unknown[]; - }; - [SDK_MESSAGES.SEND_TRANSACTIONS_V2]: { - txs: Transaction[]; - params?: SendTransactionParams; - }; -} - -export type SDKMessageIds = keyof typeof SDK_MESSAGES; - -export interface InterfaceMessageToPayload { - [INTERFACE_MESSAGES.ON_SAFE_INFO]: SafeInfo; - [INTERFACE_MESSAGES.TRANSACTION_CONFIRMED]: { - safeTxHash: string; - }; - [INTERFACE_MESSAGES.ENV_INFO]: { - txServiceUrl: string; - }; - [INTERFACE_MESSAGES.TRANSACTION_REJECTED]: Record; - [INTERFACE_MESSAGES.RPC_CALL_RESPONSE]: unknown; +export interface MethodToParams { + [METHODS.getEnvInfo]: undefined; + [METHODS.sendTransactions]: unknown; + [METHODS.rpcCall]: unknown; } export type RPCPayload = { @@ -225,9 +204,5 @@ export type RequestArgs = { }; export interface Communicator { - send( - messageId: T, - data: D, - requestId?: RequestId, - ): SentSDKMessage; + send(messageId: T, data: D, requestId?: RequestId): SentSDKMessage; } From 2b3ea14c7edd21c01f52b0c102191ebcc348d326 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 2 Nov 2020 18:11:45 +0400 Subject: [PATCH 05/85] promise based communicator wip --- src/communication/index.ts | 4 ++-- src/eth/eth.test.ts | 2 +- src/eth/index.ts | 2 +- src/index.ts | 2 +- src/sdk.test.ts | 2 +- src/txs/index.ts | 2 +- src/types.ts | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index c6b0cb5d..afb3a0f8 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,5 +1,5 @@ import { InterfaceMessageEvent, SentSDKMessage, RequestId, Communicator, Methods, MethodToParams } from '../types'; -import { METHODS } from './messageIds'; +import { METHODS } from './methods'; import { generateRequestId } from './utils'; class InterfaceCommunicator implements Communicator { @@ -95,4 +95,4 @@ class InterfaceCommunicator implements Communicator { } export default InterfaceCommunicator; -export * from './messageIds'; +export * from './methods'; diff --git a/src/eth/eth.test.ts b/src/eth/eth.test.ts index a789423a..9d498644 100644 --- a/src/eth/eth.test.ts +++ b/src/eth/eth.test.ts @@ -1,6 +1,6 @@ import { TransactionConfig, PastLogsOptions } from 'web3-core'; import SDK from '../index'; -import { SDK_MESSAGES } from '../communication/messageIds'; +import { SDK_MESSAGES } from '../communication/methods'; describe('Safe Apps SDK Read RPC Requests', () => { const sdkInstance = new SDK([/http:\/\/localhost:3000/]); diff --git a/src/eth/index.ts b/src/eth/index.ts index 698c9edc..f5403952 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -1,7 +1,7 @@ import { TransactionConfig, PastLogsOptions } from 'web3-core'; import { RPC_CALLS } from '../eth/constants'; import { RpcCallNames, RequestArgs, RPCPayload, SentSDKMessage, Communicator } from './../types'; -import { SDK_MESSAGES } from './../communication/messageIds'; +import { SDK_MESSAGES } from '../communication/methods'; const inputFormatters = { defaultBlockParam: (arg = 'latest') => arg, diff --git a/src/index.ts b/src/index.ts index a29ec3b8..07fb0fcb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,4 +3,4 @@ import SDK from './sdk'; export default SDK; export * from './types'; -export * from './communication/messageIds'; +export * from './communication/methods'; diff --git a/src/sdk.test.ts b/src/sdk.test.ts index 9ee9ee7c..ba6426a9 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -1,5 +1,5 @@ import SDK, { SdkInstance } from './index'; -import { SDK_MESSAGES } from './communication/messageIds'; +import { SDK_MESSAGES } from './communication/methods'; describe('Safe apps SDK', () => { let sdkInstance: SdkInstance; diff --git a/src/txs/index.ts b/src/txs/index.ts index e39c4f0e..79444d5f 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -1,4 +1,4 @@ -import { SDK_MESSAGES } from '../communication/messageIds'; +import { SDK_MESSAGES } from '../communication/methods'; import { TxServiceModel, SendTransactionsArgs, Communicator } from '../types'; class TXs { diff --git a/src/types.ts b/src/types.ts index 6211eb0c..ea42318c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -import { METHODS } from './communication/messageIds'; +import { METHODS } from './communication/methods'; import { RPC_CALLS } from './eth/constants'; import { TXs } from './txs'; import { Eth } from './eth'; From dc6315318747129d6cecb15447d194d95a8000b0 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 3 Nov 2020 17:05:44 +0400 Subject: [PATCH 06/85] types wip --- src/communication/index.ts | 58 ++++++-------------------------------- src/txs/index.ts | 4 +-- src/types.ts | 6 ---- 3 files changed, 11 insertions(+), 57 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index afb3a0f8..43c626d4 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,5 +1,4 @@ -import { InterfaceMessageEvent, SentSDKMessage, RequestId, Communicator, Methods, MethodToParams } from '../types'; -import { METHODS } from './methods'; +import { InterfaceMessageEvent, RequestId, Communicator, Methods, MethodToParams } from '../types'; import { generateRequestId } from './utils'; class InterfaceCommunicator implements Communicator { @@ -13,69 +12,30 @@ class InterfaceCommunicator implements Communicator { } private isValidMessage({ origin, data }: InterfaceMessageEvent): boolean { - const emptyOrMalformed = !data || !data.messageId; + const emptyOrMalformed = !data || !data.method; const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; const sameOrigin = origin === window.origin; return !emptyOrMalformed && !unknownOrigin && !sameOrigin; } - private logIncomingMessage(origin: string, payload: InterfaceMessageToPayload[InterfaceMessageIds]): void { - console.info(`SafeConnector: A message was received from origin ${origin}. `, payload); + private logIncomingMessage(msg: InterfaceMessageEvent): void { + console.info(`SafeConnector: A message was received from origin ${msg.origin}. `, msg.data); } private onParentMessage(msg: InterfaceMessageEvent): void { - this.logIncomingMessage(msg.origin, msg.data); + this.logIncomingMessage(msg); if (this.isValidMessage(msg)) { - this.handleIncomingMessage(msg.data.messageId, msg.data.data, msg.data.requestId); + this.handleIncomingMessage(msg.data.method, msg.data.params, msg.data.requestId); } } - private handleIncomingMessage( - messageId: InterfaceMessageIds, - payload: InterfaceMessageToPayload[InterfaceMessageIds], - requestId: RequestId, - ): void { - console.log(payload, requestId); - switch (messageId) { - case INTERFACE_MESSAGES.ENV_INFO: - // const typedPayload = payload as InterfaceMessageToPayload[typeof INTERFACE_MESSAGES.ENV_INFO]; - - break; - - case INTERFACE_MESSAGES.ON_SAFE_INFO: { - /* tslint:disable-next-line:no-shadowed-variable */ - // const typedPayload = payload as InterfaceMessageToPayload[typeof INTERFACE_MESSAGES.ON_SAFE_INFO]; - - break; - } - - case INTERFACE_MESSAGES.TRANSACTION_CONFIRMED: { - /* tslint:disable-next-line:no-shadowed-variable */ - // const typedPayload = payload as InterfaceMessageToPayload[typeof INTERFACE_MESSAGES.TRANSACTION_CONFIRMED]; - - break; - } - - case INTERFACE_MESSAGES.TRANSACTION_REJECTED: { - break; - } - - default: { - console.warn( - `SafeConnector: A message was received from origin ${origin} with an unknown message id: ${messageId}`, - ); - break; - } - } + private handleIncomingMessage(method: Methods, params: MethodToParams[Methods], requestId: RequestId): void { + console.log({ method, params, requestId }); } - public send( - messageId: T, - data: D, - requestId?: RequestId, - ): SentSDKMessage { + public send(messageId: T, data: D, requestId?: RequestId): unknown { if (!requestId) { requestId = generateRequestId(); } diff --git a/src/txs/index.ts b/src/txs/index.ts index 79444d5f..523baccd 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -1,4 +1,4 @@ -import { SDK_MESSAGES } from '../communication/methods'; +import { METHODS } from '../communication/methods'; import { TxServiceModel, SendTransactionsArgs, Communicator } from '../types'; class TXs { @@ -41,7 +41,7 @@ class TXs { params, }; - this.#communicator.send(SDK_MESSAGES.SEND_TRANSACTIONS_V2, messagePayload, requestId); + this.#communicator.send(METHODS.sendTransactions, messagePayload, requestId); } public setTxServiceUrl(url: string): void { diff --git a/src/types.ts b/src/types.ts index ea42318c..12dfaa47 100644 --- a/src/types.ts +++ b/src/types.ts @@ -90,12 +90,6 @@ export type RPCPayload = { params: P; }; -export type SentSDKMessage = { - messageId: T; - requestId: RequestId; - data: D; -}; - // copy-pasting all the types below from safe-react makes me think we might want to export them to a package export enum Operation { From d7ae8f6af61b41a18517c4ed16b9d931fe17c95c Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 3 Nov 2020 17:44:32 +0400 Subject: [PATCH 07/85] types wip --- src/eth/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index f5403952..9cfe3084 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -1,7 +1,7 @@ import { TransactionConfig, PastLogsOptions } from 'web3-core'; import { RPC_CALLS } from '../eth/constants'; -import { RpcCallNames, RequestArgs, RPCPayload, SentSDKMessage, Communicator } from './../types'; -import { SDK_MESSAGES } from '../communication/methods'; +import { RpcCallNames, RequestArgs, Communicator } from './../types'; +import { METHODS } from '../communication/methods'; const inputFormatters = { defaultBlockParam: (arg = 'latest') => arg, @@ -65,7 +65,7 @@ class Eth { /* eslint-disable-next-line */ formatters?: (((arg: any) => any) | null)[]; }) { - return (args: RequestArgs

): SentSDKMessage<'RPC_CALL', RPCPayload> => { + return (args: RequestArgs

): unknown => { const params = args.params; if (formatters && Array.isArray(params)) { @@ -81,7 +81,7 @@ class Eth { params, }; - const message = this.#communicator.send(SDK_MESSAGES.RPC_CALL, payload, args.requestId); + const message = this.#communicator.send(METHODS.rpcCall, payload, args.requestId); return message; }; From 613d083f839d5d2cfa3ddd8f10ffacc6ec1848d9 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 3 Nov 2020 18:54:26 +0400 Subject: [PATCH 08/85] first promisified method test - sendInitializationMessage --- src/communication/index.ts | 18 +++++++++++++++--- src/sdk.ts | 4 +++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 43c626d4..3f8ffb65 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,9 +1,13 @@ import { InterfaceMessageEvent, RequestId, Communicator, Methods, MethodToParams } from '../types'; import { generateRequestId } from './utils'; +interface CallbacksMap { + [key: string]: unknown; +} + class InterfaceCommunicator implements Communicator { private allowedOrigins: RegExp[] = []; - private callbacks = {}; + private callbacks: CallbacksMap = {}; constructor(allowedOrigins: RegExp[]) { this.allowedOrigins = allowedOrigins; @@ -35,7 +39,11 @@ class InterfaceCommunicator implements Communicator { console.log({ method, params, requestId }); } - public send(messageId: T, data: D, requestId?: RequestId): unknown { + public send( + messageId: T, + data: D, + requestId?: RequestId, + ): Promise { if (!requestId) { requestId = generateRequestId(); } @@ -50,7 +58,11 @@ class InterfaceCommunicator implements Communicator { window.parent.postMessage(message, '*'); } - return message; + return new Promise((resolve) => { + this.callbacks[requestId as string] = (response: unknown) => { + resolve(response); + }; + }); } } diff --git a/src/sdk.ts b/src/sdk.ts index b485ec3e..989a0a0c 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -19,8 +19,10 @@ class SDK { this.sendInitializationMessage(); } - private sendInitializationMessage() { + private async sendInitializationMessage() { const response = await this.#communicator.send('getEnvInfo', undefined); + + console.log({ response }); } } From 33d77f44346b18c089075afe3dac9b61ed082a90 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 5 Nov 2020 18:22:37 +0400 Subject: [PATCH 09/85] build fix --- src/communication/index.ts | 4 +- src/eth/eth.test.ts | 92 +++++++++++++++++++------------------- src/eth/index.ts | 2 +- src/sdk.test.ts | 17 +------ src/types.ts | 6 ++- 5 files changed, 56 insertions(+), 65 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 3f8ffb65..c01b5a55 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -43,7 +43,7 @@ class InterfaceCommunicator implements Communicator { messageId: T, data: D, requestId?: RequestId, - ): Promise { + ): Promise<{ requestId: string }> { if (!requestId) { requestId = generateRequestId(); } @@ -60,7 +60,7 @@ class InterfaceCommunicator implements Communicator { return new Promise((resolve) => { this.callbacks[requestId as string] = (response: unknown) => { - resolve(response); + resolve(response as { requestId: string }); }; }); } diff --git a/src/eth/eth.test.ts b/src/eth/eth.test.ts index 9d498644..a08a2cba 100644 --- a/src/eth/eth.test.ts +++ b/src/eth/eth.test.ts @@ -1,6 +1,6 @@ import { TransactionConfig, PastLogsOptions } from 'web3-core'; import SDK from '../index'; -import { SDK_MESSAGES } from '../communication/methods'; +import { METHODS } from '../communication/methods'; describe('Safe Apps SDK Read RPC Requests', () => { const sdkInstance = new SDK([/http:\/\/localhost:3000/]); @@ -17,17 +17,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('Methods requiring default block param', () => { describe('getBalance', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = sdkInstance.eth.getBalance({ + const request = await sdkInstance.eth.getBalance({ params: [addr, 'pending'], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getBalance', params: [addr, 'pending'], @@ -39,17 +39,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { expect(request.requestId).toEqual(requestId); }); - it('Should add `latest` as a default block parameter when one is not passed', () => { + it('Should add `latest` as a default block parameter when one is not passed', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = sdkInstance.eth.getBalance({ + const request = await sdkInstance.eth.getBalance({ params: [addr], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getBalance', params: [addr, 'latest'], @@ -63,17 +63,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('getCode', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = sdkInstance.eth.getCode({ + const request = await sdkInstance.eth.getCode({ params: [addr, 'pending'], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getCode', params: [addr, 'pending'], @@ -85,17 +85,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { expect(request.requestId).toEqual(requestId); }); - it('Should add `latest` as a default block parameter when one is not passed', () => { + it('Should add `latest` as a default block parameter when one is not passed', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = sdkInstance.eth.getCode({ + const request = await sdkInstance.eth.getCode({ params: [addr], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getCode', params: [addr, 'latest'], @@ -109,17 +109,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('getStorageAt', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = sdkInstance.eth.getStorageAt({ + const request = await sdkInstance.eth.getStorageAt({ params: [addr, 'earliest'], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getStorageAt', params: [addr, 'earliest'], @@ -131,17 +131,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { expect(request.requestId).toEqual(requestId); }); - it('Should add `latest` as a default block parameter when one is not passed', () => { + it('Should add `latest` as a default block parameter when one is not passed', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = sdkInstance.eth.getStorageAt({ + const request = await sdkInstance.eth.getStorageAt({ params: [addr], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getStorageAt', params: [addr, 'latest'], @@ -155,20 +155,20 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('call', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const config: TransactionConfig = { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', }; - const request = sdkInstance.eth.call({ + const request = await sdkInstance.eth.call({ params: [config, 'pending'], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_call', params: [config, 'pending'], @@ -180,20 +180,20 @@ describe('Safe Apps SDK Read RPC Requests', () => { expect(request.requestId).toEqual(requestId); }); - it('Should add `latest` as a default block parameter when one is not passed', () => { + it('Should add `latest` as a default block parameter when one is not passed', async () => { const requestId = '1000'; const config: TransactionConfig = { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', }; - const request = sdkInstance.eth.call({ + const request = await sdkInstance.eth.call({ params: [config], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_call', params: [config, 'latest'], @@ -208,7 +208,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('getPastLogs', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const number = 11054275; const params: [PastLogsOptions] = [ @@ -217,14 +217,14 @@ describe('Safe Apps SDK Read RPC Requests', () => { toBlock: 'latest', }, ]; - const request = sdkInstance.eth.getPastLogs({ + const request = await sdkInstance.eth.getPastLogs({ params, requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getLogs', params, @@ -238,17 +238,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('getBlockByHash', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; - const request = sdkInstance.eth.getBlockByHash({ + const request = await sdkInstance.eth.getBlockByHash({ params: [hash], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getBlockByHash', params: [hash, false], @@ -260,17 +260,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { expect(request.requestId).toEqual(requestId); }); - it('Should respect passed full tx object boolean param', () => { + it('Should respect passed full tx object boolean param', async () => { const requestId = '1000'; const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; - const request = sdkInstance.eth.getBlockByHash({ + const request = await sdkInstance.eth.getBlockByHash({ params: [hash, true], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getBlockByHash', params: [hash, true], @@ -284,17 +284,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('getBlockByNumber', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const number = '11054275'; - const request = sdkInstance.eth.getBlockByNumber({ + const request = await sdkInstance.eth.getBlockByNumber({ params: [number], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getBlockByNumber', params: [number, false], @@ -306,17 +306,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { expect(request.requestId).toEqual(requestId); }); - it('Should respect passed full tx object boolean param', () => { + it('Should respect passed full tx object boolean param', async () => { const requestId = '1000'; const number = '11054275'; - const request = sdkInstance.eth.getBlockByNumber({ + const request = await sdkInstance.eth.getBlockByNumber({ params: [number, true], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getBlockByNumber', params: [number, true], @@ -330,17 +330,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('getTransactionByHash', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const hash = '0x0e6cd6237b4d3e5c3f348b78399f031b527e832bd30924951ba4921cdbf440d7'; - const request = sdkInstance.eth.getTransactionByHash({ + const request = await sdkInstance.eth.getTransactionByHash({ params: [hash], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getTransactionByHash', params: [hash], @@ -354,17 +354,17 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('getTransactionReceipt', () => { - it('Should send a valid message to the interface and return a request ID', () => { + it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const hash = '0x0e6cd6237b4d3e5c3f348b78399f031b527e832bd30924951ba4921cdbf440d7'; - const request = sdkInstance.eth.getTransactionReceipt({ + const request = await sdkInstance.eth.getTransactionReceipt({ params: [hash], requestId, }); expect(spy).toHaveBeenCalledWith( { - messageId: SDK_MESSAGES.RPC_CALL, + messageId: METHODS.rpcCall, data: { call: 'eth_getTransactionReceipt', params: [hash], diff --git a/src/eth/index.ts b/src/eth/index.ts index 9cfe3084..00d5d0c4 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -65,7 +65,7 @@ class Eth { /* eslint-disable-next-line */ formatters?: (((arg: any) => any) | null)[]; }) { - return (args: RequestArgs

): unknown => { + return (args: RequestArgs

): Promise<{ requestId: string }> => { const params = args.params; if (formatters && Array.isArray(params)) { diff --git a/src/sdk.test.ts b/src/sdk.test.ts index ba6426a9..ccdec71c 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -1,5 +1,5 @@ import SDK, { SdkInstance } from './index'; -import { SDK_MESSAGES } from './communication/methods'; +import { METHODS } from './communication/methods'; describe('Safe apps SDK', () => { let sdkInstance: SdkInstance; @@ -14,19 +14,6 @@ describe('Safe apps SDK', () => { sdkInstance = new SDK([/http:\/\/localhost:3000/]); expect(sdkInstance.txs.send).not.toBeUndefined(); }); - - test('Should send initialization message', () => { - const spy = jest.spyOn(window.parent, 'postMessage'); - sdkInstance = new SDK([/http:\/\/localhost:3000/]); - expect(spy).toHaveBeenCalledWith( - expect.objectContaining({ - messageId: SDK_MESSAGES.SAFE_APP_SDK_INITIALIZED, - data: undefined, - requestId: expect.any(Number), - }), - '*', - ); - }); }); describe('sendTransactions', () => { @@ -42,7 +29,7 @@ describe('Safe apps SDK', () => { const txs = [{ to: 'address', value: '0', data: '0x' }]; sdkInstance.txs.send({ txs, requestId }); expect(spy).toHaveBeenCalledWith( - { messageId: SDK_MESSAGES.SEND_TRANSACTIONS_V2, data: { txs, params: undefined }, requestId }, + { messageId: METHODS.sendTransactions, data: { txs, params: undefined }, requestId }, '*', ); }); diff --git a/src/types.ts b/src/types.ts index 12dfaa47..3ec83cb7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -198,5 +198,9 @@ export type RequestArgs = { }; export interface Communicator { - send(messageId: T, data: D, requestId?: RequestId): SentSDKMessage; + send( + messageId: T, + data: D, + requestId?: RequestId, + ): Promise<{ requestId: string }>; } From 30b2563c4d59b919c2d80fe9f82b41e37472334e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 6 Nov 2020 12:37:57 +0400 Subject: [PATCH 10/85] update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eadab217..3a1a40f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gnosis.pm/safe-apps-sdk", - "version": "0.4.2", + "version": "1.0.0", "description": "SDK developed to integrate third-party apps with Safe-Multisig app.", "main": "dist/index.js", "typings": "dist/index.d.ts", From 901b0ee097d9173aba162ac52dd3f013ba7e8ae1 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 6 Nov 2020 15:02:23 +0400 Subject: [PATCH 11/85] use arrow functions to not deal with function binding --- src/communication/index.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index c01b5a55..579f5a1a 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -15,35 +15,35 @@ class InterfaceCommunicator implements Communicator { window.addEventListener('message', this.onParentMessage); } - private isValidMessage({ origin, data }: InterfaceMessageEvent): boolean { + private isValidMessage = ({ origin, data }: InterfaceMessageEvent): boolean => { const emptyOrMalformed = !data || !data.method; const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; const sameOrigin = origin === window.origin; return !emptyOrMalformed && !unknownOrigin && !sameOrigin; - } + }; - private logIncomingMessage(msg: InterfaceMessageEvent): void { + private logIncomingMessage = (msg: InterfaceMessageEvent): void => { console.info(`SafeConnector: A message was received from origin ${msg.origin}. `, msg.data); - } + }; - private onParentMessage(msg: InterfaceMessageEvent): void { + private onParentMessage = (msg: InterfaceMessageEvent): void => { this.logIncomingMessage(msg); if (this.isValidMessage(msg)) { this.handleIncomingMessage(msg.data.method, msg.data.params, msg.data.requestId); } - } + }; - private handleIncomingMessage(method: Methods, params: MethodToParams[Methods], requestId: RequestId): void { + private handleIncomingMessage = (method: Methods, params: MethodToParams[Methods], requestId: RequestId): void => { console.log({ method, params, requestId }); - } + }; - public send( + public send = ( messageId: T, data: D, requestId?: RequestId, - ): Promise<{ requestId: string }> { + ): Promise<{ requestId: string }> => { if (!requestId) { requestId = generateRequestId(); } @@ -63,7 +63,7 @@ class InterfaceCommunicator implements Communicator { resolve(response as { requestId: string }); }; }); - } + }; } export default InterfaceCommunicator; From 8e89ef8e0c4abf7447a85d1b53d75754d982d51d Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 6 Nov 2020 15:04:41 +0400 Subject: [PATCH 12/85] dep bump --- package.json | 6 +- yarn.lock | 763 +++++++++++++++++++++++++++------------------------ 2 files changed, 407 insertions(+), 362 deletions(-) diff --git a/package.json b/package.json index 3a1a40f6..265598a1 100644 --- a/package.json +++ b/package.json @@ -28,13 +28,13 @@ "devDependencies": { "@types/jest": "^26.0.15", "@types/node": "^14.14.6", - "@typescript-eslint/eslint-plugin": "^4.6.0", - "@typescript-eslint/parser": "^4.6.0", + "@typescript-eslint/eslint-plugin": "^4.6.1", + "@typescript-eslint/parser": "^4.6.1", "eslint": "^7.12.1", "eslint-config-prettier": "^6.15.0", "eslint-plugin-prettier": "^3.1.4", "husky": "^4.3.0", - "jest": "^26.6.1", + "jest": "^26.6.3", "lint-staged": "^10.5.1", "prettier": "^2.1.2", "rimraf": "^3.0.2", diff --git a/yarn.lock b/yarn.lock index fa11ffe2..dab129a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -257,6 +257,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/template@^7.3.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -440,46 +447,46 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jest/console@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.1.tgz#6a19eaac4aa8687b4db9130495817c65aec3d34e" - integrity sha512-cjqcXepwC5M+VeIhwT6Xpi/tT4AiNzlIx8SMJ9IihduHnsSrnWNvTBfKIpmqOOCNOPqtbBx6w2JqfoLOJguo8g== +"@jest/console@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" + integrity sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^26.6.1" - jest-util "^26.6.1" + jest-message-util "^26.6.2" + jest-util "^26.6.2" slash "^3.0.0" -"@jest/core@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.1.tgz#77426822f667a2cda82bf917cee11cc8ba71f9ac" - integrity sha512-p4F0pgK3rKnoS9olXXXOkbus1Bsu6fd8pcvLMPsUy4CVXZ8WSeiwQ1lK5hwkCIqJ+amZOYPd778sbPha/S8Srw== +"@jest/core@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" + integrity sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw== dependencies: - "@jest/console" "^26.6.1" - "@jest/reporters" "^26.6.1" - "@jest/test-result" "^26.6.1" - "@jest/transform" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/console" "^26.6.2" + "@jest/reporters" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" - jest-changed-files "^26.6.1" - jest-config "^26.6.1" - jest-haste-map "^26.6.1" - jest-message-util "^26.6.1" + jest-changed-files "^26.6.2" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" jest-regex-util "^26.0.0" - jest-resolve "^26.6.1" - jest-resolve-dependencies "^26.6.1" - jest-runner "^26.6.1" - jest-runtime "^26.6.1" - jest-snapshot "^26.6.1" - jest-util "^26.6.1" - jest-validate "^26.6.1" - jest-watcher "^26.6.1" + jest-resolve "^26.6.2" + jest-resolve-dependencies "^26.6.3" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + jest-watcher "^26.6.2" micromatch "^4.0.2" p-each-series "^2.1.0" rimraf "^3.0.0" @@ -491,47 +498,47 @@ resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-26.5.0.tgz#1d07947adc51ea17766d9f0ccf5a8d6ea94c47dc" integrity sha512-DJ+pEBUIqarrbv1W/C39f9YH0rJ4wsXZ/VC6JafJPlHW2HOucKceeaqTOQj9MEDQZjySxMLkOq5mfXZXNZcmWw== -"@jest/environment@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.1.tgz#38a56f1cc66f96bf53befcc5ebeaf1c2dce90e9a" - integrity sha512-GNvHwkOFJtNgSwdzH9flUPzF9AYAZhUg124CBoQcwcZCM9s5TLz8Y3fMtiaWt4ffbigoetjGk5PU2Dd8nLrSEw== +"@jest/environment@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" + integrity sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA== dependencies: - "@jest/fake-timers" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" "@types/node" "*" - jest-mock "^26.6.1" + jest-mock "^26.6.2" -"@jest/fake-timers@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.1.tgz#5aafba1822075b7142e702b906094bea15f51acf" - integrity sha512-T/SkMLgOquenw/nIisBRD6XAYpFir0kNuclYLkse5BpzeDUukyBr+K31xgAo9M0hgjU9ORlekAYPSzc0DKfmKg== +"@jest/fake-timers@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" + integrity sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" "@sinonjs/fake-timers" "^6.0.1" "@types/node" "*" - jest-message-util "^26.6.1" - jest-mock "^26.6.1" - jest-util "^26.6.1" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-util "^26.6.2" -"@jest/globals@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.1.tgz#b232c7611d8a2de62b4bf9eb9a007138322916f4" - integrity sha512-acxXsSguuLV/CeMYmBseefw6apO7NuXqpE+v5r3yD9ye2PY7h1nS20vY7Obk2w6S7eJO4OIAJeDnoGcLC/McEQ== +"@jest/globals@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" + integrity sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA== dependencies: - "@jest/environment" "^26.6.1" - "@jest/types" "^26.6.1" - expect "^26.6.1" + "@jest/environment" "^26.6.2" + "@jest/types" "^26.6.2" + expect "^26.6.2" -"@jest/reporters@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.1.tgz#582ede05278cf5eeffe58bc519f4a35f54fbcb0d" - integrity sha512-J6OlXVFY3q1SXWJhjme5i7qT/BAZSikdOK2t8Ht5OS32BDo6KfG5CzIzzIFnAVd82/WWbc9Hb7SJ/jwSvVH9YA== +"@jest/reporters@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" + integrity sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^26.6.1" - "@jest/test-result" "^26.6.1" - "@jest/transform" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/console" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" chalk "^4.0.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" @@ -542,63 +549,63 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.0.2" - jest-haste-map "^26.6.1" - jest-resolve "^26.6.1" - jest-util "^26.6.1" - jest-worker "^26.6.1" + jest-haste-map "^26.6.2" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" slash "^3.0.0" source-map "^0.6.0" string-length "^4.0.1" terminal-link "^2.0.0" - v8-to-istanbul "^6.0.1" + v8-to-istanbul "^7.0.0" optionalDependencies: node-notifier "^8.0.0" -"@jest/source-map@^26.5.0": - version "26.5.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.5.0.tgz#98792457c85bdd902365cd2847b58fff05d96367" - integrity sha512-jWAw9ZwYHJMe9eZq/WrsHlwF8E3hM9gynlcDpOyCb9bR8wEd9ZNBZCi7/jZyzHxC7t3thZ10gO2IDhu0bPKS5g== +"@jest/source-map@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" + integrity sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA== dependencies: callsites "^3.0.0" graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.1.tgz#d75698d8a06aa663e8936663778c831512330cc1" - integrity sha512-wqAgIerIN2gSdT2A8WeA5+AFh9XQBqYGf8etK143yng3qYd0mF0ie2W5PVmgnjw4VDU6ammI9NdXrKgNhreawg== +"@jest/test-result@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" + integrity sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ== dependencies: - "@jest/console" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/console" "^26.6.2" + "@jest/types" "^26.6.2" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.1.tgz#34216ac2c194b0eeebde30d25424d1134703fd2e" - integrity sha512-0csqA/XApZiNeTIPYh6koIDCACSoR6hi29T61tKJMtCZdEC+tF3PoNt7MS0oK/zKC6daBgCbqXxia5ztr/NyCQ== +"@jest/test-sequencer@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" + integrity sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw== dependencies: - "@jest/test-result" "^26.6.1" + "@jest/test-result" "^26.6.2" graceful-fs "^4.2.4" - jest-haste-map "^26.6.1" - jest-runner "^26.6.1" - jest-runtime "^26.6.1" + jest-haste-map "^26.6.2" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" -"@jest/transform@^26.6.1": - version "26.6.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.1.tgz#f70786f96e0f765947b4fb4f54ffcfb7bd783711" - integrity sha512-oNFAqVtqRxZRx6vXL3I4bPKUK0BIlEeaalkwxyQGGI8oXDQBtYQBpiMe5F7qPs4QdvvFYB42gPGIMMcxXaBBxQ== +"@jest/transform@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" babel-plugin-istanbul "^6.0.0" chalk "^4.0.0" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.2.4" - jest-haste-map "^26.6.1" + jest-haste-map "^26.6.2" jest-regex-util "^26.0.0" - jest-util "^26.6.1" + jest-util "^26.6.2" micromatch "^4.0.2" pirates "^4.0.1" slash "^3.0.0" @@ -637,6 +644,17 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@nodelib/fs.scandir@2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" @@ -837,61 +855,61 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.0.tgz#210cd538bb703f883aff81d3996961f5dba31fdb" - integrity sha512-1+419X+Ynijytr1iWI+/IcX/kJryc78YNpdaXR1aRO1sU3bC0vZrIAF1tIX7rudVI84W7o7M4zo5p1aVt70fAg== +"@typescript-eslint/eslint-plugin@^4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.1.tgz#99d77eb7a016fd5a5e749d2c44a7e4c317eb7da3" + integrity sha512-SNZyflefTMK2JyrPfFFzzoy2asLmZvZJ6+/L5cIqg4HfKGiW2Gr1Go1OyEVqne/U4QwmoasuMwppoBHWBWF2nA== dependencies: - "@typescript-eslint/experimental-utils" "4.6.0" - "@typescript-eslint/scope-manager" "4.6.0" + "@typescript-eslint/experimental-utils" "4.6.1" + "@typescript-eslint/scope-manager" "4.6.1" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.0.tgz#f750aef4dd8e5970b5c36084f0a5ca2f0db309a4" - integrity sha512-pnh6Beh2/4xjJVNL+keP49DFHk3orDHHFylSp3WEjtgW3y1U+6l+jNnJrGlbs6qhAz5z96aFmmbUyKhunXKvKw== +"@typescript-eslint/experimental-utils@4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.1.tgz#a9c691dfd530a9570274fe68907c24c07a06c4aa" + integrity sha512-qyPqCFWlHZXkEBoV56UxHSoXW2qnTr4JrWVXOh3soBP3q0o7p4pUEMfInDwIa0dB/ypdtm7gLOS0hg0a73ijfg== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.6.0" - "@typescript-eslint/types" "4.6.0" - "@typescript-eslint/typescript-estree" "4.6.0" + "@typescript-eslint/scope-manager" "4.6.1" + "@typescript-eslint/types" "4.6.1" + "@typescript-eslint/typescript-estree" "4.6.1" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.0.tgz#7e9ff7df2f21d5c8f65f17add3b99eeeec33199d" - integrity sha512-Dj6NJxBhbdbPSZ5DYsQqpR32MwujF772F2H3VojWU6iT4AqL4BKuoNWOPFCoSZvCcADDvQjDpa6OLDAaiZPz2Q== +"@typescript-eslint/parser@^4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.1.tgz#b801bff67b536ecc4a840ac9289ba2be57e02428" + integrity sha512-lScKRPt1wM9UwyKkGKyQDqf0bh6jm8DQ5iN37urRIXDm16GEv+HGEmum2Fc423xlk5NUOkOpfTnKZc/tqKZkDQ== dependencies: - "@typescript-eslint/scope-manager" "4.6.0" - "@typescript-eslint/types" "4.6.0" - "@typescript-eslint/typescript-estree" "4.6.0" + "@typescript-eslint/scope-manager" "4.6.1" + "@typescript-eslint/types" "4.6.1" + "@typescript-eslint/typescript-estree" "4.6.1" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.0.tgz#b7d8b57fe354047a72dfb31881d9643092838662" - integrity sha512-uZx5KvStXP/lwrMrfQQwDNvh2ppiXzz5TmyTVHb+5TfZ3sUP7U1onlz3pjoWrK9konRyFe1czyxObWTly27Ang== +"@typescript-eslint/scope-manager@4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.1.tgz#21872b91cbf7adfc7083f17b8041149148baf992" + integrity sha512-f95+80r6VdINYscJY1KDUEDcxZ3prAWHulL4qRDfNVD0I5QAVSGqFkwHERDoLYJJWmEAkUMdQVvx7/c2Hp+Bjg== dependencies: - "@typescript-eslint/types" "4.6.0" - "@typescript-eslint/visitor-keys" "4.6.0" + "@typescript-eslint/types" "4.6.1" + "@typescript-eslint/visitor-keys" "4.6.1" -"@typescript-eslint/types@4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.0.tgz#157ca925637fd53c193c6bf226a6c02b752dde2f" - integrity sha512-5FAgjqH68SfFG4UTtIFv+rqYJg0nLjfkjD0iv+5O27a0xEeNZ5rZNDvFGZDizlCD1Ifj7MAbSW2DPMrf0E9zjA== +"@typescript-eslint/types@4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.1.tgz#d3ad7478f53f22e7339dc006ab61aac131231552" + integrity sha512-k2ZCHhJ96YZyPIsykickez+OMHkz06xppVLfJ+DY90i532/Cx2Z+HiRMH8YZQo7a4zVd/TwNBuRCdXlGK4yo8w== -"@typescript-eslint/typescript-estree@4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.0.tgz#85bd98dcc8280511cfc5b2ce7b03a9ffa1732b08" - integrity sha512-s4Z9qubMrAo/tw0CbN0IN4AtfwuehGXVZM0CHNMdfYMGBDhPdwTEpBrecwhP7dRJu6d9tT9ECYNaWDHvlFSngA== +"@typescript-eslint/typescript-estree@4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.1.tgz#6025cce724329413f57e4959b2d676fceeca246f" + integrity sha512-/J/kxiyjQQKqEr5kuKLNQ1Finpfb8gf/NpbwqFFYEBjxOsZ621r9AqwS9UDRA1Rrr/eneX/YsbPAIhU2rFLjXQ== dependencies: - "@typescript-eslint/types" "4.6.0" - "@typescript-eslint/visitor-keys" "4.6.0" + "@typescript-eslint/types" "4.6.1" + "@typescript-eslint/visitor-keys" "4.6.1" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" @@ -899,12 +917,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.0.tgz#fb05d6393891b0a089b243fc8f9fb8039383d5da" - integrity sha512-38Aa9Ztl0XyFPVzmutHXqDMCu15Xx8yKvUo38Gu3GhsuckCh3StPI5t2WIO9LHEsOH7MLmlGfKUisU8eW1Sjhg== +"@typescript-eslint/visitor-keys@4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.1.tgz#6b125883402d8939df7b54528d879e88f7ba3614" + integrity sha512-owABze4toX7QXwOLT3/D5a8NecZEjEWU1srqxENTfqsY3bwVnl3YYbOh6s1rp2wQKO9RTHFGjKes08FgE7SVMw== dependencies: - "@typescript-eslint/types" "4.6.0" + "@typescript-eslint/types" "4.6.1" eslint-visitor-keys "^2.0.0" abab@^2.0.3: @@ -1110,16 +1128,16 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== -babel-jest@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.1.tgz#07bd7bec14de47fe0f2c9a139741329f1f41788b" - integrity sha512-duMWEOKrSBYRVTTNpL2SipNIWnZOjP77auOBMPQ3zXAdnDbyZQWU8r/RxNWpUf9N6cgPFecQYelYLytTVXVDtA== +babel-jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" + integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== dependencies: - "@jest/transform" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" "@types/babel__core" "^7.1.7" babel-plugin-istanbul "^6.0.0" - babel-preset-jest "^26.5.0" + babel-preset-jest "^26.6.2" chalk "^4.0.0" graceful-fs "^4.2.4" slash "^3.0.0" @@ -1135,20 +1153,20 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^26.5.0: - version "26.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.5.0.tgz#3916b3a28129c29528de91e5784a44680db46385" - integrity sha512-ck17uZFD3CDfuwCLATWZxkkuGGFhMij8quP8CNhwj8ek1mqFgbFzRJ30xwC04LLscj/aKsVFfRST+b5PT7rSuw== +babel-plugin-jest-hoist@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" + integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" -babel-preset-current-node-syntax@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz#b4b547acddbf963cba555ba9f9cbbb70bfd044da" - integrity sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ== +babel-preset-current-node-syntax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.0.tgz#cf5feef29551253471cfa82fc8e0f5063df07a77" + integrity sha512-mGkvkpocWJes1CmMKtgGUwCeeq0pOhALyymozzDWYomHTbDLwueDYG6p4TK1YOeYHCzBzYPsWkgTto10JubI1Q== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" @@ -1161,14 +1179,15 @@ babel-preset-current-node-syntax@^0.1.3: "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^26.5.0: - version "26.5.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.5.0.tgz#f1b166045cd21437d1188d29f7fba470d5bdb0e7" - integrity sha512-F2vTluljhqkiGSJGBg/jOruA8vIIIL11YrxRcO7nviNTMbbofPSHwnm8mgP7d/wS7wRSexRoI6X1A6T74d4LQA== +babel-preset-jest@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" + integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== dependencies: - babel-plugin-jest-hoist "^26.5.0" - babel-preset-current-node-syntax "^0.1.3" + babel-plugin-jest-hoist "^26.6.2" + babel-preset-current-node-syntax "^1.0.0" balanced-match@^1.0.0: version "1.0.0" @@ -1372,10 +1391,10 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -cjs-module-lexer@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.4.3.tgz#9e31f7fe701f5fcee5793f77ab4e58fa8dcde8bc" - integrity sha512-5RLK0Qfs0PNDpEyBXIr3bIT1Muw3ojSlvpw6dAmkUcO0+uTrsBn7GuEIgx40u+OzbCBLDta7nvmud85P4EmTsQ== +cjs-module-lexer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" + integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== class-utils@^0.3.5: version "0.3.6" @@ -1693,6 +1712,11 @@ diff-sequences@^26.5.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.5.0.tgz#ef766cf09d43ed40406611f11c6d8d9dd8b2fefd" integrity sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q== +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -2069,16 +2093,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.1.tgz#e1e053cdc43b21a452b36fc7cc9401e4603949c1" - integrity sha512-BRfxIBHagghMmr1D2MRY0Qv5d3Nc8HCqgbDwNXw/9izmM5eBb42a2YjLKSbsqle76ozGkAEPELQX4IdNHAKRNA== +expect@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" ansi-styles "^4.0.0" jest-get-type "^26.3.0" - jest-matcher-utils "^26.6.1" - jest-message-util "^26.6.1" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" jest-regex-util "^26.0.0" ext@^1.1.2: @@ -2848,57 +2872,57 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.1.tgz#2fac3dc51297977ee883347948d8e3d37c417fba" - integrity sha512-NhSdZ5F6b/rIN5V46x1l31vrmukD/bJUXgYAY8VtP1SknYdJwjYDRxuLt7Z8QryIdqCjMIn2C0Cd98EZ4umo8Q== +jest-changed-files@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" + integrity sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" execa "^4.0.0" throat "^5.0.0" -jest-cli@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.1.tgz#8952242fa812c05bd129abf7c022424045b7fd67" - integrity sha512-aPLoEjlwFrCWhiPpW5NUxQA1X1kWsAnQcQ0SO/fHsCvczL3W75iVAcH9kP6NN+BNqZcHNEvkhxT5cDmBfEAh+w== +jest-cli@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" + integrity sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg== dependencies: - "@jest/core" "^26.6.1" - "@jest/test-result" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/core" "^26.6.3" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" is-ci "^2.0.0" - jest-config "^26.6.1" - jest-util "^26.6.1" - jest-validate "^26.6.1" + jest-config "^26.6.3" + jest-util "^26.6.2" + jest-validate "^26.6.2" prompts "^2.0.1" yargs "^15.4.1" -jest-config@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.1.tgz#8c343fbdd9c24ad003e261f73583c3c020f32b42" - integrity sha512-mtJzIynIwW1d1nMlKCNCQiSgWaqFn8cH/fOSNY97xG7Y9tBCZbCSuW2GTX0RPmceSJGO7l27JgwC18LEg0Vg+g== +jest-config@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" + integrity sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^26.6.1" - "@jest/types" "^26.6.1" - babel-jest "^26.6.1" + "@jest/test-sequencer" "^26.6.3" + "@jest/types" "^26.6.2" + babel-jest "^26.6.3" chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" - jest-environment-jsdom "^26.6.1" - jest-environment-node "^26.6.1" + jest-environment-jsdom "^26.6.2" + jest-environment-node "^26.6.2" jest-get-type "^26.3.0" - jest-jasmine2 "^26.6.1" + jest-jasmine2 "^26.6.3" jest-regex-util "^26.0.0" - jest-resolve "^26.6.1" - jest-util "^26.6.1" - jest-validate "^26.6.1" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" micromatch "^4.0.2" - pretty-format "^26.6.1" + pretty-format "^26.6.2" jest-diff@^25.2.1: version "25.3.0" @@ -2910,7 +2934,7 @@ jest-diff@^25.2.1: jest-get-type "^25.2.6" pretty-format "^25.3.0" -jest-diff@^26.0.0, jest-diff@^26.6.1: +jest-diff@^26.0.0: version "26.6.1" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.1.tgz#38aa194979f454619bb39bdee299fb64ede5300c" integrity sha512-BBNy/zin2m4kG5In126O8chOBxLLS/XMTuuM2+YhgyHk87ewPzKTuTJcqj3lOWOi03NNgrl+DkMeV/exdvG9gg== @@ -2920,6 +2944,16 @@ jest-diff@^26.0.0, jest-diff@^26.6.1: jest-get-type "^26.3.0" pretty-format "^26.6.1" +jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + jest-docblock@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" @@ -2927,41 +2961,41 @@ jest-docblock@^26.0.0: dependencies: detect-newline "^3.0.0" -jest-each@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.1.tgz#e968e88309a3e2ae9648634af8f89d8ee5acfddd" - integrity sha512-gSn8eB3buchuq45SU7pLB7qmCGax1ZSxfaWuEFblCyNMtyokYaKFh9dRhYPujK6xYL57dLIPhLKatjmB5XWzGA== +jest-each@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" + integrity sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" chalk "^4.0.0" jest-get-type "^26.3.0" - jest-util "^26.6.1" - pretty-format "^26.6.1" + jest-util "^26.6.2" + pretty-format "^26.6.2" -jest-environment-jsdom@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.1.tgz#63093bf89daee6139616568a43633b84cf7aac21" - integrity sha512-A17RiXuHYNVlkM+3QNcQ6n5EZyAc6eld8ra9TW26luounGWpku4tj03uqRgHJCI1d4uHr5rJiuCH5JFRtdmrcA== +jest-environment-jsdom@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" + integrity sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q== dependencies: - "@jest/environment" "^26.6.1" - "@jest/fake-timers" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" "@types/node" "*" - jest-mock "^26.6.1" - jest-util "^26.6.1" + jest-mock "^26.6.2" + jest-util "^26.6.2" jsdom "^16.4.0" -jest-environment-node@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.1.tgz#4d73d8b33c26989a92a0ed3ad0bfd6f7a196d9bd" - integrity sha512-YffaCp6h0j1kbcf1NVZ7umC6CPgD67YS+G1BeornfuSkx5s3xdhuwG0DCxSiHPXyT81FfJzA1L7nXvhq50OWIg== +jest-environment-node@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" + integrity sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag== dependencies: - "@jest/environment" "^26.6.1" - "@jest/fake-timers" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" "@types/node" "*" - jest-mock "^26.6.1" - jest-util "^26.6.1" + jest-mock "^26.6.2" + jest-util "^26.6.2" jest-get-type@^25.2.6: version "25.2.6" @@ -2973,89 +3007,90 @@ jest-get-type@^26.3.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== -jest-haste-map@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.1.tgz#97e96f5fd7576d980307fbe6160b10c016b543d4" - integrity sha512-9kPafkv0nX6ta1PrshnkiyhhoQoFWncrU/uUBt3/AP1r78WSCU5iLceYRTwDvJl67H3RrXqSlSVDDa/AsUB7OQ== +jest-haste-map@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" "@types/graceful-fs" "^4.1.2" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.4" jest-regex-util "^26.0.0" - jest-serializer "^26.5.0" - jest-util "^26.6.1" - jest-worker "^26.6.1" + jest-serializer "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" micromatch "^4.0.2" sane "^4.0.3" walker "^1.0.7" optionalDependencies: fsevents "^2.1.2" -jest-jasmine2@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.1.tgz#11c92603d1fa97e3c33404359e69d6cec7e57017" - integrity sha512-2uYdT32o/ZzSxYAPduAgokO8OlAL1YdG/9oxcEY138EDNpIK5XRRJDaGzTZdIBWSxk0aR8XxN44FvfXtHB+Fiw== +jest-jasmine2@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" + integrity sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^26.6.1" - "@jest/source-map" "^26.5.0" - "@jest/test-result" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/environment" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^26.6.1" + expect "^26.6.2" is-generator-fn "^2.0.0" - jest-each "^26.6.1" - jest-matcher-utils "^26.6.1" - jest-message-util "^26.6.1" - jest-runtime "^26.6.1" - jest-snapshot "^26.6.1" - jest-util "^26.6.1" - pretty-format "^26.6.1" + jest-each "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + pretty-format "^26.6.2" throat "^5.0.0" -jest-leak-detector@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.1.tgz#f63e46dc4e3aa30d29b40ae49966a15730d25bbe" - integrity sha512-j9ZOtJSJKlHjrs4aIxWjiQUjyrffPdiAQn2Iw0916w7qZE5Lk0T2KhIH6E9vfhzP6sw0Q0jtnLLb4vQ71o1HlA== +jest-leak-detector@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" + integrity sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg== dependencies: jest-get-type "^26.3.0" - pretty-format "^26.6.1" + pretty-format "^26.6.2" -jest-matcher-utils@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.1.tgz#bc90822d352c91c2ec1814731327691d06598400" - integrity sha512-9iu3zrsYlUnl8pByhREF9rr5eYoiEb1F7ymNKg6lJr/0qD37LWS5FSW/JcoDl8UdMX2+zAzabDs7sTO+QFKjCg== +jest-matcher-utils@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== dependencies: chalk "^4.0.0" - jest-diff "^26.6.1" + jest-diff "^26.6.2" jest-get-type "^26.3.0" - pretty-format "^26.6.1" + pretty-format "^26.6.2" -jest-message-util@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.1.tgz#d62c20c0fe7be10bfd6020b675abb9b5fa933ff3" - integrity sha512-cqM4HnqncIebBNdTKrBoWR/4ufHTll0pK/FWwX0YasK+TlBQEMqw3IEdynuuOTjDPFO3ONlFn37280X48beByw== +jest-message-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.4" micromatch "^4.0.2" + pretty-format "^26.6.2" slash "^3.0.0" stack-utils "^2.0.2" -jest-mock@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.1.tgz#6c12a92a82fc833f81a5b6de6b67d78386e276a3" - integrity sha512-my0lPTBu1awY8iVG62sB2sx9qf8zxNDVX+5aFgoB8Vbqjb6LqIOsfyFA8P1z6H2IsqMbvOX9oCJnK67Y3yUIMA== +jest-mock@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" + integrity sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" "@types/node" "*" jest-pnp-resolver@^1.2.2: @@ -3068,116 +3103,116 @@ jest-regex-util@^26.0.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== -jest-resolve-dependencies@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.1.tgz#e9d091a159ad198c029279737a8b4c507791d75c" - integrity sha512-MN6lufbZJ3RBfTnJesZtHu3hUCBqPdHRe2+FhIt0yiqJ3fMgzWRqMRQyN/d/QwOE7KXwAG2ekZutbPhuD7s51A== +jest-resolve-dependencies@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" + integrity sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" jest-regex-util "^26.0.0" - jest-snapshot "^26.6.1" + jest-snapshot "^26.6.2" -jest-resolve@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.1.tgz#e9a9130cc069620d5aeeb87043dd9e130b68c6a1" - integrity sha512-hiHfQH6rrcpAmw9xCQ0vD66SDuU+7ZulOuKwc4jpbmFFsz0bQG/Ib92K+9/489u5rVw0btr/ZhiHqBpmkbCvuQ== +jest-resolve@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" + integrity sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" chalk "^4.0.0" graceful-fs "^4.2.4" jest-pnp-resolver "^1.2.2" - jest-util "^26.6.1" + jest-util "^26.6.2" read-pkg-up "^7.0.1" resolve "^1.18.1" slash "^3.0.0" -jest-runner@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.1.tgz#a945971b5a23740c1fe20e372a38de668b7c76bf" - integrity sha512-DmpNGdgsbl5s0FGkmsInmqnmqCtliCSnjWA2TFAJS1m1mL5atwfPsf+uoZ8uYQ2X0uDj4NM+nPcDnUpbNTRMBA== +jest-runner@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" + integrity sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ== dependencies: - "@jest/console" "^26.6.1" - "@jest/environment" "^26.6.1" - "@jest/test-result" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" "@types/node" "*" chalk "^4.0.0" emittery "^0.7.1" exit "^0.1.2" graceful-fs "^4.2.4" - jest-config "^26.6.1" + jest-config "^26.6.3" jest-docblock "^26.0.0" - jest-haste-map "^26.6.1" - jest-leak-detector "^26.6.1" - jest-message-util "^26.6.1" - jest-resolve "^26.6.1" - jest-runtime "^26.6.1" - jest-util "^26.6.1" - jest-worker "^26.6.1" + jest-haste-map "^26.6.2" + jest-leak-detector "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + jest-runtime "^26.6.3" + jest-util "^26.6.2" + jest-worker "^26.6.2" source-map-support "^0.5.6" throat "^5.0.0" -jest-runtime@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.1.tgz#9a131e7b4f0bc6beefd62e7443f757c1d5fa9dec" - integrity sha512-7uOCNeezXDWgjEyzYbRN2ViY7xNZzusNVGAMmU0UHRUNXuY4j4GBHKGMqPo/cBPZA9bSYp+lwK2DRRBU5Dv6YQ== - dependencies: - "@jest/console" "^26.6.1" - "@jest/environment" "^26.6.1" - "@jest/fake-timers" "^26.6.1" - "@jest/globals" "^26.6.1" - "@jest/source-map" "^26.5.0" - "@jest/test-result" "^26.6.1" - "@jest/transform" "^26.6.1" - "@jest/types" "^26.6.1" +jest-runtime@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" + integrity sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/globals" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" "@types/yargs" "^15.0.0" chalk "^4.0.0" - cjs-module-lexer "^0.4.2" + cjs-module-lexer "^0.6.0" collect-v8-coverage "^1.0.0" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.2.4" - jest-config "^26.6.1" - jest-haste-map "^26.6.1" - jest-message-util "^26.6.1" - jest-mock "^26.6.1" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" jest-regex-util "^26.0.0" - jest-resolve "^26.6.1" - jest-snapshot "^26.6.1" - jest-util "^26.6.1" - jest-validate "^26.6.1" + jest-resolve "^26.6.2" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" slash "^3.0.0" strip-bom "^4.0.0" yargs "^15.4.1" -jest-serializer@^26.5.0: - version "26.5.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.5.0.tgz#f5425cc4c5f6b4b355f854b5f0f23ec6b962bc13" - integrity sha512-+h3Gf5CDRlSLdgTv7y0vPIAoLgX/SI7T4v6hy+TEXMgYbv+ztzbg5PSN6mUXAT/hXYHvZRWm+MaObVfqkhCGxA== +jest-serializer@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== dependencies: "@types/node" "*" graceful-fs "^4.2.4" -jest-snapshot@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.1.tgz#469e9d0b749496aea7dad0d7e5e5c88b91cdb4cc" - integrity sha512-JA7bZp7HRTIJYAi85pJ/OZ2eur2dqmwIToA5/6d7Mn90isGEfeF9FvuhDLLEczgKP1ihreBzrJ6Vr7zteP5JNA== +jest-snapshot@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" + integrity sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" "@types/babel__traverse" "^7.0.4" "@types/prettier" "^2.0.0" chalk "^4.0.0" - expect "^26.6.1" + expect "^26.6.2" graceful-fs "^4.2.4" - jest-diff "^26.6.1" + jest-diff "^26.6.2" jest-get-type "^26.3.0" - jest-haste-map "^26.6.1" - jest-matcher-utils "^26.6.1" - jest-message-util "^26.6.1" - jest-resolve "^26.6.1" + jest-haste-map "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" natural-compare "^1.4.0" - pretty-format "^26.6.1" + pretty-format "^26.6.2" semver "^7.3.2" jest-util@^26.1.0: @@ -3192,60 +3227,60 @@ jest-util@^26.1.0: is-ci "^2.0.0" micromatch "^4.0.2" -jest-util@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.1.tgz#4cc0d09ec57f28d12d053887eec5dc976a352e9b" - integrity sha512-xCLZUqVoqhquyPLuDXmH7ogceGctbW8SMyQVjD9o+1+NPWI7t0vO08udcFLVPLgKWcvc+zotaUv/RuaR6l8HIA== +jest-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" "@types/node" "*" chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^2.0.0" micromatch "^4.0.2" -jest-validate@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.1.tgz#28730eb8570d60968d9d06f1a8c94d922167bd2a" - integrity sha512-BEFpGbylKocnNPZULcnk+TGaz1oFZQH/wcaXlaXABbu0zBwkOGczuWgdLucUouuQqn7VadHZZeTvo8VSFDLMOA== +jest-validate@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" + integrity sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ== dependencies: - "@jest/types" "^26.6.1" + "@jest/types" "^26.6.2" camelcase "^6.0.0" chalk "^4.0.0" jest-get-type "^26.3.0" leven "^3.1.0" - pretty-format "^26.6.1" + pretty-format "^26.6.2" -jest-watcher@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.1.tgz#debfa34e9c5c3e735593403794fe53d2955bfabc" - integrity sha512-0LBIPPncNi9CaLKK15bnxyd2E8OMl4kJg0PTiNOI+MXztXw1zVdtX/x9Pr6pXaQYps+eS/ts43O4+HByZ7yJSw== +jest-watcher@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" + integrity sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ== dependencies: - "@jest/test-result" "^26.6.1" - "@jest/types" "^26.6.1" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" - jest-util "^26.6.1" + jest-util "^26.6.2" string-length "^4.0.1" -jest-worker@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.1.tgz#c2ae8cde6802cc14056043f997469ec170d9c32a" - integrity sha512-R5IE3qSGz+QynJx8y+ICEkdI2OJ3RJjRQVEyCcFAd3yVhQSEtquziPO29Mlzgn07LOVE8u8jhJ1FqcwegiXWOw== +jest-worker@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== dependencies: "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" -jest@^26.6.1: - version "26.6.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.1.tgz#821e8280d2bdeeed40ac7bc43941dceff0f1b650" - integrity sha512-f+ahfqw3Ffy+9vA7sWFGpTmhtKEMsNAZiWBVXDkrpIO73zIz22iimjirnV78kh/eWlylmvLh/0WxHN6fZraZdA== +jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" + integrity sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q== dependencies: - "@jest/core" "^26.6.1" + "@jest/core" "^26.6.3" import-local "^3.0.2" - jest-cli "^26.6.1" + jest-cli "^26.6.3" js-sha3@0.5.7: version "0.5.7" @@ -4004,6 +4039,16 @@ pretty-format@^26.0.0, pretty-format@^26.6.1: ansi-styles "^4.0.0" react-is "^17.0.1" +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" @@ -5016,10 +5061,10 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== -v8-to-istanbul@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-6.0.1.tgz#7ef0e32faa10f841fe4c1b0f8de96ed067c0be1e" - integrity sha512-PzM1WlqquhBvsV+Gco6WSFeg1AGdD53ccMRkFeyHRE/KRZaVacPOmQYP3EeVgDBtKD2BJ8kgynBQ5OtKiHCH+w== +v8-to-istanbul@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.0.0.tgz#b4fe00e35649ef7785a9b7fcebcea05f37c332fc" + integrity sha512-fLL2rFuQpMtm9r8hrAV2apXX/WqHJ6+IC4/eQVdMDGBUgH/YMV4Gv3duk3kjmyg6uiQWBAA9nJwue4iJUOkHeA== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" From 4a0fb0fd862e2f516844b67e94feecd751e5dcca Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 6 Nov 2020 15:25:51 +0400 Subject: [PATCH 13/85] messageId -> method in send func --- src/communication/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 579f5a1a..9c8c5da8 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -40,7 +40,7 @@ class InterfaceCommunicator implements Communicator { }; public send = ( - messageId: T, + method: T, data: D, requestId?: RequestId, ): Promise<{ requestId: string }> => { @@ -49,7 +49,7 @@ class InterfaceCommunicator implements Communicator { } const message = { - messageId, + method, requestId, data, }; From be329624c7825f4d202476d932a36dd0e82cd0a4 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 6 Nov 2020 15:57:54 +0400 Subject: [PATCH 14/85] incoming msg handler wip --- src/communication/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 9c8c5da8..72e7164f 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -36,7 +36,9 @@ class InterfaceCommunicator implements Communicator { }; private handleIncomingMessage = (method: Methods, params: MethodToParams[Methods], requestId: RequestId): void => { - console.log({ method, params, requestId }); + const cb = this.callbacks[requestId]; + + cb && cb(params); }; public send = ( From ca88eacf20e9e7016ecd83f0651e3b3204d3eda1 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 6 Nov 2020 18:22:36 +0400 Subject: [PATCH 15/85] update incoming message handler --- src/communication/index.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 72e7164f..bae7cc38 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -2,7 +2,7 @@ import { InterfaceMessageEvent, RequestId, Communicator, Methods, MethodToParams import { generateRequestId } from './utils'; interface CallbacksMap { - [key: string]: unknown; + [key: string]: (...args: unknown[]) => unknown; } class InterfaceCommunicator implements Communicator { @@ -31,14 +31,18 @@ class InterfaceCommunicator implements Communicator { this.logIncomingMessage(msg); if (this.isValidMessage(msg)) { - this.handleIncomingMessage(msg.data.method, msg.data.params, msg.data.requestId); + this.handleIncomingMessage(msg.data.params, msg.data.requestId); } }; - private handleIncomingMessage = (method: Methods, params: MethodToParams[Methods], requestId: RequestId): void => { + private handleIncomingMessage = (params: MethodToParams[Methods], requestId: RequestId): void => { const cb = this.callbacks[requestId]; - cb && cb(params); + if (cb) { + cb(params); + + delete this.callbacks[requestId]; + } }; public send = ( From 06a4722f9332bfe1c3594cb95148b43663d7024b Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 6 Nov 2020 18:37:21 +0400 Subject: [PATCH 16/85] add known origins --- src/communication/index.ts | 6 +++--- src/communication/utils.ts | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index bae7cc38..ce82ce24 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,5 +1,5 @@ import { InterfaceMessageEvent, RequestId, Communicator, Methods, MethodToParams } from '../types'; -import { generateRequestId } from './utils'; +import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; interface CallbacksMap { [key: string]: (...args: unknown[]) => unknown; @@ -10,7 +10,7 @@ class InterfaceCommunicator implements Communicator { private callbacks: CallbacksMap = {}; constructor(allowedOrigins: RegExp[]) { - this.allowedOrigins = allowedOrigins; + this.allowedOrigins = [...DEFAULT_ALLOWED_ORIGINS, ...allowedOrigins]; window.addEventListener('message', this.onParentMessage); } @@ -24,7 +24,7 @@ class InterfaceCommunicator implements Communicator { }; private logIncomingMessage = (msg: InterfaceMessageEvent): void => { - console.info(`SafeConnector: A message was received from origin ${msg.origin}. `, msg.data); + console.info(`Safe Apps SDK v2: A message was received from origin ${msg.origin}. `, msg.data); }; private onParentMessage = (msg: InterfaceMessageEvent): void => { diff --git a/src/communication/utils.ts b/src/communication/utils.ts index 371a96d9..a56b220a 100644 --- a/src/communication/utils.ts +++ b/src/communication/utils.ts @@ -6,4 +6,9 @@ const generateRequestId = (): number => { return Math.trunc(Date.now()); }; -export { generateRequestId }; +const DEFAULT_ALLOWED_ORIGINS = [ + /https:\/\/.*(gnosis-safe\.io|gnosisdev.com)/, // Safe Multisig + /https?:\/\/localhost:\d+/, // Safe Multisig desktop app. +]; + +export { generateRequestId, DEFAULT_ALLOWED_ORIGINS }; From 8458c6bc1533ab6e93cd8901938b431f03f644bf Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 6 Nov 2020 18:55:45 +0400 Subject: [PATCH 17/85] =?UTF-8?q?first=20promisified=20method=20was=20succ?= =?UTF-8?q?essfully=20called=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/communication/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index ce82ce24..105bc5f8 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -16,7 +16,7 @@ class InterfaceCommunicator implements Communicator { } private isValidMessage = ({ origin, data }: InterfaceMessageEvent): boolean => { - const emptyOrMalformed = !data || !data.method; + const emptyOrMalformed = !data; const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; const sameOrigin = origin === window.origin; @@ -31,7 +31,7 @@ class InterfaceCommunicator implements Communicator { this.logIncomingMessage(msg); if (this.isValidMessage(msg)) { - this.handleIncomingMessage(msg.data.params, msg.data.requestId); + this.handleIncomingMessage(msg.data, msg.data.requestId); } }; From a0ea72d648295b38ee818aac5af8a8004a4653d3 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 9 Nov 2020 15:13:58 +0400 Subject: [PATCH 18/85] sdk wip --- src/communication/index.ts | 34 ++++++++++++++-------------------- src/communication/methods.ts | 1 + src/communication/utils.ts | 6 +++--- src/eth/index.ts | 6 +++--- src/sdk.ts | 9 ++++++++- src/txs/index.ts | 6 ++++-- src/types.ts | 3 ++- 7 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 105bc5f8..3c7f6743 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,13 +1,11 @@ -import { InterfaceMessageEvent, RequestId, Communicator, Methods, MethodToParams } from '../types'; +import { InterfaceMessageEvent, Communicator, Methods, MethodToParams } from '../types'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; -interface CallbacksMap { - [key: string]: (...args: unknown[]) => unknown; -} +type Callback = (...args: unknown[]) => unknown; class InterfaceCommunicator implements Communicator { private allowedOrigins: RegExp[] = []; - private callbacks: CallbacksMap = {}; + private callbacks = new Map(); constructor(allowedOrigins: RegExp[]) { this.allowedOrigins = [...DEFAULT_ALLOWED_ORIGINS, ...allowedOrigins]; @@ -31,28 +29,24 @@ class InterfaceCommunicator implements Communicator { this.logIncomingMessage(msg); if (this.isValidMessage(msg)) { - this.handleIncomingMessage(msg.data, msg.data.requestId); + this.handleIncomingMessage(msg.data); } }; - private handleIncomingMessage = (params: MethodToParams[Methods], requestId: RequestId): void => { - const cb = this.callbacks[requestId]; + private handleIncomingMessage = (payload: InterfaceMessageEvent['data']): void => { + const { requestId } = payload; + const cb = this.callbacks.get(requestId); if (cb) { - cb(params); + console.log({ payload }); + cb(payload.params); - delete this.callbacks[requestId]; + this.callbacks.delete(requestId); } }; - public send = ( - method: T, - data: D, - requestId?: RequestId, - ): Promise<{ requestId: string }> => { - if (!requestId) { - requestId = generateRequestId(); - } + public send = (method: T, data: D): Promise<{ requestId: string }> => { + const requestId = generateRequestId(); const message = { method, @@ -65,9 +59,9 @@ class InterfaceCommunicator implements Communicator { } return new Promise((resolve) => { - this.callbacks[requestId as string] = (response: unknown) => { + this.callbacks.set(requestId, (response: unknown) => { resolve(response as { requestId: string }); - }; + }); }); }; } diff --git a/src/communication/methods.ts b/src/communication/methods.ts index 689726de..54db5f10 100644 --- a/src/communication/methods.ts +++ b/src/communication/methods.ts @@ -2,4 +2,5 @@ export const METHODS = { getEnvInfo: 'getEnvInfo', sendTransactions: 'sendTransactions', rpcCall: 'rpcCall', + getSafeInfo: 'getSafeInfo', } as const; diff --git a/src/communication/utils.ts b/src/communication/utils.ts index a56b220a..efe427eb 100644 --- a/src/communication/utils.ts +++ b/src/communication/utils.ts @@ -1,9 +1,9 @@ -const generateRequestId = (): number => { +const generateRequestId = (): string => { if (typeof window !== 'undefined') { - return Math.trunc(window?.performance.now()); + return window?.performance.now().toString(36); } - return Math.trunc(Date.now()); + return new Date().getTime().toString(36); }; const DEFAULT_ALLOWED_ORIGINS = [ diff --git a/src/eth/index.ts b/src/eth/index.ts index 00d5d0c4..a3893f20 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -65,7 +65,7 @@ class Eth { /* eslint-disable-next-line */ formatters?: (((arg: any) => any) | null)[]; }) { - return (args: RequestArgs

): Promise<{ requestId: string }> => { + return async (args: RequestArgs

): Promise<{ requestId: string }> => { const params = args.params; if (formatters && Array.isArray(params)) { @@ -81,9 +81,9 @@ class Eth { params, }; - const message = this.#communicator.send(METHODS.rpcCall, payload, args.requestId); + const response = await this.#communicator.send(METHODS.rpcCall, payload, args.requestId); - return message; + return response; }; } } diff --git a/src/sdk.ts b/src/sdk.ts index 989a0a0c..0364cc25 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -1,3 +1,4 @@ +import { METHODS } from './communication/methods'; import { Communicator } from './types'; import InterfaceCommunicator from './communication'; import { TXs } from './txs'; @@ -20,10 +21,16 @@ class SDK { } private async sendInitializationMessage() { - const response = await this.#communicator.send('getEnvInfo', undefined); + const response = await this.#communicator.send(METHODS.getEnvInfo, undefined); console.log({ response }); } + + async getSafeInfo() { + const response = await this.#communicator.send(METHODS.getSafeInfo, undefined); + + return response; + } } export default SDK; diff --git a/src/txs/index.ts b/src/txs/index.ts index 523baccd..3a4d435c 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -31,7 +31,7 @@ class TXs { } } - send({ txs, params, requestId }: SendTransactionsArgs): void { + async send({ txs, params, requestId }: SendTransactionsArgs): Promise<{ requestId: string }> { if (!txs || !txs.length) { throw new Error('sendTransactionsWithParams: No transactions were passed'); } @@ -41,7 +41,9 @@ class TXs { params, }; - this.#communicator.send(METHODS.sendTransactions, messagePayload, requestId); + const response = await this.#communicator.send(METHODS.sendTransactions, messagePayload, requestId); + + return response; } public setTxServiceUrl(url: string): void { diff --git a/src/types.ts b/src/types.ts index 3ec83cb7..cf1b6700 100644 --- a/src/types.ts +++ b/src/types.ts @@ -38,7 +38,7 @@ export interface Transaction { data: string; } -export type RequestId = number | string; +export type RequestId = string; export interface SendTransactionParams { safeTxGas?: number; @@ -83,6 +83,7 @@ export interface MethodToParams { [METHODS.getEnvInfo]: undefined; [METHODS.sendTransactions]: unknown; [METHODS.rpcCall]: unknown; + [METHODS.getSafeInfo]: unknown; } export type RPCPayload = { From 19731d293e64718fd7e272599e64a954266c802d Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 9 Nov 2020 15:16:07 +0400 Subject: [PATCH 19/85] fix build --- src/sdk.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk.test.ts b/src/sdk.test.ts index ccdec71c..986462cd 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -44,7 +44,7 @@ describe('Safe apps SDK', () => { test('Should include passed safeTxGas and requestId params to a message body', () => { const txs = [{ to: 'address', value: '0', data: '0x' }]; - const requestId = 1234; + const requestId = '1234'; const params = { safeTxGas: 5000 }; sdkInstance.txs.send({ txs, params, requestId }); From fbd3e62929173a5ce5439b2b8e3482c03852130e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 9 Nov 2020 16:29:33 +0400 Subject: [PATCH 20/85] communicator wip --- src/communication/index.ts | 11 ++++++----- src/eth/index.ts | 4 ++-- src/sdk.test.ts | 6 +++--- src/txs/index.ts | 4 ++-- src/types.ts | 16 +++++++++------- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 3c7f6743..7c80433e 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,7 +1,8 @@ -import { InterfaceMessageEvent, Communicator, Methods, MethodToParams } from '../types'; +import { InterfaceMessageEvent, Communicator, Methods, MethodToParams, ResponseToMethod } from '../types'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; -type Callback = (...args: unknown[]) => unknown; +// eslint-disable-next-line +type Callback = (response: any) => void; class InterfaceCommunicator implements Communicator { private allowedOrigins: RegExp[] = []; @@ -45,7 +46,7 @@ class InterfaceCommunicator implements Communicator { } }; - public send = (method: T, data: D): Promise<{ requestId: string }> => { + public send = (method: M, data: P): Promise => { const requestId = generateRequestId(); const message = { @@ -59,8 +60,8 @@ class InterfaceCommunicator implements Communicator { } return new Promise((resolve) => { - this.callbacks.set(requestId, (response: unknown) => { - resolve(response as { requestId: string }); + this.callbacks.set(requestId, (response: R) => { + resolve(response); }); }); }; diff --git a/src/eth/index.ts b/src/eth/index.ts index a3893f20..dedb3846 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -65,7 +65,7 @@ class Eth { /* eslint-disable-next-line */ formatters?: (((arg: any) => any) | null)[]; }) { - return async (args: RequestArgs

): Promise<{ requestId: string }> => { + return async (args: RequestArgs

): Promise> => { const params = args.params; if (formatters && Array.isArray(params)) { @@ -81,7 +81,7 @@ class Eth { params, }; - const response = await this.#communicator.send(METHODS.rpcCall, payload, args.requestId); + const response = await this.#communicator.send(METHODS.rpcCall, payload); return response; }; diff --git a/src/sdk.test.ts b/src/sdk.test.ts index 986462cd..74992766 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -27,7 +27,7 @@ describe('Safe apps SDK', () => { const requestId = '1000'; const spy = jest.spyOn(window.parent, 'postMessage'); const txs = [{ to: 'address', value: '0', data: '0x' }]; - sdkInstance.txs.send({ txs, requestId }); + sdkInstance.txs.send({ txs }); expect(spy).toHaveBeenCalledWith( { messageId: METHODS.sendTransactions, data: { txs, params: undefined }, requestId }, '*', @@ -44,9 +44,9 @@ describe('Safe apps SDK', () => { test('Should include passed safeTxGas and requestId params to a message body', () => { const txs = [{ to: 'address', value: '0', data: '0x' }]; - const requestId = '1234'; const params = { safeTxGas: 5000 }; - sdkInstance.txs.send({ txs, params, requestId }); + + sdkInstance.txs.send({ txs, params }); // expect(request.requestId).toBe(requestId); // expect(request.data).toEqual({ txs, params }); diff --git a/src/txs/index.ts b/src/txs/index.ts index 3a4d435c..1f744bb8 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -31,7 +31,7 @@ class TXs { } } - async send({ txs, params, requestId }: SendTransactionsArgs): Promise<{ requestId: string }> { + async send({ txs, params }: SendTransactionsArgs): Promise> { if (!txs || !txs.length) { throw new Error('sendTransactionsWithParams: No transactions were passed'); } @@ -41,7 +41,7 @@ class TXs { params, }; - const response = await this.#communicator.send(METHODS.sendTransactions, messagePayload, requestId); + const response = await this.#communicator.send(METHODS.sendTransactions, messagePayload); return response; } diff --git a/src/types.ts b/src/types.ts index cf1b6700..0c5af820 100644 --- a/src/types.ts +++ b/src/types.ts @@ -47,7 +47,6 @@ export interface SendTransactionParams { export interface SendTransactionsArgs { txs: Transaction[]; params?: SendTransactionParams; - requestId?: RequestId; } export interface SdkInstance { txs: TXs; @@ -79,11 +78,18 @@ export interface InterfaceMessageEvent extends MessageEvent { }; } +export interface ResponseToMethod { + [METHODS.getEnvInfo]: { txServiceUrl: string }; + [METHODS.sendTransactions]: Record; + [METHODS.rpcCall]: Record; + [METHODS.getSafeInfo]: SafeInfo; +} + export interface MethodToParams { [METHODS.getEnvInfo]: undefined; [METHODS.sendTransactions]: unknown; [METHODS.rpcCall]: unknown; - [METHODS.getSafeInfo]: unknown; + [METHODS.getSafeInfo]: undefined; } export type RPCPayload = { @@ -199,9 +205,5 @@ export type RequestArgs = { }; export interface Communicator { - send( - messageId: T, - data: D, - requestId?: RequestId, - ): Promise<{ requestId: string }>; + send(messageId: M, data: P): Promise; } From 0c3b16fe16068e486a80366d30f3c0b017a8aa04 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 9 Nov 2020 17:02:36 +0400 Subject: [PATCH 21/85] fix handling incomming messages --- src/communication/index.ts | 6 +++--- src/types.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 7c80433e..ac2138c2 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,4 +1,4 @@ -import { InterfaceMessageEvent, Communicator, Methods, MethodToParams, ResponseToMethod } from '../types'; +import { InterfaceMessageEvent, Communicator, Methods, MethodToParams, MethodToResponse } from '../types'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; // eslint-disable-next-line @@ -40,13 +40,13 @@ class InterfaceCommunicator implements Communicator { const cb = this.callbacks.get(requestId); if (cb) { console.log({ payload }); - cb(payload.params); + cb(payload.response); this.callbacks.delete(requestId); } }; - public send = (method: M, data: P): Promise => { + public send = (method: M, data: P): Promise => { const requestId = generateRequestId(); const message = { diff --git a/src/types.ts b/src/types.ts index 0c5af820..e567a1fd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -74,11 +74,11 @@ export interface InterfaceMessageEvent extends MessageEvent { data: { requestId: RequestId; method: Methods; - params: MethodToParams[Methods]; + response: MethodToResponse[Methods]; }; } -export interface ResponseToMethod { +export interface MethodToResponse { [METHODS.getEnvInfo]: { txServiceUrl: string }; [METHODS.sendTransactions]: Record; [METHODS.rpcCall]: Record; @@ -205,5 +205,5 @@ export type RequestArgs = { }; export interface Communicator { - send(messageId: M, data: P): Promise; + send(messageId: M, data: P): Promise; } From 154588eac79eab750e8e3e6176a2eda350743baa Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 12:45:08 +0400 Subject: [PATCH 22/85] dep bump --- package.json | 10 ++--- yarn.lock | 112 ++++++++++++++++++++++++--------------------------- 2 files changed, 58 insertions(+), 64 deletions(-) diff --git a/package.json b/package.json index 265598a1..979d0641 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,10 @@ }, "devDependencies": { "@types/jest": "^26.0.15", - "@types/node": "^14.14.6", - "@typescript-eslint/eslint-plugin": "^4.6.1", - "@typescript-eslint/parser": "^4.6.1", - "eslint": "^7.12.1", + "@types/node": "^14.14.7", + "@typescript-eslint/eslint-plugin": "^4.7.0", + "@typescript-eslint/parser": "^4.7.0", + "eslint": "^7.13.0", "eslint-config-prettier": "^6.15.0", "eslint-plugin-prettier": "^3.1.4", "husky": "^4.3.0", @@ -38,7 +38,7 @@ "lint-staged": "^10.5.1", "prettier": "^2.1.2", "rimraf": "^3.0.2", - "ts-jest": "^26.4.3", + "ts-jest": "^26.4.4", "tslint": "^6.1.3", "tslint-config-prettier": "^1.18.0", "typescript": "^4.0.5" diff --git a/yarn.lock b/yarn.lock index dab129a8..831d960d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -493,11 +493,6 @@ slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/create-cache-key-function@^26.5.0": - version "26.5.0" - resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-26.5.0.tgz#1d07947adc51ea17766d9f0ccf5a8d6ea94c47dc" - integrity sha512-DJ+pEBUIqarrbv1W/C39f9YH0rJ4wsXZ/VC6JafJPlHW2HOucKceeaqTOQj9MEDQZjySxMLkOq5mfXZXNZcmWw== - "@jest/environment@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" @@ -818,10 +813,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.0.tgz#a0f841c195bdbe0b5070da9278b3e22189e8c8f6" integrity sha512-4BVAE9yp5DU3ISqBInsaRp9J474HWNaNVs8eZ1Far3dI1MwS3Wk0EvBRMM4xBh3Oz+c05hUgJmcbtAVmG8bv7w== -"@types/node@^14.14.6": - version "14.14.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" - integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== +"@types/node@^14.14.7": + version "14.14.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d" + integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -855,61 +850,61 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.1.tgz#99d77eb7a016fd5a5e749d2c44a7e4c317eb7da3" - integrity sha512-SNZyflefTMK2JyrPfFFzzoy2asLmZvZJ6+/L5cIqg4HfKGiW2Gr1Go1OyEVqne/U4QwmoasuMwppoBHWBWF2nA== +"@typescript-eslint/eslint-plugin@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.7.0.tgz#85c9bbda00c0cb604d3c241f7bc7fb171a2d3479" + integrity sha512-li9aiSVBBd7kU5VlQlT1AqP0uWGDK6JYKUQ9cVDnOg34VNnd9t4jr0Yqc/bKxJr/tDCPDaB4KzoSFN9fgVxe/Q== dependencies: - "@typescript-eslint/experimental-utils" "4.6.1" - "@typescript-eslint/scope-manager" "4.6.1" + "@typescript-eslint/experimental-utils" "4.7.0" + "@typescript-eslint/scope-manager" "4.7.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.1.tgz#a9c691dfd530a9570274fe68907c24c07a06c4aa" - integrity sha512-qyPqCFWlHZXkEBoV56UxHSoXW2qnTr4JrWVXOh3soBP3q0o7p4pUEMfInDwIa0dB/ypdtm7gLOS0hg0a73ijfg== +"@typescript-eslint/experimental-utils@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.7.0.tgz#8d1058c38bec3d3bbd9c898a1c32318d80faf3c5" + integrity sha512-cymzovXAiD4EF+YoHAB5Oh02MpnXjvyaOb+v+BdpY7lsJXZQN34oIETeUwVT2XfV9rSNpXaIcknDLfupO/tUoA== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.6.1" - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/typescript-estree" "4.6.1" + "@typescript-eslint/scope-manager" "4.7.0" + "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/typescript-estree" "4.7.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.1.tgz#b801bff67b536ecc4a840ac9289ba2be57e02428" - integrity sha512-lScKRPt1wM9UwyKkGKyQDqf0bh6jm8DQ5iN37urRIXDm16GEv+HGEmum2Fc423xlk5NUOkOpfTnKZc/tqKZkDQ== +"@typescript-eslint/parser@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.7.0.tgz#44bdab0f788b478178368baa65d3365fdc63da1c" + integrity sha512-+meGV8bMP1sJHBI2AFq1GeTwofcGiur8LoIr6v+rEmD9knyCqDlrQcFHR0KDDfldHIFDU/enZ53fla6ReF4wRw== dependencies: - "@typescript-eslint/scope-manager" "4.6.1" - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/typescript-estree" "4.6.1" + "@typescript-eslint/scope-manager" "4.7.0" + "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/typescript-estree" "4.7.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.1.tgz#21872b91cbf7adfc7083f17b8041149148baf992" - integrity sha512-f95+80r6VdINYscJY1KDUEDcxZ3prAWHulL4qRDfNVD0I5QAVSGqFkwHERDoLYJJWmEAkUMdQVvx7/c2Hp+Bjg== +"@typescript-eslint/scope-manager@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.7.0.tgz#2115526085fb72723ccdc1eeae75dec7126220ed" + integrity sha512-ILITvqwDJYbcDCROj6+Ob0oCKNg3SH46iWcNcTIT9B5aiVssoTYkhKjxOMNzR1F7WSJkik4zmuqve5MdnA0DyA== dependencies: - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/visitor-keys" "4.6.1" + "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/visitor-keys" "4.7.0" -"@typescript-eslint/types@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.1.tgz#d3ad7478f53f22e7339dc006ab61aac131231552" - integrity sha512-k2ZCHhJ96YZyPIsykickez+OMHkz06xppVLfJ+DY90i532/Cx2Z+HiRMH8YZQo7a4zVd/TwNBuRCdXlGK4yo8w== +"@typescript-eslint/types@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.7.0.tgz#5e95ef5c740f43d942542b35811f87b62fccca69" + integrity sha512-uLszFe0wExJc+I7q0Z/+BnP7wao/kzX0hB5vJn4LIgrfrMLgnB2UXoReV19lkJQS1a1mHWGGODSxnBx6JQC3Sg== -"@typescript-eslint/typescript-estree@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.1.tgz#6025cce724329413f57e4959b2d676fceeca246f" - integrity sha512-/J/kxiyjQQKqEr5kuKLNQ1Finpfb8gf/NpbwqFFYEBjxOsZ621r9AqwS9UDRA1Rrr/eneX/YsbPAIhU2rFLjXQ== +"@typescript-eslint/typescript-estree@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.7.0.tgz#539531167f05ba20eb0b6785567076679e29d393" + integrity sha512-5XZRQznD1MfUmxu1t8/j2Af4OxbA7EFU2rbo0No7meb46eHgGkSieFdfV6omiC/DGIBhH9H9gXn7okBbVOm8jw== dependencies: - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/visitor-keys" "4.6.1" + "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/visitor-keys" "4.7.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" @@ -917,12 +912,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.1.tgz#6b125883402d8939df7b54528d879e88f7ba3614" - integrity sha512-owABze4toX7QXwOLT3/D5a8NecZEjEWU1srqxENTfqsY3bwVnl3YYbOh6s1rp2wQKO9RTHFGjKes08FgE7SVMw== +"@typescript-eslint/visitor-keys@4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.7.0.tgz#6783824f22acfc49e754970ed21b88ac03b80e6f" + integrity sha512-aDJDWuCRsf1lXOtignlfiPODkzSxxop7D0rZ91L6ZuMlcMCSh0YyK+gAfo5zN/ih6WxMwhoXgJWC3cWQdaKC+A== dependencies: - "@typescript-eslint/types" "4.6.1" + "@typescript-eslint/types" "4.7.0" eslint-visitor-keys "^2.0.0" abab@^2.0.3: @@ -1900,10 +1895,10 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^7.12.1: - version "7.12.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.12.1.tgz#bd9a81fa67a6cfd51656cdb88812ce49ccec5801" - integrity sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg== +eslint@^7.13.0: + version "7.13.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.13.0.tgz#7f180126c0dcdef327bfb54b211d7802decc08da" + integrity sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ== dependencies: "@babel/code-frame" "^7.0.0" "@eslint/eslintrc" "^0.2.1" @@ -4855,12 +4850,11 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" -ts-jest@^26.4.3: - version "26.4.3" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.4.3.tgz#d153a616033e7ec8544b97ddbe2638cbe38d53db" - integrity sha512-pFDkOKFGY+nL9v5pkhm+BIFpoAuno96ff7GMnIYr/3L6slFOS365SI0fGEVYx2RKGji5M2elxhWjDMPVcOCdSw== +ts-jest@^26.4.4: + version "26.4.4" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.4.4.tgz#61f13fb21ab400853c532270e52cc0ed7e502c49" + integrity sha512-3lFWKbLxJm34QxyVNNCgXX1u4o/RV0myvA2y2Bxm46iGIjKlaY0own9gIckbjZJPn+WaJEnfPPJ20HHGpoq4yg== dependencies: - "@jest/create-cache-key-function" "^26.5.0" "@types/jest" "26.x" bs-logger "0.x" buffer-from "1.x" From 4db16c5ea2e877140572dc3f2dfbc87a7056fbce Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 14:06:05 +0400 Subject: [PATCH 23/85] include sdk version, check method validity --- src/communication/index.ts | 9 +++++++-- src/sdk.ts | 9 ++++++--- tsconfig.json | 3 ++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index ac2138c2..5a191597 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,4 +1,5 @@ import { InterfaceMessageEvent, Communicator, Methods, MethodToParams, MethodToResponse } from '../types'; +import { METHODS } from './methods'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; // eslint-disable-next-line @@ -7,9 +8,11 @@ type Callback = (response: any) => void; class InterfaceCommunicator implements Communicator { private allowedOrigins: RegExp[] = []; private callbacks = new Map(); + sdkVersion: string; - constructor(allowedOrigins: RegExp[]) { + constructor(allowedOrigins: RegExp[], sdkVersion: string) { this.allowedOrigins = [...DEFAULT_ALLOWED_ORIGINS, ...allowedOrigins]; + this.sdkVersion = sdkVersion; window.addEventListener('message', this.onParentMessage); } @@ -18,8 +21,9 @@ class InterfaceCommunicator implements Communicator { const emptyOrMalformed = !data; const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; const sameOrigin = origin === window.origin; + const knownMethod = Object.values(METHODS).includes(data.method); - return !emptyOrMalformed && !unknownOrigin && !sameOrigin; + return !emptyOrMalformed && !unknownOrigin && !sameOrigin && knownMethod; }; private logIncomingMessage = (msg: InterfaceMessageEvent): void => { @@ -53,6 +57,7 @@ class InterfaceCommunicator implements Communicator { method, requestId, data, + env: { sdkVersion: this.sdkVersion }, }; if (typeof window !== 'undefined') { diff --git a/src/sdk.ts b/src/sdk.ts index 0364cc25..1e641764 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -1,8 +1,11 @@ import { METHODS } from './communication/methods'; -import { Communicator } from './types'; +import { Communicator, SafeInfo } from './types'; import InterfaceCommunicator from './communication'; import { TXs } from './txs'; import { Eth } from './eth'; +import pkg from '../package.json'; + +const sdkVersion = pkg.version; class SDK { #communicator: Communicator; @@ -14,7 +17,7 @@ class SDK { throw new Error('Error initializing the sdk: window is undefined'); } - this.#communicator = new InterfaceCommunicator(safeAppUrlsRegExp); + this.#communicator = new InterfaceCommunicator(safeAppUrlsRegExp, sdkVersion); this.eth = new Eth(this.#communicator); this.txs = new TXs(this.#communicator); this.sendInitializationMessage(); @@ -26,7 +29,7 @@ class SDK { console.log({ response }); } - async getSafeInfo() { + async getSafeInfo(): Promise { const response = await this.#communicator.send(METHODS.getSafeInfo, undefined); return response; diff --git a/tsconfig.json b/tsconfig.json index 56ead9bd..6d6b24a2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,8 @@ "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, + "resolveJsonModule": true }, "include": ["src"] } From 3a1982b39088e22117db9d088fe84539a695e4bc Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 14:14:34 +0400 Subject: [PATCH 24/85] use fs.readfilesync instead of require --- src/sdk.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sdk.ts b/src/sdk.ts index 1e641764..3f9a6107 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -3,9 +3,11 @@ import { Communicator, SafeInfo } from './types'; import InterfaceCommunicator from './communication'; import { TXs } from './txs'; import { Eth } from './eth'; -import pkg from '../package.json'; +import fs from 'fs'; -const sdkVersion = pkg.version; +// Using require() produces weird build structure as it has to include package.json +// This is a workaround (didn't dive deep, there may be a better solution) +const sdkVersion = JSON.parse(fs.readFileSync('../package.json').toString()).version; class SDK { #communicator: Communicator; From 2e621d4faab945dcacd5b34d93d95cdaa9758e7b Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 14:30:49 +0400 Subject: [PATCH 25/85] bring back require and tweak pkg json --- package.json | 4 ++-- src/sdk.ts | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 979d0641..ec3b65f8 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,8 @@ "name": "@gnosis.pm/safe-apps-sdk", "version": "1.0.0", "description": "SDK developed to integrate third-party apps with Safe-Multisig app.", - "main": "dist/index.js", - "typings": "dist/index.d.ts", + "main": "dist/src/index.js", + "typings": "dist/src/index.d.ts", "files": [ "dist/**/*", "README.md" diff --git a/src/sdk.ts b/src/sdk.ts index 3f9a6107..1e641764 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -3,11 +3,9 @@ import { Communicator, SafeInfo } from './types'; import InterfaceCommunicator from './communication'; import { TXs } from './txs'; import { Eth } from './eth'; -import fs from 'fs'; +import pkg from '../package.json'; -// Using require() produces weird build structure as it has to include package.json -// This is a workaround (didn't dive deep, there may be a better solution) -const sdkVersion = JSON.parse(fs.readFileSync('../package.json').toString()).version; +const sdkVersion = pkg.version; class SDK { #communicator: Communicator; From 87dbee52b3f3b258b6ee74eba689a04dc8f9153c Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 14:49:20 +0400 Subject: [PATCH 26/85] add version check --- package.json | 2 ++ src/communication/index.ts | 6 +++--- src/sdk.ts | 4 ++-- src/types.ts | 1 + yarn.lock | 5 +++++ 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ec3b65f8..49d20bed 100644 --- a/package.json +++ b/package.json @@ -23,11 +23,13 @@ "author": "Gnosis (https://gnosis.pm)", "license": "MIT", "dependencies": { + "semver": "^7.3.2", "web3-core": "^1.3.0" }, "devDependencies": { "@types/jest": "^26.0.15", "@types/node": "^14.14.7", + "@types/semver": "^7.3.4", "@typescript-eslint/eslint-plugin": "^4.7.0", "@typescript-eslint/parser": "^4.7.0", "eslint": "^7.13.0", diff --git a/src/communication/index.ts b/src/communication/index.ts index 5a191597..387dae3e 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,5 +1,5 @@ +import semver from 'semver'; import { InterfaceMessageEvent, Communicator, Methods, MethodToParams, MethodToResponse } from '../types'; -import { METHODS } from './methods'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; // eslint-disable-next-line @@ -21,9 +21,9 @@ class InterfaceCommunicator implements Communicator { const emptyOrMalformed = !data; const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; const sameOrigin = origin === window.origin; - const knownMethod = Object.values(METHODS).includes(data.method); + const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gt('1.x', data.version) : false; - return !emptyOrMalformed && !unknownOrigin && !sameOrigin && knownMethod; + return !emptyOrMalformed && !unknownOrigin && !sameOrigin && allowedSDKVersion; }; private logIncomingMessage = (msg: InterfaceMessageEvent): void => { diff --git a/src/sdk.ts b/src/sdk.ts index 1e641764..28c79343 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -5,7 +5,7 @@ import { TXs } from './txs'; import { Eth } from './eth'; import pkg from '../package.json'; -const sdkVersion = pkg.version; +export const __VERSION__ = pkg.version; class SDK { #communicator: Communicator; @@ -17,7 +17,7 @@ class SDK { throw new Error('Error initializing the sdk: window is undefined'); } - this.#communicator = new InterfaceCommunicator(safeAppUrlsRegExp, sdkVersion); + this.#communicator = new InterfaceCommunicator(safeAppUrlsRegExp, __VERSION__); this.eth = new Eth(this.#communicator); this.txs = new TXs(this.#communicator); this.sendInitializationMessage(); diff --git a/src/types.ts b/src/types.ts index e567a1fd..8f4fcfad 100644 --- a/src/types.ts +++ b/src/types.ts @@ -75,6 +75,7 @@ export interface InterfaceMessageEvent extends MessageEvent { requestId: RequestId; method: Methods; response: MethodToResponse[Methods]; + version?: 'initial' | string; }; } diff --git a/yarn.lock b/yarn.lock index 831d960d..93effe0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -833,6 +833,11 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.2.tgz#5bb52ee68d0f8efa9cc0099920e56be6cc4e37f3" integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA== +"@types/semver@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.4.tgz#43d7168fec6fa0988bb1a513a697b29296721afb" + integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ== + "@types/stack-utils@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" From e125e6753018a11901eba9a2dcef1c796a7383a4 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 14:57:22 +0400 Subject: [PATCH 27/85] Fix version export --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 07fb0fcb..220d077f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import SDK from './sdk'; export default SDK; - +export * from './sdk'; export * from './types'; export * from './communication/methods'; From 53454c2c1744ece0d53ae382509f1464826627f5 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 15:16:54 +0400 Subject: [PATCH 28/85] fix version number --- src/communication/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 387dae3e..b70d189a 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -21,7 +21,7 @@ class InterfaceCommunicator implements Communicator { const emptyOrMalformed = !data; const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; const sameOrigin = origin === window.origin; - const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gt('1.x', data.version) : false; + const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gt('1.0', data.version) : false; return !emptyOrMalformed && !unknownOrigin && !sameOrigin && allowedSDKVersion; }; From 3c1398c6738ca293f2505ecf0315b71de5f758e1 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 15:20:43 +0400 Subject: [PATCH 29/85] fix version number & comparing function --- src/communication/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index b70d189a..2d3193a6 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -21,7 +21,7 @@ class InterfaceCommunicator implements Communicator { const emptyOrMalformed = !data; const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; const sameOrigin = origin === window.origin; - const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gt('1.0', data.version) : false; + const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gte('1.0.0', data.version) : false; return !emptyOrMalformed && !unknownOrigin && !sameOrigin && allowedSDKVersion; }; From 8e5c1517f41e548ed5d16aec1eb744a74ad8c524 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 15:45:53 +0400 Subject: [PATCH 30/85] Fix semver check --- src/communication/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 2d3193a6..a5d50d0e 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -21,7 +21,7 @@ class InterfaceCommunicator implements Communicator { const emptyOrMalformed = !data; const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; const sameOrigin = origin === window.origin; - const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gte('1.0.0', data.version) : false; + const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gte(data.version, '1.0.0') : false; return !emptyOrMalformed && !unknownOrigin && !sameOrigin && allowedSDKVersion; }; From 78c0f4660e2d206e73b2a2c14a5e88735d550360 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 10 Nov 2020 15:52:02 +0400 Subject: [PATCH 31/85] throw error in txs.send if tx was rejectted --- src/txs/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/txs/index.ts b/src/txs/index.ts index 1f744bb8..5e148274 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -43,6 +43,10 @@ class TXs { const response = await this.#communicator.send(METHODS.sendTransactions, messagePayload); + if (!response.success) { + throw new Error(response.error); + } + return response; } From 3921f52040b7714b1298df1887370c3c5ca5d86e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 11 Nov 2020 15:29:28 +0400 Subject: [PATCH 32/85] add types --- src/communication/index.ts | 19 ++++++++++++++----- src/types.ts | 24 +++++++++++++++++------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index a5d50d0e..3540f18c 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,5 +1,12 @@ import semver from 'semver'; -import { InterfaceMessageEvent, Communicator, Methods, MethodToParams, MethodToResponse } from '../types'; +import { + InterfaceMessageEvent, + Communicator, + Methods, + MethodToParams, + MethodToResponse, + SDKRequestData, +} from '../types'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; // eslint-disable-next-line @@ -43,20 +50,22 @@ class InterfaceCommunicator implements Communicator { const cb = this.callbacks.get(requestId); if (cb) { - console.log({ payload }); cb(payload.response); this.callbacks.delete(requestId); } }; - public send = (method: M, data: P): Promise => { + public send = ( + method: M, + params: P, + ): Promise => { const requestId = generateRequestId(); - const message = { + const message: SDKRequestData = { method, requestId, - data, + params, env: { sdkVersion: this.sdkVersion }, }; diff --git a/src/types.ts b/src/types.ts index 8f4fcfad..5b6b003a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -70,14 +70,24 @@ export interface TxRejectionEvent { export type Methods = keyof typeof METHODS; -export interface InterfaceMessageEvent extends MessageEvent { - data: { - requestId: RequestId; - method: Methods; - response: MethodToResponse[Methods]; - version?: 'initial' | string; +export type SDKRequestData = { + requestId: RequestId; + params: MethodToParams[Methods]; + env: { + sdkVersion: string; }; -} + method: Methods; +}; + +export type SDKMessageEvent = MessageEvent; + +export type InterfaceResponseData = { + requestId: RequestId; + response: MethodToResponse[Methods]; + version?: string; +}; + +export type InterfaceMessageEvent = MessageEvent; export interface MethodToResponse { [METHODS.getEnvInfo]: { txServiceUrl: string }; From bbcd8449b2cdc567551041b8026d54b4faa7f089 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 11 Nov 2020 16:31:10 +0400 Subject: [PATCH 33/85] extend types --- src/types.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 5b6b003a..967d9b44 100644 --- a/src/types.ts +++ b/src/types.ts @@ -81,9 +81,14 @@ export type SDKRequestData = { export type SDKMessageEvent = MessageEvent; +export type ErrorResponse = { + success: false; + error: string; +}; + export type InterfaceResponseData = { requestId: RequestId; - response: MethodToResponse[Methods]; + response: MethodToResponse[Methods] | ErrorResponse; version?: string; }; From 3238e96464fafad74e4c11d1c3677a11c8ca3688 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 11 Nov 2020 17:12:53 +0400 Subject: [PATCH 34/85] more type improvements --- src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 967d9b44..285f80e8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -103,7 +103,7 @@ export interface MethodToResponse { export interface MethodToParams { [METHODS.getEnvInfo]: undefined; - [METHODS.sendTransactions]: unknown; + [METHODS.sendTransactions]: SendTransactionsArgs; [METHODS.rpcCall]: unknown; [METHODS.getSafeInfo]: undefined; } From b4d3299eefb77863e0774ee7365bc478900b562f Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 11 Nov 2020 17:17:18 +0400 Subject: [PATCH 35/85] more type improvements --- src/types.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 285f80e8..e221eee5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -104,7 +104,10 @@ export interface MethodToResponse { export interface MethodToParams { [METHODS.getEnvInfo]: undefined; [METHODS.sendTransactions]: SendTransactionsArgs; - [METHODS.rpcCall]: unknown; + [METHODS.rpcCall]: { + call: string; + params: unknown[]; + }; [METHODS.getSafeInfo]: undefined; } From dc27b5809b9c84f5e20213ced2def35f850731f5 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 11 Nov 2020 17:36:07 +0400 Subject: [PATCH 36/85] more type improvements --- src/communication/index.ts | 7 ++----- src/eth/index.ts | 22 +++++++++++----------- src/types.ts | 13 +++++-------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 3540f18c..81decf80 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -56,10 +56,7 @@ class InterfaceCommunicator implements Communicator { } }; - public send = ( - method: M, - params: P, - ): Promise => { + public send = (method: M, params: MethodToParams[M]): Promise => { const requestId = generateRequestId(); const message: SDKRequestData = { @@ -74,7 +71,7 @@ class InterfaceCommunicator implements Communicator { } return new Promise((resolve) => { - this.callbacks.set(requestId, (response: R) => { + this.callbacks.set(requestId, (response: MethodToResponse[M]) => { resolve(response); }); }); diff --git a/src/eth/index.ts b/src/eth/index.ts index dedb3846..b62210bc 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -22,46 +22,46 @@ class Eth { constructor(communicator: Communicator) { this.#communicator = communicator; - this.call = this.buildRequest<[TransactionConfig, string?], typeof RPC_CALLS.eth_call>({ + this.call = this.buildRequest<[TransactionConfig, string?]>({ call: RPC_CALLS.eth_call, formatters: [null, inputFormatters.defaultBlockParam], }); - this.getBalance = this.buildRequest<[string, string?], typeof RPC_CALLS.eth_getBalance>({ + this.getBalance = this.buildRequest<[string, string?]>({ call: RPC_CALLS.eth_getBalance, formatters: [null, inputFormatters.defaultBlockParam], }); - this.getCode = this.buildRequest<[string, string?], typeof RPC_CALLS.eth_getCode>({ + this.getCode = this.buildRequest<[string, string?]>({ call: RPC_CALLS.eth_getCode, formatters: [null, inputFormatters.defaultBlockParam], }); - this.getStorageAt = this.buildRequest<[string, string?], typeof RPC_CALLS.eth_getStorageAt>({ + this.getStorageAt = this.buildRequest<[string, string?]>({ call: RPC_CALLS.eth_getStorageAt, formatters: [null, inputFormatters.defaultBlockParam], }); - this.getPastLogs = this.buildRequest<[PastLogsOptions], typeof RPC_CALLS.eth_getLogs>({ + this.getPastLogs = this.buildRequest<[PastLogsOptions]>({ call: RPC_CALLS.eth_getLogs, }); - this.getBlockByHash = this.buildRequest<[string, boolean?], typeof RPC_CALLS.eth_getBlockByHash>({ + this.getBlockByHash = this.buildRequest<[string, boolean?]>({ call: RPC_CALLS.eth_getBlockByHash, formatters: [null, inputFormatters.fullTxObjectParam], }); - this.getBlockByNumber = this.buildRequest<[string, boolean?], typeof RPC_CALLS.eth_getBlockByNumber>({ + this.getBlockByNumber = this.buildRequest<[string, boolean?]>({ call: RPC_CALLS.eth_getBlockByNumber, formatters: [null, inputFormatters.fullTxObjectParam], }); - this.getTransactionByHash = this.buildRequest<[string], typeof RPC_CALLS.eth_getTransactionByHash>({ + this.getTransactionByHash = this.buildRequest<[string]>({ call: RPC_CALLS.eth_getTransactionByHash, }); - this.getTransactionReceipt = this.buildRequest<[string], typeof RPC_CALLS.eth_getTransactionReceipt>({ + this.getTransactionReceipt = this.buildRequest<[string]>({ call: RPC_CALLS.eth_getTransactionReceipt, }); } - private buildRequest

({ + private buildRequest

({ call, formatters, }: { - call: C; + call: RpcCallNames; /* eslint-disable-next-line */ formatters?: (((arg: any) => any) | null)[]; }) { diff --git a/src/types.ts b/src/types.ts index e221eee5..971c5caa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -104,16 +104,13 @@ export interface MethodToResponse { export interface MethodToParams { [METHODS.getEnvInfo]: undefined; [METHODS.sendTransactions]: SendTransactionsArgs; - [METHODS.rpcCall]: { - call: string; - params: unknown[]; - }; + [METHODS.rpcCall]: RPCPayload; [METHODS.getSafeInfo]: undefined; } -export type RPCPayload = { - call: R; - params: P; +export type RPCPayload = { + call: RpcCallNames; + params: unknown[]; }; // copy-pasting all the types below from safe-react makes me think we might want to export them to a package @@ -224,5 +221,5 @@ export type RequestArgs = { }; export interface Communicator { - send(messageId: M, data: P): Promise; + send(messageId: M, data: MethodToParams[M]): Promise; } From 53fdfa20ec22c9887eb8ae9649ddcb0e1138a832 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 12 Nov 2020 14:08:45 +0400 Subject: [PATCH 37/85] update types for getStorageAt call --- src/eth/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index b62210bc..a4a50d91 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -34,9 +34,9 @@ class Eth { call: RPC_CALLS.eth_getCode, formatters: [null, inputFormatters.defaultBlockParam], }); - this.getStorageAt = this.buildRequest<[string, string?]>({ + this.getStorageAt = this.buildRequest<[string, number, string?]>({ call: RPC_CALLS.eth_getStorageAt, - formatters: [null, inputFormatters.defaultBlockParam], + formatters: [null, null, inputFormatters.defaultBlockParam], }); this.getPastLogs = this.buildRequest<[PastLogsOptions]>({ call: RPC_CALLS.eth_getLogs, From f5ed2cf8b6ce0135129442bcf5050f2991940574 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 12 Nov 2020 14:10:32 +0400 Subject: [PATCH 38/85] fix getStorageAt test --- src/eth/eth.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/eth/eth.test.ts b/src/eth/eth.test.ts index a08a2cba..ca6147dc 100644 --- a/src/eth/eth.test.ts +++ b/src/eth/eth.test.ts @@ -113,7 +113,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; const request = await sdkInstance.eth.getStorageAt({ - params: [addr, 'earliest'], + params: [addr, 0, 'earliest'], requestId, }); @@ -122,7 +122,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { messageId: METHODS.rpcCall, data: { call: 'eth_getStorageAt', - params: [addr, 'earliest'], + params: [addr, 0, 'earliest'], }, requestId, }, @@ -135,7 +135,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; const request = await sdkInstance.eth.getStorageAt({ - params: [addr], + params: [addr, 0], requestId, }); @@ -144,7 +144,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { messageId: METHODS.rpcCall, data: { call: 'eth_getStorageAt', - params: [addr, 'latest'], + params: [addr, 0, 'latest'], }, requestId, }, From 5e910b0a20273434dc32ef6ac01e424575b3bd6c Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 12 Nov 2020 14:17:48 +0400 Subject: [PATCH 39/85] add numberToHex formatter --- src/eth/eth.test.ts | 2 +- src/eth/index.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/eth/eth.test.ts b/src/eth/eth.test.ts index ca6147dc..7fccc6e2 100644 --- a/src/eth/eth.test.ts +++ b/src/eth/eth.test.ts @@ -122,7 +122,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { messageId: METHODS.rpcCall, data: { call: 'eth_getStorageAt', - params: [addr, 0, 'earliest'], + params: [addr, '0x0', 'earliest'], }, requestId, }, diff --git a/src/eth/index.ts b/src/eth/index.ts index a4a50d91..d00d3be9 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -6,6 +6,7 @@ import { METHODS } from '../communication/methods'; const inputFormatters = { defaultBlockParam: (arg = 'latest') => arg, fullTxObjectParam: (arg = false) => arg, + numberToHex: (arg: number) => arg.toString(16), }; class Eth { @@ -36,7 +37,7 @@ class Eth { }); this.getStorageAt = this.buildRequest<[string, number, string?]>({ call: RPC_CALLS.eth_getStorageAt, - formatters: [null, null, inputFormatters.defaultBlockParam], + formatters: [null, inputFormatters.numberToHex, inputFormatters.defaultBlockParam], }); this.getPastLogs = this.buildRequest<[PastLogsOptions]>({ call: RPC_CALLS.eth_getLogs, From b4cd34dfac513e01b7b4d77180ea79d447c66ee1 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 12 Nov 2020 17:51:30 +0400 Subject: [PATCH 40/85] format number to hex in getBlockByNumber --- src/eth/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index d00d3be9..1599f259 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -48,7 +48,7 @@ class Eth { }); this.getBlockByNumber = this.buildRequest<[string, boolean?]>({ call: RPC_CALLS.eth_getBlockByNumber, - formatters: [null, inputFormatters.fullTxObjectParam], + formatters: [inputFormatters.numberToHex, inputFormatters.fullTxObjectParam], }); this.getTransactionByHash = this.buildRequest<[string]>({ call: RPC_CALLS.eth_getTransactionByHash, From f17cc11a5cd84735dfbdce8df4725d7435eec357 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 12 Nov 2020 18:06:31 +0400 Subject: [PATCH 41/85] [breaks things]: add types to rpc calls --- src/eth/index.ts | 32 +++++++++++++++++---------- src/types.ts | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index 1599f259..8ef26f6a 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -1,6 +1,14 @@ import { TransactionConfig, PastLogsOptions } from 'web3-core'; import { RPC_CALLS } from '../eth/constants'; -import { RpcCallNames, RequestArgs, Communicator } from './../types'; +import { + RpcCallNames, + RequestArgs, + Communicator, + Log, + BlockTransactionString, + BlockTransactionObject, + Web3TransactionObject, +} from './../types'; import { METHODS } from '../communication/methods'; const inputFormatters = { @@ -23,42 +31,42 @@ class Eth { constructor(communicator: Communicator) { this.#communicator = communicator; - this.call = this.buildRequest<[TransactionConfig, string?]>({ + this.call = this.buildRequest<[TransactionConfig, string?], string>({ call: RPC_CALLS.eth_call, formatters: [null, inputFormatters.defaultBlockParam], }); - this.getBalance = this.buildRequest<[string, string?]>({ + this.getBalance = this.buildRequest<[string, string?], string>({ call: RPC_CALLS.eth_getBalance, formatters: [null, inputFormatters.defaultBlockParam], }); - this.getCode = this.buildRequest<[string, string?]>({ + this.getCode = this.buildRequest<[string, string?], string>({ call: RPC_CALLS.eth_getCode, formatters: [null, inputFormatters.defaultBlockParam], }); - this.getStorageAt = this.buildRequest<[string, number, string?]>({ + this.getStorageAt = this.buildRequest<[string, number, string?], string>({ call: RPC_CALLS.eth_getStorageAt, formatters: [null, inputFormatters.numberToHex, inputFormatters.defaultBlockParam], }); - this.getPastLogs = this.buildRequest<[PastLogsOptions]>({ + this.getPastLogs = this.buildRequest<[PastLogsOptions], Log[]>({ call: RPC_CALLS.eth_getLogs, }); - this.getBlockByHash = this.buildRequest<[string, boolean?]>({ + this.getBlockByHash = this.buildRequest<[string, boolean?], BlockTransactionString | BlockTransactionObject>({ call: RPC_CALLS.eth_getBlockByHash, formatters: [null, inputFormatters.fullTxObjectParam], }); - this.getBlockByNumber = this.buildRequest<[string, boolean?]>({ + this.getBlockByNumber = this.buildRequest<[string, boolean?], BlockTransactionString | BlockTransactionObject>({ call: RPC_CALLS.eth_getBlockByNumber, formatters: [inputFormatters.numberToHex, inputFormatters.fullTxObjectParam], }); - this.getTransactionByHash = this.buildRequest<[string]>({ + this.getTransactionByHash = this.buildRequest<[string], Web3TransactionObject>({ call: RPC_CALLS.eth_getTransactionByHash, }); - this.getTransactionReceipt = this.buildRequest<[string]>({ + this.getTransactionReceipt = this.buildRequest<[string], Web3TransactionObject>({ call: RPC_CALLS.eth_getTransactionReceipt, }); } - private buildRequest

({ + private buildRequest

>({ call, formatters, }: { @@ -66,7 +74,7 @@ class Eth { /* eslint-disable-next-line */ formatters?: (((arg: any) => any) | null)[]; }) { - return async (args: RequestArgs

): Promise> => { + return async (args: RequestArgs

): Promise => { const params = args.params; if (formatters && Array.isArray(params)) { diff --git a/src/types.ts b/src/types.ts index 971c5caa..0835b45b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -223,3 +223,60 @@ export type RequestArgs = { export interface Communicator { send(messageId: M, data: MethodToParams[M]): Promise; } + +export interface Log { + address: string; + data: string; + topics: string[]; + logIndex: number; + transactionIndex: number; + transactionHash: string; + blockHash: string; + blockNumber: number; +} + +export interface BlockHeader { + number: number; + hash: string; + parentHash: string; + nonce: string; + sha3Uncles: string; + logsBloom: string; + transactionRoot: string; + stateRoot: string; + receiptRoot: string; + miner: string; + extraData: string; + gasLimit: number; + gasUsed: number; + timestamp: number | string; +} + +export interface BlockTransactionBase extends BlockHeader { + size: number; + difficulty: number; + totalDifficulty: number; + uncles: string[]; +} + +export interface BlockTransactionObject extends BlockTransactionBase { + transactions: Transaction[]; +} + +export interface BlockTransactionString extends BlockTransactionBase { + transactions: string[]; +} + +export interface Web3TransactionObject { + hash: string; + nonce: number; + blockHash: string | null; + blockNumber: number | null; + transactionIndex: number | null; + from: string; + to: string | null; + value: string; + gasPrice: string; + gas: number; + input: string; +} From 295f7620d7e1c2c4749d9de20831e3eefd0eed15 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 13 Nov 2020 17:34:32 +0400 Subject: [PATCH 42/85] types wip --- src/communication/index.ts | 19 ++++++------------- src/eth/index.ts | 18 +++++++++++++----- src/sdk.ts | 4 ++-- src/txs/index.ts | 9 ++++++--- src/types.ts | 18 ++++++++++++------ 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 81decf80..65b2d5e8 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,18 +1,11 @@ import semver from 'semver'; -import { - InterfaceMessageEvent, - Communicator, - Methods, - MethodToParams, - MethodToResponse, - SDKRequestData, -} from '../types'; +import { InterfaceMessageEvent, Communicator, Methods, SDKRequestData, ErrorResponse } from '../types'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; // eslint-disable-next-line type Callback = (response: any) => void; -class InterfaceCommunicator implements Communicator { +class PostMessageCommunicator implements Communicator { private allowedOrigins: RegExp[] = []; private callbacks = new Map(); sdkVersion: string; @@ -56,10 +49,10 @@ class InterfaceCommunicator implements Communicator { } }; - public send = (method: M, params: MethodToParams[M]): Promise => { + public send = (method: M, params: P): Promise => { const requestId = generateRequestId(); - const message: SDKRequestData = { + const message: SDKRequestData = { method, requestId, params, @@ -71,12 +64,12 @@ class InterfaceCommunicator implements Communicator { } return new Promise((resolve) => { - this.callbacks.set(requestId, (response: MethodToResponse[M]) => { + this.callbacks.set(requestId, (response: R | ErrorResponse) => { resolve(response); }); }); }; } -export default InterfaceCommunicator; +export default PostMessageCommunicator; export * from './methods'; diff --git a/src/eth/index.ts b/src/eth/index.ts index 8ef26f6a..92819b7b 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -8,10 +8,14 @@ import { BlockTransactionString, BlockTransactionObject, Web3TransactionObject, + RPCPayload, } from './../types'; import { METHODS } from '../communication/methods'; -const inputFormatters = { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type Formatter = (arg: any) => any; + +const inputFormatters: Record = { defaultBlockParam: (arg = 'latest') => arg, fullTxObjectParam: (arg = false) => arg, numberToHex: (arg: number) => arg.toString(16), @@ -66,13 +70,13 @@ class Eth { }); } - private buildRequest

>({ + private buildRequest

({ call, formatters, }: { call: RpcCallNames; /* eslint-disable-next-line */ - formatters?: (((arg: any) => any) | null)[]; + formatters?: (Formatter | null)[]; }) { return async (args: RequestArgs

): Promise => { const params = args.params; @@ -85,12 +89,16 @@ class Eth { }); } - const payload = { + const payload: RPCPayload

= { call, params, }; - const response = await this.#communicator.send(METHODS.rpcCall, payload); + const response = await this.#communicator.send<'rpcCall', RPCPayload

, R>(METHODS.rpcCall, payload); + + if (!response.success) { + throw new Error(response.error); + } return response; }; diff --git a/src/sdk.ts b/src/sdk.ts index 28c79343..3cff3ac9 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -24,13 +24,13 @@ class SDK { } private async sendInitializationMessage() { - const response = await this.#communicator.send(METHODS.getEnvInfo, undefined); + const response = await this.#communicator.send<'getEnvInfo', undefined>(METHODS.getEnvInfo, undefined); console.log({ response }); } async getSafeInfo(): Promise { - const response = await this.#communicator.send(METHODS.getSafeInfo, undefined); + const response = await this.#communicator.send<'getSafeInfo', undefined, SafeInfo>(METHODS.getSafeInfo, undefined); return response; } diff --git a/src/txs/index.ts b/src/txs/index.ts index 5e148274..bbcd5bb9 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -1,5 +1,5 @@ import { METHODS } from '../communication/methods'; -import { TxServiceModel, SendTransactionsArgs, Communicator } from '../types'; +import { TxServiceModel, SendTransactionsArgs, Communicator, SendTransactionsResponse } from '../types'; class TXs { #txServiceUrl: string | null = null; @@ -31,7 +31,7 @@ class TXs { } } - async send({ txs, params }: SendTransactionsArgs): Promise> { + async send({ txs, params }: SendTransactionsArgs): Promise { if (!txs || !txs.length) { throw new Error('sendTransactionsWithParams: No transactions were passed'); } @@ -41,7 +41,10 @@ class TXs { params, }; - const response = await this.#communicator.send(METHODS.sendTransactions, messagePayload); + const response = await this.#communicator.send<'sendTransactions', SendTransactionsArgs, SendTransactionsResponse>( + METHODS.sendTransactions, + messagePayload, + ); if (!response.success) { throw new Error(response.error); diff --git a/src/types.ts b/src/types.ts index 0835b45b..a47cc215 100644 --- a/src/types.ts +++ b/src/types.ts @@ -48,6 +48,12 @@ export interface SendTransactionsArgs { txs: Transaction[]; params?: SendTransactionParams; } + +export type SendTransactionsResponse = { + success: true; + safeTxHash: string; +}; + export interface SdkInstance { txs: TXs; eth: Eth; @@ -70,13 +76,13 @@ export interface TxRejectionEvent { export type Methods = keyof typeof METHODS; -export type SDKRequestData = { +export type SDKRequestData = { requestId: RequestId; - params: MethodToParams[Methods]; + params: P; env: { sdkVersion: string; }; - method: Methods; + method: M; }; export type SDKMessageEvent = MessageEvent; @@ -108,9 +114,9 @@ export interface MethodToParams { [METHODS.getSafeInfo]: undefined; } -export type RPCPayload = { +export type RPCPayload

= { call: RpcCallNames; - params: unknown[]; + params: P; }; // copy-pasting all the types below from safe-react makes me think we might want to export them to a package @@ -221,7 +227,7 @@ export type RequestArgs = { }; export interface Communicator { - send(messageId: M, data: MethodToParams[M]): Promise; + send(method: M, params: P): Promise; } export interface Log { From fde32acda0977eac473ea2ec58fa35bad9d773cd Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 15:01:58 +0400 Subject: [PATCH 43/85] types fix --- src/communication/index.ts | 4 ++-- src/types.ts | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 65b2d5e8..ac75e843 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,5 +1,5 @@ import semver from 'semver'; -import { InterfaceMessageEvent, Communicator, Methods, SDKRequestData, ErrorResponse } from '../types'; +import { InterfaceMessageEvent, Communicator, Methods, SDKRequestData, ErrorResponse, SuccessResponse } from '../types'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; // eslint-disable-next-line @@ -64,7 +64,7 @@ class PostMessageCommunicator implements Communicator { } return new Promise((resolve) => { - this.callbacks.set(requestId, (response: R | ErrorResponse) => { + this.callbacks.set(requestId, (response: SuccessResponse | ErrorResponse) => { resolve(response); }); }); diff --git a/src/types.ts b/src/types.ts index a47cc215..82964646 100644 --- a/src/types.ts +++ b/src/types.ts @@ -49,6 +49,10 @@ export interface SendTransactionsArgs { params?: SendTransactionParams; } +export type SuccessResponse = R & { + success: true; +}; + export type SendTransactionsResponse = { success: true; safeTxHash: string; @@ -227,7 +231,7 @@ export type RequestArgs = { }; export interface Communicator { - send(method: M, params: P): Promise; + send(method: M, params: P): Promise | ErrorResponse>; } export interface Log { From 6ad9b45df0583346ab96a0dff348cb2a9f66a34e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 15:06:18 +0400 Subject: [PATCH 44/85] Fix tests compilation --- src/eth/eth.test.ts | 45 +++++++++++++++------------------------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/src/eth/eth.test.ts b/src/eth/eth.test.ts index 7fccc6e2..747325bb 100644 --- a/src/eth/eth.test.ts +++ b/src/eth/eth.test.ts @@ -20,7 +20,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = await sdkInstance.eth.getBalance({ + await sdkInstance.eth.getBalance({ params: [addr, 'pending'], requestId, }); @@ -36,13 +36,12 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); it('Should add `latest` as a default block parameter when one is not passed', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = await sdkInstance.eth.getBalance({ + await sdkInstance.eth.getBalance({ params: [addr], requestId, }); @@ -58,7 +57,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); @@ -66,7 +64,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = await sdkInstance.eth.getCode({ + await sdkInstance.eth.getCode({ params: [addr, 'pending'], requestId, }); @@ -82,13 +80,12 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); it('Should add `latest` as a default block parameter when one is not passed', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = await sdkInstance.eth.getCode({ + await sdkInstance.eth.getCode({ params: [addr], requestId, }); @@ -104,7 +101,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); @@ -112,7 +108,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = await sdkInstance.eth.getStorageAt({ + await sdkInstance.eth.getStorageAt({ params: [addr, 0, 'earliest'], requestId, }); @@ -128,13 +124,12 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); it('Should add `latest` as a default block parameter when one is not passed', async () => { const requestId = '1000'; const addr = '0x0000000000000000000000000000000000000000'; - const request = await sdkInstance.eth.getStorageAt({ + await sdkInstance.eth.getStorageAt({ params: [addr, 0], requestId, }); @@ -150,7 +145,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); @@ -161,7 +155,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', }; - const request = await sdkInstance.eth.call({ + await sdkInstance.eth.call({ params: [config, 'pending'], requestId, }); @@ -177,7 +171,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); it('Should add `latest` as a default block parameter when one is not passed', async () => { @@ -186,7 +179,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', }; - const request = await sdkInstance.eth.call({ + await sdkInstance.eth.call({ params: [config], requestId, }); @@ -202,7 +195,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); }); @@ -217,7 +209,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { toBlock: 'latest', }, ]; - const request = await sdkInstance.eth.getPastLogs({ + await sdkInstance.eth.getPastLogs({ params, requestId, }); @@ -233,7 +225,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); @@ -241,7 +232,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; - const request = await sdkInstance.eth.getBlockByHash({ + await sdkInstance.eth.getBlockByHash({ params: [hash], requestId, }); @@ -257,13 +248,12 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); it('Should respect passed full tx object boolean param', async () => { const requestId = '1000'; const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; - const request = await sdkInstance.eth.getBlockByHash({ + await sdkInstance.eth.getBlockByHash({ params: [hash, true], requestId, }); @@ -279,7 +269,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); @@ -287,7 +276,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const number = '11054275'; - const request = await sdkInstance.eth.getBlockByNumber({ + await sdkInstance.eth.getBlockByNumber({ params: [number], requestId, }); @@ -303,13 +292,12 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); it('Should respect passed full tx object boolean param', async () => { const requestId = '1000'; const number = '11054275'; - const request = await sdkInstance.eth.getBlockByNumber({ + await sdkInstance.eth.getBlockByNumber({ params: [number, true], requestId, }); @@ -325,7 +313,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); @@ -333,7 +320,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const hash = '0x0e6cd6237b4d3e5c3f348b78399f031b527e832bd30924951ba4921cdbf440d7'; - const request = await sdkInstance.eth.getTransactionByHash({ + await sdkInstance.eth.getTransactionByHash({ params: [hash], requestId, }); @@ -349,7 +336,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); @@ -357,7 +343,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should send a valid message to the interface and return a request ID', async () => { const requestId = '1000'; const hash = '0x0e6cd6237b4d3e5c3f348b78399f031b527e832bd30924951ba4921cdbf440d7'; - const request = await sdkInstance.eth.getTransactionReceipt({ + await sdkInstance.eth.getTransactionReceipt({ params: [hash], requestId, }); @@ -373,7 +359,6 @@ describe('Safe Apps SDK Read RPC Requests', () => { }, '*', ); - expect(request.requestId).toEqual(requestId); }); }); }); From 1177986daa4a17332f1d99f4965dc9e5f63add45 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 15:14:14 +0400 Subject: [PATCH 45/85] Fix types --- src/sdk.ts | 4 ++++ src/types.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sdk.ts b/src/sdk.ts index 3cff3ac9..837e5c6a 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -32,6 +32,10 @@ class SDK { async getSafeInfo(): Promise { const response = await this.#communicator.send<'getSafeInfo', undefined, SafeInfo>(METHODS.getSafeInfo, undefined); + if (!response.success) { + throw new Error(response.error); + } + return response; } } diff --git a/src/types.ts b/src/types.ts index 82964646..277c09d3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -80,7 +80,7 @@ export interface TxRejectionEvent { export type Methods = keyof typeof METHODS; -export type SDKRequestData = { +export type SDKRequestData = { requestId: RequestId; params: P; env: { From 80dd9938de7e909f8b4ac27e05b0b399ba30de3c Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 15:32:56 +0400 Subject: [PATCH 46/85] Type updateS --- src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index 277c09d3..213d5723 100644 --- a/src/types.ts +++ b/src/types.ts @@ -80,7 +80,7 @@ export interface TxRejectionEvent { export type Methods = keyof typeof METHODS; -export type SDKRequestData = { +export type SDKRequestData = { requestId: RequestId; params: P; env: { From 9aeb41e3f860ef2dea59c1e8559b22ca1f74a63d Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 16:34:17 +0400 Subject: [PATCH 47/85] types fix --- src/communication/index.ts | 6 +++--- src/sdk.ts | 4 ---- src/types.ts | 18 ++++++++---------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index ac75e843..38b2f5ac 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,5 +1,5 @@ import semver from 'semver'; -import { InterfaceMessageEvent, Communicator, Methods, SDKRequestData, ErrorResponse, SuccessResponse } from '../types'; +import { InterfaceMessageEvent, Communicator, Methods, SDKRequestData } from '../types'; import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; // eslint-disable-next-line @@ -49,7 +49,7 @@ class PostMessageCommunicator implements Communicator { } }; - public send = (method: M, params: P): Promise => { + public send = (method: M, params: P): Promise => { const requestId = generateRequestId(); const message: SDKRequestData = { @@ -64,7 +64,7 @@ class PostMessageCommunicator implements Communicator { } return new Promise((resolve) => { - this.callbacks.set(requestId, (response: SuccessResponse | ErrorResponse) => { + this.callbacks.set(requestId, (response: R) => { resolve(response); }); }); diff --git a/src/sdk.ts b/src/sdk.ts index 837e5c6a..3cff3ac9 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -32,10 +32,6 @@ class SDK { async getSafeInfo(): Promise { const response = await this.#communicator.send<'getSafeInfo', undefined, SafeInfo>(METHODS.getSafeInfo, undefined); - if (!response.success) { - throw new Error(response.error); - } - return response; } } diff --git a/src/types.ts b/src/types.ts index 213d5723..c49c0043 100644 --- a/src/types.ts +++ b/src/types.ts @@ -49,14 +49,12 @@ export interface SendTransactionsArgs { params?: SendTransactionParams; } -export type SuccessResponse = R & { - success: true; -}; - -export type SendTransactionsResponse = { - success: true; - safeTxHash: string; -}; +export type SendTransactionsResponse = + | { + success: true; + safeTxHash: string; + } + | ErrorResponse; export interface SdkInstance { txs: TXs; @@ -98,7 +96,7 @@ export type ErrorResponse = { export type InterfaceResponseData = { requestId: RequestId; - response: MethodToResponse[Methods] | ErrorResponse; + response: MethodToResponse[Methods]; version?: string; }; @@ -231,7 +229,7 @@ export type RequestArgs = { }; export interface Communicator { - send(method: M, params: P): Promise | ErrorResponse>; + send(method: M, params: P): Promise; } export interface Log { From b12cf01bd02f29e428f10bbabf8f9ae2c9d76d6f Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 16:36:48 +0400 Subject: [PATCH 48/85] types fix --- src/eth/index.ts | 4 ---- src/types.ts | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index 92819b7b..74286901 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -96,10 +96,6 @@ class Eth { const response = await this.#communicator.send<'rpcCall', RPCPayload

, R>(METHODS.rpcCall, payload); - if (!response.success) { - throw new Error(response.error); - } - return response; }; } diff --git a/src/types.ts b/src/types.ts index c49c0043..f5442502 100644 --- a/src/types.ts +++ b/src/types.ts @@ -229,7 +229,7 @@ export type RequestArgs = { }; export interface Communicator { - send(method: M, params: P): Promise; + send(method: M, params: P): Promise; } export interface Log { From 969efccdfb21e976243756b0c8790defd42460e0 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 16:37:43 +0400 Subject: [PATCH 49/85] remove eslint comment --- src/eth/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index 74286901..a234e343 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -75,7 +75,6 @@ class Eth { formatters, }: { call: RpcCallNames; - /* eslint-disable-next-line */ formatters?: (Formatter | null)[]; }) { return async (args: RequestArgs

): Promise => { From ed8d0a24d20e232ee988a1d5a8635d788cc6d2f7 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 16:42:35 +0400 Subject: [PATCH 50/85] fix send txs return type --- src/txs/index.ts | 10 ++++++---- src/types.ts | 10 ++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/txs/index.ts b/src/txs/index.ts index bbcd5bb9..6b0593b9 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -1,3 +1,4 @@ +import { ErrorResponse } from './../types'; import { METHODS } from '../communication/methods'; import { TxServiceModel, SendTransactionsArgs, Communicator, SendTransactionsResponse } from '../types'; @@ -41,10 +42,11 @@ class TXs { params, }; - const response = await this.#communicator.send<'sendTransactions', SendTransactionsArgs, SendTransactionsResponse>( - METHODS.sendTransactions, - messagePayload, - ); + const response = await this.#communicator.send< + 'sendTransactions', + SendTransactionsArgs, + SendTransactionsResponse | ErrorResponse + >(METHODS.sendTransactions, messagePayload); if (!response.success) { throw new Error(response.error); diff --git a/src/types.ts b/src/types.ts index f5442502..1652df69 100644 --- a/src/types.ts +++ b/src/types.ts @@ -49,12 +49,10 @@ export interface SendTransactionsArgs { params?: SendTransactionParams; } -export type SendTransactionsResponse = - | { - success: true; - safeTxHash: string; - } - | ErrorResponse; +export type SendTransactionsResponse = { + success: true; + safeTxHash: string; +}; export interface SdkInstance { txs: TXs; From 83e30a952c82903025858e81bb1a71a27030e2a5 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 19:17:43 +0400 Subject: [PATCH 51/85] fix tests for transactions --- src/communication/index.ts | 3 +-- src/sdk.test.ts | 38 ---------------------------------- src/sdk.ts | 4 ++-- src/txs/index.ts | 2 +- src/txs/txs.test.ts | 42 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 46 insertions(+), 43 deletions(-) create mode 100644 src/txs/txs.test.ts diff --git a/src/communication/index.ts b/src/communication/index.ts index 38b2f5ac..ac1854f8 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -31,9 +31,8 @@ class PostMessageCommunicator implements Communicator { }; private onParentMessage = (msg: InterfaceMessageEvent): void => { - this.logIncomingMessage(msg); - if (this.isValidMessage(msg)) { + this.logIncomingMessage(msg); this.handleIncomingMessage(msg.data); } }; diff --git a/src/sdk.test.ts b/src/sdk.test.ts index 74992766..c88c522d 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -1,5 +1,4 @@ import SDK, { SdkInstance } from './index'; -import { METHODS } from './communication/methods'; describe('Safe apps SDK', () => { let sdkInstance: SdkInstance; @@ -15,41 +14,4 @@ describe('Safe apps SDK', () => { expect(sdkInstance.txs.send).not.toBeUndefined(); }); }); - - describe('sendTransactions', () => { - test('Should throw an error when passing an empty array', () => { - expect(() => { - sdkInstance.txs.send({ txs: [] }); - }).toThrow(); - }); - - test('Should call window.parent.postMessage with a requestId when passing array of TXs', () => { - const requestId = '1000'; - const spy = jest.spyOn(window.parent, 'postMessage'); - const txs = [{ to: 'address', value: '0', data: '0x' }]; - sdkInstance.txs.send({ txs }); - expect(spy).toHaveBeenCalledWith( - { messageId: METHODS.sendTransactions, data: { txs, params: undefined }, requestId }, - '*', - ); - }); - - test('Should return a message containing requestId', () => { - const txs = [{ to: 'address', value: '0', data: '0x' }]; - sdkInstance.txs.send({ txs }); - - // expect(typeof request.requestId).toBe('number'); - // expect(request.data).toEqual({ txs }); - }); - - test('Should include passed safeTxGas and requestId params to a message body', () => { - const txs = [{ to: 'address', value: '0', data: '0x' }]; - const params = { safeTxGas: 5000 }; - - sdkInstance.txs.send({ txs, params }); - - // expect(request.requestId).toBe(requestId); - // expect(request.data).toEqual({ txs, params }); - }); - }); }); diff --git a/src/sdk.ts b/src/sdk.ts index 3cff3ac9..a490dee5 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -7,7 +7,7 @@ import pkg from '../package.json'; export const __VERSION__ = pkg.version; -class SDK { +class SafeAppsSDK { #communicator: Communicator; public readonly eth; public readonly txs; @@ -36,4 +36,4 @@ class SDK { } } -export default SDK; +export default SafeAppsSDK; diff --git a/src/txs/index.ts b/src/txs/index.ts index 6b0593b9..ea5afa59 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -34,7 +34,7 @@ class TXs { async send({ txs, params }: SendTransactionsArgs): Promise { if (!txs || !txs.length) { - throw new Error('sendTransactionsWithParams: No transactions were passed'); + throw new Error('No transactions were passed'); } const messagePayload = { diff --git a/src/txs/txs.test.ts b/src/txs/txs.test.ts new file mode 100644 index 00000000..152796b8 --- /dev/null +++ b/src/txs/txs.test.ts @@ -0,0 +1,42 @@ +import SDK from '../index'; +import { METHODS } from '../communication/methods'; + +describe('Safe Apps SDK transaction methods', () => { + const sdkInstance = new SDK([/http:\/\/localhost:3000/]); + /* eslint-disable-next-line */ + let spy: jest.SpyInstance; + + beforeEach(() => { + spy = jest.spyOn(window.parent, 'postMessage'); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('SDK.txs.send', () => { + test('Should throw an error when passing an empty array', async () => { + await expect(sdkInstance.txs.send({ txs: [] })).rejects.toEqual(new Error('No transactions were passed')); + }); + + test('Should call window.parent.postMessage when passing array of TXs', () => { + const txs = [{ to: 'address', value: '0', data: '0x' }]; + sdkInstance.txs.send({ txs }); + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ method: METHODS.sendTransactions, params: { txs, params: undefined } }), + '*', + ); + }); + + test('Should include passed params to a message body', () => { + const txs = [{ to: 'address', value: '0', data: '0x' }]; + const params = { safeTxGas: 5000 }; + + sdkInstance.txs.send({ txs, params }); + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ method: METHODS.sendTransactions, params: { txs, params } }), + '*', + ); + }); + }); +}); From c5b5110277b7e4e98c9eee101c8f7f5adb849a74 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 16 Nov 2020 19:19:28 +0400 Subject: [PATCH 52/85] formatting --- src/txs/txs.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/txs/txs.test.ts b/src/txs/txs.test.ts index 152796b8..5f9a2ec9 100644 --- a/src/txs/txs.test.ts +++ b/src/txs/txs.test.ts @@ -21,6 +21,7 @@ describe('Safe Apps SDK transaction methods', () => { test('Should call window.parent.postMessage when passing array of TXs', () => { const txs = [{ to: 'address', value: '0', data: '0x' }]; + sdkInstance.txs.send({ txs }); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ method: METHODS.sendTransactions, params: { txs, params: undefined } }), From 55df940866c76d5e2519d73ad3243e75ab7af20e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 13:32:12 +0400 Subject: [PATCH 53/85] remove interfaces deployed by gnosis from constructor --- src/communication/index.ts | 2 +- src/communication/utils.ts | 7 +------ src/sdk.ts | 4 ++-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index ac1854f8..84698fa6 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -11,7 +11,7 @@ class PostMessageCommunicator implements Communicator { sdkVersion: string; constructor(allowedOrigins: RegExp[], sdkVersion: string) { - this.allowedOrigins = [...DEFAULT_ALLOWED_ORIGINS, ...allowedOrigins]; + this.allowedOrigins = allowedOrigins; this.sdkVersion = sdkVersion; window.addEventListener('message', this.onParentMessage); diff --git a/src/communication/utils.ts b/src/communication/utils.ts index efe427eb..2ea0d609 100644 --- a/src/communication/utils.ts +++ b/src/communication/utils.ts @@ -6,9 +6,4 @@ const generateRequestId = (): string => { return new Date().getTime().toString(36); }; -const DEFAULT_ALLOWED_ORIGINS = [ - /https:\/\/.*(gnosis-safe\.io|gnosisdev.com)/, // Safe Multisig - /https?:\/\/localhost:\d+/, // Safe Multisig desktop app. -]; - -export { generateRequestId, DEFAULT_ALLOWED_ORIGINS }; +export { generateRequestId }; diff --git a/src/sdk.ts b/src/sdk.ts index a490dee5..83ab26d3 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -12,12 +12,12 @@ class SafeAppsSDK { public readonly eth; public readonly txs; - constructor(safeAppUrlsRegExp: RegExp[] = []) { + constructor(whitelistedDomains: RegExp[] = []) { if (typeof window === 'undefined') { throw new Error('Error initializing the sdk: window is undefined'); } - this.#communicator = new InterfaceCommunicator(safeAppUrlsRegExp, __VERSION__); + this.#communicator = new InterfaceCommunicator(whitelistedDomains, __VERSION__); this.eth = new Eth(this.#communicator); this.txs = new TXs(this.#communicator); this.sendInitializationMessage(); From 160879c245efd7f02c76de5b8ba111de698d506c Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 13:48:09 +0400 Subject: [PATCH 54/85] add log --- src/communication/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/communication/index.ts b/src/communication/index.ts index 84698fa6..77fbfe3f 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -31,6 +31,7 @@ class PostMessageCommunicator implements Communicator { }; private onParentMessage = (msg: InterfaceMessageEvent): void => { + console.log({ msg }); if (this.isValidMessage(msg)) { this.logIncomingMessage(msg); this.handleIncomingMessage(msg.data); From f4c1cbba0e7f473a821984a6d790e9820384710e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 13:49:58 +0400 Subject: [PATCH 55/85] import fix --- src/communication/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 77fbfe3f..8ff73ce4 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,6 +1,6 @@ import semver from 'semver'; import { InterfaceMessageEvent, Communicator, Methods, SDKRequestData } from '../types'; -import { generateRequestId, DEFAULT_ALLOWED_ORIGINS } from './utils'; +import { generateRequestId } from './utils'; // eslint-disable-next-line type Callback = (response: any) => void; From 0e6bdc0de27120deee75e3f654d714226c78e051 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 13:57:14 +0400 Subject: [PATCH 56/85] update message validation to check parent element --- src/communication/index.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 8ff73ce4..27cd2262 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -17,13 +17,13 @@ class PostMessageCommunicator implements Communicator { window.addEventListener('message', this.onParentMessage); } - private isValidMessage = ({ origin, data }: InterfaceMessageEvent): boolean => { + private isValidMessage = ({ origin, data, source }: InterfaceMessageEvent): boolean => { const emptyOrMalformed = !data; - const unknownOrigin = this.allowedOrigins?.find((regExp) => regExp.test(origin)) === undefined; + const sentFromParentEl = source === window.parent; const sameOrigin = origin === window.origin; const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gte(data.version, '1.0.0') : false; - return !emptyOrMalformed && !unknownOrigin && !sameOrigin && allowedSDKVersion; + return !emptyOrMalformed && sentFromParentEl && !sameOrigin && allowedSDKVersion; }; private logIncomingMessage = (msg: InterfaceMessageEvent): void => { @@ -31,7 +31,6 @@ class PostMessageCommunicator implements Communicator { }; private onParentMessage = (msg: InterfaceMessageEvent): void => { - console.log({ msg }); if (this.isValidMessage(msg)) { this.logIncomingMessage(msg); this.handleIncomingMessage(msg.data); From c27c575d752ba723a2a87be23244802f594a629f Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 14:18:09 +0400 Subject: [PATCH 57/85] Check for window existance in communicator's send --- src/communication/index.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 27cd2262..f6cf2339 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -27,7 +27,7 @@ class PostMessageCommunicator implements Communicator { }; private logIncomingMessage = (msg: InterfaceMessageEvent): void => { - console.info(`Safe Apps SDK v2: A message was received from origin ${msg.origin}. `, msg.data); + console.info(`Safe Apps SDK v1: A message was received from origin ${msg.origin}. `, msg.data); }; private onParentMessage = (msg: InterfaceMessageEvent): void => { @@ -58,10 +58,11 @@ class PostMessageCommunicator implements Communicator { env: { sdkVersion: this.sdkVersion }, }; - if (typeof window !== 'undefined') { - window.parent.postMessage(message, '*'); + if (typeof window === 'undefined') { + throw new Error("Window doesn't exist"); } + window.parent.postMessage(message, '*'); return new Promise((resolve) => { this.callbacks.set(requestId, (response: R) => { resolve(response); From 77043e7fc1f9dfef808ff184632ece78af6ea755 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 17:54:28 +0400 Subject: [PATCH 58/85] types fix --- src/eth/index.ts | 28 ++++++++++++++++++---------- src/types.ts | 23 ++++++----------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index a234e343..1e861654 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -9,7 +9,9 @@ import { BlockTransactionObject, Web3TransactionObject, RPCPayload, -} from './../types'; + ErrorResponse, + RpcResponse, +} from '../types'; import { METHODS } from '../communication/methods'; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -21,6 +23,11 @@ const inputFormatters: Record = { numberToHex: (arg: number) => arg.toString(16), }; +type BuildRequestArgs = { + call: RpcCallNames; + formatters?: (Formatter | null)[]; +}; + class Eth { public call; public getBalance; @@ -70,14 +77,8 @@ class Eth { }); } - private buildRequest

({ - call, - formatters, - }: { - call: RpcCallNames; - formatters?: (Formatter | null)[]; - }) { - return async (args: RequestArgs

): Promise => { + private buildRequest

({ call, formatters }: BuildRequestArgs) { + return async (args: RequestArgs

): Promise> => { const params = args.params; if (formatters && Array.isArray(params)) { @@ -93,7 +94,14 @@ class Eth { params, }; - const response = await this.#communicator.send<'rpcCall', RPCPayload

, R>(METHODS.rpcCall, payload); + const response = await this.#communicator.send<'rpcCall', RPCPayload

, RpcResponse | ErrorResponse>( + METHODS.rpcCall, + payload, + ); + + if (!response.success) { + throw new Error(response.error); + } return response; }; diff --git a/src/types.ts b/src/types.ts index 1652df69..30539b8d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -65,15 +65,6 @@ export interface SafeInfo { ethBalance: string; } -export interface TxConfirmationEvent { - requestId: RequestId; - safeTxHash: string; -} - -export interface TxRejectionEvent { - requestId: RequestId; -} - export type Methods = keyof typeof METHODS; export type SDKRequestData = { @@ -103,17 +94,10 @@ export type InterfaceMessageEvent = MessageEvent; export interface MethodToResponse { [METHODS.getEnvInfo]: { txServiceUrl: string }; [METHODS.sendTransactions]: Record; - [METHODS.rpcCall]: Record; + [METHODS.rpcCall]: unknown; [METHODS.getSafeInfo]: SafeInfo; } -export interface MethodToParams { - [METHODS.getEnvInfo]: undefined; - [METHODS.sendTransactions]: SendTransactionsArgs; - [METHODS.rpcCall]: RPCPayload; - [METHODS.getSafeInfo]: undefined; -} - export type RPCPayload

= { call: RpcCallNames; params: P; @@ -226,6 +210,11 @@ export type RequestArgs = { requestId?: RequestId; }; +export type RpcResponse = { + success: true; + data: T; +}; + export interface Communicator { send(method: M, params: P): Promise; } From 08d47ba0e669ca89704a1e690621a90e13efc617 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 18:18:38 +0400 Subject: [PATCH 59/85] Fix rpc response --- src/eth/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index 1e861654..65bcab79 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -78,7 +78,7 @@ class Eth { } private buildRequest

({ call, formatters }: BuildRequestArgs) { - return async (args: RequestArgs

): Promise> => { + return async (args: RequestArgs

): Promise => { const params = args.params; if (formatters && Array.isArray(params)) { @@ -103,7 +103,7 @@ class Eth { throw new Error(response.error); } - return response; + return response.data; }; } } From 7506f8be9e3a3a86195090745aa69fccd4390605 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 19:26:36 +0400 Subject: [PATCH 60/85] add bootstrap function --- src/sdk.ts | 16 +++++++++++----- src/txs/index.ts | 1 + src/types.ts | 6 +++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/sdk.ts b/src/sdk.ts index 83ab26d3..fcdadceb 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -1,5 +1,5 @@ import { METHODS } from './communication/methods'; -import { Communicator, SafeInfo } from './types'; +import { Communicator, SafeInfo, EnvInfo } from './types'; import InterfaceCommunicator from './communication'; import { TXs } from './txs'; import { Eth } from './eth'; @@ -20,13 +20,19 @@ class SafeAppsSDK { this.#communicator = new InterfaceCommunicator(whitelistedDomains, __VERSION__); this.eth = new Eth(this.#communicator); this.txs = new TXs(this.#communicator); - this.sendInitializationMessage(); + this.bootstrap(); } - private async sendInitializationMessage() { - const response = await this.#communicator.send<'getEnvInfo', undefined>(METHODS.getEnvInfo, undefined); + private async bootstrap(): Promise { + const { txServiceUrl } = await this.getEnvInfo(); - console.log({ response }); + this.txs.setTxServiceUrl(txServiceUrl); + } + + private async getEnvInfo(): Promise { + const response = await this.#communicator.send<'getEnvInfo', undefined, EnvInfo>(METHODS.getEnvInfo, undefined); + + return response; } async getSafeInfo(): Promise { diff --git a/src/txs/index.ts b/src/txs/index.ts index ea5afa59..6491b338 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -56,6 +56,7 @@ class TXs { } public setTxServiceUrl(url: string): void { + console.log('Setting tx service url: ', this.#txServiceUrl); this.#txServiceUrl = url; } } diff --git a/src/types.ts b/src/types.ts index 30539b8d..18e1da34 100644 --- a/src/types.ts +++ b/src/types.ts @@ -91,8 +91,12 @@ export type InterfaceResponseData = { export type InterfaceMessageEvent = MessageEvent; +export type EnvInfo = { + txServiceUrl: string; +}; + export interface MethodToResponse { - [METHODS.getEnvInfo]: { txServiceUrl: string }; + [METHODS.getEnvInfo]: EnvInfo; [METHODS.sendTransactions]: Record; [METHODS.rpcCall]: unknown; [METHODS.getSafeInfo]: SafeInfo; From ac60622c450c1d29ce3981a4f4b120370f67da6d Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 19:34:48 +0400 Subject: [PATCH 61/85] remove log --- src/txs/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/txs/index.ts b/src/txs/index.ts index 6491b338..ea5afa59 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -56,7 +56,6 @@ class TXs { } public setTxServiceUrl(url: string): void { - console.log('Setting tx service url: ', this.#txServiceUrl); this.#txServiceUrl = url; } } From e7c85ed44418f55ca438f717ac676e1db860e412 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 17 Nov 2020 19:44:22 +0400 Subject: [PATCH 62/85] add a test that checks getEnvInfo is called on init --- src/sdk.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/sdk.test.ts b/src/sdk.test.ts index c88c522d..96ee15d5 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -10,8 +10,20 @@ describe('Safe apps SDK', () => { }); test('Should initialize without regExp', () => { - sdkInstance = new SDK([/http:\/\/localhost:3000/]); + sdkInstance = new SDK([]); expect(sdkInstance.txs.send).not.toBeUndefined(); }); + + test("should send a getEnvInfo message to obtain information about interface's env", () => { + const spy = jest.spyOn(window.parent, 'postMessage'); + sdkInstance = new SDK([]); + + expect(spy).toHaveBeenCalledWith( + expect.objectContaining({ + method: 'getEnvInfo', + }), + '*', + ); + }); }); }); From 2e98395d5b15000cc2024092a7609c90c050793a Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 18 Nov 2020 15:48:04 +0400 Subject: [PATCH 63/85] add functions for generating requests/responses --- src/communication/index.ts | 26 +++++++++------------- src/communication/messageFormatter.ts | 32 +++++++++++++++++++++++++++ src/sdk.ts | 5 +---- src/types.ts | 9 ++++---- src/utils.ts | 3 +++ 5 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 src/communication/messageFormatter.ts create mode 100644 src/utils.ts diff --git a/src/communication/index.ts b/src/communication/index.ts index f6cf2339..da742bcf 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,18 +1,17 @@ import semver from 'semver'; import { InterfaceMessageEvent, Communicator, Methods, SDKRequestData } from '../types'; +import { MessageFormatter } from './messageFormatter'; import { generateRequestId } from './utils'; // eslint-disable-next-line type Callback = (response: any) => void; class PostMessageCommunicator implements Communicator { - private allowedOrigins: RegExp[] = []; + private allowedOrigins: RegExp[] | null = null; private callbacks = new Map(); - sdkVersion: string; - constructor(allowedOrigins: RegExp[], sdkVersion: string) { + constructor(allowedOrigins: RegExp[]) { this.allowedOrigins = allowedOrigins; - this.sdkVersion = sdkVersion; window.addEventListener('message', this.onParentMessage); } @@ -22,8 +21,12 @@ class PostMessageCommunicator implements Communicator { const sentFromParentEl = source === window.parent; const sameOrigin = origin === window.origin; const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gte(data.version, '1.0.0') : false; + let validOrigin = true; + if (Array.isArray(this.allowedOrigins)) { + validOrigin = this.allowedOrigins.find((regExp) => regExp.test(origin)) === undefined; + } - return !emptyOrMalformed && sentFromParentEl && !sameOrigin && allowedSDKVersion; + return !emptyOrMalformed && sentFromParentEl && !sameOrigin && allowedSDKVersion && validOrigin; }; private logIncomingMessage = (msg: InterfaceMessageEvent): void => { @@ -49,22 +52,15 @@ class PostMessageCommunicator implements Communicator { }; public send = (method: M, params: P): Promise => { - const requestId = generateRequestId(); - - const message: SDKRequestData = { - method, - requestId, - params, - env: { sdkVersion: this.sdkVersion }, - }; + const request = MessageFormatter.makeRequest(method, params); if (typeof window === 'undefined') { throw new Error("Window doesn't exist"); } - window.parent.postMessage(message, '*'); + window.parent.postMessage(request, '*'); return new Promise((resolve) => { - this.callbacks.set(requestId, (response: R) => { + this.callbacks.set(request.id, (response: R) => { resolve(response); }); }); diff --git a/src/communication/messageFormatter.ts b/src/communication/messageFormatter.ts new file mode 100644 index 00000000..5776a9c3 --- /dev/null +++ b/src/communication/messageFormatter.ts @@ -0,0 +1,32 @@ +import { ErrorResponse, SDKRequestData, Methods, RequestId, InterfaceResponseData, MethodToResponse } from '../types'; +import { generateRequestId } from './utils'; +import { getSDKVersion } from '../utils'; + +class MessageFormatter { + static makeRequest = (method: M, params: P): SDKRequestData => { + const id = generateRequestId(); + + return { + id, + method, + params, + env: { + sdkVersion: getSDKVersion(), + }, + }; + }; + + static makeResponse = (id: RequestId, response: MethodToResponse[Methods], version: string): InterfaceResponse => ({ + id, + success: true, + version, + response, + }); + + static makeErrorResponse = (error: string): ErrorResponse => ({ + success: false, + error, + }); +} + +export { MessageFormatter }; diff --git a/src/sdk.ts b/src/sdk.ts index fcdadceb..cedfe5db 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -3,9 +3,6 @@ import { Communicator, SafeInfo, EnvInfo } from './types'; import InterfaceCommunicator from './communication'; import { TXs } from './txs'; import { Eth } from './eth'; -import pkg from '../package.json'; - -export const __VERSION__ = pkg.version; class SafeAppsSDK { #communicator: Communicator; @@ -17,7 +14,7 @@ class SafeAppsSDK { throw new Error('Error initializing the sdk: window is undefined'); } - this.#communicator = new InterfaceCommunicator(whitelistedDomains, __VERSION__); + this.#communicator = new InterfaceCommunicator(whitelistedDomains); this.eth = new Eth(this.#communicator); this.txs = new TXs(this.#communicator); this.bootstrap(); diff --git a/src/types.ts b/src/types.ts index 18e1da34..784b5095 100644 --- a/src/types.ts +++ b/src/types.ts @@ -68,7 +68,7 @@ export interface SafeInfo { export type Methods = keyof typeof METHODS; export type SDKRequestData = { - requestId: RequestId; + id: RequestId; params: P; env: { sdkVersion: string; @@ -83,13 +83,14 @@ export type ErrorResponse = { error: string; }; -export type InterfaceResponseData = { - requestId: RequestId; +export type InterfaceResponse = { + id: RequestId; response: MethodToResponse[Methods]; version?: string; + success: true; }; -export type InterfaceMessageEvent = MessageEvent; +export type InterfaceMessageEvent = MessageEvent; export type EnvInfo = { txServiceUrl: string; diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 00000000..d0a4d518 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,3 @@ +import pkg from '../package.json'; + +export const getSDKVersion = (): string => pkg.version; From 4119efac80a02f62b572b8b3f951144ab5626bc8 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 18 Nov 2020 16:05:37 +0400 Subject: [PATCH 64/85] import fix --- src/communication/messageFormatter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/communication/messageFormatter.ts b/src/communication/messageFormatter.ts index 5776a9c3..56d0faed 100644 --- a/src/communication/messageFormatter.ts +++ b/src/communication/messageFormatter.ts @@ -1,4 +1,4 @@ -import { ErrorResponse, SDKRequestData, Methods, RequestId, InterfaceResponseData, MethodToResponse } from '../types'; +import { ErrorResponse, SDKRequestData, Methods, RequestId, InterfaceResponse, MethodToResponse } from '../types'; import { generateRequestId } from './utils'; import { getSDKVersion } from '../utils'; From f3da4dcca3763a49301ba5f51f625c6a505730f5 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 18 Nov 2020 16:20:07 +0400 Subject: [PATCH 65/85] import fix --- src/communication/index.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index da742bcf..2285f6a1 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,7 +1,6 @@ import semver from 'semver'; -import { InterfaceMessageEvent, Communicator, Methods, SDKRequestData } from '../types'; +import { InterfaceMessageEvent, Communicator, Methods } from '../types'; import { MessageFormatter } from './messageFormatter'; -import { generateRequestId } from './utils'; // eslint-disable-next-line type Callback = (response: any) => void; @@ -41,13 +40,13 @@ class PostMessageCommunicator implements Communicator { }; private handleIncomingMessage = (payload: InterfaceMessageEvent['data']): void => { - const { requestId } = payload; + const { id } = payload; - const cb = this.callbacks.get(requestId); + const cb = this.callbacks.get(id); if (cb) { cb(payload.response); - this.callbacks.delete(requestId); + this.callbacks.delete(id); } }; From 135a38bb080d8fa0fc6c9953073b950e0f44cc85 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 18 Nov 2020 16:39:49 +0400 Subject: [PATCH 66/85] add export --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index 220d077f..9b4e5a0e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,3 +4,4 @@ export default SDK; export * from './sdk'; export * from './types'; export * from './communication/methods'; +export { getSDKVersion } from './utils'; From 3936afd63918548690f6fa43caade1a4e390cdf0 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 18 Nov 2020 18:45:08 +0400 Subject: [PATCH 67/85] Add export for formatter --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index 9b4e5a0e..ffa8dbfb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,4 +4,5 @@ export default SDK; export * from './sdk'; export * from './types'; export * from './communication/methods'; +export * from './communication/messageFormatter'; export { getSDKVersion } from './utils'; From cab5e96641e3d807801e256c968e6ca7cb6d86aa Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 18 Nov 2020 18:53:02 +0400 Subject: [PATCH 68/85] fix make error response --- src/communication/messageFormatter.ts | 3 ++- src/types.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/communication/messageFormatter.ts b/src/communication/messageFormatter.ts index 56d0faed..7a64ed96 100644 --- a/src/communication/messageFormatter.ts +++ b/src/communication/messageFormatter.ts @@ -23,7 +23,8 @@ class MessageFormatter { response, }); - static makeErrorResponse = (error: string): ErrorResponse => ({ + static makeErrorResponse = (id: RequestId, error: string): ErrorResponse => ({ + id, success: false, error, }); diff --git a/src/types.ts b/src/types.ts index 784b5095..1fba36fd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -79,6 +79,7 @@ export type SDKRequestData = { export type SDKMessageEvent = MessageEvent; export type ErrorResponse = { + id: RequestId; success: false; error: string; }; From fdbd86f2de54e7fe79e486561893d67644bc9fd3 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 19 Nov 2020 12:34:52 +0400 Subject: [PATCH 69/85] dep bump --- package.json | 6 ++-- yarn.lock | 90 ++++++++++++++++++++++++++-------------------------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index 49d20bed..59f5ba2e 100644 --- a/package.json +++ b/package.json @@ -28,10 +28,10 @@ }, "devDependencies": { "@types/jest": "^26.0.15", - "@types/node": "^14.14.7", + "@types/node": "^14.14.8", "@types/semver": "^7.3.4", - "@typescript-eslint/eslint-plugin": "^4.7.0", - "@typescript-eslint/parser": "^4.7.0", + "@typescript-eslint/eslint-plugin": "^4.8.1", + "@typescript-eslint/parser": "^4.8.1", "eslint": "^7.13.0", "eslint-config-prettier": "^6.15.0", "eslint-plugin-prettier": "^3.1.4", diff --git a/yarn.lock b/yarn.lock index 93effe0e..259c77b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -813,10 +813,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.0.tgz#a0f841c195bdbe0b5070da9278b3e22189e8c8f6" integrity sha512-4BVAE9yp5DU3ISqBInsaRp9J474HWNaNVs8eZ1Far3dI1MwS3Wk0EvBRMM4xBh3Oz+c05hUgJmcbtAVmG8bv7w== -"@types/node@^14.14.7": - version "14.14.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d" - integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg== +"@types/node@^14.14.8": + version "14.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.8.tgz#2127bd81949a95c8b7d3240f3254352d72563aec" + integrity sha512-z/5Yd59dCKI5kbxauAJgw6dLPzW+TNOItNE00PkpzNwUIEwdj/Lsqwq94H5DdYBX7C13aRA0CY32BK76+neEUA== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -855,61 +855,61 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.7.0.tgz#85c9bbda00c0cb604d3c241f7bc7fb171a2d3479" - integrity sha512-li9aiSVBBd7kU5VlQlT1AqP0uWGDK6JYKUQ9cVDnOg34VNnd9t4jr0Yqc/bKxJr/tDCPDaB4KzoSFN9fgVxe/Q== +"@typescript-eslint/eslint-plugin@^4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.8.1.tgz#b362abe0ee478a6c6d06c14552a6497f0b480769" + integrity sha512-d7LeQ7dbUrIv5YVFNzGgaW3IQKMmnmKFneRWagRlGYOSfLJVaRbj/FrBNOBC1a3tVO+TgNq1GbHvRtg1kwL0FQ== dependencies: - "@typescript-eslint/experimental-utils" "4.7.0" - "@typescript-eslint/scope-manager" "4.7.0" + "@typescript-eslint/experimental-utils" "4.8.1" + "@typescript-eslint/scope-manager" "4.8.1" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.7.0.tgz#8d1058c38bec3d3bbd9c898a1c32318d80faf3c5" - integrity sha512-cymzovXAiD4EF+YoHAB5Oh02MpnXjvyaOb+v+BdpY7lsJXZQN34oIETeUwVT2XfV9rSNpXaIcknDLfupO/tUoA== +"@typescript-eslint/experimental-utils@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.8.1.tgz#27275c20fa4336df99ebcf6195f7d7aa7aa9f22d" + integrity sha512-WigyLn144R3+lGATXW4nNcDJ9JlTkG8YdBWHkDlN0lC3gUGtDi7Pe3h5GPvFKMcRz8KbZpm9FJV9NTW8CpRHpg== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.7.0" - "@typescript-eslint/types" "4.7.0" - "@typescript-eslint/typescript-estree" "4.7.0" + "@typescript-eslint/scope-manager" "4.8.1" + "@typescript-eslint/types" "4.8.1" + "@typescript-eslint/typescript-estree" "4.8.1" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.7.0.tgz#44bdab0f788b478178368baa65d3365fdc63da1c" - integrity sha512-+meGV8bMP1sJHBI2AFq1GeTwofcGiur8LoIr6v+rEmD9knyCqDlrQcFHR0KDDfldHIFDU/enZ53fla6ReF4wRw== +"@typescript-eslint/parser@^4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.8.1.tgz#4fe2fbdbb67485bafc4320b3ae91e34efe1219d1" + integrity sha512-QND8XSVetATHK9y2Ltc/XBl5Ro7Y62YuZKnPEwnNPB8E379fDsvzJ1dMJ46fg/VOmk0hXhatc+GXs5MaXuL5Uw== dependencies: - "@typescript-eslint/scope-manager" "4.7.0" - "@typescript-eslint/types" "4.7.0" - "@typescript-eslint/typescript-estree" "4.7.0" + "@typescript-eslint/scope-manager" "4.8.1" + "@typescript-eslint/types" "4.8.1" + "@typescript-eslint/typescript-estree" "4.8.1" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.7.0.tgz#2115526085fb72723ccdc1eeae75dec7126220ed" - integrity sha512-ILITvqwDJYbcDCROj6+Ob0oCKNg3SH46iWcNcTIT9B5aiVssoTYkhKjxOMNzR1F7WSJkik4zmuqve5MdnA0DyA== +"@typescript-eslint/scope-manager@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.8.1.tgz#e343c475f8f1d15801b546cb17d7f309b768fdce" + integrity sha512-r0iUOc41KFFbZdPAdCS4K1mXivnSZqXS5D9oW+iykQsRlTbQRfuFRSW20xKDdYiaCoH+SkSLeIF484g3kWzwOQ== dependencies: - "@typescript-eslint/types" "4.7.0" - "@typescript-eslint/visitor-keys" "4.7.0" + "@typescript-eslint/types" "4.8.1" + "@typescript-eslint/visitor-keys" "4.8.1" -"@typescript-eslint/types@4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.7.0.tgz#5e95ef5c740f43d942542b35811f87b62fccca69" - integrity sha512-uLszFe0wExJc+I7q0Z/+BnP7wao/kzX0hB5vJn4LIgrfrMLgnB2UXoReV19lkJQS1a1mHWGGODSxnBx6JQC3Sg== +"@typescript-eslint/types@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.8.1.tgz#23829c73c5fc6f4fcd5346a7780b274f72fee222" + integrity sha512-ave2a18x2Y25q5K05K/U3JQIe2Av4+TNi/2YuzyaXLAsDx6UZkz1boZ7nR/N6Wwae2PpudTZmHFXqu7faXfHmA== -"@typescript-eslint/typescript-estree@4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.7.0.tgz#539531167f05ba20eb0b6785567076679e29d393" - integrity sha512-5XZRQznD1MfUmxu1t8/j2Af4OxbA7EFU2rbo0No7meb46eHgGkSieFdfV6omiC/DGIBhH9H9gXn7okBbVOm8jw== +"@typescript-eslint/typescript-estree@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.8.1.tgz#7307e3f2c9e95df7daa8dc0a34b8c43b7ec0dd32" + integrity sha512-bJ6Fn/6tW2g7WIkCWh3QRlaSU7CdUUK52shx36/J7T5oTQzANvi6raoTsbwGM11+7eBbeem8hCCKbyvAc0X3sQ== dependencies: - "@typescript-eslint/types" "4.7.0" - "@typescript-eslint/visitor-keys" "4.7.0" + "@typescript-eslint/types" "4.8.1" + "@typescript-eslint/visitor-keys" "4.8.1" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" @@ -917,12 +917,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.7.0": - version "4.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.7.0.tgz#6783824f22acfc49e754970ed21b88ac03b80e6f" - integrity sha512-aDJDWuCRsf1lXOtignlfiPODkzSxxop7D0rZ91L6ZuMlcMCSh0YyK+gAfo5zN/ih6WxMwhoXgJWC3cWQdaKC+A== +"@typescript-eslint/visitor-keys@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.8.1.tgz#794f68ee292d1b2e3aa9690ebedfcb3a8c90e3c3" + integrity sha512-3nrwXFdEYALQh/zW8rFwP4QltqsanCDz4CwWMPiIZmwlk9GlvBeueEIbq05SEq4ganqM0g9nh02xXgv5XI3PeQ== dependencies: - "@typescript-eslint/types" "4.7.0" + "@typescript-eslint/types" "4.8.1" eslint-visitor-keys "^2.0.0" abab@^2.0.3: From 491f5dfab1bc118d7741eaf11017d9aa45dee4a9 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 19 Nov 2020 13:37:35 +0400 Subject: [PATCH 70/85] Add version to error response --- src/communication/messageFormatter.ts | 3 ++- src/types.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/communication/messageFormatter.ts b/src/communication/messageFormatter.ts index 7a64ed96..41d1f44b 100644 --- a/src/communication/messageFormatter.ts +++ b/src/communication/messageFormatter.ts @@ -23,10 +23,11 @@ class MessageFormatter { response, }); - static makeErrorResponse = (id: RequestId, error: string): ErrorResponse => ({ + static makeErrorResponse = (id: RequestId, error: string, version: string): ErrorResponse => ({ id, success: false, error, + version, }); } diff --git a/src/types.ts b/src/types.ts index 1fba36fd..cd335caa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -82,6 +82,7 @@ export type ErrorResponse = { id: RequestId; success: false; error: string; + version?: string; }; export type InterfaceResponse = { From 54ca2a473623e2a491f51b56a45b4594aa1c06a3 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 19 Nov 2020 13:51:10 +0400 Subject: [PATCH 71/85] resolve whole data object, not only response key --- src/communication/index.ts | 2 +- src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 2285f6a1..7dbcc3d4 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -44,7 +44,7 @@ class PostMessageCommunicator implements Communicator { const cb = this.callbacks.get(id); if (cb) { - cb(payload.response); + cb(payload); this.callbacks.delete(id); } diff --git a/src/types.ts b/src/types.ts index cd335caa..47f1d772 100644 --- a/src/types.ts +++ b/src/types.ts @@ -92,7 +92,7 @@ export type InterfaceResponse = { success: true; }; -export type InterfaceMessageEvent = MessageEvent; +export type InterfaceMessageEvent = MessageEvent; export type EnvInfo = { txServiceUrl: string; From 1f371c592a2e1ee0e3f5514494ca7bd1df145644 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 19 Nov 2020 15:33:53 +0400 Subject: [PATCH 72/85] Update types --- src/communication/index.ts | 6 +++--- src/communication/messageFormatter.ts | 6 +++--- src/eth/index.ts | 7 +------ src/sdk.ts | 12 ++++++++++-- src/types.ts | 15 ++++++--------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 7dbcc3d4..e88464ee 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -1,5 +1,5 @@ import semver from 'semver'; -import { InterfaceMessageEvent, Communicator, Methods } from '../types'; +import { InterfaceMessageEvent, Communicator, Methods, Response } from '../types'; import { MessageFormatter } from './messageFormatter'; // eslint-disable-next-line @@ -50,7 +50,7 @@ class PostMessageCommunicator implements Communicator { } }; - public send = (method: M, params: P): Promise => { + public send = (method: M, params: P): Promise> => { const request = MessageFormatter.makeRequest(method, params); if (typeof window === 'undefined') { @@ -59,7 +59,7 @@ class PostMessageCommunicator implements Communicator { window.parent.postMessage(request, '*'); return new Promise((resolve) => { - this.callbacks.set(request.id, (response: R) => { + this.callbacks.set(request.id, (response: Response) => { resolve(response); }); }); diff --git a/src/communication/messageFormatter.ts b/src/communication/messageFormatter.ts index 41d1f44b..04df22c0 100644 --- a/src/communication/messageFormatter.ts +++ b/src/communication/messageFormatter.ts @@ -1,4 +1,4 @@ -import { ErrorResponse, SDKRequestData, Methods, RequestId, InterfaceResponse, MethodToResponse } from '../types'; +import { ErrorResponse, SDKRequestData, Methods, RequestId, SuccessResponse, MethodToResponse } from '../types'; import { generateRequestId } from './utils'; import { getSDKVersion } from '../utils'; @@ -16,11 +16,11 @@ class MessageFormatter { }; }; - static makeResponse = (id: RequestId, response: MethodToResponse[Methods], version: string): InterfaceResponse => ({ + static makeResponse = (id: RequestId, data: MethodToResponse[Methods], version: string): SuccessResponse => ({ id, success: true, version, - response, + data, }); static makeErrorResponse = (id: RequestId, error: string, version: string): ErrorResponse => ({ diff --git a/src/eth/index.ts b/src/eth/index.ts index 65bcab79..a7f3347e 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -9,8 +9,6 @@ import { BlockTransactionObject, Web3TransactionObject, RPCPayload, - ErrorResponse, - RpcResponse, } from '../types'; import { METHODS } from '../communication/methods'; @@ -94,10 +92,7 @@ class Eth { params, }; - const response = await this.#communicator.send<'rpcCall', RPCPayload

, RpcResponse | ErrorResponse>( - METHODS.rpcCall, - payload, - ); + const response = await this.#communicator.send<'rpcCall', RPCPayload

, R>(METHODS.rpcCall, payload); if (!response.success) { throw new Error(response.error); diff --git a/src/sdk.ts b/src/sdk.ts index cedfe5db..e1605f4d 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -29,13 +29,21 @@ class SafeAppsSDK { private async getEnvInfo(): Promise { const response = await this.#communicator.send<'getEnvInfo', undefined, EnvInfo>(METHODS.getEnvInfo, undefined); - return response; + if (!response.success) { + throw new Error(response.error); + } + + return response.data; } async getSafeInfo(): Promise { const response = await this.#communicator.send<'getSafeInfo', undefined, SafeInfo>(METHODS.getSafeInfo, undefined); - return response; + if (!response.success) { + throw new Error(response.error); + } + + return response.data; } } diff --git a/src/types.ts b/src/types.ts index 47f1d772..8cf6d5f1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -85,14 +85,16 @@ export type ErrorResponse = { version?: string; }; -export type InterfaceResponse = { +export type SuccessResponse = { id: RequestId; - response: MethodToResponse[Methods]; + data: T; version?: string; success: true; }; -export type InterfaceMessageEvent = MessageEvent; +export type Response = ErrorResponse | SuccessResponse; + +export type InterfaceMessageEvent = MessageEvent; export type EnvInfo = { txServiceUrl: string; @@ -217,13 +219,8 @@ export type RequestArgs = { requestId?: RequestId; }; -export type RpcResponse = { - success: true; - data: T; -}; - export interface Communicator { - send(method: M, params: P): Promise; + send(method: M, params: P): Promise>; } export interface Log { From 3e32a4df84acf64f5718f21f10c6efccabe0536f Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 19 Nov 2020 15:37:31 +0400 Subject: [PATCH 73/85] fix txs.send method --- src/txs/index.ts | 11 +++++------ src/types.ts | 1 - 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/txs/index.ts b/src/txs/index.ts index ea5afa59..ea72cce4 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -42,17 +42,16 @@ class TXs { params, }; - const response = await this.#communicator.send< - 'sendTransactions', - SendTransactionsArgs, - SendTransactionsResponse | ErrorResponse - >(METHODS.sendTransactions, messagePayload); + const response = await this.#communicator.send<'sendTransactions', SendTransactionsArgs, SendTransactionsResponse>( + METHODS.sendTransactions, + messagePayload, + ); if (!response.success) { throw new Error(response.error); } - return response; + return response.data; } public setTxServiceUrl(url: string): void { diff --git a/src/types.ts b/src/types.ts index 8cf6d5f1..067147e0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -50,7 +50,6 @@ export interface SendTransactionsArgs { } export type SendTransactionsResponse = { - success: true; safeTxHash: string; }; From 8cf9681f9edbcda0c081d613cbda69203838953c Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 19 Nov 2020 17:49:52 +0400 Subject: [PATCH 74/85] fix types & hex formatter --- src/eth/eth.test.ts | 235 ++++++++++++++++++-------------------------- src/eth/index.ts | 6 +- 2 files changed, 98 insertions(+), 143 deletions(-) diff --git a/src/eth/eth.test.ts b/src/eth/eth.test.ts index 747325bb..047be53b 100644 --- a/src/eth/eth.test.ts +++ b/src/eth/eth.test.ts @@ -17,182 +17,158 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('Methods requiring default block param', () => { describe('getBalance', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; + it('Should send a valid message to the interface', () => { const addr = '0x0000000000000000000000000000000000000000'; - await sdkInstance.eth.getBalance({ + sdkInstance.eth.getBalance({ params: [addr, 'pending'], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getBalance', params: [addr, 'pending'], }, - requestId, - }, + }), '*', ); }); - it('Should add `latest` as a default block parameter when one is not passed', async () => { - const requestId = '1000'; + it('Should add `latest` as a default block parameter when one is not passed', () => { const addr = '0x0000000000000000000000000000000000000000'; - await sdkInstance.eth.getBalance({ + sdkInstance.eth.getBalance({ params: [addr], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getBalance', params: [addr, 'latest'], }, - requestId, - }, + }), '*', ); }); }); describe('getCode', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; + it('Should send a valid message to the interface', () => { const addr = '0x0000000000000000000000000000000000000000'; - await sdkInstance.eth.getCode({ + sdkInstance.eth.getCode({ params: [addr, 'pending'], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getCode', params: [addr, 'pending'], }, - requestId, - }, + }), '*', ); }); - it('Should add `latest` as a default block parameter when one is not passed', async () => { - const requestId = '1000'; + it('Should add `latest` as a default block parameter when one is not passed', () => { const addr = '0x0000000000000000000000000000000000000000'; - await sdkInstance.eth.getCode({ + sdkInstance.eth.getCode({ params: [addr], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getCode', params: [addr, 'latest'], }, - requestId, - }, + }), '*', ); }); }); describe('getStorageAt', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; + it('Should send a valid message to the interface', () => { const addr = '0x0000000000000000000000000000000000000000'; - await sdkInstance.eth.getStorageAt({ + sdkInstance.eth.getStorageAt({ params: [addr, 0, 'earliest'], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getStorageAt', params: [addr, '0x0', 'earliest'], }, - requestId, - }, + }), '*', ); }); - it('Should add `latest` as a default block parameter when one is not passed', async () => { - const requestId = '1000'; + it('Should add `latest` as a default block parameter when one is not passed', () => { const addr = '0x0000000000000000000000000000000000000000'; - await sdkInstance.eth.getStorageAt({ + sdkInstance.eth.getStorageAt({ params: [addr, 0], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getStorageAt', - params: [addr, 0, 'latest'], + params: [addr, '0x0', 'latest'], }, - requestId, - }, + }), '*', ); }); }); describe('call', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; + it('Should send a valid message to the interface', () => { const config: TransactionConfig = { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', }; - await sdkInstance.eth.call({ + sdkInstance.eth.call({ params: [config, 'pending'], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_call', params: [config, 'pending'], }, - requestId, - }, + }), '*', ); }); - it('Should add `latest` as a default block parameter when one is not passed', async () => { - const requestId = '1000'; + it('Should add `latest` as a default block parameter when one is not passed', () => { const config: TransactionConfig = { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', }; - await sdkInstance.eth.call({ + sdkInstance.eth.call({ params: [config], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_call', params: [config, 'latest'], }, - requestId, - }, + }), '*', ); }); @@ -200,8 +176,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { }); describe('getPastLogs', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; + it('Should send a valid message to the interface', () => { const number = 11054275; const params: [PastLogsOptions] = [ { @@ -209,154 +184,134 @@ describe('Safe Apps SDK Read RPC Requests', () => { toBlock: 'latest', }, ]; - await sdkInstance.eth.getPastLogs({ + sdkInstance.eth.getPastLogs({ params, - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getLogs', params, }, - requestId, - }, + }), '*', ); }); }); describe('getBlockByHash', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; + it('Should send a valid message to the interface', () => { const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; - await sdkInstance.eth.getBlockByHash({ + sdkInstance.eth.getBlockByHash({ params: [hash], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getBlockByHash', params: [hash, false], }, - requestId, - }, + }), '*', ); }); - it('Should respect passed full tx object boolean param', async () => { - const requestId = '1000'; + it('Should respect passed full tx object boolean param', () => { const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; - await sdkInstance.eth.getBlockByHash({ + sdkInstance.eth.getBlockByHash({ params: [hash, true], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getBlockByHash', params: [hash, true], }, - requestId, - }, + }), '*', ); }); }); describe('getBlockByNumber', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; - const number = '11054275'; - await sdkInstance.eth.getBlockByNumber({ + it('Should send a valid message to the interface', () => { + const number = 11054275; + sdkInstance.eth.getBlockByNumber({ params: [number], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getBlockByNumber', - params: [number, false], + params: ['0xa8acc3', false], }, - requestId, - }, + }), '*', ); }); - it('Should respect passed full tx object boolean param', async () => { - const requestId = '1000'; - const number = '11054275'; - await sdkInstance.eth.getBlockByNumber({ + it('Should respect passed full tx object boolean param', () => { + const number = 11054275; + sdkInstance.eth.getBlockByNumber({ params: [number, true], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getBlockByNumber', - params: [number, true], + params: ['0xa8acc3', true], }, - requestId, - }, + }), '*', ); }); }); describe('getTransactionByHash', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; + it('Should send a valid message to the interface', () => { const hash = '0x0e6cd6237b4d3e5c3f348b78399f031b527e832bd30924951ba4921cdbf440d7'; - await sdkInstance.eth.getTransactionByHash({ + sdkInstance.eth.getTransactionByHash({ params: [hash], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getTransactionByHash', params: [hash], }, - requestId, - }, + }), '*', ); }); }); describe('getTransactionReceipt', () => { - it('Should send a valid message to the interface and return a request ID', async () => { - const requestId = '1000'; + it('Should send a valid message to the interface', () => { const hash = '0x0e6cd6237b4d3e5c3f348b78399f031b527e832bd30924951ba4921cdbf440d7'; - await sdkInstance.eth.getTransactionReceipt({ + sdkInstance.eth.getTransactionReceipt({ params: [hash], - requestId, }); expect(spy).toHaveBeenCalledWith( - { - messageId: METHODS.rpcCall, - data: { + expect.objectContaining({ + method: METHODS.rpcCall, + params: { call: 'eth_getTransactionReceipt', params: [hash], }, - requestId, - }, + }), '*', ); }); diff --git a/src/eth/index.ts b/src/eth/index.ts index a7f3347e..67e87686 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -17,8 +17,8 @@ type Formatter = (arg: any) => any; const inputFormatters: Record = { defaultBlockParam: (arg = 'latest') => arg, - fullTxObjectParam: (arg = false) => arg, - numberToHex: (arg: number) => arg.toString(16), + fullTxObjectParam: (arg = false): boolean => arg, + numberToHex: (arg: number): string => `0x${arg.toString(16)}`, }; type BuildRequestArgs = { @@ -63,7 +63,7 @@ class Eth { call: RPC_CALLS.eth_getBlockByHash, formatters: [null, inputFormatters.fullTxObjectParam], }); - this.getBlockByNumber = this.buildRequest<[string, boolean?], BlockTransactionString | BlockTransactionObject>({ + this.getBlockByNumber = this.buildRequest<[number, boolean?], BlockTransactionString | BlockTransactionObject>({ call: RPC_CALLS.eth_getBlockByNumber, formatters: [inputFormatters.numberToHex, inputFormatters.fullTxObjectParam], }); From 2d9b62f9f3631a065e8d302de2431879d106e40d Mon Sep 17 00:00:00 2001 From: Richard Meissner Date: Sat, 21 Nov 2020 03:24:07 +0100 Subject: [PATCH 75/85] Remove origin check --- src/communication/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index e88464ee..ee327781 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -18,14 +18,13 @@ class PostMessageCommunicator implements Communicator { private isValidMessage = ({ origin, data, source }: InterfaceMessageEvent): boolean => { const emptyOrMalformed = !data; const sentFromParentEl = source === window.parent; - const sameOrigin = origin === window.origin; const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gte(data.version, '1.0.0') : false; let validOrigin = true; if (Array.isArray(this.allowedOrigins)) { validOrigin = this.allowedOrigins.find((regExp) => regExp.test(origin)) === undefined; } - return !emptyOrMalformed && sentFromParentEl && !sameOrigin && allowedSDKVersion && validOrigin; + return !emptyOrMalformed && sentFromParentEl && allowedSDKVersion && validOrigin; }; private logIncomingMessage = (msg: InterfaceMessageEvent): void => { From b1a2b7dfccd6e876394b547f5e010a2f14fd18db Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 13:07:03 +0400 Subject: [PATCH 76/85] remove unused var --- src/txs/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/txs/index.ts b/src/txs/index.ts index ea72cce4..075f60c3 100644 --- a/src/txs/index.ts +++ b/src/txs/index.ts @@ -1,4 +1,3 @@ -import { ErrorResponse } from './../types'; import { METHODS } from '../communication/methods'; import { TxServiceModel, SendTransactionsArgs, Communicator, SendTransactionsResponse } from '../types'; From 72ca8d5a6db1e26d009e0141e45c668111493692 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 13:56:56 +0400 Subject: [PATCH 77/85] readme change to run github actions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 44105df9..458d6133 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ npm build ## Documentation -Apps built with this Sdk are meant to be run in an iframe inside the Safe Web UI. +Apps built with the Safe Apps SDK are meant to be run in an iframe inside the Safe Web UI. This library exposes a single method called `initSdk` that receives a single optional parameter, an array of regular expressions. By default it's configured to accept messages from this URLs: - mainnet: https://gnosis-safe.io, From 93358b1cf237c90c6b592dc366b61b8c0bdcd3bb Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 14:07:36 +0400 Subject: [PATCH 78/85] readme change to run github actions 2 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 458d6133..bda3e597 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,9 @@ This library exposes a single method called `initSdk` that receives a single opt By passing the argument to `initSdk` you can add more URLs to the list. It's useful when you are running your own instance of Safe Multisig. ```js -import initSdk from '@gnosis.pm/safe-apps-sdk'; +import SafeAppsSDK from '@gnosis.pm/safe-apps-sdk'; -const appsSdk = initSdk(); +const appsSdk = new SafeAppsSDK(); ``` It returns a SDK instance that allows you to interact with the Safe Multisig application. From bbd466b70b243c962ff561b2e8a9f80c9e0beb7e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 14:41:27 +0400 Subject: [PATCH 79/85] shorten import --- .gitignore | 3 ++- README.md | 13 ++----------- src/sdk.ts | 2 +- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 4fe613cb..b94f1479 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules /dist -.DS_Store \ No newline at end of file +.DS_Store +.idea \ No newline at end of file diff --git a/README.md b/README.md index bda3e597..aa12a22e 100644 --- a/README.md +++ b/README.md @@ -29,16 +29,7 @@ npm build ## Documentation Apps built with the Safe Apps SDK are meant to be run in an iframe inside the Safe Web UI. -This library exposes a single method called `initSdk` that receives a single optional parameter, an array of regular expressions. By default it's configured to accept messages from this URLs: - -- mainnet: https://gnosis-safe.io, -- mainnet-staging: https://safe-team.staging.gnosisdev.com, -- rinkeby: https://rinkeby.gnosis-safe.io, -- rinkeby-staging: https://safe-team-rinkeby.staging.gnosisdev.com, -- rinkeby-dev: https://safe-team.dev.gnosisdev.com -- localhost (for the desktop app) - -By passing the argument to `initSdk` you can add more URLs to the list. It's useful when you are running your own instance of Safe Multisig. +This library exposes a class as a default export. ```js import SafeAppsSDK from '@gnosis.pm/safe-apps-sdk'; @@ -46,7 +37,7 @@ import SafeAppsSDK from '@gnosis.pm/safe-apps-sdk'; const appsSdk = new SafeAppsSDK(); ``` -It returns a SDK instance that allows you to interact with the Safe Multisig application. +The instance allows you to interact with the Safe Multisig application. ### Subscribing to events diff --git a/src/sdk.ts b/src/sdk.ts index e1605f4d..300e09f6 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -1,4 +1,4 @@ -import { METHODS } from './communication/methods'; +import { METHODS } from './communication'; import { Communicator, SafeInfo, EnvInfo } from './types'; import InterfaceCommunicator from './communication'; import { TXs } from './txs'; From 7e6b2aaf6a29e5b66bd13db2ef8a5c61d7d8eb52 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 14:49:47 +0400 Subject: [PATCH 80/85] accept opts object --- README.md | 2 +- src/communication/index.ts | 4 ++-- src/sdk.ts | 8 +++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aa12a22e..02951a03 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ npm build ## Documentation Apps built with the Safe Apps SDK are meant to be run in an iframe inside the Safe Web UI. -This library exposes a class as a default export. +This library exposes a class as a default export. It acce ```js import SafeAppsSDK from '@gnosis.pm/safe-apps-sdk'; diff --git a/src/communication/index.ts b/src/communication/index.ts index ee327781..7ea3f6da 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -6,10 +6,10 @@ import { MessageFormatter } from './messageFormatter'; type Callback = (response: any) => void; class PostMessageCommunicator implements Communicator { - private allowedOrigins: RegExp[] | null = null; + private readonly allowedOrigins: RegExp[] | null = null; private callbacks = new Map(); - constructor(allowedOrigins: RegExp[]) { + constructor(allowedOrigins: RegExp[] | null = null) { this.allowedOrigins = allowedOrigins; window.addEventListener('message', this.onParentMessage); diff --git a/src/sdk.ts b/src/sdk.ts index 300e09f6..5b8276ec 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -4,16 +4,22 @@ import InterfaceCommunicator from './communication'; import { TXs } from './txs'; import { Eth } from './eth'; +type Opts = { + whitelistedDomains?: RegExp[]; +}; + class SafeAppsSDK { #communicator: Communicator; public readonly eth; public readonly txs; - constructor(whitelistedDomains: RegExp[] = []) { + constructor(opts: Opts = {}) { if (typeof window === 'undefined') { throw new Error('Error initializing the sdk: window is undefined'); } + const { whitelistedDomains = null } = opts; + this.#communicator = new InterfaceCommunicator(whitelistedDomains); this.eth = new Eth(this.#communicator); this.txs = new TXs(this.#communicator); From 3244e2bfbf76f91e29ef94f409a0a685eb496a1e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 15:37:59 +0400 Subject: [PATCH 81/85] update rpc arguments --- README.md | 70 +++++++++++++++++++++++---------------------- src/eth/eth.test.ts | 64 +++++++++++------------------------------ src/eth/index.ts | 7 ++--- src/sdk.test.ts | 10 +++---- src/txs/txs.test.ts | 2 +- src/types.ts | 5 ---- 6 files changed, 61 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 02951a03..21895f54 100644 --- a/README.md +++ b/README.md @@ -29,47 +29,40 @@ npm build ## Documentation Apps built with the Safe Apps SDK are meant to be run in an iframe inside the Safe Web UI. -This library exposes a class as a default export. It acce +This library exposes a class as a default export. It accepts an optional options object: +`whitelistedDomains` - Array of regular expressions for origins you want to accept messages from. If not passed, accepts +messages from any origin (default). + ```js import SafeAppsSDK from '@gnosis.pm/safe-apps-sdk'; -const appsSdk = new SafeAppsSDK(); +const opts = { + whitelistedDomains: [/gnosis-safe\\.io/] +} + +const appsSdk = new SafeAppsSDK(opts); ``` The instance allows you to interact with the Safe Multisig application. -### Subscribing to events -Once you get the SDK instance, you will be able to subscribe to events from the Safe Multisig. +### Getting Safe information -The SDK instance exposes a method called `addListeners` that receives an object with known keys, over these keys you will be able to subscribe to different events. - -- `onSafeInfo`: It will provide you first level information like the safeAddress, network, etc. -- `onTransactionConfirmation`: Fired when the user confirms the transaction inside his wallet. The response will include `requestId` and `safeTxHash` of the transaction. +Safe information can be obtained by calling `.getSafeInfo()` ```js -import { SafeInfo } from '@gnosis.pm/safe-apps-sdk'; - -const onSafeInfo = (safeInfo: SafeInfo): void => { - console.log(safeInfo); -}; - -const onTransactionConfirmation = ({ requestId, safeTxHash }) => { - console.log(requestId, safeTxHash); -}; - -appsSdk.addListeners({ - onSafeInfo, - onTransactionConfirmation, -}); +const safe = await appsSdk.getSafeInfo() +// { +// "safeAddress": "0x2fC97b3c7324EFc0BeC094bf75d5dCdFEb082C53", +// "ethBalance": "0", +// "network": "RINKEBY" +// } ``` -You can remove listeners by calling `appsSdk.removeListeners()`. - ### Sending TXs -Sending a TX through the Safe Multisig is as simple as invoking `sendTransactionsWithParams` method with an array of TXs. +Sending a TX through the Safe Multisig is as simple as invoking `.txs.send()` ```js // Create a web3 instance @@ -93,24 +86,33 @@ const params = { safeTxGas: 500000, }; -// Send to Safe-multisig -const message = appsSdk.sendTransactionsWithParams(txs, params); -console.log(message.requestId); +try { + const txs = await appsSdk.txs.send({ txs, params }); + // { safeTxHash: '0x...' } +} catch (err) { + console.error(err.message) +} ``` -`sendTransactionsWithParams` returns a message containing the requestId. You can use it to map transaction calls with `onTransactionConfirmation` events. - > Note: `value` accepts a number or a string as a decimal or hex number. ### Retrieving transaction's status -Once you received safe transaction hash from `onTransactionConfirmation` event listener, you might want to get the status of the transaction (was it executed? how many confirmations does it have?): +Once you received safe transaction hash, you might want to get the status of the transaction (was it executed? how many confirmations does it have?): ```js -const tx = sdk.txs.getBySafeTxHash(safeTxHash); +const tx = await sdk.txs.getBySafeTxHash(safeTxHash); ``` -It will return the following structure https://github.com/gnosis/safe-apps-sdk/blob/development/src/types.ts#L157 or throw an error if the backend hasn't synced the transaction yet +It will return the following structure https://github.com/gnosis/safe-apps-sdk/blob/development/src/types.ts#L182 or throw an error if the backend hasn't synced the transaction yet + +## RPC Calls + +### getBalance + +``` +const balance = await safe.eth.getBalance({ params: ['0x...'] }) +``` ## Testing in the Safe Multisig application @@ -156,7 +158,7 @@ For this we recommend to use [react-app-rewired](https://www.npmjs.com/package/r }, ``` -Additionally you need to create the `config-overrides.js` file in the root of the project to confirgure the **CORS** headers. The content of the file should be: +Additionally, you need to create the `config-overrides.js` file in the root of the project to confirgure the **CORS** headers. The content of the file should be: ```js /* config-overrides.js */ diff --git a/src/eth/eth.test.ts b/src/eth/eth.test.ts index 047be53b..ae3f3a06 100644 --- a/src/eth/eth.test.ts +++ b/src/eth/eth.test.ts @@ -1,9 +1,9 @@ import { TransactionConfig, PastLogsOptions } from 'web3-core'; import SDK from '../index'; -import { METHODS } from '../communication/methods'; +import { METHODS } from '../communication'; describe('Safe Apps SDK Read RPC Requests', () => { - const sdkInstance = new SDK([/http:\/\/localhost:3000/]); + const sdkInstance = new SDK({ whitelistedDomains: [/http:\/\/localhost:3000/] }); /* eslint-disable-next-line */ let spy: jest.SpyInstance; @@ -19,9 +19,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('getBalance', () => { it('Should send a valid message to the interface', () => { const addr = '0x0000000000000000000000000000000000000000'; - sdkInstance.eth.getBalance({ - params: [addr, 'pending'], - }); + sdkInstance.eth.getBalance([addr, 'pending']); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -37,9 +35,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should add `latest` as a default block parameter when one is not passed', () => { const addr = '0x0000000000000000000000000000000000000000'; - sdkInstance.eth.getBalance({ - params: [addr], - }); + sdkInstance.eth.getBalance([addr]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -57,9 +53,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('getCode', () => { it('Should send a valid message to the interface', () => { const addr = '0x0000000000000000000000000000000000000000'; - sdkInstance.eth.getCode({ - params: [addr, 'pending'], - }); + sdkInstance.eth.getCode([addr, 'pending']); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -75,9 +69,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should add `latest` as a default block parameter when one is not passed', () => { const addr = '0x0000000000000000000000000000000000000000'; - sdkInstance.eth.getCode({ - params: [addr], - }); + sdkInstance.eth.getCode([addr]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -95,9 +87,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('getStorageAt', () => { it('Should send a valid message to the interface', () => { const addr = '0x0000000000000000000000000000000000000000'; - sdkInstance.eth.getStorageAt({ - params: [addr, 0, 'earliest'], - }); + sdkInstance.eth.getStorageAt([addr, 0, 'earliest']); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -113,9 +103,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should add `latest` as a default block parameter when one is not passed', () => { const addr = '0x0000000000000000000000000000000000000000'; - sdkInstance.eth.getStorageAt({ - params: [addr, 0], - }); + sdkInstance.eth.getStorageAt([addr, 0]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -136,9 +124,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', }; - sdkInstance.eth.call({ - params: [config, 'pending'], - }); + sdkInstance.eth.call([config, 'pending']); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -157,9 +143,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { from: '0x0000000000000000000000000000000000000000', to: '0x0000000000000000000000000000000000000000', }; - sdkInstance.eth.call({ - params: [config], - }); + sdkInstance.eth.call([config]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -184,9 +168,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { toBlock: 'latest', }, ]; - sdkInstance.eth.getPastLogs({ - params, - }); + sdkInstance.eth.getPastLogs(params); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -204,9 +186,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('getBlockByHash', () => { it('Should send a valid message to the interface', () => { const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; - sdkInstance.eth.getBlockByHash({ - params: [hash], - }); + sdkInstance.eth.getBlockByHash([hash]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -222,9 +202,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should respect passed full tx object boolean param', () => { const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; - sdkInstance.eth.getBlockByHash({ - params: [hash, true], - }); + sdkInstance.eth.getBlockByHash([hash, true]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -242,9 +220,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('getBlockByNumber', () => { it('Should send a valid message to the interface', () => { const number = 11054275; - sdkInstance.eth.getBlockByNumber({ - params: [number], - }); + sdkInstance.eth.getBlockByNumber([number]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -260,9 +236,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { it('Should respect passed full tx object boolean param', () => { const number = 11054275; - sdkInstance.eth.getBlockByNumber({ - params: [number, true], - }); + sdkInstance.eth.getBlockByNumber([number, true]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -280,9 +254,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('getTransactionByHash', () => { it('Should send a valid message to the interface', () => { const hash = '0x0e6cd6237b4d3e5c3f348b78399f031b527e832bd30924951ba4921cdbf440d7'; - sdkInstance.eth.getTransactionByHash({ - params: [hash], - }); + sdkInstance.eth.getTransactionByHash([hash]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -300,9 +272,7 @@ describe('Safe Apps SDK Read RPC Requests', () => { describe('getTransactionReceipt', () => { it('Should send a valid message to the interface', () => { const hash = '0x0e6cd6237b4d3e5c3f348b78399f031b527e832bd30924951ba4921cdbf440d7'; - sdkInstance.eth.getTransactionReceipt({ - params: [hash], - }); + sdkInstance.eth.getTransactionReceipt([hash]); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/src/eth/index.ts b/src/eth/index.ts index 67e87686..b46f916a 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -2,7 +2,6 @@ import { TransactionConfig, PastLogsOptions } from 'web3-core'; import { RPC_CALLS } from '../eth/constants'; import { RpcCallNames, - RequestArgs, Communicator, Log, BlockTransactionString, @@ -76,13 +75,11 @@ class Eth { } private buildRequest

({ call, formatters }: BuildRequestArgs) { - return async (args: RequestArgs

): Promise => { - const params = args.params; - + return async (params: P): Promise => { if (formatters && Array.isArray(params)) { formatters.forEach((formatter: ((...args: unknown[]) => unknown) | null, i) => { if (formatter) { - params[i] = formatter((args.params as unknown[])[i]); + params[i] = formatter(params[i]); } }); } diff --git a/src/sdk.test.ts b/src/sdk.test.ts index 96ee15d5..9548490c 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -4,19 +4,19 @@ describe('Safe apps SDK', () => { let sdkInstance: SdkInstance; describe('initSdk', () => { - test('Should initialize with regExp', () => { - sdkInstance = new SDK([/http:\/\/localhost:3000/]); + test('Should initialize with opts', () => { + sdkInstance = new SDK({ whitelistedDomains: [/http:\/\/localhost:3000/] }); expect(sdkInstance.txs.send).not.toBeUndefined(); }); - test('Should initialize without regExp', () => { - sdkInstance = new SDK([]); + test('Should initialize without opts', () => { + sdkInstance = new SDK(); expect(sdkInstance.txs.send).not.toBeUndefined(); }); test("should send a getEnvInfo message to obtain information about interface's env", () => { const spy = jest.spyOn(window.parent, 'postMessage'); - sdkInstance = new SDK([]); + sdkInstance = new SDK(); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/src/txs/txs.test.ts b/src/txs/txs.test.ts index 5f9a2ec9..d6d6d4a7 100644 --- a/src/txs/txs.test.ts +++ b/src/txs/txs.test.ts @@ -2,7 +2,7 @@ import SDK from '../index'; import { METHODS } from '../communication/methods'; describe('Safe Apps SDK transaction methods', () => { - const sdkInstance = new SDK([/http:\/\/localhost:3000/]); + const sdkInstance = new SDK(); /* eslint-disable-next-line */ let spy: jest.SpyInstance; diff --git a/src/types.ts b/src/types.ts index 067147e0..d1e062c5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -213,11 +213,6 @@ export type TxServiceModel = { export type RpcCallNames = keyof typeof RPC_CALLS; -export type RequestArgs = { - params: T; - requestId?: RequestId; -}; - export interface Communicator { send(method: M, params: P): Promise>; } From 1fef70d4eb92f8056fed259cb96135549911e50d Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 16:40:05 +0400 Subject: [PATCH 82/85] add docs for rpc calls --- README.md | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 21895f54..5d8ea697 100644 --- a/README.md +++ b/README.md @@ -33,26 +33,24 @@ This library exposes a class as a default export. It accepts an optional options `whitelistedDomains` - Array of regular expressions for origins you want to accept messages from. If not passed, accepts messages from any origin (default). - ```js import SafeAppsSDK from '@gnosis.pm/safe-apps-sdk'; const opts = { - whitelistedDomains: [/gnosis-safe\\.io/] -} + whitelistedDomains: [/gnosis-safe\\.io/], +}; const appsSdk = new SafeAppsSDK(opts); ``` The instance allows you to interact with the Safe Multisig application. - ### Getting Safe information Safe information can be obtained by calling `.getSafeInfo()` ```js -const safe = await appsSdk.getSafeInfo() +const safe = await appsSdk.getSafeInfo(); // { // "safeAddress": "0x2fC97b3c7324EFc0BeC094bf75d5dCdFEb082C53", // "ethBalance": "0", @@ -90,7 +88,7 @@ try { const txs = await appsSdk.txs.send({ txs, params }); // { safeTxHash: '0x...' } } catch (err) { - console.error(err.message) + console.error(err.message); } ``` @@ -108,10 +106,138 @@ It will return the following structure https://github.com/gnosis/safe-apps-sdk/b ## RPC Calls +### The default block parameter + +The following methods have an extra default block parameter: + +- getBalance +- getCode +- getStorageAt +- call + +When requests are made that act on the state of ethereum, the last default block parameter determines the height of the block. + +The following options are possible for the defaultBlock parameter: + +`HEX String` - an integer block number +`String "earliest"` for the earliest/genesis block +`String "latest"` - for the latest mined block (default) +`String "pending"` - for the pending state/transactions + ### getBalance +Returns the balance of the account of given address. + +```js +const balance = await appsSdk.eth.getBalance(['0x...']); +``` + +### getCode + +Returns code at a given address. + +```js +const code = await appsSdk.eth.getCode(['0x...']); +``` + +### getStorageAt + +Returns the value from a storage position at a given address. + +```js +const value = await appsSdk.eth.getStorageAt(['0x...', 0]); +``` + +### call + +Executes a new message call immediately without creating a transaction on the block chain. + +```js +const config = { + from: '0x0000000000000000000000000000000000000000', + to: '0x0000000000000000000000000000000000000000', +}; + +const result = await appsSdk.eth.call([config]); +``` + +The transaction call object: +`from` - (optional) The address the transaction is sent from. +`to` 20 Bytes - The address the transaction is directed to. +`gas` - (optional) Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions. +`gasPrice` - (optional) Integer of the gasPrice used for each paid gas +`value` - (optional) Integer of the value sent with this transaction +`data` - (optional) Hash of the method signature and encoded parameters. For details see [Ethereum Contract ABI in the Solidity documentation](https://docs.soliditylang.org/en/latest/abi-spec.html) + +### getPastLogs + +Returns an array of all logs matching a given filter object. + +```js +const params = [ + { + fromBlock: 11054275, + toBlock: 'latest', + }, +]; + +const logs = await appsSdk.eth.getPastLogs([params]); +``` + +The filter options: +`fromBlock` - Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. +`toBlock` - Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. +`address` - (optional) Contract address or a list of addresses from which logs should originate. +`topics` - (optional) Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. + +### getBlockByHash + +Returns information about a block by hash. + +```js +const hash = '0x1955a9f306903669e295196752b11bc0dee33b48cabdf44b1103b7cea086cae7'; + +const block = await appsSdk.eth.getBlockByHash([hash, true]); +``` + +Parameters +`DATA` - Hash of a block. +`Boolean` (default: false) - If true it returns the full transaction objects, if false only the hashes of the transactions. + +### getBlockByNumber + +Returns information about a block by block number. + +```js +const number = 11054275; + +const block = await appsSdk.eth.getBlockByNumber([number]); +``` + +Parameters +`QUANTITY|TAG` - integer of a block number, or the string "earliest", "latest" or "pending", as in the default block parameter. +`Boolean` (default: false) - If true it returns the full transaction objects, if false only the hashes of the transactions. + +### getTransactionByHash + +Returns the information about a transaction requested by transaction hash. + +```js +const tx = await appsSdk.eth.getTransactionByHash([ + '0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b', +]); ``` -const balance = await safe.eth.getBalance({ params: ['0x...'] }) + +### getTransactionReceipt + +Returns the receipt of a transaction by transaction hash. + +> Note: That the receipt is not available for pending transactions. + +```js +const tx = await appsSdk.eth.getTransactionReceipt([ + '0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238', +]); ``` ## Testing in the Safe Multisig application From e881992f0678e0ab922e40b6d6f0fc41ebda13fb Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 16:43:18 +0400 Subject: [PATCH 83/85] fix valid origin check --- src/communication/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/communication/index.ts b/src/communication/index.ts index 7ea3f6da..91cb3be8 100644 --- a/src/communication/index.ts +++ b/src/communication/index.ts @@ -21,7 +21,7 @@ class PostMessageCommunicator implements Communicator { const allowedSDKVersion = typeof data.version !== 'undefined' ? semver.gte(data.version, '1.0.0') : false; let validOrigin = true; if (Array.isArray(this.allowedOrigins)) { - validOrigin = this.allowedOrigins.find((regExp) => regExp.test(origin)) === undefined; + validOrigin = this.allowedOrigins.find((regExp) => regExp.test(origin)) !== undefined; } return !emptyOrMalformed && sentFromParentEl && allowedSDKVersion && validOrigin; From bd8868b8074f6ed1969c544d5ec72c8d5c5b1034 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 17:01:57 +0400 Subject: [PATCH 84/85] rename formatter --- src/eth/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/eth/index.ts b/src/eth/index.ts index b46f916a..3e697879 100644 --- a/src/eth/index.ts +++ b/src/eth/index.ts @@ -16,7 +16,7 @@ type Formatter = (arg: any) => any; const inputFormatters: Record = { defaultBlockParam: (arg = 'latest') => arg, - fullTxObjectParam: (arg = false): boolean => arg, + returnFullTxObjectParam: (arg = false): boolean => arg, numberToHex: (arg: number): string => `0x${arg.toString(16)}`, }; @@ -60,11 +60,11 @@ class Eth { }); this.getBlockByHash = this.buildRequest<[string, boolean?], BlockTransactionString | BlockTransactionObject>({ call: RPC_CALLS.eth_getBlockByHash, - formatters: [null, inputFormatters.fullTxObjectParam], + formatters: [null, inputFormatters.returnFullTxObjectParam], }); this.getBlockByNumber = this.buildRequest<[number, boolean?], BlockTransactionString | BlockTransactionObject>({ call: RPC_CALLS.eth_getBlockByNumber, - formatters: [inputFormatters.numberToHex, inputFormatters.fullTxObjectParam], + formatters: [inputFormatters.numberToHex, inputFormatters.returnFullTxObjectParam], }); this.getTransactionByHash = this.buildRequest<[string], Web3TransactionObject>({ call: RPC_CALLS.eth_getTransactionByHash, From 12ed65a295a6bcdc069a8d22cf09d9ce6c41fe10 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 24 Nov 2020 17:57:50 +0400 Subject: [PATCH 85/85] remove ethBalance from SafeInfo --- README.md | 1 - src/types.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/README.md b/README.md index 5d8ea697..4043a06a 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,6 @@ Safe information can be obtained by calling `.getSafeInfo()` const safe = await appsSdk.getSafeInfo(); // { // "safeAddress": "0x2fC97b3c7324EFc0BeC094bf75d5dCdFEb082C53", -// "ethBalance": "0", // "network": "RINKEBY" // } ``` diff --git a/src/types.ts b/src/types.ts index d1e062c5..4c6a1673 100644 --- a/src/types.ts +++ b/src/types.ts @@ -61,7 +61,6 @@ export interface SdkInstance { export interface SafeInfo { safeAddress: string; network: LowercaseNetworks; - ethBalance: string; } export type Methods = keyof typeof METHODS;