@multiplatform.one/web3 7.33.0 → 7.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplatform.one/web3",
3
- "version": "7.33.0",
3
+ "version": "7.33.1",
4
4
  "description": "Web3 wallet integration for multiplatform.one ecosystem with ConnectKit and wagmi",
5
5
  "keywords": [
6
6
  "connectkit",
@@ -120,10 +120,10 @@
120
120
  "@aave/account": "^0.2.0",
121
121
  "@coinbase/wallet-sdk": "^4.3.6",
122
122
  "@metamask/connect-evm": "^2.1.1",
123
- "@multiplatform.one/connectkit": "7.33.0",
124
- "@multiplatform.one/gpg": "7.33.0",
125
- "@multiplatform.one/platform": "7.33.0",
126
- "@multiplatform.one/theme": "7.33.0",
123
+ "@multiplatform.one/connectkit": "7.33.1",
124
+ "@multiplatform.one/gpg": "7.33.1",
125
+ "@multiplatform.one/platform": "7.33.1",
126
+ "@multiplatform.one/theme": "7.33.1",
127
127
  "@noble/curves": "^1.9.7",
128
128
  "@solana/kit": "^8.3.0",
129
129
  "@solana/wallet-adapter-base": "^0.9.27",
@@ -145,7 +145,7 @@
145
145
  "wagmi": "^3.7.1"
146
146
  },
