@nexus-cross/crossx-sdk-core 0.0.0-beta.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.
Files changed (94) hide show
  1. package/README.md +302 -0
  2. package/dist/__tests__/mocks/MockCryptoPort.d.ts +15 -0
  3. package/dist/__tests__/mocks/MockCryptoPort.d.ts.map +1 -0
  4. package/dist/__tests__/mocks/MockOAuthPort.d.ts +11 -0
  5. package/dist/__tests__/mocks/MockOAuthPort.d.ts.map +1 -0
  6. package/dist/__tests__/mocks/MockStoragePort.d.ts +18 -0
  7. package/dist/__tests__/mocks/MockStoragePort.d.ts.map +1 -0
  8. package/dist/__tests__/mocks/MockTransportPort.d.ts +14 -0
  9. package/dist/__tests__/mocks/MockTransportPort.d.ts.map +1 -0
  10. package/dist/__tests__/mocks/MockWalletProviderPort.d.ts +28 -0
  11. package/dist/__tests__/mocks/MockWalletProviderPort.d.ts.map +1 -0
  12. package/dist/__tests__/sdk/CROSSxSDK.test.d.ts +2 -0
  13. package/dist/__tests__/sdk/CROSSxSDK.test.d.ts.map +1 -0
  14. package/dist/__tests__/sdk/EthereumProvider.test.d.ts +2 -0
  15. package/dist/__tests__/sdk/EthereumProvider.test.d.ts.map +1 -0
  16. package/dist/__tests__/usecases/SignInUseCase.test.d.ts +2 -0
  17. package/dist/__tests__/usecases/SignInUseCase.test.d.ts.map +1 -0
  18. package/dist/__tests__/usecases/SignOutUseCase.test.d.ts +2 -0
  19. package/dist/__tests__/usecases/SignOutUseCase.test.d.ts.map +1 -0
  20. package/dist/__tests__/usecases/WithdrawUseCase.test.d.ts +2 -0
  21. package/dist/__tests__/usecases/WithdrawUseCase.test.d.ts.map +1 -0
  22. package/dist/adapters/confirmation/BrowserConfirmationAdapter.d.ts +36 -0
  23. package/dist/adapters/confirmation/BrowserConfirmationAdapter.d.ts.map +1 -0
  24. package/dist/adapters/crypto/JoseCryptoAdapter.d.ts +16 -0
  25. package/dist/adapters/crypto/JoseCryptoAdapter.d.ts.map +1 -0
  26. package/dist/adapters/index.d.ts +10 -0
  27. package/dist/adapters/index.d.ts.map +1 -0
  28. package/dist/adapters/oauth/BrowserOAuthAdapter.d.ts +7 -0
  29. package/dist/adapters/oauth/BrowserOAuthAdapter.d.ts.map +1 -0
  30. package/dist/adapters/storage/LocalStorageAdapter.d.ts +10 -0
  31. package/dist/adapters/storage/LocalStorageAdapter.d.ts.map +1 -0
  32. package/dist/adapters/transport/FetchTransportAdapter.d.ts +6 -0
  33. package/dist/adapters/transport/FetchTransportAdapter.d.ts.map +1 -0
  34. package/dist/adapters/wallet/MockWalletProviderAdapter.d.ts +28 -0
  35. package/dist/adapters/wallet/MockWalletProviderAdapter.d.ts.map +1 -0
  36. package/dist/adapters/wallet/RemoteWalletProviderAdapter.d.ts +47 -0
  37. package/dist/adapters/wallet/RemoteWalletProviderAdapter.d.ts.map +1 -0
  38. package/dist/adapters/wallet/types.d.ts +112 -0
  39. package/dist/adapters/wallet/types.d.ts.map +1 -0
  40. package/dist/core/index.d.ts +9 -0
  41. package/dist/core/index.d.ts.map +1 -0
  42. package/dist/core/ports/ConfirmationPort.d.ts +74 -0
  43. package/dist/core/ports/ConfirmationPort.d.ts.map +1 -0
  44. package/dist/core/ports/CryptoPort.d.ts +43 -0
  45. package/dist/core/ports/CryptoPort.d.ts.map +1 -0
  46. package/dist/core/ports/LoggerPort.d.ts +23 -0
  47. package/dist/core/ports/LoggerPort.d.ts.map +1 -0
  48. package/dist/core/ports/OAuthPort.d.ts +18 -0
  49. package/dist/core/ports/OAuthPort.d.ts.map +1 -0
  50. package/dist/core/ports/StoragePort.d.ts +25 -0
  51. package/dist/core/ports/StoragePort.d.ts.map +1 -0
  52. package/dist/core/ports/TransportPort.d.ts +24 -0
  53. package/dist/core/ports/TransportPort.d.ts.map +1 -0
  54. package/dist/core/ports/WalletProviderPort.d.ts +106 -0
  55. package/dist/core/ports/WalletProviderPort.d.ts.map +1 -0
  56. package/dist/core/ports/index.d.ts +12 -0
  57. package/dist/core/ports/index.d.ts.map +1 -0
  58. package/dist/core/services/TokenMemoryStore.d.ts +17 -0
  59. package/dist/core/services/TokenMemoryStore.d.ts.map +1 -0
  60. package/dist/core/types/caip.d.ts +119 -0
  61. package/dist/core/types/caip.d.ts.map +1 -0
  62. package/dist/core/types/chain.d.ts +90 -0
  63. package/dist/core/types/chain.d.ts.map +1 -0
  64. package/dist/core/types/errors.d.ts +56 -0
  65. package/dist/core/types/errors.d.ts.map +1 -0
  66. package/dist/core/types/index.d.ts +309 -0
  67. package/dist/core/types/index.d.ts.map +1 -0
  68. package/dist/core/types/prepare.d.ts +21 -0
  69. package/dist/core/types/prepare.d.ts.map +1 -0
  70. package/dist/core/usecases/MigrateWalletUseCase.d.ts +10 -0
  71. package/dist/core/usecases/MigrateWalletUseCase.d.ts.map +1 -0
  72. package/dist/core/usecases/SignInUseCase.d.ts +38 -0
  73. package/dist/core/usecases/SignInUseCase.d.ts.map +1 -0
  74. package/dist/core/usecases/SignOutUseCase.d.ts +10 -0
  75. package/dist/core/usecases/SignOutUseCase.d.ts.map +1 -0
  76. package/dist/core/usecases/WithdrawUseCase.d.ts +11 -0
  77. package/dist/core/usecases/WithdrawUseCase.d.ts.map +1 -0
  78. package/dist/core/usecases/index.d.ts +9 -0
  79. package/dist/core/usecases/index.d.ts.map +1 -0
  80. package/dist/core/utils/apiUrl.d.ts +16 -0
  81. package/dist/core/utils/apiUrl.d.ts.map +1 -0
  82. package/dist/core/utils/logger.d.ts +19 -0
  83. package/dist/core/utils/logger.d.ts.map +1 -0
  84. package/dist/index.cjs +939 -0
  85. package/dist/index.d.ts +14 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.js +4773 -0
  88. package/dist/sdk/CROSSxSDK.d.ts +278 -0
  89. package/dist/sdk/CROSSxSDK.d.ts.map +1 -0
  90. package/dist/sdk/EthereumProvider.d.ts +32 -0
  91. package/dist/sdk/EthereumProvider.d.ts.map +1 -0
  92. package/dist/sdk/factory.d.ts +8 -0
  93. package/dist/sdk/factory.d.ts.map +1 -0
  94. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,302 @@
