From 5a24667f3166cf3d5cb4eaeb5e3beb615e27218c Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 10 May 2023 23:40:35 +0200 Subject: [PATCH 1/3] optimize: SDK bundle size by ~100kb --- .changeset/pretty-cats-walk.md | 5 + packages/safe-apps-sdk/dist/package.json | 2 +- packages/safe-apps-sdk/dist/src/safe/index.js | 90 +++++++++++++--- .../safe-apps-sdk/dist/src/safe/index.js.map | 2 +- .../dist/src/safe/signatures.d.ts | 5 +- .../safe-apps-sdk/dist/src/safe/signatures.js | 11 +- .../dist/src/safe/signatures.js.map | 2 +- .../safe-apps-sdk/dist/src/setupTests.d.ts | 1 + packages/safe-apps-sdk/dist/src/setupTests.js | 5 + .../safe-apps-sdk/dist/src/setupTests.js.map | 1 + .../safe-apps-sdk/dist/src/types/sdk.d.ts | 8 +- .../safe-apps-sdk/jest-environment-jsdom.js | 19 ++++ packages/safe-apps-sdk/jest.config.js | 2 +- packages/safe-apps-sdk/package.json | 2 +- packages/safe-apps-sdk/src/safe/index.ts | 101 +++++++++++++++--- packages/safe-apps-sdk/src/safe/safe.test.ts | 73 +++++++++++-- packages/safe-apps-sdk/src/safe/signatures.ts | 11 +- packages/safe-apps-sdk/src/setupTests.ts | 3 + packages/safe-apps-sdk/src/types/sdk.ts | 6 +- yarn.lock | 74 +++++++++++++ 20 files changed, 352 insertions(+), 71 deletions(-) create mode 100644 .changeset/pretty-cats-walk.md create mode 100644 packages/safe-apps-sdk/dist/src/setupTests.d.ts create mode 100644 packages/safe-apps-sdk/dist/src/setupTests.js create mode 100644 packages/safe-apps-sdk/dist/src/setupTests.js.map create mode 100644 packages/safe-apps-sdk/jest-environment-jsdom.js create mode 100644 packages/safe-apps-sdk/src/setupTests.ts diff --git a/.changeset/pretty-cats-walk.md b/.changeset/pretty-cats-walk.md new file mode 100644 index 00000000..ceb7c182 --- /dev/null +++ b/.changeset/pretty-cats-walk.md @@ -0,0 +1,5 @@ +--- +'@safe-global/safe-apps-sdk': major +--- + +Optimized SDK bundle size by ~100kb diff --git a/packages/safe-apps-sdk/dist/package.json b/packages/safe-apps-sdk/dist/package.json index fa7dde65..d8988a1f 100644 --- a/packages/safe-apps-sdk/dist/package.json +++ b/packages/safe-apps-sdk/dist/package.json @@ -24,7 +24,7 @@ "license": "MIT", "dependencies": { "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", - "ethers": "^5.7.2" + "viem": "0.3.21" }, "devDependencies": { "rimraf": "^3.0.2" diff --git a/packages/safe-apps-sdk/dist/src/safe/index.js b/packages/safe-apps-sdk/dist/src/safe/index.js index a67f9e5e..0ff00bc3 100644 --- a/packages/safe-apps-sdk/dist/src/safe/index.js +++ b/packages/safe-apps-sdk/dist/src/safe/index.js @@ -10,7 +10,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Safe = void 0; -const ethers_1 = require("ethers"); +const viem_1 = require("viem"); const signatures_1 = require("./signatures"); const methods_1 = require("../communication/methods"); const constants_1 = require("../eth/constants"); @@ -37,10 +37,35 @@ class Safe { } async check1271Signature(messageHash, signature = '0x') { const safeInfo = await this.getInfo(); - const encodedIsValidSignatureCall = signatures_1.EIP_1271_INTERFACE.encodeFunctionData('isValidSignature', [ - messageHash, - signature, - ]); + const encodedIsValidSignatureCall = (0, viem_1.encodeFunctionData)({ + abi: [ + { + constant: false, + inputs: [ + { + name: '_dataHash', + type: 'bytes32', + }, + { + name: '_signature', + type: 'bytes', + }, + ], + name: 'isValidSignature', + outputs: [ + { + name: '', + type: 'bytes4', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + ], + functionName: 'isValidSignature', + args: [messageHash, signature], + }); const payload = { call: constants_1.RPC_CALLS.eth_call, params: [ @@ -61,11 +86,35 @@ class Safe { } async check1271SignatureBytes(messageHash, signature = '0x') { const safeInfo = await this.getInfo(); - const msgBytes = ethers_1.ethers.utils.arrayify(messageHash); - const encodedIsValidSignatureCall = signatures_1.EIP_1271_BYTES_INTERFACE.encodeFunctionData('isValidSignature', [ - msgBytes, - signature, - ]); + const encodedIsValidSignatureCall = (0, viem_1.encodeFunctionData)({ + abi: [ + { + constant: false, + inputs: [ + { + name: '_data', + type: 'bytes', + }, + { + name: '_signature', + type: 'bytes', + }, + ], + name: 'isValidSignature', + outputs: [ + { + name: '', + type: 'bytes4', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + ], + functionName: 'isValidSignature', + args: [messageHash, signature], + }); const payload = { call: constants_1.RPC_CALLS.eth_call, params: [ @@ -85,10 +134,27 @@ class Safe { } } calculateMessageHash(message) { - return ethers_1.ethers.utils.hashMessage(message); + return (0, viem_1.hashMessage)(message); } calculateTypedMessageHash(typedMessage) { - return ethers_1.ethers.utils._TypedDataEncoder.hash(typedMessage.domain, typedMessage.types, typedMessage.message); + const chainId = typeof typedMessage.domain.chainId === 'object' + ? typedMessage.domain.chainId.toNumber() + : Number(typedMessage.domain.chainId); + let primaryType = typedMessage.primaryType; + if (!primaryType) { + const fields = Object.values(typedMessage.types); + // We try to infer primaryType (simplified ether's version) + const primaryTypes = Object.keys(typedMessage.types).filter((typeName) => fields.every((dataTypes) => dataTypes.every(({ type }) => type.replace('[', '').replace(']', '') !== typeName))); + if (primaryTypes.length === 0 || primaryTypes.length > 1) + throw new Error('Please specify primaryType'); + primaryType = primaryTypes[0]; + } + return (0, viem_1.hashTypedData)({ + message: typedMessage.message, + domain: Object.assign(Object.assign({}, typedMessage.domain), { chainId, verifyingContract: typedMessage.domain.verifyingContract, salt: typedMessage.domain.salt }), + types: typedMessage.types, + primaryType, + }); } async getOffChainSignature(messageHash) { const response = await this.communicator.send(methods_1.Methods.getOffChainSignature, messageHash); diff --git a/packages/safe-apps-sdk/dist/src/safe/index.js.map b/packages/safe-apps-sdk/dist/src/safe/index.js.map index 8768c3b7..50e0ef3e 100644 --- a/packages/safe-apps-sdk/dist/src/safe/index.js.map +++ b/packages/safe-apps-sdk/dist/src/safe/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/safe/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/safe/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/safe-apps-sdk/dist/src/safe/signatures.d.ts b/packages/safe-apps-sdk/dist/src/safe/signatures.d.ts index e3bbc2d1..3c9e6389 100644 --- a/packages/safe-apps-sdk/dist/src/safe/signatures.d.ts +++ b/packages/safe-apps-sdk/dist/src/safe/signatures.d.ts @@ -1,6 +1,3 @@ -import { ethers } from 'ethers'; declare const MAGIC_VALUE = "0x1626ba7e"; declare const MAGIC_VALUE_BYTES = "0x20c13b0b"; -declare const EIP_1271_INTERFACE: ethers.utils.Interface; -declare const EIP_1271_BYTES_INTERFACE: ethers.utils.Interface; -export { EIP_1271_INTERFACE, EIP_1271_BYTES_INTERFACE, MAGIC_VALUE, MAGIC_VALUE_BYTES }; +export { MAGIC_VALUE, MAGIC_VALUE_BYTES }; diff --git a/packages/safe-apps-sdk/dist/src/safe/signatures.js b/packages/safe-apps-sdk/dist/src/safe/signatures.js index 8e6c208d..145dccea 100644 --- a/packages/safe-apps-sdk/dist/src/safe/signatures.js +++ b/packages/safe-apps-sdk/dist/src/safe/signatures.js @@ -1,17 +1,8 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.MAGIC_VALUE_BYTES = exports.MAGIC_VALUE = exports.EIP_1271_BYTES_INTERFACE = exports.EIP_1271_INTERFACE = void 0; -const ethers_1 = require("ethers"); +exports.MAGIC_VALUE_BYTES = exports.MAGIC_VALUE = void 0; const MAGIC_VALUE = '0x1626ba7e'; exports.MAGIC_VALUE = MAGIC_VALUE; const MAGIC_VALUE_BYTES = '0x20c13b0b'; exports.MAGIC_VALUE_BYTES = MAGIC_VALUE_BYTES; -const EIP_1271_INTERFACE = new ethers_1.ethers.utils.Interface([ - 'function isValidSignature(bytes32 _dataHash, bytes calldata _signature) external view', -]); -exports.EIP_1271_INTERFACE = EIP_1271_INTERFACE; -const EIP_1271_BYTES_INTERFACE = new ethers_1.ethers.utils.Interface([ - 'function isValidSignature(bytes calldata _data, bytes calldata _signature) public view', -]); -exports.EIP_1271_BYTES_INTERFACE = EIP_1271_BYTES_INTERFACE; //# sourceMappingURL=signatures.js.map \ No newline at end of file diff --git a/packages/safe-apps-sdk/dist/src/safe/signatures.js.map b/packages/safe-apps-sdk/dist/src/safe/signatures.js.map index 80dcc306..4c8c580a 100644 --- a/packages/safe-apps-sdk/dist/src/safe/signatures.js.map +++ b/packages/safe-apps-sdk/dist/src/safe/signatures.js.map @@ -1 +1 @@ -{"version":3,"file":"signatures.js","sourceRoot":"","sources":["../../../src/safe/signatures.ts"],"names":[],"mappings":";;;AAAA,mCAAgC;AAEhC,MAAM,WAAW,GAAG,YAAY,CAAC;AAUsB,kCAAW;AATlE,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAS6B,8CAAiB;AAPrF,MAAM,kBAAkB,GAAG,IAAI,eAAM,CAAC,KAAK,CAAC,SAAS,CAAC;IACpD,uFAAuF;CACxF,CAAC,CAAC;AAKM,gDAAkB;AAJ3B,MAAM,wBAAwB,GAAG,IAAI,eAAM,CAAC,KAAK,CAAC,SAAS,CAAC;IAC1D,wFAAwF;CACzF,CAAC,CAAC;AAE0B,4DAAwB"} \ No newline at end of file +{"version":3,"file":"signatures.js","sourceRoot":"","sources":["../../../src/safe/signatures.ts"],"names":[],"mappings":";;;AAAA,MAAM,WAAW,GAAG,YAAY,CAAC;AAGxB,kCAAW;AAFpB,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAEjB,8CAAiB"} \ No newline at end of file diff --git a/packages/safe-apps-sdk/dist/src/setupTests.d.ts b/packages/safe-apps-sdk/dist/src/setupTests.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/packages/safe-apps-sdk/dist/src/setupTests.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/safe-apps-sdk/dist/src/setupTests.js b/packages/safe-apps-sdk/dist/src/setupTests.js new file mode 100644 index 00000000..caca9adb --- /dev/null +++ b/packages/safe-apps-sdk/dist/src/setupTests.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const util_1 = require("util"); +global.TextEncoder = util_1.TextEncoder; +//# sourceMappingURL=setupTests.js.map \ No newline at end of file diff --git a/packages/safe-apps-sdk/dist/src/setupTests.js.map b/packages/safe-apps-sdk/dist/src/setupTests.js.map new file mode 100644 index 00000000..fc8c4abb --- /dev/null +++ b/packages/safe-apps-sdk/dist/src/setupTests.js.map @@ -0,0 +1 @@ +{"version":3,"file":"setupTests.js","sourceRoot":"","sources":["../../src/setupTests.ts"],"names":[],"mappings":";;AAAA,+BAAmC;AAEnC,MAAM,CAAC,WAAW,GAAG,kBAAW,CAAC"} \ No newline at end of file diff --git a/packages/safe-apps-sdk/dist/src/types/sdk.d.ts b/packages/safe-apps-sdk/dist/src/types/sdk.d.ts index 33a8cd29..af4aa765 100644 --- a/packages/safe-apps-sdk/dist/src/types/sdk.d.ts +++ b/packages/safe-apps-sdk/dist/src/types/sdk.d.ts @@ -1,5 +1,4 @@ import { ChainInfo as _ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'; -import { BigNumberish, BytesLike } from 'ethers'; export type ChainInfo = Pick<_ChainInfo, 'chainName' | 'chainId' | 'shortName' | 'nativeCurrency' | 'blockExplorerUriTemplate'>; export { NativeCurrency } from '@safe-global/safe-gateway-typescript-sdk'; export type BaseTransaction = { @@ -26,9 +25,11 @@ export type SignMessageParams = { export interface TypedDataDomain { name?: string; version?: string; - chainId?: BigNumberish; + chainId?: string | number | bigint | { + toNumber: () => number; + }; verifyingContract?: string; - salt?: BytesLike; + salt?: string; } export interface TypedDataTypes { name: string; @@ -41,6 +42,7 @@ export type EIP712TypedData = { domain: TypedDataDomain; types: TypedMessageTypes; message: Record; + primaryType?: string; }; export type SignTypedMessageParams = { typedData: EIP712TypedData; diff --git a/packages/safe-apps-sdk/jest-environment-jsdom.js b/packages/safe-apps-sdk/jest-environment-jsdom.js new file mode 100644 index 00000000..537fa605 --- /dev/null +++ b/packages/safe-apps-sdk/jest-environment-jsdom.js @@ -0,0 +1,19 @@ +// https://github.com/paralleldrive/cuid2/issues/44#issuecomment-1531731695 +const { TextEncoder, TextDecoder } = require('util'); +const { default: $JSDOMEnvironment, TestEnvironment } = require('jest-environment-jsdom'); + +Object.defineProperty(exports, '__esModule', { + value: true, +}); + +class JSDOMEnvironment extends $JSDOMEnvironment { + constructor(...args) { + const { global } = super(...args); + global.Uint8Array = Uint8Array; + if (!global.TextEncoder) global.TextEncoder = TextEncoder; + if (!global.TextDecoder) global.TextDecoder = TextDecoder; + } +} + +exports.default = JSDOMEnvironment; +exports.TestEnvironment = TestEnvironment === $JSDOMEnvironment ? JSDOMEnvironment : TestEnvironment; diff --git a/packages/safe-apps-sdk/jest.config.js b/packages/safe-apps-sdk/jest.config.js index 86a1997d..4fd8ed22 100644 --- a/packages/safe-apps-sdk/jest.config.js +++ b/packages/safe-apps-sdk/jest.config.js @@ -4,5 +4,5 @@ module.exports = { moduleDirectories: ['node_modules', 'src'], roots: ['src'], verbose: true, - testEnvironment: 'jsdom', + testEnvironment: './jest-environment-jsdom.js', }; diff --git a/packages/safe-apps-sdk/package.json b/packages/safe-apps-sdk/package.json index c138816e..044e293e 100644 --- a/packages/safe-apps-sdk/package.json +++ b/packages/safe-apps-sdk/package.json @@ -24,7 +24,7 @@ "license": "MIT", "dependencies": { "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", - "ethers": "^5.7.2" + "viem": "0.3.21" }, "devDependencies": { "rimraf": "^3.0.2" diff --git a/packages/safe-apps-sdk/src/safe/index.ts b/packages/safe-apps-sdk/src/safe/index.ts index 0d1da50d..379f4907 100644 --- a/packages/safe-apps-sdk/src/safe/index.ts +++ b/packages/safe-apps-sdk/src/safe/index.ts @@ -1,5 +1,5 @@ -import { ethers } from 'ethers'; -import { EIP_1271_INTERFACE, EIP_1271_BYTES_INTERFACE, MAGIC_VALUE_BYTES, MAGIC_VALUE } from './signatures'; +import { encodeFunctionData, Address, hashMessage, hashTypedData } from 'viem'; +import { MAGIC_VALUE_BYTES, MAGIC_VALUE } from './signatures'; import { Methods } from '../communication/methods'; import { RPC_CALLS } from '../eth/constants'; import { @@ -57,10 +57,35 @@ class Safe { private async check1271Signature(messageHash: string, signature = '0x'): Promise { const safeInfo = await this.getInfo(); - const encodedIsValidSignatureCall = EIP_1271_INTERFACE.encodeFunctionData('isValidSignature', [ - messageHash, - signature, - ]); + const encodedIsValidSignatureCall = encodeFunctionData({ + abi: [ + { + constant: false, + inputs: [ + { + name: '_dataHash', + type: 'bytes32', + }, + { + name: '_signature', + type: 'bytes', + }, + ], + name: 'isValidSignature', + outputs: [ + { + name: '', + type: 'bytes4', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + ] as const, + functionName: 'isValidSignature', + args: [messageHash as Address, signature as Address], + }); const payload = { call: RPC_CALLS.eth_call, @@ -86,12 +111,36 @@ class Safe { private async check1271SignatureBytes(messageHash: string, signature = '0x'): Promise { const safeInfo = await this.getInfo(); - const msgBytes = ethers.utils.arrayify(messageHash); - const encodedIsValidSignatureCall = EIP_1271_BYTES_INTERFACE.encodeFunctionData('isValidSignature', [ - msgBytes, - signature, - ]); + const encodedIsValidSignatureCall = encodeFunctionData({ + abi: [ + { + constant: false, + inputs: [ + { + name: '_data', + type: 'bytes', + }, + { + name: '_signature', + type: 'bytes', + }, + ], + name: 'isValidSignature', + outputs: [ + { + name: '', + type: 'bytes4', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + ] as const, + functionName: 'isValidSignature', + args: [messageHash as Address, signature as Address], + }); const payload = { call: RPC_CALLS.eth_call, @@ -117,11 +166,37 @@ class Safe { } calculateMessageHash(message: string): string { - return ethers.utils.hashMessage(message); + return hashMessage(message); } calculateTypedMessageHash(typedMessage: EIP712TypedData): string { - return ethers.utils._TypedDataEncoder.hash(typedMessage.domain, typedMessage.types, typedMessage.message); + const chainId = + typeof typedMessage.domain.chainId === 'object' + ? typedMessage.domain.chainId.toNumber() + : Number(typedMessage.domain.chainId); + + let primaryType = typedMessage.primaryType; + if (!primaryType) { + const fields = Object.values(typedMessage.types); + // We try to infer primaryType (simplified ether's version) + const primaryTypes = Object.keys(typedMessage.types).filter((typeName) => + fields.every((dataTypes) => dataTypes.every(({ type }) => type.replace('[', '').replace(']', '') !== typeName)), + ); + if (primaryTypes.length === 0 || primaryTypes.length > 1) throw new Error('Please specify primaryType'); + primaryType = primaryTypes[0]; + } + + return hashTypedData({ + message: typedMessage.message, + domain: { + ...typedMessage.domain, + chainId, + verifyingContract: typedMessage.domain.verifyingContract as Address, + salt: typedMessage.domain.salt as Address, + }, + types: typedMessage.types, + primaryType, + }); } async getOffChainSignature(messageHash: string): Promise { diff --git a/packages/safe-apps-sdk/src/safe/safe.test.ts b/packages/safe-apps-sdk/src/safe/safe.test.ts index 6d8b0241..e8fdc7a9 100644 --- a/packages/safe-apps-sdk/src/safe/safe.test.ts +++ b/packages/safe-apps-sdk/src/safe/safe.test.ts @@ -53,6 +53,57 @@ describe('Safe Apps SDK safe methods', () => { }); }); + describe('SDK.safe.calculateTypedMessageHash', () => { + test('Should generate correct EIP-712 message hash', () => { + const safeInfoSpy = jest.spyOn(sdkInstance.safe, 'getInfo'); + safeInfoSpy.mockImplementationOnce( + (): Promise => + Promise.resolve({ + chainId: 4, + safeAddress: '0x9C6FEA0B2eAc5b6D8bBB6C30401D42aA95398190', + owners: [], + threshold: 1, + isReadOnly: false, + }), + ); + + const typedMessage = { + domain: { + name: 'Ether Mail', + version: '1', + chainId: 1, + verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', + }, + types: { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }, + message: { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }, + }; + const expectedHash = '0xbe609aee343fb3c4b28e1df9e632fca64fcfaede20f02e86244efddf30957bd2'; + const hash = sdkInstance.safe.calculateTypedMessageHash(typedMessage); + + expect(hash).toEqual(expectedHash); + }); + }); + describe('SDK.safe.check1271Signature', () => { test('Should send a valid message to the interface', async () => { const safeInfoSpy = jest.spyOn(sdkInstance.safe, 'getInfo'); @@ -66,7 +117,7 @@ describe('Safe Apps SDK safe methods', () => { isReadOnly: false, }), ); - const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // ethers.utils.formatBytes32String('approve rugpull') + const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // stringToHex('approve rugpull', { size: 32 }) // @ts-expect-error method is private but we are testing it sdkInstance.safe.check1271Signature(message); await sleep(200); @@ -110,7 +161,7 @@ describe('Safe Apps SDK safe methods', () => { }), ); - const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // ethers.utils.formatBytes32String('approve rugpull') + const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // stringToHex('approve rugpull', { size: 32 }) // @ts-expect-error method is private but we are testing it expect(await sdkInstance.safe.check1271Signature(message)).toEqual(true); }); @@ -131,7 +182,7 @@ describe('Safe Apps SDK safe methods', () => { ); rpcCallSpy.mockImplementationOnce(() => Promise.reject(new Error('Hash not approved'))); - const message = '0x68616c6c6f000000000000000000000000000000000000000000000000000000'; // ethers.utils.formatBytes32String('hallo') + const message = '0x68616c6c6f000000000000000000000000000000000000000000000000000000'; // stringToHex('hallo') // @ts-expect-error method is private but we are testing it expect(await sdkInstance.safe.check1271Signature(message)).toEqual(false); }); @@ -150,7 +201,7 @@ describe('Safe Apps SDK safe methods', () => { isReadOnly: false, }), ); - const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // ethers.utils.formatBytes32String('approve rugpull') + const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // stringToHex('approve rugpull', { size: 32 }) // @ts-expect-error method is private but we are testing it sdkInstance.safe.check1271SignatureBytes(message); await sleep(200); @@ -194,7 +245,7 @@ describe('Safe Apps SDK safe methods', () => { }), ); - const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // ethers.utils.formatBytes32String('approve rugpull') + const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // stringToHex('approve rugpull', { size: 32 }) // @ts-expect-error method is private but we are testing it expect(await sdkInstance.safe.check1271SignatureBytes(message)).toEqual(true); }); @@ -215,7 +266,7 @@ describe('Safe Apps SDK safe methods', () => { ); rpcCallSpy.mockImplementationOnce(() => Promise.reject(new Error('Hash not approved'))); - const message = '0x68616c6c6f000000000000000000000000000000000000000000000000000000'; // ethers.utils.formatBytes32String('hallo') + const message = '0x68616c6c6f000000000000000000000000000000000000000000000000000000'; // stringToHex('hallo') // @ts-expect-error method is private but we are testing it expect(await sdkInstance.safe.check1271SignatureBytes(message)).toEqual(false); }); @@ -225,7 +276,7 @@ describe('Safe Apps SDK safe methods', () => { test('Should call SDK.safe.isMessageHashSigned with a hash of the message', () => { const isMessageHashSignedSpy = jest.spyOn(sdkInstance.safe, 'isMessageHashSigned'); - // ethers.utils.formatBytes32String('approve rugpull') + // stringToHex('approve rugpull', { size: 32 }) const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; const expectedHash = '0xaae9257b8ff1c926ac3cdf36923661de4e81bf934e38958beeede3519aa18b08'; @@ -248,7 +299,7 @@ describe('Safe Apps SDK safe methods', () => { }), ); - const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // ethers.utils.formatBytes32String('approve rugpull') + const message = '0x617070726f76652072756770756c6c0000000000000000000000000000000000'; // stringToHex('approve rugpull', { size: 32 }) sdkInstance.safe.isMessageHashSigned(message); await sleep(200); @@ -288,7 +339,7 @@ describe('Safe Apps SDK safe methods', () => { // @ts-expect-error ts fails to infer the return type because of a private method check1271SignatureSpy.mockImplementationOnce(() => Promise.resolve(true)); - // ethers.utils.formatBytes32String('approve rugpull') + // stringToHex('approve rugpull', { size: 32 }) const message = sdkInstance.safe.calculateMessageHash( '0x617070726f76652072756770756c6c0000000000000000000000000000000000', ); @@ -318,7 +369,7 @@ describe('Safe Apps SDK safe methods', () => { // @ts-expect-error ts fails to infer the return type because of a private method check1271SignatureBytesSpy.mockImplementationOnce(() => Promise.resolve(true)); - // ethers.utils.formatBytes32String('approve rugpull') + // stringToHex('approve rugpull', { size: 32 }) const message = sdkInstance.safe.calculateMessageHash( '0x617070726f76652072756770756c6c0000000000000000000000000000000000', ); @@ -348,7 +399,7 @@ describe('Safe Apps SDK safe methods', () => { // @ts-expect-error ts fails to infer the return type because of a private method check1271SignatureBytesSpy.mockImplementationOnce(() => Promise.resolve(false)); - // ethers.utils.formatBytes32String('approve rugpull') + // stringToHex('approve rugpull', { size: 32 }) const message = sdkInstance.safe.calculateMessageHash( '0x617070726f76652072756770756c6c0000000000000000000000000000000000', ); diff --git a/packages/safe-apps-sdk/src/safe/signatures.ts b/packages/safe-apps-sdk/src/safe/signatures.ts index 6773122c..0e1cb1c2 100644 --- a/packages/safe-apps-sdk/src/safe/signatures.ts +++ b/packages/safe-apps-sdk/src/safe/signatures.ts @@ -1,13 +1,4 @@ -import { ethers } from 'ethers'; - const MAGIC_VALUE = '0x1626ba7e'; const MAGIC_VALUE_BYTES = '0x20c13b0b'; -const EIP_1271_INTERFACE = new ethers.utils.Interface([ - 'function isValidSignature(bytes32 _dataHash, bytes calldata _signature) external view', -]); -const EIP_1271_BYTES_INTERFACE = new ethers.utils.Interface([ - 'function isValidSignature(bytes calldata _data, bytes calldata _signature) public view', -]); - -export { EIP_1271_INTERFACE, EIP_1271_BYTES_INTERFACE, MAGIC_VALUE, MAGIC_VALUE_BYTES }; +export { MAGIC_VALUE, MAGIC_VALUE_BYTES }; diff --git a/packages/safe-apps-sdk/src/setupTests.ts b/packages/safe-apps-sdk/src/setupTests.ts new file mode 100644 index 00000000..e6cfa5bc --- /dev/null +++ b/packages/safe-apps-sdk/src/setupTests.ts @@ -0,0 +1,3 @@ +import { TextEncoder } from 'util'; + +global.TextEncoder = TextEncoder; diff --git a/packages/safe-apps-sdk/src/types/sdk.ts b/packages/safe-apps-sdk/src/types/sdk.ts index 3258bcc1..f8571c11 100644 --- a/packages/safe-apps-sdk/src/types/sdk.ts +++ b/packages/safe-apps-sdk/src/types/sdk.ts @@ -1,5 +1,4 @@ import { ChainInfo as _ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'; -import { BigNumberish, BytesLike } from 'ethers'; export type ChainInfo = Pick< _ChainInfo, @@ -36,9 +35,9 @@ export type SignMessageParams = { export interface TypedDataDomain { name?: string; version?: string; - chainId?: BigNumberish; + chainId?: string | number | bigint | { toNumber: () => number }; verifyingContract?: string; - salt?: BytesLike; + salt?: string; } export interface TypedDataTypes { @@ -52,6 +51,7 @@ export type EIP712TypedData = { domain: TypedDataDomain; types: TypedMessageTypes; message: Record; + primaryType?: string; }; export type SignTypedMessageParams = { diff --git a/yarn.lock b/yarn.lock index 1e366859..7f92a0f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.1.0.tgz#417fef4a143f4396ad0b3b4351fee21323f15aa8" integrity sha512-mMVJ/j/GbZ/De4ZHWbQAQO1J6iVnjtZLc9WEdkUQb8S/Bu2cAF2bETXUgMAdvMG3/ngtKmcNBe+Zms9bg6jnQQ== +"@adraffy/ens-normalize@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.0.tgz#223572538f6bea336750039bb43a4016dcc8182d" + integrity sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ== + "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -3228,11 +3233,23 @@ dependencies: eslint-scope "5.1.1" +"@noble/curves@1.0.0", "@noble/curves@~1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932" + integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw== + dependencies: + "@noble/hashes" "1.3.0" + "@noble/ed25519@^1.7.0": version "1.7.1" resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.1.tgz#6899660f6fbb97798a6fbd227227c4589a454724" integrity sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw== +"@noble/hashes@1.3.0", "@noble/hashes@~1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" + integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== + "@noble/hashes@^1.1.2": version "1.1.5" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" @@ -3629,6 +3646,28 @@ dependencies: cross-fetch "^3.1.5" +"@scure/base@~1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + +"@scure/bip32@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" + integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q== + dependencies: + "@noble/curves" "~1.0.0" + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" + integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@segment/react-tiny-virtual-list@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@segment/react-tiny-virtual-list/-/react-tiny-virtual-list-2.2.1.tgz#658da8a93cfb83537235c89307818d6f1741aeb3" @@ -4627,6 +4666,11 @@ resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-0.1.14.tgz#2740762f2719df2c69c63ab30b67fdf4bef70305" integrity sha512-hSzb6Ni/PejVzliKkc5T3ehzRJxr5k4fZMGYuouqwArWQ8z7R4jrIlm2j2nNOD7Epz6ZucdiVluU1YH0d/EEyw== +"@wagmi/chains@0.2.16": + version "0.2.16" + resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-0.2.16.tgz#a726716e4619ec1c192b312e23f9c38407617aa0" + integrity sha512-rkWaI2PxCnbD8G07ZZff5QXftnSkYL0h5f4DkHCG3fGYYr/ZDvmCL4bMae7j7A9sAif1csPPBmbCzHp3R5ogCQ== + "@wagmi/connectors@0.1.10": version "0.1.10" resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-0.1.10.tgz#101a25fae908f29cc28caede0dde958711119adb" @@ -5227,6 +5271,11 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abitype@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.2.tgz#cacd330d07488a4020d84f54fc361361234b9c83" + integrity sha512-B1ViNMGpfx/qjVQi0RTc2HEFHuR9uoCoTEkwELT5Y7pBPtBbctYijz9BK6+Kd0hQ3S70FhYTO2dWWk0QNUEXMA== + abitype@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.2.5.tgz#e571ef2ed99db1cae551fffde5bcbcee4e446177" @@ -10020,6 +10069,11 @@ isomorphic-fetch@^2.1.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" +isomorphic-ws@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + isomorphic-ws@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" @@ -15948,6 +16002,21 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +viem@0.3.21: + version "0.3.21" + resolved "https://registry.yarnpkg.com/viem/-/viem-0.3.21.tgz#0ff655e2a1cc6d4a00929b6fc0d5e0581a6b5464" + integrity sha512-AjP5tcJDfmsdstYqh3PjZXPOVdv7+kQ3mFwRlwD4Y3RwNbdZ6L89zXiYV1rIBfPa9VXnW/xr+NNyzAKsVuauLQ== + dependencies: + "@adraffy/ens-normalize" "1.9.0" + "@noble/curves" "1.0.0" + "@noble/hashes" "1.3.0" + "@scure/bip32" "1.3.0" + "@scure/bip39" "1.2.0" + "@wagmi/chains" "0.2.16" + abitype "0.8.2" + isomorphic-ws "5.0.0" + ws "8.12.0" + w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -16602,6 +16671,11 @@ ws@7.5.3: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== +ws@8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" + integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== + ws@^7.4.0, ws@^7.4.5, ws@^7.4.6, ws@^7.5.1: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" From 2fb9a82d9584e1a04ab59b732160211deda589ac Mon Sep 17 00:00:00 2001 From: Vladimir Date: Thu, 8 Jun 2023 21:27:48 +0200 Subject: [PATCH 2/3] upgrade: viem to v1.0 --- packages/safe-apps-sdk/package.json | 2 +- yarn.lock | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/safe-apps-sdk/package.json b/packages/safe-apps-sdk/package.json index 044e293e..992abde7 100644 --- a/packages/safe-apps-sdk/package.json +++ b/packages/safe-apps-sdk/package.json @@ -24,7 +24,7 @@ "license": "MIT", "dependencies": { "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", - "viem": "0.3.21" + "viem": "1.0.0" }, "devDependencies": { "rimraf": "^3.0.2" diff --git a/yarn.lock b/yarn.lock index 7f92a0f8..35cb4b2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4666,10 +4666,10 @@ resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-0.1.14.tgz#2740762f2719df2c69c63ab30b67fdf4bef70305" integrity sha512-hSzb6Ni/PejVzliKkc5T3ehzRJxr5k4fZMGYuouqwArWQ8z7R4jrIlm2j2nNOD7Epz6ZucdiVluU1YH0d/EEyw== -"@wagmi/chains@0.2.16": - version "0.2.16" - resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-0.2.16.tgz#a726716e4619ec1c192b312e23f9c38407617aa0" - integrity sha512-rkWaI2PxCnbD8G07ZZff5QXftnSkYL0h5f4DkHCG3fGYYr/ZDvmCL4bMae7j7A9sAif1csPPBmbCzHp3R5ogCQ== +"@wagmi/chains@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-1.1.0.tgz#d351b3dc6f472b167f180721f46f6098b6c1585b" + integrity sha512-pWZlxBk0Ql8E7DV8DwqlbBpOyUdaG9UDlQPBxJNALuEK1I0tbQ3AVvSDnlsEIt06UPmPo5o27gzs3hwPQ/A+UA== "@wagmi/connectors@0.1.10": version "0.1.10" @@ -5271,10 +5271,10 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -abitype@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.2.tgz#cacd330d07488a4020d84f54fc361361234b9c83" - integrity sha512-B1ViNMGpfx/qjVQi0RTc2HEFHuR9uoCoTEkwELT5Y7pBPtBbctYijz9BK6+Kd0hQ3S70FhYTO2dWWk0QNUEXMA== +abitype@0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.7.tgz#e4b3f051febd08111f486c0cc6a98fa72d033622" + integrity sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w== abitype@^0.2.5: version "0.2.5" @@ -16002,18 +16002,18 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -viem@0.3.21: - version "0.3.21" - resolved "https://registry.yarnpkg.com/viem/-/viem-0.3.21.tgz#0ff655e2a1cc6d4a00929b6fc0d5e0581a6b5464" - integrity sha512-AjP5tcJDfmsdstYqh3PjZXPOVdv7+kQ3mFwRlwD4Y3RwNbdZ6L89zXiYV1rIBfPa9VXnW/xr+NNyzAKsVuauLQ== +viem@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.0.0.tgz#28709e40addf74d5be45c96b73e521b014694c0c" + integrity sha512-JqdO5TYSuv+/cV9xOmHUKB6qXeyLHtl3gcYYHnfFstfdzivfBttmKtwHiZPdffvcr5DqKsYFT5LLrFnfz5vfLQ== dependencies: "@adraffy/ens-normalize" "1.9.0" "@noble/curves" "1.0.0" "@noble/hashes" "1.3.0" "@scure/bip32" "1.3.0" "@scure/bip39" "1.2.0" - "@wagmi/chains" "0.2.16" - abitype "0.8.2" + "@wagmi/chains" "1.1.0" + abitype "0.8.7" isomorphic-ws "5.0.0" ws "8.12.0" From cdc7c615cdb703c2e6120f0022bde5f3d03b6053 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Thu, 8 Jun 2023 22:32:52 +0200 Subject: [PATCH 3/3] fix: viem package.json declaration --- packages/safe-apps-sdk/package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/safe-apps-sdk/package.json b/packages/safe-apps-sdk/package.json index 992abde7..f0208136 100644 --- a/packages/safe-apps-sdk/package.json +++ b/packages/safe-apps-sdk/package.json @@ -24,7 +24,7 @@ "license": "MIT", "dependencies": { "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", - "viem": "1.0.0" + "viem": "^1.0.0" }, "devDependencies": { "rimraf": "^3.0.2" diff --git a/yarn.lock b/yarn.lock index 35cb4b2b..85190c2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16002,7 +16002,7 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -viem@1.0.0: +viem@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/viem/-/viem-1.0.0.tgz#28709e40addf74d5be45c96b73e521b014694c0c" integrity sha512-JqdO5TYSuv+/cV9xOmHUKB6qXeyLHtl3gcYYHnfFstfdzivfBttmKtwHiZPdffvcr5DqKsYFT5LLrFnfz5vfLQ==