@gluwa/connect-kit 0.1.0-next.3 → 0.2.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/assets/creditwallet.png +0 -0
  3. package/assets/fonts/Inter-Medium.ttf +0 -0
  4. package/assets/fonts/Inter-Medium.woff2 +0 -0
  5. package/assets/fonts/Inter-Regular.ttf +0 -0
  6. package/assets/fonts/Inter-Regular.woff2 +0 -0
  7. package/assets/fonts/Inter-SemiBold.ttf +0 -0
  8. package/assets/fonts/Inter-SemiBold.woff2 +0 -0
  9. package/assets/graphic.png +0 -0
  10. package/assets/metamask.png +0 -0
  11. package/assets/wc-logo.svg +3 -0
  12. package/assets/wc-search.png +0 -0
  13. package/dist/chunk-EDNRW47A.js +401 -0
  14. package/dist/credit-connect.js +2 -394
  15. package/dist/index.css +2074 -0
  16. package/dist/index.d.ts +53 -33
  17. package/dist/index.js +1404 -1504
  18. package/dist/package.json +16 -10
  19. package/package.json +14 -11
  20. package/src/ConnectKitProvider.tsx +126 -75
  21. package/src/api/account.ts +21 -0
  22. package/src/api/balance.ts +10 -0
  23. package/src/api/chain.ts +17 -0
  24. package/src/api/contract.ts +33 -0
  25. package/src/api/transaction.ts +12 -0
  26. package/src/assets.d.ts +5 -0
  27. package/src/components/actionItem/index.tsx +50 -0
  28. package/src/components/actionItem/style.scss +47 -0
  29. package/src/components/copyLink/index.tsx +16 -0
  30. package/src/components/copyLink/style.scss +16 -0
  31. package/src/components/qrArea/index.tsx +70 -0
  32. package/src/components/qrArea/style.scss +130 -0
  33. package/src/components/searchBar/asset/Search.tsx +20 -0
  34. package/src/components/searchBar/asset/XMarkCircle.tsx +24 -0
  35. package/src/components/searchBar/index.tsx +44 -0
  36. package/src/components/searchBar/style.scss +58 -0
  37. package/src/components/snackbar/index.tsx +25 -0
  38. package/src/components/snackbar/style.scss +51 -0
  39. package/src/components/toggle/index.tsx +27 -0
  40. package/src/components/toggle/style.scss +53 -0
  41. package/src/components/walletGrid/index.tsx +64 -0
  42. package/src/components/walletGrid/style.scss +108 -0
  43. package/src/components/walletItem/index.tsx +49 -0
  44. package/src/components/walletItem/style.scss +70 -0
  45. package/src/connector-meta.ts +12 -7
  46. package/src/core/config.ts +102 -0
  47. package/src/creditConnectConnector.ts +192 -184
  48. package/src/events/account.ts +49 -0
  49. package/src/hooks/useWCState.ts +45 -13
  50. package/src/hooks/useWagmiConnect.ts +13 -9
  51. package/src/index.ts +35 -2
  52. package/src/layout/allWallets/index.tsx +52 -0
  53. package/src/layout/allWallets/style.scss +62 -0
  54. package/src/layout/connectDialog/asset/backIcon.tsx +24 -0
  55. package/src/layout/connectDialog/asset/checkIcon.tsx +28 -0
  56. package/src/layout/connectDialog/asset/closeIcon.tsx +21 -0
  57. package/src/layout/connectDialog/asset/copyIcon.tsx +28 -0
  58. package/src/layout/connectDialog/asset/linkIcon.tsx +24 -0
  59. package/src/layout/connectDialog/asset/spinner.tsx +21 -0
  60. package/src/layout/connectDialog/idle/index.tsx +32 -0
  61. package/src/layout/connectDialog/idle/style.scss +61 -0
  62. package/src/layout/connectDialog/index.tsx +286 -0
  63. package/src/layout/connectDialog/loading/index.tsx +13 -0
  64. package/src/layout/connectDialog/loading/style.scss +19 -0
  65. package/src/layout/connectDialog/metaMask/index.tsx +61 -0
  66. package/src/layout/connectDialog/metaMask/style.scss +65 -0
  67. package/src/layout/connectDialog/qr/index.tsx +33 -0
  68. package/src/layout/connectDialog/style.scss +95 -0
  69. package/src/layout/connectDialog/timeout/index.tsx +31 -0
  70. package/src/layout/connectDialog/timeout/style.scss +64 -0
  71. package/src/layout/connectDialog/walletConnect/index.tsx +45 -0
  72. package/src/layout/connectDialog/walletConnect/style.scss +48 -0
  73. package/src/layout/connectDialog/walletQR/index.tsx +37 -0
  74. package/src/layout/detailPanel/index.tsx +147 -0
  75. package/src/layout/detailPanel/style.scss +64 -0
  76. package/src/layout/selectorPanel/index.tsx +100 -0
  77. package/src/layout/selectorPanel/style.scss +113 -0
  78. package/src/style/color.scss +417 -0
  79. package/src/style/font.scss +28 -0
  80. package/src/style/index.scss +5 -0
  81. package/src/style/mixin.scss +217 -0
  82. package/src/style/reset.scss +110 -0
  83. package/src/style/variables.scss +13 -0
  84. package/src/types.ts +19 -7
  85. package/src/utils/platform.ts +7 -4
  86. package/tsup.config.ts +32 -2
  87. package/dist/chunk-DDA6FP6U.js +0 -7
  88. package/src/ConnectModal.scss +0 -665
  89. package/src/ConnectModal.tsx +0 -559
  90. package/src/components/QRFrame.tsx +0 -43
  91. package/src/views/CreditWalletView.tsx +0 -59
  92. package/src/views/IdleView.tsx +0 -10
  93. package/src/views/MetaMaskView.tsx +0 -64
  94. package/src/views/SwitchChainView.tsx +0 -67
  95. package/src/views/WalletConnectView.tsx +0 -206