1
+ # @nexus-cross/crossx-sdk-core
2
+
3
+ CROSSx Embedded Wallet SDK — Clean Architecture + Hexagonal Architecture 기반
4
+
5
+ ## 특징
6
+
7
+ - **EIP-1193 Provider**: ethers.js / viem / wagmi 와 바로 연동
8
+ - **Clean Architecture**: 순수 비즈니스 로직과 구현 분리
9
+ - **환경 독립적**: Web / Node / React Native 모두 지원 가능
10
+ - **Port & Adapters**: 구현체를 교체해도 core 코드 변경 없음
11
+ - **CAIP-2**: 표준 체인 ID 형식 (`eip155:612044`)
12
+ - **트랜잭션 컨펌 모달**: 서명/전송 전 사용자 승인 필수 (우회 불가)
13
+
14
+ ## 설치
15
+
16
+ ```bash
17
+ npm install @nexus-cross/crossx-sdk-core
18
+ ```
19
+
20
+ ## 빠른 시작
21
+
22
+ ```ts
23
+ import { createCROSSxSDK, ChainId } from '@nexus-cross/crossx-sdk-core';
24
+
25
+ const sdk = createCROSSxSDK({
26
+ receiptPolling: { intervalMs: 2000, timeoutMs: 60000 }, // 선택
27
+ });
28
+
29
+ await sdk.init();
30
+ const result = await sdk.signIn();
31
+ console.log('지갑 주소:', sdk.getAddress());
32
+ ```
33
+
34
+ > 백엔드 URL은 `.env`의 `VITE_*` 환경 변수로만 설정합니다.
35
+ > `SDKConfig`에 URL 필드를 추가하거나 직접 전달하지 마세요.
36
+
37
+ ---
38
+
39
+ ## API 레퍼런스
40
+
41
+ ### 초기화 & 인증
42
+
43
+ ```ts
44
+ // SDK 초기화 (자동 로그인 복구 포함)
45
+ await sdk.init();
46
+
47
+ // 로그인 (OAuth popup)
48
+ const result = await sdk.signIn();
49
+ const result = await sdk.signIn({ provider: 'google' });
50
+
51
+ // 인증 상태 확인
52
+ sdk.isAuthenticated(); // boolean
53
+ sdk.getAddress(); // string | null
54
+
55
+ // 로그아웃
56
+ await sdk.signOut();
57
+
58
+ // 계정 탈퇴
59
+ await sdk.withdraw();
60
+ ```
61
+
62
+ ---
63
+
64
+ ### 지갑
65
+
66
+ ```ts
67
+ // 지갑 생성 (로그인 후 지갑이 없을 때)
68
+ const { address } = await sdk.createWallet();
69
+
70
+ // 네이티브 잔액 조회
71
+ const { wei, formatted } = await sdk.getBalance('eip155:612044');
72
+ console.log(formatted); // "1.234567 CROSS"
73
+
74
+ // 현재 nonce 조회
75
+ const nonce = await sdk.getNonce('eip155:612044');
76
+ ```
77
+
78
+ ---
79
+
80
+ ### 트랜잭션 컨펌 모달
81
+
82
+ `signTransaction()` / `sendTransaction()` / `sendTransactionAndWait()` 호출 시 SDK가 자동으로 사용자 승인 모달을 표시합니다. DApp 개발자가 우회할 수 있는 공개 API는 없습니다.
83
+
84
+ ```ts
85
+ import { CROSSxError, ErrorCode } from '@nexus-cross/crossx-sdk-core';
86
+
87
+ try {
88
+ const result = await sdk.signTransaction(ChainId.CROSS_TESTNET, tx);
89
+ } catch (error) {
90
+ if (error instanceof CROSSxError && error.code === ErrorCode.USER_REJECTED) {
91
+ console.log('사용자가 취소했습니다');
92
+ }
93
+ }
94
+ ```
95
+
96
+ > 자세한 내용 → [트랜잭션 컨펌 모달 가이드](../../doc/transaction-confirmation.md)
97
+
98
+ ---
99
+
100
+ ### 트랜잭션 서명 & 전송
101
+
102
+ ```ts
103
+ const tx = {
104
+ from: sdk.getAddress()!,
105
+ to: '0x...',
106
+ value: '0x2386f26fc10000',
107
+ data: '0x',
108
+ chainId: 612044,
109
+ gasLimit: '0x5208',
110
+ maxFeePerGas: '0x77359400',
111
+ maxPriorityFeePerGas: '0x3b9aca00',
112
+ nonce: await sdk.getNonce('eip155:612044'),
113
+ };
114
+
115
+ // 서명만
116
+ const { signedTx, txHash } = await sdk.signTransaction('eip155:612044', tx);
117
+
118
+ // 전송 (status: 'pending' 즉시 반환)
119
+ const { txHash } = await sdk.sendTransaction('eip155:612044', tx);
120
+
121
+ // 전송 + Receipt 폴링 (블록 포함까지 대기)
122
+ const { txHash, receipt } = await sdk.sendTransactionAndWait('eip155:612044', tx);
123
+ console.log(receipt.status); // '0x1' = success, '0x0' = reverted
124
+ ```
125
+
126
+ ---
127
+
128
+ ### Receipt 조회 & 폴링
129
+
130
+ ```ts
131
+ // 단일 조회 (채굴 전이면 null)
132
+ const receipt = await sdk.getTransactionReceipt(txHash, 'eip155:612044');
133
+
134
+ // 채굴될 때까지 폴링
135
+ const receipt = await sdk.waitForTransaction(txHash, 'eip155:612044');
136
+
137
+ // 폴링 옵션 오버라이드
138
+ const receipt = await sdk.waitForTransaction(txHash, 'eip155:612044', {
139
+ intervalMs: 3000,
140
+ timeoutMs: 120000,
141
+ });
142
+ ```
143
+
144
+ ---
145
+
146
+ ### EIP-1193 Provider
147
+
148
+ ethers.js, viem, wagmi 등과 연동하기 위한 표준 Provider입니다.
149
+
150
+ ```ts
151
+ const provider = sdk.getProvider('eip155:612044');
152
+
153
+ // ethers.js
154
+ import { ethers } from 'ethers';
155
+ const ethersProvider = new ethers.BrowserProvider(provider);
156
+ const signer = await ethersProvider.getSigner();
157
+ await signer.sendTransaction({ to: '0x...', value: ethers.parseEther('0.01') });
158
+
159
+ // viem
160
+ import { createWalletClient, custom } from 'viem';
161
+ const client = createWalletClient({ transport: custom(provider) });
162
+ ```
163
+
164
+ ---
165
+
166
+ ### 범용 RPC 호출
167
+
168
+ `/wallet/rpc` 엔드포인트를 통해 노드에 직접 JSON-RPC 요청을 보냅니다.
169
+
170
+ ```ts
171
+ // 네이티브 잔액
172
+ const balance = await sdk.rpcRequest('eth_getBalance', [address, 'latest'], 'eip155:612044');
173
+
174
+ // eth_call — ERC-20 balanceOf
175
+ const selector = '70a08231';
176
+ const padded = address.slice(2).padStart(64, '0');
177
+ const raw = await sdk.rpcRequest(
178
+ 'eth_call',
179
+ [{ to: contractAddress, data: '0x' + selector + padded }, 'latest'],
180
+ 'eip155:612044',
181
+ );
182
+ console.log(BigInt(raw).toString());
183
+
184
+ // Provider를 통한 동일 호출
185
+ const result = await provider.request({
186
+ method: 'eth_call',
187
+ params: [{ to: contractAddress, data: '0x' + selector + padded }, 'latest'],
188
+ });
189
+ ```
190
+
191
+ ---
192
+
193
+ ## SDKConfig
194
+
195
+ ```ts
196
+ const sdk = createCROSSxSDK({
197
+ /** OAuth 팝업 방식: 'popup' (기본) | 'modal' */
198
+ oauthDisplayMode: 'popup',
199
+
200
+ /** Mock 지갑 사용 여부 (개발/테스트용) */
201
+ useMockWallet: false,
202
+
203
+ /** 확인 모달 테마: 'light' (기본) | 'dark' */
204
+ theme: 'light',
205
+
206
+ /**
207
+ * 확인 모달 색상 커스터마이징 (light / dark 모드별 독립 오버라이드)
208
+ */
209
+ themeTokens: {
210
+ light: {
211
+ primary: '#FF6B35', // 버튼·강조색 (기본: #019D92)
212
+ bg: '#F5F0EB', // 카드 배경색 (기본: #FFFFFF)
213
+ },
214
+ dark: {
215
+ primary: '#FF6B35',
216
+ bg: '#1A0A00', // 카드 배경색 (기본: #121212)
217
+ },
218
+ },
219
+
220
+ /** Receipt 폴링 기본값 */
221
+ receiptPolling: {
222
+ intervalMs: 2000, // 폴링 간격 (ms)
223
+ timeoutMs: 60000, // 최대 대기 시간 (ms)
224
+ },
225
+
226
+ /**
227
+ * 디버그 로그 출력 여부 (기본: true)
228
+ * ⚠️ 프로덕션 빌드에서는 이 값과 관계없이 항상 비활성화됩니다.
229
+ */
230
+ debug: true,
231
+ });
232
+ ```
233
+
234
+ ### 확인 모달 테마
235
+
236
+ | 방법 | 설명 |
237
+ |---|---|
238
+ | `config.theme` | 초기 테마 설정 (`'light'` 기본) |
239
+ | `sdk.setTheme('dark')` | 런타임 테마 전환 (`themeTokens` 오버라이드 유지) |
240
+ | `config.themeTokens.light.*` | 라이트 모드 Semantic 토큰 오버라이드 |
241
+ | `config.themeTokens.dark.*` | 다크 모드 Semantic 토큰 오버라이드 |
242
+
243
+ 오버라이드 가능한 토큰: `primary` · `secondary` · `onPrimary` · `borderDefault` · `borderSubtle` · `textPrimary` · `textSecondary` · `textTertiary` · `surfaceDefault` · `bg`
244
+
245
+ 자세한 내용은 [컨펌 모달 & Prepare 플로우](../../doc/transaction-confirmation.md#색상-커스터마이징-themetokens)를 참고하세요.
246
+
247
+ ---
248
+
249
+ ## 체인 ID 상수
250
+
251
+ 오타 방지를 위해 `ChainId` 상수를 사용하세요.
252
+
253
+ ```ts
254
+ import { ChainId } from '@nexus-cross/crossx-sdk-core';
255
+
256
+ await sdk.getBalance(ChainId.CROSS_TESTNET); // 'eip155:612044'
257
+ await sdk.getBalance(ChainId.CROSS_MAINNET); // 'eip155:612055'
258
+ ```
259
+
260
+ ---
261
+
262
+ ## 환경 변수
263
+
264
+ | 변수명 | 용도 | 필수 |
265
+ |---|---|---|
266
+ | `VITE_WALLET_GATEWAY_URL` | Wallet Gateway API URL | ✅ |
267
+ | `VITE_OAUTH_SERVICE_URL` | OAuth 서비스 URL | ✅ |
268
+ | `VITE_AUTH_API_URL` | 인증 API URL | ✅ |
269
+
270
+ ---
271
+
272
+ ## 공개 타입
273
+
274
+ ```ts
275
+ import type {
276
+ SDKConfig,
277
+ ConfirmationTokenOverride, // themeTokens 타입 (light/dark 모드별 오버라이드)
278
+ ConfirmationThemeTokens, // 단일 모드 Semantic 토큰 타입
279
+ AuthResult,
280
+ EvmTransactionRequest,
281
+ TransactionResult,
282
+ TransactionWithReceipt, // sendTransactionAndWait() 반환 타입
283
+ TransactionReceipt, // waitForTransaction() 반환 타입
284
+ SignTransactionResult,
285
+ ChainIdValue,
286
+ } from '@nexus-cross/crossx-sdk-core';
287
+ ```
288
+
289
+ ---
290
+
291
+ ## 관련 문서
292
+
293
+ - [트랜잭션 컨펌 모달](../../doc/transaction-confirmation.md)
294
+ - [Ethereum Provider 가이드](../../doc/ethereum-provider.md)
295
+ - [환경 변수 설정](../../doc/environment-variables.md)
296
+ - [CAIP-2 체인 ID 가이드](../../doc/caip-integration.md)
297
+ - [wagmi 통합 가이드](../../doc/wagmi-integration.md)
298
+ - [아키텍처 설명](../../doc/architecture.md)
299
+
300
+ ## 라이센스
301
+
302
+ MIT
@@ -0,0 +1,15 @@
1
+ import { CryptoPort, JWTVerifyResult } from '../../core/ports';
2
+ import { JWTPayload } from '../../core/types';
3
+
4
+ declare const DEFAULT_PAYLOAD: JWTPayload;
5
+ /**
6
+ * CryptoPort mock.
7
+ * 기본적으로 유효한 JWT 검증 결과를 반환합니다.
8
+ * 만료 시나리오 테스트 시 verifyJWT.mockResolvedValueOnce({ valid: false, payload: ... }) 로 오버라이드하세요.
9
+ */
10
+ export declare class MockCryptoPort implements CryptoPort {
11
+ verifyJWT: import('vitest').Mock<(_token: string) => Promise<JWTVerifyResult>>;
12
+ decodeJWT: import('vitest').Mock<(_token: string) => JWTPayload>;
13
+ }
14
+ export { DEFAULT_PAYLOAD };
15
+ //# sourceMappingURL=MockCryptoPort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockCryptoPort.d.ts","sourceRoot":"","sources":["../../../src/__tests__/mocks/MockCryptoPort.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,QAAA,MAAM,eAAe,EAAE,UAKtB,CAAC;AAEF;;;;GAIG;AACH,qBAAa,cAAe,YAAW,UAAU;IAC/C,SAAS,iCAAwB,MAAM,KAAG,OAAO,CAAC,eAAe,CAAC,EAI9D;IAEJ,SAAS,iCAAkB,MAAM,KAAG,UAAU,EAAqB;CACpE;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { OAuthPort, OAuthConfig } from '../../core/ports';
2
+
3
+ /**
4
+ * OAuthPort mock.
5
+ * 기본적으로 'mock-firebase-token' 을 반환합니다.
6
+ * 실패 시나리오는 openAuth.mockRejectedValueOnce(new Error('popup closed')) 로 테스트하세요.
7
+ */
8
+ export declare class MockOAuthPort implements OAuthPort {
9
+ openAuth: import('vitest').Mock<(_config: OAuthConfig) => Promise<string>>;
10
+ }
11
+ //# sourceMappingURL=MockOAuthPort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockOAuthPort.d.ts","sourceRoot":"","sources":["../../../src/__tests__/mocks/MockOAuthPort.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/D;;;;GAIG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,QAAQ,kCAAyB,WAAW,KAAG,OAAO,CAAC,MAAM,CAAC,EAA2B;CAC1F"}
@@ -0,0 +1,18 @@
1
+ import { StoragePort } from '../../core/ports';
2
+
3
+ /**
4
+ * In-memory StoragePort mock.
5
+ * 각 테스트에서 new MockStoragePort() 로 독립적인 인스턴스를 생성하세요.
6
+ */
7
+ export declare class MockStoragePort implements StoragePort {
8
+ private store;
9
+ set<T>(key: string, value: T): Promise<void>;
10
+ get<T>(key: string): Promise<T | null>;
11
+ remove(key: string): Promise<void>;
12
+ clear(): Promise<void>;
13
+ /** 테스트 헬퍼: 현재 저장된 값을 동기적으로 조회 */
14
+ peek<T>(key: string): T | undefined;
15
+ /** 테스트 헬퍼: 저장된 키 목록 */
16
+ keys(): string[];
17
+ }
18
+ //# sourceMappingURL=MockStoragePort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockStoragePort.d.ts","sourceRoot":"","sources":["../../../src/__tests__/mocks/MockStoragePort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,OAAO,CAAC,KAAK,CAA8B;IAErC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAItC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,iCAAiC;IACjC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAInC,uBAAuB;IACvB,IAAI,IAAI,MAAM,EAAE;CAGjB"}
@@ -0,0 +1,14 @@
1
+ import { TransportPort, TransportRequest, TransportResponse } from '../../core/ports';
2
+
3
+ /**
4
+ * vi.fn() 기반 TransportPort mock.
5
+ * request 메서드의 반환값을 테스트마다 mockResolvedValueOnce 로 제어하세요.
6
+ *
7
+ * @example
8
+ * const transport = new MockTransportPort();
9
+ * transport.request.mockResolvedValueOnce({ status: 200, data: { access_token: 'abc' }, headers: {} });
10
+ */
11
+ export declare class MockTransportPort implements TransportPort {
12
+ request: import('vitest').Mock<(_req: TransportRequest) => Promise<TransportResponse>>;
13
+ }
14
+ //# sourceMappingURL=MockTransportPort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockTransportPort.d.ts","sourceRoot":"","sources":["../../../src/__tests__/mocks/MockTransportPort.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE3F;;;;;;;GAOG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,+BAAsB,gBAAgB,KAAG,OAAO,CAAC,iBAAiB,CAAC,EAItE;CACL"}
@@ -0,0 +1,28 @@
1
+ import { WalletProviderPort, WalletData, SignResponse } from '../../core/ports';
2
+ import { AddressInfo, TransactionReceipt } from '../../core/types/chain';
3
+
4
+ export declare const MOCK_ADDRESS = "0xaabbccdd00112233445566778899aabbccddeeff";
5
+ export declare const MOCK_TX_HASH = "0xaa11bb22cc33dd44ee55ff6600112233445566778899aabbccddeeff00112233";
6
+ declare const MOCK_WALLET_DATA: WalletData;
7
+ declare const MOCK_SIGN_RESPONSE: SignResponse;
8
+ declare const MOCK_RECEIPT: TransactionReceipt;
9
+ /**
10
+ * WalletProviderPort mock.
11
+ * 모든 메서드가 vi.fn() 으로 spy 되어 있어 호출 여부/인수 검증이 가능합니다.
12
+ */
13
+ export declare class MockWalletProviderPort implements WalletProviderPort {
14
+ getOrCreateWallet: import('vitest').Mock<(_userId: string) => Promise<WalletData>>;
15
+ getAddress: import('vitest').Mock<(_userId: string, _index: number) => Promise<AddressInfo>>;
16
+ signMessage: import('vitest').Mock<(_userId: string, _chainId: string, _message: string, _index?: number) => Promise<SignResponse>>;
17
+ signTransaction: import('vitest').Mock<(_userId: string, _chainId: string, _tx: any, _index?: number) => Promise<SignResponse>>;
18
+ sendTransaction: import('vitest').Mock<(_userId: string, _chainId: string, _tx: any) => Promise<{
19
+ txHash: string;
20
+ }>>;
21
+ getBalance: import('vitest').Mock<(_userId: string, _chainId: string) => Promise<string>>;
22
+ getTransactionCount: import('vitest').Mock<(_userId: string, _chainId: string) => Promise<number>>;
23
+ getTransactionReceipt: import('vitest').Mock<(_userId: string, _txHash: string) => Promise<TransactionReceipt | null>>;
24
+ rpcRequest: import('vitest').Mock<(_method: string, _params: any[], _chainId: string) => Promise<any>>;
25
+ withdraw: import('vitest').Mock<(_confirmation: string) => Promise<void>>;
26
+ }
27
+ export { MOCK_WALLET_DATA, MOCK_SIGN_RESPONSE, MOCK_RECEIPT };
28
+ //# sourceMappingURL=MockWalletProviderPort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockWalletProviderPort.d.ts","sourceRoot":"","sources":["../../../src/__tests__/mocks/MockWalletProviderPort.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE9E,eAAO,MAAM,YAAY,+CAA+C,CAAC;AACzE,eAAO,MAAM,YAAY,uEAAuE,CAAC;AAEjG,QAAA,MAAM,gBAAgB,EAAE,UAKvB,CAAC;AAIF,QAAA,MAAM,kBAAkB,EAAE,YAKzB,CAAC;AAEF,QAAA,MAAM,YAAY,EAAE,kBAYnB,CAAC;AAEF;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,kBAAkB;IAC/D,iBAAiB,kCAAyB,MAAM,KAAG,OAAO,CAAC,UAAU,CAAC,EAAsB;IAE5F,UAAU,kCAAyB,MAAM,UAAU,MAAM,KAAG,OAAO,CAAC,WAAW,CAAC,EAG5E;IAEJ,WAAW,kCACO,MAAM,YAAY,MAAM,YAAY,MAAM,WAAW,MAAM,KAAG,OAAO,CAAC,YAAY,CAAC,EAEnG;IAEF,eAAe,kCACG,MAAM,YAAY,MAAM,OAAO,GAAG,WAAW,MAAM,KAAG,OAAO,CAAC,YAAY,CAAC,EAE3F;IAEF,eAAe,kCACG,MAAM,YAAY,MAAM,OAAO,GAAG,KAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,EAEhF;IAEF,UAAU,kCAAyB,MAAM,YAAY,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,EAAuB;IAEpG,mBAAmB,kCAAyB,MAAM,YAAY,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,EAAO;IAE7F,qBAAqB,kCACH,MAAM,WAAW,MAAM,KAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAE5E;IAEF,UAAU,kCAAyB,MAAM,WAAW,GAAG,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,GAAG,CAAC,EAAU;IAEpG,QAAQ,wCAA+B,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,EAAQ;CACtE;AAED,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=CROSSxSDK.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CROSSxSDK.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/sdk/CROSSxSDK.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=EthereumProvider.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EthereumProvider.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/sdk/EthereumProvider.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SignInUseCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignInUseCase.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/usecases/SignInUseCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SignOutUseCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignOutUseCase.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/usecases/SignOutUseCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=WithdrawUseCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WithdrawUseCase.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/usecases/WithdrawUseCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { ConfirmationPort, ConfirmationDetails, TransactionCompleteDetails } from '../../core/ports/ConfirmationPort';
2
+ import { SDKThemeTokens } from '../../core/types';
3
+
4
+ export type ConfirmationTheme = 'light' | 'dark';
5
+ export declare class BrowserConfirmationAdapter implements ConfirmationPort {
6
+ private theme;
7
+ private overrides;
8
+ private tokens;
9
+ constructor(theme?: ConfirmationTheme, overrides?: SDKThemeTokens);
10
+ setTheme(theme: ConfirmationTheme, overrides?: SDKThemeTokens): void;
11
+ getTheme(): ConfirmationTheme;
12
+ /**
13
+ * 로그인 프로바이더 선택 팝업: "Welcome onboard"
14
+ * Apple / Google 버튼을 표시하고 선택된 프로바이더를 반환합니다.
15
+ * @returns 'google' | 'apple' | null(취소)
16
+ */
17
+ showLoginSelector(): Promise<'google' | 'apple' | null>;
18
+ /**
19
+ * 마이그레이션 발견 팝업: "Wallet Found on Social Account"
20
+ * @returns 'recover' 또는 'skip'
21
+ */
22
+ showMigrationFoundPrompt(): Promise<'recover' | 'skip'>;
23
+ /**
24
+ * PIN 입력 팝업: "Recover My Wallet"
25
+ * @param errorMessage 이전 시도 실패 시 에러 메시지
26
+ * @returns 4자리 PIN 문자열 또는 null(취소)
27
+ */
28
+ showPinInputPrompt(errorMessage?: string): Promise<string | null>;
29
+ /**
30
+ * 트랜잭션 전송 완료 팝업을 표시합니다.
31
+ * "Done" 버튼 클릭, 닫기 버튼 클릭, 배경 클릭, Escape 키로 닫힙니다.
32
+ */
33
+ showTransactionComplete(details: TransactionCompleteDetails): Promise<void>;
34
+ requestConfirmation(details: ConfirmationDetails): Promise<boolean>;
35
+ }
36
+ //# sourceMappingURL=BrowserConfirmationAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BrowserConfirmationAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/confirmation/BrowserConfirmationAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EAEnB,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,CAAC;AAk/CjD,qBAAa,0BAA2B,YAAW,gBAAgB;IACjE,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,MAAM,CAAc;gBAEhB,KAAK,GAAE,iBAA2B,EAAE,SAAS,CAAC,EAAE,cAAc;IAM1E,QAAQ,CAAC,KAAK,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,cAAc,GAAG,IAAI;IAMpE,QAAQ,IAAI,iBAAiB;IAI7B;;;;OAIG;IACH,iBAAiB,IAAI,OAAO,CAAC,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAC;IA+BvD;;;OAGG;IACH,wBAAwB,IAAI,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC;IA0BvD;;;;OAIG;IACH,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiBjE;;;OAGG;IACH,uBAAuB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC3E,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;CA2CpE"}
@@ -0,0 +1,16 @@
1
+ import { CryptoPort, JWTVerifyOptions, JWTVerifyResult } from '../../core/ports';
2
+ import { JWTPayload } from '../../core/types';
3
+
4
+ export declare class JoseCryptoAdapter implements CryptoPort {
5
+ verifyJWT(token: string, options?: JWTVerifyOptions): Promise<JWTVerifyResult>;
6
+ decodeJWT(token: string): JWTPayload;
7
+ /**
8
+ * EIP-191 personal_sign 서명에서 서명자 Ethereum 주소를 복원합니다.
9
+ *
10
+ * hash = keccak256("\x19Ethereum Signed Message:\n" + len(msgBytes) + msgBytes)
11
+ * publicKey = ecrecover(hash, v, r, s)
12
+ * address = keccak256(publicKey)[12:]
13
+ */
14
+ recoverPersonalSignSigner(message: string, signature: string): string;
15
+ }
16
+ //# sourceMappingURL=JoseCryptoAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JoseCryptoAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/crypto/JoseCryptoAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,qBAAa,iBAAkB,YAAW,UAAU;IAC5C,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAkCpF,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAIpC;;;;;;OAMG;IACH,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;CAkCtE"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Adapters
3
+ * 환경별 Port 구현체
4
+ */
5
+ export * from './storage/LocalStorageAdapter';
6
+ export * from './crypto/JoseCryptoAdapter';
7
+ export * from './transport/FetchTransportAdapter';
8
+ export * from './oauth/BrowserOAuthAdapter';
9
+ export * from './wallet/MockWalletProviderAdapter';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oCAAoC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { OAuthPort, OAuthConfig } from '../../core/ports';
2
+
3
+ export declare class BrowserOAuthAdapter implements OAuthPort {
4
+ private static generateState;
5
+ openAuth(config: OAuthConfig): Promise<string>;
6
+ }
7
+ //# sourceMappingURL=BrowserOAuthAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BrowserOAuthAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/oauth/BrowserOAuthAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/D,qBAAa,mBAAoB,YAAW,SAAS;IACnD,OAAO,CAAC,MAAM,CAAC,aAAa;IAM5B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;CAkF/C"}
@@ -0,0 +1,10 @@
1
+ import { StoragePort } from '../../core/ports';
2
+
3
+ export declare class LocalStorageAdapter implements StoragePort {
4
+ private prefix;
5
+ set<T>(key: string, value: T): Promise<void>;
6
+ get<T>(key: string): Promise<T | null>;
7
+ remove(key: string): Promise<void>;
8
+ clear(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=LocalStorageAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalStorageAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/storage/LocalStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,MAAM,CAAa;IAErB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAatC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAa7B"}
@@ -0,0 +1,6 @@
1
+ import { TransportPort, TransportRequest, TransportResponse } from '../../core/ports';
2
+
3
+ export declare class FetchTransportAdapter implements TransportPort {
4
+ request<T = any>(request: TransportRequest): Promise<TransportResponse<T>>;
5
+ }
6
+ //# sourceMappingURL=FetchTransportAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FetchTransportAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/transport/FetchTransportAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAI3F,qBAAa,qBAAsB,YAAW,aAAa;IACnD,OAAO,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;CA0BjF"}
@@ -0,0 +1,28 @@
1
+ import { WalletProviderPort, WalletData, SignResponse } from '../../core/ports/WalletProviderPort';
2
+ import { TransactionReceipt, AddressInfo, EvmTransactionRequest } from '../../core/types/chain';
3
+ import { StoragePort } from '../../core/ports';
4
+ import { PrepareAction, PrepareContext, PrepareResult } from '../../core/types/prepare';
5
+
6
+ export declare class MockWalletProviderAdapter implements WalletProviderPort {
7
+ private storage;
8
+ constructor(storage: StoragePort);
9
+ getOrCreateWallet(userId: string): Promise<WalletData>;
10
+ getAddress(userId: string, index: number): Promise<AddressInfo>;
11
+ getBalance(_address: string, _chainId: string): Promise<string>;
12
+ getTransactionCount(_address: string, _chainId: string): Promise<number>;
13
+ getTransactionReceipt(_txHash: string, _chainId: string): Promise<TransactionReceipt | null>;
14
+ rpcRequest(method: string, _params: any[], _chainId: string): Promise<any>;
15
+ prepare(action: PrepareAction, _context: PrepareContext): Promise<PrepareResult>;
16
+ signMessage(userId: string, chainId: string, message: string, index?: number, uuid?: string, from?: string): Promise<SignResponse>;
17
+ signTypedData(userId: string, chainId: string, typedData: unknown, index?: number, uuid?: string, from?: string): Promise<SignResponse>;
18
+ signTransaction(userId: string, chainId: string, tx: EvmTransactionRequest, index?: number, uuid?: string): Promise<SignResponse>;
19
+ sendTransaction(userId: string, chainId: string, tx: EvmTransactionRequest, uuid?: string): Promise<{
20
+ txHash: string;
21
+ }>;
22
+ withdraw(confirmation: string): Promise<void>;
23
+ recoverWallet(userId: string, shareC: string): Promise<WalletData>;
24
+ migrateWallet(pin: string, sub: string): Promise<WalletData>;
25
+ private generateMockEvmAddress;
26
+ private generateMockSignature;
27
+ }
28
+ //# sourceMappingURL=MockWalletProviderAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockWalletProviderAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/wallet/MockWalletProviderAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,UAAU,EACV,YAAY,EACb,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAM7F,qBAAa,yBAA0B,YAAW,kBAAkB;IACtD,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,WAAW;IAElC,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAoBtD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAO/D,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/D,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIxE,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAI5F,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAK1E,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAMhF,WAAW,CACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,MAAU,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC;IAKlB,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,OAAO,EAClB,KAAK,GAAE,MAAU,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC;IAKlB,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,qBAAqB,EACzB,KAAK,GAAE,MAAU,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC;IAMlB,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,qBAAqB,EACzB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAKxB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAYlE,aAAa,CACjB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,UAAU,CAAC;IAYtB,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,qBAAqB;CAM9B"}