@gluwa/connect-kit 0.1.0-next.2 → 0.1.0-next.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @gluwa/wallet-kit
2
2
 
3
+ ## 0.1.0-next.3
4
+
5
+ ### Patch Changes
6
+
7
+ - fa6fa6f: 0.1.0-next.3
8
+
3
9
  ## 0.1.0-next.2
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ var __defProp = Object.defineProperty;
3
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
+
5
+ export {
6
+ __name
7
+ };
@@ -0,0 +1,16 @@
1
+ import { createConnector } from '@wagmi/core';
2
+ import { StorageProvider } from '@gluwa/credit-connect-sdk/storage';
3
+ import { E2EEProvider } from '@gluwa/credit-connect-sdk/e2ee';
4
+ import { HubFactoryProvider } from '@gluwa/credit-connect-sdk/hub';
5
+
6
+ type CreditConnectConnectorOptions = {
7
+ projectKey: string;
8
+ serverUrl: string;
9
+ storage: StorageProvider;
10
+ e2ee: E2EEProvider;
11
+ createHub: HubFactoryProvider['createHubFromDapp'];
12
+ onDisplayUri?: (uri: string | null) => void;
13
+ };
14
+ declare const creditConnectConnector: (options: CreditConnectConnectorOptions) => ReturnType<typeof createConnector>;
15
+
16
+ export { type CreditConnectConnectorOptions, creditConnectConnector };
@@ -0,0 +1,399 @@
1
+ import React from "react";
2
+ import {
3
+ __name
4
+ } from "./chunk-DDA6FP6U.js";
5
+
6
+ // src/creditConnectConnector.ts
7
+ import { createConnector } from "@wagmi/core";
8
+ import { getAddress } from "viem";
9
+ import { DappSessionManager } from "@gluwa/credit-connect-sdk/dapp";
10
+ var CONNECTOR_ID = "credit-connect";
11
+ var CONNECTOR_NAME = "Credit Wallet";
12
+ var CONNECTOR_TYPE = "credit-connect";
13
+ var castConnectResult = /* @__PURE__ */ __name((value) => value, "castConnectResult");
14
+ var creditConnectConnector = /* @__PURE__ */ __name((options) => {
15
+ let manager = null;
16
+ let selectedChainId = null;
17
+ let connectPromise = null;
18
+ let provider = null;
19
+ let isLocalDisconnect = false;
20
+ let emitWagmiMessage = null;
21
+ let emitWagmiDisconnect = null;
22
+ const providerListeners = /* @__PURE__ */ new Map();
23
+ const emitProviderEvent = /* @__PURE__ */ __name((event, ...args) => {
24
+ const listeners = providerListeners.get(event);
25
+ if (listeners) for (const fn of listeners) fn(...args);
26
+ }, "emitProviderEvent");
27
+ const getCurrentSession = /* @__PURE__ */ __name(() => {
28
+ if (!manager || manager.state.status !== "CONNECTED" || !manager.state.session) return null;
29
+ return manager.state.session;
30
+ }, "getCurrentSession");
31
+ const getEvmAddressInfo = /* @__PURE__ */ __name((session) => session.addressInfoList.filter((info) => info.networkType === "eip155"), "getEvmAddressInfo");
32
+ const getChecksummedAccounts = /* @__PURE__ */ __name((session) => getEvmAddressInfo(session).map((info) => getAddress(info.address)), "getChecksummedAccounts");
33
+ const resetState = /* @__PURE__ */ __name(() => {
34
+ connectPromise = null;
35
+ selectedChainId = null;
36
+ }, "resetState");
37
+ const createManagerIfNeeded = /* @__PURE__ */ __name(() => {
38
+ if (manager) return manager;
39
+ manager = new DappSessionManager({
40
+ projectKey: options.projectKey,
41
+ serverUrl: options.serverUrl,
42
+ storage: options.storage,
43
+ e2ee: options.e2ee,
44
+ createHub: options.createHub,
45
+ enableReconnect: true,
46
+ autoInit: true
47
+ });
48
+ manager.on("changeState", (state) => {
49
+ var _a;
50
+ if (state.status === "CONNECTING" && state.connectingPayload) {
51
+ (_a = options.onDisplayUri) == null ? void 0 : _a.call(options, state.connectingPayload);
52
+ emitWagmiMessage == null ? void 0 : emitWagmiMessage("display_uri", state.connectingPayload);
53
+ }
54
+ if (state.status === "DISCONNECTED" && !isLocalDisconnect) {
55
+ resetState();
56
+ emitProviderEvent("disconnect");
57
+ emitWagmiDisconnect == null ? void 0 : emitWagmiDisconnect();
58
+ }
59
+ });
60
+ return manager;
61
+ }, "createManagerIfNeeded");
62
+ const ensureManagerInitialized = /* @__PURE__ */ __name(async () => {
63
+ const m = createManagerIfNeeded();
64
+ if (m.state.status === "PENDING") {
65
+ await m.initSession();
66
+ return m;
67
+ }
68
+ if (m.state.status === "INITIALIZING") {
69
+ await new Promise((resolve) => {
70
+ const unsub = m.on("changeState", (state) => {
71
+ if (state.status !== "INITIALIZING") {
72
+ unsub();
73
+ resolve();
74
+ }
75
+ });
76
+ });
77
+ }
78
+ return m;
79
+ }, "ensureManagerInitialized");
80
+ return createConnector((config) => {
81
+ emitWagmiMessage = /* @__PURE__ */ __name((type, data) => {
82
+ config.emitter.emit("message", {
83
+ type,
84
+ data
85
+ });
86
+ }, "emitWagmiMessage");
87
+ emitWagmiDisconnect = /* @__PURE__ */ __name(() => {
88
+ config.emitter.emit("disconnect");
89
+ }, "emitWagmiDisconnect");
90
+ return {
91
+ id: CONNECTOR_ID,
92
+ name: CONNECTOR_NAME,
93
+ type: CONNECTOR_TYPE,
94
+ async setup() {
95
+ await ensureManagerInitialized();
96
+ },
97
+ async connect(parameters) {
98
+ var _a;
99
+ try {
100
+ const m = createManagerIfNeeded();
101
+ if (m.state.status === "INITIALIZING") {
102
+ await new Promise((resolve) => {
103
+ const unsub = m.on("changeState", (state) => {
104
+ if (state.status !== "INITIALIZING") {
105
+ unsub();
106
+ resolve();
107
+ }
108
+ });
109
+ });
110
+ }
111
+ if (parameters == null ? void 0 : parameters.isReconnecting) {
112
+ const session2 = getCurrentSession();
113
+ if (!session2) throw new Error("No active session to reconnect");
114
+ const accounts2 = getChecksummedAccounts(session2);
115
+ if (accounts2.length === 0) throw new Error("No EVM address found");
116
+ const chainId2 = Number.parseInt(getEvmAddressInfo(session2)[0].networkIdentifier, 10);
117
+ if (!Number.isFinite(chainId2)) throw new Error(`Invalid chainId: ${chainId2}`);
118
+ selectedChainId = chainId2;
119
+ if ((parameters == null ? void 0 : parameters.withCapabilities) === true) {
120
+ return castConnectResult({
121
+ accounts: accounts2.map((address) => ({
122
+ address,
123
+ capabilities: {}
124
+ })),
125
+ chainId: chainId2
126
+ });
127
+ }
128
+ return castConnectResult({
129
+ accounts: accounts2,
130
+ chainId: chainId2
131
+ });
132
+ }
133
+ if (m.state.status === "CONNECTING" && m.state.connectingPayload) {
134
+ (_a = options.onDisplayUri) == null ? void 0 : _a.call(options, m.state.connectingPayload);
135
+ if (!connectPromise) {
136
+ connectPromise = new Promise((resolve) => {
137
+ const unsub = m.on("changeState", (state) => {
138
+ if (state.status === "CONNECTED") {
139
+ unsub();
140
+ resolve(true);
141
+ } else if (state.status === "DISCONNECTED") {
142
+ unsub();
143
+ resolve(false);
144
+ }
145
+ });
146
+ });
147
+ }
148
+ }
149
+ if (m.state.status !== "CONNECTED") {
150
+ if (!connectPromise) {
151
+ if (m.state.status !== "DISCONNECTED") {
152
+ throw new Error(`Cannot connect from ${m.state.status} state`);
153
+ }
154
+ connectPromise = m.connectNewSession();
155
+ }
156
+ const connected = await connectPromise;
157
+ connectPromise = null;
158
+ if (!connected) throw new Error("Credit Connect session failed");
159
+ }
160
+ const session = getCurrentSession();
161
+ if (!session) throw new Error("Credit Connect session failed");
162
+ const accounts = getChecksummedAccounts(session);
163
+ if (accounts.length === 0) throw new Error("No EVM address found");
164
+ const chainId = Number.parseInt(getEvmAddressInfo(session)[0].networkIdentifier, 10);
165
+ if (!Number.isFinite(chainId)) throw new Error(`Invalid chainId: ${chainId}`);
166
+ selectedChainId = chainId;
167
+ if ((parameters == null ? void 0 : parameters.withCapabilities) === true) {
168
+ return castConnectResult({
169
+ accounts: accounts.map((address) => ({
170
+ address,
171
+ capabilities: {}
172
+ })),
173
+ chainId
174
+ });
175
+ }
176
+ return castConnectResult({
177
+ accounts,
178
+ chainId
179
+ });
180
+ } catch (error) {
181
+ resetState();
182
+ throw error;
183
+ }
184
+ },
185
+ async switchChain({ chainId }) {
186
+ const session = getCurrentSession();
187
+ if (!session) throw new Error("No active session");
188
+ const supported = getEvmAddressInfo(session).some((info) => Number.parseInt(info.networkIdentifier, 10) === chainId);
189
+ if (!supported) {
190
+ const err = new Error(`Unsupported chain: ${chainId}`);
191
+ err.code = 4902;
192
+ throw err;
193
+ }
194
+ selectedChainId = chainId;
195
+ config.emitter.emit("change", {
196
+ chainId
197
+ });
198
+ const chain = config.chains.find((c) => c.id === chainId);
199
+ if (!chain) throw new Error(`Chain ${chainId} not in config`);
200
+ return chain;
201
+ },
202
+ async isAuthorized() {
203
+ await ensureManagerInitialized();
204
+ const session = getCurrentSession();
205
+ if (!session) return false;
206
+ return session.addressInfoList.some((info) => info.networkType === "eip155");
207
+ },
208
+ async disconnect() {
209
+ isLocalDisconnect = true;
210
+ try {
211
+ if ((manager == null ? void 0 : manager.state.status) === "CONNECTED") {
212
+ await manager.disconnectSession();
213
+ }
214
+ } finally {
215
+ isLocalDisconnect = false;
216
+ }
217
+ provider = null;
218
+ resetState();
219
+ config.emitter.emit("disconnect");
220
+ },
221
+ async getAccounts() {
222
+ await ensureManagerInitialized();
223
+ const session = getCurrentSession();
224
+ if (!session) return [];
225
+ return getChecksummedAccounts(session);
226
+ },
227
+ async getChainId() {
228
+ await ensureManagerInitialized();
229
+ const session = getCurrentSession();
230
+ if (!session) throw new Error("No active session");
231
+ if (selectedChainId !== null) return selectedChainId;
232
+ const evmAddressInfo = getEvmAddressInfo(session);
233
+ if (evmAddressInfo.length === 0) throw new Error("No EVM address found");
234
+ const chainId = Number.parseInt(evmAddressInfo[0].networkIdentifier, 10);
235
+ if (!Number.isFinite(chainId)) throw new Error(`Invalid chainId: ${chainId}`);
236
+ selectedChainId = chainId;
237
+ return chainId;
238
+ },
239
+ async getProvider() {
240
+ if (provider) return provider;
241
+ await ensureManagerInitialized();
242
+ const createdProvider = {
243
+ request: /* @__PURE__ */ __name(async (args) => {
244
+ const { method, params: rawParams } = args;
245
+ const params = Array.isArray(rawParams) ? [
246
+ ...rawParams
247
+ ] : rawParams === void 0 ? [] : [
248
+ rawParams
249
+ ];
250
+ const session = getCurrentSession();
251
+ const getSelectedAddressInfo = /* @__PURE__ */ __name((address) => {
252
+ if (!session) throw new Error("No active session");
253
+ const evmInfo = getEvmAddressInfo(session);
254
+ if (evmInfo.length === 0) throw new Error("No EVM address found");
255
+ if (!address) return evmInfo[0];
256
+ const found = evmInfo.find((info) => info.address.toLowerCase() === address.toLowerCase());
257
+ if (!found) throw new Error(`Address not in session: ${address}`);
258
+ return found;
259
+ }, "getSelectedAddressInfo");
260
+ if (method === "eth_accounts") {
261
+ if (!session) return [];
262
+ return getChecksummedAccounts(session);
263
+ }
264
+ if (method === "eth_chainId") {
265
+ if (!session) throw new Error("No active session");
266
+ if (selectedChainId !== null) return `0x${selectedChainId.toString(16)}`;
267
+ const evmInfo = getEvmAddressInfo(session);
268
+ if (evmInfo.length === 0) throw new Error("No EVM address found");
269
+ const chainId = Number.parseInt(evmInfo[0].networkIdentifier, 10);
270
+ if (!Number.isFinite(chainId)) throw new Error(`Invalid chainId: ${chainId}`);
271
+ selectedChainId = chainId;
272
+ return `0x${chainId.toString(16)}`;
273
+ }
274
+ if (method === "wallet_switchEthereumChain") {
275
+ const [{ chainId: rawChainId }] = params != null ? params : [];
276
+ if (!rawChainId) throw new Error("wallet_switchEthereumChain missing chainId param");
277
+ const chainId = Number.parseInt(rawChainId, 16);
278
+ if (!Number.isFinite(chainId)) throw new Error(`Invalid chainId: ${rawChainId}`);
279
+ if (!session) throw new Error("No active session");
280
+ const supported = getEvmAddressInfo(session).some((info) => Number.parseInt(info.networkIdentifier, 10) === chainId);
281
+ if (!supported) {
282
+ const err = new Error(`Unsupported chain: ${chainId}`);
283
+ err.code = 4902;
284
+ throw err;
285
+ }
286
+ selectedChainId = chainId;
287
+ config.emitter.emit("change", {
288
+ chainId
289
+ });
290
+ return null;
291
+ }
292
+ if (method === "personal_sign") {
293
+ const [messageParam, addressParam] = params != null ? params : [];
294
+ const message = typeof messageParam === "string" ? messageParam : String(messageParam != null ? messageParam : "");
295
+ const address = typeof addressParam === "string" ? addressParam : void 0;
296
+ const addressInfo = getSelectedAddressInfo(address);
297
+ const response = await (session == null ? void 0 : session.jsonRpc.request("signMessage", {
298
+ message,
299
+ addressInfo
300
+ }));
301
+ return response == null ? void 0 : response.signature;
302
+ }
303
+ if (method === "eth_sign") {
304
+ const [addressParam, messageParam] = params != null ? params : [];
305
+ const address = typeof addressParam === "string" ? addressParam : void 0;
306
+ const message = typeof messageParam === "string" ? messageParam : String(messageParam != null ? messageParam : "");
307
+ const addressInfo = getSelectedAddressInfo(address);
308
+ const response = await (session == null ? void 0 : session.jsonRpc.request("signMessage", {
309
+ message,
310
+ addressInfo
311
+ }));
312
+ return response == null ? void 0 : response.signature;
313
+ }
314
+ if (method === "eth_signTypedData" || method === "eth_signTypedData_v4") {
315
+ const [addressParam, typedDataParam] = params != null ? params : [];
316
+ const address = typeof addressParam === "string" ? addressParam : void 0;
317
+ const typedData = typeof typedDataParam === "string" ? typedDataParam : JSON.stringify(typedDataParam != null ? typedDataParam : "");
318
+ const addressInfo = getSelectedAddressInfo(address);
319
+ const response = await (session == null ? void 0 : session.jsonRpc.request("signTypedData", {
320
+ typedData,
321
+ addressInfo
322
+ }));
323
+ return response == null ? void 0 : response.signature;
324
+ }
325
+ if (method === "eth_sendTransaction") {
326
+ const [txParams] = params != null ? params : [];
327
+ const addressInfo = getSelectedAddressInfo(txParams == null ? void 0 : txParams.from);
328
+ const response = await (session == null ? void 0 : session.jsonRpc.request("sendTransaction", {
329
+ addressInfo,
330
+ to: txParams == null ? void 0 : txParams.to,
331
+ value: txParams == null ? void 0 : txParams.value,
332
+ data: txParams == null ? void 0 : txParams.data,
333
+ gas: txParams == null ? void 0 : txParams.gas,
334
+ gasPrice: txParams == null ? void 0 : txParams.gasPrice,
335
+ maxFeePerGas: txParams == null ? void 0 : txParams.maxFeePerGas,
336
+ maxPriorityFeePerGas: txParams == null ? void 0 : txParams.maxPriorityFeePerGas,
337
+ nonce: txParams == null ? void 0 : txParams.nonce,
338
+ chainId: txParams == null ? void 0 : txParams.chainId
339
+ }));
340
+ return response == null ? void 0 : response.txHash;
341
+ }
342
+ if (method === "credit_connect_send_message") {
343
+ if (!session) throw new Error("No active session");
344
+ const [messageParam] = params != null ? params : [];
345
+ const message = typeof messageParam === "string" ? messageParam : JSON.stringify(messageParam != null ? messageParam : "");
346
+ await session.msg.sendMessage(message);
347
+ return true;
348
+ }
349
+ if (method === "credit_connect_jsonrpc_ping") {
350
+ if (!session) throw new Error("No active session");
351
+ return await session.jsonRpc.request("pingPong", {});
352
+ }
353
+ throw new Error(`Unsupported provider method: ${method}`);
354
+ }, "request"),
355
+ on: /* @__PURE__ */ __name((event, listener) => {
356
+ let listeners = providerListeners.get(event);
357
+ if (!listeners) {
358
+ listeners = /* @__PURE__ */ new Set();
359
+ providerListeners.set(event, listeners);
360
+ }
361
+ listeners.add(listener);
362
+ return createdProvider;
363
+ }, "on"),
364
+ removeListener: /* @__PURE__ */ __name((event, listener) => {
365
+ var _a;
366
+ (_a = providerListeners.get(event)) == null ? void 0 : _a.delete(listener);
367
+ return createdProvider;
368
+ }, "removeListener")
369
+ };
370
+ provider = createdProvider;
371
+ return provider;
372
+ },
373
+ onAccountsChanged(accounts) {
374
+ if (!accounts || accounts.length === 0) {
375
+ config.emitter.emit("disconnect");
376
+ return;
377
+ }
378
+ config.emitter.emit("change", {
379
+ accounts: accounts.map(getAddress)
380
+ });
381
+ },
382
+ onChainChanged(chainId) {
383
+ const normalized = typeof chainId === "string" ? Number.parseInt(chainId, 16) : Number(chainId);
384
+ if (!Number.isFinite(normalized)) return;
385
+ selectedChainId = normalized;
386
+ config.emitter.emit("change", {
387
+ chainId: normalized
388
+ });
389
+ },
390
+ onDisconnect() {
391
+ resetState();
392
+ config.emitter.emit("disconnect");
393
+ }
394
+ };
395
+ });
396
+ }, "creditConnectConnector");
397
+ export {
398
+ creditConnectConnector
399
+ };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,5 @@
1
1
  import { ReactNode, FC } from 'react';
