@gluwa/connect-kit 0.1.0-next.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/.eslintrc.cjs +67 -0
- package/CHANGELOG.md +18 -0
- package/README.md +0 -0
- package/assets/creditwallet.png +0 -0
- package/assets/deeplink.png +0 -0
- package/assets/graphic.png +0 -0
- package/assets/metamask.png +0 -0
- package/assets/wc.png +0 -0
- package/dist/README.md +0 -0
- package/dist/_esm-PE6HOEBI.js +3909 -0
- package/dist/ccip-UBX2BH3T.js +15 -0
- package/dist/chunk-6KUZ225H.js +5259 -0
- package/dist/chunk-EVEWD66F.js +447 -0
- package/dist/chunk-U2IU7TQD.js +45 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +1820 -0
- package/dist/package.json +64 -0
- package/dist/secp256k1-FYSVLDVL.js +2311 -0
- package/package.json +57 -0
- package/src/ConnectModal.scss +627 -0
- package/src/ConnectModal.tsx +521 -0
- package/src/assets.d.ts +4 -0
- package/src/connector-meta.ts +41 -0
- package/src/creditConnectConnector.ts +451 -0
- package/src/hooks/useWagmiConnect.ts +125 -0
- package/src/index.ts +4 -0
- package/src/types.ts +34 -0
- package/src/utils/platform.ts +16 -0
- package/src/views/CreditWalletView.tsx +69 -0
- package/src/views/IdleView.tsx +10 -0
- package/src/views/MetaMaskView.tsx +89 -0
- package/src/views/WalletConnectView.tsx +266 -0
- package/tsconfig.json +8 -0
- package/tsup.config.ts +18 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
import graphic from '../../assets/graphic.png';
|
|
3
|
+
|
|
4
|
+
export const IdleView: FC = () => (
|
|
5
|
+
<div className="ck-view ck-view--idle">
|
|
6
|
+
<img className="ck-view__illustration" src={graphic} alt="" aria-hidden="true" />
|
|
7
|
+
<h4 className="ck-view__title">Connect anytime, anywhere</h4>
|
|
8
|
+
<p className="ck-view__description">Choose a wallet on the left to start connecting.</p>
|
|
9
|
+
</div>
|
|
10
|
+
);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { type FC, useEffect } from 'react';
|
|
2
|
+
import { QRCodeSVG } from 'qrcode.react';
|
|
3
|
+
import { isMobileDevice, tryOpenDeepLink } from '../utils/platform';
|
|
4
|
+
import { CONNECTOR_META } from '../connector-meta';
|
|
5
|
+
|
|
6
|
+
const { downloadUrl, deepLinkBase } = CONNECTOR_META.METAMASK;
|
|
7
|
+
|
|
8
|
+
interface MetaMaskViewProps {
|
|
9
|
+
qrUri: string | null;
|
|
10
|
+
hasExtension: boolean;
|
|
11
|
+
logoUrl?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const MetaMaskView: FC<MetaMaskViewProps> = ({ qrUri, hasExtension, logoUrl }) => {
|
|
15
|
+
const isMobile = isMobileDevice();
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (isMobile && qrUri && deepLinkBase) {
|
|
19
|
+
tryOpenDeepLink(qrUri, deepLinkBase);
|
|
20
|
+
}
|
|
21
|
+
}, [isMobile, qrUri]);
|
|
22
|
+
|
|
23
|
+
if (isMobile && deepLinkBase) {
|
|
24
|
+
return (
|
|
25
|
+
<div className="ck-view ck-view--mobile-redirect">
|
|
26
|
+
<p>Opening MetaMask...</p>
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (hasExtension) {
|
|
32
|
+
return (
|
|
33
|
+
<div className="ck-view ck-view--extension">
|
|
34
|
+
<span className="ck-view__wallet-icon ck-view__wallet-icon--metamask" aria-hidden="true" />
|
|
35
|
+
<h4 className="ck-view__title">Open MetaMask</h4>
|
|
36
|
+
<p className="ck-view__description">Check the connection in your extension</p>
|
|
37
|
+
<span className="ck-spinner" aria-label="Connecting" />
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="ck-view ck-view--qr">
|
|
44
|
+
<div className={`ck-qr-frame ${!qrUri ? 'ck-qr-frame--loading' : ''}`}>
|
|
45
|
+
{qrUri ? (
|
|
46
|
+
<QRCodeSVG
|
|
47
|
+
value={qrUri}
|
|
48
|
+
size={196}
|
|
49
|
+
level="H"
|
|
50
|
+
imageSettings={
|
|
51
|
+
logoUrl ? { src: logoUrl, width: 40, height: 40, excavate: true } : undefined
|
|
52
|
+
}
|
|
53
|
+
/>
|
|
54
|
+
) : (
|
|
55
|
+
<div className="ck-qr-spinner" aria-label="Loading QR code" />
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
{qrUri && (
|
|
60
|
+
<button
|
|
61
|
+
type="button"
|
|
62
|
+
className="ck-copy-link"
|
|
63
|
+
onClick={() => {
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
65
|
+
navigator.clipboard.writeText(qrUri);
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
Copy link
|
|
69
|
+
</button>
|
|
70
|
+
)}
|
|
71
|
+
|
|
72
|
+
{downloadUrl && (
|
|
73
|
+
<div className="ck-download-card">
|
|
74
|
+
<div className="ck-download-card__text">
|
|
75
|
+
<p className="ck-download-card__title">Don't have MetaMask Wallet?</p>
|
|
76
|
+
</div>
|
|
77
|
+
<a
|
|
78
|
+
href={downloadUrl}
|
|
79
|
+
target="_blank"
|
|
80
|
+
rel="nofollow noopener noreferrer"
|
|
81
|
+
className="ck-btn-primary"
|
|
82
|
+
>
|
|
83
|
+
Download
|
|
84
|
+
</a>
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { type FC, useMemo } from 'react';
|
|
2
|
+
import { QRCodeSVG } from 'qrcode.react';
|
|
3
|
+
import { isMobileDevice, tryOpenDeepLink } from '../utils/platform';
|
|
4
|
+
import { type WCWallet, type WCSubView } from '../types';
|
|
5
|
+
import deeplink from '../../assets/deeplink.png';
|
|
6
|
+
|
|
7
|
+
interface WalletConnectViewProps {
|
|
8
|
+
subView: WCSubView;
|
|
9
|
+
qrUri: string | null;
|
|
10
|
+
logoUrl?: string;
|
|
11
|
+
walletList: WCWallet[];
|
|
12
|
+
walletListLoading: boolean;
|
|
13
|
+
walletListSearch: string;
|
|
14
|
+
walletListFilterActive: boolean;
|
|
15
|
+
selectedWallet: WCWallet | null;
|
|
16
|
+
onShowList: () => void;
|
|
17
|
+
onSelectWallet: (wallet: WCWallet) => void;
|
|
18
|
+
onSearchChange: (q: string) => void;
|
|
19
|
+
onFilterToggle: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const WalletConnectView: FC<WalletConnectViewProps> = (props) => {
|
|
23
|
+
const { subView, selectedWallet } = props;
|
|
24
|
+
|
|
25
|
+
if (subView === 'list') return <WalletListView {...props} />;
|
|
26
|
+
if (subView === 'wallet' && selectedWallet)
|
|
27
|
+
return <WalletQRView wallet={selectedWallet} qrUri={props.qrUri} />;
|
|
28
|
+
return <WCQRView {...props} />;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const WCQRView: FC<WalletConnectViewProps> = ({ qrUri, logoUrl, walletList, onShowList }) => (
|
|
32
|
+
<div className="ck-view ck-view--qr">
|
|
33
|
+
<div className={`ck-qr-frame ${!qrUri ? 'ck-qr-frame--loading' : ''}`}>
|
|
34
|
+
{qrUri ? (
|
|
35
|
+
<QRCodeSVG
|
|
36
|
+
value={qrUri}
|
|
37
|
+
size={196}
|
|
38
|
+
level="H"
|
|
39
|
+
imageSettings={
|
|
40
|
+
logoUrl
|
|
41
|
+
? {
|
|
42
|
+
src: logoUrl,
|
|
43
|
+
width: 40,
|
|
44
|
+
height: 40,
|
|
45
|
+
excavate: true,
|
|
46
|
+
}
|
|
47
|
+
: undefined
|
|
48
|
+
}
|
|
49
|
+
/>
|
|
50
|
+
) : (
|
|
51
|
+
<div className="ck-qr-spinner" aria-label="Loading QR code" />
|
|
52
|
+
)}
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<p className="ck-view__caption">Scan this QR Code with your phone</p>
|
|
56
|
+
|
|
57
|
+
{qrUri && (
|
|
58
|
+
<button
|
|
59
|
+
type="button"
|
|
60
|
+
className="ck-copy-link"
|
|
61
|
+
onClick={() => {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
63
|
+
navigator.clipboard.writeText(qrUri);
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
Copy link
|
|
67
|
+
</button>
|
|
68
|
+
)}
|
|
69
|
+
|
|
70
|
+
<button type="button" className="ck-all-wallets-btn" onClick={onShowList}>
|
|
71
|
+
<span className="ck-all-wallets-btn__icon" aria-hidden="true" />
|
|
72
|
+
<span className="ck-all-wallets-btn__label">All Wallets</span>
|
|
73
|
+
{walletList.length > 0 && (
|
|
74
|
+
<span className="ck-all-wallets-btn__count">{walletList.length}+</span>
|
|
75
|
+
)}
|
|
76
|
+
</button>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const CREDIT_WALLET_NAME = 'Credit Wallet';
|
|
81
|
+
|
|
82
|
+
const WalletListView: FC<WalletConnectViewProps> = ({
|
|
83
|
+
walletList,
|
|
84
|
+
walletListLoading,
|
|
85
|
+
walletListSearch,
|
|
86
|
+
walletListFilterActive,
|
|
87
|
+
logoUrl,
|
|
88
|
+
qrUri,
|
|
89
|
+
onSelectWallet,
|
|
90
|
+
onSearchChange,
|
|
91
|
+
onFilterToggle,
|
|
92
|
+
}) => {
|
|
93
|
+
const isMobile = isMobileDevice();
|
|
94
|
+
|
|
95
|
+
const filtered = useMemo(() => {
|
|
96
|
+
const q = walletListSearch.trim().toLowerCase();
|
|
97
|
+
let list = walletList;
|
|
98
|
+
if (walletListFilterActive) {
|
|
99
|
+
list = list.filter(
|
|
100
|
+
(w) => w.mobileNative || w.mobileUniversal || w.desktopNative || w.desktopUniversal,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
if (q) {
|
|
104
|
+
list = list.filter((w) => w.name.toLowerCase().includes(q));
|
|
105
|
+
}
|
|
106
|
+
return [...list].sort((a, b) => {
|
|
107
|
+
if (a.name === CREDIT_WALLET_NAME) return -1;
|
|
108
|
+
if (b.name === CREDIT_WALLET_NAME) return 1;
|
|
109
|
+
return 0;
|
|
110
|
+
});
|
|
111
|
+
}, [walletList, walletListSearch, walletListFilterActive]);
|
|
112
|
+
|
|
113
|
+
const handleClickWallet = (wallet: WCWallet): void => {
|
|
114
|
+
const uri = qrUri;
|
|
115
|
+
if (isMobile && uri) {
|
|
116
|
+
const target = wallet.mobileNative || wallet.mobileUniversal;
|
|
117
|
+
if (target) {
|
|
118
|
+
tryOpenDeepLink(uri, target);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
onSelectWallet(wallet);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<div className="ck-view ck-view--wallet-list">
|
|
127
|
+
<div className="ck-wallet-search">
|
|
128
|
+
<input
|
|
129
|
+
type="text"
|
|
130
|
+
className="ck-wallet-search__input"
|
|
131
|
+
placeholder="Search wallet"
|
|
132
|
+
value={walletListSearch}
|
|
133
|
+
onChange={(e) => {
|
|
134
|
+
onSearchChange(e.target.value);
|
|
135
|
+
}}
|
|
136
|
+
/>
|
|
137
|
+
<button
|
|
138
|
+
type="button"
|
|
139
|
+
className={`ck-wc-filter${walletListFilterActive ? ' is-active' : ''}`}
|
|
140
|
+
onClick={onFilterToggle}
|
|
141
|
+
aria-pressed={walletListFilterActive}
|
|
142
|
+
aria-label="Show WalletConnect wallets only"
|
|
143
|
+
title="WalletConnect wallets only"
|
|
144
|
+
>
|
|
145
|
+
{logoUrl && (
|
|
146
|
+
<img src={logoUrl} alt="" className="ck-wc-filter__icon" aria-hidden="true" />
|
|
147
|
+
)}
|
|
148
|
+
<span className="ck-wc-filter__track">
|
|
149
|
+
<span className="ck-wc-filter__thumb" />
|
|
150
|
+
</span>
|
|
151
|
+
</button>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
{walletListLoading && walletList.length === 0 && (
|
|
155
|
+
<div className="ck-wallet-list-loading">
|
|
156
|
+
<span className="ck-spinner" aria-label="Loading wallets" />
|
|
157
|
+
</div>
|
|
158
|
+
)}
|
|
159
|
+
|
|
160
|
+
{!walletListLoading && filtered.length === 0 && walletList.length > 0 && (
|
|
161
|
+
<p className="ck-wallet-list-empty">No wallets found.</p>
|
|
162
|
+
)}
|
|
163
|
+
|
|
164
|
+
<div className="ck-wallet-grid-scroll">
|
|
165
|
+
<ul className="ck-wallet-grid">
|
|
166
|
+
{filtered.map((wallet) => {
|
|
167
|
+
const hasDeeplink = !!(
|
|
168
|
+
wallet.mobileNative ||
|
|
169
|
+
wallet.mobileUniversal ||
|
|
170
|
+
wallet.desktopNative ||
|
|
171
|
+
wallet.desktopUniversal
|
|
172
|
+
);
|
|
173
|
+
return (
|
|
174
|
+
<li key={wallet.id}>
|
|
175
|
+
<button
|
|
176
|
+
type="button"
|
|
177
|
+
className="ck-wallet-grid__item"
|
|
178
|
+
onClick={() => {
|
|
179
|
+
handleClickWallet(wallet);
|
|
180
|
+
}}
|
|
181
|
+
>
|
|
182
|
+
{wallet.imageUrl ? (
|
|
183
|
+
<img className="ck-wallet-grid__icon" src={wallet.imageUrl} alt="" />
|
|
184
|
+
) : (
|
|
185
|
+
<span className="ck-wallet-grid__icon-placeholder" aria-hidden="true" />
|
|
186
|
+
)}
|
|
187
|
+
<span className="ck-wallet-grid__name">
|
|
188
|
+
<span className="ck-wallet-grid__name-text">{wallet.name}</span>
|
|
189
|
+
{hasDeeplink && (
|
|
190
|
+
<img
|
|
191
|
+
src={deeplink}
|
|
192
|
+
alt=""
|
|
193
|
+
className="ck-wallet-grid__wc-badge"
|
|
194
|
+
aria-hidden="true"
|
|
195
|
+
/>
|
|
196
|
+
)}
|
|
197
|
+
</span>
|
|
198
|
+
</button>
|
|
199
|
+
</li>
|
|
200
|
+
);
|
|
201
|
+
})}
|
|
202
|
+
</ul>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const WalletQRView: FC<{ wallet: WCWallet; qrUri: string | null }> = ({ wallet, qrUri }) => {
|
|
209
|
+
const downloadUrl = wallet.appIos || wallet.appAndroid || wallet.homepage;
|
|
210
|
+
const logoSrc = wallet.imageUrl;
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<div className="ck-view ck-view--qr">
|
|
214
|
+
<div className={`ck-qr-frame ${!qrUri ? 'ck-qr-frame--loading' : ''}`}>
|
|
215
|
+
{qrUri ? (
|
|
216
|
+
<QRCodeSVG
|
|
217
|
+
value={qrUri}
|
|
218
|
+
size={196}
|
|
219
|
+
level="H"
|
|
220
|
+
{...(logoSrc && {
|
|
221
|
+
imageSettings: {
|
|
222
|
+
src: logoSrc,
|
|
223
|
+
width: 40,
|
|
224
|
+
height: 40,
|
|
225
|
+
excavate: true,
|
|
226
|
+
},
|
|
227
|
+
})}
|
|
228
|
+
/>
|
|
229
|
+
) : (
|
|
230
|
+
<div className="ck-qr-spinner" aria-label="Loading QR code" />
|
|
231
|
+
)}
|
|
232
|
+
</div>
|
|
233
|
+
|
|
234
|
+
<p className="ck-view__caption">Scan this QR Code with your phone</p>
|
|
235
|
+
|
|
236
|
+
{qrUri && (
|
|
237
|
+
<button
|
|
238
|
+
type="button"
|
|
239
|
+
className="ck-copy-link"
|
|
240
|
+
onClick={() => {
|
|
241
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
242
|
+
navigator.clipboard.writeText(qrUri);
|
|
243
|
+
}}
|
|
244
|
+
>
|
|
245
|
+
Copy link
|
|
246
|
+
</button>
|
|
247
|
+
)}
|
|
248
|
+
|
|
249
|
+
{downloadUrl && (
|
|
250
|
+
<div className="ck-download-card">
|
|
251
|
+
<div className="ck-download-card__text">
|
|
252
|
+
<p className="ck-download-card__title">Don't have {wallet.name}?</p>
|
|
253
|
+
</div>
|
|
254
|
+
<a
|
|
255
|
+
href={downloadUrl}
|
|
256
|
+
target="_blank"
|
|
257
|
+
rel="nofollow noopener noreferrer"
|
|
258
|
+
className="ck-btn-primary"
|
|
259
|
+
>
|
|
260
|
+
Download
|
|
261
|
+
</a>
|
|
262
|
+
</div>
|
|
263
|
+
)}
|
|
264
|
+
</div>
|
|
265
|
+
);
|
|
266
|
+
};
|
package/tsconfig.json
ADDED
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup';
|
|
2
|
+
import { sassPlugin } from 'esbuild-sass-plugin';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
entry: { index: 'src/index.ts' },
|
|
6
|
+
format: ['esm'],
|
|
7
|
+
dts: true,
|
|
8
|
+
clean: true,
|
|
9
|
+
target: 'es2019',
|
|
10
|
+
external: ['react', 'react-native'],
|
|
11
|
+
banner: {
|
|
12
|
+
js: 'import React from "react";',
|
|
13
|
+
},
|
|
14
|
+
esbuildPlugins: [sassPlugin({ type: 'style' })],
|
|
15
|
+
esbuildOptions(options) {
|
|
16
|
+
options.loader = { ...options.loader, '.png': 'dataurl' };
|
|
17
|
+
},
|
|
18
|
+
});
|