@nexus-cross/crossx-sdk-core 1.3.0 → 1.3.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/dist/adapters/confirmation/BrowserConfirmationAdapter.d.ts +6 -3
- package/dist/adapters/confirmation/BrowserConfirmationAdapter.d.ts.map +1 -1
- package/dist/core/i18n/messages.en.d.ts.map +1 -1
- package/dist/core/i18n/messages.ko.d.ts.map +1 -1
- package/dist/core/i18n/types.d.ts +2 -0
- package/dist/core/i18n/types.d.ts.map +1 -1
- package/dist/core/ports/ConfirmationPort.d.ts +5 -2
- package/dist/core/ports/ConfirmationPort.d.ts.map +1 -1
- package/dist/core/types/errors.d.ts +2 -0
- package/dist/core/types/errors.d.ts.map +1 -1
- package/dist/core/types/events.d.ts +2 -0
- package/dist/core/types/events.d.ts.map +1 -1
- package/dist/core/types/index.d.ts +21 -0
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/crossx.global +124 -43
- package/dist/index.cjs +106 -25
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +707 -614
- package/dist/sdk/CROSSxSDK.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,10 +2,10 @@ var Ls = Object.defineProperty;
|
|
|
2
2
|
var Ds = (r, e, s) => e in r ? Ls(r, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : r[e] = s;
|
|
3
3
|
var I = (r, e, s) => Ds(r, typeof e != "symbol" ? e + "" : e, s);
|
|
4
4
|
import { createRemoteJWKSet as Ms, jwtVerify as $s, decodeJwt as Bs } from "jose";
|
|
5
|
-
var p = /* @__PURE__ */ ((r) => (r.AUTH_NOT_INITIALIZED = "AUTH_NOT_INITIALIZED", r.AUTH_FAILED = "AUTH_FAILED", r.AUTH_TOKEN_INVALID = "AUTH_TOKEN_INVALID", r.AUTH_TOKEN_EXPIRED = "AUTH_TOKEN_EXPIRED", r.AUTH_NOT_AUTHENTICATED = "AUTH_NOT_AUTHENTICATED", r.ALREADY_AUTHENTICATED = "ALREADY_AUTHENTICATED", r.WALLET_NOT_FOUND = "WALLET_NOT_FOUND", r.WALLET_CREATION_FAILED = "WALLET_CREATION_FAILED", r.WALLET_ALREADY_EXISTS = "WALLET_ALREADY_EXISTS", r.SIGN_FAILED = "SIGN_FAILED", r.SIGN_REJECTED = "SIGN_REJECTED", r.TX_FAILED = "TX_FAILED", r.TX_REJECTED = "TX_REJECTED", r.BROADCAST_FAILED = "BROADCAST_FAILED", r.USER_REJECTED = "USER_REJECTED", r.TX_INVALID_PARAMS = "TX_INVALID_PARAMS", r.NETWORK_ERROR = "NETWORK_ERROR", r.NETWORK_NOT_CONFIGURED = "NETWORK_NOT_CONFIGURED", r.INVALID_CHAIN = "INVALID_CHAIN", r.CHAIN_NOT_SUPPORTED = "CHAIN_NOT_SUPPORTED", r.CHAIN_ADAPTER_NOT_FOUND = "CHAIN_ADAPTER_NOT_FOUND", r.NOT_IMPLEMENTED = "NOT_IMPLEMENTED", r.SIGNATURE_FAILED = "SIGNATURE_FAILED", r.TRANSACTION_FAILED = "TRANSACTION_FAILED", r.PREPARE_FAILED = "PREPARE_FAILED", r.PREPARE_EXPIRED = "PREPARE_EXPIRED", r.PREPARE_MISMATCH = "PREPARE_MISMATCH", r.MIGRATION_FAILED = "MIGRATION_FAILED", r.MIGRATION_BACKUP_EXISTS = "MIGRATION_BACKUP_EXISTS", r.MIGRATION_PIN_LOCKED = "MIGRATION_PIN_LOCKED", r.GATEWAY_INTERNAL_ERROR = "GATEWAY_INTERNAL_ERROR", r.GATEWAY_LOCK_CONFLICT = "GATEWAY_LOCK_CONFLICT", r.WALLET_INCONSISTENT_STATE = "WALLET_INCONSISTENT_STATE", r.PROJECT_ID_MISSING = "PROJECT_ID_MISSING", r.ORIGIN_NOT_ALLOWED = "ORIGIN_NOT_ALLOWED", r.APP_IDENTIFIER_MISSING = "APP_IDENTIFIER_MISSING", r.INVALID_APP_TYPE = "INVALID_APP_TYPE", r.PROJECT_NOT_REGISTERED = "PROJECT_NOT_REGISTERED", r.SIGNATURE_SIGNER_MISMATCH = "SIGNATURE_SIGNER_MISMATCH", r.GAS_ESTIMATION_FAILED = "GAS_ESTIMATION_FAILED", r.TYPED_DATA_CHAIN_ID_MISMATCH = "TYPED_DATA_CHAIN_ID_MISMATCH", r.PIN_NOT_SET = "PIN_NOT_SET", r.PIN_WRONG = "PIN_WRONG", r.PIN_INVALID = "PIN_INVALID", r.PIN_REPEATED_PATTERN = "PIN_REPEATED_PATTERN", r.PIN_CANCELLED = "PIN_CANCELLED", r.PIN_LOCKED = "PIN_LOCKED", r.HMAC_REQUIRED = "HMAC_REQUIRED", r.HMAC_VERIFICATION_FAILED = "HMAC_VERIFICATION_FAILED", r.WITHDRAW_FAILED = "WITHDRAW_FAILED", r.INVALID_CONFIG = "INVALID_CONFIG", r.UNKNOWN_ERROR = "UNKNOWN_ERROR", r))(p || {});
|
|
6
|
-
class
|
|
5
|
+
var p = /* @__PURE__ */ ((r) => (r.AUTH_NOT_INITIALIZED = "AUTH_NOT_INITIALIZED", r.AUTH_FAILED = "AUTH_FAILED", r.AUTH_TOKEN_INVALID = "AUTH_TOKEN_INVALID", r.AUTH_TOKEN_EXPIRED = "AUTH_TOKEN_EXPIRED", r.AUTH_NOT_AUTHENTICATED = "AUTH_NOT_AUTHENTICATED", r.ALREADY_AUTHENTICATED = "ALREADY_AUTHENTICATED", r.WALLET_NOT_FOUND = "WALLET_NOT_FOUND", r.WALLET_CREATION_FAILED = "WALLET_CREATION_FAILED", r.WALLET_ALREADY_EXISTS = "WALLET_ALREADY_EXISTS", r.SIGN_FAILED = "SIGN_FAILED", r.SIGN_REJECTED = "SIGN_REJECTED", r.TX_FAILED = "TX_FAILED", r.TX_REJECTED = "TX_REJECTED", r.BROADCAST_FAILED = "BROADCAST_FAILED", r.USER_REJECTED = "USER_REJECTED", r.TX_INVALID_PARAMS = "TX_INVALID_PARAMS", r.NETWORK_ERROR = "NETWORK_ERROR", r.NETWORK_NOT_CONFIGURED = "NETWORK_NOT_CONFIGURED", r.INVALID_CHAIN = "INVALID_CHAIN", r.CHAIN_NOT_SUPPORTED = "CHAIN_NOT_SUPPORTED", r.CHAIN_ADAPTER_NOT_FOUND = "CHAIN_ADAPTER_NOT_FOUND", r.NOT_IMPLEMENTED = "NOT_IMPLEMENTED", r.SIGNATURE_FAILED = "SIGNATURE_FAILED", r.TRANSACTION_FAILED = "TRANSACTION_FAILED", r.PREPARE_FAILED = "PREPARE_FAILED", r.PREPARE_EXPIRED = "PREPARE_EXPIRED", r.PREPARE_MISMATCH = "PREPARE_MISMATCH", r.MIGRATION_FAILED = "MIGRATION_FAILED", r.MIGRATION_BACKUP_EXISTS = "MIGRATION_BACKUP_EXISTS", r.MIGRATION_PIN_LOCKED = "MIGRATION_PIN_LOCKED", r.GATEWAY_INTERNAL_ERROR = "GATEWAY_INTERNAL_ERROR", r.GATEWAY_LOCK_CONFLICT = "GATEWAY_LOCK_CONFLICT", r.WALLET_INCONSISTENT_STATE = "WALLET_INCONSISTENT_STATE", r.PROJECT_ID_MISSING = "PROJECT_ID_MISSING", r.ORIGIN_NOT_ALLOWED = "ORIGIN_NOT_ALLOWED", r.APP_IDENTIFIER_MISSING = "APP_IDENTIFIER_MISSING", r.INVALID_APP_TYPE = "INVALID_APP_TYPE", r.PROJECT_NOT_REGISTERED = "PROJECT_NOT_REGISTERED", r.SIGNATURE_SIGNER_MISMATCH = "SIGNATURE_SIGNER_MISMATCH", r.GAS_ESTIMATION_FAILED = "GAS_ESTIMATION_FAILED", r.TYPED_DATA_CHAIN_ID_MISMATCH = "TYPED_DATA_CHAIN_ID_MISMATCH", r.PIN_NOT_SET = "PIN_NOT_SET", r.PIN_WRONG = "PIN_WRONG", r.PIN_INVALID = "PIN_INVALID", r.PIN_REPEATED_PATTERN = "PIN_REPEATED_PATTERN", r.PIN_CANCELLED = "PIN_CANCELLED", r.EXTERNAL_WALLET_REQUESTED = "EXTERNAL_WALLET_REQUESTED", r.PIN_LOCKED = "PIN_LOCKED", r.HMAC_REQUIRED = "HMAC_REQUIRED", r.HMAC_VERIFICATION_FAILED = "HMAC_VERIFICATION_FAILED", r.WITHDRAW_FAILED = "WITHDRAW_FAILED", r.INVALID_CONFIG = "INVALID_CONFIG", r.UNKNOWN_ERROR = "UNKNOWN_ERROR", r))(p || {});
|
|
6
|
+
class m extends Error {
|
|
7
7
|
constructor(e, s, t) {
|
|
8
|
-
super(s), this.code = e, this.details = t, this.name = "CROSSxError", Object.setPrototypeOf(this,
|
|
8
|
+
super(s), this.code = e, this.details = t, this.name = "CROSSxError", Object.setPrototypeOf(this, m.prototype);
|
|
9
9
|
}
|
|
10
10
|
toJSON() {
|
|
11
11
|
return {
|
|
@@ -107,7 +107,7 @@ class Fs {
|
|
|
107
107
|
}
|
|
108
108
|
case "personal_sign":
|
|
109
109
|
case "eth_sign":
|
|
110
|
-
throw new
|
|
110
|
+
throw new m(
|
|
111
111
|
p.NOT_IMPLEMENTED,
|
|
112
112
|
`${e}은(는) 아직 지원되지 않습니다. sdk.signMessage()를 직접 사용하세요.`
|
|
113
113
|
);
|
|
@@ -115,7 +115,7 @@ class Fs {
|
|
|
115
115
|
case "eth_signTypedData_v1":
|
|
116
116
|
case "eth_signTypedData_v3":
|
|
117
117
|
case "eth_signTypedData_v4":
|
|
118
|
-
throw new
|
|
118
|
+
throw new m(
|
|
119
119
|
p.NOT_IMPLEMENTED,
|
|
120
120
|
`${e}은(는) 아직 지원되지 않습니다. sdk.signTypedData() 또는 sdk.signTypedDataOffchain()을 직접 사용하세요.`
|
|
121
121
|
);
|
|
@@ -171,7 +171,7 @@ let Ee = null;
|
|
|
171
171
|
function vt(r) {
|
|
172
172
|
Ee = r;
|
|
173
173
|
}
|
|
174
|
-
const
|
|
174
|
+
const d = {
|
|
175
175
|
log(...r) {
|
|
176
176
|
if (Ee) {
|
|
177
177
|
Ee.log(...r);
|
|
@@ -211,6 +211,8 @@ const u = {
|
|
|
211
211
|
loginSelector_title: "로그인 방법 선택",
|
|
212
212
|
loginSelector_google: "Google로 계속하기",
|
|
213
213
|
loginSelector_apple: "Apple로 계속하기",
|
|
214
|
+
loginSelector_connectOtherWallets: "다른 지갑으로 연결",
|
|
215
|
+
loginSelector_connectOtherWalletsDesc: "기존 Web3 지갑을 연결하여 자산을 관리하세요.",
|
|
214
216
|
// ── 마이그레이션 모달 ────────────────────────────────────────
|
|
215
217
|
migration_foundTitle: "기존 지갑 발견",
|
|
216
218
|
migration_foundDescription: "기존 CROSSx 지갑이 발견되었습니다. 복구하시겠습니까?",
|
|
@@ -276,6 +278,8 @@ const u = {
|
|
|
276
278
|
loginSelector_title: "Choose a sign-in method",
|
|
277
279
|
loginSelector_google: "Continue with Google",
|
|
278
280
|
loginSelector_apple: "Continue with Apple",
|
|
281
|
+
loginSelector_connectOtherWallets: "Connect with Other Wallets",
|
|
282
|
+
loginSelector_connectOtherWalletsDesc: "Connect your existing Web3 wallet to manage your assets.",
|
|
279
283
|
// ── Migration modal ──────────────────────────────────────────
|
|
280
284
|
migration_foundTitle: "Existing Wallet Found",
|
|
281
285
|
migration_foundDescription: "An existing CROSSx wallet was found. Would you like to recover it?",
|
|
@@ -344,7 +348,7 @@ class qs {
|
|
|
344
348
|
*/
|
|
345
349
|
checkResponseError(e, s) {
|
|
346
350
|
if (e != null && e.code && e.code !== 200 && e.code > 0)
|
|
347
|
-
throw new
|
|
351
|
+
throw new m(
|
|
348
352
|
p.AUTH_FAILED,
|
|
349
353
|
`${s} 실패 (코드 ${e.code}): ${e.message}`
|
|
350
354
|
);
|
|
@@ -352,7 +356,7 @@ class qs {
|
|
|
352
356
|
if (typeof t == "object" && t !== null && "code" in t) {
|
|
353
357
|
const n = t;
|
|
354
358
|
if (n.code && n.code !== 200 && n.code > 0)
|
|
355
|
-
throw new
|
|
359
|
+
throw new m(
|
|
356
360
|
p.AUTH_FAILED,
|
|
357
361
|
`${s} 실패 (코드 ${n.code}): ${n.message}`
|
|
358
362
|
);
|
|
@@ -365,55 +369,55 @@ class qs {
|
|
|
365
369
|
const c = e == null ? void 0 : e.provider;
|
|
366
370
|
let l = "/login";
|
|
367
371
|
c === "google" ? l = "/google" : c === "apple" && (l = "/apple");
|
|
368
|
-
const { oauthServiceUrl:
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
authUrl:
|
|
372
|
-
expectedOrigin: new URL(
|
|
372
|
+
const { oauthServiceUrl: u, authApiUrl: h } = this.config, g = `${u}${l}`;
|
|
373
|
+
d.log(`[CROSSx] OAuth 팝업 열기 (${c || "일반"} 로그인)`);
|
|
374
|
+
const _ = await this.oauth.openAuth({
|
|
375
|
+
authUrl: g,
|
|
376
|
+
expectedOrigin: new URL(u).origin
|
|
373
377
|
});
|
|
374
|
-
|
|
375
|
-
const { accessToken: w, refreshToken: v } = await this.exchangeFirebaseToken(
|
|
378
|
+
d.log("[CROSSx] OAuth Firebase 토큰 받음 (length:", _.length, ")");
|
|
379
|
+
const { accessToken: w, refreshToken: v } = await this.exchangeFirebaseToken(_, h);
|
|
376
380
|
let y, S;
|
|
377
381
|
try {
|
|
378
|
-
const U = this.crypto.decodeJWT(
|
|
382
|
+
const U = this.crypto.decodeJWT(_);
|
|
379
383
|
S = (n = U.firebase) == null ? void 0 : n.sign_in_provider;
|
|
380
384
|
const N = ((o = U.firebase) == null ? void 0 : o.identities) ?? {};
|
|
381
|
-
S === "google.com" ? y = (i = N["google.com"]) == null ? void 0 : i[0] : S === "apple.com" && (y = (a = N["apple.com"]) == null ? void 0 : a[0]),
|
|
385
|
+
S === "google.com" ? y = (i = N["google.com"]) == null ? void 0 : i[0] : S === "apple.com" && (y = (a = N["apple.com"]) == null ? void 0 : a[0]), d.log("[CROSSx] OAuth provider sub 추출 — provider:", S, "hasProviderSub:", !!y);
|
|
382
386
|
} catch {
|
|
383
|
-
|
|
387
|
+
d.warn("[CROSSx] firebaseToken에서 providerSub 추출 실패");
|
|
384
388
|
}
|
|
385
389
|
if (w) {
|
|
386
390
|
const U = this.crypto.decodeJWT(w);
|
|
387
|
-
|
|
391
|
+
d.log("[CROSSx] access_token 디코딩 — sub:", U.sub, "exp:", U.exp);
|
|
388
392
|
const N = await this.crypto.verifyJWT(w);
|
|
389
393
|
if (t = N.signatureVerified ?? !1, !N.valid)
|
|
390
|
-
throw
|
|
394
|
+
throw d.error("[CROSSx] access_token 검증 실패"), new Error("유효하지 않은 access token");
|
|
391
395
|
const V = N.payload;
|
|
392
396
|
s = {
|
|
393
397
|
id: V.sub,
|
|
394
398
|
email: V.email,
|
|
395
399
|
signInProvider: S,
|
|
396
400
|
providerSub: y
|
|
397
|
-
}, this.tokenStore.set(w), this.useCookieAuth || (await this.storage.set(this.STORAGE_KEY_ACCESS_TOKEN, w), v && this.config.secureStorageAvailable !== !1 ? await this.storage.set(this.STORAGE_KEY_REFRESH_TOKEN, v) : v &&
|
|
401
|
+
}, this.tokenStore.set(w), this.useCookieAuth || (await this.storage.set(this.STORAGE_KEY_ACCESS_TOKEN, w), v && this.config.secureStorageAvailable !== !1 ? await this.storage.set(this.STORAGE_KEY_REFRESH_TOKEN, v) : v && d.warn("[CROSSx] 안전한 스토리지 미사용 — refresh_token 영속 저장을 건너뜁니다"));
|
|
398
402
|
} else {
|
|
399
|
-
const U = this.crypto.decodeJWT(
|
|
403
|
+
const U = this.crypto.decodeJWT(_);
|
|
400
404
|
s = {
|
|
401
405
|
id: U.sub,
|
|
402
406
|
email: U.email,
|
|
403
407
|
signInProvider: S,
|
|
404
408
|
providerSub: y
|
|
405
|
-
},
|
|
409
|
+
}, d.log("[CROSSx] Cookie 모드 — Firebase 토큰에서 사용자 정보 추출 — id:", s.id);
|
|
406
410
|
}
|
|
407
|
-
|
|
411
|
+
d.log("[CROSSx] 사용자 정보 — id:", s.id);
|
|
408
412
|
const C = this.useCookieAuth ? { id: s.id, signInProvider: s.signInProvider, providerSub: s.providerSub } : s;
|
|
409
|
-
await this.storage.set(this.STORAGE_KEY_USER, C),
|
|
413
|
+
await this.storage.set(this.STORAGE_KEY_USER, C), d.log("[CROSSx] 사용자 정보 저장 완료 (authMode:", this.useCookieAuth ? "cookie" : "token", ")");
|
|
410
414
|
} catch (c) {
|
|
411
|
-
return
|
|
415
|
+
return d.error("[CROSSx] SignIn 에러 (OAuth/토큰 교환 단계):", c), {
|
|
412
416
|
success: !1,
|
|
413
417
|
error: c instanceof Error ? c.message : "Sign in failed"
|
|
414
418
|
};
|
|
415
419
|
}
|
|
416
|
-
return
|
|
420
|
+
return d.log("[CROSSx][Migration Phase 1] OAuth 로그인 완료, 지갑 로드 시작 — userId:", s.id), this.loadWallet(s, t);
|
|
417
421
|
}
|
|
418
422
|
/**
|
|
419
423
|
* Firebase 토큰 → CROSSx 인증 교환
|
|
@@ -422,7 +426,7 @@ class qs {
|
|
|
422
426
|
*/
|
|
423
427
|
async exchangeFirebaseToken(e, s) {
|
|
424
428
|
const t = this.useCookieAuth, n = t ? `${s}/cross-auth/social/login/cookie` : `${s}/cross-auth/social/login`;
|
|
425
|
-
|
|
429
|
+
d.log("[CROSSx] Firebase 토큰 교환 요청");
|
|
426
430
|
const o = await this.transport.request({
|
|
427
431
|
url: n,
|
|
428
432
|
method: "POST",
|
|
@@ -430,18 +434,18 @@ class qs {
|
|
|
430
434
|
body: { auth_code: e, login_type: "firebase" },
|
|
431
435
|
...t ? { credentials: "include" } : {}
|
|
432
436
|
});
|
|
433
|
-
|
|
437
|
+
d.log("[CROSSx] 토큰 교환 응답 — status:", o.status);
|
|
434
438
|
const i = o.data;
|
|
435
439
|
this.checkResponseError(i, "Token exchange");
|
|
436
440
|
const a = this.extractAccessToken(i);
|
|
437
441
|
if (t && !a)
|
|
438
|
-
return
|
|
442
|
+
return d.log("[CROSSx] Cookie 모드 — 로그인 성공 (JWT는 HttpOnly 쿠키)"), {};
|
|
439
443
|
if (!a)
|
|
440
|
-
throw new
|
|
444
|
+
throw new m(
|
|
441
445
|
p.AUTH_FAILED,
|
|
442
446
|
"토큰 교환 응답에서 access_token을 찾을 수 없습니다"
|
|
443
447
|
);
|
|
444
|
-
|
|
448
|
+
d.log("[CROSSx] access_token 교환 성공");
|
|
445
449
|
let c;
|
|
446
450
|
return t || (c = this.extractRefreshToken(i)), { accessToken: a, refreshToken: c };
|
|
447
451
|
}
|
|
@@ -504,38 +508,38 @@ class qs {
|
|
|
504
508
|
if (t.valid) {
|
|
505
509
|
const n = await this.storage.get(this.STORAGE_KEY_USER);
|
|
506
510
|
if (n)
|
|
507
|
-
return
|
|
511
|
+
return d.log("[CROSSx] restoreSession — 메모리 토큰 유효, 세션 복원"), this.loadWallet(n, t.signatureVerified);
|
|
508
512
|
}
|
|
509
513
|
this.tokenStore.clear();
|
|
510
514
|
}
|
|
511
515
|
if (this.useCookieAuth) {
|
|
512
|
-
|
|
516
|
+
d.log("[CROSSx] restoreSession — 쿠키 기반 silentRefresh 시도");
|
|
513
517
|
const t = await this.silentRefresh();
|
|
514
518
|
t && this.tokenStore.set(t);
|
|
515
519
|
} else {
|
|
516
520
|
const t = await this.storage.get(this.STORAGE_KEY_ACCESS_TOKEN), n = await this.storage.get(this.STORAGE_KEY_REFRESH_TOKEN);
|
|
517
|
-
if (
|
|
521
|
+
if (d.log(
|
|
518
522
|
"[CROSSx] restoreSession — access_token:",
|
|
519
523
|
t ? "있음" : "없음",
|
|
520
524
|
"refresh_token:",
|
|
521
525
|
n ? "있음" : "없음"
|
|
522
526
|
), !n)
|
|
523
|
-
return
|
|
527
|
+
return d.log("[CROSSx] restoreSession — refresh_token 없음, 세션 복원 생략"), null;
|
|
524
528
|
t && this.tokenStore.set(t);
|
|
525
529
|
const o = await this.silentRefresh(n);
|
|
526
|
-
|
|
530
|
+
d.log("[CROSSx] restoreSession — silentRefresh 결과:", o ? "토큰 발급 성공" : "토큰 없음"), o && this.tokenStore.set(o);
|
|
527
531
|
}
|
|
528
532
|
const s = await this.storage.get(this.STORAGE_KEY_USER);
|
|
529
|
-
if (
|
|
533
|
+
if (d.log("[CROSSx] restoreSession — userInfo 조회:", s ? `있음 (id: ${s.id})` : "없음"), !s)
|
|
530
534
|
return null;
|
|
531
|
-
|
|
535
|
+
d.log("[CROSSx] restoreSession — silentRefresh 성공, 세션 복원 — userId:", s.id);
|
|
532
536
|
try {
|
|
533
537
|
return await this.loadWallet(s, !1);
|
|
534
538
|
} catch (t) {
|
|
535
|
-
return
|
|
539
|
+
return d.warn("[CROSSx] restoreSession — 지갑 로드 실패 (세션은 유지):", t), { success: !0, user: s, tokenSignatureVerified: !1 };
|
|
536
540
|
}
|
|
537
541
|
} catch (e) {
|
|
538
|
-
return
|
|
542
|
+
return d.log("[CROSSx] restoreSession — 세션 복원 실패, 스토리지 정리:", e), this.tokenStore.clear(), this.useCookieAuth || await this.storage.remove(this.STORAGE_KEY_REFRESH_TOKEN), await this.storage.remove(this.STORAGE_KEY_USER), null;
|
|
539
543
|
}
|
|
540
544
|
}
|
|
541
545
|
silentRefresh(e) {
|
|
@@ -556,22 +560,22 @@ class qs {
|
|
|
556
560
|
body: o,
|
|
557
561
|
...t ? { credentials: "include" } : {}
|
|
558
562
|
});
|
|
559
|
-
|
|
563
|
+
d.log("[CROSSx] silentRefresh 응답 — status:", i.status);
|
|
560
564
|
const a = i.data;
|
|
561
565
|
this.checkResponseError(a, "Silent refresh");
|
|
562
566
|
const c = this.extractAccessToken(a);
|
|
563
567
|
if (t && !c) {
|
|
564
|
-
|
|
568
|
+
d.log("[CROSSx] silentRefresh 성공 (cookie 갱신)");
|
|
565
569
|
return;
|
|
566
570
|
}
|
|
567
571
|
if (!c)
|
|
568
|
-
throw new
|
|
572
|
+
throw new m(p.AUTH_FAILED, "토큰 자동 갱신 실패: 응답에 토큰이 없습니다");
|
|
569
573
|
if (this.tokenStore.set(c), !t) {
|
|
570
574
|
await this.storage.set(this.STORAGE_KEY_ACCESS_TOKEN, c);
|
|
571
575
|
const l = this.extractRefreshToken(a);
|
|
572
576
|
l && this.config.secureStorageAvailable !== !1 && await this.storage.set(this.STORAGE_KEY_REFRESH_TOKEN, l);
|
|
573
577
|
}
|
|
574
|
-
return
|
|
578
|
+
return d.log("[CROSSx] silentRefresh 성공"), c;
|
|
575
579
|
}
|
|
576
580
|
/**
|
|
577
581
|
* 외부에서 발급된 CROSSx JWT를 직접 주입하여 로그인합니다.
|
|
@@ -588,22 +592,22 @@ class qs {
|
|
|
588
592
|
let o = await this.crypto.verifyJWT(e);
|
|
589
593
|
if (n = o.signatureVerified ?? !1, !o.valid) {
|
|
590
594
|
if (!s)
|
|
591
|
-
return
|
|
592
|
-
|
|
595
|
+
return d.error("[CROSSx] signInWithJWT: access_token 검증 실패, refreshToken 없음"), { success: !1, error: "유효하지 않은 access token" };
|
|
596
|
+
d.log("[CROSSx] signInWithJWT: access_token 만료, refreshToken으로 갱신 시도");
|
|
593
597
|
const a = await this.silentRefresh(s);
|
|
594
598
|
if (!a)
|
|
595
|
-
return
|
|
599
|
+
return d.error("[CROSSx] signInWithJWT: silentRefresh 실패"), { success: !1, error: "access token이 만료되었고 갱신에 실패했습니다" };
|
|
596
600
|
if (e = a, o = await this.crypto.verifyJWT(e), n = o.signatureVerified ?? !1, !o.valid)
|
|
597
|
-
return
|
|
598
|
-
|
|
601
|
+
return d.error("[CROSSx] signInWithJWT: 갱신된 access_token도 유효하지 않음"), { success: !1, error: "갱신된 access token이 유효하지 않습니다" };
|
|
602
|
+
d.log("[CROSSx] signInWithJWT: silentRefresh 성공, 새 access_token 사용");
|
|
599
603
|
}
|
|
600
604
|
const i = o.payload;
|
|
601
|
-
|
|
605
|
+
d.log("[CROSSx] signInWithJWT — sub:", i.sub, "signatureVerified:", n), t = {
|
|
602
606
|
id: i.sub,
|
|
603
607
|
email: i.email
|
|
604
|
-
}, this.tokenStore.set(e), this.useCookieAuth || (await this.storage.set(this.STORAGE_KEY_ACCESS_TOKEN, e), s && this.config.secureStorageAvailable !== !1 && await this.storage.set(this.STORAGE_KEY_REFRESH_TOKEN, s)), await this.storage.set(this.STORAGE_KEY_USER, t),
|
|
608
|
+
}, this.tokenStore.set(e), this.useCookieAuth || (await this.storage.set(this.STORAGE_KEY_ACCESS_TOKEN, e), s && this.config.secureStorageAvailable !== !1 && await this.storage.set(this.STORAGE_KEY_REFRESH_TOKEN, s)), await this.storage.set(this.STORAGE_KEY_USER, t), d.log("[CROSSx] signInWithJWT — 토큰 및 사용자 정보 저장 완료");
|
|
605
609
|
} catch (o) {
|
|
606
|
-
return
|
|
610
|
+
return d.error("[CROSSx] signInWithJWT 에러:", o), {
|
|
607
611
|
success: !1,
|
|
608
612
|
error: o instanceof Error ? o.message : "JWT sign in failed"
|
|
609
613
|
};
|
|
@@ -624,9 +628,9 @@ class qs {
|
|
|
624
628
|
const t = await this.storage.get(Et);
|
|
625
629
|
t && await this.storage.set(this.STORAGE_KEY_ACCESS_TOKEN, t);
|
|
626
630
|
const n = await this.storage.get(It);
|
|
627
|
-
n && await this.storage.set(this.STORAGE_KEY_REFRESH_TOKEN, n), await this.storage.remove(At), await this.storage.remove(Et), await this.storage.remove(It),
|
|
631
|
+
n && await this.storage.set(this.STORAGE_KEY_REFRESH_TOKEN, n), await this.storage.remove(At), await this.storage.remove(Et), await this.storage.remove(It), d.log("[CROSSx] 스토리지 키 마이그레이션 완료 (projectId 스코프)");
|
|
628
632
|
} catch (e) {
|
|
629
|
-
|
|
633
|
+
d.warn("[CROSSx] 스토리지 키 마이그레이션 실패:", e);
|
|
630
634
|
}
|
|
631
635
|
}
|
|
632
636
|
}
|
|
@@ -634,29 +638,29 @@ class qs {
|
|
|
634
638
|
let t, n = !1;
|
|
635
639
|
try {
|
|
636
640
|
if (typeof this.walletProvider.checkWallet == "function") {
|
|
637
|
-
|
|
641
|
+
d.log("[CROSSx] GET /mnemonic/check — 지갑 상태 확인 (비밀번호 불필요)");
|
|
638
642
|
const o = await this.walletProvider.checkWallet();
|
|
639
|
-
if (
|
|
640
|
-
|
|
643
|
+
if (d.log("[CROSSx] 지갑 상태:", o), o === "migration_required")
|
|
644
|
+
d.log("[CROSSx] migration_required → needsMigration = true"), n = !0;
|
|
641
645
|
else if (o === "exists")
|
|
642
646
|
try {
|
|
643
647
|
const i = await this.walletProvider.getAddresses(e.id);
|
|
644
|
-
i.length > 0 ? (t = i[0].address,
|
|
648
|
+
i.length > 0 ? (t = i[0].address, d.log("[CROSSx] 캐시된 주소 로드 완료 (비밀번호 불필요):", t)) : d.log("[CROSSx] 주소 캐시 없음 — createWallet 단계에서 비밀번호 입력 후 로드");
|
|
645
649
|
} catch (i) {
|
|
646
|
-
|
|
650
|
+
d.warn("[CROSSx] getAddresses 실패, createWallet 단계에서 재시도:", i);
|
|
647
651
|
}
|
|
648
652
|
} else
|
|
649
|
-
|
|
653
|
+
d.log("[CROSSx] getOrCreateWallet 직접 호출 (폴백)"), t = (await this.walletProvider.getOrCreateWallet(e.id)).address, d.log("[CROSSx] 지갑 로드 완료 — address:", t);
|
|
650
654
|
} catch (o) {
|
|
651
|
-
if (o instanceof
|
|
652
|
-
|
|
655
|
+
if (o instanceof m && o.code === p.MIGRATION_BACKUP_EXISTS)
|
|
656
|
+
d.log("[CROSSx] MIGRATION_BACKUP_EXISTS 감지 → needsMigration = true"), n = !0;
|
|
653
657
|
else {
|
|
654
|
-
if (o instanceof
|
|
655
|
-
throw
|
|
656
|
-
|
|
658
|
+
if (o instanceof m && (o.code === p.PROJECT_NOT_REGISTERED || o.code === p.PROJECT_ID_MISSING || o.code === p.ORIGIN_NOT_ALLOWED))
|
|
659
|
+
throw d.error("[CROSSx] 프로젝트 설정 에러:", o.message), o;
|
|
660
|
+
d.warn("[CROSSx] 지갑 상태 확인 실패 (로그인은 유지):", o);
|
|
657
661
|
}
|
|
658
662
|
}
|
|
659
|
-
return
|
|
663
|
+
return d.log("[CROSSx] loadWallet 결과 — address:", t, "needsMigration:", n), { success: !0, address: t, user: e, needsMigration: n, tokenSignatureVerified: s };
|
|
660
664
|
}
|
|
661
665
|
}
|
|
662
666
|
class Ks {
|
|
@@ -675,13 +679,13 @@ class Vs {
|
|
|
675
679
|
}
|
|
676
680
|
async execute(e, s) {
|
|
677
681
|
if (!this.walletProvider.migrateWallet)
|
|
678
|
-
throw new
|
|
682
|
+
throw new m(
|
|
679
683
|
p.NOT_IMPLEMENTED,
|
|
680
684
|
"현재 환경에서는 마이그레이션이 지원되지 않습니다"
|
|
681
685
|
);
|
|
682
|
-
|
|
686
|
+
d.log("[CROSSx][Migration Phase 4] MigrateWalletUseCase.execute() — pin 길이:", e.length, "sub:", s);
|
|
683
687
|
const t = await this.walletProvider.migrateWallet(e, s);
|
|
684
|
-
return
|
|
688
|
+
return d.log("[CROSSx][Migration Phase 5] MigrateWalletUseCase 완료 — address:", t.address), {
|
|
685
689
|
address: t.address
|
|
686
690
|
};
|
|
687
691
|
}
|
|
@@ -752,7 +756,7 @@ class zs {
|
|
|
752
756
|
body: o
|
|
753
757
|
})).data;
|
|
754
758
|
if (a != null && a.error)
|
|
755
|
-
throw new
|
|
759
|
+
throw new m(
|
|
756
760
|
p.UNKNOWN_ERROR,
|
|
757
761
|
`RPC 오류 [${e}] (${t}): ${a.error.message} (코드: ${a.error.code})`
|
|
758
762
|
);
|
|
@@ -820,9 +824,9 @@ function Js() {
|
|
|
820
824
|
return Ge.production;
|
|
821
825
|
}
|
|
822
826
|
const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA00", kt = 130, Pt = 6, Nt = 18, tr = 5 * 60 * 1e3, sr = 30 * 1e3, re = class re extends js {
|
|
823
|
-
constructor(e, s, t, n, o, i, a, c, l,
|
|
824
|
-
var
|
|
825
|
-
super(), this.storage = t, this.crypto = n, this.transport = o, this.oauth = i, this.walletProvider = a, this.tokenStore = c, this.initialized = !1, this._initPromise = null, this.authenticated = !1, this.userId = null, this.address = null, this.activeWalletIndex = 0, this.userEmail = null, this.loginType = null, this.providerSub = null, this.tokenSignatureVerified = !1, this._verifyPinMutex = null, this._config = Object.freeze({ ...e }), this.internalConfig = e, this.adapterConfig = s, e.logger && vt(e.logger), this.confirmation = l, this.pinStore = h ?? new es(), this.chainRegistry =
|
|
827
|
+
constructor(e, s, t, n, o, i, a, c, l, u, h) {
|
|
828
|
+
var g;
|
|
829
|
+
super(), this.storage = t, this.crypto = n, this.transport = o, this.oauth = i, this.walletProvider = a, this.tokenStore = c, this.initialized = !1, this._initPromise = null, this.authenticated = !1, this.userId = null, this.address = null, this.activeWalletIndex = 0, this.userEmail = null, this.loginType = null, this.providerSub = null, this.tokenSignatureVerified = !1, this._verifyPinMutex = null, this._config = Object.freeze({ ...e }), this.internalConfig = e, this.adapterConfig = s, e.logger && vt(e.logger), this.confirmation = l, this.pinStore = h ?? new es(), this.chainRegistry = u, this.jsonRpc = new zs(u, o), this.signInUseCase = new qs(
|
|
826
830
|
this.internalConfig,
|
|
827
831
|
t,
|
|
828
832
|
n,
|
|
@@ -830,7 +834,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
830
834
|
o,
|
|
831
835
|
a,
|
|
832
836
|
c
|
|
833
|
-
), this.signOutUseCase = new Ks(this.internalConfig, t, c), this.migrateWalletUseCase = new Vs(t, a), (
|
|
837
|
+
), this.signOutUseCase = new Ks(this.internalConfig, t, c), this.migrateWalletUseCase = new Vs(t, a), (g = a.setOnUnauthorized) == null || g.call(a, () => this.forceLogout());
|
|
834
838
|
}
|
|
835
839
|
get config() {
|
|
836
840
|
return this._config;
|
|
@@ -856,7 +860,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
856
860
|
}
|
|
857
861
|
async _doInitialize(e) {
|
|
858
862
|
var s, t;
|
|
859
|
-
|
|
863
|
+
d.log("[CROSSx SDK] v1.3.2 초기화 중..."), this.confirmation.setMessages(St(this._config.locale));
|
|
860
864
|
try {
|
|
861
865
|
const n = Js();
|
|
862
866
|
this.internalConfig.oauthServiceUrl = n.oauthServiceUrl, this.internalConfig.authApiUrl = n.authApiUrl, this.internalConfig.walletGatewayUrl = n.walletGatewayUrl, this.adapterConfig.gatewayUrl = n.walletGatewayUrl, (t = (s = this.crypto).setJWKSEndpoint) == null || t.call(s, `${n.authApiUrl}/.well-known/jwks.json`);
|
|
@@ -866,25 +870,32 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
866
870
|
try {
|
|
867
871
|
await this.loadWalletAfterAuth(e == null ? void 0 : e.preferredWalletIndex);
|
|
868
872
|
} catch (i) {
|
|
869
|
-
if (!(i instanceof
|
|
873
|
+
if (!(i instanceof m && i.code === p.PIN_CANCELLED))
|
|
870
874
|
throw i;
|
|
871
|
-
|
|
875
|
+
d.log("[CROSSx] initialize: 비밀번호 입력 취소 — 지갑 미로드 상태로 계속");
|
|
872
876
|
}
|
|
873
877
|
}
|
|
874
878
|
return this.initialized = !0, this.emit("initialized", { restored: !!(o != null && o.success) }), o ?? null;
|
|
875
879
|
} catch (n) {
|
|
876
|
-
throw new
|
|
880
|
+
throw new m(p.AUTH_NOT_INITIALIZED, "SDK 초기화에 실패했습니다", n);
|
|
877
881
|
}
|
|
878
882
|
}
|
|
879
883
|
async signIn(e) {
|
|
880
884
|
if (this.ensureInitialized(), this.authenticated)
|
|
881
|
-
throw new
|
|
885
|
+
throw new m(
|
|
882
886
|
p.ALREADY_AUTHENTICATED,
|
|
883
887
|
"이미 로그인된 상태입니다. signOut()을 먼저 호출하세요."
|
|
884
888
|
);
|
|
885
889
|
let s = e;
|
|
886
890
|
if (!(e != null && e.provider)) {
|
|
887
|
-
const t = await this.confirmation.showLoginSelector(
|
|
891
|
+
const t = await this.confirmation.showLoginSelector({
|
|
892
|
+
showConnectOtherWallets: this._config.showConnectOtherWallets
|
|
893
|
+
});
|
|
894
|
+
if (t === "external")
|
|
895
|
+
throw this.emit("connectExternalWallet", {}), new m(
|
|
896
|
+
p.EXTERNAL_WALLET_REQUESTED,
|
|
897
|
+
"User requested external wallet connection"
|
|
898
|
+
);
|
|
888
899
|
if (t === null)
|
|
889
900
|
return { success: !1, error: "User cancelled login" };
|
|
890
901
|
s = { ...e, provider: t };
|
|
@@ -893,7 +904,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
893
904
|
const t = await this.signInUseCase.execute(s);
|
|
894
905
|
return t.success && this.applyAuthResult(t), t;
|
|
895
906
|
} catch (t) {
|
|
896
|
-
throw new
|
|
907
|
+
throw new m(p.AUTH_FAILED, "로그인에 실패했습니다", t);
|
|
897
908
|
}
|
|
898
909
|
}
|
|
899
910
|
/**
|
|
@@ -924,8 +935,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
924
935
|
const t = await this.getAddresses(), n = await this.selectWalletIfMultiple(t);
|
|
925
936
|
return { ...s, address: (n == null ? void 0 : n.address) ?? s.address, addresses: t };
|
|
926
937
|
} catch (t) {
|
|
927
|
-
throw t instanceof
|
|
928
|
-
(n) =>
|
|
938
|
+
throw t instanceof m && t.code === p.PIN_CANCELLED && (d.log("[CROSSx] signInWithCreate: 비밀번호 설정 취소 — 자동 로그아웃 진행"), await this.signOut().catch(
|
|
939
|
+
(n) => d.warn("[CROSSx] signInWithCreate: 자동 로그아웃 실패", n)
|
|
929
940
|
)), t;
|
|
930
941
|
}
|
|
931
942
|
}
|
|
@@ -946,7 +957,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
946
957
|
*/
|
|
947
958
|
async signInWithJWT(e, s) {
|
|
948
959
|
if (this.ensureInitialized(), this.authenticated)
|
|
949
|
-
throw new
|
|
960
|
+
throw new m(
|
|
950
961
|
p.ALREADY_AUTHENTICATED,
|
|
951
962
|
"이미 로그인된 상태입니다. signOut()을 먼저 호출하세요."
|
|
952
963
|
);
|
|
@@ -954,7 +965,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
954
965
|
const t = await this.signInUseCase.executeWithJWT(e, s);
|
|
955
966
|
return t.success && this.applyAuthResult(t), t;
|
|
956
967
|
} catch (t) {
|
|
957
|
-
throw new
|
|
968
|
+
throw new m(p.AUTH_FAILED, "JWT 로그인에 실패했습니다", t);
|
|
958
969
|
}
|
|
959
970
|
}
|
|
960
971
|
async signOut() {
|
|
@@ -962,7 +973,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
962
973
|
try {
|
|
963
974
|
await this.signOutUseCase.execute(), this.clearAuthState();
|
|
964
975
|
} catch (e) {
|
|
965
|
-
throw new
|
|
976
|
+
throw new m(p.UNKNOWN_ERROR, "로그아웃에 실패했습니다", e);
|
|
966
977
|
}
|
|
967
978
|
}
|
|
968
979
|
isAuthenticated() {
|
|
@@ -1027,7 +1038,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1027
1038
|
try {
|
|
1028
1039
|
await this.loadWalletAfterAuth();
|
|
1029
1040
|
} catch (s) {
|
|
1030
|
-
s instanceof
|
|
1041
|
+
s instanceof m && s.code === p.PIN_CANCELLED || d.warn("[CROSSx] ensureLoggedIn: loadWalletAfterAuth 실패:", s);
|
|
1031
1042
|
}
|
|
1032
1043
|
return !0;
|
|
1033
1044
|
}
|
|
@@ -1067,12 +1078,12 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1067
1078
|
*/
|
|
1068
1079
|
async migrateWallet(e) {
|
|
1069
1080
|
if (this.ensureAuthenticated(), !this.userId)
|
|
1070
|
-
throw new
|
|
1081
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "사용자 ID를 찾을 수 없습니다");
|
|
1071
1082
|
try {
|
|
1072
1083
|
const s = await this.migrateWalletUseCase.execute(e, this.userId);
|
|
1073
|
-
return this.address = s.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: s.address, index: 0 }),
|
|
1084
|
+
return this.address = s.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: s.address, index: 0 }), d.log("[CROSSx] migrateWallet 완료 — address:", s.address), s;
|
|
1074
1085
|
} catch (s) {
|
|
1075
|
-
throw s instanceof
|
|
1086
|
+
throw s instanceof m ? s : new m(
|
|
1076
1087
|
p.MIGRATION_FAILED,
|
|
1077
1088
|
"지갑 마이그레이션에 실패했습니다",
|
|
1078
1089
|
s
|
|
@@ -1094,7 +1105,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1094
1105
|
async getAddress(e) {
|
|
1095
1106
|
if (e !== void 0) {
|
|
1096
1107
|
if (this.ensureAuthenticated(), !this.userId)
|
|
1097
|
-
throw new
|
|
1108
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "사용자 ID를 찾을 수 없습니다");
|
|
1098
1109
|
return { address: (await this.walletProvider.getAddress(this.userId, e)).address, index: e };
|
|
1099
1110
|
}
|
|
1100
1111
|
return !this.authenticated || !this.address ? null : { address: this.address, index: this.activeWalletIndex };
|
|
@@ -1134,7 +1145,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1134
1145
|
*/
|
|
1135
1146
|
async selectWallet(e) {
|
|
1136
1147
|
if (this.ensureAuthenticated(), !this.userId)
|
|
1137
|
-
throw new
|
|
1148
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "사용자 ID를 찾을 수 없습니다");
|
|
1138
1149
|
let s = await this.walletProvider.getAddresses(this.userId);
|
|
1139
1150
|
s.length === 0 && this.address && (s = [{ address: this.address, index: 0 }]);
|
|
1140
1151
|
const t = await this.confirmation.showWalletSelector(
|
|
@@ -1178,7 +1189,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1178
1189
|
try {
|
|
1179
1190
|
return await this.chainRegistry.getChains();
|
|
1180
1191
|
} catch (e) {
|
|
1181
|
-
throw e instanceof
|
|
1192
|
+
throw e instanceof m ? e : new m(p.UNKNOWN_ERROR, "체인 목록 조회에 실패했습니다", e);
|
|
1182
1193
|
}
|
|
1183
1194
|
}
|
|
1184
1195
|
/**
|
|
@@ -1197,7 +1208,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1197
1208
|
try {
|
|
1198
1209
|
return await this.chainRegistry.getChain(e);
|
|
1199
1210
|
} catch (s) {
|
|
1200
|
-
throw s instanceof
|
|
1211
|
+
throw s instanceof m ? s : new m(p.CHAIN_NOT_SUPPORTED, `체인 조회에 실패했습니다: ${e}`, s);
|
|
1201
1212
|
}
|
|
1202
1213
|
}
|
|
1203
1214
|
// ============================================================================
|
|
@@ -1238,16 +1249,16 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1238
1249
|
*/
|
|
1239
1250
|
async createWallet() {
|
|
1240
1251
|
if (this.ensureAuthenticated(), !this.userId)
|
|
1241
|
-
throw new
|
|
1242
|
-
|
|
1252
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "사용자 ID를 찾을 수 없습니다");
|
|
1253
|
+
d.log("[CROSSx] createWallet 시작");
|
|
1243
1254
|
const e = await this.fetchWalletStatus();
|
|
1244
|
-
if (
|
|
1255
|
+
if (d.log("[CROSSx] 지갑 상태:", e), e === "migration_required") {
|
|
1245
1256
|
const s = this.providerSub ?? this.userId;
|
|
1246
|
-
|
|
1257
|
+
d.log("[CROSSx] migration_required → 마이그레이션 UI 시작 — sub:", s);
|
|
1247
1258
|
const t = await this.handleMigrationFlow(s);
|
|
1248
1259
|
if (t)
|
|
1249
1260
|
return this.address = t.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: t.address, index: 0 }), { address: t.address };
|
|
1250
|
-
throw new
|
|
1261
|
+
throw new m(
|
|
1251
1262
|
p.MIGRATION_FAILED,
|
|
1252
1263
|
"사용자가 마이그레이션을 건너뛰었습니다"
|
|
1253
1264
|
);
|
|
@@ -1258,15 +1269,15 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1258
1269
|
const s = await this.withPinRetry(
|
|
1259
1270
|
() => this.walletProvider.getOrCreateWallet(this.userId)
|
|
1260
1271
|
);
|
|
1261
|
-
return this.address = s.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: s.address, index: 0 }),
|
|
1272
|
+
return this.address = s.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: s.address, index: 0 }), d.log("[CROSSx] 지갑 준비 완료:", s.address), { address: s.address };
|
|
1262
1273
|
} catch (s) {
|
|
1263
|
-
if (s instanceof
|
|
1274
|
+
if (s instanceof m && s.code === p.MIGRATION_BACKUP_EXISTS) {
|
|
1264
1275
|
const t = this.providerSub ?? this.userId;
|
|
1265
|
-
|
|
1276
|
+
d.log("[CROSSx] MIGRATION_BACKUP_EXISTS (폴백) → 마이그레이션 UI 시작");
|
|
1266
1277
|
const n = await this.handleMigrationFlow(t);
|
|
1267
1278
|
if (n)
|
|
1268
1279
|
return this.address = n.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: n.address, index: 0 }), { address: n.address };
|
|
1269
|
-
throw new
|
|
1280
|
+
throw new m(
|
|
1270
1281
|
p.MIGRATION_FAILED,
|
|
1271
1282
|
"사용자가 마이그레이션을 건너뛰었습니다"
|
|
1272
1283
|
);
|
|
@@ -1277,15 +1288,15 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1277
1288
|
await this.ensurePinSetup();
|
|
1278
1289
|
try {
|
|
1279
1290
|
const s = await this.walletProvider.getOrCreateWallet(this.userId);
|
|
1280
|
-
return this.address = s.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: s.address, index: 0 }),
|
|
1291
|
+
return this.address = s.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: s.address, index: 0 }), d.log("[CROSSx] 지갑 준비 완료:", s.address), { address: s.address };
|
|
1281
1292
|
} catch (s) {
|
|
1282
|
-
if (s instanceof
|
|
1293
|
+
if (s instanceof m && s.code === p.MIGRATION_BACKUP_EXISTS) {
|
|
1283
1294
|
const t = this.providerSub ?? this.userId;
|
|
1284
|
-
|
|
1295
|
+
d.log("[CROSSx] MIGRATION_BACKUP_EXISTS (폴백) → 마이그레이션 UI 시작");
|
|
1285
1296
|
const n = await this.handleMigrationFlow(t);
|
|
1286
1297
|
if (n)
|
|
1287
1298
|
return this.address = n.address, this.activeWalletIndex = 0, this.emit("addressChanged", { address: n.address, index: 0 }), { address: n.address };
|
|
1288
|
-
throw new
|
|
1299
|
+
throw new m(
|
|
1289
1300
|
p.MIGRATION_FAILED,
|
|
1290
1301
|
"사용자가 마이그레이션을 건너뛰었습니다"
|
|
1291
1302
|
);
|
|
@@ -1299,7 +1310,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1299
1310
|
try {
|
|
1300
1311
|
return await this.walletProvider.checkWallet();
|
|
1301
1312
|
} catch (e) {
|
|
1302
|
-
return
|
|
1313
|
+
return d.warn("[CROSSx] checkWallet 실패 (폴백: not_found 처리):", e), "not_found";
|
|
1303
1314
|
}
|
|
1304
1315
|
return null;
|
|
1305
1316
|
}
|
|
@@ -1315,7 +1326,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1315
1326
|
*/
|
|
1316
1327
|
async signMessage(e, s, t) {
|
|
1317
1328
|
if (this.ensureAuthenticated(), !this.userId)
|
|
1318
|
-
throw new
|
|
1329
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "사용자 ID를 찾을 수 없습니다");
|
|
1319
1330
|
const n = await this.resolveAddress(t == null ? void 0 : t.index);
|
|
1320
1331
|
if (!await this.confirmation.requestConfirmation({
|
|
1321
1332
|
type: "sign-message",
|
|
@@ -1325,7 +1336,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1325
1336
|
dappName: (t == null ? void 0 : t.dappName) ?? this._config.appName,
|
|
1326
1337
|
accountName: t == null ? void 0 : t.accountName
|
|
1327
1338
|
}))
|
|
1328
|
-
throw new
|
|
1339
|
+
throw new m(p.USER_REJECTED, "User rejected the message signing request");
|
|
1329
1340
|
try {
|
|
1330
1341
|
const i = await this.withPinRetry(async () => {
|
|
1331
1342
|
let a;
|
|
@@ -1345,7 +1356,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1345
1356
|
address: n.address
|
|
1346
1357
|
};
|
|
1347
1358
|
} catch (i) {
|
|
1348
|
-
throw i instanceof
|
|
1359
|
+
throw i instanceof m ? i : new m(p.SIGNATURE_FAILED, `메시지 서명에 실패했습니다 (${e})`, i);
|
|
1349
1360
|
}
|
|
1350
1361
|
}
|
|
1351
1362
|
/**
|
|
@@ -1371,9 +1382,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1371
1382
|
*/
|
|
1372
1383
|
async signTypedData(e, s, t) {
|
|
1373
1384
|
if (this.ensureAuthenticated(), !this.userId)
|
|
1374
|
-
throw new
|
|
1385
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "사용자 ID를 찾을 수 없습니다");
|
|
1375
1386
|
if (!this.walletProvider.signTypedData)
|
|
1376
|
-
throw new
|
|
1387
|
+
throw new m(p.NOT_IMPLEMENTED, "signTypedData가 구현되어 있지 않습니다");
|
|
1377
1388
|
re.validateTypedDataChainId(e, s);
|
|
1378
1389
|
const n = await this.resolveAddress(t == null ? void 0 : t.index);
|
|
1379
1390
|
if (!await this.confirmation.requestConfirmation({
|
|
@@ -1384,7 +1395,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1384
1395
|
dappName: (t == null ? void 0 : t.dappName) ?? this._config.appName,
|
|
1385
1396
|
accountName: t == null ? void 0 : t.accountName
|
|
1386
1397
|
}))
|
|
1387
|
-
throw new
|
|
1398
|
+
throw new m(p.USER_REJECTED, "User rejected the typed data signing request");
|
|
1388
1399
|
try {
|
|
1389
1400
|
const i = await this.withPinRetry(async () => {
|
|
1390
1401
|
let a;
|
|
@@ -1403,7 +1414,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1403
1414
|
address: n.address
|
|
1404
1415
|
};
|
|
1405
1416
|
} catch (i) {
|
|
1406
|
-
throw i instanceof
|
|
1417
|
+
throw i instanceof m ? i : new m(p.SIGNATURE_FAILED, `타입 데이터 서명에 실패했습니다 (${e})`, i);
|
|
1407
1418
|
}
|
|
1408
1419
|
}
|
|
1409
1420
|
/**
|
|
@@ -1439,7 +1450,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1439
1450
|
*/
|
|
1440
1451
|
async signTransaction(e, s, t) {
|
|
1441
1452
|
if (this.ensureAuthenticated(), !this.userId)
|
|
1442
|
-
throw new
|
|
1453
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "사용자 ID를 찾을 수 없습니다");
|
|
1443
1454
|
const n = await this.withResolvedGasAndFee(s, e);
|
|
1444
1455
|
n.from || (n.from = (await this.resolveAddress(t == null ? void 0 : t.index)).address);
|
|
1445
1456
|
const o = Je(e);
|
|
@@ -1459,7 +1470,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1459
1470
|
dappName: (t == null ? void 0 : t.dappName) ?? this._config.appName,
|
|
1460
1471
|
accountName: t == null ? void 0 : t.accountName
|
|
1461
1472
|
}))
|
|
1462
|
-
throw new
|
|
1473
|
+
throw new m(p.USER_REJECTED, "User rejected the transaction signing request");
|
|
1463
1474
|
try {
|
|
1464
1475
|
const a = await this.withPinRetry(async () => {
|
|
1465
1476
|
let c;
|
|
@@ -1477,9 +1488,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1477
1488
|
txHash: a.txHash ?? ""
|
|
1478
1489
|
};
|
|
1479
1490
|
} catch (a) {
|
|
1480
|
-
if (a instanceof
|
|
1491
|
+
if (a instanceof m) throw a;
|
|
1481
1492
|
const c = a instanceof Error ? a.message : String(a);
|
|
1482
|
-
throw new
|
|
1493
|
+
throw new m(
|
|
1483
1494
|
p.SIGNATURE_FAILED,
|
|
1484
1495
|
`트랜잭션 서명에 실패했습니다 (${e}): ${c}`,
|
|
1485
1496
|
a
|
|
@@ -1494,7 +1505,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1494
1505
|
*/
|
|
1495
1506
|
async sendTransaction(e, s, t) {
|
|
1496
1507
|
if (this.ensureAuthenticated(), !this.userId)
|
|
1497
|
-
throw new
|
|
1508
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "사용자 ID를 찾을 수 없습니다");
|
|
1498
1509
|
const n = await this.withResolvedGasAndFee(s, e);
|
|
1499
1510
|
n.from || (n.from = (await this.resolveAddress(t == null ? void 0 : t.index)).address);
|
|
1500
1511
|
const o = Je(e);
|
|
@@ -1514,7 +1525,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1514
1525
|
dappName: (t == null ? void 0 : t.dappName) ?? this._config.appName,
|
|
1515
1526
|
accountName: t == null ? void 0 : t.accountName
|
|
1516
1527
|
}))
|
|
1517
|
-
throw new
|
|
1528
|
+
throw new m(p.USER_REJECTED, "User rejected the transaction request");
|
|
1518
1529
|
try {
|
|
1519
1530
|
const a = await this.withPinRetry(async () => {
|
|
1520
1531
|
let c;
|
|
@@ -1536,9 +1547,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1536
1547
|
});
|
|
1537
1548
|
return { chainId: e, txHash: a, status: "pending" };
|
|
1538
1549
|
} catch (a) {
|
|
1539
|
-
if (a instanceof
|
|
1550
|
+
if (a instanceof m) throw a;
|
|
1540
1551
|
const c = a instanceof Error ? a.message : String(a);
|
|
1541
|
-
throw new
|
|
1552
|
+
throw new m(
|
|
1542
1553
|
p.TRANSACTION_FAILED,
|
|
1543
1554
|
`트랜잭션 전송에 실패했습니다 (${e}): ${c}`,
|
|
1544
1555
|
a
|
|
@@ -1569,9 +1580,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1569
1580
|
for (; Date.now() < a; ) {
|
|
1570
1581
|
const l = await this.getTransactionReceipt(e, s);
|
|
1571
1582
|
if (l) return l;
|
|
1572
|
-
await new Promise((
|
|
1583
|
+
await new Promise((u) => setTimeout(u, c)), c = Math.min(c * 2, o);
|
|
1573
1584
|
}
|
|
1574
|
-
throw new
|
|
1585
|
+
throw new m(
|
|
1575
1586
|
p.UNKNOWN_ERROR,
|
|
1576
1587
|
`트랜잭션 영수증 조회 시간이 초과되었습니다 (${e})`
|
|
1577
1588
|
);
|
|
@@ -1593,11 +1604,11 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1593
1604
|
*/
|
|
1594
1605
|
async sendTransactionWithWaitForReceipt(e, s, t = {}) {
|
|
1595
1606
|
var v, y;
|
|
1596
|
-
const { intervalMs: n, timeoutMs: o, ...i } = t, { txHash: a } = await this.sendTransaction(e, s, i), c = n ?? ((v = this._config.receiptPolling) == null ? void 0 : v.intervalMs) ?? Xs, l = o ?? ((y = this._config.receiptPolling) == null ? void 0 : y.timeoutMs) ?? Tt,
|
|
1597
|
-
let
|
|
1607
|
+
const { intervalMs: n, timeoutMs: o, ...i } = t, { txHash: a } = await this.sendTransaction(e, s, i), c = n ?? ((v = this._config.receiptPolling) == null ? void 0 : v.intervalMs) ?? Xs, l = o ?? ((y = this._config.receiptPolling) == null ? void 0 : y.timeoutMs) ?? Tt, u = Je(e), h = s.from ?? "";
|
|
1608
|
+
let g, _;
|
|
1598
1609
|
const w = this.waitForTxAndGetReceipt(a, e, { intervalMs: c, timeoutMs: l }).then((S) => {
|
|
1599
|
-
|
|
1600
|
-
const C = BigInt(S.gasUsed) * BigInt(S.effectiveGasPrice), U = s.value ? BigInt(s.value) : 0n, N = re.formatTxAmount(s.value,
|
|
1610
|
+
g = S;
|
|
1611
|
+
const C = BigInt(S.gasUsed) * BigInt(S.effectiveGasPrice), U = s.value ? BigInt(s.value) : 0n, N = re.formatTxAmount(s.value, u.symbol, u.decimals), V = re.formatTxAmount("0x" + C.toString(16), u.symbol, u.decimals), W = re.formatTxAmount("0x" + (U + C).toString(16), u.symbol, u.decimals);
|
|
1601
1612
|
return {
|
|
1602
1613
|
chainId: e,
|
|
1603
1614
|
txHash: a,
|
|
@@ -1606,23 +1617,23 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1606
1617
|
amount: N,
|
|
1607
1618
|
fees: V,
|
|
1608
1619
|
total: W,
|
|
1609
|
-
nativeSymbol:
|
|
1620
|
+
nativeSymbol: u.symbol,
|
|
1610
1621
|
status: S.status === "0x1" ? "success" : "reverted"
|
|
1611
1622
|
};
|
|
1612
|
-
}).catch((S) => (
|
|
1623
|
+
}).catch((S) => (_ = S instanceof Error ? S : new Error(String(S)), {
|
|
1613
1624
|
chainId: e,
|
|
1614
1625
|
txHash: a,
|
|
1615
1626
|
from: h,
|
|
1616
1627
|
to: s.to,
|
|
1617
|
-
amount: re.formatTxAmount(s.value,
|
|
1618
|
-
nativeSymbol:
|
|
1628
|
+
amount: re.formatTxAmount(s.value, u.symbol, u.decimals),
|
|
1629
|
+
nativeSymbol: u.symbol,
|
|
1619
1630
|
status: "timeout"
|
|
1620
1631
|
}));
|
|
1621
1632
|
if (await this.confirmation.showTransactionProgress(
|
|
1622
1633
|
{ chainId: e, txHash: a, from: h, to: s.to },
|
|
1623
1634
|
w
|
|
1624
|
-
),
|
|
1625
|
-
return { chainId: e, txHash: a, receipt:
|
|
1635
|
+
), _) throw _;
|
|
1636
|
+
return { chainId: e, txHash: a, receipt: g };
|
|
1626
1637
|
}
|
|
1627
1638
|
// ============================================================================
|
|
1628
1639
|
// PIN 관리 (공개 API)
|
|
@@ -1670,12 +1681,12 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1670
1681
|
this.ensureAuthenticated();
|
|
1671
1682
|
const t = this.walletProvider;
|
|
1672
1683
|
if (typeof t.changePin != "function")
|
|
1673
|
-
throw new
|
|
1684
|
+
throw new m(p.NOT_IMPLEMENTED, "changePin이 구현되어 있지 않습니다");
|
|
1674
1685
|
this.pinStore.set(e);
|
|
1675
1686
|
try {
|
|
1676
|
-
await t.changePin(e, s), this.pinStore.set(s),
|
|
1687
|
+
await t.changePin(e, s), this.pinStore.set(s), d.log("[CROSSx] PIN 변경 완료");
|
|
1677
1688
|
} catch (n) {
|
|
1678
|
-
throw n instanceof
|
|
1689
|
+
throw n instanceof m ? n : new m(p.UNKNOWN_ERROR, "PIN 변경에 실패했습니다", n);
|
|
1679
1690
|
}
|
|
1680
1691
|
}
|
|
1681
1692
|
// ============================================================================
|
|
@@ -1696,7 +1707,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1696
1707
|
return await this.walletRpc("eth_gasPrice", [], e);
|
|
1697
1708
|
} catch (s) {
|
|
1698
1709
|
const t = s instanceof Error ? s.message : String(s);
|
|
1699
|
-
throw new
|
|
1710
|
+
throw new m(p.GAS_ESTIMATION_FAILED, `가스 가격 조회에 실패했습니다 (${e}): ${t}`, s);
|
|
1700
1711
|
}
|
|
1701
1712
|
}
|
|
1702
1713
|
/**
|
|
@@ -1717,7 +1728,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1717
1728
|
return await this.walletRpc("eth_estimateGas", [t], s);
|
|
1718
1729
|
} catch (n) {
|
|
1719
1730
|
const o = n instanceof Error ? n.message : String(n);
|
|
1720
|
-
throw new
|
|
1731
|
+
throw new m(p.GAS_ESTIMATION_FAILED, `가스 추정에 실패했습니다 (${s}): ${o}`, n);
|
|
1721
1732
|
}
|
|
1722
1733
|
}
|
|
1723
1734
|
/**
|
|
@@ -1738,7 +1749,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1738
1749
|
return (s == null ? void 0 : s.baseFeePerGas) ?? null;
|
|
1739
1750
|
} catch (s) {
|
|
1740
1751
|
const t = s instanceof Error ? s.message : String(s);
|
|
1741
|
-
throw new
|
|
1752
|
+
throw new m(p.GAS_ESTIMATION_FAILED, `baseFeePerGas 조회에 실패했습니다 (${e}): ${t}`, s);
|
|
1742
1753
|
}
|
|
1743
1754
|
}
|
|
1744
1755
|
/**
|
|
@@ -1757,7 +1768,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1757
1768
|
return await this.walletRpc("eth_maxPriorityFeePerGas", [], e);
|
|
1758
1769
|
} catch (s) {
|
|
1759
1770
|
const t = s instanceof Error ? s.message : String(s);
|
|
1760
|
-
throw new
|
|
1771
|
+
throw new m(p.GAS_ESTIMATION_FAILED, `maxPriorityFeePerGas 조회에 실패했습니다 (${e}): ${t}`, s);
|
|
1761
1772
|
}
|
|
1762
1773
|
}
|
|
1763
1774
|
// ============================================================================
|
|
@@ -1775,9 +1786,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1775
1786
|
const t = await this.jsonRpc.call("eth_getTransactionCount", [s, "pending"], e);
|
|
1776
1787
|
return parseInt(t ?? "0x0", 16);
|
|
1777
1788
|
} catch (t) {
|
|
1778
|
-
if (t instanceof
|
|
1789
|
+
if (t instanceof m) throw t;
|
|
1779
1790
|
const n = t instanceof Error ? t.message : String(t);
|
|
1780
|
-
throw new
|
|
1791
|
+
throw new m(p.UNKNOWN_ERROR, `Nonce 조회에 실패했습니다: ${n}`, t);
|
|
1781
1792
|
}
|
|
1782
1793
|
}
|
|
1783
1794
|
/**
|
|
@@ -1794,9 +1805,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1794
1805
|
const n = await this.jsonRpc.call("eth_getBalance", [s, "latest"], e) ?? "0x0";
|
|
1795
1806
|
return { wei: n, formatted: re.formatWei(n), chainId: e };
|
|
1796
1807
|
} catch (t) {
|
|
1797
|
-
if (t instanceof
|
|
1808
|
+
if (t instanceof m) throw t;
|
|
1798
1809
|
const n = t instanceof Error ? t.message : String(t);
|
|
1799
|
-
throw new
|
|
1810
|
+
throw new m(p.UNKNOWN_ERROR, `잔액 조회에 실패했습니다 (${e}): ${n}`, t);
|
|
1800
1811
|
}
|
|
1801
1812
|
}
|
|
1802
1813
|
static formatWei(e) {
|
|
@@ -1846,9 +1857,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1846
1857
|
try {
|
|
1847
1858
|
return await this.jsonRpc.call(e, s, t);
|
|
1848
1859
|
} catch (n) {
|
|
1849
|
-
if (n instanceof
|
|
1860
|
+
if (n instanceof m) throw n;
|
|
1850
1861
|
const o = n instanceof Error ? n.message : String(n);
|
|
1851
|
-
throw new
|
|
1862
|
+
throw new m(p.UNKNOWN_ERROR, `walletRpc 호출에 실패했습니다 [${e}] (${t}): ${o}`, n);
|
|
1852
1863
|
}
|
|
1853
1864
|
}
|
|
1854
1865
|
// ============================================================================
|
|
@@ -1877,14 +1888,14 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1877
1888
|
* 4) PIN 잠금 발생 시 카운트다운 화면 표시 → 자동 해제 후 PIN 재입력
|
|
1878
1889
|
*/
|
|
1879
1890
|
async handleMigrationFlow(e) {
|
|
1880
|
-
var c, l,
|
|
1881
|
-
|
|
1891
|
+
var c, l, u;
|
|
1892
|
+
d.log('[CROSSx][Migration Phase 3] "Wallet Found" 팝업 표시');
|
|
1882
1893
|
const s = ((c = this._config.migration) == null ? void 0 : c.allowSkip) ?? !0, t = await this.confirmation.showMigrationFoundPrompt({ allowSkip: s });
|
|
1883
|
-
if (
|
|
1884
|
-
return
|
|
1894
|
+
if (d.log("[CROSSx][Migration Phase 3] 사용자 선택:", t), t === "skip")
|
|
1895
|
+
return d.log("[CROSSx][Migration Phase 3] 사용자가 마이그레이션을 건너뜀 → 종료"), null;
|
|
1885
1896
|
let n, o = 0, i = 5, a = null;
|
|
1886
1897
|
for (; ; ) {
|
|
1887
|
-
o++,
|
|
1898
|
+
o++, d.log(
|
|
1888
1899
|
`[CROSSx][Migration Phase 4] PIN 입력 팝업 표시 (시도 #${o}/${i})`,
|
|
1889
1900
|
n ? `— 이전 메시지: ${n}` : ""
|
|
1890
1901
|
);
|
|
@@ -1894,45 +1905,45 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1894
1905
|
maxAttempts: i
|
|
1895
1906
|
});
|
|
1896
1907
|
if (h === null)
|
|
1897
|
-
return
|
|
1898
|
-
|
|
1908
|
+
return d.log("[CROSSx][Migration Phase 4] 사용자가 PIN 입력을 취소함 → 종료"), null;
|
|
1909
|
+
d.log("[CROSSx][Migration Phase 4] PIN 입력 완료 — verify-recovery-pin API 호출"), n = void 0;
|
|
1899
1910
|
try {
|
|
1900
|
-
const
|
|
1901
|
-
if (!
|
|
1902
|
-
|
|
1911
|
+
const g = await ((u = (l = this.walletProvider).verifyRecoveryPin) == null ? void 0 : u.call(l, h, e));
|
|
1912
|
+
if (!g) {
|
|
1913
|
+
d.log("[CROSSx][Migration Phase 4] verifyRecoveryPin 미지원 — PIN 검증 생략"), a = h;
|
|
1903
1914
|
break;
|
|
1904
1915
|
}
|
|
1905
|
-
if (
|
|
1906
|
-
|
|
1916
|
+
if (g.valid) {
|
|
1917
|
+
d.log("[CROSSx][Migration Phase 4] PIN 검증 성공"), a = h;
|
|
1907
1918
|
break;
|
|
1908
1919
|
}
|
|
1909
|
-
const
|
|
1910
|
-
if (i =
|
|
1911
|
-
const w =
|
|
1912
|
-
|
|
1920
|
+
const _ = g.pinStatus;
|
|
1921
|
+
if (i = _.maxAttempts, o = i - _.remainingAttempts, _.remainingAttempts === 0 && _.lockExpiresAt) {
|
|
1922
|
+
const w = _.lockExpiresAt * 1e3, v = Math.max(1, Math.round((w - Date.now()) / 1e3)), y = v <= 1800 ? "Too many failed attempts. Please try again in 30 minutes." : "Too many failed attempts. Please try again in 24 hours.";
|
|
1923
|
+
d.warn(`[CROSSx][Migration Phase 4] verify-recovery-pin 잠금 — ${v}초, 메시지: ${y}`), await this.confirmation.showRecoveryPinLockedPrompt(v, y), o = 0, n = "Your account lock has been lifted. You may try again.";
|
|
1913
1924
|
} else
|
|
1914
|
-
|
|
1915
|
-
} catch (
|
|
1916
|
-
if (!(
|
|
1917
|
-
if (
|
|
1918
|
-
const
|
|
1919
|
-
if (i = (
|
|
1920
|
-
return
|
|
1921
|
-
const w = ((
|
|
1922
|
-
|
|
1925
|
+
d.warn(`[CROSSx][Migration Phase 4] PIN 불일치 (시도 ${o}/${i})`), n = "Incorrect PIN.";
|
|
1926
|
+
} catch (g) {
|
|
1927
|
+
if (!(g instanceof m)) throw g;
|
|
1928
|
+
if (g.code === p.MIGRATION_PIN_LOCKED) {
|
|
1929
|
+
const _ = g.details;
|
|
1930
|
+
if (i = (_ == null ? void 0 : _.maxAttempts) ?? 5, (_ == null ? void 0 : _.permanent) === !0)
|
|
1931
|
+
return d.warn("[CROSSx][Migration Phase 4] PIN 영구 잠금 (verify-recovery-pin)"), await this.confirmation.showRecoveryPinLockedPrompt(0, "Your account has been permanently locked due to too many failed attempts."), null;
|
|
1932
|
+
const w = ((_ == null ? void 0 : _.lockExpiresAt) ?? 0) * 1e3, v = Math.max(1, Math.round((w - Date.now()) / 1e3)), y = v <= 1800 ? "Too many failed attempts. Please try again in 30 minutes." : "Too many failed attempts. Please try again in 24 hours.";
|
|
1933
|
+
d.warn(`[CROSSx][Migration Phase 4] verify-recovery-pin 이미 잠금 — ${v}초`), await this.confirmation.showRecoveryPinLockedPrompt(v, y), o = 0, n = "Your account lock has been lifted. You may try again.";
|
|
1923
1934
|
} else
|
|
1924
|
-
throw
|
|
1935
|
+
throw d.error("[CROSSx][Migration Phase 4] verify-recovery-pin 실패 (복구 불가):", g), g;
|
|
1925
1936
|
}
|
|
1926
1937
|
}
|
|
1927
|
-
|
|
1938
|
+
d.log("[CROSSx][Migration Phase 5] PIN 검증 완료 — 비밀번호 설정 및 마이그레이션 진행");
|
|
1928
1939
|
try {
|
|
1929
1940
|
await this.ensurePinSetup();
|
|
1930
1941
|
const h = await this.migrateWalletUseCase.execute(a, e);
|
|
1931
|
-
return
|
|
1942
|
+
return d.log("[CROSSx][Migration Phase 5] 마이그레이션 성공 — address:", h.address), h;
|
|
1932
1943
|
} catch (h) {
|
|
1933
|
-
if (h instanceof
|
|
1934
|
-
return
|
|
1935
|
-
throw
|
|
1944
|
+
if (h instanceof m && h.code === p.MIGRATION_FAILED)
|
|
1945
|
+
return d.warn("[CROSSx][Migration Phase 5] migrate PIN 불일치 (경합) — 처음부터 재시도"), this.handleMigrationFlow(e);
|
|
1946
|
+
throw d.error("[CROSSx][Migration Phase 5] 마이그레이션 실패 (복구 불가):", h), h;
|
|
1936
1947
|
}
|
|
1937
1948
|
}
|
|
1938
1949
|
/**
|
|
@@ -1954,21 +1965,21 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1954
1965
|
if (n) {
|
|
1955
1966
|
const l = c.from ?? this.address;
|
|
1956
1967
|
if (l) {
|
|
1957
|
-
|
|
1958
|
-
const
|
|
1959
|
-
c.nonce = parseInt(
|
|
1968
|
+
d.log("[CROSSx] nonce 비어있음 → eth_getTransactionCount 호출 (from:", l, ")");
|
|
1969
|
+
const u = await this.jsonRpc.call("eth_getTransactionCount", [l, "pending"], s);
|
|
1970
|
+
c.nonce = parseInt(u ?? "0x0", 16), d.log("[CROSSx] nonce 결과:", c.nonce);
|
|
1960
1971
|
}
|
|
1961
1972
|
}
|
|
1962
|
-
if (o && (
|
|
1963
|
-
|
|
1973
|
+
if (o && (d.log("[CROSSx] gasLimit 비어있음 → eth_estimateGas 호출"), c.gasLimit = await this.estimateGas(e, s), d.log("[CROSSx] estimateGas 결과:", c.gasLimit)), i) {
|
|
1974
|
+
d.log("[CROSSx] gasPrice & maxFeePerGas 비어있음 → baseFee 조회로 Dynamic/Legacy 판별");
|
|
1964
1975
|
const l = await this.getBaseFeePerGas(s);
|
|
1965
1976
|
if (l) {
|
|
1966
|
-
const
|
|
1967
|
-
c.maxFeePerGas = "0x" + (BigInt(l) + BigInt(
|
|
1977
|
+
const u = Rt;
|
|
1978
|
+
c.maxFeePerGas = "0x" + (BigInt(l) + BigInt(u)).toString(16), c.maxPriorityFeePerGas = u, d.log("[CROSSx] Dynamic 체인 감지 — baseFee:", l, "maxFeePerGas:", c.maxFeePerGas, "maxPriorityFeePerGas: 1 Gwei");
|
|
1968
1979
|
} else
|
|
1969
|
-
c.gasPrice = er,
|
|
1980
|
+
c.gasPrice = er, d.log("[CROSSx] Legacy 체인 감지 — gasPrice: 2 Gwei");
|
|
1970
1981
|
}
|
|
1971
|
-
return !i && a && (c.maxPriorityFeePerGas = Rt,
|
|
1982
|
+
return !i && a && (c.maxPriorityFeePerGas = Rt, d.log("[CROSSx] maxPriorityFeePerGas 비어있음 → 1 Gwei 기본값 적용")), c;
|
|
1972
1983
|
}
|
|
1973
1984
|
/**
|
|
1974
1985
|
* EIP-712 signTypedData 호출 시 chainId와 typedData.domain.chainId 정합성 검증.
|
|
@@ -1980,7 +1991,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1980
1991
|
const t = re.extractDomainChainId(s);
|
|
1981
1992
|
if (e === "0") {
|
|
1982
1993
|
if (t !== void 0 && t !== 0)
|
|
1983
|
-
throw new
|
|
1994
|
+
throw new m(
|
|
1984
1995
|
p.TYPED_DATA_CHAIN_ID_MISMATCH,
|
|
1985
1996
|
`오프체인 서명(chainId=0)에서는 typedData.domain.chainId가 없거나 0이어야 합니다. 현재 값: ${t}`
|
|
1986
1997
|
);
|
|
@@ -1990,12 +2001,12 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1990
2001
|
if (n) {
|
|
1991
2002
|
const o = Number(n[1]);
|
|
1992
2003
|
if (t === void 0)
|
|
1993
|
-
throw new
|
|
2004
|
+
throw new m(
|
|
1994
2005
|
p.TYPED_DATA_CHAIN_ID_MISMATCH,
|
|
1995
2006
|
`온체인 서명(${e})에서는 typedData.domain.chainId가 반드시 있어야 합니다`
|
|
1996
2007
|
);
|
|
1997
2008
|
if (t !== o)
|
|
1998
|
-
throw new
|
|
2009
|
+
throw new m(
|
|
1999
2010
|
p.TYPED_DATA_CHAIN_ID_MISMATCH,
|
|
2000
2011
|
`typedData.domain.chainId (${t})가 chainId (${e}, 예상값: ${o})와 일치하지 않습니다`
|
|
2001
2012
|
);
|
|
@@ -2014,9 +2025,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2014
2025
|
static validateSignatureFormat(e) {
|
|
2015
2026
|
const s = e.startsWith("0x") ? e.slice(2) : e;
|
|
2016
2027
|
if (!/^[0-9a-fA-F]+$/.test(s))
|
|
2017
|
-
throw new
|
|
2028
|
+
throw new m(p.SIGNATURE_FAILED, "유효하지 않은 서명: 올바른 hex 문자열이 아닙니다");
|
|
2018
2029
|
if (s.length !== kt)
|
|
2019
|
-
throw new
|
|
2030
|
+
throw new m(
|
|
2020
2031
|
p.SIGNATURE_FAILED,
|
|
2021
2032
|
`서명 길이가 유효하지 않습니다: ${kt} hex 문자(65 바이트) 예상, 현재 ${s.length}`
|
|
2022
2033
|
);
|
|
@@ -2025,9 +2036,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2025
2036
|
static validateSignedTxFormat(e) {
|
|
2026
2037
|
const s = e.startsWith("0x") ? e.slice(2) : e;
|
|
2027
2038
|
if (!/^[0-9a-fA-F]+$/.test(s))
|
|
2028
|
-
throw new
|
|
2039
|
+
throw new m(p.SIGNATURE_FAILED, "유효하지 않은 서명된 트랜잭션: 올바른 hex 문자열이 아닙니다");
|
|
2029
2040
|
if (s.length < 2)
|
|
2030
|
-
throw new
|
|
2041
|
+
throw new m(p.SIGNATURE_FAILED, "유효하지 않은 서명된 트랜잭션: 너무 짧습니다");
|
|
2031
2042
|
}
|
|
2032
2043
|
/**
|
|
2033
2044
|
* Gateway 서명 응답의 ecrecover 검증 (XF-036)
|
|
@@ -2040,17 +2051,17 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2040
2051
|
try {
|
|
2041
2052
|
const n = this.crypto.recoverPersonalSignSigner(e, s);
|
|
2042
2053
|
if (n.toLowerCase() !== t.toLowerCase())
|
|
2043
|
-
throw
|
|
2054
|
+
throw d.error("[CROSSx] 서명 검증 실패: 서명자 주소 불일치", {
|
|
2044
2055
|
expected: t,
|
|
2045
2056
|
recovered: n
|
|
2046
|
-
}), new
|
|
2057
|
+
}), new m(
|
|
2047
2058
|
p.SIGNATURE_SIGNER_MISMATCH,
|
|
2048
2059
|
`서명자 주소가 일치하지 않습니다: 예상 ${t}, 복원된 주소 ${n}`
|
|
2049
2060
|
);
|
|
2050
|
-
|
|
2061
|
+
d.log("[CROSSx] 서명 ecrecover 검증 성공");
|
|
2051
2062
|
} catch (n) {
|
|
2052
|
-
if (n instanceof
|
|
2053
|
-
|
|
2063
|
+
if (n instanceof m) throw n;
|
|
2064
|
+
d.warn("[CROSSx] ecrecover 검증 중 예외 (무시):", n);
|
|
2054
2065
|
}
|
|
2055
2066
|
}
|
|
2056
2067
|
/** AuthResult를 내부 상태에 반영합니다. */
|
|
@@ -2076,7 +2087,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2076
2087
|
* (서버 세션 종료 API를 호출하면 또 다시 -10002가 날 수 있으므로 스킵)
|
|
2077
2088
|
*/
|
|
2078
2089
|
forceLogout() {
|
|
2079
|
-
this.authenticated && (
|
|
2090
|
+
this.authenticated && (d.warn("[CROSSx] 인증 만료(Gateway -10002) — 강제 로그아웃"), this.clearAuthState());
|
|
2080
2091
|
}
|
|
2081
2092
|
/**
|
|
2082
2093
|
* Firebase sign_in_provider 값을 정규화합니다.
|
|
@@ -2094,8 +2105,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2094
2105
|
if (this.pinStore.has()) return;
|
|
2095
2106
|
const e = await this.confirmation.showPinSetupPrompt();
|
|
2096
2107
|
if (!e)
|
|
2097
|
-
throw new
|
|
2098
|
-
this.pinStore.set(e),
|
|
2108
|
+
throw new m(p.PIN_CANCELLED, "사용자가 PIN 설정을 취소했습니다");
|
|
2109
|
+
this.pinStore.set(e), d.log("[CROSSx] PIN 설정 완료 (메모리 캐시)");
|
|
2099
2110
|
}
|
|
2100
2111
|
/**
|
|
2101
2112
|
* 서명/전송 전 PIN 입력 모달 표시 후 메모리 캐시
|
|
@@ -2108,8 +2119,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2108
2119
|
e && this.pinStore.clear();
|
|
2109
2120
|
const s = await this.confirmation.showPinInputPrompt({ errorMessage: e });
|
|
2110
2121
|
if (!s)
|
|
2111
|
-
throw new
|
|
2112
|
-
this.pinStore.set(s),
|
|
2122
|
+
throw new m(p.PIN_CANCELLED, "사용자가 PIN 입력을 취소했습니다");
|
|
2123
|
+
this.pinStore.set(s), d.log("[CROSSx] PIN 입력 완료 (메모리 캐시)");
|
|
2113
2124
|
}
|
|
2114
2125
|
/**
|
|
2115
2126
|
* PIN 입력 + verify-password API로 서버 검증
|
|
@@ -2129,7 +2140,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2129
2140
|
else if (this.pinStore.has())
|
|
2130
2141
|
return;
|
|
2131
2142
|
if (this._verifyPinMutex && !e) {
|
|
2132
|
-
|
|
2143
|
+
d.log("[CROSSx] ensureVerifiedPin: 진행 중인 검증 대기"), await this._verifyPinMutex;
|
|
2133
2144
|
return;
|
|
2134
2145
|
}
|
|
2135
2146
|
let t, n;
|
|
@@ -2144,8 +2155,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2144
2155
|
lockExpiresAt: s
|
|
2145
2156
|
});
|
|
2146
2157
|
if (!i)
|
|
2147
|
-
throw new
|
|
2148
|
-
this.pinStore.set(i),
|
|
2158
|
+
throw new m(p.PIN_CANCELLED, "사용자가 PIN 입력을 취소했습니다");
|
|
2159
|
+
this.pinStore.set(i), d.log("[CROSSx] PIN 캐시 완료 (verifyPin 미지원, 로컬 전용)"), t();
|
|
2149
2160
|
return;
|
|
2150
2161
|
}
|
|
2151
2162
|
const o = await this.confirmation.showPinInputPrompt({
|
|
@@ -2156,9 +2167,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2156
2167
|
var a;
|
|
2157
2168
|
this.pinStore.set(i);
|
|
2158
2169
|
try {
|
|
2159
|
-
return await this.walletProvider.verifyPin(i) ? (
|
|
2170
|
+
return await this.walletProvider.verifyPin(i) ? (d.log("[CROSSx] PIN 서버 검증 완료 (verify-password)"), { ok: !0 }) : (this.pinStore.clear(), { ok: !1, error: "Incorrect PIN. Please try again." });
|
|
2160
2171
|
} catch (c) {
|
|
2161
|
-
if (this.pinStore.clear(), c instanceof
|
|
2172
|
+
if (this.pinStore.clear(), c instanceof m) {
|
|
2162
2173
|
if (c.code === p.PIN_WRONG)
|
|
2163
2174
|
return { ok: !1, error: "Incorrect PIN. Please try again." };
|
|
2164
2175
|
if (c.code === p.PIN_INVALID)
|
|
@@ -2171,8 +2182,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2171
2182
|
}
|
|
2172
2183
|
});
|
|
2173
2184
|
if (!o)
|
|
2174
|
-
throw new
|
|
2175
|
-
this.pinStore.set(o),
|
|
2185
|
+
throw new m(p.PIN_CANCELLED, "사용자가 PIN 입력을 취소했습니다");
|
|
2186
|
+
this.pinStore.set(o), d.log("[CROSSx] PIN 갱신 완료 (verify 모달 닫힘)"), t();
|
|
2176
2187
|
} catch (o) {
|
|
2177
2188
|
throw n(o), o;
|
|
2178
2189
|
} finally {
|
|
@@ -2189,16 +2200,16 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2189
2200
|
async loadWalletAfterAuth(e) {
|
|
2190
2201
|
if (!this.userId) return;
|
|
2191
2202
|
const s = await this.fetchWalletStatus();
|
|
2192
|
-
if (
|
|
2203
|
+
if (d.log("[CROSSx] loadWalletAfterAuth 지갑 상태:", s), s !== "exists") return;
|
|
2193
2204
|
const t = await this.walletProvider.getAddresses(this.userId);
|
|
2194
2205
|
if (t.length > 0) {
|
|
2195
2206
|
const o = e !== void 0 ? t.find((i) => i.index === e) ?? t[0] : t[0];
|
|
2196
|
-
this.address = o.address, this.activeWalletIndex = o.index,
|
|
2207
|
+
this.address = o.address, this.activeWalletIndex = o.index, d.log("[CROSSx] 캐시된 주소 로드 완료 (비밀번호 불필요):", this.address), this.emit("addressChanged", { address: o.address, index: o.index });
|
|
2197
2208
|
return;
|
|
2198
2209
|
}
|
|
2199
|
-
|
|
2210
|
+
d.log("[CROSSx] 주소 캐시 없음 — 비밀번호 확인 후 address(0) 조회"), await this.ensureVerifiedPin();
|
|
2200
2211
|
const n = await this.walletProvider.getAddress(this.userId, 0);
|
|
2201
|
-
this.address = n.address, this.activeWalletIndex = 0,
|
|
2212
|
+
this.address = n.address, this.activeWalletIndex = 0, d.log("[CROSSx] 세션 복원 후 지갑 주소 로드 완료:", this.address), this.emit("addressChanged", { address: n.address, index: 0 });
|
|
2202
2213
|
}
|
|
2203
2214
|
/**
|
|
2204
2215
|
* PIN_WRONG 에러 시 서버 검증 포함 PIN 재입력 모달을 표시하고 재시도합니다.
|
|
@@ -2218,7 +2229,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2218
2229
|
try {
|
|
2219
2230
|
return await e();
|
|
2220
2231
|
} catch (n) {
|
|
2221
|
-
if (n instanceof
|
|
2232
|
+
if (n instanceof m)
|
|
2222
2233
|
if (n.code === p.PIN_WRONG)
|
|
2223
2234
|
s = "Incorrect PIN. Please enter your current PIN.";
|
|
2224
2235
|
else if (n.code === p.PIN_INVALID)
|
|
@@ -2232,11 +2243,11 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2232
2243
|
throw n;
|
|
2233
2244
|
}
|
|
2234
2245
|
for (; ; ) {
|
|
2235
|
-
|
|
2246
|
+
d.warn("[CROSSx] PIN 불일치/잠금 — 재입력 요청:", s), this.pinStore.clear(), await this.ensureVerifiedPin(s, t), t = void 0;
|
|
2236
2247
|
try {
|
|
2237
2248
|
return await e();
|
|
2238
2249
|
} catch (n) {
|
|
2239
|
-
if (n instanceof
|
|
2250
|
+
if (n instanceof m) {
|
|
2240
2251
|
if (n.code === p.PIN_WRONG) {
|
|
2241
2252
|
s = "Incorrect PIN. Please try again.";
|
|
2242
2253
|
continue;
|
|
@@ -2264,21 +2275,21 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2264
2275
|
async resolveAddress(e) {
|
|
2265
2276
|
if (e === void 0 || e === this.activeWalletIndex) {
|
|
2266
2277
|
if (!this.address)
|
|
2267
|
-
throw new
|
|
2278
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "활성 지갑 주소를 찾을 수 없습니다");
|
|
2268
2279
|
return { address: this.address, index: this.activeWalletIndex };
|
|
2269
2280
|
}
|
|
2270
2281
|
return { address: (await this.withPinRetry(() => this.walletProvider.getAddress(this.userId, e))).address, index: e };
|
|
2271
2282
|
}
|
|
2272
2283
|
ensureInitialized() {
|
|
2273
2284
|
if (!this.initialized)
|
|
2274
|
-
throw new
|
|
2285
|
+
throw new m(
|
|
2275
2286
|
p.AUTH_NOT_INITIALIZED,
|
|
2276
2287
|
"SDK가 초기화되지 않았습니다. initialize()를 먼저 호출하세요."
|
|
2277
2288
|
);
|
|
2278
2289
|
}
|
|
2279
2290
|
ensureAuthenticated() {
|
|
2280
2291
|
if (this.ensureInitialized(), !this.authenticated)
|
|
2281
|
-
throw new
|
|
2292
|
+
throw new m(
|
|
2282
2293
|
p.AUTH_NOT_AUTHENTICATED,
|
|
2283
2294
|
"인증되지 않은 상태입니다. signIn()을 먼저 호출하세요."
|
|
2284
2295
|
);
|
|
@@ -2321,7 +2332,7 @@ class rr {
|
|
|
2321
2332
|
const t = JSON.stringify(s);
|
|
2322
2333
|
localStorage.setItem(this.prefix + e, t);
|
|
2323
2334
|
} catch (t) {
|
|
2324
|
-
throw
|
|
2335
|
+
throw d.error("Storage set error:", t), t;
|
|
2325
2336
|
}
|
|
2326
2337
|
}
|
|
2327
2338
|
async get(e) {
|
|
@@ -2329,14 +2340,14 @@ class rr {
|
|
|
2329
2340
|
const s = localStorage.getItem(this.prefix + e);
|
|
2330
2341
|
return s ? JSON.parse(s) : null;
|
|
2331
2342
|
} catch (s) {
|
|
2332
|
-
return
|
|
2343
|
+
return d.error("Storage get error:", s), null;
|
|
2333
2344
|
}
|
|
2334
2345
|
}
|
|
2335
2346
|
async remove(e) {
|
|
2336
2347
|
try {
|
|
2337
2348
|
localStorage.removeItem(this.prefix + e);
|
|
2338
2349
|
} catch (s) {
|
|
2339
|
-
throw
|
|
2350
|
+
throw d.error("Storage remove error:", s), s;
|
|
2340
2351
|
}
|
|
2341
2352
|
}
|
|
2342
2353
|
async clear() {
|
|
@@ -2345,7 +2356,7 @@ class rr {
|
|
|
2345
2356
|
s.startsWith(this.prefix) && localStorage.removeItem(s);
|
|
2346
2357
|
});
|
|
2347
2358
|
} catch (e) {
|
|
2348
|
-
throw
|
|
2359
|
+
throw d.error("Storage clear error:", e), e;
|
|
2349
2360
|
}
|
|
2350
2361
|
}
|
|
2351
2362
|
}
|
|
@@ -2415,25 +2426,25 @@ class Ot {
|
|
|
2415
2426
|
async migrateFromLegacyDB() {
|
|
2416
2427
|
if (this.dbName === Xe) return null;
|
|
2417
2428
|
try {
|
|
2418
|
-
const e = await this.openDB(Xe), s = e.transaction([Se, de], "readonly"), t = s.objectStore(Se).get($e), n = await new Promise((l,
|
|
2419
|
-
t.onsuccess = () => l(t.result), t.onerror = () =>
|
|
2429
|
+
const e = await this.openDB(Xe), s = e.transaction([Se, de], "readonly"), t = s.objectStore(Se).get($e), n = await new Promise((l, u) => {
|
|
2430
|
+
t.onsuccess = () => l(t.result), t.onerror = () => u(t.error);
|
|
2420
2431
|
});
|
|
2421
2432
|
if (!n)
|
|
2422
2433
|
return e.close(), null;
|
|
2423
2434
|
const o = s.objectStore(de).getAll(), i = s.objectStore(de).getAllKeys(), [a, c] = await Promise.all([
|
|
2424
|
-
new Promise((l,
|
|
2425
|
-
o.onsuccess = () => l(o.result), o.onerror = () =>
|
|
2435
|
+
new Promise((l, u) => {
|
|
2436
|
+
o.onsuccess = () => l(o.result), o.onerror = () => u(o.error);
|
|
2426
2437
|
}),
|
|
2427
|
-
new Promise((l,
|
|
2428
|
-
i.onsuccess = () => l(i.result), i.onerror = () =>
|
|
2438
|
+
new Promise((l, u) => {
|
|
2439
|
+
i.onsuccess = () => l(i.result), i.onerror = () => u(i.error);
|
|
2429
2440
|
})
|
|
2430
2441
|
]);
|
|
2431
2442
|
e.close(), await this.idbPut(Se, $e, n);
|
|
2432
2443
|
for (let l = 0; l < c.length; l++)
|
|
2433
2444
|
await this.idbPut(de, String(c[l]), a[l]);
|
|
2434
|
-
return indexedDB.deleteDatabase(Xe),
|
|
2445
|
+
return indexedDB.deleteDatabase(Xe), d.log("[CROSSx] IndexedDB 레거시 DB 마이그레이션 완료"), n;
|
|
2435
2446
|
} catch (e) {
|
|
2436
|
-
return
|
|
2447
|
+
return d.warn("[CROSSx] IndexedDB 레거시 DB 마이그레이션 실패:", e), null;
|
|
2437
2448
|
}
|
|
2438
2449
|
}
|
|
2439
2450
|
async encrypt(e) {
|
|
@@ -2460,7 +2471,7 @@ class Ot {
|
|
|
2460
2471
|
const t = JSON.stringify(s), n = await this.encrypt(t);
|
|
2461
2472
|
await this.idbPut(de, e, n);
|
|
2462
2473
|
} catch (t) {
|
|
2463
|
-
throw
|
|
2474
|
+
throw d.error("[CROSSx] IndexedDB set error:", t), t;
|
|
2464
2475
|
}
|
|
2465
2476
|
}
|
|
2466
2477
|
async get(e) {
|
|
@@ -2471,21 +2482,21 @@ class Ot {
|
|
|
2471
2482
|
const t = await this.decrypt(s);
|
|
2472
2483
|
return JSON.parse(t);
|
|
2473
2484
|
} catch (s) {
|
|
2474
|
-
return
|
|
2485
|
+
return d.error("[CROSSx] IndexedDB get error:", s), null;
|
|
2475
2486
|
}
|
|
2476
2487
|
}
|
|
2477
2488
|
async remove(e) {
|
|
2478
2489
|
try {
|
|
2479
2490
|
await this.ensureReady(), await this.idbDelete(de, e);
|
|
2480
2491
|
} catch (s) {
|
|
2481
|
-
throw
|
|
2492
|
+
throw d.error("[CROSSx] IndexedDB remove error:", s), s;
|
|
2482
2493
|
}
|
|
2483
2494
|
}
|
|
2484
2495
|
async clear() {
|
|
2485
2496
|
try {
|
|
2486
2497
|
await this.ensureReady(), await this.idbClear(de);
|
|
2487
2498
|
} catch (e) {
|
|
2488
|
-
throw
|
|
2499
|
+
throw d.error("[CROSSx] IndexedDB clear error:", e), e;
|
|
2489
2500
|
}
|
|
2490
2501
|
}
|
|
2491
2502
|
/**
|
|
@@ -2662,11 +2673,11 @@ class fr {
|
|
|
2662
2673
|
const a = Ze(e), c = this.outputLen;
|
|
2663
2674
|
if (c % 4)
|
|
2664
2675
|
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
2665
|
-
const l = c / 4,
|
|
2666
|
-
if (l >
|
|
2676
|
+
const l = c / 4, u = this.get();
|
|
2677
|
+
if (l > u.length)
|
|
2667
2678
|
throw new Error("_sha2: outputLen bigger than state");
|
|
2668
2679
|
for (let h = 0; h < l; h++)
|
|
2669
|
-
a.setUint32(4 * h,
|
|
2680
|
+
a.setUint32(4 * h, u[h], o);
|
|
2670
2681
|
}
|
|
2671
2682
|
digest() {
|
|
2672
2683
|
const { buffer: e, outputLen: s } = this;
|
|
@@ -2787,15 +2798,15 @@ class vr extends fr {
|
|
|
2787
2798
|
for (let h = 0; h < 16; h++, s += 4)
|
|
2788
2799
|
we[h] = e.getUint32(s, !1);
|
|
2789
2800
|
for (let h = 16; h < 64; h++) {
|
|
2790
|
-
const
|
|
2801
|
+
const g = we[h - 15], _ = we[h - 2], w = ue(g, 7) ^ ue(g, 18) ^ g >>> 3, v = ue(_, 17) ^ ue(_, 19) ^ _ >>> 10;
|
|
2791
2802
|
we[h] = v + we[h - 7] + w + we[h - 16] | 0;
|
|
2792
2803
|
}
|
|
2793
|
-
let { A: t, B: n, C: o, D: i, E: a, F: c, G: l, H:
|
|
2804
|
+
let { A: t, B: n, C: o, D: i, E: a, F: c, G: l, H: u } = this;
|
|
2794
2805
|
for (let h = 0; h < 64; h++) {
|
|
2795
|
-
const
|
|
2796
|
-
|
|
2806
|
+
const g = ue(a, 6) ^ ue(a, 11) ^ ue(a, 25), _ = u + g + hr(a, c, l) + br[h] + we[h] | 0, v = (ue(t, 2) ^ ue(t, 13) ^ ue(t, 22)) + pr(t, n, o) | 0;
|
|
2807
|
+
u = l, l = c, c = a, a = i + _ | 0, i = o, o = n, n = t, t = _ + v | 0;
|
|
2797
2808
|
}
|
|
2798
|
-
t = t + this.A | 0, n = n + this.B | 0, o = o + this.C | 0, i = i + this.D | 0, a = a + this.E | 0, c = c + this.F | 0, l = l + this.G | 0,
|
|
2809
|
+
t = t + this.A | 0, n = n + this.B | 0, o = o + this.C | 0, i = i + this.D | 0, a = a + this.E | 0, c = c + this.F | 0, l = l + this.G | 0, u = u + this.H | 0, this.set(t, n, o, i, a, c, l, u);
|
|
2799
2810
|
}
|
|
2800
2811
|
roundClean() {
|
|
2801
2812
|
Pe(we);
|
|
@@ -2887,28 +2898,28 @@ function kr(r, e, s) {
|
|
|
2887
2898
|
if (ge(r, "hashLen"), ge(e, "qByteLen"), typeof s != "function")
|
|
2888
2899
|
throw new Error("hmacFn must be a function");
|
|
2889
2900
|
const t = (y) => new Uint8Array(y), n = Uint8Array.of(), o = Uint8Array.of(0), i = Uint8Array.of(1), a = 1e3;
|
|
2890
|
-
let c = t(r), l = t(r),
|
|
2901
|
+
let c = t(r), l = t(r), u = 0;
|
|
2891
2902
|
const h = () => {
|
|
2892
|
-
c.fill(1), l.fill(0),
|
|
2893
|
-
},
|
|
2894
|
-
l =
|
|
2903
|
+
c.fill(1), l.fill(0), u = 0;
|
|
2904
|
+
}, g = (...y) => s(l, ve(c, ...y)), _ = (y = n) => {
|
|
2905
|
+
l = g(o, y), c = g(), y.length !== 0 && (l = g(i, y), c = g());
|
|
2895
2906
|
}, w = () => {
|
|
2896
|
-
if (
|
|
2907
|
+
if (u++ >= a)
|
|
2897
2908
|
throw new Error("drbg: tried max amount of iterations");
|
|
2898
2909
|
let y = 0;
|
|
2899
2910
|
const S = [];
|
|
2900
2911
|
for (; y < e; ) {
|
|
2901
|
-
c =
|
|
2912
|
+
c = g();
|
|
2902
2913
|
const C = c.slice();
|
|
2903
2914
|
S.push(C), y += c.length;
|
|
2904
2915
|
}
|
|
2905
2916
|
return ve(...S);
|
|
2906
2917
|
};
|
|
2907
2918
|
return (y, S) => {
|
|
2908
|
-
h(),
|
|
2919
|
+
h(), _(y);
|
|
2909
2920
|
let C;
|
|
2910
2921
|
for (; !(C = S(w())); )
|
|
2911
|
-
|
|
2922
|
+
_();
|
|
2912
2923
|
return h(), C;
|
|
2913
2924
|
};
|
|
2914
2925
|
}
|
|
@@ -2977,10 +2988,10 @@ function Or(r, e) {
|
|
|
2977
2988
|
function Cr(r) {
|
|
2978
2989
|
const e = je(r), s = xs(r), t = s(e, e.neg(e.ONE)), n = s(e, t), o = s(e, e.neg(t)), i = (r + Pr) / fs;
|
|
2979
2990
|
return (a, c) => {
|
|
2980
|
-
let l = a.pow(c, i),
|
|
2981
|
-
const h = a.mul(l, n),
|
|
2982
|
-
l = a.cmov(l,
|
|
2983
|
-
const v = a.eql(a.sqr(
|
|
2991
|
+
let l = a.pow(c, i), u = a.mul(l, t);
|
|
2992
|
+
const h = a.mul(l, n), g = a.mul(l, o), _ = a.eql(a.sqr(u), c), w = a.eql(a.sqr(h), c);
|
|
2993
|
+
l = a.cmov(l, u, _), u = a.cmov(g, h, w);
|
|
2994
|
+
const v = a.eql(a.sqr(u), c), y = a.cmov(l, u, v);
|
|
2984
2995
|
return xt(a, y, c), y;
|
|
2985
2996
|
};
|
|
2986
2997
|
}
|
|
@@ -3004,18 +3015,18 @@ function xs(r) {
|
|
|
3004
3015
|
return l;
|
|
3005
3016
|
if (Bt(c, l) !== 1)
|
|
3006
3017
|
throw new Error("Cannot find square root");
|
|
3007
|
-
let
|
|
3008
|
-
for (; !c.eql(
|
|
3009
|
-
if (c.is0(
|
|
3018
|
+
let u = s, h = c.mul(c.ONE, o), g = c.pow(l, e), _ = c.pow(l, i);
|
|
3019
|
+
for (; !c.eql(g, c.ONE); ) {
|
|
3020
|
+
if (c.is0(g))
|
|
3010
3021
|
return c.ZERO;
|
|
3011
|
-
let w = 1, v = c.sqr(
|
|
3022
|
+
let w = 1, v = c.sqr(g);
|
|
3012
3023
|
for (; !c.eql(v, c.ONE); )
|
|
3013
|
-
if (w++, v = c.sqr(v), w ===
|
|
3024
|
+
if (w++, v = c.sqr(v), w === u)
|
|
3014
3025
|
throw new Error("Cannot find square root");
|
|
3015
|
-
const y = ee << BigInt(
|
|
3016
|
-
|
|
3026
|
+
const y = ee << BigInt(u - w - 1), S = c.pow(h, y);
|
|
3027
|
+
u = w, h = c.sqr(S), g = c.mul(g, h), _ = c.mul(_, S);
|
|
3017
3028
|
}
|
|
3018
|
-
return
|
|
3029
|
+
return _;
|
|
3019
3030
|
};
|
|
3020
3031
|
}
|
|
3021
3032
|
function Lr(r) {
|
|
@@ -3231,8 +3242,8 @@ function Ht(r, e, s) {
|
|
|
3231
3242
|
const { windowSize: t, mask: n, maxNumber: o, shiftBy: i } = s;
|
|
3232
3243
|
let a = Number(r & n), c = r >> i;
|
|
3233
3244
|
a > t && (a -= o, c += Ae);
|
|
3234
|
-
const l = e * t,
|
|
3235
|
-
return { nextN: c, offset:
|
|
3245
|
+
const l = e * t, u = l + Math.abs(a) - 1, h = a === 0, g = a < 0, _ = e % 2 !== 0;
|
|
3246
|
+
return { nextN: c, offset: u, isZero: h, isNeg: g, isNegF: _, offsetF: l };
|
|
3236
3247
|
}
|
|
3237
3248
|
const et = /* @__PURE__ */ new WeakMap(), bs = /* @__PURE__ */ new WeakMap();
|
|
3238
3249
|
function tt(r) {
|
|
@@ -3293,8 +3304,8 @@ class Fr {
|
|
|
3293
3304
|
let n = this.ZERO, o = this.BASE;
|
|
3294
3305
|
const i = Qe(e, this.bits);
|
|
3295
3306
|
for (let a = 0; a < i.windows; a++) {
|
|
3296
|
-
const { nextN: c, offset: l, isZero:
|
|
3297
|
-
t = c,
|
|
3307
|
+
const { nextN: c, offset: l, isZero: u, isNeg: h, isNegF: g, offsetF: _ } = Ht(t, a, i);
|
|
3308
|
+
t = c, u ? o = o.add(Ke(g, s[_])) : n = n.add(Ke(h, s[l]));
|
|
3298
3309
|
}
|
|
3299
3310
|
return Ft(t), { p: n, f: o };
|
|
3300
3311
|
}
|
|
@@ -3306,10 +3317,10 @@ class Fr {
|
|
|
3306
3317
|
wNAFUnsafe(e, s, t, n = this.ZERO) {
|
|
3307
3318
|
const o = Qe(e, this.bits);
|
|
3308
3319
|
for (let i = 0; i < o.windows && t !== Ne; i++) {
|
|
3309
|
-
const { nextN: a, offset: c, isZero: l, isNeg:
|
|
3320
|
+
const { nextN: a, offset: c, isZero: l, isNeg: u } = Ht(t, i, o);
|
|
3310
3321
|
if (t = a, !l) {
|
|
3311
3322
|
const h = s[c];
|
|
3312
|
-
n = n.add(
|
|
3323
|
+
n = n.add(u ? h.negate() : h);
|
|
3313
3324
|
}
|
|
3314
3325
|
}
|
|
3315
3326
|
return Ft(t), n;
|
|
@@ -3418,13 +3429,13 @@ Ss.create = (r, e) => new vs(r, e);
|
|
|
3418
3429
|
const Wt = (r, e) => (r + (r >= 0 ? e : -e) / Es) / e;
|
|
3419
3430
|
function Kr(r, e, s) {
|
|
3420
3431
|
const [[t, n], [o, i]] = e, a = Wt(i * r, s), c = Wt(-n * r, s);
|
|
3421
|
-
let l = r - a * t - c * o,
|
|
3422
|
-
const h = l < _e,
|
|
3423
|
-
h && (l = -l),
|
|
3424
|
-
const
|
|
3425
|
-
if (l < _e || l >=
|
|
3432
|
+
let l = r - a * t - c * o, u = -a * n - c * i;
|
|
3433
|
+
const h = l < _e, g = u < _e;
|
|
3434
|
+
h && (l = -l), g && (u = -u);
|
|
3435
|
+
const _ = ft(Math.ceil(Rr(s) / 2)) + Re;
|
|
3436
|
+
if (l < _e || l >= _ || u < _e || u >= _)
|
|
3426
3437
|
throw new Error("splitScalar (endomorphism): failed, k=" + r);
|
|
3427
|
-
return { k1neg: h, k1: l, k2neg:
|
|
3438
|
+
return { k1neg: h, k1: l, k2neg: g, k2: u };
|
|
3428
3439
|
}
|
|
3429
3440
|
function ct(r) {
|
|
3430
3441
|
if (!["compact", "recovered", "der"].includes(r))
|
|
@@ -3482,8 +3493,8 @@ const ye = {
|
|
|
3482
3493
|
throw new s("tlv.decode: length bytes not complete");
|
|
3483
3494
|
if (l[0] === 0)
|
|
3484
3495
|
throw new s("tlv.decode(long): zero leftmost byte");
|
|
3485
|
-
for (const
|
|
3486
|
-
i = i << 8 |
|
|
3496
|
+
for (const u of l)
|
|
3497
|
+
i = i << 8 | u;
|
|
3487
3498
|
if (t += c, i < 128)
|
|
3488
3499
|
throw new s("tlv.decode(long): not minimal encoding");
|
|
3489
3500
|
}
|
|
@@ -3520,8 +3531,8 @@ const ye = {
|
|
|
3520
3531
|
const { Err: e, _int: s, _tlv: t } = ye, n = z(r, void 0, "signature"), { v: o, l: i } = t.decode(48, n);
|
|
3521
3532
|
if (i.length)
|
|
3522
3533
|
throw new e("invalid signature: left bytes after parsing");
|
|
3523
|
-
const { v: a, l: c } = t.decode(2, o), { v: l, l:
|
|
3524
|
-
if (
|
|
3534
|
+
const { v: a, l: c } = t.decode(2, o), { v: l, l: u } = t.decode(2, c);
|
|
3535
|
+
if (u.length)
|
|
3525
3536
|
throw new e("invalid signature: left bytes after parsing");
|
|
3526
3537
|
return { r: s.decode(a), s: s.decode(l) };
|
|
3527
3538
|
},
|
|
@@ -3546,22 +3557,22 @@ function jr(r, e = {}) {
|
|
|
3546
3557
|
if (c && (!t.is0(o.a) || typeof c.beta != "bigint" || !Array.isArray(c.basises)))
|
|
3547
3558
|
throw new Error('invalid endo: expected "beta": bigint and "basises": array');
|
|
3548
3559
|
const l = As(t, n);
|
|
3549
|
-
function
|
|
3560
|
+
function u() {
|
|
3550
3561
|
if (!t.isOdd)
|
|
3551
3562
|
throw new Error("compression is not supported: Field does not have .isOdd()");
|
|
3552
3563
|
}
|
|
3553
|
-
function h(A, f,
|
|
3564
|
+
function h(A, f, x) {
|
|
3554
3565
|
const { x: b, y: E } = f.toAffine(), M = t.toBytes(b);
|
|
3555
|
-
if (qe(
|
|
3556
|
-
|
|
3566
|
+
if (qe(x, "isCompressed"), x) {
|
|
3567
|
+
u();
|
|
3557
3568
|
const O = !t.isOdd(E);
|
|
3558
3569
|
return ve(Is(O), M);
|
|
3559
3570
|
} else
|
|
3560
3571
|
return ve(Uint8Array.of(4), M, t.toBytes(E));
|
|
3561
3572
|
}
|
|
3562
|
-
function
|
|
3573
|
+
function g(A) {
|
|
3563
3574
|
z(A, void 0, "Point");
|
|
3564
|
-
const { publicKey: f, publicKeyUncompressed:
|
|
3575
|
+
const { publicKey: f, publicKeyUncompressed: x } = l, b = A.length, E = A[0], M = A.subarray(1);
|
|
3565
3576
|
if (b === f && (E === 2 || E === 3)) {
|
|
3566
3577
|
const O = t.fromBytes(M);
|
|
3567
3578
|
if (!t.isValid(O))
|
|
@@ -3574,33 +3585,33 @@ function jr(r, e = {}) {
|
|
|
3574
3585
|
const K = J instanceof Error ? ": " + J.message : "";
|
|
3575
3586
|
throw new Error("bad point: is not on curve, sqrt error" + K);
|
|
3576
3587
|
}
|
|
3577
|
-
|
|
3588
|
+
u();
|
|
3578
3589
|
const B = t.isOdd(T);
|
|
3579
3590
|
return (E & 1) === 1 !== B && (T = t.neg(T)), { x: O, y: T };
|
|
3580
|
-
} else if (b ===
|
|
3591
|
+
} else if (b === x && E === 4) {
|
|
3581
3592
|
const O = t.BYTES, $ = t.fromBytes(M.subarray(0, O)), T = t.fromBytes(M.subarray(O, O * 2));
|
|
3582
3593
|
if (!y($, T))
|
|
3583
3594
|
throw new Error("bad point: is not on curve");
|
|
3584
3595
|
return { x: $, y: T };
|
|
3585
3596
|
} else
|
|
3586
|
-
throw new Error(`bad point: got length ${b}, expected compressed=${f} or uncompressed=${
|
|
3597
|
+
throw new Error(`bad point: got length ${b}, expected compressed=${f} or uncompressed=${x}`);
|
|
3587
3598
|
}
|
|
3588
|
-
const
|
|
3599
|
+
const _ = e.toBytes || h, w = e.fromBytes || g;
|
|
3589
3600
|
function v(A) {
|
|
3590
|
-
const f = t.sqr(A),
|
|
3591
|
-
return t.add(t.add(
|
|
3601
|
+
const f = t.sqr(A), x = t.mul(f, A);
|
|
3602
|
+
return t.add(t.add(x, t.mul(A, o.a)), o.b);
|
|
3592
3603
|
}
|
|
3593
3604
|
function y(A, f) {
|
|
3594
|
-
const
|
|
3595
|
-
return t.eql(
|
|
3605
|
+
const x = t.sqr(f), b = v(A);
|
|
3606
|
+
return t.eql(x, b);
|
|
3596
3607
|
}
|
|
3597
3608
|
if (!y(o.Gx, o.Gy))
|
|
3598
3609
|
throw new Error("bad curve params: generator point");
|
|
3599
3610
|
const S = t.mul(t.pow(o.a, He), zr), C = t.mul(t.sqr(o.b), BigInt(27));
|
|
3600
3611
|
if (t.is0(t.add(S, C)))
|
|
3601
3612
|
throw new Error("bad curve params: a or b");
|
|
3602
|
-
function U(A, f,
|
|
3603
|
-
if (!t.isValid(f) ||
|
|
3613
|
+
function U(A, f, x = !1) {
|
|
3614
|
+
if (!t.isValid(f) || x && t.is0(f))
|
|
3604
3615
|
throw new Error(`bad point coordinate ${A}`);
|
|
3605
3616
|
return f;
|
|
3606
3617
|
}
|
|
@@ -3614,12 +3625,12 @@ function jr(r, e = {}) {
|
|
|
3614
3625
|
return Kr(A, c.basises, n.ORDER);
|
|
3615
3626
|
}
|
|
3616
3627
|
const W = Mt((A, f) => {
|
|
3617
|
-
const { X:
|
|
3628
|
+
const { X: x, Y: b, Z: E } = A;
|
|
3618
3629
|
if (t.eql(E, t.ONE))
|
|
3619
|
-
return { x
|
|
3630
|
+
return { x, y: b };
|
|
3620
3631
|
const M = A.is0();
|
|
3621
3632
|
f == null && (f = M ? t.ONE : t.inv(E));
|
|
3622
|
-
const O = t.mul(
|
|
3633
|
+
const O = t.mul(x, f), $ = t.mul(b, f), T = t.mul(E, f);
|
|
3623
3634
|
if (M)
|
|
3624
3635
|
return { x: t.ZERO, y: t.ZERO };
|
|
3625
3636
|
if (!t.eql(T, t.ONE))
|
|
@@ -3631,41 +3642,41 @@ function jr(r, e = {}) {
|
|
|
3631
3642
|
return;
|
|
3632
3643
|
throw new Error("bad point: ZERO");
|
|
3633
3644
|
}
|
|
3634
|
-
const { x: f, y:
|
|
3635
|
-
if (!t.isValid(f) || !t.isValid(
|
|
3645
|
+
const { x: f, y: x } = A.toAffine();
|
|
3646
|
+
if (!t.isValid(f) || !t.isValid(x))
|
|
3636
3647
|
throw new Error("bad point: x or y not field elements");
|
|
3637
|
-
if (!y(f,
|
|
3648
|
+
if (!y(f, x))
|
|
3638
3649
|
throw new Error("bad point: equation left != right");
|
|
3639
3650
|
if (!A.isTorsionFree())
|
|
3640
3651
|
throw new Error("bad point: not in prime-order subgroup");
|
|
3641
3652
|
return !0;
|
|
3642
3653
|
});
|
|
3643
|
-
function k(A, f,
|
|
3644
|
-
return
|
|
3654
|
+
function k(A, f, x, b, E) {
|
|
3655
|
+
return x = new D(t.mul(x.X, A), x.Y, x.Z), f = Ke(b, f), x = Ke(E, x), f.add(x);
|
|
3645
3656
|
}
|
|
3646
3657
|
const R = class R {
|
|
3647
3658
|
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
3648
|
-
constructor(f,
|
|
3659
|
+
constructor(f, x, b) {
|
|
3649
3660
|
I(this, "X");
|
|
3650
3661
|
I(this, "Y");
|
|
3651
3662
|
I(this, "Z");
|
|
3652
|
-
this.X = U("x", f), this.Y = U("y",
|
|
3663
|
+
this.X = U("x", f), this.Y = U("y", x, !0), this.Z = U("z", b), Object.freeze(this);
|
|
3653
3664
|
}
|
|
3654
3665
|
static CURVE() {
|
|
3655
3666
|
return o;
|
|
3656
3667
|
}
|
|
3657
3668
|
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
3658
3669
|
static fromAffine(f) {
|
|
3659
|
-
const { x
|
|
3660
|
-
if (!f || !t.isValid(
|
|
3670
|
+
const { x, y: b } = f || {};
|
|
3671
|
+
if (!f || !t.isValid(x) || !t.isValid(b))
|
|
3661
3672
|
throw new Error("invalid affine point");
|
|
3662
3673
|
if (f instanceof R)
|
|
3663
3674
|
throw new Error("projective point not allowed");
|
|
3664
|
-
return t.is0(
|
|
3675
|
+
return t.is0(x) && t.is0(b) ? R.ZERO : new R(x, b, t.ONE);
|
|
3665
3676
|
}
|
|
3666
3677
|
static fromBytes(f) {
|
|
3667
|
-
const
|
|
3668
|
-
return
|
|
3678
|
+
const x = R.fromAffine(w(z(f, void 0, "point")));
|
|
3679
|
+
return x.assertValidity(), x;
|
|
3669
3680
|
}
|
|
3670
3681
|
static fromHex(f) {
|
|
3671
3682
|
return R.fromBytes(We(f));
|
|
@@ -3682,8 +3693,8 @@ function jr(r, e = {}) {
|
|
|
3682
3693
|
* @param isLazy true will defer table computation until the first multiplication
|
|
3683
3694
|
* @returns
|
|
3684
3695
|
*/
|
|
3685
|
-
precompute(f = 8,
|
|
3686
|
-
return L.createCache(this, f),
|
|
3696
|
+
precompute(f = 8, x = !0) {
|
|
3697
|
+
return L.createCache(this, f), x || this.multiply(He), this;
|
|
3687
3698
|
}
|
|
3688
3699
|
// TODO: return `this`
|
|
3689
3700
|
/** A point on curve is valid if it conforms to equation. */
|
|
@@ -3699,7 +3710,7 @@ function jr(r, e = {}) {
|
|
|
3699
3710
|
/** Compare one point to another. */
|
|
3700
3711
|
equals(f) {
|
|
3701
3712
|
N(f);
|
|
3702
|
-
const { X:
|
|
3713
|
+
const { X: x, Y: b, Z: E } = this, { X: M, Y: O, Z: $ } = f, T = t.eql(t.mul(x, $), t.mul(M, E)), B = t.eql(t.mul(b, $), t.mul(O, E));
|
|
3703
3714
|
return T && B;
|
|
3704
3715
|
}
|
|
3705
3716
|
/** Flips point to one corresponding to (x, -y) in Affine coordinates. */
|
|
@@ -3711,7 +3722,7 @@ function jr(r, e = {}) {
|
|
|
3711
3722
|
// https://eprint.iacr.org/2015/1060, algorithm 3
|
|
3712
3723
|
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
|
|
3713
3724
|
double() {
|
|
3714
|
-
const { a: f, b:
|
|
3725
|
+
const { a: f, b: x } = o, b = t.mul(x, He), { X: E, Y: M, Z: O } = this;
|
|
3715
3726
|
let $ = t.ZERO, T = t.ZERO, B = t.ZERO, G = t.mul(E, E), J = t.mul(M, M), K = t.mul(O, O), F = t.mul(E, M);
|
|
3716
3727
|
return F = t.add(F, F), B = t.mul(E, O), B = t.add(B, B), $ = t.mul(f, B), T = t.mul(b, K), T = t.add($, T), $ = t.sub(J, T), T = t.add(J, T), T = t.mul($, T), $ = t.mul(F, $), B = t.mul(b, B), K = t.mul(f, K), F = t.sub(G, K), F = t.mul(f, F), F = t.add(F, B), B = t.add(G, G), G = t.add(B, G), G = t.add(G, K), G = t.mul(G, F), T = t.add(T, G), K = t.mul(M, O), K = t.add(K, K), G = t.mul(K, F), $ = t.sub($, G), B = t.mul(K, J), B = t.add(B, B), B = t.add(B, B), new R($, T, B);
|
|
3717
3728
|
}
|
|
@@ -3721,11 +3732,11 @@ function jr(r, e = {}) {
|
|
|
3721
3732
|
// Cost: 12M + 0S + 3*a + 3*b3 + 23add.
|
|
3722
3733
|
add(f) {
|
|
3723
3734
|
N(f);
|
|
3724
|
-
const { X:
|
|
3735
|
+
const { X: x, Y: b, Z: E } = this, { X: M, Y: O, Z: $ } = f;
|
|
3725
3736
|
let T = t.ZERO, B = t.ZERO, G = t.ZERO;
|
|
3726
3737
|
const J = o.a, K = t.mul(o.b, He);
|
|
3727
|
-
let F = t.mul(
|
|
3728
|
-
oe = t.mul(oe, j), j = t.add(F, X), oe = t.sub(oe, j), j = t.add(
|
|
3738
|
+
let F = t.mul(x, M), X = t.mul(b, O), Z = t.mul(E, $), oe = t.add(x, b), j = t.add(M, O);
|
|
3739
|
+
oe = t.mul(oe, j), j = t.add(F, X), oe = t.sub(oe, j), j = t.add(x, E);
|
|
3729
3740
|
let Q = t.add(M, $);
|
|
3730
3741
|
return j = t.mul(j, Q), Q = t.add(F, Z), j = t.sub(j, Q), Q = t.add(b, E), T = t.add(O, $), Q = t.mul(Q, T), T = t.add(X, Z), Q = t.sub(Q, T), G = t.mul(J, j), T = t.mul(K, Z), G = t.add(T, G), T = t.sub(X, G), G = t.add(X, G), B = t.mul(T, G), X = t.add(F, F), X = t.add(X, F), Z = t.mul(J, Z), j = t.mul(K, j), X = t.add(X, Z), Z = t.sub(F, Z), Z = t.mul(J, Z), j = t.add(j, Z), F = t.mul(X, j), B = t.add(B, F), F = t.mul(Q, j), T = t.mul(oe, T), T = t.sub(T, F), F = t.mul(oe, X), G = t.mul(Q, G), G = t.add(G, F), new R(T, B, G);
|
|
3731
3742
|
}
|
|
@@ -3745,14 +3756,14 @@ function jr(r, e = {}) {
|
|
|
3745
3756
|
* @returns New point
|
|
3746
3757
|
*/
|
|
3747
3758
|
multiply(f) {
|
|
3748
|
-
const { endo:
|
|
3759
|
+
const { endo: x } = e;
|
|
3749
3760
|
if (!n.isValidNot0(f))
|
|
3750
3761
|
throw new Error("invalid scalar: out of range");
|
|
3751
3762
|
let b, E;
|
|
3752
3763
|
const M = (O) => L.cached(this, O, ($) => Ut(R, $));
|
|
3753
|
-
if (
|
|
3764
|
+
if (x) {
|
|
3754
3765
|
const { k1neg: O, k1: $, k2neg: T, k2: B } = V(f), { p: G, f: J } = M($), { p: K, f: F } = M(B);
|
|
3755
|
-
E = J.add(F), b = k(
|
|
3766
|
+
E = J.add(F), b = k(x.beta, G, K, O, T);
|
|
3756
3767
|
} else {
|
|
3757
3768
|
const { p: O, f: $ } = M(f);
|
|
3758
3769
|
b = O, E = $;
|
|
@@ -3765,7 +3776,7 @@ function jr(r, e = {}) {
|
|
|
3765
3776
|
* an exposed secret key e.g. sig verification, which works over *public* keys.
|
|
3766
3777
|
*/
|
|
3767
3778
|
multiplyUnsafe(f) {
|
|
3768
|
-
const { endo:
|
|
3779
|
+
const { endo: x } = e, b = this;
|
|
3769
3780
|
if (!n.isValid(f))
|
|
3770
3781
|
throw new Error("invalid scalar: out of range");
|
|
3771
3782
|
if (f === _e || b.is0())
|
|
@@ -3774,9 +3785,9 @@ function jr(r, e = {}) {
|
|
|
3774
3785
|
return b;
|
|
3775
3786
|
if (L.hasCache(this))
|
|
3776
3787
|
return this.multiply(f);
|
|
3777
|
-
if (
|
|
3788
|
+
if (x) {
|
|
3778
3789
|
const { k1neg: E, k1: M, k2neg: O, k2: $ } = V(f), { p1: T, p2: B } = Gr(R, b, M, $);
|
|
3779
|
-
return k(
|
|
3790
|
+
return k(x.beta, T, B, E, O);
|
|
3780
3791
|
} else
|
|
3781
3792
|
return L.unsafe(b, f);
|
|
3782
3793
|
}
|
|
@@ -3803,7 +3814,7 @@ function jr(r, e = {}) {
|
|
|
3803
3814
|
return this.multiplyUnsafe(i).is0();
|
|
3804
3815
|
}
|
|
3805
3816
|
toBytes(f = !0) {
|
|
3806
|
-
return qe(f, "isCompressed"), this.assertValidity(),
|
|
3817
|
+
return qe(f, "isCompressed"), this.assertValidity(), _(R, this, f);
|
|
3807
3818
|
}
|
|
3808
3819
|
toHex(f = !0) {
|
|
3809
3820
|
return Me(this.toBytes(f));
|
|
@@ -3836,50 +3847,50 @@ function As(r, e) {
|
|
|
3836
3847
|
}
|
|
3837
3848
|
function Yr(r, e = {}) {
|
|
3838
3849
|
const { Fn: s } = r, t = e.randomBytes || os, n = Object.assign(As(r.Fp, s), { seed: ws(s.ORDER) });
|
|
3839
|
-
function o(
|
|
3850
|
+
function o(_) {
|
|
3840
3851
|
try {
|
|
3841
|
-
const w = s.fromBytes(
|
|
3852
|
+
const w = s.fromBytes(_);
|
|
3842
3853
|
return s.isValidNot0(w);
|
|
3843
3854
|
} catch {
|
|
3844
3855
|
return !1;
|
|
3845
3856
|
}
|
|
3846
3857
|
}
|
|
3847
|
-
function i(
|
|
3858
|
+
function i(_, w) {
|
|
3848
3859
|
const { publicKey: v, publicKeyUncompressed: y } = n;
|
|
3849
3860
|
try {
|
|
3850
|
-
const S =
|
|
3851
|
-
return w === !0 && S !== v || w === !1 && S !== y ? !1 : !!r.fromBytes(
|
|
3861
|
+
const S = _.length;
|
|
3862
|
+
return w === !0 && S !== v || w === !1 && S !== y ? !1 : !!r.fromBytes(_);
|
|
3852
3863
|
} catch {
|
|
3853
3864
|
return !1;
|
|
3854
3865
|
}
|
|
3855
3866
|
}
|
|
3856
|
-
function a(
|
|
3857
|
-
return Hr(z(
|
|
3867
|
+
function a(_ = t(n.seed)) {
|
|
3868
|
+
return Hr(z(_, n.seed, "seed"), s.ORDER);
|
|
3858
3869
|
}
|
|
3859
|
-
function c(
|
|
3860
|
-
return r.BASE.multiply(s.fromBytes(
|
|
3870
|
+
function c(_, w = !0) {
|
|
3871
|
+
return r.BASE.multiply(s.fromBytes(_)).toBytes(w);
|
|
3861
3872
|
}
|
|
3862
|
-
function l(
|
|
3873
|
+
function l(_) {
|
|
3863
3874
|
const { secretKey: w, publicKey: v, publicKeyUncompressed: y } = n;
|
|
3864
|
-
if (!ut(
|
|
3875
|
+
if (!ut(_) || "_lengths" in s && s._lengths || w === v)
|
|
3865
3876
|
return;
|
|
3866
|
-
const S = z(
|
|
3877
|
+
const S = z(_, void 0, "key").length;
|
|
3867
3878
|
return S === v || S === y;
|
|
3868
3879
|
}
|
|
3869
|
-
function
|
|
3870
|
-
if (l(
|
|
3880
|
+
function u(_, w, v = !0) {
|
|
3881
|
+
if (l(_) === !0)
|
|
3871
3882
|
throw new Error("first arg must be private key");
|
|
3872
3883
|
if (l(w) === !1)
|
|
3873
3884
|
throw new Error("second arg must be public key");
|
|
3874
|
-
const y = s.fromBytes(
|
|
3885
|
+
const y = s.fromBytes(_);
|
|
3875
3886
|
return r.fromBytes(w).multiply(y).toBytes(v);
|
|
3876
3887
|
}
|
|
3877
3888
|
const h = {
|
|
3878
3889
|
isValidSecretKey: o,
|
|
3879
3890
|
isValidPublicKey: i,
|
|
3880
3891
|
randomSecretKey: a
|
|
3881
|
-
},
|
|
3882
|
-
return Object.freeze({ getPublicKey: c, getSharedSecret:
|
|
3892
|
+
}, g = qr(a, c);
|
|
3893
|
+
return Object.freeze({ getPublicKey: c, getSharedSecret: u, keygen: g, Point: r, utils: h, lengths: n });
|
|
3883
3894
|
}
|
|
3884
3895
|
function Jr(r, e, s = {}) {
|
|
3885
3896
|
ts(e), _t(s, {}, {
|
|
@@ -3889,70 +3900,70 @@ function Jr(r, e, s = {}) {
|
|
|
3889
3900
|
bits2int: "function",
|
|
3890
3901
|
bits2int_modN: "function"
|
|
3891
3902
|
}), s = Object.assign({}, s);
|
|
3892
|
-
const t = s.randomBytes || os, n = s.hmac || ((f,
|
|
3903
|
+
const t = s.randomBytes || os, n = s.hmac || ((f, x) => Ss(e, f, x)), { Fp: o, Fn: i } = r, { ORDER: a, BITS: c } = i, { keygen: l, getPublicKey: u, getSharedSecret: h, utils: g, lengths: _ } = Yr(r, s), w = {
|
|
3893
3904
|
prehash: !0,
|
|
3894
3905
|
lowS: typeof s.lowS == "boolean" ? s.lowS : !0,
|
|
3895
3906
|
format: "compact",
|
|
3896
3907
|
extraEntropy: !1
|
|
3897
3908
|
}, v = a * Es < o.ORDER;
|
|
3898
3909
|
function y(f) {
|
|
3899
|
-
const
|
|
3900
|
-
return f >
|
|
3910
|
+
const x = a >> Re;
|
|
3911
|
+
return f > x;
|
|
3901
3912
|
}
|
|
3902
|
-
function S(f,
|
|
3903
|
-
if (!i.isValidNot0(
|
|
3913
|
+
function S(f, x) {
|
|
3914
|
+
if (!i.isValidNot0(x))
|
|
3904
3915
|
throw new Error(`invalid signature ${f}: out of range 1..Point.Fn.ORDER`);
|
|
3905
|
-
return
|
|
3916
|
+
return x;
|
|
3906
3917
|
}
|
|
3907
3918
|
function C() {
|
|
3908
3919
|
if (v)
|
|
3909
3920
|
throw new Error('"recovered" sig type is not supported for cofactor >2 curves');
|
|
3910
3921
|
}
|
|
3911
|
-
function U(f,
|
|
3912
|
-
ct(
|
|
3913
|
-
const b =
|
|
3922
|
+
function U(f, x) {
|
|
3923
|
+
ct(x);
|
|
3924
|
+
const b = _.signature, E = x === "compact" ? b : x === "recovered" ? b + 1 : void 0;
|
|
3914
3925
|
return z(f, E);
|
|
3915
3926
|
}
|
|
3916
3927
|
class N {
|
|
3917
|
-
constructor(
|
|
3928
|
+
constructor(x, b, E) {
|
|
3918
3929
|
I(this, "r");
|
|
3919
3930
|
I(this, "s");
|
|
3920
3931
|
I(this, "recovery");
|
|
3921
|
-
if (this.r = S("r",
|
|
3932
|
+
if (this.r = S("r", x), this.s = S("s", b), E != null) {
|
|
3922
3933
|
if (C(), ![0, 1, 2, 3].includes(E))
|
|
3923
3934
|
throw new Error("invalid recovery id");
|
|
3924
3935
|
this.recovery = E;
|
|
3925
3936
|
}
|
|
3926
3937
|
Object.freeze(this);
|
|
3927
3938
|
}
|
|
3928
|
-
static fromBytes(
|
|
3929
|
-
U(
|
|
3939
|
+
static fromBytes(x, b = w.format) {
|
|
3940
|
+
U(x, b);
|
|
3930
3941
|
let E;
|
|
3931
3942
|
if (b === "der") {
|
|
3932
|
-
const { r: T, s: B } = ye.toSig(z(
|
|
3943
|
+
const { r: T, s: B } = ye.toSig(z(x));
|
|
3933
3944
|
return new N(T, B);
|
|
3934
3945
|
}
|
|
3935
|
-
b === "recovered" && (E =
|
|
3936
|
-
const M =
|
|
3946
|
+
b === "recovered" && (E = x[0], b = "compact", x = x.subarray(1));
|
|
3947
|
+
const M = _.signature / 2, O = x.subarray(0, M), $ = x.subarray(M, M * 2);
|
|
3937
3948
|
return new N(i.fromBytes(O), i.fromBytes($), E);
|
|
3938
3949
|
}
|
|
3939
|
-
static fromHex(
|
|
3940
|
-
return this.fromBytes(We(
|
|
3950
|
+
static fromHex(x, b) {
|
|
3951
|
+
return this.fromBytes(We(x), b);
|
|
3941
3952
|
}
|
|
3942
3953
|
assertRecovery() {
|
|
3943
|
-
const { recovery:
|
|
3944
|
-
if (
|
|
3954
|
+
const { recovery: x } = this;
|
|
3955
|
+
if (x == null)
|
|
3945
3956
|
throw new Error("invalid recovery id: must be present");
|
|
3946
|
-
return
|
|
3957
|
+
return x;
|
|
3947
3958
|
}
|
|
3948
|
-
addRecoveryBit(
|
|
3949
|
-
return new N(this.r, this.s,
|
|
3959
|
+
addRecoveryBit(x) {
|
|
3960
|
+
return new N(this.r, this.s, x);
|
|
3950
3961
|
}
|
|
3951
|
-
recoverPublicKey(
|
|
3962
|
+
recoverPublicKey(x) {
|
|
3952
3963
|
const { r: b, s: E } = this, M = this.assertRecovery(), O = M === 2 || M === 3 ? b + a : b;
|
|
3953
3964
|
if (!o.isValid(O))
|
|
3954
3965
|
throw new Error("invalid recovery id: sig.r+curve.n != R.x");
|
|
3955
|
-
const $ = o.toBytes(O), T = r.fromBytes(ve(Is((M & 1) === 0), $)), B = i.inv(O), G = W(z(
|
|
3966
|
+
const $ = o.toBytes(O), T = r.fromBytes(ve(Is((M & 1) === 0), $)), B = i.inv(O), G = W(z(x, void 0, "msgHash")), J = i.create(-G * B), K = i.create(E * B), F = r.BASE.multiplyUnsafe(J).add(T.multiplyUnsafe(K));
|
|
3956
3967
|
if (F.is0())
|
|
3957
3968
|
throw new Error("invalid recovery: point at infinify");
|
|
3958
3969
|
return F.assertValidity(), F;
|
|
@@ -3961,39 +3972,39 @@ function Jr(r, e, s = {}) {
|
|
|
3961
3972
|
hasHighS() {
|
|
3962
3973
|
return y(this.s);
|
|
3963
3974
|
}
|
|
3964
|
-
toBytes(
|
|
3965
|
-
if (ct(
|
|
3975
|
+
toBytes(x = w.format) {
|
|
3976
|
+
if (ct(x), x === "der")
|
|
3966
3977
|
return We(ye.hexFromSig(this));
|
|
3967
3978
|
const { r: b, s: E } = this, M = i.toBytes(b), O = i.toBytes(E);
|
|
3968
|
-
return
|
|
3979
|
+
return x === "recovered" ? (C(), ve(Uint8Array.of(this.assertRecovery()), M, O)) : ve(M, O);
|
|
3969
3980
|
}
|
|
3970
|
-
toHex(
|
|
3971
|
-
return Me(this.toBytes(
|
|
3981
|
+
toHex(x) {
|
|
3982
|
+
return Me(this.toBytes(x));
|
|
3972
3983
|
}
|
|
3973
3984
|
}
|
|
3974
|
-
const V = s.bits2int || function(
|
|
3975
|
-
if (
|
|
3985
|
+
const V = s.bits2int || function(x) {
|
|
3986
|
+
if (x.length > 8192)
|
|
3976
3987
|
throw new Error("input is too large");
|
|
3977
|
-
const b = ze(
|
|
3988
|
+
const b = ze(x), E = x.length * 8 - c;
|
|
3978
3989
|
return E > 0 ? b >> BigInt(E) : b;
|
|
3979
|
-
}, W = s.bits2int_modN || function(
|
|
3980
|
-
return i.create(V(
|
|
3990
|
+
}, W = s.bits2int_modN || function(x) {
|
|
3991
|
+
return i.create(V(x));
|
|
3981
3992
|
}, P = ft(c);
|
|
3982
3993
|
function k(f) {
|
|
3983
3994
|
return Tr("num < 2^" + c, f, _e, P), i.toBytes(f);
|
|
3984
3995
|
}
|
|
3985
|
-
function D(f,
|
|
3986
|
-
return z(f, void 0, "message"),
|
|
3996
|
+
function D(f, x) {
|
|
3997
|
+
return z(f, void 0, "message"), x ? z(e(f), void 0, "prehashed message") : f;
|
|
3987
3998
|
}
|
|
3988
|
-
function q(f,
|
|
3999
|
+
function q(f, x, b) {
|
|
3989
4000
|
const { lowS: E, prehash: M, extraEntropy: O } = st(b, w);
|
|
3990
4001
|
f = D(f, M);
|
|
3991
|
-
const $ = W(f), T = i.fromBytes(
|
|
4002
|
+
const $ = W(f), T = i.fromBytes(x);
|
|
3992
4003
|
if (!i.isValidNot0(T))
|
|
3993
4004
|
throw new Error("invalid private key");
|
|
3994
4005
|
const B = [k(T), k($)];
|
|
3995
4006
|
if (O != null && O !== !1) {
|
|
3996
|
-
const F = O === !0 ? t(
|
|
4007
|
+
const F = O === !0 ? t(_.secretKey) : O;
|
|
3997
4008
|
B.push(z(F, void 0, "extraEntropy"));
|
|
3998
4009
|
}
|
|
3999
4010
|
const G = ve(...B), J = $;
|
|
@@ -4012,13 +4023,13 @@ function Jr(r, e, s = {}) {
|
|
|
4012
4023
|
}
|
|
4013
4024
|
return { seed: G, k2sig: K };
|
|
4014
4025
|
}
|
|
4015
|
-
function L(f,
|
|
4016
|
-
const { seed: E, k2sig: M } = q(f,
|
|
4026
|
+
function L(f, x, b = {}) {
|
|
4027
|
+
const { seed: E, k2sig: M } = q(f, x, b);
|
|
4017
4028
|
return kr(e.outputLen, i.BYTES, n)(E, M).toBytes(b.format);
|
|
4018
4029
|
}
|
|
4019
|
-
function R(f,
|
|
4030
|
+
function R(f, x, b, E = {}) {
|
|
4020
4031
|
const { lowS: M, prehash: O, format: $ } = st(E, w);
|
|
4021
|
-
if (b = z(b, void 0, "publicKey"),
|
|
4032
|
+
if (b = z(b, void 0, "publicKey"), x = D(x, O), !ut(f)) {
|
|
4022
4033
|
const T = f instanceof N ? ", use sig.toBytes()" : "";
|
|
4023
4034
|
throw new Error("verify expects Uint8Array signature" + T);
|
|
4024
4035
|
}
|
|
@@ -4027,22 +4038,22 @@ function Jr(r, e, s = {}) {
|
|
|
4027
4038
|
const T = N.fromBytes(f, $), B = r.fromBytes(b);
|
|
4028
4039
|
if (M && T.hasHighS())
|
|
4029
4040
|
return !1;
|
|
4030
|
-
const { r: G, s: J } = T, K = W(
|
|
4041
|
+
const { r: G, s: J } = T, K = W(x), F = i.inv(J), X = i.create(K * F), Z = i.create(G * F), oe = r.BASE.multiplyUnsafe(X).add(B.multiplyUnsafe(Z));
|
|
4031
4042
|
return oe.is0() ? !1 : i.create(oe.x) === G;
|
|
4032
4043
|
} catch {
|
|
4033
4044
|
return !1;
|
|
4034
4045
|
}
|
|
4035
4046
|
}
|
|
4036
|
-
function A(f,
|
|
4047
|
+
function A(f, x, b = {}) {
|
|
4037
4048
|
const { prehash: E } = st(b, w);
|
|
4038
|
-
return
|
|
4049
|
+
return x = D(x, E), N.fromBytes(f, "recovered").recoverPublicKey(x).toBytes();
|
|
4039
4050
|
}
|
|
4040
4051
|
return Object.freeze({
|
|
4041
4052
|
keygen: l,
|
|
4042
|
-
getPublicKey:
|
|
4053
|
+
getPublicKey: u,
|
|
4043
4054
|
getSharedSecret: h,
|
|
4044
|
-
utils:
|
|
4045
|
-
lengths:
|
|
4055
|
+
utils: g,
|
|
4056
|
+
lengths: _,
|
|
4046
4057
|
Point: r,
|
|
4047
4058
|
sign: L,
|
|
4048
4059
|
verify: R,
|
|
@@ -4068,7 +4079,7 @@ const gt = {
|
|
|
4068
4079
|
]
|
|
4069
4080
|
}, qt = /* @__PURE__ */ BigInt(2);
|
|
4070
4081
|
function Zr(r) {
|
|
4071
|
-
const e = gt.p, s = BigInt(3), t = BigInt(6), n = BigInt(11), o = BigInt(22), i = BigInt(23), a = BigInt(44), c = BigInt(88), l = r * r * r % e,
|
|
4082
|
+
const e = gt.p, s = BigInt(3), t = BigInt(6), n = BigInt(11), o = BigInt(22), i = BigInt(23), a = BigInt(44), c = BigInt(88), l = r * r * r % e, u = l * l * r % e, h = ae(u, s, e) * u % e, g = ae(h, s, e) * u % e, _ = ae(g, qt, e) * l % e, w = ae(_, n, e) * _ % e, v = ae(w, o, e) * w % e, y = ae(v, a, e) * v % e, S = ae(y, c, e) * y % e, C = ae(S, a, e) * v % e, U = ae(C, s, e) * u % e, N = ae(U, i, e) * w % e, V = ae(N, t, e) * l % e, W = ae(V, qt, e);
|
|
4072
4083
|
if (!lt.eql(lt.sqr(W), r))
|
|
4073
4084
|
throw new Error("Cannot find square root");
|
|
4074
4085
|
return W;
|
|
@@ -4091,14 +4102,14 @@ function ln(r, e = 24) {
|
|
|
4091
4102
|
for (let i = 0; i < 10; i++)
|
|
4092
4103
|
s[i] = r[i] ^ r[i + 10] ^ r[i + 20] ^ r[i + 30] ^ r[i + 40];
|
|
4093
4104
|
for (let i = 0; i < 10; i += 2) {
|
|
4094
|
-
const a = (i + 8) % 10, c = (i + 2) % 10, l = s[c],
|
|
4095
|
-
for (let
|
|
4096
|
-
r[i +
|
|
4105
|
+
const a = (i + 8) % 10, c = (i + 2) % 10, l = s[c], u = s[c + 1], h = Kt(l, u, 1) ^ s[a], g = Vt(l, u, 1) ^ s[a + 1];
|
|
4106
|
+
for (let _ = 0; _ < 50; _ += 10)
|
|
4107
|
+
r[i + _] ^= h, r[i + _ + 1] ^= g;
|
|
4097
4108
|
}
|
|
4098
4109
|
let n = r[2], o = r[3];
|
|
4099
4110
|
for (let i = 0; i < 24; i++) {
|
|
4100
|
-
const a = Rs[i], c = Kt(n, o, a), l = Vt(n, o, a),
|
|
4101
|
-
n = r[
|
|
4111
|
+
const a = Rs[i], c = Kt(n, o, a), l = Vt(n, o, a), u = Ts[i];
|
|
4112
|
+
n = r[u], o = r[u + 1], r[u] = c, r[u + 1] = l;
|
|
4102
4113
|
}
|
|
4103
4114
|
for (let i = 0; i < 50; i += 10) {
|
|
4104
4115
|
for (let a = 0; a < 10; a++)
|
|
@@ -4193,46 +4204,46 @@ class hn {
|
|
|
4193
4204
|
}
|
|
4194
4205
|
setJWKSEndpoint(e) {
|
|
4195
4206
|
try {
|
|
4196
|
-
this.jwks = Ms(new URL(e)),
|
|
4207
|
+
this.jwks = Ms(new URL(e)), d.log("[CROSSx] JWKS 엔드포인트 설정:", e);
|
|
4197
4208
|
} catch (s) {
|
|
4198
|
-
|
|
4209
|
+
d.warn("[CROSSx] JWKS 엔드포인트 URL 파싱 실패:", s);
|
|
4199
4210
|
}
|
|
4200
4211
|
}
|
|
4201
4212
|
async verifyJWT(e, s) {
|
|
4202
4213
|
try {
|
|
4203
4214
|
const t = this.decodeJWT(e);
|
|
4204
|
-
|
|
4215
|
+
d.log("[CROSSx] JWT 디코딩 성공:", {
|
|
4205
4216
|
sub: t.sub,
|
|
4206
4217
|
exp: t.exp,
|
|
4207
4218
|
iat: t.iat
|
|
4208
4219
|
});
|
|
4209
4220
|
const n = Math.floor(Date.now() / 1e3);
|
|
4210
4221
|
if (t.exp && t.exp + un < n)
|
|
4211
|
-
return
|
|
4222
|
+
return d.warn("[CROSSx] 토큰 만료:", {
|
|
4212
4223
|
exp: t.exp,
|
|
4213
4224
|
now: n,
|
|
4214
4225
|
만료시간: new Date(t.exp * 1e3).toISOString()
|
|
4215
4226
|
}), { payload: t, valid: !1, signatureVerified: !1 };
|
|
4216
4227
|
if (!t.sub)
|
|
4217
|
-
return
|
|
4228
|
+
return d.warn("[CROSSx] JWT에 sub(사용자ID) 없음"), { payload: t, valid: !1, signatureVerified: !1 };
|
|
4218
4229
|
if (this.jwks)
|
|
4219
4230
|
try {
|
|
4220
4231
|
const { payload: o } = await $s(e, this.jwks, {
|
|
4221
4232
|
algorithms: ["RS256", "ES256"]
|
|
4222
4233
|
});
|
|
4223
|
-
return
|
|
4234
|
+
return d.log("[CROSSx] JWT 서명 검증 성공"), {
|
|
4224
4235
|
payload: o,
|
|
4225
4236
|
valid: !0,
|
|
4226
4237
|
signatureVerified: !0
|
|
4227
4238
|
};
|
|
4228
4239
|
} catch (o) {
|
|
4229
4240
|
if (o instanceof Error && (o.name === "JWSSignatureVerificationFailed" || o.name === "JWTClaimValidationFailed"))
|
|
4230
|
-
return
|
|
4231
|
-
|
|
4241
|
+
return d.error("[CROSSx] JWT 서명 검증 실패:", o), { payload: t, valid: !1, signatureVerified: !1 };
|
|
4242
|
+
d.warn("[CROSSx] JWKS 엔드포인트 접근 불가 — 서명 미검증 모드로 전환");
|
|
4232
4243
|
}
|
|
4233
|
-
return
|
|
4244
|
+
return d.log("[CROSSx] JWT 검증 성공 (서명 미검증 — JWKS 미설정 또는 접근 불가)"), { payload: t, valid: !0, signatureVerified: !1 };
|
|
4234
4245
|
} catch (t) {
|
|
4235
|
-
throw
|
|
4246
|
+
throw d.error("[CROSSx] JWT 검증 중 에러:", t), t;
|
|
4236
4247
|
}
|
|
4237
4248
|
}
|
|
4238
4249
|
decodeJWT(e) {
|
|
@@ -4254,10 +4265,10 @@ ${t.length}`
|
|
|
4254
4265
|
const i = zt(o), a = s.startsWith("0x") ? s.slice(2) : s;
|
|
4255
4266
|
if (a.length !== 130)
|
|
4256
4267
|
throw new Error(`서명 길이가 유효하지 않습니다: 130 hex 문자 예상, 현재 ${a.length}`);
|
|
4257
|
-
const c = pn(a), l = c.slice(0, 32),
|
|
4268
|
+
const c = pn(a), l = c.slice(0, 32), u = c.slice(32, 64), h = c[64], g = h >= 27 ? h - 27 : h, v = new en.Signature(
|
|
4258
4269
|
jt(l),
|
|
4259
|
-
jt(
|
|
4260
|
-
).addRecoveryBit(
|
|
4270
|
+
jt(u)
|
|
4271
|
+
).addRecoveryBit(g).recoverPublicKey(i).toBytes(!1).slice(1), y = zt(v);
|
|
4261
4272
|
return "0x" + Me(y.slice(12));
|
|
4262
4273
|
}
|
|
4263
4274
|
}
|
|
@@ -4349,21 +4360,21 @@ class be {
|
|
|
4349
4360
|
*/
|
|
4350
4361
|
static async verifyIdTokenNonce(e, s) {
|
|
4351
4362
|
const t = be.parseJwtPayload(e), n = t.nonce, o = typeof t.iss == "string" ? t.iss : "(unknown)";
|
|
4352
|
-
if (
|
|
4363
|
+
if (d.log("[CROSSx] nonce 검증 시작 —", {
|
|
4353
4364
|
iss: o,
|
|
4354
4365
|
nonceClaimType: typeof n,
|
|
4355
4366
|
nonceClaimPresent: typeof n == "string" && n !== "",
|
|
4356
4367
|
// Apple의 nonce_supported 플래그 확인 (false면 서버가 nonce를 전달하지 않은 것)
|
|
4357
4368
|
appleNonceSupported: t.nonce_supported ?? "(field absent)"
|
|
4358
4369
|
}), o.includes("securetoken.google.com")) {
|
|
4359
|
-
|
|
4370
|
+
d.log(
|
|
4360
4371
|
"[CROSSx] Firebase ID Token 감지 — nonce 검증 skip.",
|
|
4361
4372
|
"서버 측에서 Google/Apple nonce 검증이 완료된 것으로 간주합니다."
|
|
4362
4373
|
);
|
|
4363
4374
|
return;
|
|
4364
4375
|
}
|
|
4365
4376
|
if (typeof n != "string" || n === "")
|
|
4366
|
-
throw
|
|
4377
|
+
throw d.error("[CROSSx] nonce claim 누락 — JWT payload 전체 키 목록:", Object.keys(t)), d.error(
|
|
4367
4378
|
"[CROSSx] 원인 추정: OAuth 서버가 Google/Apple 인증 요청에 nonce 파라미터를 포함하지 않았을 수 있습니다.",
|
|
4368
4379
|
"서버 로그에서 /auth/google, /auth/apple 요청 URL에 nonce 쿼리가 있는지 확인하세요."
|
|
4369
4380
|
), new Error(
|
|
@@ -4371,43 +4382,43 @@ class be {
|
|
|
4371
4382
|
);
|
|
4372
4383
|
if (o.includes("appleid.apple.com")) {
|
|
4373
4384
|
const i = await be.sha256Hex(s);
|
|
4374
|
-
if (
|
|
4385
|
+
if (d.log("[CROSSx] Apple nonce 검증 —", {
|
|
4375
4386
|
expectedHashLength: i.length,
|
|
4376
4387
|
receivedHashLength: n.length,
|
|
4377
4388
|
match: n === i
|
|
4378
4389
|
}), n !== i)
|
|
4379
4390
|
throw new Error("ID Token nonce 불일치 — replay attack 가능성이 있습니다");
|
|
4380
|
-
} else if (
|
|
4391
|
+
} else if (d.log("[CROSSx] Google nonce 검증 —", {
|
|
4381
4392
|
expectedLength: s.length,
|
|
4382
4393
|
receivedLength: n.length,
|
|
4383
4394
|
match: n === s
|
|
4384
4395
|
}), n !== s)
|
|
4385
4396
|
throw new Error("ID Token nonce 불일치 — replay attack 가능성이 있습니다");
|
|
4386
|
-
|
|
4397
|
+
d.log("[CROSSx] nonce 검증 성공 —", { iss: o });
|
|
4387
4398
|
}
|
|
4388
4399
|
openAuth(e) {
|
|
4389
4400
|
return new Promise((s, t) => {
|
|
4390
|
-
const n = Math.max(e.width ?? 500, 500), o = Math.max(e.height ?? 700, 700), i = window.screenX + (window.outerWidth - n) / 2, a = window.screenY + (window.outerHeight - o) / 2, c = be.generateRandom16Hex(), l = be.generateRandom16Hex(),
|
|
4391
|
-
|
|
4401
|
+
const n = Math.max(e.width ?? 500, 500), o = Math.max(e.height ?? 700, 700), i = window.screenX + (window.outerWidth - n) / 2, a = window.screenY + (window.outerHeight - o) / 2, c = be.generateRandom16Hex(), l = be.generateRandom16Hex(), u = e.authUrl.includes("?") ? "&" : "?", h = `${e.authUrl}${u}state=${c}&nonce=${l}`;
|
|
4402
|
+
d.log("[CROSSx] OAuth 팝업 열기 — state, nonce 생성 완료:", {
|
|
4392
4403
|
stateLength: c.length,
|
|
4393
4404
|
nonceLength: l.length,
|
|
4394
4405
|
authUrlBase: e.authUrl
|
|
4395
4406
|
});
|
|
4396
|
-
const
|
|
4407
|
+
const g = window.open(
|
|
4397
4408
|
h,
|
|
4398
4409
|
"CROSSx OAuth",
|
|
4399
4410
|
`width=${n},height=${o},left=${i},top=${a}`
|
|
4400
4411
|
);
|
|
4401
|
-
if (!
|
|
4412
|
+
if (!g) {
|
|
4402
4413
|
t(new Error("팝업 창을 열 수 없습니다. 팝업 차단을 해제해 주세요."));
|
|
4403
4414
|
return;
|
|
4404
4415
|
}
|
|
4405
|
-
const
|
|
4406
|
-
|
|
4416
|
+
const _ = setTimeout(() => {
|
|
4417
|
+
d.warn("[CROSSx] OAuth 타임아웃 (5분) — postMessage를 수신하지 못했습니다"), N(), t(new Error("Authentication timeout"));
|
|
4407
4418
|
}, 5 * 60 * 1e3), w = 10, v = 30;
|
|
4408
4419
|
let y = 0, S = null;
|
|
4409
4420
|
const C = () => {
|
|
4410
|
-
clearInterval(U),
|
|
4421
|
+
clearInterval(U), d.warn("[CROSSx] COOP 감지 — OAuth 서버 응답을 " + v + "초간 대기합니다"), S = setTimeout(() => {
|
|
4411
4422
|
N(), t(new Error(
|
|
4412
4423
|
"OAuth 서버로부터 응답을 받지 못했습니다. 브라우저 보안 정책(COOP)으로 인해 팝업 통신이 차단되었을 수 있습니다. 다시 시도해 주세요."
|
|
4413
4424
|
));
|
|
@@ -4415,44 +4426,44 @@ class be {
|
|
|
4415
4426
|
}, U = setInterval(() => {
|
|
4416
4427
|
y++;
|
|
4417
4428
|
try {
|
|
4418
|
-
|
|
4429
|
+
g.closed && (y <= w ? C() : (N(), t(new Error("로그인이 취소되었습니다"))));
|
|
4419
4430
|
} catch {
|
|
4420
4431
|
C();
|
|
4421
4432
|
}
|
|
4422
4433
|
}, 1e3), N = () => {
|
|
4423
|
-
clearTimeout(
|
|
4434
|
+
clearTimeout(_), clearInterval(U), S && clearTimeout(S), window.removeEventListener("message", V);
|
|
4424
4435
|
}, V = (W) => {
|
|
4425
4436
|
var k, D, q, L, R;
|
|
4426
4437
|
if (W.origin !== e.expectedOrigin) return;
|
|
4427
4438
|
if (!gn.has(W.origin)) {
|
|
4428
|
-
|
|
4439
|
+
d.error("[CROSSx] postMessage origin이 허용 목록에 없음:", W.origin), N(), t(new Error("Unauthorized OAuth origin"));
|
|
4429
4440
|
return;
|
|
4430
4441
|
}
|
|
4431
|
-
N(),
|
|
4442
|
+
N(), d.log("[CROSSx] OAuth postMessage 수신 — status:", W.data.status);
|
|
4432
4443
|
const P = W.data.state ?? ((k = W.data.data) == null ? void 0 : k.state);
|
|
4433
4444
|
if (!P || P !== c) {
|
|
4434
4445
|
t(new Error("OAuth state mismatch — possible CSRF attack"));
|
|
4435
4446
|
return;
|
|
4436
4447
|
}
|
|
4437
4448
|
if (W.data.status === "success") {
|
|
4438
|
-
const A = (D = W.data.data) == null ? void 0 : D.idToken, f = (q = W.data.data) == null ? void 0 : q.accessToken,
|
|
4439
|
-
if (
|
|
4449
|
+
const A = (D = W.data.data) == null ? void 0 : D.idToken, f = (q = W.data.data) == null ? void 0 : q.accessToken, x = f ?? A;
|
|
4450
|
+
if (d.log("[CROSSx] OAuth 토큰 수신:", {
|
|
4440
4451
|
hasAccessToken: !!f,
|
|
4441
4452
|
hasIdToken: !!A
|
|
4442
|
-
}), !
|
|
4443
|
-
|
|
4453
|
+
}), !x) {
|
|
4454
|
+
d.error("[CROSSx] 토큰을 찾을 수 없음:", W.data), t(new Error("Token not found in response"));
|
|
4444
4455
|
return;
|
|
4445
4456
|
}
|
|
4446
|
-
A ? be.verifyIdTokenNonce(A, l).then(() => s(
|
|
4447
|
-
|
|
4448
|
-
}) : f ? f.split(".").length === 3 ? be.verifyIdTokenNonce(f, l).then(() => s(
|
|
4449
|
-
|
|
4450
|
-
}) : (
|
|
4457
|
+
A ? be.verifyIdTokenNonce(A, l).then(() => s(x)).catch((b) => {
|
|
4458
|
+
d.error("[CROSSx] nonce 검증 실패:", b), t(b instanceof Error ? b : new Error("nonce verification failed"));
|
|
4459
|
+
}) : f ? f.split(".").length === 3 ? be.verifyIdTokenNonce(f, l).then(() => s(x)).catch((E) => {
|
|
4460
|
+
d.error("[CROSSx] accessToken nonce 검증 실패:", E), t(E instanceof Error ? E : new Error("nonce verification failed"));
|
|
4461
|
+
}) : (d.warn(
|
|
4451
4462
|
"[CROSSx] opaque accessToken만 수신 (idToken 없음) — nonce 검증 불가.",
|
|
4452
4463
|
"서버 측 nonce 검증이 필요합니다."
|
|
4453
|
-
), s(
|
|
4464
|
+
), s(x)) : t(new Error("Token not found in response"));
|
|
4454
4465
|
} else
|
|
4455
|
-
|
|
4466
|
+
d.error("[CROSSx] OAuth 실패:", (L = W.data.data) == null ? void 0 : L.error), t(new Error(((R = W.data.data) == null ? void 0 : R.error) || "Authentication failed"));
|
|
4456
4467
|
};
|
|
4457
4468
|
window.addEventListener("message", V);
|
|
4458
4469
|
});
|
|
@@ -4471,9 +4482,9 @@ class mn {
|
|
|
4471
4482
|
*/
|
|
4472
4483
|
async checkWallet() {
|
|
4473
4484
|
if (this.migrateScenario !== void 0)
|
|
4474
|
-
return
|
|
4485
|
+
return d.log("[Mock] checkWallet → migration_required"), "migration_required";
|
|
4475
4486
|
const s = await this.storage.get(Ce) ? "exists" : "not_found";
|
|
4476
|
-
return
|
|
4487
|
+
return d.log(`[Mock] checkWallet → ${s}`), s;
|
|
4477
4488
|
}
|
|
4478
4489
|
async getOrCreateWallet(e) {
|
|
4479
4490
|
var s;
|
|
@@ -4488,9 +4499,9 @@ class mn {
|
|
|
4488
4499
|
};
|
|
4489
4500
|
await this.storage.set(Ce, n);
|
|
4490
4501
|
const o = (s = this.pinStore) == null ? void 0 : s.get();
|
|
4491
|
-
return o && (await this.storage.set(Te, o),
|
|
4502
|
+
return o && (await this.storage.set(Te, o), d.log("[Mock] 지갑 생성 — PIN 저장됨")), n;
|
|
4492
4503
|
} catch (t) {
|
|
4493
|
-
throw new
|
|
4504
|
+
throw new m(p.WALLET_CREATION_FAILED, "지갑 생성에 실패했습니다", t);
|
|
4494
4505
|
}
|
|
4495
4506
|
}
|
|
4496
4507
|
/** GET /mnemonic/addresses 모킹 — PIN 불필요, 캐시된 주소 반환 */
|
|
@@ -4506,21 +4517,21 @@ class mn {
|
|
|
4506
4517
|
}
|
|
4507
4518
|
async prepare(e, s) {
|
|
4508
4519
|
const t = "mock-" + crypto.randomUUID();
|
|
4509
|
-
return
|
|
4520
|
+
return d.log(`[Mock] prepare action=${e} → uuid=${t}`), { uuid: t, expiresAt: new Date(Date.now() + 5 * 6e4).toISOString() };
|
|
4510
4521
|
}
|
|
4511
4522
|
async signMessage(e, s, t, n = 0, o, i) {
|
|
4512
|
-
return
|
|
4523
|
+
return d.log(`[Mock] signMessage chainId=${s} index=${n} uuid=${o} from=${i}: "${t}"`), { chainId: s, signature: this.generateMockSignature(), format: "hex" };
|
|
4513
4524
|
}
|
|
4514
4525
|
async signTypedData(e, s, t, n = 0, o, i) {
|
|
4515
|
-
return
|
|
4526
|
+
return d.log(`[Mock] signTypedData chainId=${s} index=${n} uuid=${o} from=${i}`), { chainId: s, signature: this.generateMockSignature(), format: "hex" };
|
|
4516
4527
|
}
|
|
4517
4528
|
async signTransaction(e, s, t, n = 0, o) {
|
|
4518
|
-
|
|
4529
|
+
d.log(`[Mock] signTransaction chainId=${s} index=${n} uuid=${o}:`, t);
|
|
4519
4530
|
const i = "0x" + Array(64).fill(0).map(() => Math.floor(Math.random() * 16).toString(16)).join("");
|
|
4520
4531
|
return { chainId: s, signature: this.generateMockSignature(), txHash: i, format: "hex" };
|
|
4521
4532
|
}
|
|
4522
4533
|
async sendTransaction(e, s, t, n) {
|
|
4523
|
-
return
|
|
4534
|
+
return d.log(`[Mock] sendTransaction chainId=${s} uuid=${n}:`, t), { txHash: "0x" + Array(64).fill(0).map(() => Math.floor(Math.random() * 16).toString(16)).join("") };
|
|
4524
4535
|
}
|
|
4525
4536
|
/**
|
|
4526
4537
|
* POST /mnemonic/verify-password 모킹
|
|
@@ -4528,10 +4539,10 @@ class mn {
|
|
|
4528
4539
|
*/
|
|
4529
4540
|
async verifyPin(e) {
|
|
4530
4541
|
var t;
|
|
4531
|
-
if (
|
|
4542
|
+
if (d.log("[Mock] verifyPin"), this.pinScenario === "wrong")
|
|
4532
4543
|
return !1;
|
|
4533
4544
|
const s = await this.storage.get(Te);
|
|
4534
|
-
return s && s !== e ? !1 : (s || await this.storage.set(Te, e), (t = this.pinStore) == null || t.set(e),
|
|
4545
|
+
return s && s !== e ? !1 : (s || await this.storage.set(Te, e), (t = this.pinStore) == null || t.set(e), d.log("[Mock] verifyPin → 성공"), !0);
|
|
4535
4546
|
}
|
|
4536
4547
|
/**
|
|
4537
4548
|
* POST /mnemonic/change-password 모킹
|
|
@@ -4539,17 +4550,17 @@ class mn {
|
|
|
4539
4550
|
*/
|
|
4540
4551
|
async changePin(e, s) {
|
|
4541
4552
|
var o;
|
|
4542
|
-
if (
|
|
4543
|
-
throw new
|
|
4553
|
+
if (d.log("[Mock] changePin"), this.pinScenario === "wrong")
|
|
4554
|
+
throw new m(p.PIN_WRONG, "Incorrect PIN.");
|
|
4544
4555
|
const t = (o = this.pinStore) == null ? void 0 : o.get(), n = await this.storage.get(Te);
|
|
4545
4556
|
if (n && t && n !== t)
|
|
4546
|
-
throw new
|
|
4547
|
-
await this.storage.set(Te, s),
|
|
4557
|
+
throw new m(p.PIN_WRONG, "Incorrect PIN.");
|
|
4558
|
+
await this.storage.set(Te, s), d.log("[Mock] changePin 완료");
|
|
4548
4559
|
}
|
|
4549
4560
|
async migrateWallet(e, s) {
|
|
4550
4561
|
var o;
|
|
4551
|
-
if (
|
|
4552
|
-
throw new
|
|
4562
|
+
if (d.log(`[Mock] migrateWallet pin=${e} sub=${s}`), this.migrateScenario === "wrong_pin")
|
|
4563
|
+
throw new m(p.MIGRATION_FAILED, "Incorrect PIN.", {
|
|
4553
4564
|
permanent: !1,
|
|
4554
4565
|
lockExpiresAt: 0,
|
|
4555
4566
|
remainingAttempts: 4,
|
|
@@ -4563,7 +4574,7 @@ class mn {
|
|
|
4563
4574
|
maxAttempts: 5,
|
|
4564
4575
|
...this.migrateScenario.locked
|
|
4565
4576
|
};
|
|
4566
|
-
throw new
|
|
4577
|
+
throw new m(
|
|
4567
4578
|
p.MIGRATION_PIN_LOCKED,
|
|
4568
4579
|
"Too many incorrect PIN attempts. Your account has been temporarily locked.",
|
|
4569
4580
|
a
|
|
@@ -4577,21 +4588,21 @@ class mn {
|
|
|
4577
4588
|
};
|
|
4578
4589
|
await this.storage.set(Ce, t);
|
|
4579
4590
|
const n = (o = this.pinStore) == null ? void 0 : o.get();
|
|
4580
|
-
return n && (await this.storage.set(Te, n),
|
|
4591
|
+
return n && (await this.storage.set(Te, n), d.log("[Mock] 마이그레이션 — PIN 저장됨")), t;
|
|
4581
4592
|
}
|
|
4582
4593
|
/**
|
|
4583
4594
|
* POST /mnemonic/share-c 모킹
|
|
4584
4595
|
* 새로운 Share-C 문자열을 반환합니다.
|
|
4585
4596
|
*/
|
|
4586
4597
|
async getShareC() {
|
|
4587
|
-
return
|
|
4598
|
+
return d.log("[Mock] getShareC"), "mock-share-c-" + crypto.randomUUID();
|
|
4588
4599
|
}
|
|
4589
4600
|
/**
|
|
4590
4601
|
* POST /mnemonic/verify-recovery-pin 모킹
|
|
4591
4602
|
* CROSSx 4자리 복구 PIN 검증
|
|
4592
4603
|
*/
|
|
4593
4604
|
async verifyRecoveryPin(e, s) {
|
|
4594
|
-
return
|
|
4605
|
+
return d.log("[Mock] verifyRecoveryPin"), { valid: !0 };
|
|
4595
4606
|
}
|
|
4596
4607
|
generateMockEvmAddress() {
|
|
4597
4608
|
return "0x" + Array(40).fill(0).map(
|
|
@@ -4621,7 +4632,7 @@ class Le {
|
|
|
4621
4632
|
getAuthToken() {
|
|
4622
4633
|
const e = this.tokenStore.get();
|
|
4623
4634
|
if (!e)
|
|
4624
|
-
throw new
|
|
4635
|
+
throw new m(
|
|
4625
4636
|
p.AUTH_NOT_AUTHENTICATED,
|
|
4626
4637
|
"인증 토큰을 찾을 수 없습니다. 먼저 로그인해 주세요."
|
|
4627
4638
|
);
|
|
@@ -4635,40 +4646,40 @@ class Le {
|
|
|
4635
4646
|
"X-Project-Id": this.projectId
|
|
4636
4647
|
};
|
|
4637
4648
|
try {
|
|
4638
|
-
const
|
|
4649
|
+
const u = (await this.transport.request({
|
|
4639
4650
|
url: o,
|
|
4640
4651
|
method: e,
|
|
4641
4652
|
headers: i,
|
|
4642
4653
|
body: t ?? void 0
|
|
4643
4654
|
})).data;
|
|
4644
|
-
if (
|
|
4645
|
-
if (
|
|
4646
|
-
const h =
|
|
4647
|
-
|
|
4648
|
-
code:
|
|
4655
|
+
if (u && typeof u.code == "number") {
|
|
4656
|
+
if (u.code < 0 || u.code >= 400) {
|
|
4657
|
+
const h = u.message || u.data || "API 요청에 실패했습니다";
|
|
4658
|
+
d.error("[CROSSx] Wallet Gateway API 에러 (HTTP 200):", {
|
|
4659
|
+
code: u.code,
|
|
4649
4660
|
message: h,
|
|
4650
4661
|
url: o,
|
|
4651
4662
|
method: e
|
|
4652
4663
|
});
|
|
4653
|
-
const
|
|
4654
|
-
throw
|
|
4664
|
+
const g = Le.mapGatewayError(u.code, u.data), _ = Le.getGatewayErrorMessage(u.code, h), w = u.data, v = g === p.PIN_LOCKED ? Le.extractLockDetails(w) : w ?? void 0, y = new m(g, _, v);
|
|
4665
|
+
throw g === p.AUTH_NOT_AUTHENTICATED && this._onUnauthorized && (d.warn("[CROSSx] Gateway -10002 감지 — 강제 로그아웃 실행"), this._onUnauthorized()), y;
|
|
4655
4666
|
}
|
|
4656
|
-
return
|
|
4667
|
+
return d.log("[CROSSx] Wallet Gateway API 성공:", { code: u.code, url: o, method: e }), u.data ?? u;
|
|
4657
4668
|
}
|
|
4658
|
-
return
|
|
4669
|
+
return u;
|
|
4659
4670
|
} catch (l) {
|
|
4660
|
-
if (l instanceof
|
|
4671
|
+
if (l instanceof m) throw l;
|
|
4661
4672
|
if ((a = l.response) != null && a.data) {
|
|
4662
|
-
const
|
|
4663
|
-
throw
|
|
4664
|
-
code:
|
|
4673
|
+
const u = l.response.data, h = u.message || u.data || "API 요청에 실패했습니다", g = u.code || "UNKNOWN";
|
|
4674
|
+
throw d.error("[CROSSx] Wallet Gateway API 에러 (HTTP 에러):", {
|
|
4675
|
+
code: g,
|
|
4665
4676
|
message: h,
|
|
4666
4677
|
url: o,
|
|
4667
4678
|
method: e,
|
|
4668
4679
|
status: (c = l.response) == null ? void 0 : c.status
|
|
4669
|
-
}), new
|
|
4680
|
+
}), new m(
|
|
4670
4681
|
p.UNKNOWN_ERROR,
|
|
4671
|
-
`Wallet Gateway 오류 (${
|
|
4682
|
+
`Wallet Gateway 오류 (${g}): ${h}`
|
|
4672
4683
|
);
|
|
4673
4684
|
}
|
|
4674
4685
|
throw l;
|
|
@@ -4679,9 +4690,9 @@ class Le {
|
|
|
4679
4690
|
* 결과를 내부 캐시에 저장하여 getOrCreateWallet에서 재사용합니다.
|
|
4680
4691
|
*/
|
|
4681
4692
|
async checkWallet() {
|
|
4682
|
-
|
|
4693
|
+
d.log("[CROSSx] GET /mnemonic/check");
|
|
4683
4694
|
const e = await this.request("GET", "/mnemonic/check");
|
|
4684
|
-
return
|
|
4695
|
+
return d.log("[CROSSx] /mnemonic/check 결과:", e.result), this._walletStatusCache = e.result, e.result;
|
|
4685
4696
|
}
|
|
4686
4697
|
/**
|
|
4687
4698
|
* 지갑 생성 또는 로드
|
|
@@ -4692,24 +4703,24 @@ class Le {
|
|
|
4692
4703
|
*/
|
|
4693
4704
|
async getOrCreateWallet(e) {
|
|
4694
4705
|
let s;
|
|
4695
|
-
if (this._walletStatusCache !== null ? (s = this._walletStatusCache, this._walletStatusCache = null,
|
|
4696
|
-
throw
|
|
4706
|
+
if (this._walletStatusCache !== null ? (s = this._walletStatusCache, this._walletStatusCache = null, d.log("[CROSSx] getOrCreateWallet — 캐시된 상태 사용:", s)) : (d.log("[CROSSx] GET /mnemonic/check — 지갑 상태 확인"), s = await this.checkWallet(), this._walletStatusCache = null), s === "migration_required")
|
|
4707
|
+
throw d.log("[CROSSx] migration_required → MIGRATION_BACKUP_EXISTS throw"), new m(
|
|
4697
4708
|
p.MIGRATION_BACKUP_EXISTS,
|
|
4698
4709
|
"CROSSx 백업이 존재합니다. 마이그레이션을 진행해 주세요."
|
|
4699
4710
|
);
|
|
4700
4711
|
if (s === "exists") {
|
|
4701
|
-
|
|
4712
|
+
d.log("[CROSSx] 기존 지갑 발견 — POST /mnemonic/address(0)로 주소 조회");
|
|
4702
4713
|
const o = await this.getAddress(e, 0);
|
|
4703
|
-
return
|
|
4714
|
+
return d.log("[CROSSx] 주소 조회 완료 — address:", o.address), {
|
|
4704
4715
|
id: e,
|
|
4705
4716
|
address: o.address,
|
|
4706
4717
|
derivationPath: "m/44'/60'/0'/0/0",
|
|
4707
4718
|
createdAt: Date.now()
|
|
4708
4719
|
};
|
|
4709
4720
|
}
|
|
4710
|
-
|
|
4721
|
+
d.log("[CROSSx] POST /mnemonic/create — 신규 지갑 생성");
|
|
4711
4722
|
const t = { ignoreBackup: !1, password: this.requirePin() }, n = await this.request("POST", "/mnemonic/create", t);
|
|
4712
|
-
return
|
|
4723
|
+
return d.log("[CROSSx] /mnemonic/create 완료 — address:", n.address), {
|
|
4713
4724
|
id: e,
|
|
4714
4725
|
address: n.address,
|
|
4715
4726
|
derivationPath: "m/44'/60'/0'/0/0",
|
|
@@ -4736,15 +4747,15 @@ class Le {
|
|
|
4736
4747
|
switch (e) {
|
|
4737
4748
|
case "sign":
|
|
4738
4749
|
case "send":
|
|
4739
|
-
if (!s.tx) throw new
|
|
4750
|
+
if (!s.tx) throw new m(p.TX_INVALID_PARAMS, "prepare: tx가 필요합니다");
|
|
4740
4751
|
t = { unsignedTx: this.buildUnsignedTx(s.tx) };
|
|
4741
4752
|
break;
|
|
4742
4753
|
case "sign-message":
|
|
4743
|
-
if (!s.message) throw new
|
|
4754
|
+
if (!s.message) throw new m(p.TX_INVALID_PARAMS, "prepare: message가 필요합니다");
|
|
4744
4755
|
t = { message: s.message }, s.from && (t.from = s.from);
|
|
4745
4756
|
break;
|
|
4746
4757
|
case "sign-typed-data":
|
|
4747
|
-
if (!s.typedData) throw new
|
|
4758
|
+
if (!s.typedData) throw new m(p.TX_INVALID_PARAMS, "prepare: typedData가 필요합니다");
|
|
4748
4759
|
t = { typedData: s.typedData }, s.from && (t.from = s.from);
|
|
4749
4760
|
break;
|
|
4750
4761
|
}
|
|
@@ -4803,13 +4814,13 @@ class Le {
|
|
|
4803
4814
|
)).txHash };
|
|
4804
4815
|
}
|
|
4805
4816
|
async migrateWallet(e, s) {
|
|
4806
|
-
|
|
4817
|
+
d.log("[CROSSx][Migration Phase 4] POST /mnemonic/migrate 호출");
|
|
4807
4818
|
const t = { recoveryPin: e, sub: s, password: this.requirePin() }, n = await this.request(
|
|
4808
4819
|
"POST",
|
|
4809
4820
|
"/mnemonic/migrate",
|
|
4810
4821
|
t
|
|
4811
4822
|
);
|
|
4812
|
-
return
|
|
4823
|
+
return d.log("[CROSSx][Migration Phase 4] /mnemonic/migrate 완료 — address:", n.address), {
|
|
4813
4824
|
id: s,
|
|
4814
4825
|
address: n.address,
|
|
4815
4826
|
derivationPath: "m/44'/60'/0'/0/0",
|
|
@@ -4860,7 +4871,7 @@ class Le {
|
|
|
4860
4871
|
requirePin() {
|
|
4861
4872
|
const e = this.getPin();
|
|
4862
4873
|
if (!e)
|
|
4863
|
-
throw new
|
|
4874
|
+
throw new m(
|
|
4864
4875
|
p.PIN_NOT_SET,
|
|
4865
4876
|
"PIN이 설정되지 않았습니다. PIN을 입력해 주세요."
|
|
4866
4877
|
);
|
|
@@ -5044,7 +5055,7 @@ class De {
|
|
|
5044
5055
|
handleEnvelopeError(e) {
|
|
5045
5056
|
if (e.code < 0) {
|
|
5046
5057
|
const s = typeof e.data == "string" ? e.data : e.message ?? "체인 레지스트리 요청에 실패했습니다";
|
|
5047
|
-
throw new
|
|
5058
|
+
throw new m(
|
|
5048
5059
|
De.mapErrorCode(e.code),
|
|
5049
5060
|
s
|
|
5050
5061
|
);
|
|
@@ -5055,7 +5066,7 @@ class De {
|
|
|
5055
5066
|
(t) => t.chainId === e
|
|
5056
5067
|
);
|
|
5057
5068
|
if (s) return s;
|
|
5058
|
-
throw new
|
|
5069
|
+
throw new m(
|
|
5059
5070
|
p.CHAIN_NOT_SUPPORTED,
|
|
5060
5071
|
`지원하지 않는 체인: ${e}`
|
|
5061
5072
|
);
|
|
@@ -6260,6 +6271,79 @@ const yn = `
|
|
|
6260
6271
|
transform: none !important;
|
|
6261
6272
|
}
|
|
6262
6273
|
|
|
6274
|
+
/* ── Connect Other Wallets (Login Selector) ───────────────── */
|
|
6275
|
+
.__crossx-login-or-divider {
|
|
6276
|
+
display: flex;
|
|
6277
|
+
align-items: center;
|
|
6278
|
+
gap: 16px;
|
|
6279
|
+
width: 100%;
|
|
6280
|
+
}
|
|
6281
|
+
.__crossx-login-or-divider hr {
|
|
6282
|
+
flex: 1;
|
|
6283
|
+
border: none;
|
|
6284
|
+
border-top: 1px solid var(--cx-border);
|
|
6285
|
+
margin: 0;
|
|
6286
|
+
}
|
|
6287
|
+
.__crossx-login-or-divider span {
|
|
6288
|
+
font-size: 16px;
|
|
6289
|
+
font-weight: 400;
|
|
6290
|
+
line-height: 1.3;
|
|
6291
|
+
color: var(--cx-hint);
|
|
6292
|
+
font-family: 'Sora', 'Pretendard', -apple-system, sans-serif;
|
|
6293
|
+
white-space: nowrap;
|
|
6294
|
+
flex-shrink: 0;
|
|
6295
|
+
}
|
|
6296
|
+
.__crossx-connect-other-btn {
|
|
6297
|
+
display: flex;
|
|
6298
|
+
gap: 8px;
|
|
6299
|
+
align-items: center;
|
|
6300
|
+
width: 100%;
|
|
6301
|
+
padding: 16px;
|
|
6302
|
+
background: var(--cx-pill-bg);
|
|
6303
|
+
border: 1px solid var(--cx-border);
|
|
6304
|
+
border-radius: 20px;
|
|
6305
|
+
cursor: pointer;
|
|
6306
|
+
appearance: none;
|
|
6307
|
+
-webkit-appearance: none;
|
|
6308
|
+
-webkit-tap-highlight-color: transparent;
|
|
6309
|
+
box-shadow: none;
|
|
6310
|
+
outline: none;
|
|
6311
|
+
}
|
|
6312
|
+
.__crossx-connect-other-btn:hover,
|
|
6313
|
+
.__crossx-connect-other-btn:focus,
|
|
6314
|
+
.__crossx-connect-other-btn:active {
|
|
6315
|
+
opacity: 1 !important;
|
|
6316
|
+
box-shadow: none !important;
|
|
6317
|
+
outline: none !important;
|
|
6318
|
+
filter: none !important;
|
|
6319
|
+
transform: none !important;
|
|
6320
|
+
background: var(--cx-pill-bg) !important;
|
|
6321
|
+
}
|
|
6322
|
+
.__crossx-connect-other-text {
|
|
6323
|
+
display: flex;
|
|
6324
|
+
flex: 1;
|
|
6325
|
+
flex-direction: column;
|
|
6326
|
+
align-items: flex-start;
|
|
6327
|
+
justify-content: center;
|
|
6328
|
+
min-width: 0;
|
|
6329
|
+
}
|
|
6330
|
+
.__crossx-connect-other-title {
|
|
6331
|
+
font-size: 18px;
|
|
6332
|
+
font-weight: 700;
|
|
6333
|
+
line-height: 1.3;
|
|
6334
|
+
color: var(--cx-value);
|
|
6335
|
+
font-family: 'Pretendard', 'Sora', -apple-system, sans-serif;
|
|
6336
|
+
text-align: left;
|
|
6337
|
+
}
|
|
6338
|
+
.__crossx-connect-other-desc {
|
|
6339
|
+
font-size: 14px;
|
|
6340
|
+
font-weight: 400;
|
|
6341
|
+
line-height: 1.4;
|
|
6342
|
+
color: var(--cx-subtitle);
|
|
6343
|
+
font-family: 'Pretendard', 'Sora', -apple-system, sans-serif;
|
|
6344
|
+
text-align: left;
|
|
6345
|
+
}
|
|
6346
|
+
|
|
6263
6347
|
/* ── Wallet Selector Modal ─────────────────────────────────── */
|
|
6264
6348
|
.__crossx-wallet-list {
|
|
6265
6349
|
display: flex;
|
|
@@ -7028,8 +7112,8 @@ function Tn(r, e) {
|
|
|
7028
7112
|
}
|
|
7029
7113
|
function Rn(r, e) {
|
|
7030
7114
|
const s = e, t = r.nativeSymbol ?? "ETH", n = r.nativeDecimals ?? 18, o = Ye(r.dappName), i = r.to ? `<span class="__crossx-addr-text">${se(r.to)}</span>
|
|
7031
|
-
<button class="__crossx-copy-btn" data-copy="${H(r.to)}" title="Copy address">${xe}</button>` : "<span>—</span>", a = Os(r), l = bn(r.value, t, n) ?? "—",
|
|
7032
|
-
return
|
|
7115
|
+
<button class="__crossx-copy-btn" data-copy="${H(r.to)}" title="Copy address">${xe}</button>` : "<span>—</span>", a = Os(r), l = bn(r.value, t, n) ?? "—", u = document.createElement("div");
|
|
7116
|
+
return u.id = te, u.innerHTML = `
|
|
7033
7117
|
<div class="__crossx-card __crossx-card--migration __crossx-card--send-tx" style="${ce(s)}" role="dialog" aria-modal="true" aria-labelledby="__crossx-ttl">
|
|
7034
7118
|
<div class="__crossx-header">
|
|
7035
7119
|
<p class="__crossx-title" id="__crossx-ttl">Approve transaction</p>
|
|
@@ -7054,7 +7138,7 @@ function Rn(r, e) {
|
|
|
7054
7138
|
<button class="__crossx-approve-btn" id="__crossx-confirm-btn">Approve</button>
|
|
7055
7139
|
</div>
|
|
7056
7140
|
</div>
|
|
7057
|
-
`,
|
|
7141
|
+
`, u;
|
|
7058
7142
|
}
|
|
7059
7143
|
function Ye(r) {
|
|
7060
7144
|
var e;
|
|
@@ -7143,8 +7227,8 @@ function Cn(r, e, s) {
|
|
|
7143
7227
|
if (!a) return;
|
|
7144
7228
|
const c = e.from ? Y("From", `<span class="__crossx-addr-text">${se(e.from)}</span>
|
|
7145
7229
|
<button class="__crossx-copy-btn" data-copy="${H(e.from)}" title="Copy address">${xe}</button>`) : "", l = e.to ? Y("To", `<span class="__crossx-addr-text">${se(e.to)}</span>
|
|
7146
|
-
<button class="__crossx-copy-btn" data-copy="${H(e.to)}" title="Copy address">${xe}</button>`) : "",
|
|
7147
|
-
<button class="__crossx-copy-btn" data-copy="${H(e.txHash)}" title="Copy hash">${xe}</button>`) : "",
|
|
7230
|
+
<button class="__crossx-copy-btn" data-copy="${H(e.to)}" title="Copy address">${xe}</button>`) : "", u = e.amount ? Y("Transfer", `<span>${H(e.amount)}</span>`) : "", h = e.fees ? Y("Tx Fee", `<span>${H(e.fees)}</span>`) : "", g = e.txHash ? Y("Tx Hash", `<span class="__crossx-addr-text">${se(e.txHash)}</span>
|
|
7231
|
+
<button class="__crossx-copy-btn" data-copy="${H(e.txHash)}" title="Copy hash">${xe}</button>`) : "", _ = e.total ? `<div class="__crossx-total-pill">
|
|
7148
7232
|
<span class="__crossx-total-label">Total<br>(including fees)</span>
|
|
7149
7233
|
<span class="__crossx-total-amount">${H(e.total)}</span>
|
|
7150
7234
|
</div>` : "";
|
|
@@ -7152,11 +7236,11 @@ function Cn(r, e, s) {
|
|
|
7152
7236
|
<div class="__crossx-rows">
|
|
7153
7237
|
${c}
|
|
7154
7238
|
${l}
|
|
7155
|
-
${
|
|
7239
|
+
${u}
|
|
7156
7240
|
${h}
|
|
7157
|
-
${
|
|
7241
|
+
${g}
|
|
7158
7242
|
</div>
|
|
7159
|
-
${
|
|
7243
|
+
${_}
|
|
7160
7244
|
<button class="__crossx-approve-btn" id="__crossx-done-btn">${t ? "All Done" : "Done"}</button>
|
|
7161
7245
|
`, a.querySelectorAll(".__crossx-copy-btn").forEach((w) => {
|
|
7162
7246
|
w.addEventListener("click", (v) => {
|
|
@@ -7215,13 +7299,13 @@ function Dn(r, e) {
|
|
|
7215
7299
|
<span class="__crossx-td-label">Primary Type</span>
|
|
7216
7300
|
<span class="__crossx-td-value">${H(o)}</span>
|
|
7217
7301
|
</div>`;
|
|
7218
|
-
for (const [l,
|
|
7219
|
-
const h = Pn(
|
|
7220
|
-
<button class="__crossx-copy-btn" data-copy="${H(String(
|
|
7302
|
+
for (const [l, u] of Object.entries(i)) {
|
|
7303
|
+
const h = Pn(u), _ = kn(u) ? `<span class="__crossx-addr-text">${se(u)}</span>
|
|
7304
|
+
<button class="__crossx-copy-btn" data-copy="${H(String(u))}" title="Copy">${xe}</button>` : `<span>${h}</span>`;
|
|
7221
7305
|
a += `
|
|
7222
7306
|
<div class="__crossx-td-row">
|
|
7223
7307
|
<span class="__crossx-td-label">${H(l)}</span>
|
|
7224
|
-
<div class="__crossx-td-value">${
|
|
7308
|
+
<div class="__crossx-td-value">${_}</div>
|
|
7225
7309
|
</div>`;
|
|
7226
7310
|
}
|
|
7227
7311
|
const c = document.createElement("div");
|
|
@@ -7308,14 +7392,23 @@ const Bn = `<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="h
|
|
|
7308
7392
|
<path d="M10.24 23.69A11.16 11.16 0 0 1 9.66 20c0-1.28.22-2.52.58-3.69v-4.72H4.16A18.49 18.49 0 0 0 2 20c0 2.97.71 5.78 1.97 8.28l6.27-4.59z" fill="#FBBC05"/>
|
|
7309
7393
|
<path d="M20.5 8.76c2.69 0 5.1.92 7 2.73l5.24-5.24C29.58 3.36 25.43 1.5 20.5 1.5A18.49 18.49 0 0 0 4.16 11.59l6.08 4.72C11.68 11.98 15.73 8.76 20.5 8.76z" fill="#EA4335"/>
|
|
7310
7394
|
</svg>`;
|
|
7311
|
-
function Hn(r) {
|
|
7312
|
-
const
|
|
7313
|
-
|
|
7314
|
-
|
|
7395
|
+
function Hn(r, e = !1) {
|
|
7396
|
+
const s = r, t = e ? `
|
|
7397
|
+
<div class="__crossx-login-or-divider">
|
|
7398
|
+
<hr><span>or</span><hr>
|
|
7399
|
+
</div>
|
|
7400
|
+
<button class="__crossx-connect-other-btn" id="__crossx-connect-btn" type="button">
|
|
7401
|
+
<div class="__crossx-connect-other-text">
|
|
7402
|
+
<span class="__crossx-connect-other-title">Connect with Other Wallets</span>
|
|
7403
|
+
<span class="__crossx-connect-other-desc">Connect your existing Web3 wallet to manage your assets.</span>
|
|
7404
|
+
</div>
|
|
7405
|
+
</button>` : "", n = document.createElement("div");
|
|
7406
|
+
return n.id = te, n.innerHTML = `
|
|
7407
|
+
<div class="__crossx-card __crossx-card--migration" style="${ce(s)}" role="dialog" aria-modal="true" aria-labelledby="__crossx-ttl">
|
|
7315
7408
|
<div class="__crossx-header">
|
|
7316
7409
|
<div style="display:flex;flex-direction:column;gap:4px;padding-right:36px;">
|
|
7317
|
-
<p class="__crossx-title" id="__crossx-ttl" style="padding-right:0;">
|
|
7318
|
-
<p class="__crossx-subtitle">
|
|
7410
|
+
<p class="__crossx-title" id="__crossx-ttl" style="padding-right:0;">CROSS Wallet</p>
|
|
7411
|
+
<p class="__crossx-subtitle">Sign in instantly with your social account</p>
|
|
7319
7412
|
</div>
|
|
7320
7413
|
<button class="__crossx-close" id="__crossx-close-btn" aria-label="Close">${ie}</button>
|
|
7321
7414
|
</div>
|
|
@@ -7330,14 +7423,13 @@ function Hn(r) {
|
|
|
7330
7423
|
<span class="__crossx-login-icon">${Un}</span>
|
|
7331
7424
|
<span class="__crossx-login-btn-label">Sign in with Google</span>
|
|
7332
7425
|
</button>
|
|
7333
|
-
</div
|
|
7334
|
-
<hr class="__crossx-divider">
|
|
7426
|
+
</div>${t}
|
|
7335
7427
|
<p class="__crossx-login-terms">
|
|
7336
7428
|
By continuing, you agree to NEXUS <a class="__crossx-login-terms-link" href="https://terms.crosstoken.io/docs/cross-terms-of-use" target="_blank" rel="noopener noreferrer">Terms of Service</a> and consent to its <a class="__crossx-login-terms-link" href="https://terms.crosstoken.io/docs/nexus-privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy.</a>
|
|
7337
7429
|
</p>
|
|
7338
7430
|
</div>
|
|
7339
7431
|
</div>
|
|
7340
|
-
`,
|
|
7432
|
+
`, n;
|
|
7341
7433
|
}
|
|
7342
7434
|
function Fn(r, e = !0) {
|
|
7343
7435
|
const s = r, t = e ? `<button class="__crossx-close" id="__crossx-close-btn" aria-label="Close">${ie}</button>` : "", n = e ? '<button class="__crossx-skip-btn" id="__crossx-skip-btn">Skip for Now</button>' : "", o = document.createElement("div");
|
|
@@ -7364,7 +7456,7 @@ function Fn(r, e = !0) {
|
|
|
7364
7456
|
`, o;
|
|
7365
7457
|
}
|
|
7366
7458
|
function Gn(r, e) {
|
|
7367
|
-
const s = r, { errorMessage: t, attemptCount: n, maxAttempts: o = 5 } = e ?? {}, i = !!t, a = i ? " --error" : "", c = n != null && n > 0 ? `<p class="__crossx-pin-attempt">${n}/${o}</p>` : "", l = n != null && n >= 3 ? '<p class="__crossx-pin-warning">Your account will be locked after further failures.</p>' : "",
|
|
7459
|
+
const s = r, { errorMessage: t, attemptCount: n, maxAttempts: o = 5 } = e ?? {}, i = !!t, a = i ? " --error" : "", c = n != null && n > 0 ? `<p class="__crossx-pin-attempt">${n}/${o}</p>` : "", l = n != null && n >= 3 ? '<p class="__crossx-pin-warning">Your account will be locked after further failures.</p>' : "", u = i ? `<p class="__crossx-pin-error-text">${t}</p>` : "", h = document.createElement("div");
|
|
7368
7460
|
return h.id = te, h.innerHTML = `
|
|
7369
7461
|
<div class="__crossx-card __crossx-card--migration" style="${ce(s)}" role="dialog" aria-modal="true" aria-labelledby="__crossx-ttl">
|
|
7370
7462
|
<div class="__crossx-header">
|
|
@@ -7382,7 +7474,7 @@ function Gn(r, e) {
|
|
|
7382
7474
|
<input class="__crossx-pin-input${a}" type="tel" maxlength="1" inputmode="numeric" pattern="[0-9]" autocomplete="off">
|
|
7383
7475
|
</div>
|
|
7384
7476
|
<p class="__crossx-pin-hint">Enter your 4-digit PIN to recover your wallet.</p>
|
|
7385
|
-
${
|
|
7477
|
+
${u}
|
|
7386
7478
|
</div>
|
|
7387
7479
|
</div>
|
|
7388
7480
|
`, h;
|
|
@@ -7464,7 +7556,7 @@ function nt(r) {
|
|
|
7464
7556
|
<span id="__crossx-pin6-lock-countdown"></span>
|
|
7465
7557
|
</p>` : "", a = e ? " --locked" : "", c = Array.from(
|
|
7466
7558
|
{ length: 6 },
|
|
7467
|
-
(l,
|
|
7559
|
+
(l, u) => `<input class="__crossx-pin6-box${a}" type="password" maxlength="1" inputmode="numeric" pattern="[0-9]" autocomplete="off" aria-label="PIN digit ${u + 1}"${e ? " disabled" : ""}>`
|
|
7468
7560
|
).join("");
|
|
7469
7561
|
return `
|
|
7470
7562
|
<div class="__crossx-header">
|
|
@@ -7506,15 +7598,15 @@ function zn(r) {
|
|
|
7506
7598
|
function ot(r, e, s, t, n, o) {
|
|
7507
7599
|
var V, W;
|
|
7508
7600
|
let i = !!(o && o > Date.now()), a = !1;
|
|
7509
|
-
const c = () => Array.from(r.querySelectorAll(".__crossx-pin6-box")), l = () => r.querySelector("#__crossx-pin6-boxes"),
|
|
7601
|
+
const c = () => Array.from(r.querySelectorAll(".__crossx-pin6-box")), l = () => r.querySelector("#__crossx-pin6-boxes"), u = () => r.querySelector("#__crossx-pin6-error"), h = () => r.querySelector("#__crossx-pin6-lock-msg"), g = () => r.querySelector("#__crossx-pin6-lock-countdown"), _ = () => r.querySelector(".__crossx-pin6-body"), w = () => c().map((P) => P.value).join(""), v = (P) => {
|
|
7510
7602
|
i = P, c().forEach((k) => {
|
|
7511
7603
|
k.disabled = P, k.classList.toggle("--locked", P);
|
|
7512
7604
|
});
|
|
7513
7605
|
}, y = () => {
|
|
7514
|
-
const P =
|
|
7606
|
+
const P = u();
|
|
7515
7607
|
P && (P.textContent = "");
|
|
7516
7608
|
}, S = (P) => {
|
|
7517
|
-
const k =
|
|
7609
|
+
const k = u();
|
|
7518
7610
|
k && (k.textContent = P);
|
|
7519
7611
|
const D = l();
|
|
7520
7612
|
D == null || D.classList.add("--shake"), setTimeout(() => D == null ? void 0 : D.classList.remove("--shake"), 500), c().forEach((q) => {
|
|
@@ -7528,17 +7620,17 @@ function ot(r, e, s, t, n, o) {
|
|
|
7528
7620
|
v(!0), c().forEach((A) => {
|
|
7529
7621
|
A.value = "";
|
|
7530
7622
|
});
|
|
7531
|
-
const k =
|
|
7623
|
+
const k = u();
|
|
7532
7624
|
if (k && (k.textContent = "Too many failed attempts. Please wait."), !h()) {
|
|
7533
7625
|
const A = document.createElement("p");
|
|
7534
7626
|
A.className = "__crossx-pin6-lock-msg", A.id = "__crossx-pin6-lock-msg", A.innerHTML = `${Cs}<span id="__crossx-pin6-lock-countdown"></span>`;
|
|
7535
|
-
const f =
|
|
7536
|
-
f ? f.insertAdjacentElement("afterend", A) : (R =
|
|
7627
|
+
const f = u();
|
|
7628
|
+
f ? f.insertAdjacentElement("afterend", A) : (R = _()) == null || R.appendChild(A);
|
|
7537
7629
|
}
|
|
7538
7630
|
const D = () => {
|
|
7539
|
-
var
|
|
7540
|
-
const A = P - Date.now(), f =
|
|
7541
|
-
A <= 0 ? (clearInterval(q), v(!1), (
|
|
7631
|
+
var x;
|
|
7632
|
+
const A = P - Date.now(), f = g();
|
|
7633
|
+
A <= 0 ? (clearInterval(q), v(!1), (x = h()) == null || x.remove(), k && (k.textContent = ""), setTimeout(() => {
|
|
7542
7634
|
var b;
|
|
7543
7635
|
return (b = c()[0]) == null ? void 0 : b.focus();
|
|
7544
7636
|
}, 50)) : f && (f.textContent = ` ${zn(A)}`);
|
|
@@ -7581,7 +7673,7 @@ function ot(r, e, s, t, n, o) {
|
|
|
7581
7673
|
};
|
|
7582
7674
|
(V = l()) == null || V.addEventListener("click", (P) => {
|
|
7583
7675
|
P.target.classList.contains("__crossx-pin6-box") || N();
|
|
7584
|
-
}), (W =
|
|
7676
|
+
}), (W = _()) == null || W.addEventListener("click", (P) => {
|
|
7585
7677
|
const k = P.target;
|
|
7586
7678
|
k.classList.contains("__crossx-pin6-box") || k.closest("button") || N();
|
|
7587
7679
|
}), c().forEach((P, k) => {
|
|
@@ -7605,8 +7697,8 @@ function ot(r, e, s, t, n, o) {
|
|
|
7605
7697
|
const q = (((R = D.clipboardData) == null ? void 0 : R.getData("text")) ?? "").replace(/\D/g, "").slice(0, 6);
|
|
7606
7698
|
if (!q) return;
|
|
7607
7699
|
const L = c();
|
|
7608
|
-
q.split("").forEach((f,
|
|
7609
|
-
L[
|
|
7700
|
+
q.split("").forEach((f, x) => {
|
|
7701
|
+
L[x] && (L[x].value = f);
|
|
7610
7702
|
}), (A = L[Math.min(q.length - 1, 5)]) == null || A.focus(), y(), w().length === 6 && setTimeout(U, 80);
|
|
7611
7703
|
}), P.addEventListener("focus", () => P.select());
|
|
7612
7704
|
});
|
|
@@ -7625,7 +7717,7 @@ function Jn(r, e, s) {
|
|
|
7625
7717
|
i.addEventListener("input", () => {
|
|
7626
7718
|
const c = i.value.replace(/\D/g, "");
|
|
7627
7719
|
i.value = c ? c[0] : "", c && a < 3 && t[a + 1].focus();
|
|
7628
|
-
const l = Array.from(t).map((
|
|
7720
|
+
const l = Array.from(t).map((u) => u.value).join("");
|
|
7629
7721
|
l.length === 4 && setTimeout(() => e(l), 200);
|
|
7630
7722
|
}), i.addEventListener("keydown", (c) => {
|
|
7631
7723
|
c.key === "Backspace" && !i.value && a > 0 && (t[a - 1].focus(), t[a - 1].value = ""), c.key === "Escape" && s();
|
|
@@ -7636,11 +7728,11 @@ function Jn(r, e, s) {
|
|
|
7636
7728
|
c.preventDefault();
|
|
7637
7729
|
const l = (((h = c.clipboardData) == null ? void 0 : h.getData("text")) ?? "").replace(/\D/g, "").slice(0, 4);
|
|
7638
7730
|
if (!l) return;
|
|
7639
|
-
l.split("").forEach((
|
|
7640
|
-
t[
|
|
7731
|
+
l.split("").forEach((g, _) => {
|
|
7732
|
+
t[_] && (t[_].value = g);
|
|
7641
7733
|
});
|
|
7642
|
-
const
|
|
7643
|
-
t[
|
|
7734
|
+
const u = Math.min(l.length, 3);
|
|
7735
|
+
t[u].focus(), l.length === 4 && setTimeout(() => e(l), 200);
|
|
7644
7736
|
});
|
|
7645
7737
|
});
|
|
7646
7738
|
const n = r.querySelector(".__crossx-pin-inputs");
|
|
@@ -7678,7 +7770,7 @@ class Xn {
|
|
|
7678
7770
|
let c = !1;
|
|
7679
7771
|
const l = () => {
|
|
7680
7772
|
c || (c = !0, i.remove(), document.body.style.overflow = a);
|
|
7681
|
-
},
|
|
7773
|
+
}, u = (y) => {
|
|
7682
7774
|
l(), n(y);
|
|
7683
7775
|
}, h = () => {
|
|
7684
7776
|
l(), n(null);
|
|
@@ -7687,24 +7779,24 @@ class Xn {
|
|
|
7687
7779
|
i.querySelectorAll(".__crossx-wallet-item").forEach((y) => {
|
|
7688
7780
|
y.addEventListener("click", () => {
|
|
7689
7781
|
const S = y.dataset.walletAddress ?? "", C = parseInt(y.dataset.walletIndex ?? "0", 10);
|
|
7690
|
-
|
|
7782
|
+
u({ address: S, index: C });
|
|
7691
7783
|
});
|
|
7692
7784
|
});
|
|
7693
7785
|
})();
|
|
7694
|
-
const
|
|
7695
|
-
|
|
7696
|
-
|
|
7786
|
+
const _ = i.querySelector("#__crossx-add-wallet-btn");
|
|
7787
|
+
_ && _.addEventListener("click", async () => {
|
|
7788
|
+
_.disabled = !0;
|
|
7697
7789
|
try {
|
|
7698
7790
|
const y = await s();
|
|
7699
7791
|
o.push(y);
|
|
7700
7792
|
const S = i.querySelector("#__crossx-wallet-list");
|
|
7701
7793
|
if (S) {
|
|
7702
7794
|
const C = document.createElement("button");
|
|
7703
|
-
C.className = "__crossx-wallet-item", C.dataset.walletIndex = String(y.index), C.dataset.walletAddress = y.address, C.innerHTML = `<span class="__crossx-wallet-addr">${se(y.address)}</span>`, C.addEventListener("click", () =>
|
|
7795
|
+
C.className = "__crossx-wallet-item", C.dataset.walletIndex = String(y.index), C.dataset.walletAddress = y.address, C.innerHTML = `<span class="__crossx-wallet-addr">${se(y.address)}</span>`, C.addEventListener("click", () => u(y)), S.appendChild(C), C.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
7704
7796
|
}
|
|
7705
7797
|
} catch {
|
|
7706
7798
|
} finally {
|
|
7707
|
-
|
|
7799
|
+
_.disabled = !1;
|
|
7708
7800
|
}
|
|
7709
7801
|
}), (v = i.querySelector("#__crossx-close-btn")) == null || v.addEventListener("click", h), i.addEventListener("click", (y) => {
|
|
7710
7802
|
y.target === i && h();
|
|
@@ -7716,30 +7808,31 @@ class Xn {
|
|
|
7716
7808
|
});
|
|
7717
7809
|
}
|
|
7718
7810
|
/**
|
|
7719
|
-
* 로그인 프로바이더 선택 팝업: "
|
|
7811
|
+
* 로그인 프로바이더 선택 팝업: "CROSS Wallet"
|
|
7720
7812
|
* Apple / Google 버튼을 표시하고 선택된 프로바이더를 반환합니다.
|
|
7721
|
-
*
|
|
7813
|
+
* showConnectOtherWallets가 true이면 "Connect with Other Wallets" 버튼도 표시합니다.
|
|
7814
|
+
* @returns 'google' | 'apple' | 'external' | null(취소)
|
|
7722
7815
|
*/
|
|
7723
|
-
showLoginSelector() {
|
|
7724
|
-
return new Promise((
|
|
7725
|
-
var
|
|
7816
|
+
showLoginSelector(e) {
|
|
7817
|
+
return new Promise((s) => {
|
|
7818
|
+
var c, l, u, h;
|
|
7726
7819
|
he();
|
|
7727
|
-
const
|
|
7728
|
-
pe(
|
|
7729
|
-
const
|
|
7730
|
-
|
|
7731
|
-
},
|
|
7732
|
-
|
|
7820
|
+
const t = Hn(this.tokens, e == null ? void 0 : e.showConnectOtherWallets);
|
|
7821
|
+
pe(t);
|
|
7822
|
+
const n = () => t.remove(), o = (g) => {
|
|
7823
|
+
n(), s(g);
|
|
7824
|
+
}, i = () => {
|
|
7825
|
+
n(), s(null);
|
|
7733
7826
|
};
|
|
7734
|
-
(
|
|
7735
|
-
|
|
7736
|
-
}),
|
|
7737
|
-
|
|
7827
|
+
(c = t.querySelector("#__crossx-apple-btn")) == null || c.addEventListener("click", () => o("apple")), (l = t.querySelector("#__crossx-google-btn")) == null || l.addEventListener("click", () => o("google")), (u = t.querySelector("#__crossx-connect-btn")) == null || u.addEventListener("click", () => o("external")), (h = t.querySelector("#__crossx-close-btn")) == null || h.addEventListener("click", i), t.addEventListener("click", (g) => {
|
|
7828
|
+
g.target === t && i();
|
|
7829
|
+
}), t.querySelectorAll(".__crossx-login-terms-link").forEach((g) => {
|
|
7830
|
+
g.addEventListener("click", (_) => _.stopPropagation());
|
|
7738
7831
|
});
|
|
7739
|
-
const
|
|
7740
|
-
|
|
7832
|
+
const a = (g) => {
|
|
7833
|
+
g.key === "Escape" && (document.removeEventListener("keydown", a), i());
|
|
7741
7834
|
};
|
|
7742
|
-
document.addEventListener("keydown",
|
|
7835
|
+
document.addEventListener("keydown", a);
|
|
7743
7836
|
});
|
|
7744
7837
|
}
|
|
7745
7838
|
/**
|
|
@@ -7758,14 +7851,14 @@ class Xn {
|
|
|
7758
7851
|
o(), t("recover");
|
|
7759
7852
|
};
|
|
7760
7853
|
if ((a = n.querySelector("#__crossx-recover-btn")) == null || a.addEventListener("click", i), s) {
|
|
7761
|
-
const
|
|
7854
|
+
const u = () => {
|
|
7762
7855
|
o(), t("skip");
|
|
7763
7856
|
};
|
|
7764
|
-
(c = n.querySelector("#__crossx-skip-btn")) == null || c.addEventListener("click",
|
|
7765
|
-
|
|
7857
|
+
(c = n.querySelector("#__crossx-skip-btn")) == null || c.addEventListener("click", u), (l = n.querySelector("#__crossx-close-btn")) == null || l.addEventListener("click", u), n.addEventListener("click", (g) => {
|
|
7858
|
+
g.target === n && u();
|
|
7766
7859
|
});
|
|
7767
|
-
const h = (
|
|
7768
|
-
|
|
7860
|
+
const h = (g) => {
|
|
7861
|
+
g.key === "Escape" && (document.removeEventListener("keydown", h), u());
|
|
7769
7862
|
};
|
|
7770
7863
|
document.addEventListener("keydown", h);
|
|
7771
7864
|
}
|
|
@@ -7801,13 +7894,13 @@ class Xn {
|
|
|
7801
7894
|
}, a = Zt(this.tokens, Kn(n)), c = document.body.style.overflow;
|
|
7802
7895
|
document.body.style.overflow = "hidden", pe(a);
|
|
7803
7896
|
let l = !1;
|
|
7804
|
-
const
|
|
7897
|
+
const u = () => {
|
|
7805
7898
|
l || (l = !0, a.remove(), document.body.style.overflow = c);
|
|
7806
7899
|
}, h = (C) => {
|
|
7807
|
-
|
|
7808
|
-
},
|
|
7809
|
-
|
|
7810
|
-
},
|
|
7900
|
+
u(), s(C);
|
|
7901
|
+
}, g = () => {
|
|
7902
|
+
u(), s(null);
|
|
7903
|
+
}, _ = a.querySelector(".__crossx-card"), w = {
|
|
7811
7904
|
tooShort: (t == null ? void 0 : t.pinValidation_tooShort) ?? "Please enter a 6-digit PIN.",
|
|
7812
7905
|
numbersOnly: (t == null ? void 0 : t.pinValidation_numbersOnly) ?? "Only numbers (0-9) are allowed.",
|
|
7813
7906
|
repeatingDigit: (t == null ? void 0 : t.pinValidation_repeatingDigit) ?? "Cannot use the same number 3+ times in a row.",
|
|
@@ -7815,27 +7908,27 @@ class Xn {
|
|
|
7815
7908
|
alternatingPattern: (t == null ? void 0 : t.pinValidation_alternatingPattern) ?? "Repeating patterns (e.g., 121212) are not allowed."
|
|
7816
7909
|
}, v = (C) => {
|
|
7817
7910
|
var U;
|
|
7818
|
-
|
|
7911
|
+
_.innerHTML = nt({
|
|
7819
7912
|
title: i.title,
|
|
7820
7913
|
headerSubtitle: i.headerSubtitle
|
|
7821
|
-
}), (U =
|
|
7914
|
+
}), (U = _.querySelector("#__crossx-close-btn")) == null || U.addEventListener("click", g), ot(_, (N) => {
|
|
7822
7915
|
N === C ? h(C) : y(o.mismatchError);
|
|
7823
|
-
},
|
|
7916
|
+
}, g);
|
|
7824
7917
|
}, y = (C) => {
|
|
7825
7918
|
var U;
|
|
7826
|
-
|
|
7919
|
+
_.innerHTML = nt({
|
|
7827
7920
|
title: o.title,
|
|
7828
7921
|
headerSubtitle: o.headerSubtitle,
|
|
7829
7922
|
subtitle: o.subtitle,
|
|
7830
7923
|
errorMessage: C
|
|
7831
|
-
}), (U =
|
|
7924
|
+
}), (U = _.querySelector("#__crossx-close-btn")) == null || U.addEventListener("click", g), ot(_, (N) => {
|
|
7832
7925
|
const V = Vn(N, w);
|
|
7833
7926
|
V ? y(V) : v(N);
|
|
7834
|
-
},
|
|
7927
|
+
}, g);
|
|
7835
7928
|
};
|
|
7836
7929
|
(() => {
|
|
7837
7930
|
var q;
|
|
7838
|
-
const C = Array.from(
|
|
7931
|
+
const C = Array.from(_.querySelectorAll(".__crossx-pw-notice-item")), U = _.querySelector("#__crossx-pin-notice-next"), N = /* @__PURE__ */ new Set();
|
|
7839
7932
|
U.removeAttribute("disabled");
|
|
7840
7933
|
const V = U.dataset.nextLabel ?? "Next", W = U.dataset.submitLabel ?? "I Understand", P = () => {
|
|
7841
7934
|
const L = N.size === C.length;
|
|
@@ -7870,9 +7963,9 @@ class Xn {
|
|
|
7870
7963
|
L.scrollIntoView({ behavior: "smooth", block: "nearest" }), L.classList.add("--highlight"), setTimeout(() => {
|
|
7871
7964
|
L.classList.remove("--highlight"), k(L, R);
|
|
7872
7965
|
}, 400);
|
|
7873
|
-
}), (q =
|
|
7966
|
+
}), (q = _.querySelector("#__crossx-close-btn")) == null || q.addEventListener("click", g);
|
|
7874
7967
|
})(), a.addEventListener("click", (C) => {
|
|
7875
|
-
C.target === a &&
|
|
7968
|
+
C.target === a && g();
|
|
7876
7969
|
});
|
|
7877
7970
|
});
|
|
7878
7971
|
}
|
|
@@ -7895,18 +7988,18 @@ class Xn {
|
|
|
7895
7988
|
})
|
|
7896
7989
|
), l = document.body.style.overflow;
|
|
7897
7990
|
document.body.style.overflow = "hidden", pe(c);
|
|
7898
|
-
let
|
|
7991
|
+
let u = !1;
|
|
7899
7992
|
const h = () => {
|
|
7900
|
-
|
|
7901
|
-
},
|
|
7993
|
+
u || (u = !0, c.remove(), document.body.style.overflow = l);
|
|
7994
|
+
}, g = (S) => {
|
|
7902
7995
|
h(), s(S);
|
|
7903
|
-
},
|
|
7996
|
+
}, _ = () => {
|
|
7904
7997
|
h(), s(null);
|
|
7905
7998
|
}, w = (S) => {
|
|
7906
7999
|
h(), t(S);
|
|
7907
8000
|
}, v = c.querySelector(".__crossx-card");
|
|
7908
|
-
(y = v.querySelector("#__crossx-close-btn")) == null || y.addEventListener("click",
|
|
7909
|
-
S.target === c &&
|
|
8001
|
+
(y = v.querySelector("#__crossx-close-btn")) == null || y.addEventListener("click", _), ot(v, g, _, w, e == null ? void 0 : e.onSubmit, e == null ? void 0 : e.lockExpiresAt), c.addEventListener("click", (S) => {
|
|
8002
|
+
S.target === c && _();
|
|
7910
8003
|
});
|
|
7911
8004
|
});
|
|
7912
8005
|
}
|
|
@@ -7950,8 +8043,8 @@ class Xn {
|
|
|
7950
8043
|
}, a = () => {
|
|
7951
8044
|
i(), t();
|
|
7952
8045
|
}, c = o(a);
|
|
7953
|
-
(l = n.querySelector("#__crossx-close-btn")) == null || l.addEventListener("click", a), n.addEventListener("click", (
|
|
7954
|
-
|
|
8046
|
+
(l = n.querySelector("#__crossx-close-btn")) == null || l.addEventListener("click", a), n.addEventListener("click", (u) => {
|
|
8047
|
+
u.target === n && a();
|
|
7955
8048
|
});
|
|
7956
8049
|
});
|
|
7957
8050
|
}
|
|
@@ -7969,11 +8062,11 @@ class Xn {
|
|
|
7969
8062
|
n(), s();
|
|
7970
8063
|
};
|
|
7971
8064
|
(a = t.querySelector("#__crossx-done-btn")) == null || a.addEventListener("click", o), (c = t.querySelector("#__crossx-close-btn")) == null || c.addEventListener("click", o), t.querySelectorAll(".__crossx-copy-btn").forEach((l) => {
|
|
7972
|
-
l.addEventListener("click", (
|
|
7973
|
-
var
|
|
7974
|
-
|
|
8065
|
+
l.addEventListener("click", (u) => {
|
|
8066
|
+
var g;
|
|
8067
|
+
u.stopPropagation();
|
|
7975
8068
|
const h = l.dataset.copy;
|
|
7976
|
-
h && ((
|
|
8069
|
+
h && ((g = navigator.clipboard) == null || g.writeText(h).catch(() => {
|
|
7977
8070
|
}));
|
|
7978
8071
|
});
|
|
7979
8072
|
}), t.addEventListener("click", (l) => {
|
|
@@ -7999,12 +8092,12 @@ class Xn {
|
|
|
7999
8092
|
const a = () => {
|
|
8000
8093
|
i || (i = !0, o(), t());
|
|
8001
8094
|
}, c = () => {
|
|
8002
|
-
var
|
|
8003
|
-
(
|
|
8004
|
-
|
|
8095
|
+
var u, h;
|
|
8096
|
+
(u = n.querySelector("#__crossx-done-btn")) == null || u.addEventListener("click", a), (h = n.querySelector("#__crossx-close-btn")) == null || h.addEventListener("click", a), n.addEventListener("click", (g) => {
|
|
8097
|
+
g.target === n && a();
|
|
8005
8098
|
});
|
|
8006
|
-
const l = (
|
|
8007
|
-
|
|
8099
|
+
const l = (g) => {
|
|
8100
|
+
g.key === "Escape" && (document.removeEventListener("keydown", l), a());
|
|
8008
8101
|
};
|
|
8009
8102
|
document.addEventListener("keydown", l);
|
|
8010
8103
|
};
|
|
@@ -8015,7 +8108,7 @@ class Xn {
|
|
|
8015
8108
|
}
|
|
8016
8109
|
requestConfirmation(e) {
|
|
8017
8110
|
return new Promise((s) => {
|
|
8018
|
-
var c, l,
|
|
8111
|
+
var c, l, u;
|
|
8019
8112
|
he();
|
|
8020
8113
|
let t;
|
|
8021
8114
|
e.type === "sign-message" ? t = Ln(e, this.tokens) : e.type === "sign-typed-data" ? t = Dn(e, this.tokens) : e.type === "sign" ? t = Tn(e, this.tokens) : t = Rn(e, this.tokens), pe(t);
|
|
@@ -8024,12 +8117,12 @@ class Xn {
|
|
|
8024
8117
|
}, i = () => {
|
|
8025
8118
|
n(), s(!1);
|
|
8026
8119
|
};
|
|
8027
|
-
(c = t.querySelector("#__crossx-confirm-btn")) == null || c.addEventListener("click", o), (l = t.querySelector("#__crossx-cancel-btn")) == null || l.addEventListener("click", i), (
|
|
8028
|
-
h.addEventListener("click", (
|
|
8120
|
+
(c = t.querySelector("#__crossx-confirm-btn")) == null || c.addEventListener("click", o), (l = t.querySelector("#__crossx-cancel-btn")) == null || l.addEventListener("click", i), (u = t.querySelector("#__crossx-close-btn")) == null || u.addEventListener("click", i), t.querySelectorAll(".__crossx-copy-btn").forEach((h) => {
|
|
8121
|
+
h.addEventListener("click", (g) => {
|
|
8029
8122
|
var w;
|
|
8030
|
-
|
|
8031
|
-
const
|
|
8032
|
-
|
|
8123
|
+
g.stopPropagation();
|
|
8124
|
+
const _ = h.dataset.copy;
|
|
8125
|
+
_ && ((w = navigator.clipboard) == null || w.writeText(_).catch(() => {
|
|
8033
8126
|
}));
|
|
8034
8127
|
});
|
|
8035
8128
|
}), t.addEventListener("click", (h) => {
|
|
@@ -8076,21 +8169,21 @@ function so(r, e) {
|
|
|
8076
8169
|
gatewayUrl: s.walletGatewayUrl,
|
|
8077
8170
|
projectId: r.projectId
|
|
8078
8171
|
}, o = t.authMode !== "cookie" && Ot.isAvailable();
|
|
8079
|
-
!o && t.authMode !== "cookie" &&
|
|
8172
|
+
!o && t.authMode !== "cookie" && d.warn(
|
|
8080
8173
|
"[CROSSx] IndexedDB 사용 불가 — LocalStorage fallback 사용 중.",
|
|
8081
8174
|
"refresh_token이 평문 저장되지 않도록 세션 영속성이 제한됩니다.",
|
|
8082
8175
|
"IndexedDB를 지원하는 브라우저 사용을 권장합니다."
|
|
8083
8176
|
), t.secureStorageAvailable = o;
|
|
8084
|
-
const i = o ? new Ot(r.projectId) : new rr(), a = new hn(), c = new xn(), l = new be(),
|
|
8085
|
-
let
|
|
8086
|
-
r.useMockWallet ? (
|
|
8177
|
+
const i = o ? new Ot(r.projectId) : new rr(), a = new hn(), c = new xn(), l = new be(), u = new Zn(), h = new es();
|
|
8178
|
+
let g;
|
|
8179
|
+
r.useMockWallet ? (d.log("[CROSSx] Mock Wallet Provider 사용"), g = new mn(i, h)) : (d.log("[CROSSx] Remote Wallet Provider 사용"), g = new Le(
|
|
8087
8180
|
n,
|
|
8088
8181
|
i,
|
|
8089
8182
|
c,
|
|
8090
|
-
|
|
8183
|
+
u,
|
|
8091
8184
|
h
|
|
8092
8185
|
));
|
|
8093
|
-
const
|
|
8186
|
+
const _ = new De(n, c), w = new Xn(r.theme ?? "light", r.themeTokens), v = e != null && e.wrapConfirmation ? e.wrapConfirmation(w) : w;
|
|
8094
8187
|
return new it(
|
|
8095
8188
|
t,
|
|
8096
8189
|
n,
|
|
@@ -8098,15 +8191,15 @@ function so(r, e) {
|
|
|
8098
8191
|
a,
|
|
8099
8192
|
c,
|
|
8100
8193
|
l,
|
|
8101
|
-
|
|
8102
|
-
|
|
8194
|
+
g,
|
|
8195
|
+
u,
|
|
8103
8196
|
v,
|
|
8104
|
-
|
|
8197
|
+
_,
|
|
8105
8198
|
h
|
|
8106
8199
|
);
|
|
8107
8200
|
}
|
|
8108
8201
|
export {
|
|
8109
|
-
|
|
8202
|
+
m as CROSSxError,
|
|
8110
8203
|
Fs as CROSSxEthereumProvider,
|
|
8111
8204
|
it as CROSSxSDK,
|
|
8112
8205
|
to as ChainId,
|