@multiplatform.one/web3 7.31.1 → 7.33.0

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.
Files changed (179) hide show
  1. package/README.md +84 -0
  2. package/dist/cjs/clients/evm.cjs +52 -1
  3. package/dist/cjs/clients/evm.native.js +56 -1
  4. package/dist/cjs/clients/evm.native.js.map +1 -1
  5. package/dist/cjs/clients/hooks.cjs +5 -2
  6. package/dist/cjs/clients/hooks.native.js +7 -2
  7. package/dist/cjs/clients/hooks.native.js.map +1 -1
  8. package/dist/cjs/clients/index.cjs +4 -0
  9. package/dist/cjs/clients/index.native.js +4 -0
  10. package/dist/cjs/clients/index.native.js.map +1 -1
  11. package/dist/cjs/clients/preparedSend.cjs +96 -0
  12. package/dist/cjs/clients/preparedSend.native.js +225 -0
  13. package/dist/cjs/clients/preparedSend.native.js.map +1 -0
  14. package/dist/cjs/connectkit/connectors/metaMaskConnectConnector.cjs +108 -27
  15. package/dist/cjs/connectkit/connectors/metaMaskConnectConnector.native.js +105 -28
  16. package/dist/cjs/connectkit/connectors/metaMaskConnectConnector.native.js.map +1 -1
  17. package/dist/cjs/connectkit/index.cjs +2 -0
  18. package/dist/cjs/connectkit/index.native.js +2 -0
  19. package/dist/cjs/connectkit/index.native.js.map +1 -1
  20. package/dist/cjs/connectkit/openConnector/context.cjs +16 -3
  21. package/dist/cjs/connectkit/openConnector/context.native.js +19 -4
  22. package/dist/cjs/connectkit/openConnector/context.native.js.map +1 -1
  23. package/dist/cjs/connectkit/openConnector/launcher.cjs +2 -2
  24. package/dist/cjs/connectkit/openConnector/launcher.native.js +2 -2
  25. package/dist/cjs/connectkit/openConnector/launcher.native.js.map +1 -1
  26. package/dist/cjs/phantom/evm.cjs +133 -0
  27. package/dist/cjs/phantom/evm.native.js +269 -0
  28. package/dist/cjs/phantom/evm.native.js.map +1 -0
  29. package/dist/cjs/phantom/index.cjs +36 -0
  30. package/dist/cjs/phantom/index.native.js +39 -0
  31. package/dist/cjs/phantom/index.native.js.map +1 -0
  32. package/dist/cjs/phantom/urls.cjs +33 -0
  33. package/dist/cjs/phantom/urls.native.js +38 -0
  34. package/dist/cjs/phantom/urls.native.js.map +1 -0
  35. package/dist/cjs/wagmi/driver.cjs +13 -9
  36. package/dist/cjs/wagmi/driver.native.js +17 -9
  37. package/dist/cjs/wagmi/driver.native.js.map +1 -1
  38. package/dist/esm/clients/evm.mjs +53 -2
  39. package/dist/esm/clients/evm.mjs.map +1 -1
  40. package/dist/esm/clients/evm.native.js +57 -2
  41. package/dist/esm/clients/evm.native.js.map +1 -1
  42. package/dist/esm/clients/hooks.mjs +5 -2
  43. package/dist/esm/clients/hooks.mjs.map +1 -1
  44. package/dist/esm/clients/hooks.native.js +7 -2
  45. package/dist/esm/clients/hooks.native.js.map +1 -1
  46. package/dist/esm/clients/index.mjs +2 -1
  47. package/dist/esm/clients/index.mjs.map +1 -1
  48. package/dist/esm/clients/index.native.js +2 -1
  49. package/dist/esm/clients/index.native.js.map +1 -1
  50. package/dist/esm/clients/preparedSend.mjs +69 -0
  51. package/dist/esm/clients/preparedSend.mjs.map +1 -0
  52. package/dist/esm/clients/preparedSend.native.js +195 -0
  53. package/dist/esm/clients/preparedSend.native.js.map +1 -0
  54. package/dist/esm/connectkit/connectors/metaMaskConnectConnector.mjs +107 -28
  55. package/dist/esm/connectkit/connectors/metaMaskConnectConnector.mjs.map +1 -1
  56. package/dist/esm/connectkit/connectors/metaMaskConnectConnector.native.js +104 -29
  57. package/dist/esm/connectkit/connectors/metaMaskConnectConnector.native.js.map +1 -1
  58. package/dist/esm/connectkit/index.mjs +2 -2
  59. package/dist/esm/connectkit/index.mjs.map +1 -1
  60. package/dist/esm/connectkit/index.native.js +2 -2
  61. package/dist/esm/connectkit/index.native.js.map +1 -1
  62. package/dist/esm/connectkit/openConnector/context.mjs +17 -4
  63. package/dist/esm/connectkit/openConnector/context.mjs.map +1 -1
  64. package/dist/esm/connectkit/openConnector/context.native.js +20 -5
  65. package/dist/esm/connectkit/openConnector/context.native.js.map +1 -1
  66. package/dist/esm/connectkit/openConnector/launcher.mjs +2 -2
  67. package/dist/esm/connectkit/openConnector/launcher.mjs.map +1 -1
  68. package/dist/esm/connectkit/openConnector/launcher.native.js +2 -2
  69. package/dist/esm/connectkit/openConnector/launcher.native.js.map +1 -1
  70. package/dist/esm/phantom/evm.mjs +103 -0
  71. package/dist/esm/phantom/evm.mjs.map +1 -0
  72. package/dist/esm/phantom/evm.native.js +236 -0
  73. package/dist/esm/phantom/evm.native.js.map +1 -0
  74. package/dist/esm/phantom/index.mjs +4 -0
  75. package/dist/esm/phantom/index.mjs.map +1 -0
  76. package/dist/esm/phantom/index.native.js +4 -0
  77. package/dist/esm/phantom/index.native.js.map +1 -0
  78. package/dist/esm/phantom/urls.mjs +7 -0
  79. package/dist/esm/phantom/urls.mjs.map +1 -0
  80. package/dist/esm/phantom/urls.native.js +9 -0
  81. package/dist/esm/phantom/urls.native.js.map +1 -0
  82. package/dist/esm/wagmi/driver.mjs +14 -10
  83. package/dist/esm/wagmi/driver.mjs.map +1 -1
  84. package/dist/esm/wagmi/driver.native.js +18 -10
  85. package/dist/esm/wagmi/driver.native.js.map +1 -1
  86. package/dist/jsx/clients/evm.mjs +53 -2
  87. package/dist/jsx/clients/evm.mjs.map +1 -1
  88. package/dist/jsx/clients/evm.native.js +56 -1
  89. package/dist/jsx/clients/evm.native.js.map +1 -1
  90. package/dist/jsx/clients/hooks.mjs +5 -2
  91. package/dist/jsx/clients/hooks.mjs.map +1 -1
  92. package/dist/jsx/clients/hooks.native.js +7 -2
  93. package/dist/jsx/clients/hooks.native.js.map +1 -1
  94. package/dist/jsx/clients/index.mjs +2 -1
  95. package/dist/jsx/clients/index.mjs.map +1 -1
  96. package/dist/jsx/clients/index.native.js +4 -0
  97. package/dist/jsx/clients/index.native.js.map +1 -1
  98. package/dist/jsx/clients/preparedSend.mjs +69 -0
  99. package/dist/jsx/clients/preparedSend.mjs.map +1 -0
  100. package/dist/jsx/clients/preparedSend.native.js +225 -0
  101. package/dist/jsx/clients/preparedSend.native.js.map +1 -0
  102. package/dist/jsx/connectkit/connectors/metaMaskConnectConnector.mjs +107 -28
  103. package/dist/jsx/connectkit/connectors/metaMaskConnectConnector.mjs.map +1 -1
  104. package/dist/jsx/connectkit/connectors/metaMaskConnectConnector.native.js +105 -28
  105. package/dist/jsx/connectkit/connectors/metaMaskConnectConnector.native.js.map +1 -1
  106. package/dist/jsx/connectkit/index.mjs +2 -2
  107. package/dist/jsx/connectkit/index.mjs.map +1 -1
  108. package/dist/jsx/connectkit/index.native.js +2 -0
  109. package/dist/jsx/connectkit/index.native.js.map +1 -1
  110. package/dist/jsx/connectkit/openConnector/context.mjs +17 -4
  111. package/dist/jsx/connectkit/openConnector/context.mjs.map +1 -1
  112. package/dist/jsx/connectkit/openConnector/context.native.js +19 -4
  113. package/dist/jsx/connectkit/openConnector/context.native.js.map +1 -1
  114. package/dist/jsx/connectkit/openConnector/launcher.mjs +2 -2
  115. package/dist/jsx/connectkit/openConnector/launcher.mjs.map +1 -1
  116. package/dist/jsx/connectkit/openConnector/launcher.native.js +2 -2
  117. package/dist/jsx/connectkit/openConnector/launcher.native.js.map +1 -1
  118. package/dist/jsx/phantom/evm.mjs +103 -0
  119. package/dist/jsx/phantom/evm.mjs.map +1 -0
  120. package/dist/jsx/phantom/evm.native.js +269 -0
  121. package/dist/jsx/phantom/evm.native.js.map +1 -0
  122. package/dist/jsx/phantom/index.mjs +4 -0
  123. package/dist/jsx/phantom/index.mjs.map +1 -0
  124. package/dist/jsx/phantom/index.native.js +39 -0
  125. package/dist/jsx/phantom/index.native.js.map +1 -0
  126. package/dist/jsx/phantom/urls.mjs +7 -0
  127. package/dist/jsx/phantom/urls.mjs.map +1 -0
  128. package/dist/jsx/phantom/urls.native.js +38 -0
  129. package/dist/jsx/phantom/urls.native.js.map +1 -0
  130. package/dist/jsx/wagmi/driver.mjs +14 -10
  131. package/dist/jsx/wagmi/driver.mjs.map +1 -1
  132. package/dist/jsx/wagmi/driver.native.js +17 -9
  133. package/dist/jsx/wagmi/driver.native.js.map +1 -1
  134. package/dist/keycloak/login.iife.js +382 -382
  135. package/package.json +12 -6
  136. package/src/clients/evm.ts +86 -0
  137. package/src/clients/hooks.spec.tsx +1 -0
  138. package/src/clients/hooks.ts +4 -1
  139. package/src/clients/index.ts +12 -0
  140. package/src/clients/preparedSend.spec.ts +214 -0
  141. package/src/clients/preparedSend.ts +136 -0
  142. package/src/connectkit/connectors/metaMaskConnectConnector.spec.ts +256 -4
  143. package/src/connectkit/connectors/metaMaskConnectConnector.ts +145 -33
  144. package/src/connectkit/index.ts +2 -0
  145. package/src/connectkit/openConnector/context.tsx +10 -5
  146. package/src/connectkit/openConnector/launcher.spec.ts +24 -2
  147. package/src/connectkit/openConnector/launcher.ts +10 -3
  148. package/src/core/types.ts +7 -0
  149. package/src/phantom/evm.spec.ts +195 -0
  150. package/src/phantom/evm.ts +163 -0
  151. package/src/phantom/index.ts +16 -0
  152. package/src/phantom/urls.spec.ts +29 -0
  153. package/src/phantom/urls.ts +16 -0
  154. package/src/wagmi/driver.spec.ts +31 -0
  155. package/src/wagmi/driver.ts +11 -4
  156. package/types/clients/evm.d.ts +32 -0
  157. package/types/clients/evm.d.ts.map +1 -1
  158. package/types/clients/hooks.d.ts.map +1 -1
  159. package/types/clients/index.d.ts +2 -1
  160. package/types/clients/index.d.ts.map +1 -1
  161. package/types/clients/preparedSend.d.ts +71 -0
  162. package/types/clients/preparedSend.d.ts.map +1 -0
  163. package/types/connectkit/connectors/metaMaskConnectConnector.d.ts +27 -0
  164. package/types/connectkit/connectors/metaMaskConnectConnector.d.ts.map +1 -1
  165. package/types/connectkit/index.d.ts +1 -1
  166. package/types/connectkit/index.d.ts.map +1 -1
  167. package/types/connectkit/openConnector/context.d.ts.map +1 -1
  168. package/types/connectkit/openConnector/launcher.d.ts +8 -1
  169. package/types/connectkit/openConnector/launcher.d.ts.map +1 -1
  170. package/types/core/types.d.ts +7 -0
  171. package/types/core/types.d.ts.map +1 -1
  172. package/types/phantom/evm.d.ts +76 -0
  173. package/types/phantom/evm.d.ts.map +1 -0
  174. package/types/phantom/index.d.ts +3 -0
  175. package/types/phantom/index.d.ts.map +1 -0
  176. package/types/phantom/urls.d.ts +11 -0
  177. package/types/phantom/urls.d.ts.map +1 -0
  178. package/types/wagmi/driver.d.ts +1 -1
  179. package/types/wagmi/driver.d.ts.map +1 -1
