From 47f0293ed33565fdb1860028ffc9376a1ee3ded4 Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Mon, 24 Mar 2025 12:56:50 +1100 Subject: [PATCH 1/8] Add console.logs for debugging issues during starkex gen --- packages/internal/toolkit/src/crypto.ts | 6 ++++-- packages/x-provider/src/imx-wallet/ImxSigner.ts | 4 ++++ packages/x-provider/src/imx-wallet/imxWallet.ts | 14 +++++++++++++- .../x-provider/src/l1-providers/metaMaskWrapper.ts | 8 +++++++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/internal/toolkit/src/crypto.ts b/packages/internal/toolkit/src/crypto.ts index 67e2815e2c..a10107eb7e 100644 --- a/packages/internal/toolkit/src/crypto.ts +++ b/packages/internal/toolkit/src/crypto.ts @@ -1,6 +1,6 @@ import BN from 'bn.js'; import * as encUtils from 'enc-utils'; -import { Signer } from 'ethers'; +import { Signer, toUtf8Bytes } from 'ethers'; type SignatureOptions = { r: BN; @@ -42,7 +42,9 @@ export async function signRaw( payload: string, signer: Signer, ): Promise { - const signature = deserializeSignature(await signer.signMessage(payload)); + console.log('signRaw.payload', { payload }); + console.log('signRaw.toUtf8Bytes', { toUtf8Bytes: toUtf8Bytes(payload).toString() }); + const signature = deserializeSignature(await signer.signMessage(toUtf8Bytes(payload))); return serializeEthSignature(signature); } diff --git a/packages/x-provider/src/imx-wallet/ImxSigner.ts b/packages/x-provider/src/imx-wallet/ImxSigner.ts index 7df7d8b5c1..29bfee856f 100644 --- a/packages/x-provider/src/imx-wallet/ImxSigner.ts +++ b/packages/x-provider/src/imx-wallet/ImxSigner.ts @@ -1,4 +1,5 @@ import { StarkSigner } from '@imtbl/x-client'; +import { toUtf8Bytes } from 'ethers'; import { COMMUNICATION_TYPE, ResponseEventType, @@ -28,6 +29,9 @@ export class ImxSigner implements StarkSigner { } public signMessage(rawMessage: string): Promise { + console.log('signMessage.rawMessage', { rawMessage }); + console.log('signMessage.toUtf8Bytes.toString()', { toUtf8Bytes: toUtf8Bytes(rawMessage).toString() }); + return new Promise((resolve, reject) => { const listener = (event: MessageEvent) => { messageResponseListener( diff --git a/packages/x-provider/src/imx-wallet/imxWallet.ts b/packages/x-provider/src/imx-wallet/imxWallet.ts index 46e1c94787..9c577ed6f6 100644 --- a/packages/x-provider/src/imx-wallet/imxWallet.ts +++ b/packages/x-provider/src/imx-wallet/imxWallet.ts @@ -1,5 +1,10 @@ import { Environment } from '@imtbl/config'; -import { BrowserProvider, toUtf8Bytes } from 'ethers'; +import { + BrowserProvider, + getBytes, + toUtf8Bytes, + toUtf8String, +} from 'ethers'; import { ConnectRequest, ConnectResponse, @@ -25,6 +30,13 @@ export async function connect( ): Promise { const l1Signer = await l1Provider.getSigner(); const address = await l1Signer.getAddress(); + + console.log('DEFAULT_CONNECTION_MESSAGE', { message: DEFAULT_CONNECTION_MESSAGE }); + console.log('toUtf8Bytes.toString()', { toUtf8Bytes: toUtf8Bytes(DEFAULT_CONNECTION_MESSAGE).toString() }); + + console.log('toUtf8String 1', { toUtf8String: toUtf8String(toUtf8Bytes(DEFAULT_CONNECTION_MESSAGE)) }); + console.log('toUtf8String 2', { toUtf8String: toUtf8String(getBytes(toUtf8Bytes(DEFAULT_CONNECTION_MESSAGE))) }); + const signature = await l1Signer.signMessage(toUtf8Bytes(DEFAULT_CONNECTION_MESSAGE)); const iframe = await getOrSetupIFrame(env); diff --git a/packages/x-provider/src/l1-providers/metaMaskWrapper.ts b/packages/x-provider/src/l1-providers/metaMaskWrapper.ts index 4707897d81..e7bf452888 100644 --- a/packages/x-provider/src/l1-providers/metaMaskWrapper.ts +++ b/packages/x-provider/src/l1-providers/metaMaskWrapper.ts @@ -27,9 +27,15 @@ export class MetaMaskIMXProvider extends GenericIMXProvider { metaMaskProvider, config.baseConfig.environment, ); + + const signer = await metaMaskProvider.getSigner(); + + console.log('metaMaskProvider.getSigner().getAddress()', await signer.getAddress()); + console.log('imxSigner.getAddress()', this.imxSigner.getAddress()); + return new MetaMaskIMXProvider( config, - await metaMaskProvider.getSigner(), + signer, this.imxSigner, ); }, From 418150a2292e3691740e9cde3d215bf24b76115a Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Mon, 24 Mar 2025 13:19:07 +1100 Subject: [PATCH 2/8] Fix tests --- .../src/l1-providers/metaMaskWrapper.test.ts | 76 ++++++++++++++----- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/packages/x-provider/src/l1-providers/metaMaskWrapper.test.ts b/packages/x-provider/src/l1-providers/metaMaskWrapper.test.ts index a694e92194..a72ec330e2 100644 --- a/packages/x-provider/src/l1-providers/metaMaskWrapper.test.ts +++ b/packages/x-provider/src/l1-providers/metaMaskWrapper.test.ts @@ -42,8 +42,13 @@ describe('metaMetaWrapper', () => { describe('connect', () => { it('should create a metamask imx provider with a eth signer and imx signer when calling connect', async () => { - const ethSigner = {}; - const imxSigner = {}; + const ethSigner = { + getAddress: jest.fn().mockResolvedValue('0x123'), + }; + const imxSigner = { + getAddress: jest.fn().mockResolvedValue('0x456'), + signMessage: jest.fn().mockResolvedValue('signed-message'), + }; const getSignerMock = jest.fn().mockReturnValue(ethSigner); (connect as jest.Mock).mockResolvedValue({ @@ -95,40 +100,51 @@ describe('metaMetaWrapper', () => { describe('signMessage', () => { it('should call sign message on imx signer and return a string', async () => { - const getSignerMock = jest.fn().mockReturnValue({}); + const ethSigner = { + getAddress: jest.fn().mockResolvedValue('0x123'), + }; + const imxSigner = { + getAddress: jest.fn().mockResolvedValue('0x456'), + signMessage: jest.fn().mockResolvedValue('signed-message'), + }; + + const getSignerMock = jest.fn().mockReturnValue(ethSigner); (connect as jest.Mock).mockResolvedValue({ getSigner: getSignerMock, }); - const signMessageMock = jest.fn().mockReturnValue('Signed message'); - (buildImxSigner as jest.Mock).mockResolvedValue({ - signMessage: signMessageMock, - }); + (buildImxSigner as jest.Mock).mockResolvedValue(imxSigner); await MetaMaskIMXProvider.connect(config); const signedMessage = await MetaMaskIMXProvider.signMessage( 'Message to sign', ); - expect(signMessageMock).toBeCalledTimes(1); - expect(signMessageMock).toBeCalledWith('Message to sign'); - expect(signedMessage).toEqual('Signed message'); + expect(imxSigner.signMessage).toBeCalledTimes(1); + expect(imxSigner.signMessage).toBeCalledWith('Message to sign'); + expect(signedMessage).toEqual('signed-message'); }); it('should throw provider error when error calling sign message', async () => { + const ethSigner = { + getAddress: jest.fn().mockResolvedValue('0x123'), + }; + const imxSigner = { + getAddress: jest.fn().mockResolvedValue('0x456'), + signMessage: jest.fn().mockRejectedValue(new Error('Sign message failed')), + }; + + const getSignerMock = jest.fn().mockReturnValue(ethSigner); (connect as jest.Mock).mockResolvedValue({ - getSigner: jest.fn().mockReturnValue({}), - }); - (buildImxSigner as jest.Mock).mockResolvedValue({ - signMessage: jest - .fn() - .mockRejectedValue(new Error('Error signing the message')), + getSigner: getSignerMock, }); + (buildImxSigner as jest.Mock).mockResolvedValue(imxSigner); + await MetaMaskIMXProvider.connect(config); await expect( MetaMaskIMXProvider.signMessage('Message to sign'), ).rejects.toThrow( new ProviderError( - 'Error signing the message', + 'Sign message failed', ProviderErrorType.PROVIDER_CONNECTION_ERROR, ), ); @@ -137,10 +153,19 @@ describe('metaMetaWrapper', () => { describe('disconnect', () => { it('should call disconnect with the imx signer', async () => { + const ethSigner = { + getAddress: jest.fn().mockResolvedValue('0x123'), + }; + const imxSigner = { + getAddress: jest.fn().mockResolvedValue('0x456'), + signMessage: jest.fn().mockResolvedValue('signed-message'), + }; + + const getSignerMock = jest.fn().mockReturnValue(ethSigner); (connect as jest.Mock).mockResolvedValue({ - getSigner: jest.fn(), + getSigner: getSignerMock, }); - (buildImxSigner as jest.Mock).mockResolvedValue({}); + (buildImxSigner as jest.Mock).mockResolvedValue(imxSigner); (disconnectImxSigner as jest.Mock).mockResolvedValue({}); await MetaMaskIMXProvider.connect(config); await MetaMaskIMXProvider.disconnect(); @@ -148,10 +173,19 @@ describe('metaMetaWrapper', () => { }); it('should throw provider error when error calling disconnect', async () => { + const ethSigner = { + getAddress: jest.fn().mockResolvedValue('0x123'), + }; + const imxSigner = { + getAddress: jest.fn().mockResolvedValue('0x456'), + signMessage: jest.fn().mockResolvedValue('signed-message'), + }; + + const getSignerMock = jest.fn().mockReturnValue(ethSigner); (connect as jest.Mock).mockResolvedValue({ - getSigner: jest.fn().mockReturnValue({}), + getSigner: getSignerMock, }); - (buildImxSigner as jest.Mock).mockResolvedValue({}); + (buildImxSigner as jest.Mock).mockResolvedValue(imxSigner); (disconnectImxSigner as jest.Mock).mockRejectedValue( new Error('Error disconnecting'), ); From 1169c70e7c4b32970bd2e3446764dfd470f16559 Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Tue, 25 Mar 2025 18:20:18 +1100 Subject: [PATCH 3/8] fix: use byte array for stark key generation signature message Replaces string-based signature message with raw bytes in stark key generation to prevent encoding issues in non-English systems. This aligns with the fix for wallet connection message encoding. --- .../utils/stark/legacy/crypto/constants.ts | 13 +++++++++++- .../x-client/src/utils/stark/starkCurve.ts | 4 ++-- .../x-provider/src/imx-wallet/imxWallet.ts | 21 +++++++++++-------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/packages/x-client/src/utils/stark/legacy/crypto/constants.ts b/packages/x-client/src/utils/stark/legacy/crypto/constants.ts index 73fc31b236..2e49de617c 100644 --- a/packages/x-client/src/utils/stark/legacy/crypto/constants.ts +++ b/packages/x-client/src/utils/stark/legacy/crypto/constants.ts @@ -4,11 +4,21 @@ import BN from 'bn.js'; import elliptic from 'elliptic'; import hashJS from 'hash.js'; +import { toUtf8String } from 'ethers'; import { constantPointsHex } from './points'; import { Instruction, InstructionWithFee } from './types'; const DEFAULT_ACCOUNT_MAPPING_KEY = 'STARKWARE_ACCOUNT_MAPPING'; -const DEFAULT_SIGNATURE_MESSAGE = 'Only sign this request if you’ve initiated an action with Immutable X.'; +// const DEFAULT_SIGNATURE_MESSAGE = 'Only sign this request if you’ve initiated an action with Immutable X.'; +// non-english systems may not encode this correctly +const DEFAULT_SIGNATURE_BYTES = new Uint8Array([ + 79, 110, 108, 121, 32, 115, 105, 103, 110, 32, 116, 104, 105, 115, 32, 114, + 101, 113, 117, 101, 115, 116, 32, 105, 102, 32, 121, 111, 117, 226, 128, 153, + 118, 101, 32, 105, 110, 105, 116, 105, 97, 116, 101, 100, 32, 97, 110, 32, + 97, 99, 116, 105, 111, 110, 32, 119, 105, 116, 104, 32, 73, 109, 109, 117, + 116, 97, 98, 108, 101, 32, 88, 46, +]); +const DEFAULT_SIGNATURE_MESSAGE = toUtf8String(DEFAULT_SIGNATURE_BYTES); const DEFAULT_ACCOUNT_LAYER = 'starkex'; const DEFAULT_ACCOUNT_APPLICATION = 'immutablex'; @@ -95,6 +105,7 @@ export { DEFAULT_ACCOUNT_INDEX, DEFAULT_ACCOUNT_LAYER, DEFAULT_ACCOUNT_MAPPING_KEY, + DEFAULT_SIGNATURE_BYTES, DEFAULT_SIGNATURE_MESSAGE, instructionEncodingMap, MAX_ECDSA_BN, diff --git a/packages/x-client/src/utils/stark/starkCurve.ts b/packages/x-client/src/utils/stark/starkCurve.ts index b79dd5db72..9b080075c1 100644 --- a/packages/x-client/src/utils/stark/starkCurve.ts +++ b/packages/x-client/src/utils/stark/starkCurve.ts @@ -6,7 +6,7 @@ import * as encUtils from 'enc-utils'; // eslint-disable-next-line @typescript-eslint/naming-convention import BN from 'bn.js'; import { hdkey } from '@ethereumjs/wallet'; -import { Signature, Signer, toUtf8Bytes } from 'ethers'; +import { Signature, Signer } from 'ethers'; import { createStarkSigner } from './starkSigner'; import * as legacy from './legacy/crypto'; import { getStarkPublicKeyFromImx } from './getStarkPublicKeyFromImx'; @@ -286,7 +286,7 @@ export async function generateLegacyStarkPrivateKey( signer: Signer, ): Promise { const address = (await signer.getAddress()).toLowerCase(); - const signature = await signer.signMessage(toUtf8Bytes(legacy.DEFAULT_SIGNATURE_MESSAGE)); + const signature = await signer.signMessage(legacy.DEFAULT_SIGNATURE_BYTES); const seed = Signature.from(signature).s; const path = legacy.getAccountPath( legacy.DEFAULT_ACCOUNT_LAYER, diff --git a/packages/x-provider/src/imx-wallet/imxWallet.ts b/packages/x-provider/src/imx-wallet/imxWallet.ts index 9c577ed6f6..6601708ede 100644 --- a/packages/x-provider/src/imx-wallet/imxWallet.ts +++ b/packages/x-provider/src/imx-wallet/imxWallet.ts @@ -1,8 +1,6 @@ import { Environment } from '@imtbl/config'; import { BrowserProvider, - getBytes, - toUtf8Bytes, toUtf8String, } from 'ethers'; import { @@ -21,7 +19,14 @@ import { messageResponseListener } from './messageResponseListener'; import { ImxSigner } from './ImxSigner'; import { getOrSetupIFrame } from './imxWalletIFrame'; -const DEFAULT_CONNECTION_MESSAGE = 'Only sign this request if you’ve initiated an action with Immutable X.'; +// "Only sign this request if you've initiated an action with Immutable X." +const DEFAULT_CONNECTION_BYTES = new Uint8Array([ + 79, 110, 108, 121, 32, 115, 105, 103, 110, 32, 116, 104, 105, 115, 32, 114, + 101, 113, 117, 101, 115, 116, 32, 105, 102, 32, 121, 111, 117, 226, 128, 153, + 118, 101, 32, 105, 110, 105, 116, 105, 97, 116, 101, 100, 32, 97, 110, 32, + 97, 99, 116, 105, 111, 110, 32, 119, 105, 116, 104, 32, 73, 109, 109, 117, + 116, 97, 98, 108, 101, 32, 88, 46, +]); const CONNECTION_FAILED_ERROR = 'The L2 IMX Wallet connection has failed'; export async function connect( @@ -31,13 +36,11 @@ export async function connect( const l1Signer = await l1Provider.getSigner(); const address = await l1Signer.getAddress(); - console.log('DEFAULT_CONNECTION_MESSAGE', { message: DEFAULT_CONNECTION_MESSAGE }); - console.log('toUtf8Bytes.toString()', { toUtf8Bytes: toUtf8Bytes(DEFAULT_CONNECTION_MESSAGE).toString() }); + // log read message here + console.log('DEFAULT_CONNECTION_BYTES.toString()', { bytes: DEFAULT_CONNECTION_BYTES.toString() }); + console.log('DEFAULT_CONNECTION_BYTES.toUtf8String()', { bytes: toUtf8String(DEFAULT_CONNECTION_BYTES) }); - console.log('toUtf8String 1', { toUtf8String: toUtf8String(toUtf8Bytes(DEFAULT_CONNECTION_MESSAGE)) }); - console.log('toUtf8String 2', { toUtf8String: toUtf8String(getBytes(toUtf8Bytes(DEFAULT_CONNECTION_MESSAGE))) }); - - const signature = await l1Signer.signMessage(toUtf8Bytes(DEFAULT_CONNECTION_MESSAGE)); + const signature = await l1Signer.signMessage(DEFAULT_CONNECTION_BYTES); const iframe = await getOrSetupIFrame(env); return new Promise((resolve, reject) => { From 638aae10fabb88306ce2e577e8a2e8a2f9d80188 Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Wed, 26 Mar 2025 16:08:32 +1100 Subject: [PATCH 4/8] fix(crypto): fix utf-8 encoding during L1 signing - Add debug logs to track utf-8 byte encoding/decoding - Compare utf-8 bytes between TextEncoder/TextDecoder and ethers.toUtf8Bytes - Attempt to fix encoding issue by using ethers.toUtf8Bytes directly for signing - Add validation that encoded bytes match expected connection string --- packages/internal/toolkit/src/crypto.ts | 33 +++++++++++++++++-- packages/x-client/src/utils/crypto/crypto.ts | 13 +++++++- .../x-provider/src/imx-wallet/ImxSigner.ts | 4 --- .../x-provider/src/imx-wallet/imxWallet.ts | 32 ++++++++++++++++++ 4 files changed, 75 insertions(+), 7 deletions(-) diff --git a/packages/internal/toolkit/src/crypto.ts b/packages/internal/toolkit/src/crypto.ts index a10107eb7e..c6e1725655 100644 --- a/packages/internal/toolkit/src/crypto.ts +++ b/packages/internal/toolkit/src/crypto.ts @@ -43,8 +43,37 @@ export async function signRaw( signer: Signer, ): Promise { console.log('signRaw.payload', { payload }); - console.log('signRaw.toUtf8Bytes', { toUtf8Bytes: toUtf8Bytes(payload).toString() }); - const signature = deserializeSignature(await signer.signMessage(toUtf8Bytes(payload))); + console.log('signRaw.toUtf8Bytes', { bytes: toUtf8Bytes(payload).toString() }); + console.log('signRaw.payload.normalize() === payload', { result: payload === payload.normalize() }); + + // prevent utf-8 encoding issues + const encoder = new TextEncoder(); + const buffer = encoder.encode(payload); + // use this message to sign + const message = new TextDecoder('utf-8').decode(buffer); + + const buffer2 = Buffer.from(payload, 'utf8'); + const message2 = new TextDecoder('utf-8').decode(buffer2); + + // compare message utf8 bytes with payload.normalize() + console.log('signRaw.message === payload.normalize()', { result: message === payload.normalize() }); + console.log('signRaw.message2 === payload.normalize()', { result: message2 === payload.normalize() }); + + // output utf8 bytes + console.log('signRaw.message', { message, bytes: toUtf8Bytes(message).toString() }); + console.log('signRaw.message2', { message2, bytes: toUtf8Bytes(message2).toString() }); + + // compare utf8 bytes output + console.log( + 'signRaw.toUtf8Bytes === toUtf8Bytes(message)', + { result: toUtf8Bytes(payload).toString() === toUtf8Bytes(message).toString() }, + ); + console.log( + 'signRaw.toUtf8Bytes === toUtf8Bytes(message2)', + { result: toUtf8Bytes(payload).toString() === toUtf8Bytes(message2).toString() }, + ); + + const signature = deserializeSignature(await signer.signMessage(toUtf8Bytes(message))); return serializeEthSignature(signature); } diff --git a/packages/x-client/src/utils/crypto/crypto.ts b/packages/x-client/src/utils/crypto/crypto.ts index a13f0029eb..2732cfb84d 100644 --- a/packages/x-client/src/utils/crypto/crypto.ts +++ b/packages/x-client/src/utils/crypto/crypto.ts @@ -48,7 +48,18 @@ export async function signRaw( payload: string, signer: Signer, ): Promise { - const signature = deserializeSignature(await signer.signMessage(payload)); + // prevent utf-8 encoding issues + const encoder = new TextEncoder(); + const buffer = encoder.encode(payload); + const message = new TextDecoder('utf-8').decode(buffer); + + const buffer2 = Buffer.from(payload, 'utf8'); + const message2 = new TextDecoder('utf-8').decode(buffer2); + + console.log('signRaw.message', { message }); + console.log('signRaw.message2', { message2 }); + + const signature = deserializeSignature(await signer.signMessage(message)); return serializeEthSignature(signature); } diff --git a/packages/x-provider/src/imx-wallet/ImxSigner.ts b/packages/x-provider/src/imx-wallet/ImxSigner.ts index 29bfee856f..7df7d8b5c1 100644 --- a/packages/x-provider/src/imx-wallet/ImxSigner.ts +++ b/packages/x-provider/src/imx-wallet/ImxSigner.ts @@ -1,5 +1,4 @@ import { StarkSigner } from '@imtbl/x-client'; -import { toUtf8Bytes } from 'ethers'; import { COMMUNICATION_TYPE, ResponseEventType, @@ -29,9 +28,6 @@ export class ImxSigner implements StarkSigner { } public signMessage(rawMessage: string): Promise { - console.log('signMessage.rawMessage', { rawMessage }); - console.log('signMessage.toUtf8Bytes.toString()', { toUtf8Bytes: toUtf8Bytes(rawMessage).toString() }); - return new Promise((resolve, reject) => { const listener = (event: MessageEvent) => { messageResponseListener( diff --git a/packages/x-provider/src/imx-wallet/imxWallet.ts b/packages/x-provider/src/imx-wallet/imxWallet.ts index 6601708ede..ecaf7f5449 100644 --- a/packages/x-provider/src/imx-wallet/imxWallet.ts +++ b/packages/x-provider/src/imx-wallet/imxWallet.ts @@ -1,6 +1,7 @@ import { Environment } from '@imtbl/config'; import { BrowserProvider, + toUtf8Bytes, toUtf8String, } from 'ethers'; import { @@ -27,6 +28,37 @@ const DEFAULT_CONNECTION_BYTES = new Uint8Array([ 97, 99, 116, 105, 111, 110, 32, 119, 105, 116, 104, 32, 73, 109, 109, 117, 116, 97, 98, 108, 101, 32, 88, 46, ]); +const DEFAULT_CONNECTION_STRING_1 = 'Only sign this request if you’ve initiated an action with Immutable X.'; +const DEFAULT_CONNECTION_STRING_2 = Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString('utf8'); +console.log('DEFAULT_CONNECTION_STRING_2', { string: DEFAULT_CONNECTION_STRING_2 }); + +// log utf8 bytes +console.log('DEFAULT_CONNECTION_BYTES.toString()', { bytes: DEFAULT_CONNECTION_BYTES.toString() }); +console.log('DEFAULT_CONNECTION_STRING_1', { bytes: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString() }); +console.log('DEFAULT_CONNECTION_STRING_2', { bytes: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString() }); +console.log( + 'DEFAULT_CONNECTION_STRING_1.normalize()', + { bytes: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1.normalize()).toString() }, +); +console.log( + 'DEFAULT_CONNECTION_STRING_2.normalize()', + { bytes: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2.normalize()).toString() }, +); +console.log( + 'Buffer.from(DEFAULT_CONNECTION_STRING_1, utf8).toString()', + { bytes: Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString() }, +); + +// console.log if the bytes of DEFAULT_CONNECTION_STRING_1 and DEFAULT_CONNECTION_STRING_2 are the same as DEFAULT_CONNECTION_BYTES +console.log( + 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1)', + { bytes: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString() }, +); +console.log( + 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2)', + { bytes: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString() }, +); + const CONNECTION_FAILED_ERROR = 'The L2 IMX Wallet connection has failed'; export async function connect( From ced95aaaf51a5054413cd6873270e84f77c63f87 Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Wed, 26 Mar 2025 16:29:33 +1100 Subject: [PATCH 5/8] Add TextDecoder to jest --- packages/passport/sdk/jest.setup.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/passport/sdk/jest.setup.js b/packages/passport/sdk/jest.setup.js index 2e10cd9913..19bb4a9b80 100644 --- a/packages/passport/sdk/jest.setup.js +++ b/packages/passport/sdk/jest.setup.js @@ -1,7 +1,7 @@ -import { TextEncoder } from 'util'; +import { TextEncoder, TextDecoder } from 'util'; global.TextEncoder = TextEncoder; - +global.TextDecoder = TextDecoder; /** * Required for ethers v6 * @see https://github.com/ethers-io/ethers.js/issues/4365 From 9e14332c36f6e85d9ec46c6e04efee3629097851 Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Thu, 27 Mar 2025 17:24:13 +1100 Subject: [PATCH 6/8] Change console.log -> track --- packages/internal/toolkit/package.json | 1 + packages/internal/toolkit/src/crypto.ts | 62 ++++++++++++---- packages/x-provider/package.json | 1 + .../x-provider/src/imx-wallet/imxWallet.ts | 71 +++++++++++-------- .../src/l1-providers/metaMaskWrapper.ts | 11 ++- pnpm-lock.yaml | 6 ++ 6 files changed, 108 insertions(+), 44 deletions(-) diff --git a/packages/internal/toolkit/package.json b/packages/internal/toolkit/package.json index 0ba440999a..45b292ce7a 100644 --- a/packages/internal/toolkit/package.json +++ b/packages/internal/toolkit/package.json @@ -6,6 +6,7 @@ "bugs": "https://github.com/immutable/ts-immutable-sdk/issues", "dependencies": { "@imtbl/x-client": "workspace:*", + "@imtbl/metrics": "workspace:*", "@magic-ext/oidc": "12.0.2", "@metamask/detect-provider": "^2.0.0", "axios": "^1.6.5", diff --git a/packages/internal/toolkit/src/crypto.ts b/packages/internal/toolkit/src/crypto.ts index c6e1725655..d3b4c781e8 100644 --- a/packages/internal/toolkit/src/crypto.ts +++ b/packages/internal/toolkit/src/crypto.ts @@ -1,6 +1,7 @@ import BN from 'bn.js'; import * as encUtils from 'enc-utils'; import { Signer, toUtf8Bytes } from 'ethers'; +import { track } from '@imtbl/metrics'; type SignatureOptions = { r: BN; @@ -42,9 +43,16 @@ export async function signRaw( payload: string, signer: Signer, ): Promise { - console.log('signRaw.payload', { payload }); - console.log('signRaw.toUtf8Bytes', { bytes: toUtf8Bytes(payload).toString() }); - console.log('signRaw.payload.normalize() === payload', { result: payload === payload.normalize() }); + track('internal.crypto', 'log', { param: 'signRaw.payload', val: payload }); + track('internal.crypto', 'log', { param: 'signRaw.toUtf8Bytes', val: toUtf8Bytes(payload).toString() }); + track( + 'internal.crypto', + 'log', + { + param: 'signRaw.payload.normalize() === payload', + val: payload === payload.normalize(), + }, + ); // prevent utf-8 encoding issues const encoder = new TextEncoder(); @@ -56,21 +64,47 @@ export async function signRaw( const message2 = new TextDecoder('utf-8').decode(buffer2); // compare message utf8 bytes with payload.normalize() - console.log('signRaw.message === payload.normalize()', { result: message === payload.normalize() }); - console.log('signRaw.message2 === payload.normalize()', { result: message2 === payload.normalize() }); + track( + 'internal.crypto', + 'log', + { + param: 'signRaw.message === payload.normalize()', + val: message === payload.normalize(), + }, + ); + track( + 'internal.crypto', + 'log', + { param: 'signRaw.message2 === payload.normalize()', val: message2 === payload.normalize() }, + ); // output utf8 bytes - console.log('signRaw.message', { message, bytes: toUtf8Bytes(message).toString() }); - console.log('signRaw.message2', { message2, bytes: toUtf8Bytes(message2).toString() }); - + track( + 'internal.crypto', + 'log', + { param: 'signRaw.message', val: message, bytes: toUtf8Bytes(message).toString() }, + ); + track( + 'internal.crypto', + 'log', + { param: 'signRaw.message2', val: message2, bytes: toUtf8Bytes(message2).toString() }, + ); // compare utf8 bytes output - console.log( - 'signRaw.toUtf8Bytes === toUtf8Bytes(message)', - { result: toUtf8Bytes(payload).toString() === toUtf8Bytes(message).toString() }, + track( + 'internal.crypto', + 'log', + { + param: 'signRaw.toUtf8Bytes === toUtf8Bytes(message)', + val: toUtf8Bytes(payload).toString() === toUtf8Bytes(message).toString(), + }, ); - console.log( - 'signRaw.toUtf8Bytes === toUtf8Bytes(message2)', - { result: toUtf8Bytes(payload).toString() === toUtf8Bytes(message2).toString() }, + track( + 'internal.crypto', + 'log', + { + param: 'signRaw.toUtf8Bytes === toUtf8Bytes(message2)', + val: toUtf8Bytes(payload).toString() === toUtf8Bytes(message2).toString(), + }, ); const signature = deserializeSignature(await signer.signMessage(toUtf8Bytes(message))); diff --git a/packages/x-provider/package.json b/packages/x-provider/package.json index 13d7ab37de..b06eae0e03 100644 --- a/packages/x-provider/package.json +++ b/packages/x-provider/package.json @@ -9,6 +9,7 @@ "@imtbl/generated-clients": "workspace:*", "@imtbl/toolkit": "workspace:*", "@imtbl/x-client": "workspace:*", + "@imtbl/metrics": "workspace:*", "@magic-ext/oidc": "12.0.2", "@metamask/detect-provider": "^2.0.0", "axios": "^1.6.5", diff --git a/packages/x-provider/src/imx-wallet/imxWallet.ts b/packages/x-provider/src/imx-wallet/imxWallet.ts index ecaf7f5449..90441ea776 100644 --- a/packages/x-provider/src/imx-wallet/imxWallet.ts +++ b/packages/x-provider/src/imx-wallet/imxWallet.ts @@ -4,6 +4,7 @@ import { toUtf8Bytes, toUtf8String, } from 'ethers'; +import { track } from '@imtbl/metrics'; import { ConnectRequest, ConnectResponse, @@ -30,35 +31,47 @@ const DEFAULT_CONNECTION_BYTES = new Uint8Array([ ]); const DEFAULT_CONNECTION_STRING_1 = 'Only sign this request if you’ve initiated an action with Immutable X.'; const DEFAULT_CONNECTION_STRING_2 = Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString('utf8'); -console.log('DEFAULT_CONNECTION_STRING_2', { string: DEFAULT_CONNECTION_STRING_2 }); - -// log utf8 bytes -console.log('DEFAULT_CONNECTION_BYTES.toString()', { bytes: DEFAULT_CONNECTION_BYTES.toString() }); -console.log('DEFAULT_CONNECTION_STRING_1', { bytes: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString() }); -console.log('DEFAULT_CONNECTION_STRING_2', { bytes: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString() }); -console.log( - 'DEFAULT_CONNECTION_STRING_1.normalize()', - { bytes: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1.normalize()).toString() }, -); -console.log( - 'DEFAULT_CONNECTION_STRING_2.normalize()', - { bytes: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2.normalize()).toString() }, -); -console.log( - 'Buffer.from(DEFAULT_CONNECTION_STRING_1, utf8).toString()', - { bytes: Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString() }, -); -// console.log if the bytes of DEFAULT_CONNECTION_STRING_1 and DEFAULT_CONNECTION_STRING_2 are the same as DEFAULT_CONNECTION_BYTES -console.log( - 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1)', - { bytes: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString() }, +// track language and charset +track('xProvider', 'log', { param: 'navigator.language', val: navigator?.language }); +track('xProvider', 'log', { param: 'navigator.languages', val: navigator?.languages?.join(',') }); +track('xProvider', 'log', { param: 'document.characterSet', val: document?.characterSet }); + +track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_STRING_2', val: DEFAULT_CONNECTION_STRING_2 }); +track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_BYTES', val: DEFAULT_CONNECTION_BYTES.toString() }); +track( + 'xProvider', + 'log', + { param: 'DEFAULT_CONNECTION_STRING_1', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString() }, ); -console.log( - 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2)', - { bytes: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString() }, +track( + 'xProvider', + 'log', + { param: 'DEFAULT_CONNECTION_STRING_2', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString() }, ); +track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_STRING_1.normalize()', + val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1.normalize()).toString(), +}); +track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_STRING_2.normalize()', + val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2.normalize()).toString(), +}); +track('xProvider', 'log', { + param: 'Buffer.from(DEFAULT_CONNECTION_STRING_1, utf8).toString()', + val: Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString(), +}); + +track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1)', + val: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString(), +}); +track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2)', + val: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString(), +}); + const CONNECTION_FAILED_ERROR = 'The L2 IMX Wallet connection has failed'; export async function connect( @@ -68,9 +81,11 @@ export async function connect( const l1Signer = await l1Provider.getSigner(); const address = await l1Signer.getAddress(); - // log read message here - console.log('DEFAULT_CONNECTION_BYTES.toString()', { bytes: DEFAULT_CONNECTION_BYTES.toString() }); - console.log('DEFAULT_CONNECTION_BYTES.toUtf8String()', { bytes: toUtf8String(DEFAULT_CONNECTION_BYTES) }); + track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_BYTES', val: DEFAULT_CONNECTION_BYTES.toString() }); + track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_BYTES.toUtf8String()', + val: toUtf8String(DEFAULT_CONNECTION_BYTES), + }); const signature = await l1Signer.signMessage(DEFAULT_CONNECTION_BYTES); const iframe = await getOrSetupIFrame(env); diff --git a/packages/x-provider/src/l1-providers/metaMaskWrapper.ts b/packages/x-provider/src/l1-providers/metaMaskWrapper.ts index e7bf452888..885789b7da 100644 --- a/packages/x-provider/src/l1-providers/metaMaskWrapper.ts +++ b/packages/x-provider/src/l1-providers/metaMaskWrapper.ts @@ -1,3 +1,4 @@ +import { track } from '@imtbl/metrics'; import { ProviderConfiguration } from '../config'; import { connect } from './metaMask'; import { @@ -30,8 +31,14 @@ export class MetaMaskIMXProvider extends GenericIMXProvider { const signer = await metaMaskProvider.getSigner(); - console.log('metaMaskProvider.getSigner().getAddress()', await signer.getAddress()); - console.log('imxSigner.getAddress()', this.imxSigner.getAddress()); + track('xProvider', 'log', { + param: 'metaMaskProvider.getSigner().getAddress()', + val: await signer.getAddress(), + }); + track('xProvider', 'log', { + param: 'imxSigner.getAddress()', + val: this.imxSigner.getAddress(), + }); return new MetaMaskIMXProvider( config, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 88d5e26a7c..6a7a8a0bf9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1858,6 +1858,9 @@ importers: packages/internal/toolkit: dependencies: + '@imtbl/metrics': + specifier: workspace:* + version: link:../metrics '@imtbl/x-client': specifier: workspace:* version: link:../../x-client @@ -2391,6 +2394,9 @@ importers: '@imtbl/generated-clients': specifier: workspace:* version: link:../internal/generated-clients + '@imtbl/metrics': + specifier: workspace:* + version: link:../internal/metrics '@imtbl/toolkit': specifier: workspace:* version: link:../internal/toolkit From 9e19a7825cf27c19cc9840f9528521197638382d Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Thu, 27 Mar 2025 17:41:24 +1100 Subject: [PATCH 7/8] Reorganise logs --- packages/internal/toolkit/src/crypto.ts | 18 ++-- .../x-provider/src/imx-wallet/imxWallet.ts | 91 ++++++++++--------- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/packages/internal/toolkit/src/crypto.ts b/packages/internal/toolkit/src/crypto.ts index d3b4c781e8..c0cf58f40c 100644 --- a/packages/internal/toolkit/src/crypto.ts +++ b/packages/internal/toolkit/src/crypto.ts @@ -43,10 +43,10 @@ export async function signRaw( payload: string, signer: Signer, ): Promise { - track('internal.crypto', 'log', { param: 'signRaw.payload', val: payload }); - track('internal.crypto', 'log', { param: 'signRaw.toUtf8Bytes', val: toUtf8Bytes(payload).toString() }); + track('xProvider', 'log', { param: 'signRaw.payload', val: payload }); + track('xProvider', 'log', { param: 'signRaw.toUtf8Bytes', val: toUtf8Bytes(payload).toString() }); track( - 'internal.crypto', + 'xProvider', 'log', { param: 'signRaw.payload.normalize() === payload', @@ -65,7 +65,7 @@ export async function signRaw( // compare message utf8 bytes with payload.normalize() track( - 'internal.crypto', + 'xProvider', 'log', { param: 'signRaw.message === payload.normalize()', @@ -73,25 +73,25 @@ export async function signRaw( }, ); track( - 'internal.crypto', + 'xProvider', 'log', { param: 'signRaw.message2 === payload.normalize()', val: message2 === payload.normalize() }, ); // output utf8 bytes track( - 'internal.crypto', + 'xProvider', 'log', { param: 'signRaw.message', val: message, bytes: toUtf8Bytes(message).toString() }, ); track( - 'internal.crypto', + 'xProvider', 'log', { param: 'signRaw.message2', val: message2, bytes: toUtf8Bytes(message2).toString() }, ); // compare utf8 bytes output track( - 'internal.crypto', + 'xProvider', 'log', { param: 'signRaw.toUtf8Bytes === toUtf8Bytes(message)', @@ -99,7 +99,7 @@ export async function signRaw( }, ); track( - 'internal.crypto', + 'xProvider', 'log', { param: 'signRaw.toUtf8Bytes === toUtf8Bytes(message2)', diff --git a/packages/x-provider/src/imx-wallet/imxWallet.ts b/packages/x-provider/src/imx-wallet/imxWallet.ts index 90441ea776..fb03fbba47 100644 --- a/packages/x-provider/src/imx-wallet/imxWallet.ts +++ b/packages/x-provider/src/imx-wallet/imxWallet.ts @@ -31,48 +31,53 @@ const DEFAULT_CONNECTION_BYTES = new Uint8Array([ ]); const DEFAULT_CONNECTION_STRING_1 = 'Only sign this request if you’ve initiated an action with Immutable X.'; const DEFAULT_CONNECTION_STRING_2 = Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString('utf8'); +const CONNECTION_FAILED_ERROR = 'The L2 IMX Wallet connection has failed'; -// track language and charset -track('xProvider', 'log', { param: 'navigator.language', val: navigator?.language }); -track('xProvider', 'log', { param: 'navigator.languages', val: navigator?.languages?.join(',') }); -track('xProvider', 'log', { param: 'document.characterSet', val: document?.characterSet }); - -track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_STRING_2', val: DEFAULT_CONNECTION_STRING_2 }); -track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_BYTES', val: DEFAULT_CONNECTION_BYTES.toString() }); -track( - 'xProvider', - 'log', - { param: 'DEFAULT_CONNECTION_STRING_1', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString() }, -); -track( - 'xProvider', - 'log', - { param: 'DEFAULT_CONNECTION_STRING_2', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString() }, -); - -track('xProvider', 'log', { - param: 'DEFAULT_CONNECTION_STRING_1.normalize()', - val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1.normalize()).toString(), -}); -track('xProvider', 'log', { - param: 'DEFAULT_CONNECTION_STRING_2.normalize()', - val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2.normalize()).toString(), -}); -track('xProvider', 'log', { - param: 'Buffer.from(DEFAULT_CONNECTION_STRING_1, utf8).toString()', - val: Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString(), -}); - -track('xProvider', 'log', { - param: 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1)', - val: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString(), -}); -track('xProvider', 'log', { - param: 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2)', - val: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString(), -}); +function trackConnectionDetails() { + // track language and charset + track('xProvider', 'log', { param: 'navigator.language', val: navigator?.language }); + track('xProvider', 'log', { param: 'navigator.languages', val: navigator?.languages?.join(',') }); + track('xProvider', 'log', { param: 'document.characterSet', val: document?.characterSet }); -const CONNECTION_FAILED_ERROR = 'The L2 IMX Wallet connection has failed'; + // track connection encoding details + track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_STRING_2', val: DEFAULT_CONNECTION_STRING_2 }); + track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_BYTES', val: DEFAULT_CONNECTION_BYTES.toString() }); + track( + 'xProvider', + 'log', + { param: 'DEFAULT_CONNECTION_STRING_1', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString() }, + ); + track( + 'xProvider', + 'log', + { param: 'DEFAULT_CONNECTION_STRING_2', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString() }, + ); + track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_STRING_1.normalize()', + val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1.normalize()).toString(), + }); + track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_STRING_2.normalize()', + val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2.normalize()).toString(), + }); + track('xProvider', 'log', { + param: 'Buffer.from(DEFAULT_CONNECTION_STRING_1, utf8).toString()', + val: Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString(), + }); + track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1)', + val: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString(), + }); + track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2)', + val: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString(), + }); + track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_BYTES', val: DEFAULT_CONNECTION_BYTES.toString() }); + track('xProvider', 'log', { + param: 'DEFAULT_CONNECTION_BYTES.toUtf8String()', + val: toUtf8String(DEFAULT_CONNECTION_BYTES), + }); +} export async function connect( l1Provider: BrowserProvider, @@ -81,11 +86,7 @@ export async function connect( const l1Signer = await l1Provider.getSigner(); const address = await l1Signer.getAddress(); - track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_BYTES', val: DEFAULT_CONNECTION_BYTES.toString() }); - track('xProvider', 'log', { - param: 'DEFAULT_CONNECTION_BYTES.toUtf8String()', - val: toUtf8String(DEFAULT_CONNECTION_BYTES), - }); + trackConnectionDetails(); const signature = await l1Signer.signMessage(DEFAULT_CONNECTION_BYTES); const iframe = await getOrSetupIFrame(env); From faae51e1b1e43d3a04081a5da303688514c0f108 Mon Sep 17 00:00:00 2001 From: Bryan Dichtl Date: Fri, 28 Mar 2025 10:41:17 +1100 Subject: [PATCH 8/8] Add l1 address to logs --- packages/internal/toolkit/src/crypto.ts | 97 +++++++++---------- .../x-provider/src/imx-wallet/imxWallet.ts | 54 +++++++---- .../src/l1-providers/metaMaskWrapper.ts | 5 +- 3 files changed, 88 insertions(+), 68 deletions(-) diff --git a/packages/internal/toolkit/src/crypto.ts b/packages/internal/toolkit/src/crypto.ts index c0cf58f40c..bacbd1e795 100644 --- a/packages/internal/toolkit/src/crypto.ts +++ b/packages/internal/toolkit/src/crypto.ts @@ -43,16 +43,22 @@ export async function signRaw( payload: string, signer: Signer, ): Promise { - track('xProvider', 'log', { param: 'signRaw.payload', val: payload }); - track('xProvider', 'log', { param: 'signRaw.toUtf8Bytes', val: toUtf8Bytes(payload).toString() }); - track( - 'xProvider', - 'log', - { - param: 'signRaw.payload.normalize() === payload', - val: payload === payload.normalize(), - }, - ); + const address = await signer.getAddress(); + track('xProvider', 'log', { + address, + param: 'signRaw.payload', + val: payload, + }); + track('xProvider', 'log', { + address, + param: 'signRaw.toUtf8Bytes', + val: toUtf8Bytes(payload).toString(), + }); + track('xProvider', 'log', { + address, + param: 'signRaw.payload.normalize() === payload', + val: payload === payload.normalize(), + }); // prevent utf-8 encoding issues const encoder = new TextEncoder(); @@ -64,48 +70,41 @@ export async function signRaw( const message2 = new TextDecoder('utf-8').decode(buffer2); // compare message utf8 bytes with payload.normalize() - track( - 'xProvider', - 'log', - { - param: 'signRaw.message === payload.normalize()', - val: message === payload.normalize(), - }, - ); - track( - 'xProvider', - 'log', - { param: 'signRaw.message2 === payload.normalize()', val: message2 === payload.normalize() }, - ); + track('xProvider', 'log', { + address, + param: 'signRaw.message === payload.normalize()', + val: message === payload.normalize(), + }); + track('xProvider', 'log', { + address, + param: 'signRaw.message2 === payload.normalize()', + val: message2 === payload.normalize(), + }); // output utf8 bytes - track( - 'xProvider', - 'log', - { param: 'signRaw.message', val: message, bytes: toUtf8Bytes(message).toString() }, - ); - track( - 'xProvider', - 'log', - { param: 'signRaw.message2', val: message2, bytes: toUtf8Bytes(message2).toString() }, - ); + track('xProvider', 'log', { + address, + param: 'signRaw.message', + val: message, + bytes: toUtf8Bytes(message).toString(), + }); + track('xProvider', 'log', { + address, + param: 'signRaw.message2', + val: message2, + bytes: toUtf8Bytes(message2).toString(), + }); // compare utf8 bytes output - track( - 'xProvider', - 'log', - { - param: 'signRaw.toUtf8Bytes === toUtf8Bytes(message)', - val: toUtf8Bytes(payload).toString() === toUtf8Bytes(message).toString(), - }, - ); - track( - 'xProvider', - 'log', - { - param: 'signRaw.toUtf8Bytes === toUtf8Bytes(message2)', - val: toUtf8Bytes(payload).toString() === toUtf8Bytes(message2).toString(), - }, - ); + track('xProvider', 'log', { + address, + param: 'signRaw.toUtf8Bytes === toUtf8Bytes(message)', + val: toUtf8Bytes(payload).toString() === toUtf8Bytes(message).toString(), + }); + track('xProvider', 'log', { + address, + param: 'signRaw.toUtf8Bytes === toUtf8Bytes(message2)', + val: toUtf8Bytes(payload).toString() === toUtf8Bytes(message2).toString(), + }); const signature = deserializeSignature(await signer.signMessage(toUtf8Bytes(message))); return serializeEthSignature(signature); diff --git a/packages/x-provider/src/imx-wallet/imxWallet.ts b/packages/x-provider/src/imx-wallet/imxWallet.ts index fb03fbba47..e2308fbbe0 100644 --- a/packages/x-provider/src/imx-wallet/imxWallet.ts +++ b/packages/x-provider/src/imx-wallet/imxWallet.ts @@ -33,47 +33,65 @@ const DEFAULT_CONNECTION_STRING_1 = 'Only sign this request if you’ve initiate const DEFAULT_CONNECTION_STRING_2 = Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString('utf8'); const CONNECTION_FAILED_ERROR = 'The L2 IMX Wallet connection has failed'; -function trackConnectionDetails() { +function trackConnectionDetails(address: string) { // track language and charset - track('xProvider', 'log', { param: 'navigator.language', val: navigator?.language }); - track('xProvider', 'log', { param: 'navigator.languages', val: navigator?.languages?.join(',') }); - track('xProvider', 'log', { param: 'document.characterSet', val: document?.characterSet }); + track('xProvider', 'log', { address, param: 'navigator.language', val: navigator?.language }); + track('xProvider', 'log', { address, param: 'navigator.languages', val: navigator?.languages?.join(',') }); + track('xProvider', 'log', { address, param: 'document.characterSet', val: document?.characterSet }); // track connection encoding details - track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_STRING_2', val: DEFAULT_CONNECTION_STRING_2 }); - track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_BYTES', val: DEFAULT_CONNECTION_BYTES.toString() }); - track( - 'xProvider', - 'log', - { param: 'DEFAULT_CONNECTION_STRING_1', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString() }, - ); - track( - 'xProvider', - 'log', - { param: 'DEFAULT_CONNECTION_STRING_2', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString() }, - ); track('xProvider', 'log', { + address, + param: 'DEFAULT_CONNECTION_STRING_2', + val: DEFAULT_CONNECTION_STRING_2, + }); + track('xProvider', 'log', { + address, + param: 'DEFAULT_CONNECTION_BYTES', + val: DEFAULT_CONNECTION_BYTES.toString(), + }); + track('xProvider', 'log', { + address, + param: 'DEFAULT_CONNECTION_STRING_1', + val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString(), + }); + track('xProvider', 'log', { + address, + param: 'DEFAULT_CONNECTION_STRING_2', + val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString(), + }); + track('xProvider', 'log', { + address, param: 'DEFAULT_CONNECTION_STRING_1.normalize()', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_1.normalize()).toString(), }); track('xProvider', 'log', { + address, param: 'DEFAULT_CONNECTION_STRING_2.normalize()', val: toUtf8Bytes(DEFAULT_CONNECTION_STRING_2.normalize()).toString(), }); track('xProvider', 'log', { + address, param: 'Buffer.from(DEFAULT_CONNECTION_STRING_1, utf8).toString()', val: Buffer.from(DEFAULT_CONNECTION_STRING_1, 'utf8').toString(), }); track('xProvider', 'log', { + address, param: 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1)', val: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_1).toString(), }); track('xProvider', 'log', { + address, param: 'DEFAULT_CONNECTION_BYTES === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2)', val: DEFAULT_CONNECTION_BYTES.toString() === toUtf8Bytes(DEFAULT_CONNECTION_STRING_2).toString(), }); - track('xProvider', 'log', { param: 'DEFAULT_CONNECTION_BYTES', val: DEFAULT_CONNECTION_BYTES.toString() }); track('xProvider', 'log', { + address, + param: 'DEFAULT_CONNECTION_BYTES', + val: DEFAULT_CONNECTION_BYTES.toString(), + }); + track('xProvider', 'log', { + address, param: 'DEFAULT_CONNECTION_BYTES.toUtf8String()', val: toUtf8String(DEFAULT_CONNECTION_BYTES), }); @@ -86,7 +104,7 @@ export async function connect( const l1Signer = await l1Provider.getSigner(); const address = await l1Signer.getAddress(); - trackConnectionDetails(); + trackConnectionDetails(address); const signature = await l1Signer.signMessage(DEFAULT_CONNECTION_BYTES); const iframe = await getOrSetupIFrame(env); diff --git a/packages/x-provider/src/l1-providers/metaMaskWrapper.ts b/packages/x-provider/src/l1-providers/metaMaskWrapper.ts index 885789b7da..9072055b55 100644 --- a/packages/x-provider/src/l1-providers/metaMaskWrapper.ts +++ b/packages/x-provider/src/l1-providers/metaMaskWrapper.ts @@ -30,12 +30,15 @@ export class MetaMaskIMXProvider extends GenericIMXProvider { ); const signer = await metaMaskProvider.getSigner(); + const address = await signer.getAddress(); track('xProvider', 'log', { + address, param: 'metaMaskProvider.getSigner().getAddress()', - val: await signer.getAddress(), + val: address, }); track('xProvider', 'log', { + address, param: 'imxSigner.getAddress()', val: this.imxSigner.getAddress(), });