@nexus-cross/crossx-sdk-react 2.0.2-beta.2 → 2.0.2
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/README.md +139 -292
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,81 +1,45 @@
|
|
|
1
1
|
# @nexus-cross/crossx-sdk-react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React hooks and provider for integrating the CROSSx Embedded Wallet into React applications.
|
|
4
4
|
|
|
5
|
-
> **wagmi
|
|
6
|
-
>
|
|
5
|
+
> **Using wagmi?** Use [`@nexus-cross/crossx-sdk-wagmi`](https://www.npmjs.com/package/@nexus-cross/crossx-sdk-wagmi) instead.
|
|
6
|
+
> This package is for apps that use CROSSx wallet exclusively, without wagmi.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## 패키지 구조
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
@nexus-cross/crossx-sdk-core ← 핵심 SDK (인증, 서명, 트랜잭션)
|
|
14
|
-
@nexus-cross/crossx-sdk-react ← React Hooks & Provider (이 패키지)
|
|
15
|
-
@nexus-cross/crossx-sdk-wagmi ← wagmi Connector (wagmi 사용 시)
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 설치
|
|
8
|
+
## Installation
|
|
21
9
|
|
|
22
10
|
```bash
|
|
23
|
-
# pnpm (monorepo 내부)
|
|
24
|
-
pnpm add @nexus-cross/crossx-sdk-react
|
|
25
|
-
|
|
26
|
-
# npm
|
|
27
11
|
npm install @nexus-cross/crossx-sdk-react
|
|
12
|
+
# or
|
|
13
|
+
pnpm add @nexus-cross/crossx-sdk-react
|
|
28
14
|
```
|
|
29
15
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## 환경 변수
|
|
35
|
-
|
|
36
|
-
`.env` 파일에 아래 값을 설정합니다. SDK 내부에서 자동으로 읽습니다.
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
# OAuth 서비스 URL (로그인용) — 필수
|
|
40
|
-
VITE_OAUTH_SERVICE_URL=https://dev-cross-wallet-oauth.crosstoken.io
|
|
41
|
-
|
|
42
|
-
# JWT 검증 API URL — 필수
|
|
43
|
-
VITE_AUTH_API_URL=https://dev-cross-auth.crosstoken.io
|
|
44
|
-
|
|
45
|
-
# Embedded Wallet Gateway URL (지갑 기능용) — 필수
|
|
46
|
-
VITE_WALLET_GATEWAY_URL=https://dev-embedded-wallet-gateway.crosstoken.io/api/v1
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
> URL은 `SDKConfig`에 노출하지 않습니다. 환경 변수로만 전환 가능합니다. (외부 개발사에는 위 설정을 알리지 않을 예정)
|
|
50
|
-
|
|
51
|
-
---
|
|
16
|
+
**Peer dependency:** `react ^18.0.0`
|
|
52
17
|
|
|
53
18
|
## Quick Start
|
|
54
19
|
|
|
55
|
-
### 1.
|
|
56
|
-
|
|
57
|
-
앱 최상위에 `CROSSxProvider`를 배치합니다. `config`에는 `SDKConfig` 객체를 전달합니다.
|
|
20
|
+
### 1. Wrap your app with `CROSSxProvider`
|
|
58
21
|
|
|
59
22
|
```tsx
|
|
60
|
-
// main.tsx
|
|
61
|
-
import React from 'react';
|
|
62
|
-
import ReactDOM from 'react-dom/client';
|
|
63
23
|
import { CROSSxProvider } from '@nexus-cross/crossx-sdk-react';
|
|
64
|
-
import App from './App';
|
|
65
24
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
25
|
+
const config = {
|
|
26
|
+
projectId: 'your-project-id',
|
|
27
|
+
appName: 'My DApp',
|
|
28
|
+
theme: 'light' as const,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function App() {
|
|
32
|
+
return (
|
|
33
|
+
<CROSSxProvider config={config}>
|
|
34
|
+
<YourApp />
|
|
70
35
|
</CROSSxProvider>
|
|
71
|
-
|
|
72
|
-
|
|
36
|
+
);
|
|
37
|
+
}
|
|
73
38
|
```
|
|
74
39
|
|
|
75
|
-
|
|
76
|
-
기존 세션이 있으면 자동으로 복원됩니다.
|
|
40
|
+
The provider automatically calls `createCROSSxSDK(config)` → `sdk.initialize()` on mount, restoring any existing session.
|
|
77
41
|
|
|
78
|
-
### 2.
|
|
42
|
+
### 2. Sign in / Sign out — `useAuth`
|
|
79
43
|
|
|
80
44
|
```tsx
|
|
81
45
|
import { useAuth } from '@nexus-cross/crossx-sdk-react';
|
|
@@ -83,20 +47,20 @@ import { useAuth } from '@nexus-cross/crossx-sdk-react';
|
|
|
83
47
|
function LoginButton() {
|
|
84
48
|
const { signIn, signOut, isAuthenticated, isLoading, error } = useAuth();
|
|
85
49
|
|
|
86
|
-
if (isLoading) return <p
|
|
50
|
+
if (isLoading) return <p>Loading...</p>;
|
|
87
51
|
|
|
88
52
|
return isAuthenticated ? (
|
|
89
|
-
<button onClick={signOut}
|
|
53
|
+
<button onClick={signOut}>Sign Out</button>
|
|
90
54
|
) : (
|
|
91
55
|
<div>
|
|
92
|
-
<button onClick={signIn}
|
|
56
|
+
<button onClick={signIn}>Sign In</button>
|
|
93
57
|
{error && <p style={{ color: 'red' }}>{error}</p>}
|
|
94
58
|
</div>
|
|
95
59
|
);
|
|
96
60
|
}
|
|
97
61
|
```
|
|
98
62
|
|
|
99
|
-
### 3.
|
|
63
|
+
### 3. Sign & Send — `useWallet`
|
|
100
64
|
|
|
101
65
|
```tsx
|
|
102
66
|
import { useWallet } from '@nexus-cross/crossx-sdk-react';
|
|
@@ -106,38 +70,33 @@ function WalletActions() {
|
|
|
106
70
|
const { address, signMessage, sendTransaction, isLoading, error } = useWallet();
|
|
107
71
|
|
|
108
72
|
const handleSign = async () => {
|
|
109
|
-
// chainId는 CAIP-2 형식 문자열 (예: 'eip155:612055')
|
|
110
73
|
const result = await signMessage(ChainId.CROSS_MAINNET, 'Hello CROSSx!');
|
|
111
|
-
console.log('
|
|
74
|
+
console.log('Signature:', result.signature);
|
|
112
75
|
};
|
|
113
76
|
|
|
114
77
|
const handleSend = async () => {
|
|
115
78
|
const result = await sendTransaction(ChainId.CROSS_MAINNET, {
|
|
116
79
|
from: address!,
|
|
117
|
-
to: '
|
|
118
|
-
value: '0x2386f26fc10000',
|
|
119
|
-
gasLimit: '0x5208',
|
|
120
|
-
maxFeePerGas: '0x77359400',
|
|
121
|
-
maxPriorityFeePerGas: '0x3b9aca00',
|
|
80
|
+
to: '0x...',
|
|
81
|
+
value: '0x2386f26fc10000',
|
|
122
82
|
});
|
|
123
83
|
console.log('txHash:', result.txHash);
|
|
124
84
|
};
|
|
125
85
|
|
|
126
86
|
return (
|
|
127
87
|
<div>
|
|
128
|
-
<p
|
|
129
|
-
<button onClick={handleSign} disabled={isLoading}
|
|
130
|
-
<button onClick={handleSend} disabled={isLoading}
|
|
88
|
+
<p>Address: {address ?? '—'}</p>
|
|
89
|
+
<button onClick={handleSign} disabled={isLoading}>Sign Message</button>
|
|
90
|
+
<button onClick={handleSend} disabled={isLoading}>Send Transaction</button>
|
|
131
91
|
{error && <p style={{ color: 'red' }}>{error}</p>}
|
|
132
92
|
</div>
|
|
133
93
|
);
|
|
134
94
|
}
|
|
135
95
|
```
|
|
136
96
|
|
|
137
|
-
### 4. SDK
|
|
97
|
+
### 4. Direct SDK access — `useCROSSx`
|
|
138
98
|
|
|
139
|
-
|
|
140
|
-
`useCROSSx`로 SDK 인스턴스에 직접 접근합니다.
|
|
99
|
+
For features not covered by hooks (balance, nonce, RPC, typed data signing, etc.), access the SDK instance directly.
|
|
141
100
|
|
|
142
101
|
```tsx
|
|
143
102
|
import { useCROSSx } from '@nexus-cross/crossx-sdk-react';
|
|
@@ -148,67 +107,28 @@ function AdvancedPanel() {
|
|
|
148
107
|
const handleGetBalance = async () => {
|
|
149
108
|
if (!sdk) return;
|
|
150
109
|
const { formatted } = await sdk.getBalance('eip155:612055');
|
|
151
|
-
console.log('
|
|
110
|
+
console.log('Balance:', formatted);
|
|
152
111
|
};
|
|
153
112
|
|
|
154
113
|
const handleSignTypedData = async () => {
|
|
155
114
|
if (!sdk) return;
|
|
156
115
|
const result = await sdk.signTypedData('eip155:612055', {
|
|
157
|
-
types: {
|
|
158
|
-
EIP712Domain: [
|
|
159
|
-
{ name: 'name', type: 'string' },
|
|
160
|
-
{ name: 'version', type: 'string' },
|
|
161
|
-
{ name: 'chainId', type: 'uint256' },
|
|
162
|
-
{ name: 'verifyingContract', type: 'address' },
|
|
163
|
-
],
|
|
164
|
-
Permit: [
|
|
165
|
-
{ name: 'owner', type: 'address' },
|
|
166
|
-
{ name: 'spender', type: 'address' },
|
|
167
|
-
{ name: 'value', type: 'uint256' },
|
|
168
|
-
{ name: 'nonce', type: 'uint256' },
|
|
169
|
-
{ name: 'deadline', type: 'uint256' },
|
|
170
|
-
],
|
|
171
|
-
},
|
|
116
|
+
types: { /* EIP-712 type definitions */ },
|
|
172
117
|
primaryType: 'Permit',
|
|
173
|
-
domain: {
|
|
174
|
-
|
|
175
|
-
version: '1',
|
|
176
|
-
chainId: 612055,
|
|
177
|
-
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
|
|
178
|
-
},
|
|
179
|
-
message: {
|
|
180
|
-
owner: walletAddress,
|
|
181
|
-
spender: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
|
|
182
|
-
value: '1000000000000000000',
|
|
183
|
-
nonce: '0',
|
|
184
|
-
deadline: '1234567890',
|
|
185
|
-
},
|
|
118
|
+
domain: { /* domain separator */ },
|
|
119
|
+
message: { /* typed message */ },
|
|
186
120
|
});
|
|
187
|
-
console.log('
|
|
121
|
+
console.log('Signature:', result.signature);
|
|
188
122
|
};
|
|
189
123
|
|
|
190
|
-
|
|
191
|
-
if (!sdk) return;
|
|
192
|
-
// eth_call로 ERC-20 balanceOf 직접 호출
|
|
193
|
-
const data = '0x70a08231000000000000000000000000' +
|
|
194
|
-
walletAddress!.slice(2).toLowerCase().padStart(64, '0');
|
|
195
|
-
const raw = await sdk.walletRpc(
|
|
196
|
-
'eth_call',
|
|
197
|
-
[{ to: '0x9f85c7b5d7637e18f946cc8af9c131318c6833d9', data }, 'latest'],
|
|
198
|
-
'eip155:612044'
|
|
199
|
-
);
|
|
200
|
-
console.log('balanceOf result:', raw);
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
if (!isInitialized) return <p>초기화 중...</p>;
|
|
124
|
+
if (!isInitialized) return <p>Initializing...</p>;
|
|
204
125
|
|
|
205
126
|
return (
|
|
206
127
|
<div>
|
|
207
|
-
<p
|
|
208
|
-
<p
|
|
209
|
-
<button onClick={handleGetBalance}
|
|
210
|
-
<button onClick={handleSignTypedData}>EIP-712
|
|
211
|
-
<button onClick={handleRpcCall}>eth_call (tUSDT)</button>
|
|
128
|
+
<p>Authenticated: {isAuthenticated ? 'Yes' : 'No'}</p>
|
|
129
|
+
<p>Address: {walletAddress ?? '—'}</p>
|
|
130
|
+
<button onClick={handleGetBalance}>Get Balance</button>
|
|
131
|
+
<button onClick={handleSignTypedData}>EIP-712 Sign</button>
|
|
212
132
|
</div>
|
|
213
133
|
);
|
|
214
134
|
}
|
|
@@ -220,147 +140,108 @@ function AdvancedPanel() {
|
|
|
220
140
|
|
|
221
141
|
### `<CROSSxProvider>`
|
|
222
142
|
|
|
223
|
-
| Prop |
|
|
224
|
-
|
|
225
|
-
| `config` | `SDKConfig` | SDK
|
|
226
|
-
| `children` | `ReactNode` |
|
|
227
|
-
|
|
228
|
-
`SDKConfig` 주요 필드:
|
|
143
|
+
| Prop | Type | Description |
|
|
144
|
+
|------|------|-------------|
|
|
145
|
+
| `config` | `SDKConfig` | SDK configuration object |
|
|
146
|
+
| `children` | `ReactNode` | Child components |
|
|
229
147
|
|
|
230
|
-
|
|
231
|
-
|------|------|--------|------|
|
|
232
|
-
| `theme` | `'light' \| 'dark'` | `'light'` | 확인 모달 테마 |
|
|
233
|
-
| `themeTokens` | `ConfirmationTokenOverride` | — | 모달 색상 커스터마이징 |
|
|
234
|
-
| `oauthDisplayMode` | `'popup' \| 'modal'` | `'popup'` | OAuth 로그인 표시 방식 |
|
|
235
|
-
| `useMockWallet` | `boolean` | `false` | Mock 지갑 사용 (개발용) |
|
|
236
|
-
| `debug` | `boolean` | `true` | 디버그 로그 출력 |
|
|
148
|
+
Key `SDKConfig` fields:
|
|
237
149
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
`ConfirmationThemeTokens` 오버라이드 가능 필드:
|
|
248
|
-
|
|
249
|
-
| 필드 | Semantic 토큰 | 기본값 (light / dark) |
|
|
250
|
-
|------|------|------|
|
|
251
|
-
| `primary` | Primary | `#019D92` / `#019D92` |
|
|
252
|
-
| `secondary` | Secondary | `#E70077` / `#E70077` |
|
|
253
|
-
| `onPrimary` | OnPrimary | `#FFFFFF` / `#FFFFFF` |
|
|
254
|
-
| `borderDefault` | Border/Default | `rgba(18,18,18,0.05)` / `rgba(255,255,255,0.05)` |
|
|
255
|
-
| `borderSubtle` | Border/Subtle | `rgba(18,18,18,0.1)` / `rgba(255,255,255,0.1)` |
|
|
256
|
-
| `textPrimary` | TextIcon/Primary | `#121212` / `#FFFFFF` |
|
|
257
|
-
| `textSecondary` | TextIcon/Secondary | `rgba(18,18,18,0.7)` / `rgba(255,255,255,0.7)` |
|
|
258
|
-
| `textTertiary` | TextIcon/Tertiary | `rgba(18,18,18,0.5)` / `rgba(255,255,255,0.5)` |
|
|
259
|
-
| `surfaceDefault` | Surface/default | `rgba(18,18,18,0.05)` / `rgba(255,255,255,0.05)` |
|
|
260
|
-
| `bg` | Surface/BG | `#FFFFFF` / `#121212` |
|
|
150
|
+
| Field | Type | Default | Description |
|
|
151
|
+
|-------|------|---------|-------------|
|
|
152
|
+
| `projectId` | `string` | — | **Required.** Project ID from the management console |
|
|
153
|
+
| `appName` | `string` | — | **Required.** App name shown in confirmation modals |
|
|
154
|
+
| `theme` | `'light' \| 'dark'` | `'light'` | Confirmation modal theme |
|
|
155
|
+
| `autoDetectTheme` | `boolean` | `false` | Follow OS dark mode setting |
|
|
156
|
+
| `themeTokens` | `SDKThemeTokens` | — | Per-mode color overrides |
|
|
157
|
+
| `locale` | `'en' \| 'ko'` | `'en'` | Modal UI language |
|
|
158
|
+
| `debug` | `boolean` | `true` | Debug logging (dev builds only) |
|
|
261
159
|
|
|
262
160
|
---
|
|
263
161
|
|
|
264
162
|
### `useAuth()`
|
|
265
163
|
|
|
266
|
-
|
|
164
|
+
Authentication state and actions.
|
|
267
165
|
|
|
268
166
|
```ts
|
|
269
167
|
const {
|
|
270
|
-
isAuthenticated, // boolean
|
|
271
|
-
isLoading, // boolean
|
|
272
|
-
error, // string | null
|
|
273
|
-
signIn, // () => Promise<AuthResult>
|
|
274
|
-
signOut, // () => Promise<void>
|
|
168
|
+
isAuthenticated, // boolean
|
|
169
|
+
isLoading, // boolean
|
|
170
|
+
error, // string | null
|
|
171
|
+
signIn, // () => Promise<AuthResult>
|
|
172
|
+
signOut, // () => Promise<void>
|
|
275
173
|
} = useAuth();
|
|
276
174
|
```
|
|
277
175
|
|
|
278
|
-
`signIn()` 호출 시 OAuth 팝업/모달이 열립니다.
|
|
279
|
-
성공하면 내부적으로 `window.location.reload()`가 호출되어 Provider 상태가 갱신됩니다.
|
|
280
|
-
|
|
281
176
|
---
|
|
282
177
|
|
|
283
178
|
### `useWallet()`
|
|
284
179
|
|
|
285
|
-
|
|
180
|
+
Wallet address, message signing, and transaction sending.
|
|
286
181
|
|
|
287
182
|
```ts
|
|
288
183
|
const {
|
|
289
|
-
address, // string | null —
|
|
290
|
-
isLoading, // boolean
|
|
291
|
-
error, // string | null
|
|
292
|
-
signMessage, // (chainId, message) => Promise<
|
|
293
|
-
sendTransaction, // (chainId, tx) => Promise<
|
|
184
|
+
address, // string | null — wallet address (0x...)
|
|
185
|
+
isLoading, // boolean
|
|
186
|
+
error, // string | null
|
|
187
|
+
signMessage, // (chainId, message) => Promise<SignMessageResp>
|
|
188
|
+
sendTransaction, // (chainId, tx) => Promise<SendTxResp>
|
|
294
189
|
} = useWallet();
|
|
295
190
|
```
|
|
296
191
|
|
|
297
192
|
**`signMessage(chainId, message)`**
|
|
298
193
|
|
|
299
|
-
|
|
|
300
|
-
|
|
301
|
-
| `chainId` | `string` | `
|
|
194
|
+
| Parameter | Type | Example |
|
|
195
|
+
|-----------|------|---------|
|
|
196
|
+
| `chainId` | `string` | `ChainId.CROSS_MAINNET` |
|
|
302
197
|
| `message` | `string` | `'Hello CROSSx!'` |
|
|
303
198
|
|
|
304
|
-
|
|
199
|
+
Returns: `{ chainId, signature, message, address }`
|
|
305
200
|
|
|
306
201
|
**`sendTransaction(chainId, tx)`**
|
|
307
202
|
|
|
308
|
-
|
|
|
309
|
-
|
|
310
|
-
| `chainId` | `string` | CAIP-2
|
|
311
|
-
| `tx` | `EvmTransactionRequest` |
|
|
312
|
-
|
|
313
|
-
`EvmTransactionRequest` 주요 필드:
|
|
314
|
-
|
|
315
|
-
| 필드 | 타입 | 필수 | 설명 |
|
|
316
|
-
|------|------|:----:|------|
|
|
317
|
-
| `from` | `string` | O | 보내는 주소 |
|
|
318
|
-
| `to` | `string` | O | 받는 주소 |
|
|
319
|
-
| `value` | `string` | | hex wei (예: `'0x2386f26fc10000'`) |
|
|
320
|
-
| `data` | `string` | | calldata hex |
|
|
321
|
-
| `gasLimit` | `string` | | gas limit hex |
|
|
322
|
-
| `maxFeePerGas` | `string` | | EIP-1559 max fee |
|
|
323
|
-
| `maxPriorityFeePerGas` | `string` | | EIP-1559 priority fee |
|
|
324
|
-
| `nonce` | `number` | | 트랜잭션 순서 |
|
|
203
|
+
| Parameter | Type | Description |
|
|
204
|
+
|-----------|------|-------------|
|
|
205
|
+
| `chainId` | `string` | CAIP-2 chain ID |
|
|
206
|
+
| `tx` | `EvmTransactionRequest` | Transaction object |
|
|
325
207
|
|
|
326
|
-
|
|
208
|
+
Returns: `{ chainId, txHash, status }`
|
|
327
209
|
|
|
328
210
|
---
|
|
329
211
|
|
|
330
212
|
### `useCROSSx()`
|
|
331
213
|
|
|
332
|
-
SDK
|
|
214
|
+
Direct access to the SDK instance and global state.
|
|
333
215
|
|
|
334
216
|
```ts
|
|
335
217
|
const {
|
|
336
|
-
sdk, // CROSSxSDK | null
|
|
337
|
-
isInitialized, // boolean
|
|
338
|
-
isAuthenticated, // boolean
|
|
339
|
-
walletAddress, // string | null
|
|
218
|
+
sdk, // CROSSxSDK | null
|
|
219
|
+
isInitialized, // boolean
|
|
220
|
+
isAuthenticated, // boolean
|
|
221
|
+
walletAddress, // string | null
|
|
340
222
|
} = useCROSSx();
|
|
341
223
|
```
|
|
342
224
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
|
346
|
-
|
|
347
|
-
| `sdk.signMessage(chainId,
|
|
348
|
-
| `sdk.signTypedData(chainId,
|
|
349
|
-
| `sdk.signTransaction(chainId, tx)` |
|
|
350
|
-
| `sdk.sendTransaction(chainId, tx)` |
|
|
351
|
-
| `sdk.
|
|
352
|
-
| `sdk.getBalance(chainId)` |
|
|
353
|
-
| `sdk.getNonce(chainId)` |
|
|
354
|
-
| `sdk.walletRpc(method, params, chainId)` |
|
|
355
|
-
| `sdk.getProvider(chainId)` | EIP-1193
|
|
356
|
-
| `sdk.createWallet()` |
|
|
357
|
-
| `sdk.
|
|
225
|
+
Available methods via `sdk`:
|
|
226
|
+
|
|
227
|
+
| Method | Description |
|
|
228
|
+
|--------|-------------|
|
|
229
|
+
| `sdk.signMessage(chainId, msg)` | EIP-191 personal sign |
|
|
230
|
+
| `sdk.signTypedData(chainId, data)` | EIP-712 typed data sign |
|
|
231
|
+
| `sdk.signTransaction(chainId, tx)` | Sign without broadcasting |
|
|
232
|
+
| `sdk.sendTransaction(chainId, tx)` | Sign + broadcast |
|
|
233
|
+
| `sdk.sendTransactionWithWaitForReceipt(chainId, tx)` | Send + poll receipt |
|
|
234
|
+
| `sdk.getBalance(chainId)` | Native balance |
|
|
235
|
+
| `sdk.getNonce(chainId)` | Current nonce |
|
|
236
|
+
| `sdk.walletRpc(method, params, chainId)` | Generic JSON-RPC |
|
|
237
|
+
| `sdk.getProvider(chainId)` | EIP-1193 provider |
|
|
238
|
+
| `sdk.createWallet()` | Manual wallet creation |
|
|
239
|
+
| `sdk.selectWallet()` | Open wallet selector |
|
|
240
|
+
| `sdk.applyTheme('dark')` | Runtime theme switch |
|
|
358
241
|
|
|
359
242
|
---
|
|
360
243
|
|
|
361
|
-
##
|
|
362
|
-
|
|
363
|
-
체인 ID 오타 방지를 위한 상수를 제공합니다.
|
|
244
|
+
## Chain ID Constants
|
|
364
245
|
|
|
365
246
|
```ts
|
|
366
247
|
import { ChainId } from '@nexus-cross/crossx-sdk-react';
|
|
@@ -371,100 +252,66 @@ ChainId.CROSS_TESTNET // 'eip155:612044'
|
|
|
371
252
|
|
|
372
253
|
---
|
|
373
254
|
|
|
374
|
-
##
|
|
375
|
-
|
|
376
|
-
| | `@nexus-cross/crossx-sdk-react` | `@nexus-cross/crossx-sdk-wagmi` |
|
|
377
|
-
|---|---|---|
|
|
378
|
-
| **의존성** | React만 필요 | wagmi + viem + @tanstack/react-query |
|
|
379
|
-
| **접근 방식** | CROSSx 전용 hooks | wagmi 표준 hooks (`useAccount`, `useConnect` 등) |
|
|
380
|
-
| **EIP-1193** | 필요 시 `sdk.getProvider()` | 자동 제공 (wagmi connector) |
|
|
381
|
-
| **적합 대상** | CROSSx 지갑만 사용하는 앱 | 멀티 지갑(MetaMask 등) 지원 앱 |
|
|
382
|
-
|
|
383
|
-
wagmi를 사용하는 경우 `@nexus-cross/crossx-sdk-wagmi`의 `createCROSSxConnector`를 사용하세요.
|
|
384
|
-
wagmi 예제는 `examples/wagmi-app`을 참고하세요.
|
|
385
|
-
|
|
386
|
-
---
|
|
387
|
-
|
|
388
|
-
## 확인 모달 (Confirmation)
|
|
255
|
+
## Confirmation Modal
|
|
389
256
|
|
|
390
|
-
|
|
257
|
+
All sign/send operations automatically display an approval modal:
|
|
391
258
|
|
|
392
|
-
- **Message Sign** — "Signature Request"
|
|
393
|
-
- **EIP-712 Typed Data** —
|
|
394
|
-
- **Transaction
|
|
259
|
+
- **Message Sign** — "Signature Request" modal
|
|
260
|
+
- **EIP-712 Typed Data** — Structured key-value display
|
|
261
|
+
- **Transaction** — Recipient, amount, and fee details
|
|
395
262
|
|
|
396
|
-
|
|
263
|
+
On mobile (≤480px), the modal automatically renders as a bottom sheet.
|
|
397
264
|
|
|
398
|
-
###
|
|
265
|
+
### Theme Customization
|
|
399
266
|
|
|
400
|
-
**초기화 시 고정:**
|
|
401
267
|
```tsx
|
|
268
|
+
// At initialization
|
|
402
269
|
<CROSSxProvider config={{ theme: 'dark' }}>
|
|
403
|
-
```
|
|
404
270
|
|
|
405
|
-
|
|
406
|
-
```ts
|
|
271
|
+
// Runtime switch
|
|
407
272
|
const { sdk } = useCROSSx();
|
|
408
|
-
sdk?.
|
|
273
|
+
sdk?.applyTheme('dark');
|
|
274
|
+
|
|
275
|
+
// Custom colors
|
|
276
|
+
<CROSSxProvider config={{
|
|
277
|
+
theme: 'light',
|
|
278
|
+
themeTokens: {
|
|
279
|
+
light: { primary: '#FF6B35', bg: '#F5F0EB' },
|
|
280
|
+
dark: { primary: '#FF6B35', bg: '#1A0A00' },
|
|
281
|
+
},
|
|
282
|
+
}}>
|
|
409
283
|
```
|
|
410
284
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
`themeTokens.light` / `themeTokens.dark` 로 각 모드를 독립적으로 오버라이드합니다.
|
|
414
|
-
지정하지 않은 항목은 해당 모드의 기본값을 유지합니다.
|
|
415
|
-
|
|
416
|
-
```tsx
|
|
417
|
-
<CROSSxProvider
|
|
418
|
-
config={{
|
|
419
|
-
theme: 'light',
|
|
420
|
-
themeTokens: {
|
|
421
|
-
light: {
|
|
422
|
-
primary: '#FF6B35', // 버튼·강조색 (기본: #019D92)
|
|
423
|
-
bg: '#F5F0EB', // 카드 배경색 (기본: #FFFFFF)
|
|
424
|
-
},
|
|
425
|
-
dark: {
|
|
426
|
-
primary: '#FF6B35',
|
|
427
|
-
bg: '#1A0A00', // 카드 배경색 (기본: #121212)
|
|
428
|
-
},
|
|
429
|
-
},
|
|
430
|
-
}}
|
|
431
|
-
>
|
|
432
|
-
```
|
|
285
|
+
---
|
|
433
286
|
|
|
434
|
-
|
|
287
|
+
## Comparison with wagmi Package
|
|
435
288
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
289
|
+
| | `@nexus-cross/crossx-sdk-react` | `@nexus-cross/crossx-sdk-wagmi` |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| **Dependencies** | React only | wagmi + viem + @tanstack/react-query |
|
|
292
|
+
| **Approach** | CROSSx-specific hooks | wagmi standard hooks (`useAccount`, etc.) |
|
|
293
|
+
| **EIP-1193** | Via `sdk.getProvider()` | Automatic (wagmi connector) |
|
|
294
|
+
| **Best for** | CROSSx-only apps | Multi-wallet apps (MetaMask, etc.) |
|
|
440
295
|
|
|
441
296
|
---
|
|
442
297
|
|
|
443
|
-
##
|
|
298
|
+
## Troubleshooting
|
|
444
299
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
Embedded Wallet로 마이그레이션됩니다.
|
|
300
|
+
**`useCROSSx must be used within CROSSxProvider`**
|
|
301
|
+
Wrap your app root with `<CROSSxProvider>`.
|
|
448
302
|
|
|
449
|
-
|
|
303
|
+
**OAuth popup doesn't open**
|
|
304
|
+
Check browser popup blocker, or use `config.oauthDisplayMode = 'modal'`.
|
|
450
305
|
|
|
451
306
|
---
|
|
452
307
|
|
|
453
|
-
##
|
|
454
|
-
|
|
455
|
-
### `useCROSSx must be used within CROSSxProvider`
|
|
456
|
-
앱 최상위에 `<CROSSxProvider>`가 빠져있습니다.
|
|
308
|
+
## Related Packages
|
|
457
309
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
### 로그인 후 상태가 업데이트되지 않음
|
|
463
|
-
현재 `useAuth().signIn()`은 성공 시 `window.location.reload()`를 호출합니다.
|
|
464
|
-
SPA 라우터와 충돌하는 경우 `useCROSSx()`로 직접 상태를 관리하세요.
|
|
465
|
-
|
|
466
|
-
---
|
|
310
|
+
| Package | Description |
|
|
311
|
+
|---------|-------------|
|
|
312
|
+
| [`@nexus-cross/crossx-sdk-core`](https://www.npmjs.com/package/@nexus-cross/crossx-sdk-core) | Core SDK (vanilla JS) |
|
|
313
|
+
| [`@nexus-cross/crossx-sdk-wagmi`](https://www.npmjs.com/package/@nexus-cross/crossx-sdk-wagmi) | wagmi connector |
|
|
467
314
|
|
|
468
|
-
##
|
|
315
|
+
## License
|
|
469
316
|
|
|
470
317
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexus-cross/crossx-sdk-react",
|
|
3
|
-
"version": "2.0.2
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "CROSSx React SDK - React Hooks and Components for Embedded Wallet",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"react": "^18.0.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@nexus-cross/crossx-sdk-core": "2.0.2
|
|
36
|
+
"@nexus-cross/crossx-sdk-core": "2.0.2"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/react": "^18.2.48",
|