@@ -32,6 +32,13 @@ export type OpenConnectorOptions = {
32
32
  * to settle however long that takes.
33
33
  */
34
34
  fallbackMs?: number;
35
+ /**
36
+ * The chain to connect on. MetaMask asks the wallet for it first, so a page
37
+ * that knows its purchase chain connects there and needs no switch after.
38
+ * Must be one of the config's chains; a wallet that does not grant it
39
+ * connects on another, which the connect result reports.
40
+ */
41
+ chainId?: number;
35
42
  };
36
43
 
37
44
  export type PendingConnect = {
@@ -45,7 +52,7 @@ export type PendingConnect = {
45
52
  type Listener = (event: Event) => void;
46
53
 
47
54
  export type LauncherDeps = {
48
- connect: (connector: Connector) => Promise<unknown>;
55
+ connect: (connector: Connector, chainId?: number) => Promise<unknown>;
49
56
  /** Show the connecting state for this wallet. */
50
57
  showConnecting: (walletId: string) => void;
51
58
  /** Show the wallet list. */
@@ -103,7 +110,7 @@ export function createConnectorLauncher(getDeps: () => LauncherDeps): ConnectorL
103
110
 
104
111
  const current = session;
105
112
  if (current && current.pending.connector.uid === connector.uid) {
106
- deps.connect(connector).then(
113
+ deps.connect(connector, options.chainId).then(
107
114
  () => end(current),
108
115
  () => undefined,
109
116
  );
@@ -173,7 +180,7 @@ export function createConnectorLauncher(getDeps: () => LauncherDeps): ConnectorL
173
180
  };
174
181
 
175
182
  connector.emitter?.on?.("message", onMessage);
176
- deps.connect(connector).then(
183
+ deps.connect(connector, options.chainId).then(
177
184
  () => end(s),
178
185
  (error: unknown) => fallBack(error ?? new Error("connect failed")),
179
186
  );
package/src/core/types.ts CHANGED
@@ -29,6 +29,13 @@ export interface DriverState {
29
29
  export interface DriverConnectOptions {
30
30
  /** Called with a pairing URI when the connector hands off to another app or device. */
31
31
  onDisplayUri?: (uri: string) => void;
32
+ /**
33
+ * EVM: the chain to connect on, asked of the wallet first so no switch is
34
+ * needed after. A chain the config does not list rejects before the wallet
35
+ * is asked. Ignored by drivers without EVM chains, and by a connector the
36
+ * driver already holds open.
37
+ */
38
+ chainId?: number;
32
39
  }
33
40
 
34
41
  /** What the connection store's `connect` takes. */
@@ -0,0 +1,195 @@
1
+ import { baseSepolia } from "viem/chains";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import {
4
+ connectPhantomEvm,
5
+ discoverPhantomEthereumProvider,
6
+ openInPhantom,
7
+ phantomEthereumProvider,
8
+ phantomEvmRoute,
9
+ PhantomNotInjectedError,
10
+ type PhantomEthereumProvider,
11
+ } from "./evm";
12
+
13
+ const account = "0x1111111111111111111111111111111111111111";
14
+
15
+ function fakeProvider(chainId: number, opts: { unknownChain?: boolean } = {}) {
16
+ let current = chainId;
17
+ let known = !opts.unknownChain;
18
+ const calls: { method: string; params?: unknown }[] = [];
19
+ const request = vi.fn(async ({ method, params }: { method: string; params?: unknown }) => {
20
+ calls.push({ method, params });
21
+ switch (method) {
22
+ case "eth_requestAccounts":
23
+ case "eth_accounts":
24
+ return [account];
25
+ case "eth_chainId":
26
+ return `0x${current.toString(16)}`;
27
+ case "wallet_switchEthereumChain": {
28
+ if (!known) throw Object.assign(new Error("Unrecognized chain"), { code: 4902 });
29
+ current = Number((params as [{ chainId: string }])[0].chainId);
30
+ return null;
31
+ }
32
+ case "wallet_addEthereumChain":
33
+ known = true;
34
+ return null;
35
+ default:
36
+ throw new Error(`unexpected ${method}`);
37
+ }
38
+ });
39
+ const provider = { isPhantom: true, request, on: vi.fn(), removeListener: vi.fn() };
40
+ return { provider: provider as unknown as PhantomEthereumProvider, calls };
41
+ }
42
+
43
+ describe("phantom evm", () => {
44
+ it("finds window.phantom.ethereum, then a Phantom window.ethereum, and nothing else", () => {
45
+ const own = { isPhantom: true } as unknown as PhantomEthereumProvider;
46
+ const other = { isMetaMask: true } as unknown as PhantomEthereumProvider;
47
+ expect(phantomEthereumProvider({ phantom: { ethereum: own }, ethereum: other })).toBe(own);
48
+ expect(phantomEthereumProvider({ ethereum: own })).toBe(own);
49
+ expect(phantomEthereumProvider({ ethereum: other })).toBeUndefined();
50
+ expect(phantomEvmRoute({ ethereum: other })).toBe("browse");
51
+ expect(phantomEvmRoute({ phantom: { ethereum: own } })).toBe("injected");
52
+ });
53
+
54
+ it("takes Phantom's EIP-6963 announcement", async () => {
55
+ const provider = { isPhantom: true } as unknown as PhantomEthereumProvider;
56
+ const target = new EventTarget();
57
+ target.addEventListener("eip6963:requestProvider", () => {
58
+ target.dispatchEvent(
59
+ Object.assign(new Event("eip6963:announceProvider"), {
60
+ detail: { info: { rdns: "io.metamask" }, provider: {} },
61
+ }),
62
+ );
63
+ target.dispatchEvent(
64
+ Object.assign(new Event("eip6963:announceProvider"), {
65
+ detail: { info: { rdns: "app.phantom" }, provider },
66
+ }),
67
+ );
68
+ });
69
+ const win = {
70
+ addEventListener: target.addEventListener.bind(target),
71
+ removeEventListener: target.removeEventListener.bind(target),
72
+ dispatchEvent: target.dispatchEvent.bind(target),
73
+ };
74
+ await expect(discoverPhantomEthereumProvider({ window: win as never })).resolves.toBe(provider);
75
+ });
76
+
77
+ it("resolves undefined when nothing announces", async () => {
78
+ const target = new EventTarget();
79
+ const win = {
80
+ addEventListener: target.addEventListener.bind(target),
81
+ removeEventListener: target.removeEventListener.bind(target),
82
+ dispatchEvent: target.dispatchEvent.bind(target),
83
+ };
84
+ await expect(
85
+ discoverPhantomEthereumProvider({ window: win as never, timeout: 5 }),
86
+ ).resolves.toBeUndefined();
87
+ });
88
+
89
+ it("opens this page in Phantom's browser synchronously", () => {
90
+ const assign = vi.fn();
91
+ const link = openInPhantom({
92
+ window: {
93
+ location: {
94
+ href: "https://dev.promanager.vip/u/buy?mobile=1",
95
+ origin: "https://dev.promanager.vip",
96
+ assign,
97
+ },
98
+ },
99
+ });
100
+ expect(link).toBe(
101
+ "https://phantom.com/ul/browse/https%3A%2F%2Fdev.promanager.vip%2Fu%2Fbuy%3Fmobile%3D1?ref=https%3A%2F%2Fdev.promanager.vip",
102
+ );
103
+ expect(assign).toHaveBeenCalledWith(link);
104
+ });
105
+
106
+ it("connects, switches to Base Sepolia, and returns a client on it", async () => {
107
+ const { provider, calls } = fakeProvider(1);
108
+ const client = await connectPhantomEvm({ chain: baseSepolia, provider });
109
+ expect(client.address.toLowerCase()).toBe(account);
110
+ expect(client.chainId).toBe(84532);
111
+ expect(calls.map((c) => c.method)).toEqual([
112
+ "eth_requestAccounts",
113
+ "eth_chainId",
114
+ "wallet_switchEthereumChain",
115
+ ]);
116
+ expect(calls[2].params).toEqual([{ chainId: "0x14a34" }]);
117
+ });
118
+
119
+ it("adds the chain when Phantom does not know it", async () => {
120
+ const { provider, calls } = fakeProvider(1, { unknownChain: true });
121
+ await connectPhantomEvm({ chain: baseSepolia, provider });
122
+ expect(calls.map((c) => c.method)).toEqual([
123
+ "eth_requestAccounts",
124
+ "eth_chainId",
125
+ "wallet_switchEthereumChain",
126
+ "wallet_addEthereumChain",
127
+ "wallet_switchEthereumChain",
128
+ ]);
129
+ expect((calls[3].params as [{ chainId: string; rpcUrls: string[] }])[0]).toMatchObject({
130
+ chainId: "0x14a34",
131
+ rpcUrls: [...baseSepolia.rpcUrls.default.http],
132
+ });
133
+ });
134
+
135
+ it("skips the switch when already on the chain", async () => {
136
+ const { provider, calls } = fakeProvider(84532);
137
+ await connectPhantomEvm({ chain: baseSepolia, provider });
138
+ expect(calls.map((c) => c.method)).toEqual(["eth_requestAccounts", "eth_chainId"]);
139
+ });
140
+
141
+ it("sends an ERC-20 transfer to Phantom as eth_sendTransaction", async () => {
142
+ const { provider } = fakeProvider(84532);
143
+ const sent: unknown[] = [];
144
+ const request = provider.request as unknown as ReturnType<typeof vi.fn>;
145
+ const base = request.getMockImplementation() as (a: {
146
+ method: string;
147
+ params?: unknown;
148
+ }) => Promise<unknown>;
149
+ request.mockImplementation(async (args: { method: string; params?: unknown }) => {
150
+ if (args.method === "eth_sendTransaction") {
151
+ sent.push(args.params);
152
+ return `0x${"ab".repeat(32)}`;
153
+ }
154
+ return base(args);
155
+ });
156
+ const client = await connectPhantomEvm({ chain: baseSepolia, provider });
157
+ const hash = await client.walletClient.writeContract({
158
+ address: "0xc6fe3521644e0f5439fe345f64d372cd6ed37491",
159
+ abi: [
160
+ {
161
+ type: "function",
162
+ name: "transfer",
163
+ stateMutability: "nonpayable",
164
+ inputs: [
165
+ { name: "to", type: "address" },
166
+ { name: "amount", type: "uint256" },
167
+ ],
168
+ outputs: [{ type: "bool" }],
169
+ },
170
+ ],
171
+ functionName: "transfer",
172
+ args: ["0x2222222222222222222222222222222222222222", 10n ** 18n],
173
+ gas: 100000n,
174
+ });
175
+ expect(hash).toBe(`0x${"ab".repeat(32)}`);
176
+ expect(sent[0]).toEqual([
177
+ expect.objectContaining({
178
+ from: account,
179
+ to: "0xc6fe3521644e0f5439fe345f64d372cd6ed37491",
180
+ data: expect.stringMatching(/^0xa9059cbb0{24}2{40}/),
181
+ }),
182
+ ]);
183
+ });
184
+
185
+ it("says to reopen in Phantom when nothing is injected", async () => {
186
+ vi.stubGlobal("phantom", undefined);
187
+ try {
188
+ await expect(connectPhantomEvm({ chain: baseSepolia })).rejects.toBeInstanceOf(
189
+ PhantomNotInjectedError,
190
+ );
191
+ } finally {
192
+ vi.unstubAllGlobals();
193
+ }
194
+ });
195
+ });
@@ -0,0 +1,163 @@
1
+ import { numberToHex, type Chain, type EIP1193Provider, type PublicClient } from "viem";
2
+ import { evmClient, type EvmClient } from "../clients/evm";
3
+ import { phantomBrowseUrl } from "./urls";
4
+
5
+ export type PhantomEthereumProvider = EIP1193Provider & { isPhantom?: boolean };
6
+
7
+ interface PhantomWindow {
8
+ phantom?: { ethereum?: PhantomEthereumProvider };
9
+ ethereum?: PhantomEthereumProvider;
10
+ location?: { href: string; origin: string; assign(url: string): void };
11
+ addEventListener?: (type: string, listener: (event: Event) => void) => void;
12
+ removeEventListener?: (type: string, listener: (event: Event) => void) => void;
13
+ dispatchEvent?: (event: Event) => boolean;
14
+ }
15
+
16
+ const phantomRdns = "app.phantom";
17
+
18
+ /**
19
+ * Phantom's injected EVM provider: `window.phantom.ethereum`, else a
20
+ * `window.ethereum` that says it is Phantom. Present in Phantom's desktop
21
+ * extension and its in-app browser, never in Chrome or Safari on a phone.
22
+ */
23
+ export function phantomEthereumProvider(
24
+ win: PhantomWindow = globalThis as PhantomWindow,
25
+ ): PhantomEthereumProvider | undefined {
26
+ const own = win.phantom?.ethereum;
27
+ if (own?.isPhantom) return own;
28
+ if (win.ethereum?.isPhantom) return win.ethereum;
29
+ return undefined;
30
+ }
31
+
32
+ /**
33
+ * phantomEthereumProvider, or Phantom's EIP-6963 announcement (rdns
34
+ * `app.phantom`) when the provider is not on `window` yet. Resolves undefined
35
+ * after `timeout` ms.
36
+ */
37
+ export function discoverPhantomEthereumProvider(
38
+ options: { timeout?: number; window?: PhantomWindow } = {},
39
+ ): Promise<PhantomEthereumProvider | undefined> {
40
+ const win = options.window ?? (globalThis as PhantomWindow);
41
+ const found = phantomEthereumProvider(win);
42
+ if (found || !win.addEventListener || !win.dispatchEvent) return Promise.resolve(found);
43
+ return new Promise((resolve) => {
44
+ const onAnnounce = (event: Event) => {
45
+ const detail = (
46
+ event as CustomEvent<{ info?: { rdns?: string }; provider?: PhantomEthereumProvider }>
47
+ ).detail;
48
+ if (detail?.info?.rdns !== phantomRdns || !detail.provider) return;
49
+ done(detail.provider);
50
+ };
51
+ const timer = setTimeout(() => done(phantomEthereumProvider(win)), options.timeout ?? 500);
52
+ const done = (provider: PhantomEthereumProvider | undefined) => {
53
+ clearTimeout(timer);
54
+ win.removeEventListener?.("eip6963:announceProvider", onAnnounce);
55
+ resolve(provider);
56
+ };
57
+ win.addEventListener?.("eip6963:announceProvider", onAnnounce);
58
+ win.dispatchEvent?.(new Event("eip6963:requestProvider"));
59
+ });
60
+ }
61
+
62
+ /**
63
+ * How this page reaches Phantom's EVM wallet: `injected` when Phantom's
64
+ * provider is here (extension or Phantom's browser), `browse` when the page
65
+ * must first reopen inside Phantom with openInPhantom.
66
+ */
67
+ export function phantomEvmRoute(win: PhantomWindow = globalThis as PhantomWindow) {
68
+ return phantomEthereumProvider(win) ? ("injected" as const) : ("browse" as const);
69
+ }
70
+
71
+ export interface OpenInPhantomOptions {
72
+ /** The page to open in Phantom's browser. Defaults to this page. */
73
+ url?: string;
74
+ /** The requesting app. Defaults to this page's origin. */
75
+ ref?: string;
76
+ /** Defaults to `location.assign`. */
77
+ navigate?: (url: string) => void;
78
+ base?: string;
79
+ window?: PhantomWindow;
80
+ }
81
+
82
+ /**
83
+ * Reopens the page inside Phantom's in-app browser. Call it straight from the
84
+ * tap handler with nothing awaited first: mobile browsers only follow a link
85
+ * into another app without a prompt inside the tap's user activation.
86
+ * Returns the link, for an `<a href>` instead.
87
+ */
88
+ export function openInPhantom(options: OpenInPhantomOptions = {}): string {
89
+ const win = options.window ?? (globalThis as PhantomWindow);
90
+ const url = options.url ?? win.location?.href;
91
+ const ref = options.ref ?? win.location?.origin ?? url;
92
+ if (!url || !ref) throw new Error("openInPhantom: no page URL here; pass `url` and `ref`");
93
+ const link = phantomBrowseUrl(url, ref, { base: options.base });
94
+ (options.navigate ?? ((target: string) => win.location?.assign(target)))(link);
95
+ return link;
96
+ }
97
+
98
+ export interface ConnectPhantomEvmOptions {
99
+ chain: Chain;
100
+ /** Defaults to phantomEthereumProvider(). */
101
+ provider?: PhantomEthereumProvider;
102
+ publicClient?: PublicClient;
103
+ rpcUrl?: string;
104
+ }
105
+
106
+ export class PhantomNotInjectedError extends Error {
107
+ constructor() {
108
+ super(
109
+ "Phantom's EVM provider is not on this page: on a phone, reopen it in Phantom with openInPhantom()",
110
+ );
111
+ this.name = "PhantomNotInjectedError";
112
+ }
113
+ }
114
+
115
+ const errorCode = (error: unknown) =>
116
+ (error as { code?: unknown; cause?: { code?: unknown } } | undefined)?.code ??
117
+ (error as { cause?: { code?: unknown } } | undefined)?.cause?.code;
118
+
119
+ async function ensureChain(provider: PhantomEthereumProvider, chain: Chain) {
120
+ const current = await provider.request({ method: "eth_chainId" });
121
+ if (Number(current) === chain.id) return;
122
+ const chainId = numberToHex(chain.id);
123
+ try {
124
+ await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId }] });
125
+ } catch (error) {
126
+ if (errorCode(error) !== 4902) throw error;
127
+ await provider.request({
128
+ method: "wallet_addEthereumChain",
129
+ params: [
130
+ {
131
+ chainId,
132
+ chainName: chain.name,
133
+ nativeCurrency: chain.nativeCurrency,
134
+ rpcUrls: [...chain.rpcUrls.default.http],
135
+ blockExplorerUrls: chain.blockExplorers ? [chain.blockExplorers.default.url] : undefined,
136
+ },
137
+ ],
138
+ });
139
+ await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId }] });
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Connects Phantom's injected EVM wallet, moves it to `chain`, and returns
145
+ * the mpo EVM client on it, so `erc20.transfer` and `writeContract` go to
146
+ * Phantom for approval. Testnets such as Base Sepolia need Phantom's Testnet
147
+ * Mode on.
148
+ */
149
+ export async function connectPhantomEvm(options: ConnectPhantomEvmOptions): Promise<EvmClient> {
150
+ const provider = options.provider ?? phantomEthereumProvider();
151
+ if (!provider) throw new PhantomNotInjectedError();
152
+ const accounts = await provider.request({ method: "eth_requestAccounts" });
153
+ const account = accounts[0];
154
+ if (!account) throw new Error("Phantom returned no EVM account");
155
+ await ensureChain(provider, options.chain);
156
+ return evmClient({
157
+ provider,
158
+ account,
159
+ chain: options.chain,
160
+ publicClient: options.publicClient,
161
+ rpcUrl: options.rpcUrl,
162
+ });
163
+ }
@@ -0,0 +1,16 @@
1
+ // `@multiplatform.one/web3/phantom`: Phantom's EVM wallet from a phone's own
2
+ // browser. Phantom's deeplinks carry no EVM methods, so the page reopens in
3
+ // Phantom's in-app browser (openInPhantom) and connects the provider Phantom
4
+ // injects there (connectPhantomEvm).
5
+ export {
6
+ connectPhantomEvm,
7
+ discoverPhantomEthereumProvider,
8
+ openInPhantom,
9
+ phantomEthereumProvider,
10
+ phantomEvmRoute,
11
+ PhantomNotInjectedError,
12
+ type ConnectPhantomEvmOptions,
13
+ type OpenInPhantomOptions,
14
+ type PhantomEthereumProvider,
15
+ } from "./evm";
16
+ export { phantomBrowseUrl, phantomUniversalLinkBase } from "./urls";
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { phantomBrowseUrl } from "./urls";
3
+
4
+ describe("phantomBrowseUrl", () => {
5
+ it("builds the browse link Phantom documents", () => {
6
+ expect(
7
+ phantomBrowseUrl(
8
+ "https://magiceden.io/item-details/8yjN8iRuoiYiKW487cnW9vn6mLBR5E8aCNKsBRmTP9vN",
9
+ "https://magiceden.io",
10
+ ),
11
+ ).toBe(
12
+ "https://phantom.com/ul/browse/https%3A%2F%2Fmagiceden.io%2Fitem-details%2F8yjN8iRuoiYiKW487cnW9vn6mLBR5E8aCNKsBRmTP9vN?ref=https%3A%2F%2Fmagiceden.io",
13
+ );
14
+ });
15
+
16
+ it("keeps a page's own query inside the browse link", () => {
17
+ expect(
18
+ phantomBrowseUrl(
19
+ "https://dev.promanager.vip/u/buy?mobile=1&x=a b",
20
+ "https://dev.promanager.vip",
21
+ {
22
+ base: "https://phantom.app/ul/",
23
+ },
24
+ ),
25
+ ).toBe(
26
+ "https://phantom.app/ul/browse/https%3A%2F%2Fdev.promanager.vip%2Fu%2Fbuy%3Fmobile%3D1%26x%3Da%20b?ref=https%3A%2F%2Fdev.promanager.vip",
27
+ );
28
+ });
29
+ });
@@ -0,0 +1,16 @@
1
+ /** Phantom's universal-link host. `https://phantom.app/ul` still answers; Phantom asks new code to use this one. */
2
+ export const phantomUniversalLinkBase = "https://phantom.com/ul";
3
+
4
+ /**
5
+ * Opens `url` inside Phantom's in-app browser, where Phantom injects
6
+ * `window.phantom.ethereum`. Phantom's deeplinks carry no EVM methods, so
7
+ * this is how a phone's browser reaches its EVM wallet.
8
+ */
9
+ export function phantomBrowseUrl(
10
+ url: string,
11
+ ref: string,
12
+ options: { base?: string } = {},
13
+ ): string {
14
+ const base = (options.base ?? phantomUniversalLinkBase).replace(/\/+$/, "");
15
+ return `${base}/browse/${encodeURIComponent(url)}?ref=${encodeURIComponent(ref)}`;
16
+ }
@@ -71,6 +71,37 @@ function setup(options: { displayUri?: string } = {}) {
71
71
  describeConnectionDriver("wagmiDriver", setup);
72
72
 
73
73
  describe("wagmiDriver", () => {
74
+ it("connects on the chain the caller names", async () => {
75
+ const { driver, connector } = setup();
76
+ const spy = vi.spyOn(connector("wallet.one"), "connect");
77
+ const chainId = 8453;
78
+
79
+ await driver.connect("wallet.one", { chainId });
80
+
81
+ expect(spy).toHaveBeenCalledWith(expect.objectContaining({ chainId }));
82
+ });
83
+
84
+ it("refuses a chain the config does not list before asking the wallet", async () => {
85
+ const { driver, connector, wallets } = setup();
86
+ const spy = vi.spyOn(connector("wallet.one"), "connect");
87
+
88
+ await expect(driver.connect("wallet.one", { chainId: 999_999 })).rejects.toThrow(
89
+ /Chain not configured/,
90
+ );
91
+
92
+ expect(spy).not.toHaveBeenCalled();
93
+ expect(wallets.get("wallet.one").open).toBeFalsy();
94
+ });
95
+
96
+ it("connects as before when no chain is named", async () => {
97
+ const { driver, connector } = setup();
98
+ const spy = vi.spyOn(connector("wallet.one"), "connect");
99
+
100
+ await driver.connect("wallet.one");
101
+
102
+ expect(spy.mock.calls[0]![0]).not.toHaveProperty("chainId", expect.anything());
103
+ });
104
+
74
105
  it("hands a pairing URI to onDisplayUri while connecting, and stops after", async () => {
75
106
  const { driver, config, connector } = setup({ displayUri: "metamask://wc?uri=pair" });
76
107
  const onDisplayUri = vi.fn();
@@ -1,6 +1,7 @@
1
- import type { Config, Connection, Connector } from "wagmi";
1
+ import { ChainNotConfiguredError, type Config, type Connection, type Connector } from "wagmi";
2
2
  import {
3
3
  connect,
4
+ getAccount,
4
5
  getPublicClient,
5
6
  getWalletClient,
6
7
  switchConnection,
@@ -231,17 +232,22 @@ export function wagmiDriver(config: Config, options: WagmiDriverOptions = {}): C
231
232
  },
232
233
  async connect(connectorId, connectOptions: DriverConnectOptions = {}) {
233
234
  const connector = connectorFor(connectorId);
235
+ const { onDisplayUri, chainId } = connectOptions;
236
+ if (chainId !== undefined && !config.chains.some((chain) => chain.id === chainId))
237
+ throw new ChainNotConfiguredError();
234
238
  const open = await reuse(connector);
235
239
  if (open) return open;
236
240
  if (empty(connector)) forget(connector);
237
- const { onDisplayUri } = connectOptions;
238
241
  const onMessage = ({ type, data }: { type: string; data?: unknown }) => {
239
242
  if (type === "display_uri" && typeof data === "string") onDisplayUri?.(data);
240
243
  };
241
244
  if (onDisplayUri) connector.emitter.on("message", onMessage);
242
245
  try {
243
- const { accounts, chainId } = await connect(config, { connector });
244
- return opened(connector, accounts, chainId);
246
+ const connection = await connect(
247
+ config,
248
+ chainId === undefined ? { connector } : { connector, chainId },
249
+ );
250
+ return opened(connector, connection.accounts, connection.chainId);
245
251
  } finally {
246
252
  if (onDisplayUri) connector.emitter.off("message", onMessage);
247
253
  }
@@ -296,6 +302,7 @@ export function wagmiDriver(config: Config, options: WagmiDriverOptions = {}): C
296
302
  return evmClient({
297
303
  walletClient: walletClient as unknown as EvmWalletClient,
298
304
  ...(publicClient ? { publicClient: publicClient as unknown as PublicClient } : {}),
305
+ current: () => getAccount(config),
299
306
  });
300
307
  }
301
308
  }
@@ -1,4 +1,5 @@
1
1
  import { type Abi, type Account, type Address, type Chain, type ContractFunctionArgs, type ContractFunctionName, type EIP1193Provider, type Hash, type Hex, type PublicClient, type SendTransactionParameters, type TransactionReceipt, type Transport, type WalletClient, type WriteContractParameters } from "viem";
2
+ import { type CurrentWalletState, type PreparedEvmSend } from "./preparedSend";
2
3
  import type { ChainClient } from "./types";
3
4
  /** A viem wallet client with its account and chain hoisted, the shape wagmi's getWalletClient returns. */
4
5
  export type EvmWalletClient = WalletClient<Transport, Chain, Account>;
@@ -158,6 +159,27 @@ export interface Erc20Actions {
158
159
  signal?: AbortSignal;
159
160
  }): Promise<Hash | null>;
160
161
  }
162
+ /** What `prepareTransaction` takes: the transaction, and optionally its gas, nonce and lifetime. */
163
+ export interface EvmPrepareTransactionParameters {
164
+ to: Address;
165
+ data?: Hex;
166
+ value?: bigint;
167
+ gas?: bigint;
168
+ nonce?: number;
169
+ /** How long the prepared send stays good. 60 s by default. */
170
+ maxAgeMs?: number;
171
+ }
172
+ /** What `prepareWriteContract` takes: viem's contract call, simulated before the tap. */
173
+ export interface EvmPrepareWriteContractParameters<abi extends Abi | readonly unknown[] = Abi, functionName extends WritableFunctionName<abi> = WritableFunctionName<abi>> {
174
+ address: Address;
175
+ abi: abi;
176
+ functionName: functionName;
177
+ args?: ContractFunctionArgs<abi, "nonpayable" | "payable", functionName>;
178
+ value?: bigint;
179
+ gas?: bigint;
180
+ nonce?: number;
181
+ maxAgeMs?: number;
182
+ }
161
183
  export interface EvmClient extends ChainClient<"evm"> {
162
184
  readonly address: Address;
163
185
  readonly chainId: number;
@@ -189,6 +211,14 @@ export interface EvmClient extends ChainClient<"evm"> {
189
211
  confirmTransaction(hash: Hash, options?: EvmWaitOptions): Promise<TransactionReceipt>;
190
212
  /** The chain explorer's page for `hash`, when the chain names an explorer. */
191
213
  explorerTxUrl(hash: Hash): string | undefined;
214
+ /**
215
+ * Does the network work for a send ahead of the user's tap (nonce, gas,
216
+ * fees), so the tap's handler calls `send()` with nothing awaited and the
217
+ * wallet app opens without "Continue to MetaMask?". See PreparedEvmSend.
218
+ */
219
+ prepareTransaction(parameters: EvmPrepareTransactionParameters): Promise<PreparedEvmSend>;
220
+ /** prepareTransaction for a contract call: simulates it, then encodes it. */
221
+ prepareWriteContract<const abi extends Abi | readonly unknown[], functionName extends WritableFunctionName<abi>>(parameters: EvmPrepareWriteContractParameters<abi, functionName>): Promise<PreparedEvmSend>;
192
222
  readonly erc20: Erc20Actions;
193
223
  }
194
224
  export type EvmClientConfig = ({
@@ -203,6 +233,8 @@ export type EvmClientConfig = ({
203
233
  /** Reads go here. Defaults to an http client on `rpcUrl`, else the chain's default RPC. */
204
234
  publicClient?: PublicClient;
205
235
  rpcUrl?: string;
236
+ /** The wallet's account and chain now, which a prepared send checks before it sends. */
237
+ current?: CurrentWalletState;
206
238
  };
207
239
  /** Bind a viem WalletClient and PublicClient into the mpo EVM client. */
208
240
  export declare function evmClient(config: EvmClientConfig): EvmClient;
@@ -1 +1 @@
1
- {"version":3,"file":"evm.d.ts","sourceRoot":"","sources":["../../src/clients/evm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"evm.d.ts","sourceRoot":"","sources":["../../src/clients/evm.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/clients/hooks.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,EAAa,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAC;AACxE,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGlD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,SAAS,GAAG,SAAS,CA2BzF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,aAAa,GAAG,SAAS,CAkBjG;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,SAAS,GAAG,SAAS,CAYpD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,SAAS,CAY5D"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/clients/hooks.ts"],"names":[],"mappings":"AAKA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,EAAa,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAC;AACxE,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGlD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,UAAU,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,SAAS,GAAG,SAAS,CA6BzF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,aAAa,GAAG,SAAS,CAkBjG;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,SAAS,GAAG,SAAS,CAYpD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,SAAS,CAY5D"}
@@ -1,5 +1,6 @@
1
1
  export { ReadOnlyClientError, UnsupportedClientMethodError, type ChainClient, type ClientCapability, type ClientFamily, } from "./types";
2
- export { classifyTxError, evmClient, ReceiptPendingError, ReceiptWaitAbortedError, TransactionReplacedError, TransactionRevertedError, type Erc20Actions, type EvmClient, type EvmClientConfig, type EvmReplacementReason, type EvmSendTransactionParameters, type EvmWaitOptions, type EvmWalletClient, type EvmWriteContractParameters, type TxErrorKind, } from "./evm";
2
+ export { classifyTxError, evmClient, ReceiptPendingError, ReceiptWaitAbortedError, TransactionReplacedError, TransactionRevertedError, type Erc20Actions, type EvmClient, type EvmClientConfig, type EvmPrepareTransactionParameters, type EvmPrepareWriteContractParameters, type EvmReplacementReason, type EvmSendTransactionParameters, type EvmWaitOptions, type EvmWalletClient, type EvmWriteContractParameters, type TxErrorKind, } from "./evm";
3
+ export { DEFAULT_PREPARED_SEND_MAX_AGE_MS, prepareEvmSend, PreparedSendStaleError, type CurrentWalletState, type Eip1193Request, type PrepareEvmSendParameters, type PreparedEvmSend, type PreparedSendStaleReason, } from "./preparedSend";
3
4
  export { evmReadClient, evmReadClients, type Erc20ReadActions, type EvmReadClient, type EvmReadClientConfig, type EvmReadClients, } from "./evmRead";
4
5
  export type { Web3ChainConfig } from "../providers/walletConfig";
5
6
  export { suiClient, type SuiClient } from "./sui";