2
- import { createConnector } from '@wagmi/core';
3
- import { StorageProvider } from '@gluwa/credit-connect-sdk/storage';
4
- import { E2EEProvider } from '@gluwa/credit-connect-sdk/e2ee';
5
- import { HubFactoryProvider } from '@gluwa/credit-connect-sdk/hub';
2
+ import { Config } from 'wagmi';
6
3
 
7
4
  type ConnectorId = 'CREDIT_WALLET' | 'CREDIT_CONNECT' | 'METAMASK' | 'WALLET_CONNECT';
8
5
  type CreditWalletStrategy = 'walletConnect' | 'creditConnect';
@@ -69,6 +66,16 @@ interface ConnectKitProviderProps {
69
66
  * 미제공 시 기본 동작은 selector로 복귀.
70
67
  */
71
68
  renderConnectError?: (ctx: ConnectErrorContext) => ReactNode;
69
+ /**
70
+ * 기존 프로젝트 통합용. wagmi config를 넘기면 ConnectKitProvider 내부에서
71
+ * WagmiProvider를 직접 세운다.
72
+ *
73
+ * - 기존 프로젝트: 앱에 WagmiProvider가 없으므로 wagmiConfig를 넘긴다.
74
+ * ConnectKitProvider가 같은 config 인스턴스로 WagmiProvider를 셀프 마운트하므로
75
+ * 기존 wagmi 상태 store와 단일 config를 공유한다.
76
+ * - 신규 프로젝트: 앱이 이미 WagmiProvider를 감싸므로 이 prop은 불필요하다.
77
+ */
78
+ wagmiConfig?: Config;
72
79
  }