147
147
  "devDependencies": {
148
- "@multiplatform.one/config": "7.33.0",
148
+ "@multiplatform.one/config": "7.33.1",
149
149
  "@tamagui/build": "2.7.6",
150
150
  "@tanstack/react-query": "^5.100.7",
151
151
  "@testing-library/jest-dom": "^6.9.1",
@@ -339,6 +339,50 @@ describe("metaMaskConnect under wagmi", () => {
339
339
  expect(request.mock.calls.map(([call]) => call.method)).toContain("personal_sign");
340
340
  });
341
341
 
342
+ it("signs under mainnet's scope when the desktop extension sits on a chain the app does not list", async () => {
343
+ // As @metamask/connect-evm's EIP1193Provider: the scope comes from
344
+ // selectedChainId before the first await, and a chain outside
345
+ // supportedNetworks is refused there.
346
+ const scopes: string[] = [];
347
+ const provider = {
348
+ selectedChainId: "0x2105" as string | undefined,
349
+ request: vi.fn(({ method }: { method: string }) => {
350
+ const chainId = provider.selectedChainId!;
351
+ const { api } = createEVMClient.mock.calls[0]![0] as {
352
+ api: { supportedNetworks: Record<string, string> };
353
+ };
354
+ if (!api.supportedNetworks[chainId])
355
+ return Promise.reject(
356
+ new Error(`Chain eip155:${Number(chainId)} is not configured in supportedNetworks`),
357
+ );
358
+ scopes.push(`eip155:${Number(chainId)}`);
359
+ return Promise.resolve(method === "personal_sign" ? "0x5167" : "0xabc");
360
+ }),
361
+ };
362
+ client.getChainId.mockImplementation(() => provider.selectedChainId!);
363
+ client.getProvider.mockReturnValue(provider as never);
364
+ client.connect.mockImplementationOnce(async () => ({ accounts: [first], chainId: "0x1" }));
365
+ const config = createConfig({
366
+ chains: [polygon, mainnet],
367
+ connectors: [metaMaskConnect({ dapp: { name: "test", url: "https://example.test" } })],
368
+ transports: { [polygon.id]: http(), [mainnet.id]: http() },
369
+ multiInjectedProviderDiscovery: false,
370
+ storage: null,
371
+ });
372
+ await connect(config, { connector: config.connectors[0]! });
373
+ (await clientEvents()).chainChanged("0x2105");
374
+
375
+ const signature = await signMessage(config, { message: "prove it" });
376
+
377
+ expect(signature).toBe("0x5167");
378
+ expect(scopes).toEqual(["eip155:1"]);
379
+ expect(provider.selectedChainId).toBe("0x2105");
380
+ await expect(sendTransaction(config, { to: second, value: 1n, gas: 21000n })).rejects.toThrow();
381
+ expect(provider.request.mock.calls.map(([call]) => call.method)).not.toContain(
382
+ "eth_sendTransaction",
383
+ );
384
+ });
385
+
342
386
  it("sends no transaction or typed signature on mainnet for an app that does not list it", async () => {
343
387
  const request = vi.fn(async ({ method }: { method: string }) =>
344
388
  method === "eth_chainId" ? "0x1" : "0xabc",
@@ -115,20 +115,45 @@ const offListMethods = new Set([
115
115
  "wallet_registerOnboarding",
116
116
  ]);
117
117
 
118
+ /**
119
+ * MetaMask Connect scopes a request to the provider's selected chain and refuses
120
+ * one outside supportedNetworks. The desktop extension moves that chain to
121
+ * wherever the user's MetaMask sits, Base say, so personal_sign there never
122
+ * reached the wallet (MPO-494). It goes under mainnet's scope instead, which
123
+ * MetaMask Connect adds to every session. The provider reads the scope before
124
+ * its first await, so the selected chain is put back before anything else runs.
125
+ */
126
+ function signUnderMainnet(
127
+ provider: EIP1193Provider,
128
+ args: { method: string; params?: unknown },
129
+ ): Promise<unknown> {
130
+ const selected = provider.selectedChainId;
131
+ provider.selectedChainId = numberToHex(mainnet.id);
132
+ try {
133
+ return provider.request(args as never);
134
+ } finally {
135
+ provider.selectedChainId = selected;
136
+ }
137
+ }
138
+
118
139
  function listedChainsOnly(
119
140
  provider: EIP1193Provider,
120
141
  mm: MetamaskConnectEVM,
121
142
  networks: Record<Hex, string>,
143
+ supportedNetworks: Record<Hex, string>,
122
144
  ): EIP1193Provider {
123
145
  const request = (async (args: { method: string; params?: unknown }) => {
124
146
  const chainId = mm.getChainId();
125
- if (chainId && !networks[numberToHex(Number(chainId))] && !offListMethods.has(args.method))
147
+ const current = chainId ? numberToHex(Number(chainId)) : undefined;
148
+ if (current && !networks[current] && !offListMethods.has(args.method))
126
149
  throw Object.assign(
127
150
  new Error(
128
151
  `MetaMask is on chain ${Number(chainId)}, which this app does not list, so ${args.method} was not sent`,
129
152
  ),
130
153
  { code: 4901 },
131
154
  );
155
+ if (current && !supportedNetworks[current] && args.method === "personal_sign")
156
+ return signUnderMainnet(provider, args);
132
157
  return provider.request(args as never);
133
158
  }) as EIP1193Provider["request"];
134
159
  return new Proxy(provider, {
@@ -383,7 +408,10 @@ export function metaMaskConnect(parameters: MetaMaskConnectParameters) {
383
408
  const mm = await claim();
384
409
  const provider = mm.getProvider();
385
410
  if (guarded?.provider !== provider)
386
- guarded = { provider, wrapped: listedChainsOnly(provider, mm, networks) };
411
+ guarded = {
412
+ provider,
413
+ wrapped: listedChainsOnly(provider, mm, networks, supportedNetworks),
414
+ };
387
415
  return guarded.wrapped;
388
416
  },
389
417
  async isAuthorized() {
@@ -1 +1 @@
1
- {"version":3,"file":"metaMaskConnectConnector.d.ts","sourceRoot":"","sources":["../../../src/connectkit/connectors/metaMaskConnectConnector.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,uBAAuB,CAAC;AAEjF,OAAO,EAA2B,KAAK,iBAAiB,EAAmB,MAAM,OAAO,CAAC;AACzF,OAAO,EAEL,KAAK,KAAK,EAEV,KAAK,GAAG,EAKT,MAAM,MAAM,CAAC;AAKd,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,6EAA6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;CAC3C,CAAC;AAEF,KAAK,eAAe,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAGxD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,GACzC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAQrB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,EAC7B,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,GACzC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAOrB;AA6ED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE1D;AAOD,wGAAwG;AACxG,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE,CAK9F;AAqBD;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAIxC;AAgFD,oFAAoF;AACpF,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD;AAWD,wBAAgB,eAAe,CAAC,UAAU,EAAE,yBAAyB,wFAqJpE;yBArJe,eAAe"}
1
+ {"version":3,"file":"metaMaskConnectConnector.d.ts","sourceRoot":"","sources":["../../../src/connectkit/connectors/metaMaskConnectConnector.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,uBAAuB,CAAC;AAEjF,OAAO,EAA2B,KAAK,iBAAiB,EAAmB,MAAM,OAAO,CAAC;AACzF,OAAO,EAEL,KAAK,KAAK,EAEV,KAAK,GAAG,EAKT,MAAM,MAAM,CAAC;AAKd,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,6EAA6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC;CAC3C,CAAC;AAEF,KAAK,eAAe,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAGxD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,GACzC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAQrB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,EAC7B,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,GACzC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAOrB;AAsGD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE1D;AAOD,wGAAwG;AACxG,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE,CAK9F;AAqBD;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAIxC;AAgFD,oFAAoF;AACpF,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD;AAWD,wBAAgB,eAAe,CAAC,UAAU,EAAE,yBAAyB,wFAwJpE;yBAxJe,eAAe"}