@multiplatform.one/web3 7.16.0 → 7.18.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.
- package/dist/cjs/connectkit/components/Common/ConnectorList/index.cjs +33 -5
- package/dist/cjs/connectkit/components/Common/ConnectorList/index.native.js +38 -5
- package/dist/cjs/connectkit/components/Common/ConnectorList/index.native.js.map +1 -1
- package/dist/cjs/connectkit/components/ConnectButton/index.cjs +5 -0
- package/dist/cjs/connectkit/components/ConnectButton/index.native.js +5 -0
- package/dist/cjs/connectkit/components/ConnectButton/index.native.js.map +1 -1
- package/dist/cjs/connectkit/components/ConnectModal/ConnectWithInjector/index.cjs +9 -4
- package/dist/cjs/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js +12 -7
- package/dist/cjs/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js.map +1 -1
- package/dist/cjs/connectkit/index.cjs +5 -0
- package/dist/cjs/connectkit/index.native.js +5 -0
- package/dist/cjs/connectkit/index.native.js.map +1 -1
- package/dist/cjs/connectkit/openConnector/context.cjs +146 -0
- package/dist/cjs/connectkit/openConnector/context.native.js +188 -0
- package/dist/cjs/connectkit/openConnector/context.native.js.map +1 -0
- package/dist/cjs/connectkit/openConnector/device.cjs +42 -0
- package/dist/cjs/connectkit/openConnector/device.native.js +51 -0
- package/dist/cjs/connectkit/openConnector/device.native.js.map +1 -0
- package/dist/cjs/connectkit/openConnector/index.cjs +35 -0
- package/dist/cjs/connectkit/openConnector/index.native.js +38 -0
- package/dist/cjs/connectkit/openConnector/index.native.js.map +1 -0
- package/dist/cjs/connectkit/openConnector/launcher.cjs +133 -0
- package/dist/cjs/connectkit/openConnector/launcher.native.js +158 -0
- package/dist/cjs/connectkit/openConnector/launcher.native.js.map +1 -0
- package/dist/cjs/connectkit/screens.cjs +1 -10
- package/dist/cjs/connectkit/screens.native.js +1 -12
- package/dist/cjs/connectkit/screens.native.js.map +1 -1
- package/dist/cjs/connectkit/siwe/connectIntent.cjs +9 -5
- package/dist/cjs/connectkit/siwe/connectIntent.native.js +10 -3
- package/dist/cjs/connectkit/siwe/connectIntent.native.js.map +1 -1
- package/dist/cjs/connectkit/useWeb3Modal.cjs +21 -0
- package/dist/cjs/connectkit/useWeb3Modal.native.js +22 -0
- package/dist/cjs/connectkit/useWeb3Modal.native.js.map +1 -1
- package/dist/cjs/connectkit/web3Bridge.cjs +4 -1
- package/dist/cjs/connectkit/web3Bridge.native.js +4 -1
- package/dist/cjs/connectkit/web3Bridge.native.js.map +1 -1
- package/dist/cjs/connectkit/web3Provider.native.js.map +1 -1
- package/dist/esm/connectkit/components/Common/ConnectorList/index.mjs +34 -6
- package/dist/esm/connectkit/components/Common/ConnectorList/index.mjs.map +1 -1
- package/dist/esm/connectkit/components/Common/ConnectorList/index.native.js +39 -6
- package/dist/esm/connectkit/components/Common/ConnectorList/index.native.js.map +1 -1
- package/dist/esm/connectkit/components/ConnectButton/index.mjs +5 -0
- package/dist/esm/connectkit/components/ConnectButton/index.mjs.map +1 -1
- package/dist/esm/connectkit/components/ConnectButton/index.native.js +5 -0
- package/dist/esm/connectkit/components/ConnectButton/index.native.js.map +1 -1
- package/dist/esm/connectkit/components/ConnectModal/ConnectWithInjector/index.mjs +9 -4
- package/dist/esm/connectkit/components/ConnectModal/ConnectWithInjector/index.mjs.map +1 -1
- package/dist/esm/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js +12 -7
- package/dist/esm/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js.map +1 -1
- package/dist/esm/connectkit/index.mjs +3 -1
- package/dist/esm/connectkit/index.mjs.map +1 -1
- package/dist/esm/connectkit/index.native.js +3 -1
- package/dist/esm/connectkit/index.native.js.map +1 -1
- package/dist/esm/connectkit/openConnector/context.mjs +118 -0
- package/dist/esm/connectkit/openConnector/context.mjs.map +1 -0
- package/dist/esm/connectkit/openConnector/context.native.js +146 -0
- package/dist/esm/connectkit/openConnector/context.native.js.map +1 -0
- package/dist/esm/connectkit/openConnector/device.mjs +16 -0
- package/dist/esm/connectkit/openConnector/device.mjs.map +1 -0
- package/dist/esm/connectkit/openConnector/device.native.js +22 -0
- package/dist/esm/connectkit/openConnector/device.native.js.map +1 -0
- package/dist/esm/connectkit/openConnector/index.mjs +4 -0
- package/dist/esm/connectkit/openConnector/index.mjs.map +1 -0
- package/dist/esm/connectkit/openConnector/index.native.js +4 -0
- package/dist/esm/connectkit/openConnector/index.native.js.map +1 -0
- package/dist/esm/connectkit/openConnector/launcher.mjs +106 -0
- package/dist/esm/connectkit/openConnector/launcher.mjs.map +1 -0
- package/dist/esm/connectkit/openConnector/launcher.native.js +128 -0
- package/dist/esm/connectkit/openConnector/launcher.native.js.map +1 -0
- package/dist/esm/connectkit/screens.mjs +2 -11
- package/dist/esm/connectkit/screens.mjs.map +1 -1
- package/dist/esm/connectkit/screens.native.js +2 -13
- package/dist/esm/connectkit/screens.native.js.map +1 -1
- package/dist/esm/connectkit/siwe/connectIntent.mjs +9 -6
- package/dist/esm/connectkit/siwe/connectIntent.mjs.map +1 -1
- package/dist/esm/connectkit/siwe/connectIntent.native.js +10 -4
- package/dist/esm/connectkit/siwe/connectIntent.native.js.map +1 -1
- package/dist/esm/connectkit/useWeb3Modal.mjs +22 -1
- package/dist/esm/connectkit/useWeb3Modal.mjs.map +1 -1
- package/dist/esm/connectkit/useWeb3Modal.native.js +23 -1
- package/dist/esm/connectkit/useWeb3Modal.native.js.map +1 -1
- package/dist/esm/connectkit/web3Bridge.mjs +4 -1
- package/dist/esm/connectkit/web3Bridge.mjs.map +1 -1
- package/dist/esm/connectkit/web3Bridge.native.js +4 -1
- package/dist/esm/connectkit/web3Bridge.native.js.map +1 -1
- package/dist/esm/connectkit/web3Provider.mjs.map +1 -1
- package/dist/esm/connectkit/web3Provider.native.js.map +1 -1
- package/dist/jsx/connectkit/components/Common/ConnectorList/index.mjs +34 -6
- package/dist/jsx/connectkit/components/Common/ConnectorList/index.mjs.map +1 -1
- package/dist/jsx/connectkit/components/Common/ConnectorList/index.native.js +38 -5
- package/dist/jsx/connectkit/components/Common/ConnectorList/index.native.js.map +1 -1
- package/dist/jsx/connectkit/components/ConnectButton/index.mjs +5 -0
- package/dist/jsx/connectkit/components/ConnectButton/index.mjs.map +1 -1
- package/dist/jsx/connectkit/components/ConnectButton/index.native.js +5 -0
- package/dist/jsx/connectkit/components/ConnectButton/index.native.js.map +1 -1
- package/dist/jsx/connectkit/components/ConnectModal/ConnectWithInjector/index.mjs +9 -4
- package/dist/jsx/connectkit/components/ConnectModal/ConnectWithInjector/index.mjs.map +1 -1
- package/dist/jsx/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js +12 -7
- package/dist/jsx/connectkit/components/ConnectModal/ConnectWithInjector/index.native.js.map +1 -1
- package/dist/jsx/connectkit/index.mjs +3 -1
- package/dist/jsx/connectkit/index.mjs.map +1 -1
- package/dist/jsx/connectkit/index.native.js +5 -0
- package/dist/jsx/connectkit/index.native.js.map +1 -1
- package/dist/jsx/connectkit/openConnector/context.mjs +118 -0
- package/dist/jsx/connectkit/openConnector/context.mjs.map +1 -0
- package/dist/jsx/connectkit/openConnector/context.native.js +188 -0
- package/dist/jsx/connectkit/openConnector/context.native.js.map +1 -0
- package/dist/jsx/connectkit/openConnector/device.mjs +16 -0
- package/dist/jsx/connectkit/openConnector/device.mjs.map +1 -0
- package/dist/jsx/connectkit/openConnector/device.native.js +51 -0
- package/dist/jsx/connectkit/openConnector/device.native.js.map +1 -0
- package/dist/jsx/connectkit/openConnector/index.mjs +4 -0
- package/dist/jsx/connectkit/openConnector/index.mjs.map +1 -0
- package/dist/jsx/connectkit/openConnector/index.native.js +38 -0
- package/dist/jsx/connectkit/openConnector/index.native.js.map +1 -0
- package/dist/jsx/connectkit/openConnector/launcher.mjs +106 -0
- package/dist/jsx/connectkit/openConnector/launcher.mjs.map +1 -0
- package/dist/jsx/connectkit/openConnector/launcher.native.js +158 -0
- package/dist/jsx/connectkit/openConnector/launcher.native.js.map +1 -0
- package/dist/jsx/connectkit/screens.mjs +2 -11
- package/dist/jsx/connectkit/screens.mjs.map +1 -1
- package/dist/jsx/connectkit/screens.native.js +1 -12
- package/dist/jsx/connectkit/screens.native.js.map +1 -1
- package/dist/jsx/connectkit/siwe/connectIntent.mjs +9 -6
- package/dist/jsx/connectkit/siwe/connectIntent.mjs.map +1 -1
- package/dist/jsx/connectkit/siwe/connectIntent.native.js +10 -3
- package/dist/jsx/connectkit/siwe/connectIntent.native.js.map +1 -1
- package/dist/jsx/connectkit/useWeb3Modal.mjs +22 -1
- package/dist/jsx/connectkit/useWeb3Modal.mjs.map +1 -1
- package/dist/jsx/connectkit/useWeb3Modal.native.js +22 -0
- package/dist/jsx/connectkit/useWeb3Modal.native.js.map +1 -1
- package/dist/jsx/connectkit/web3Bridge.mjs +4 -1
- package/dist/jsx/connectkit/web3Bridge.mjs.map +1 -1
- package/dist/jsx/connectkit/web3Bridge.native.js +4 -1
- package/dist/jsx/connectkit/web3Bridge.native.js.map +1 -1
- package/dist/jsx/connectkit/web3Provider.mjs.map +1 -1
- package/dist/jsx/connectkit/web3Provider.native.js.map +1 -1
- package/package.json +7 -6
- package/src/connectkit/components/Common/ConnectorList/index.tsx +30 -2
- package/src/connectkit/components/ConnectButton/index.tsx +5 -0
- package/src/connectkit/components/ConnectModal/ConnectWithInjector/index.tsx +13 -8
- package/src/connectkit/index.ts +8 -0
- package/src/connectkit/openConnector/context.tsx +176 -0
- package/src/connectkit/openConnector/device.spec.ts +86 -0
- package/src/connectkit/openConnector/device.ts +37 -0
- package/src/connectkit/openConnector/index.ts +18 -0
- package/src/connectkit/openConnector/launcher.spec.ts +325 -0
- package/src/connectkit/openConnector/launcher.ts +203 -0
- package/src/connectkit/openConnector/modal.spec.tsx +330 -0
- package/src/connectkit/screens.tsx +2 -11
- package/src/connectkit/siwe/connectIntent.spec.ts +90 -0
- package/src/connectkit/siwe/connectIntent.ts +19 -6
- package/src/connectkit/useWeb3Modal.ts +25 -1
- package/src/connectkit/web3Bridge.tsx +4 -1
- package/src/connectkit/web3Provider.tsx +4 -1
- package/types/connectkit/components/Common/ConnectorList/index.d.ts.map +1 -1
- package/types/connectkit/components/ConnectButton/index.d.ts.map +1 -1
- package/types/connectkit/components/ConnectModal/ConnectWithInjector/index.d.ts.map +1 -1
- package/types/connectkit/index.d.ts +2 -0
- package/types/connectkit/index.d.ts.map +1 -1
- package/types/connectkit/openConnector/context.d.ts +48 -0
- package/types/connectkit/openConnector/context.d.ts.map +1 -0
- package/types/connectkit/openConnector/device.d.ts +18 -0
- package/types/connectkit/openConnector/device.d.ts.map +1 -0
- package/types/connectkit/openConnector/index.d.ts +3 -0
- package/types/connectkit/openConnector/index.d.ts.map +1 -0
- package/types/connectkit/openConnector/launcher.d.ts +64 -0
- package/types/connectkit/openConnector/launcher.d.ts.map +1 -0
- package/types/connectkit/screens.d.ts.map +1 -1
- package/types/connectkit/siwe/connectIntent.d.ts +8 -3
- package/types/connectkit/siwe/connectIntent.d.ts.map +1 -1
- package/types/connectkit/useWeb3Modal.d.ts +16 -0
- package/types/connectkit/useWeb3Modal.d.ts.map +1 -1
- package/types/connectkit/web3Bridge.d.ts.map +1 -1
- package/types/connectkit/web3Provider.d.ts +4 -1
- package/types/connectkit/web3Provider.d.ts.map +1 -1
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { act, cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
5
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
6
|
+
import { WagmiProvider, createConfig, createStorage, http, type CreateConnectorFn } from "wagmi";
|
|
7
|
+
import { connect } from "wagmi/actions";
|
|
8
|
+
import { mock } from "wagmi/connectors";
|
|
9
|
+
import { mainnet } from "wagmi/chains";
|
|
10
|
+
import { routes, useContext } from "@multiplatform.one/connectkit";
|
|
11
|
+
import { GpgProvider } from "@multiplatform.one/gpg";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
ConnectKitProvider,
|
|
15
|
+
DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS,
|
|
16
|
+
useModal,
|
|
17
|
+
type Web3ConnectKitOptions,
|
|
18
|
+
} from "..";
|
|
19
|
+
import ConnectorList from "../components/Common/ConnectorList";
|
|
20
|
+
|
|
21
|
+
const ANDROID_UA =
|
|
22
|
+
"Mozilla/5.0 (Linux; Android 16; Pixel 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Mobile Safari/537.36";
|
|
23
|
+
const DESKTOP_UA =
|
|
24
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36";
|
|
25
|
+
|
|
26
|
+
function setUserAgent(ua: string) {
|
|
27
|
+
Object.defineProperty(window.navigator, "userAgent", { value: ua, configurable: true });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function memoryStorage() {
|
|
31
|
+
const map = new Map<string, string>();
|
|
32
|
+
return {
|
|
33
|
+
getItem: (key: string) => map.get(key) ?? null,
|
|
34
|
+
setItem: (key: string, value: string) => void map.set(key, value),
|
|
35
|
+
removeItem: (key: string) => void map.delete(key),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const ACCOUNT = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
|
|
40
|
+
|
|
41
|
+
// A second wallet: the mock connector under another id.
|
|
42
|
+
const otherWallet: CreateConnectorFn = (config) => ({
|
|
43
|
+
...mock({ accounts: [ACCOUNT], features: {} })(config),
|
|
44
|
+
id: "other",
|
|
45
|
+
name: "Other Wallet",
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
function makeConfig({ second = false }: { second?: boolean } = {}) {
|
|
49
|
+
return createConfig({
|
|
50
|
+
chains: [mainnet],
|
|
51
|
+
connectors: [mock({ accounts: [ACCOUNT], features: {} }), ...(second ? [otherWallet] : [])],
|
|
52
|
+
transports: { [mainnet.id]: http() },
|
|
53
|
+
storage: createStorage({ storage: memoryStorage() }),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A config whose first connector's connect never answers (no wallet app). */
|
|
58
|
+
function makeUnansweredConfig(options?: { second?: boolean }) {
|
|
59
|
+
const config = makeConfig(options);
|
|
60
|
+
const connectSpy = vi
|
|
61
|
+
.spyOn(config.connectors[0], "connect")
|
|
62
|
+
.mockImplementation(() => new Promise(() => {}));
|
|
63
|
+
return { config, connectSpy };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type Probe = { route?: string; open?: boolean; connectorId?: string; routes: string[] };
|
|
67
|
+
|
|
68
|
+
function Harness({
|
|
69
|
+
options,
|
|
70
|
+
gpg,
|
|
71
|
+
children,
|
|
72
|
+
probe,
|
|
73
|
+
config,
|
|
74
|
+
}: {
|
|
75
|
+
options?: Web3ConnectKitOptions;
|
|
76
|
+
gpg?: boolean;
|
|
77
|
+
children?: React.ReactNode;
|
|
78
|
+
probe: Probe;
|
|
79
|
+
config?: ReturnType<typeof makeConfig>;
|
|
80
|
+
}) {
|
|
81
|
+
const [cfg] = React.useState(() => config ?? makeConfig());
|
|
82
|
+
const [client] = React.useState(() => new QueryClient());
|
|
83
|
+
const tree = (
|
|
84
|
+
<ConnectKitProvider options={options}>
|
|
85
|
+
<ProbeRoute probe={probe} />
|
|
86
|
+
{children}
|
|
87
|
+
</ConnectKitProvider>
|
|
88
|
+
);
|
|
89
|
+
return (
|
|
90
|
+
<WagmiProvider config={cfg}>
|
|
91
|
+
<QueryClientProvider client={client}>
|
|
92
|
+
{gpg ? (
|
|
93
|
+
<GpgProvider getNonce={async () => "nonce"} onSign={() => true}>
|
|
94
|
+
{tree}
|
|
95
|
+
</GpgProvider>
|
|
96
|
+
) : (
|
|
97
|
+
tree
|
|
98
|
+
)}
|
|
99
|
+
</QueryClientProvider>
|
|
100
|
+
</WagmiProvider>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function ProbeRoute({ probe }: { probe: Probe }) {
|
|
105
|
+
const context = useContext();
|
|
106
|
+
probe.route = context.route;
|
|
107
|
+
probe.open = context.open;
|
|
108
|
+
probe.connectorId = context.connector.id;
|
|
109
|
+
if (probe.routes[probe.routes.length - 1] !== context.route) probe.routes.push(context.route);
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let modal: ReturnType<typeof useModal> | undefined;
|
|
114
|
+
let ctx: ReturnType<typeof useContext> | undefined;
|
|
115
|
+
function GrabModal() {
|
|
116
|
+
modal = useModal();
|
|
117
|
+
ctx = useContext();
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
122
|
+
|
|
123
|
+
afterEach(() => {
|
|
124
|
+
vi.useRealTimers();
|
|
125
|
+
cleanup();
|
|
126
|
+
modal = undefined;
|
|
127
|
+
ctx = undefined;
|
|
128
|
+
setUserAgent(DESKTOP_UA);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe("GPG in the wallet list", () => {
|
|
132
|
+
it("renders a GPG row next to the wallets when GPG sign-in is on, and it opens the GPG screen", async () => {
|
|
133
|
+
const probe: Probe = { routes: [] };
|
|
134
|
+
render(
|
|
135
|
+
<Harness gpg probe={probe}>
|
|
136
|
+
<ConnectorList />
|
|
137
|
+
</Harness>,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const row = await screen.findByText("GPG");
|
|
141
|
+
expect(screen.getByText("Mock Connector")).toBeTruthy();
|
|
142
|
+
const button = row.closest("button") as HTMLButtonElement;
|
|
143
|
+
expect(button.getAttribute("data-screen-entry")).toBe(routes.SIGNINWITHGPG);
|
|
144
|
+
|
|
145
|
+
fireEvent.click(button);
|
|
146
|
+
await waitFor(() => expect(probe.route).toBe(routes.SIGNINWITHGPG));
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("has no GPG row without a GpgProvider", async () => {
|
|
150
|
+
const probe: Probe = { routes: [] };
|
|
151
|
+
render(
|
|
152
|
+
<Harness probe={probe}>
|
|
153
|
+
<ConnectorList />
|
|
154
|
+
</Harness>,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
await screen.findByText("Mock Connector");
|
|
158
|
+
expect(screen.queryByText("GPG")).toBeNull();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe("mobile.preferredConnector", () => {
|
|
163
|
+
it("sends openSIWE() on a phone straight to the connector, with no list", async () => {
|
|
164
|
+
setUserAgent(ANDROID_UA);
|
|
165
|
+
const probe: Probe = { routes: [] };
|
|
166
|
+
render(
|
|
167
|
+
<Harness options={{ mobile: { preferredConnector: "mock" } }} probe={probe}>
|
|
168
|
+
<GrabModal />
|
|
169
|
+
</Harness>,
|
|
170
|
+
);
|
|
171
|
+
await waitFor(() => expect(modal).toBeDefined());
|
|
172
|
+
|
|
173
|
+
expect(probe.open).toBe(false);
|
|
174
|
+
probe.routes.length = 0;
|
|
175
|
+
act(() => modal!.openSIWE());
|
|
176
|
+
|
|
177
|
+
expect(probe.routes).toEqual([routes.CONNECT]);
|
|
178
|
+
expect(probe.route).toBe(routes.CONNECT);
|
|
179
|
+
expect(probe.connectorId).toBe("mock");
|
|
180
|
+
expect(probe.open).toBe(true);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("keeps the wallet list on desktop", async () => {
|
|
184
|
+
setUserAgent(DESKTOP_UA);
|
|
185
|
+
const probe: Probe = { routes: [] };
|
|
186
|
+
render(
|
|
187
|
+
<Harness options={{ mobile: { preferredConnector: "mock" } }} probe={probe}>
|
|
188
|
+
<GrabModal />
|
|
189
|
+
</Harness>,
|
|
190
|
+
);
|
|
191
|
+
await waitFor(() => expect(modal).toBeDefined());
|
|
192
|
+
|
|
193
|
+
act(() => modal!.openSIWE());
|
|
194
|
+
|
|
195
|
+
expect(probe.route).toBe(routes.CONNECTORS);
|
|
196
|
+
expect(probe.open).toBe(true);
|
|
197
|
+
expect(modal!.pendingConnector).toBeNull();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("openConnector connects the wallet from the connecting screen, never the list", async () => {
|
|
201
|
+
setUserAgent(ANDROID_UA);
|
|
202
|
+
const config = makeConfig();
|
|
203
|
+
const connectSpy = vi.spyOn(config.connectors[0], "connect");
|
|
204
|
+
const probe: Probe = { routes: [] };
|
|
205
|
+
render(
|
|
206
|
+
<Harness probe={probe} config={config}>
|
|
207
|
+
<GrabModal />
|
|
208
|
+
</Harness>,
|
|
209
|
+
);
|
|
210
|
+
await waitFor(() => expect(modal).toBeDefined());
|
|
211
|
+
|
|
212
|
+
probe.routes.length = 0;
|
|
213
|
+
act(() => modal!.openConnector("mock"));
|
|
214
|
+
|
|
215
|
+
expect(probe.route).toBe(routes.CONNECT);
|
|
216
|
+
expect(probe.connectorId).toBe("mock");
|
|
217
|
+
await waitFor(() => expect(config.state.status).toBe("connected"));
|
|
218
|
+
expect(connectSpy).toHaveBeenCalledTimes(1);
|
|
219
|
+
expect(probe.routes).toEqual([routes.CONNECT]);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
describe("the openConnector session", () => {
|
|
224
|
+
async function renderUnanswered(options?: { second?: boolean }) {
|
|
225
|
+
setUserAgent(ANDROID_UA);
|
|
226
|
+
const { config, connectSpy } = makeUnansweredConfig(options);
|
|
227
|
+
const probe: Probe = { routes: [] };
|
|
228
|
+
render(
|
|
229
|
+
<Harness probe={probe} config={config}>
|
|
230
|
+
<GrabModal />
|
|
231
|
+
</Harness>,
|
|
232
|
+
);
|
|
233
|
+
await waitFor(() => expect(modal).toBeDefined());
|
|
234
|
+
return { config, connectSpy, probe };
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
it("a modal the user closed stays closed when the fallback would have fired", async () => {
|
|
238
|
+
const { probe } = await renderUnanswered();
|
|
239
|
+
|
|
240
|
+
act(() => modal!.openConnector("mock", { fallbackMs: 50 }));
|
|
241
|
+
expect(probe.open).toBe(true);
|
|
242
|
+
expect(modal!.pendingConnector).toBe("mock");
|
|
243
|
+
|
|
244
|
+
act(() => ctx!.setOpen(false));
|
|
245
|
+
expect(modal!.pendingConnector).toBeNull();
|
|
246
|
+
|
|
247
|
+
await act(() => sleep(150));
|
|
248
|
+
expect(probe.open).toBe(false);
|
|
249
|
+
expect(probe.route).toBe(routes.CONNECT);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("a screen the user moved to keeps them when the fallback would have fired", async () => {
|
|
253
|
+
const { probe } = await renderUnanswered();
|
|
254
|
+
|
|
255
|
+
act(() => modal!.openConnector("mock", { fallbackMs: 50 }));
|
|
256
|
+
act(() => ctx!.setRoute(routes.ABOUT));
|
|
257
|
+
expect(modal!.pendingConnector).toBeNull();
|
|
258
|
+
|
|
259
|
+
await act(() => sleep(150));
|
|
260
|
+
expect(probe.route).toBe(routes.ABOUT);
|
|
261
|
+
expect(probe.open).toBe(true);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it("the user staying on the connecting screen still gets the list", async () => {
|
|
265
|
+
const { probe } = await renderUnanswered();
|
|
266
|
+
|
|
267
|
+
act(() => modal!.openConnector("mock", { fallbackMs: 50 }));
|
|
268
|
+
await act(() => sleep(150));
|
|
269
|
+
|
|
270
|
+
expect(probe.route).toBe(routes.CONNECTORS);
|
|
271
|
+
expect(probe.open).toBe(true);
|
|
272
|
+
expect(modal!.pendingConnector).toBeNull();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it("another wallet connecting ends the session the unanswered connect left", async () => {
|
|
276
|
+
const { config } = await renderUnanswered({ second: true });
|
|
277
|
+
|
|
278
|
+
act(() => modal!.openConnector("mock", { fallbackMs: 0 }));
|
|
279
|
+
expect(modal!.pendingConnector).toBe("mock");
|
|
280
|
+
|
|
281
|
+
await act(async () => {
|
|
282
|
+
await connect(config, { connector: config.connectors[1] });
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
await waitFor(() => expect(modal!.pendingConnector).toBeNull());
|
|
286
|
+
expect(config.state.current).toBe(config.connectors[1].uid);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("reaches connector.connect with no macrotask between the call and the connect", async () => {
|
|
290
|
+
const { connectSpy } = await renderUnanswered();
|
|
291
|
+
let macrotaskRan = false;
|
|
292
|
+
let connectBeforeMacrotask: boolean | undefined;
|
|
293
|
+
connectSpy.mockImplementation(() => {
|
|
294
|
+
connectBeforeMacrotask = !macrotaskRan;
|
|
295
|
+
return new Promise(() => {});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
await act(async () => {
|
|
299
|
+
setTimeout(() => {
|
|
300
|
+
macrotaskRan = true;
|
|
301
|
+
}, 0);
|
|
302
|
+
modal!.openConnector("mock");
|
|
303
|
+
await sleep(0);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
expect(connectSpy).toHaveBeenCalledTimes(1);
|
|
307
|
+
expect(connectBeforeMacrotask).toBe(true);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it("an explicit call on desktop falls back after the desktop default", async () => {
|
|
311
|
+
const { config } = makeUnansweredConfig();
|
|
312
|
+
const probe: Probe = { routes: [] };
|
|
313
|
+
render(
|
|
314
|
+
<Harness probe={probe} config={config}>
|
|
315
|
+
<GrabModal />
|
|
316
|
+
</Harness>,
|
|
317
|
+
);
|
|
318
|
+
await waitFor(() => expect(modal).toBeDefined());
|
|
319
|
+
vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
|
|
320
|
+
|
|
321
|
+
act(() => modal!.openConnector("mock"));
|
|
322
|
+
expect(probe.route).toBe(routes.CONNECT);
|
|
323
|
+
|
|
324
|
+
act(() => vi.advanceTimersByTime(DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS - 1));
|
|
325
|
+
expect(probe.route).toBe(routes.CONNECT);
|
|
326
|
+
act(() => vi.advanceTimersByTime(1));
|
|
327
|
+
expect(probe.route).toBe(routes.CONNECTORS);
|
|
328
|
+
expect(modal!.pendingConnector).toBeNull();
|
|
329
|
+
});
|
|
330
|
+
});
|
|
@@ -18,7 +18,7 @@ import DownloadApp from "./components/Pages/DownloadApp";
|
|
|
18
18
|
import Profile from "./components/Pages/Profile";
|
|
19
19
|
import SwitchNetworks from "./components/Pages/SwitchNetworks";
|
|
20
20
|
import SignInWithEthereum from "./components/Pages/SignInWithEthereum";
|
|
21
|
-
import {
|
|
21
|
+
import { gpgScreen } from "@multiplatform.one/gpg";
|
|
22
22
|
|
|
23
23
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
24
|
// web3's screen catalogue — the wallet (+ the legacy GPG) screens contributed to
|
|
@@ -134,16 +134,7 @@ export const web3Screens: readonly ScreenDef[] = [
|
|
|
134
134
|
availableWhen: (s) => !!s.connected,
|
|
135
135
|
onBack: (api) => api.setRoute(routes.PROFILE),
|
|
136
136
|
},
|
|
137
|
-
|
|
138
|
-
id: routes.SIGNINWITHGPG,
|
|
139
|
-
component: SignInWithGpg,
|
|
140
|
-
// Hardcoded (vs a locale key) to avoid touching every locale file for Phase 1.
|
|
141
|
-
heading: "Sign in with GPG",
|
|
142
|
-
// GPG has no connect step — valid in both connected and disconnected states.
|
|
143
|
-
availableWhen: () => true,
|
|
144
|
-
showBack: false,
|
|
145
|
-
showInfo: false,
|
|
146
|
-
},
|
|
137
|
+
gpgScreen,
|
|
147
138
|
];
|
|
148
139
|
|
|
149
140
|
/**
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CONNECT_INTENT_TTL_MS,
|
|
5
|
+
clearConnectIntent,
|
|
6
|
+
consumeConnectIntent,
|
|
7
|
+
setConnectIntent,
|
|
8
|
+
} from "./connectIntent";
|
|
9
|
+
|
|
10
|
+
const KEY = "wallet:connect-intent";
|
|
11
|
+
|
|
12
|
+
function memoryStorage() {
|
|
13
|
+
const map = new Map<string, string>();
|
|
14
|
+
return {
|
|
15
|
+
getItem: (k: string) => (map.has(k) ? (map.get(k) as string) : null),
|
|
16
|
+
setItem: (k: string, v: string) => void map.set(k, String(v)),
|
|
17
|
+
removeItem: (k: string) => void map.delete(k),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe("connectIntent", () => {
|
|
22
|
+
let storage: ReturnType<typeof memoryStorage>;
|
|
23
|
+
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
storage = memoryStorage();
|
|
26
|
+
vi.stubGlobal("window", { sessionStorage: storage });
|
|
27
|
+
});
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
vi.unstubAllGlobals();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("defaults the TTL to 90 s", () => {
|
|
33
|
+
expect(CONNECT_INTENT_TTL_MS).toBe(90_000);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("is honoured within the TTL", () => {
|
|
37
|
+
setConnectIntent(undefined, 1_000);
|
|
38
|
+
expect(consumeConnectIntent(1_000 + 89_999)).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("expires after the TTL, so a cold load never fires an unsolicited signature", () => {
|
|
42
|
+
setConnectIntent(undefined, 1_000);
|
|
43
|
+
expect(consumeConnectIntent(1_000 + 90_000)).toBe(false);
|
|
44
|
+
expect(storage.getItem(KEY)).toBeNull();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("is consumed once", () => {
|
|
48
|
+
setConnectIntent(undefined, 1_000);
|
|
49
|
+
expect(consumeConnectIntent(2_000)).toBe(true);
|
|
50
|
+
expect(consumeConnectIntent(2_000)).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("takes a custom TTL", () => {
|
|
54
|
+
setConnectIntent(5_000, 1_000);
|
|
55
|
+
expect(consumeConnectIntent(5_999)).toBe(true);
|
|
56
|
+
setConnectIntent(5_000, 1_000);
|
|
57
|
+
expect(consumeConnectIntent(6_000)).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("treats the old '1' flag as expired", () => {
|
|
61
|
+
storage.setItem(KEY, "1");
|
|
62
|
+
expect(consumeConnectIntent()).toBe(false);
|
|
63
|
+
expect(storage.getItem(KEY)).toBeNull();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("is false with nothing stored and after a clear", () => {
|
|
67
|
+
expect(consumeConnectIntent()).toBe(false);
|
|
68
|
+
setConnectIntent();
|
|
69
|
+
clearConnectIntent();
|
|
70
|
+
expect(consumeConnectIntent()).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("degrades to false when storage throws", () => {
|
|
74
|
+
vi.stubGlobal("window", {
|
|
75
|
+
sessionStorage: {
|
|
76
|
+
getItem: () => {
|
|
77
|
+
throw new Error("SecurityError");
|
|
78
|
+
},
|
|
79
|
+
setItem: () => {
|
|
80
|
+
throw new Error("SecurityError");
|
|
81
|
+
},
|
|
82
|
+
removeItem: () => {
|
|
83
|
+
throw new Error("SecurityError");
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
expect(() => setConnectIntent()).not.toThrow();
|
|
88
|
+
expect(consumeConnectIntent()).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -15,25 +15,38 @@
|
|
|
15
15
|
* page load with a wallet already connected must NOT pop a modal the user never asked
|
|
16
16
|
* for. Only a connect the user just initiated carries the intent, and it's consumed
|
|
17
17
|
* once acted on.
|
|
18
|
+
*
|
|
19
|
+
* The stored value is the moment the intent expires. An abandoned connect (the user
|
|
20
|
+
* opened the wallet and never came back) would otherwise leave the flag set for the
|
|
21
|
+
* rest of the tab's life, and a later visit whose wallet auto-reconnects would pop a
|
|
22
|
+
* signature request nobody asked for.
|
|
18
23
|
*/
|
|
19
24
|
const KEY = "wallet:connect-intent";
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
/** How long a connect intent stays good. Long enough for a wallet app round trip. */
|
|
27
|
+
export const CONNECT_INTENT_TTL_MS = 90_000;
|
|
28
|
+
|
|
29
|
+
export function setConnectIntent(ttlMs: number = CONNECT_INTENT_TTL_MS, now: number = Date.now()) {
|
|
22
30
|
if (typeof window === "undefined") return;
|
|
23
31
|
try {
|
|
24
|
-
window.sessionStorage.setItem(KEY,
|
|
32
|
+
window.sessionStorage.setItem(KEY, String(now + ttlMs));
|
|
25
33
|
} catch {
|
|
26
34
|
// Private mode / storage disabled — degrade to the old behaviour, don't throw.
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
37
|
|
|
30
|
-
/**
|
|
31
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Reads and clears the flag; true only for a connect the user initiated within the
|
|
40
|
+
* TTL. A second call returns false.
|
|
41
|
+
*/
|
|
42
|
+
export function consumeConnectIntent(now: number = Date.now()): boolean {
|
|
32
43
|
if (typeof window === "undefined") return false;
|
|
33
44
|
try {
|
|
34
|
-
const
|
|
45
|
+
const raw = window.sessionStorage.getItem(KEY);
|
|
46
|
+
if (raw === null) return false;
|
|
35
47
|
window.sessionStorage.removeItem(KEY);
|
|
36
|
-
|
|
48
|
+
const expiresAt = Number(raw);
|
|
49
|
+
return Number.isFinite(expiresAt) && now < expiresAt;
|
|
37
50
|
} catch {
|
|
38
51
|
return false;
|
|
39
52
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { routes, useModal } from "@multiplatform.one/connectkit";
|
|
1
|
+
import { routes, useModal, useModalState } from "@multiplatform.one/connectkit";
|
|
2
2
|
import { useSIWE } from "./siwe";
|
|
3
3
|
import { useConnectCallback, useConnectCallbackProps } from "./hooks/useConnectCallback";
|
|
4
|
+
import { useConnectorLauncher, type OpenConnectorOptions } from "./openConnector";
|
|
4
5
|
|
|
5
6
|
type UseModalProps = {} & useConnectCallbackProps;
|
|
6
7
|
|
|
@@ -10,11 +11,31 @@ type UseModalProps = {} & useConnectCallbackProps;
|
|
|
10
11
|
export const useWeb3Modal = ({ onConnect, onDisconnect }: UseModalProps = {}) => {
|
|
11
12
|
const base = useModal();
|
|
12
13
|
const { signIn } = useSIWE();
|
|
14
|
+
const launcher = useConnectorLauncher();
|
|
15
|
+
const isConnected = !!useModalState().connected;
|
|
13
16
|
|
|
14
17
|
useConnectCallback({ onConnect, onDisconnect });
|
|
15
18
|
|
|
16
19
|
return {
|
|
17
20
|
...base,
|
|
21
|
+
/**
|
|
22
|
+
* Connect one wallet straight from the caller's click, skipping the list.
|
|
23
|
+
* Call it synchronously inside the click handler. It starts wagmi's connect
|
|
24
|
+
* before it returns and before any UI change, and wagmi reaches the connector
|
|
25
|
+
* a few promise ticks later, still inside the click's task, so a phone's wallet
|
|
26
|
+
* deeplink keeps the tap's user activation. Shows the connecting screen, and
|
|
27
|
+
* the wallet list if the page stays in front for `fallbackMs` with the connect
|
|
28
|
+
* unanswered (no wallet app, or no answer after coming back from it) or the
|
|
29
|
+
* connect fails. Closing the modal or leaving the connecting screen stops that
|
|
30
|
+
* fallback. Calling it again while that connect is pending re-opens the
|
|
31
|
+
* pending request.
|
|
32
|
+
*/
|
|
33
|
+
openConnector: (id: string, options?: OpenConnectorOptions) => {
|
|
34
|
+
if (launcher) launcher.openConnector(id, options);
|
|
35
|
+
else base.openScreen(routes.CONNECTORS);
|
|
36
|
+
},
|
|
37
|
+
/** Wallet id `openConnector` is connecting, or null. */
|
|
38
|
+
pendingConnector: launcher?.pendingConnector ?? null,
|
|
18
39
|
// Disconnected routes
|
|
19
40
|
openAbout: () => base.openScreen(routes.ABOUT),
|
|
20
41
|
openOnboarding: () => base.openScreen(routes.ONBOARDING),
|
|
@@ -22,6 +43,9 @@ export const useWeb3Modal = ({ onConnect, onDisconnect }: UseModalProps = {}) =>
|
|
|
22
43
|
openProfile: () => base.openScreen(routes.PROFILE),
|
|
23
44
|
openSwitchNetworks: () => base.openScreen(routes.SWITCHNETWORKS),
|
|
24
45
|
openSIWE: (triggerSIWE?: boolean) => {
|
|
46
|
+
// A phone with a preferred connector goes straight to it; the connect lands
|
|
47
|
+
// on the sign-in screen through the connect intent.
|
|
48
|
+
if (!isConnected && launcher?.openPreferredConnector()) return;
|
|
25
49
|
base.openScreen(routes.SIGNINWITHETHEREUM);
|
|
26
50
|
if (triggerSIWE) signIn();
|
|
27
51
|
},
|
|
@@ -17,6 +17,7 @@ import { clearConnectIntent, consumeConnectIntent } from "./siwe/connectIntent";
|
|
|
17
17
|
import { SIWEContext } from "./siwe/SIWEContext";
|
|
18
18
|
import { GpgContext } from "@multiplatform.one/gpg";
|
|
19
19
|
import { useWallet } from "./wallets/useWallets";
|
|
20
|
+
import { ConnectorLauncherProvider } from "./openConnector";
|
|
20
21
|
|
|
21
22
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
23
|
// The web3 ⇄ connectkit bridge: the ONE place that knows both wagmi and the
|
|
@@ -138,7 +139,9 @@ export const Web3ModalBridge: React.FC<Web3ModalBridgeProps> = ({
|
|
|
138
139
|
return (
|
|
139
140
|
<Web3ContextProvider enabled={context.open}>
|
|
140
141
|
<Web3ScreenRegistrar />
|
|
141
|
-
<ModalStateProvider value={modalState}>
|
|
142
|
+
<ModalStateProvider value={modalState}>
|
|
143
|
+
<ConnectorLauncherProvider>{children}</ConnectorLauncherProvider>
|
|
144
|
+
</ModalStateProvider>
|
|
142
145
|
</Web3ContextProvider>
|
|
143
146
|
);
|
|
144
147
|
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { ConnectKitProvider as BaseProvider } from "@multiplatform.one/connectkit";
|
|
3
3
|
import { Web3ModalBridge } from "./web3Bridge";
|
|
4
|
+
import type { Web3ConnectKitOptions } from "./openConnector";
|
|
4
5
|
|
|
5
|
-
type Props = React.ComponentProps<typeof BaseProvider
|
|
6
|
+
type Props = Omit<React.ComponentProps<typeof BaseProvider>, "options"> & {
|
|
7
|
+
options?: Web3ConnectKitOptions;
|
|
8
|
+
};
|
|
6
9
|
|
|
7
10
|
// web3's ConnectKitProvider = connectkit's agnostic provider pre-wired with the wagmi
|
|
8
11
|
// bridge. Consumers importing ConnectKitProvider from @multiplatform.one/web3 get the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/connectkit/components/Common/ConnectorList/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/connectkit/components/Common/ConnectorList/index.tsx"],"names":[],"mappings":"AAkDA,QAAA,MAAM,aAAa,+CA8FlB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/connectkit/components/ConnectButton/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAOL,WAAW,EACX,IAAI,EACJ,KAAK,EAMN,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/connectkit/components/ConnectButton/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAOL,WAAW,EACX,IAAI,EACJ,KAAK,EAMN,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAgF7B,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;AAE1B,KAAK,0BAA0B,GAAG;IAChC,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE;QACvB,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;QAClB,KAAK,CAAC,EAAE,KAAK,GAAG;YACd,WAAW,CAAC,EAAE,OAAO,CAAC;SACvB,CAAC;QACF,WAAW,EAAE,OAAO,CAAC;QACrB,WAAW,EAAE,OAAO,CAAC;QACrB,YAAY,EAAE,OAAO,CAAC;QACtB,OAAO,CAAC,EAAE,IAAI,CAAC;QACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,KAAK,KAAK,CAAC,SAAS,CAAC;CACvB,CAAC;AA6LF,KAAK,qBAAqB,GAAG;IAE3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IAGrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,WAAW,CAAC,EAAE,WAAW,CAAC;IAG1B,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACtC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAE/B,KAAK,EACL,WAAmB,EACnB,UAAiB,EAGjB,KAAK,EACL,IAAI,EACJ,WAAW,EAGX,OAAO,GACR,EAAE,qBAAqB,kDA+GvB;yBA5He,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/connectkit/components/ConnectModal/ConnectWithInjector/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/connectkit/components/ConnectModal/ConnectWithInjector/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AA2CnD,eAAO,MAAM,MAAM;;;;;;;;CAQlB,CAAC;AA+BF,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC;IAClC,mBAAmB,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,UAAU,CAAC,EAAE,OAAO,MAAM,CAAC;CAC5B,CAkfA,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -4,6 +4,8 @@ export { default as getDefaultConfig } from "./defaultConfig";
|
|
|
4
4
|
export { default as getDefaultConnectors } from "./defaultConnectors";
|
|
5
5
|
export { wallets } from "./wallets";
|
|
6
6
|
export { useWeb3Modal as useModal } from "./useWeb3Modal";
|
|
7
|
+
export { DEFAULT_DESKTOP_OPEN_CONNECTOR_FALLBACK_MS, DEFAULT_OPEN_CONNECTOR_FALLBACK_MS, type MobileConnectOptions, type OpenConnectorOptions, type Web3ConnectKitOptions, } from "./openConnector";
|
|
8
|
+
export { CONNECT_INTENT_TTL_MS } from "./siwe/connectIntent";
|
|
7
9
|
export { SIWEProvider, useSIWE, SIWE_NONCE_QUERY_KEY, SIWE_SESSION_QUERY_KEY } from "./siwe";
|
|
8
10
|
export type { SIWESession, SIWEConfig } from "./siwe";
|
|
9
11
|
export { GpgProvider, useGpg, GpgStatusState, GPG_NONCE_QUERY_KEY, SignInWithGpgButton, } from "@multiplatform.one/gpg";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/connectkit/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,UAAU,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,YAAY,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAC;AAC7F,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAItD,OAAO,EACL,WAAW,EACX,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAInE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAKhF,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,UAAU,EACV,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EACL,sBAAsB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,eAAe,EACf,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,SAAS,GACf,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,uBAAuB,GAC7B,MAAM,kCAAkC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/connectkit/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,UAAU,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,YAAY,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,0CAA0C,EAC1C,kCAAkC,EAClC,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAC;AAC7F,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAItD,OAAO,EACL,WAAW,EACX,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAInE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAKhF,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,UAAU,EACV,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EACL,sBAAsB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,eAAe,EACf,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,SAAS,GACf,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,uBAAuB,GAC7B,MAAM,kCAAkC,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type Connector } from "wagmi";
|
|
3
|
+
import { type ConnectKitOptions } from "@multiplatform.one/connectkit";
|
|
4
|
+
import { type WalletProps } from "../wallets/useWallets";
|
|
5
|
+
import { type OpenConnectorOptions, type PendingConnect } from "./launcher";
|
|
6
|
+
export type MobileConnectOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* Connector id a phone connects straight to (e.g. `"metaMaskSDK"`): `openSIWE()`
|
|
9
|
+
* and the default ConnectKit button skip the wallet list for it. Desktop keeps
|
|
10
|
+
* the list. A phone here is what connectkit's `isMobile()` reads from the user
|
|
11
|
+
* agent, so iPadOS Safari and Android's "Desktop site", which both send a desktop
|
|
12
|
+
* one, keep the list too.
|
|
13
|
+
*/
|
|
14
|
+
preferredConnector?: string;
|
|
15
|
+
/** Passed to `openConnector` for the preferred connector. */
|
|
16
|
+
fallbackMs?: number;
|
|
17
|
+
};
|
|
18
|
+
/** ConnectKit options as web3's ConnectKitProvider takes them. */
|
|
19
|
+
export type Web3ConnectKitOptions = ConnectKitOptions & {
|
|
20
|
+
mobile?: MobileConnectOptions;
|
|
21
|
+
};
|
|
22
|
+
export type ConnectorLauncherValue = {
|
|
23
|
+
openConnector: (id: string, options?: OpenConnectorOptions) => void;
|
|
24
|
+
/**
|
|
25
|
+
* On a phone with `mobile.preferredConnector` set, open that connector and
|
|
26
|
+
* return true. Otherwise do nothing and return false.
|
|
27
|
+
*/
|
|
28
|
+
openPreferredConnector: () => boolean;
|
|
29
|
+
/** Wallet id `openConnector` is connecting, or null. */
|
|
30
|
+
pendingConnector: string | null;
|
|
31
|
+
/** The pending connect's wallet deeplink, once the connector announced it. */
|
|
32
|
+
pendingDeeplink: string | null;
|
|
33
|
+
/** The pending connect, for screens that must not start a second one. */
|
|
34
|
+
pending: PendingConnect | null;
|
|
35
|
+
};
|
|
36
|
+
/** The launcher, or null outside web3's ConnectKitProvider. */
|
|
37
|
+
export declare function useConnectorLauncher(): ConnectorLauncherValue | null;
|
|
38
|
+
export declare function getMobileOptions(options?: ConnectKitOptions): MobileConnectOptions;
|
|
39
|
+
/**
|
|
40
|
+
* Find the list wallet for a connector id. The list hides the MetaMask SDK row
|
|
41
|
+
* behind an injected MetaMask (EIP-6963 `io.metamask`), so an id that is not in
|
|
42
|
+
* the list resolves through its connector's rdns.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveWallet(wallets: readonly WalletProps[], connectors: readonly Connector[], id: string): WalletProps | undefined;
|
|
45
|
+
export declare const ConnectorLauncherProvider: React.FC<{
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
}>;
|
|
48
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/connectkit/openConnector/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AACf,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,kEAAkE;AAClE,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GAAG;IACtD,MAAM,CAAC,EAAE,oBAAoB,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACpE;;;OAGG;IACH,sBAAsB,EAAE,MAAM,OAAO,CAAC;IACtC,wDAAwD;IACxD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,8EAA8E;IAC9E,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,yEAAyE;IACzE,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;CAChC,CAAC;AAIF,+DAA+D;AAC/D,wBAAgB,oBAAoB,IAAI,sBAAsB,GAAG,IAAI,CAEpE;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,oBAAoB,CAElF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,SAAS,WAAW,EAAE,EAC/B,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,EAAE,EAAE,MAAM,GACT,WAAW,GAAG,SAAS,CAOzB;AAED,eAAO,MAAM,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAoF7E,CAAC"}
|