@gluwa/connect-kit 0.2.0-next.9 → 0.2.1-next.4

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 (50) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/assets/wc.png +0 -0
  3. package/dist/{chunk-VE5LB7BN.js → chunk-TMKSC7ZT.js} +9 -2
  4. package/dist/credit-connect.js +1 -1
  5. package/dist/index.css +178 -122
  6. package/dist/index.d.ts +96 -26
  7. package/dist/index.js +681 -266
  8. package/dist/package.json +1 -1
  9. package/package.json +6 -6
  10. package/src/ConnectKitProvider.tsx +8 -1
  11. package/src/api/wrappers.ts +361 -0
  12. package/src/components/qrArea/index.tsx +25 -3
  13. package/src/components/qrArea/style.scss +61 -2
  14. package/src/components/toast/index.tsx +41 -0
  15. package/src/components/toast/style.scss +108 -0
  16. package/src/core/config.ts +23 -2
  17. package/src/core/deeplinkSignal.ts +25 -0
  18. package/src/creditConnectConnector.ts +15 -5
  19. package/src/events/account.ts +15 -18
  20. package/src/hooks/useConnectBanner.ts +79 -0
  21. package/src/hooks/useConnectTimeout.ts +21 -9
  22. package/src/hooks/useMetaMaskExtension.ts +2 -1
  23. package/src/hooks/useWCState.ts +7 -2
  24. package/src/hooks/useWagmiConnect.ts +41 -14
  25. package/src/index.ts +29 -24
  26. package/src/layout/allWallets/index.tsx +16 -2
  27. package/src/layout/connectDialog/asset/warningIcon.tsx +21 -0
  28. package/src/layout/connectDialog/idle/assets/banner-placeholder.png +0 -0
  29. package/src/layout/connectDialog/idle/index.tsx +40 -16
  30. package/src/layout/connectDialog/idle/style.scss +42 -51
  31. package/src/layout/connectDialog/index.tsx +174 -37
  32. package/src/layout/connectDialog/metaMask/index.tsx +3 -2
  33. package/src/layout/connectDialog/qr/index.tsx +3 -1
  34. package/src/layout/connectDialog/style.scss +0 -48
  35. package/src/layout/connectDialog/timeout/index.tsx +0 -5
  36. package/src/layout/connectDialog/timeout/style.scss +0 -5
  37. package/src/layout/connectDialog/walletQR/index.tsx +3 -1
  38. package/src/layout/detailPanel/index.tsx +39 -6
  39. package/src/layout/detailPanel/style.scss +2 -1
  40. package/src/layout/selectorPanel/index.tsx +1 -0
  41. package/src/types.ts +20 -0
  42. package/src/utils/platform.ts +7 -0
  43. package/src/api/account.ts +0 -21
  44. package/src/api/asset.ts +0 -10
  45. package/src/api/balance.ts +0 -10
  46. package/src/api/chain.ts +0 -17
  47. package/src/api/contract.ts +0 -33
  48. package/src/api/transaction.ts +0 -12
  49. package/src/components/snackbar/index.tsx +0 -25
  50. package/src/components/snackbar/style.scss +0 -51
@@ -46,51 +46,3 @@
46
46
  &[data-step='detail'] .ck-selector { display: none !important; }
47
47
  }
48
48
  }
49
-
50
- .ck-root .ck-dialog-snackbar {
51
- position: fixed;
52
- top: clamp(20px, 9.2vh, 99px);
53
- left: 50%;
54
- z-index: 1001;
55
- width: min(calc(100vw - 40px), 400px);
56
- transform: translateX(-50%);
57
- animation: ck-dialog-snackbar-in 0.2s ease;
58
-
59
- @include tablet {
60
- top: clamp(
61
- calc(env(safe-area-inset-top, 0px) + 20px),
62
- calc(env(safe-area-inset-top, 0px) + 20px),
63
- calc(env(safe-area-inset-top, 0px) + 20px)
64
- );
65
- left: 20px;
66
- right: 20px;
67
- width: auto;
68
- transform: none;
69
- }
70
- }
71
-
72
- @keyframes ck-dialog-snackbar-in {
73
- from {
74
- opacity: 0;
75
- transform: translateX(-50%) translateY(8px);
76
- }
77
-
78
- to {
79
- opacity: 1;
80
- transform: translateX(-50%) translateY(0);
81
- }
82
- }
83
-
84
- @include tablet {
85
- @keyframes ck-dialog-snackbar-in {
86
- from {
87
- opacity: 0;
88
- transform: translateY(8px);
89
- }
90
-
91
- to {
92
- opacity: 1;
93
- transform: translateY(0);
94
- }
95
- }
96
- }
@@ -10,11 +10,6 @@ export const Timeout: FC<TimeoutProps> = ({ onRetry }) => {
10
10
  <div className="ck-timeout">
11
11
  <div className="ck-timeout-text">
12
12
  <h3 className="ck-timeout-title">Connection Failed</h3>
13
- <p className="ck-timeout-desc">
14
- The connection took too long to respond.
15
- <br />
16
- Please check your network and try again.
17
- </p>
18
13
  </div>
19
14
  <button type="button" className="ck-timeout-retry-btn" onClick={onRetry}>
20
15
  Try Again
@@ -21,11 +21,6 @@
21
21
  color: var(--scale-gray-900);
22
22
  }