73
80
  interface ConnectKitContextValue {
74
81
  isOpen: boolean;
@@ -82,14 +89,4 @@ interface ConnectKitContextValue {
82
89
  declare const ConnectKitProvider: FC<ConnectKitProviderProps>;
83
90
  declare const useConnectKit: () => ConnectKitContextValue;
84
91
 
85
- type CreditConnectConnectorOptions = {
86
- projectKey: string;
87
- serverUrl: string;
88
- storage: StorageProvider;
89
- e2ee: E2EEProvider;
90
- createHub: HubFactoryProvider['createHubFromDapp'];
91
- onDisplayUri?: (uri: string | null) => void;
92
- };
93
- declare const creditConnectConnector: (options: CreditConnectConnectorOptions) => ReturnType<typeof createConnector>;
94
-
95
- export { type ConnectErrorContext, type ConnectErrorReason, type ConnectKitContextValue, ConnectKitProvider, type ConnectKitProviderProps, ConnectModal, type ConnectModalProps, type ConnectResult, type ConnectorId, type Connectors, type CreditConnectConnectorOptions, type CreditWalletStrategy, type WCSubView, type WCWallet, creditConnectConnector, useConnectKit };
92
+ export { type ConnectErrorContext, type ConnectErrorReason, type ConnectKitContextValue, ConnectKitProvider, type ConnectKitProviderProps, ConnectModal, type ConnectModalProps, type ConnectResult, type ConnectorId, type Connectors, type CreditWalletStrategy, type WCSubView, type WCWallet, useConnectKit };