package/dist/package.json CHANGED
@@ -1,14 +1,17 @@
1
1
  {
2
2
  "name": "@gluwa/connect-kit",
3
- "version": "0.1.0-next.3",
3
+ "version": "0.2.0-next.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
7
+ "types": "./src/index.ts",
7
8
  "default": "./src/index.ts"
8
9
  },
9
10
  "./credit-connect": {
11
+ "types": "./src/credit-connect.ts",
10
12
  "default": "./src/credit-connect.ts"
11
13
  },
14
+ "./index.css": "./dist/index.css",
12
15
  "./package.json": "./package.json"
13
16
  },
14
17
  "publishConfig": {
@@ -27,7 +30,10 @@
27
30
  "./index.css": "./dist/index.css"
28
31
  }
29
32
  },
30
- "sideEffects": true,
33
+ "sideEffects": [
34
+ "**/*.scss",
35
+ "**/*.css"
36
+ ],
31
37
  "scripts": {
32
38
  "prepack": "pnpm build && cp package.json dist/ && cp README.md dist/",
33
39
  "build": "tsup",
@@ -38,7 +44,13 @@
38
44
  "author": "",
39
45
  "license": "ISC",
40
46
  "dependencies": {
41
- "qrcode.react": "^3.2.0"
47
+ "qrcode.react": "^4.2.0",
48
+ "wagmi": "^2.15.6",
49
+ "@wagmi/core": "^2.16.7",
50
+ "@gluwa/credit-connect-sdk": "workspace:*",
51
+ "@gluwa/credit-connect-storage-local": "workspace:*",
52
+ "@gluwa/credit-connect-e2ee-tweetnacl": "workspace:*",
53
+ "@gluwa/credit-connect-hub-node-ws": "workspace:*"
42
54
  },
43
55
  "devDependencies": {
44
56
  "@gluwa/credit-connect-sdk": "workspace:*",
@@ -55,17 +67,11 @@
55
67
  "wagmi": "^2.15.6"
56
68
  },
57
69
  "peerDependencies": {
58
- "@gluwa/credit-connect-sdk": "workspace:*",
59
70
  "@tanstack/react-query": ">=5.0.0",
60
- "@wagmi/core": ">=2.0.0",
61
71
  "react": "^18.0.0 || ^19.0.0",
62
- "viem": ">=2.0.0",
63
- "wagmi": ">=2.0.0"
72
+ "viem": ">=2.0.0"
64
73
  },
65
74
  "peerDependenciesMeta": {
66
- "@gluwa/credit-connect-sdk": {
67
- "optional": true
68
- },
69
75
  "@tanstack/react-query": {
70
76
  "optional": true
71
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gluwa/connect-kit",
3
- "version": "0.1.0-next.3",
3
+ "version": "0.2.0-next.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -16,11 +16,20 @@
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
19
- "sideEffects": true,
19
+ "sideEffects": [
20
+ "**/*.scss",
21
+ "**/*.css"
22
+ ],
20
23
  "author": "",
21
24
  "license": "ISC",
22
25
  "dependencies": {
23
- "qrcode.react": "^3.2.0"
26
+ "qrcode.react": "^4.2.0",
27
+ "wagmi": "^2.15.6",
28
+ "@wagmi/core": "^2.16.7",
29
+ "@gluwa/credit-connect-sdk": "0.2.0-next.3",
30
+ "@gluwa/credit-connect-storage-local": "0.2.0-next.3",
31
+ "@gluwa/credit-connect-e2ee-tweetnacl": "0.2.0-next.3",
32
+ "@gluwa/credit-connect-hub-node-ws": "0.1.0-next.3"
24
33
  },
25
34
  "devDependencies": {
26
35
  "@tanstack/react-query": "^5.62.0",
@@ -34,20 +43,14 @@
34
43
  "typescript-eslint": "^8.18.2",
35
44
  "viem": "^2.31.7",
36
45
  "wagmi": "^2.15.6",
37
- "@gluwa/credit-connect-sdk": "0.2.0-next.1"
46
+ "@gluwa/credit-connect-sdk": "0.2.0-next.3"
38
47
  },
39
48
  "peerDependencies": {
40
49
  "@tanstack/react-query": ">=5.0.0",
41
- "@wagmi/core": ">=2.0.0",
42
50
  "react": "^18.0.0 || ^19.0.0",
43
- "viem": ">=2.0.0",
44
- "wagmi": ">=2.0.0",
45
- "@gluwa/credit-connect-sdk": "0.2.0-next.1"
51
+ "viem": ">=2.0.0"
46
52
  },
47
53
  "peerDependenciesMeta": {
48
- "@gluwa/credit-connect-sdk": {
49
- "optional": true
50
- },
51
54
  "@tanstack/react-query": {
52
55
  "optional": true
53
56
  }
@@ -9,53 +9,45 @@ import {
9
9
  type FC,
10
10
  type ReactNode,
11
11
  } from 'react';
12
- import { WagmiProvider, useAccount, useDisconnect } from 'wagmi';
13
- import type { Config } from 'wagmi';
12
+ import { WagmiProvider, useAccount, useConfig, useDisconnect, useSwitchChain } from 'wagmi';
13
+ import { getAccount } from '@wagmi/core';
14
14
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
15
- import { ConnectModal } from './ConnectModal';
16
- import type { ConnectErrorContext, ConnectResult, ConnectorId, Connectors } from './types';
15
+ // import { ConnectModal } from './ConnectModal';
16
+ import { ConnectDialog } from './layout/connectDialog';
17
+ import { getConfig, getKitConfig, initConfig } from './core/config';
18
+ import { resolveConnectorId } from './connector-meta';
19
+ import type {
20
+ ConnectErrorContext,
21
+ ConnectKitConfig,
22
+ ConnectKitTheme,
23
+ ConnectResult,
24
+ ConnectorId,
25
+ ConnectorKey,
26
+ Connectors,
27
+ } from './types';
17
28
 
18
- // wagmiConfig prop으로 기존 프로젝트 통합 시 내부에서 사용하는 QueryClient.
19
- // 모듈 레벨에 한 번만 생성 — 연결 플로우용으로만 쓰이므로 공유해도 무방.
20
29
  const internalQueryClient = new QueryClient();
21
30
 
22
31
  export interface ConnectKitProviderProps {
23
32
  children: ReactNode;
33
+ kitConfig?: ConnectKitConfig;
24
34
  connectors: Connectors;
25
- wcProjectId?: string;
26
- /**
27
- * 연결돼 있는 동안 강제할 체인 ID. 다른 체인에 연결돼 있으면
28
- * 자동으로 스위치 모달이 떠서 사용자에게 전환 또는 disconnect를 요구.
29
- */
30
35
  requiredChainId?: number;
31
- /**
32
- * 연결이 정상적으로 끝나고(체인 검증까지 통과) "사용 가능한 상태"가 됐을 때 한 번 호출.
33
- * 재연결(reconnect)에서는 호출되지 않음 — 그쪽은 dApp의 watchAccount 책임.
34
- */
36
+ theme: ConnectKitTheme;
35
37
  onConnect?: (result: ConnectResult) => void;
36
38
  onLog?: (message: string, error?: Error) => void;
37
- /**
38
- * 연결 실패(거절/미설치/기타) 시 모달 안에 표시할 fallback UI를 dApp이 직접 그리고 싶을 때.
39
- * 미제공 시 기본 동작은 selector로 복귀.
40
- */
41
39
  renderConnectError?: (ctx: ConnectErrorContext) => ReactNode;
42
- /**
43
- * 기존 프로젝트 통합용. wagmi config를 넘기면 ConnectKitProvider 내부에서
44
- * WagmiProvider를 직접 세운다.
45
- *
46
- * - 기존 프로젝트: 앱에 WagmiProvider가 없으므로 wagmiConfig를 넘긴다.
47
- * ConnectKitProvider가 같은 config 인스턴스로 WagmiProvider를 셀프 마운트하므로
48
- * 기존 wagmi 상태 store와 단일 config를 공유한다.
49
- * - 신규 프로젝트: 앱이 이미 WagmiProvider를 감싸므로 이 prop은 불필요하다.
50
- */
51
- wagmiConfig?: Config;
52
40
  }
53
-
54
41
  export interface ConnectKitContextValue {
55
42
  isOpen: boolean;
56
43
  open: () => void;
57
44
  close: () => void;
58
45
  isConnected: boolean;
46
+ needsChainSwitch: boolean;
47
+ requiredChainId: number | undefined;
48
+ currentChainId: number | undefined;
49
+ isSwitchingChain: boolean;
50
+ switchToRequiredChain: () => Promise<void>;
59
51
  address: `0x${string}` | undefined;
60
52
  connectorId: ConnectorId | null;
61
53
  disconnect: () => Promise<void>;
@@ -63,58 +55,80 @@ export interface ConnectKitContextValue {
63
55
 
64
56
  const ConnectKitContext = createContext<ConnectKitContextValue | null>(null);
65
57
 
66
- const resolveConnectorId = (wagmiConnectorId: string | undefined): ConnectorId | null => {
67
- if (!wagmiConnectorId) return null;
68
- if (wagmiConnectorId === 'credit-connect') return 'CREDIT_CONNECT';
69
- if (wagmiConnectorId === 'walletConnect') return 'WALLET_CONNECT';
70
- const lower = wagmiConnectorId.toLowerCase();
71
- if (lower.includes('metamask') || wagmiConnectorId === 'injected') return 'METAMASK';
72
- if (lower.includes('walletconnect')) return 'WALLET_CONNECT';
73
- return null;
58
+ // 외부 API Connectors (ConnectorKey 배열) 내부 ConnectorId[] 매핑.
59
+ // 입력 순서 그대로 selector 표시 순서.
60
+ const CONNECTOR_KEY_TO_ID: Record<ConnectorKey, ConnectorId> = {
61
+ creditWallet: 'CREDIT_CONNECT',
62
+ metamask: 'METAMASK',
63
+ walletConnect: 'WALLET_CONNECT',
64
+ };
65
+ const resolveConnectorsFromConfig = (connectorsConfig?: Connectors): ConnectorId[] => {
66
+ if (!connectorsConfig) return [];
67
+ return connectorsConfig.map((key) => CONNECTOR_KEY_TO_ID[key]);
74
68
  };
75
69
 
76
70
  export const ConnectKitProvider: FC<ConnectKitProviderProps> = (props) => {
77
- if (props.wagmiConfig) {
78
- return (
79
- <WagmiProvider config={props.wagmiConfig}>
80
- <QueryClientProvider client={internalQueryClient}>
81
- <ConnectKitProviderInner {...props} />
82
- </QueryClientProvider>
83
- </WagmiProvider>
84
- );
85
- }
86
- return <ConnectKitProviderInner {...props} />;
71
+ const wagmiConfig = useMemo(
72
+ () => (props.kitConfig ? initConfig(props.kitConfig) : getConfig()),
73
+ [props.kitConfig],
74
+ );
75
+
76
+ const resolvedKitConfig = props.kitConfig ?? getKitConfig();
77
+
78
+ return (
79
+ <WagmiProvider config={wagmiConfig} reconnectOnMount={false}>
80
+ <QueryClientProvider client={internalQueryClient}>
81
+ <ConnectKitProviderInner {...props} kitConfig={resolvedKitConfig} />
82
+ </QueryClientProvider>
83
+ </WagmiProvider>
84
+ );
85
+ };
86
+
87
+ type ConnectKitProviderInnerProps = Omit<ConnectKitProviderProps, 'kitConfig'> & {
88
+ kitConfig: ConnectKitConfig;
87
89
  };
88
90
 
89
- const ConnectKitProviderInner: FC<ConnectKitProviderProps> = ({
91
+ const ConnectKitProviderInner: FC<ConnectKitProviderInnerProps> = ({
90
92
  children,
91
93
  connectors,
92
- wcProjectId,
94
+ kitConfig,
93
95
  requiredChainId,
96
+ theme,
94
97
  onConnect,
95
98
  onLog,
96
- renderConnectError,
97
99
  }) => {
100
+ // NOTE: renderConnectError 는 ConnectDialog 가 아직 error UI customization 을 받지 않으므로
101
+ // destructure 에서 제외. 추후 ConnectDialog 의 timeout/error content 에 wire 필요 시 복원.
98
102
  const [isOpen, setIsOpen] = useState(false);
99
103
  const [pendingResult, setPendingResult] = useState<ConnectResult | null>(null);
100
104
 
101
105
  const account = useAccount();
106
+ const wagmiConfig = useConfig();
102
107
  const { disconnectAsync } = useDisconnect();
108
+ const { switchChainAsync } = useSwitchChain();
103
109
 
104
- // dApp의 onConnect는 ref로 잡아 effect 재실행 노이즈 차단
105
110
  const onConnectRef = useRef(onConnect);
106
111
  useEffect(() => {
107
112
  onConnectRef.current = onConnect;
108
113
  }, [onConnect]);
109
114
 
110
- // chain mismatch invariant: 연결돼 있지만 요구 체인이 아니면 modal force-open
111
- const chainMismatch =
115
+ const isMountedRef = useRef(true);
116
+ useEffect(() => {
117
+ isMountedRef.current = true;
118
+ return () => {
119
+ isMountedRef.current = false;
120
+ };
121
+ }, []);
122
+
123
+ const needsChainSwitch =
112
124
  requiredChainId != null &&
113
125
  account.status === 'connected' &&
114
126
  account.chainId != null &&
115
127
  account.chainId !== requiredChainId;
116
128
 
117
- const effectiveOpen = isOpen || chainMismatch;
129
+ const [isSwitchingChain, setIsSwitchingChain] = useState(false);
130
+
131
+ const effectiveOpen = isOpen;
118
132
 
119
133
  const open = useCallback((): void => {
120
134
  setIsOpen(true);
@@ -122,34 +136,62 @@ const ConnectKitProviderInner: FC<ConnectKitProviderProps> = ({
122
136
 
123
137
  const close = useCallback((): void => {
124
138
  setIsOpen(false);
125
- }, []);
139
+ const status = getAccount(wagmiConfig).status;
140
+ if (status === 'connecting' || status === 'reconnecting') {
141
+ disconnectAsync().catch(() => undefined);
142
+ }
143
+ }, [wagmiConfig, disconnectAsync]);
126
144
 
127
145
  const disconnect = useCallback(async (): Promise<void> => {
128
146
  await disconnectAsync();
129
147
  }, [disconnectAsync]);
130
148
 
131
- // ConnectModal Provider: 연결 결과를 일단 보류했다가
132
- // chain 검증까지 통과한 후에만 dApp으로 forward
133
- const handleModalConnect = useCallback((result: ConnectResult): void => {
149
+ const switchToRequiredChain = useCallback(async (): Promise<void> => {
150
+ if (requiredChainId == null) return;
151
+ setIsSwitchingChain(true);
152
+ try {
153
+ await switchChainAsync({ chainId: requiredChainId });
154
+ } finally {
155
+ if (isMountedRef.current) setIsSwitchingChain(false);
156
+ }
157
+ }, [requiredChainId, switchChainAsync]);
158
+
159
+ // ConnectDialog 의 wagmi connect 성공 → pendingResult set → 아래 useEffect 가
160
+ // account.status === 'connected' 확인 후 외부 onConnect 호출 + modal close.
161
+ // wagmi state 가 비동기로 'connected' 로 전환되는 race 흡수용.
162
+ const handleDialogConnect = useCallback((result: ConnectResult): void => {
134
163
  setPendingResult(result);
135
164
  }, []);
136
165
 
137
- // pendingResult가 있고, 연결 + chain 매칭이 충족되면 dApp으로 발화
138
- useEffect(() => {
166
+ const handleDialogError = useCallback(
167
+ (error: Error, connectorId: ConnectorId): void => {
168
+ onLog?.(`[connect-kit] connect failed: ${connectorId} — ${error.message}`, error);
169
+ },
170
+ [onLog],
171
+ );
172
+
173
+ // 연결 성공 시 modal 자동 close — wagmi state 만 기준으로.
174
+ // 이전 구현은 pendingResult 가 set 된 경우만 close 했는데, `setPendingResult` 는
175
+ // ConnectDialog 의 onConnect (`connectAsync.then`) 안에서만 호출됨. MM deeplink 같은
176
+ // 시나리오 (앱 이동 → 승인 → 복귀) 에서 wagmi 가 자체적으로 'connected' 로 전이하지만
177
+ // connectAsync 의 promise 는 resolve 안 될 수 있음 → pendingResult set 안 됨 → modal 안 닫힘.
178
+ // 모든 connector (WC/CC/MM) 의 connected 가 일관된 close 트리거가 되도록 단순화.
179
+ useEffect((): void => {
180
+ if (!effectiveOpen) return;
181
+ if (account.status !== 'connected') return;
182
+ setIsOpen(false);
183
+ }, [effectiveOpen, account.status]);
184
+
185
+ // 외부 onConnect 콜백은 best-effort — pendingResult 가 set 된 경우만 호출.
186
+ useEffect((): void => {
139
187
  if (!pendingResult) return;
140
188
  if (account.status !== 'connected') {
141
- // 연결이 끊겼거나 진행 중 — pending 폐기
142
189
  setPendingResult(null);
143
190
  return;
144
191
  }
145
- if (requiredChainId != null && account.chainId !== requiredChainId) {
146
- // chain 아직 안 맞음 — switch 후 다시 평가
147
- return;
148
- }
149
192
  onConnectRef.current?.(pendingResult);
150
193
  setPendingResult(null);
151
- setIsOpen(false);
152
- }, [pendingResult, account.status, account.chainId, requiredChainId]);
194
+ }, [pendingResult, account.status]);
153
195
 
154
196
  const value = useMemo<ConnectKitContextValue>(
155
197
  () => ({
@@ -157,6 +199,11 @@ const ConnectKitProviderInner: FC<ConnectKitProviderProps> = ({
157
199
  open,
158
200
  close,
159
201
  isConnected: account.status === 'connected',
202
+ needsChainSwitch,
203
+ requiredChainId,
204
+ currentChainId: account.chainId,
205
+ isSwitchingChain,
206
+ switchToRequiredChain,
160
207
  address: account.address,
161
208
  connectorId: resolveConnectorId(account.connector?.id),
162
209
  disconnect,
@@ -166,6 +213,11 @@ const ConnectKitProviderInner: FC<ConnectKitProviderProps> = ({
166
213
  open,
167
214
  close,
168
215
  account.status,
216
+ needsChainSwitch,
217
+ requiredChainId,
218
+ account.chainId,
219
+ isSwitchingChain,
220
+ switchToRequiredChain,
169
221
  account.address,
170
222
  account.connector?.id,
171
223
  disconnect,
@@ -175,15 +227,14 @@ const ConnectKitProviderInner: FC<ConnectKitProviderProps> = ({
175
227
  return (
176
228
  <ConnectKitContext.Provider value={value}>
177
229
  {children}
178
- <ConnectModal
230
+ <ConnectDialog
179
231
  open={effectiveOpen}
180
- connectors={connectors}
181
- wcProjectId={wcProjectId}
182
- requiredChainId={requiredChainId}
183
- renderConnectError={renderConnectError}
184
- onConnect={handleModalConnect}
232
+ theme={theme}
233
+ connectors={resolveConnectorsFromConfig(connectors)}
234
+ wcProjectId={kitConfig.wcProjectId}
185
235
  onClose={close}
186
- onLog={onLog}
236
+ onConnect={handleDialogConnect}
237
+ onError={handleDialogError}
187
238
  />
188
239
  </ConnectKitContext.Provider>
189
240
  );
@@ -0,0 +1,21 @@
1
+ import {
2
+ getAccount as wagmiGetAccount,
3
+ signMessage as wagmiSignMessage,
4
+ signTypedData as wagmiSignTypedData,
5
+ type GetAccountReturnType,
6
+ type SignMessageParameters,
7
+ type SignTypedDataParameters,
8
+ } from '@wagmi/core';
9
+ import { getConfig } from '../core/config';
10
+
11
+ export const getAccount = (): GetAccountReturnType => {
12
+ return wagmiGetAccount(getConfig());
13
+ };
14
+
15
+ export const signMessage = (params: SignMessageParameters): Promise<`0x${string}`> => {
16
+ return wagmiSignMessage(getConfig(), params);
17
+ };
18
+
19
+ export const signTypedData = (params: SignTypedDataParameters): Promise<`0x${string}`> => {
20
+ return wagmiSignTypedData(getConfig(), params);
21
+ };
@@ -0,0 +1,10 @@
1
+ import {
2
+ getBalance as wagmiGetBalance,
3
+ type GetBalanceParameters,
4
+ type GetBalanceReturnType,
5
+ } from '@wagmi/core';
6
+ import { getConfig } from '../core/config';
7
+
8
+ export const getBalance = (params: GetBalanceParameters): Promise<GetBalanceReturnType> => {
9
+ return wagmiGetBalance(getConfig(), params);
10
+ };
@@ -0,0 +1,17 @@
1
+ import {
2
+ switchChain as wagmiSwitchChain,
3
+ getPublicClient as wagmiGetPublicClient,
4
+ type SwitchChainParameters,
5
+ type GetPublicClientParameters,
6
+ type GetPublicClientReturnType,
7
+ } from '@wagmi/core';
8
+ import type { Chain } from 'viem';
9
+ import { getConfig } from '../core/config';
10
+
11
+ export const switchChain = (params: SwitchChainParameters): Promise<Chain> => {
12
+ return wagmiSwitchChain(getConfig(), params);
13
+ };
14
+
15
+ export const getPublicClient = (params?: GetPublicClientParameters): GetPublicClientReturnType => {
16
+ return wagmiGetPublicClient(getConfig(), params);
17
+ };
@@ -0,0 +1,33 @@
1
+ import {
2
+ readContract as wagmiReadContract,
3
+ writeContract as wagmiWriteContract,
4
+ type ReadContractParameters,
5
+ type ReadContractReturnType,
6
+ type WriteContractParameters,
7
+ type WriteContractReturnType,
8
+ type Config,
9
+ } from '@wagmi/core';
10
+ import type { Abi, ContractFunctionArgs, ContractFunctionName } from 'viem';
11
+ import { getConfig } from '../core/config';
12
+
13
+ export function readContract<
14
+ const abi extends Abi | readonly unknown[],
15
+ functionName extends ContractFunctionName<abi, 'pure' | 'view'>,
16
+ args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
17
+ >(
18
+ parameters: ReadContractParameters<abi, functionName, args, Config>,
19
+ ): Promise<ReadContractReturnType<abi, functionName, args>> {
20
+ return wagmiReadContract(getConfig(), parameters as any) as Promise<
21
+ ReadContractReturnType<abi, functionName, args>
22
+ >;
23
+ }
24
+
25
+ export function writeContract<
26
+ const abi extends Abi | readonly unknown[],
27
+ functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
28
+ args extends ContractFunctionArgs<abi, 'nonpayable' | 'payable', functionName>,
29
+ >(
30
+ parameters: WriteContractParameters<abi, functionName, args, Config>,
31
+ ): Promise<WriteContractReturnType> {
32
+ return wagmiWriteContract(getConfig(), parameters as any);
33
+ }
@@ -0,0 +1,12 @@
1
+ import {
2
+ waitForTransactionReceipt as wagmiWaitForTransactionReceipt,
3
+ type WaitForTransactionReceiptParameters,
4
+ type WaitForTransactionReceiptReturnType,
5
+ } from '@wagmi/core';
6
+ import { getConfig } from '../core/config';
7
+
8
+ export const waitForTransactionReceipt = (
9
+ params: WaitForTransactionReceiptParameters,
10
+ ): Promise<WaitForTransactionReceiptReturnType> => {
11
+ return wagmiWaitForTransactionReceipt(getConfig(), params);
12
+ };
package/src/assets.d.ts CHANGED
@@ -2,3 +2,8 @@ declare module '*.png' {
2
2
  const src: string;
3
3
  export default src;
4
4
  }
5
+
6
+ declare module '*.svg' {
7
+ const src: string;
8
+ export default src;
9
+ }
@@ -0,0 +1,50 @@
1
+ import { type ReactNode, type AnchorHTMLAttributes, type ButtonHTMLAttributes } from 'react';
2
+ import './style.scss';
3
+
4
+ interface ActionItemContent {
5
+ label?: string;
6
+ description?: string;
7
+ action?: string;
8
+ children?: ReactNode;
9
+ }
10
+
11
+ type ActionItemAsAnchor = { as: 'a' } & AnchorHTMLAttributes<HTMLAnchorElement> & ActionItemContent;
12
+ type ActionItemAsButton = { as: 'button' } & ButtonHTMLAttributes<HTMLButtonElement> &
13
+ ActionItemContent;
14
+
15
+ type ActionItemProps = ActionItemAsAnchor | ActionItemAsButton;
16
+
17
+ const ActionItemBody = ({ label, description, action, children }: ActionItemContent): ReactNode => {
18
+ if (children) return <>{children}</>;
19
+ return (
20
+ <>
21
+ <span className="ck-action-item-content">
22
+ <span className="ck-action-item-label">{label}</span>
23
+ {description && <span className="ck-action-item-desc">{description}</span>}
24
+ </span>
25
+ {action && <span className="ck-action-item-action">{action}</span>}
26
+ </>
27
+ );
28
+ };
29
+
30
+ export const ActionItem = (props: ActionItemProps) => {
31
+ if (props.as === 'a') {
32
+ const { as: _, label, description, action, children, className, ...rest } = props;
33
+ return (
34
+ <a className={`ck-action-item${className ? ` ${className}` : ''}`} {...rest}>
35
+ <ActionItemBody label={label} description={description} action={action}>
36
+ {children}
37
+ </ActionItemBody>
38
+ </a>
39
+ );
40
+ }
41
+
42
+ const { as: _, label, description, action, children, className, ...rest } = props;
43
+ return (
44
+ <button className={`ck-action-item${className ? ` ${className}` : ''}`} {...rest}>
45
+ <ActionItemBody label={label} description={description} action={action}>
46
+ {children}
47
+ </ActionItemBody>
48
+ </button>
49
+ );
50
+ };
@@ -0,0 +1,47 @@
1
+ @use '../../style/mixin.scss' as *;
2
+
3
+ .ck-root .ck-action-item {
4
+ display: flex;
5
+ align-items: center;
6
+ gap: 16px;
7
+ width: 100%;
8
+ padding: 16px 20px;
9
+ border-radius: 12px;
10
+ background: var(--scale-gray-100);
11
+ cursor: pointer;
12
+ margin-top: auto;
13
+ flex-shrink: 0;
14
+ text-decoration: none;
15
+ }
16
+
17
+ .ck-action-item-content {
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 2px;
21
+ flex: 1;
22
+ min-width: 0;
23
+ }
24
+
25
+ .ck-action-item-label {
26
+ @include textToken('subtitle2-bold');
27
+ color: var(--scale-gray-900);
28
+ }
29
+
30
+ .ck-action-item-desc {
31
+ @include textToken('label5-regular');
32
+ color: var(--scale-gray-600);
33
+ }
34
+
35
+ .ck-action-item-action {
36
+ display: inline-flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ padding: 0 20px;
40
+ height: 44px;
41
+ border-radius: 6px;
42
+ background: var(--scale-blue2-alpha-100);
43
+ @include textToken('label5-bold');
44
+ color: var(--semantic-brand-trugi-primary);
45
+ white-space: nowrap;
46
+ flex-shrink: 0;
47
+ }
@@ -0,0 +1,16 @@
1
+ import { type FC } from 'react';
2
+ import './style.scss';
3
+ import { CopyIcon } from '../../layout/connectDialog/asset/copyIcon';
4
+
5
+ interface CopyLinkProps {
6
+ onCopy?: () => void;
7
+ }
8
+
9
+ export const CopyLink: FC<CopyLinkProps> = ({ onCopy }) => {
10
+ return (
11
+ <button type="button" className="ck-copy-link" onClick={onCopy}>
12
+ <CopyIcon className="ck-copy-link-icon" />
13
+ Copy link
14
+ </button>
15
+ );
16
+ };
@@ -0,0 +1,16 @@
1
+ @use '../../style/mixin.scss' as *;
2
+
3
+ .ck-root .ck-copy-link {
4
+ display: inline-flex;
5
+ align-items: center;
6
+ align-self: center;
7
+ gap: 6px;
8
+ @include textToken('body3-l1-regular');
9
+ color: var(--scale-gray-500);
10
+ cursor: pointer;
11
+ }
12
+
13
+ .ck-copy-link-icon {
14
+ flex-shrink: 0;
15
+ color: var(--scale-gray-500);
16
+ }