23
23
 
24
- .ck-timeout-desc {
25
- @include textToken('body4-l1-regular');
26
- color: var(--scale-gray-600);
27
- }
28
-
29
24
  .ck-root .ck-timeout-retry-btn {
30
25
  display: inline-flex;
31
26
  align-items: center;
@@ -7,9 +7,10 @@ interface WalletQRProps {
7
7
  wallet: WCWallet;
8
8
  uri?: string | null;
9
9
  onCopy?: () => void;
10
+ onOpenApp?: () => void;
10
11
  }
11
12
 
12
- export const WalletQR: FC<WalletQRProps> = ({ wallet, uri = null, onCopy }) => {
13
+ export const WalletQR: FC<WalletQRProps> = ({ wallet, uri = null, onCopy, onOpenApp }) => {
13
14
  const downloadUrl = wallet.appIos || wallet.appAndroid || wallet.homepage;
14
15
 
15
16
  return (
@@ -21,6 +22,7 @@ export const WalletQR: FC<WalletQRProps> = ({ wallet, uri = null, onCopy }) => {
21
22
  hasBg
22
23
  label={`Scan with ${wallet.name}`}
23
24
  onCopy={onCopy}
25
+ onOpenApp={onOpenApp}
24
26
  />
25
27
  {downloadUrl && (
26
28
  <ActionItem
@@ -2,7 +2,7 @@ import { type FC } from 'react';
2
2
  import { CloseIcon } from '../connectDialog/asset/closeIcon';
3
3
  import { BackIcon } from '../connectDialog/asset/backIcon';
4
4
  import './style.scss';
5
- import { type ConnectorId, type WCWallet } from '../../types';
5
+ import { type ConnectBanner, type ConnectorId, type WCWallet } from '../../types';
6
6
  import { CONNECTOR_META } from '../../connector-meta';
7
7
  import { Idle } from '../connectDialog/idle';
8
8
  import { Loading } from '../connectDialog/loading';
@@ -25,6 +25,8 @@ export type DetailContent =
25
25
  | 'wallet-qr';
26
26
 
27
27
  interface DetailPanelProps {
28
+ connectBanner?: ConnectBanner | null;
29
+ connectBannerLoading?: boolean;
28
30
  selectedConnector: ConnectorId | null;
29
31
  selectedWallet?: WCWallet | null;
30
32
  content?: DetailContent;
@@ -40,6 +42,8 @@ interface DetailPanelProps {
40
42
  onShowAllWallets?: () => void;
41
43
  onSelectWallet?: (wallet: WCWallet) => void;
42
44
  onCopyLink?: () => void;
45
+ /** 모바일 QR 화면의 'Open app' 버튼 — 해당 지갑 앱을 deeplink 로 연다. */
46
+ onOpenApp?: () => void;
43
47
  /** timeout 화면의 "Try Again" 버튼 핸들러. */
44
48
  onRetry?: () => void;
45
49
  }
@@ -68,6 +72,8 @@ const getTitle = (content: DetailContent, connector: ConnectorId | null): string
68
72
  };
69
73
 
70
74
  export const DetailPanel: FC<DetailPanelProps> = ({
75
+ connectBanner = null,
76
+ connectBannerLoading = false,
71
77
  selectedConnector,
72
78
  selectedWallet = null,
73
79
  content = 'idle',
@@ -80,6 +86,7 @@ export const DetailPanel: FC<DetailPanelProps> = ({
80
86
  onShowAllWallets,
81
87
  onSelectWallet,
82
88
  onCopyLink,
89
+ onOpenApp,
83
90
  onRetry,
84
91
  }) => {
85
92
  // CONNECTOR_META 에서 활성 connector 의 logo / downloadUrl 가져옴.
@@ -91,6 +98,10 @@ export const DetailPanel: FC<DetailPanelProps> = ({
91
98
  ? `Scan with ${selectedWallet.name}`
92
99
  : getTitle(content, selectedConnector);
93
100
  const showBack = content !== 'idle';
101
+ const closeColor =
102
+ content === 'idle' && !connectBannerLoading
103
+ ? (connectBanner?.closeColor ?? '#FFFFFF')
104
+ : undefined;
94
105
 
95
106
  return (
96
107
  <section className="ck-detail">
@@ -105,15 +116,37 @@ export const DetailPanel: FC<DetailPanelProps> = ({
105
116
  ) : (
106
117
  <span className="ck-detail-header-spacer" aria-hidden="true" />
107
118
  )}
108
- <button type="button" className="ck-btn-close" onClick={onClose} aria-label="Close">
119
+ <button
120
+ type="button"
121
+ className="ck-btn-close"
122
+ onClick={onClose}
123
+ aria-label="Close"
124
+ style={{ color: closeColor }}
125
+ >
109
126
  <CloseIcon />
110
127
  </button>
111
128
  </header>
112
129
  <div className="ck-detail-body">
113
- {content === 'idle' && <Idle />}
130
+ {content === 'idle' && !connectBannerLoading && (
131
+ <Idle
132
+ title={connectBanner?.title}
133
+ description={connectBanner?.subtitle}
134
+ linkText={connectBanner?.linkText}
135
+ linkUrl={connectBanner?.linkUrl}
136
+ imageUrl={connectBanner?.imageUrl}
137
+ titleColor={connectBanner?.titleColor}
138
+ descriptionColor={connectBanner?.subtitleColor}
139
+ linkTextColor={connectBanner?.linkTextColor}
140
+ />
141
+ )}
114
142
  {content === 'loading' && <Loading />}
115
143
  {content === 'qr' && (
116
- <QR uri={qrUri} logoUrl={connectorLogoUrl} downloadUrl={connectorDownloadUrl} />
144
+ <QR
145
+ uri={qrUri}
146
+ logoUrl={connectorLogoUrl}
147
+ downloadUrl={connectorDownloadUrl}
148
+ onOpenApp={onOpenApp}
149
+ />
117
150
  )}
118
151
  {content === 'timeout' && <Timeout onRetry={onRetry} />}
119
152
  {(content === 'metamask-ext' || content === 'metamask-qr') && (
@@ -122,7 +155,7 @@ export const DetailPanel: FC<DetailPanelProps> = ({
122
155
  logoUrl={connectorLogoUrl}
123
156
  uri={qrUri}
124
157
  downloadUrl={connectorDownloadUrl}
125
- onCopy={onCopyLink}
158
+ onOpenApp={onOpenApp}
126
159
  />
127
160
  )}
128
161
  {content === 'walletconnect' && (
@@ -142,7 +175,7 @@ export const DetailPanel: FC<DetailPanelProps> = ({
142
175
  />
143
176
  )}
144
177
  {content === 'wallet-qr' && selectedWallet && (
145
- <WalletQR wallet={selectedWallet} uri={qrUri} onCopy={onCopyLink} />
178
+ <WalletQR wallet={selectedWallet} uri={qrUri} onCopy={onCopyLink} onOpenApp={onOpenApp} />
146
179
  )}
147
180
  </div>
148
181
  </section>
@@ -13,11 +13,12 @@
13
13
  .ck-detail-header {
14
14
  display: flex;
15
15
  align-items: center;
16
+ position: relative;
17
+ z-index: 1;
16
18
  gap: 10px;
17
19
  height: 60px;
18
20
  padding: 0 20px;
19
21
  flex-shrink: 0;
20
- background: var(--semantic-paper-sheet);
21
22
  }
22
23
 
23
24
  .ck-btn-back {
@@ -87,6 +87,7 @@ export const SelectorPanel: FC<SelectorPanelProps> = ({
87
87
 
88
88
  <a
89
89
  className="ck-no-wallet-btn"
90
+ // TODO: Change to Penguin Wallet
90
91
  href="https://creditcoin.org/Credit-Wallet"
91
92
  target="_blank"
92
93
  rel="noopener noreferrer"
package/src/types.ts CHANGED
@@ -37,6 +37,26 @@ export type WCSubView = 'qr' | 'list' | 'wallet';
37
37
 
38
38
  export type ConnectKitTheme = 'light' | 'dark';
39
39
 
40
+ export type ConnectBannerSiteKey =
41
+ | 'penguin-swap'
42
+ | 'penguin-bridge'
43
+ | 'penguin-base'
44
+ | 'penguin-wallet';
45
+
46
+ export interface ConnectBanner {
47
+ id: number;
48
+ siteKey: ConnectBannerSiteKey;
49
+ title: string;
50
+ subtitle: string;
51
+ linkText: string;
52
+ linkUrl: string;
53
+ imageUrl: string;
54
+ titleColor: string;
55
+ subtitleColor: string;
56
+ linkTextColor: string;
57
+ closeColor: string;
58
+ }
59
+
40
60
  export interface ConnectResult {
41
61
  address: `0x${string}`;
42
62
  connectorId: ConnectorId;
@@ -3,6 +3,13 @@ export const isMobileDevice = (): boolean => {
3
3
  return /android|iphone|ipad|ipod/i.test(navigator.userAgent);
4
4
  };
5
5
 
6
+ // 인앱 지갑 웹뷰 판별: 모바일 + 호스트가 window.ethereum(EIP-1193) 을 주입한 경우.
7
+ export const hasInjectedMobileProvider = (): boolean => {
8
+ if (!isMobileDevice()) return false;
9
+ if (typeof window === 'undefined') return false;
10
+ return typeof (window as Window & { ethereum?: unknown }).ethereum !== 'undefined';
11
+ };
12
+
6
13
  export const tryOpenDeepLink = (uri: string, deepLinkBase: string): void => {
7
14
  const sep = deepLinkBase.endsWith('/') ? '' : '/';
8
15
  window.location.replace(`${deepLinkBase}${sep}wc?uri=${encodeURIComponent(uri)}`);
@@ -1,21 +0,0 @@
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
- };
package/src/api/asset.ts DELETED
@@ -1,10 +0,0 @@
1
- import {
2
- watchAsset as wagmiWatchAsset,
3
- type WatchAssetParameters,
4
- type WatchAssetReturnType,
5
- } from '@wagmi/core';
6
- import { getConfig } from '../core/config';
7
-
8
- export const watchAsset = (params: WatchAssetParameters): Promise<WatchAssetReturnType> => {
9
- return wagmiWatchAsset(getConfig(), params);
10
- };
@@ -1,10 +0,0 @@
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
- };
package/src/api/chain.ts DELETED
@@ -1,17 +0,0 @@
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
- };
@@ -1,33 +0,0 @@
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
- }
@@ -1,12 +0,0 @@
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
- };
@@ -1,25 +0,0 @@
1
- import { type FC } from 'react';
2
- import './style.scss';
3
- import { CloseIcon } from '../../layout/connectDialog/asset/closeIcon';
4
- import { CheckIcon } from '../../layout/connectDialog/asset/checkIcon';
5
-
6
- interface SnackbarProps {
7
- message: string;
8
- onClose?: () => void;
9
- }
10
-
11
- export const Snackbar: FC<SnackbarProps> = ({ message, onClose }) => {
12
- return (
13
- <div className="ck-snackbar" role="status" aria-live="polite">
14
- <div className="ck-snackbar-content">
15
- <CheckIcon className="ck-snackbar-check" />
16
- <p className="ck-snackbar-message">{message}</p>
17
- </div>
18
- {onClose && (
19
- <button type="button" className="ck-snackbar-close" onClick={onClose} aria-label="Close">
20
- <CloseIcon width={20} height={20} />
21
- </button>
22
- )}
23
- </div>
24
- );
25
- };
@@ -1,51 +0,0 @@
1
- @use '../../style/mixin.scss' as *;
2
-
3
- .ck-snackbar {
4
- display: flex;
5
- align-items: center;
6
- gap: 16px;
7
- padding: 12px 16px;
8
- border-radius: 8px;
9
- background: var(--semantic-paper-sheet);
10
- border: 1px solid var(--semantic-divider-divider-1);
11
- width: 100%;
12
- max-width: 400px;
13
-
14
- @include tablet {
15
- max-width: none;
16
- }
17
- }
18
-
19
- .ck-snackbar-content {
20
- display: flex;
21
- align-items: center;
22
- gap: 8px;
23
- flex: 1;
24
- min-width: 0;
25
- }
26
-
27
- .ck-snackbar-check {
28
- display: flex;
29
- align-items: center;
30
- justify-content: center;
31
- width: 24px;
32
- height: 24px;
33
- flex-shrink: 0;
34
- color: var(--semantic-information-success);
35
- }
36
-
37
- .ck-snackbar-message {
38
- @include textToken('body3-l1-medium');
39
- color: var(--scale-gray-900);
40
- flex: 1;
41
- min-width: 0;
42
- }
43
-
44
- .ck-root .ck-snackbar-close {
45
- display: flex;
46
- align-items: center;
47
- justify-content: center;
48
- flex-shrink: 0;
49
- color: var(--scale-gray-700);
50
- cursor: pointer;
51
- }