@nexus-cross/crossx-sdk-core 1.3.1 → 1.3.3
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 +766 -676
- 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 f = 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:", f.length, ")");
|
|
379
|
+
const { accessToken: w, refreshToken: v } = await this.exchangeFirebaseToken(f, h);
|
|
376
380
|
let y, S;
|
|
377
381
|
try {
|
|
378
|
-
const U = this.crypto.decodeJWT(
|
|
382
|
+
const U = this.crypto.decodeJWT(f);
|
|
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(f);
|
|
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.4 초기화 중..."), 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, f;
|
|
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) => (f = 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
|
+
), f) throw f;
|
|
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 f = g.pinStatus;
|
|
1921
|
+
if (i = f.maxAttempts, o = i - f.remainingAttempts, f.remainingAttempts === 0 && f.lockExpiresAt) {
|
|
1922
|
+
const w = f.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 f = g.details;
|
|
1930
|
+
if (i = (f == null ? void 0 : f.maxAttempts) ?? 5, (f == null ? void 0 : f.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 = ((f == null ? void 0 : f.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
|
/**
|
|
@@ -1948,27 +1959,24 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1948
1959
|
* jsonRpc 서비스를 통해 nonce 및 가스 파라미터를 자동 조회합니다.
|
|
1949
1960
|
*/
|
|
1950
1961
|
async withResolvedGasAndFee(e, s) {
|
|
1951
|
-
const t = (
|
|
1962
|
+
const t = (f) => !(f != null && f.trim()), n = e.nonce === void 0 || e.nonce === null, o = t(e.gasLimit), i = t(e.gasPrice) && t(e.maxFeePerGas), a = !t(e.maxFeePerGas) && t(e.maxPriorityFeePerGas);
|
|
1952
1963
|
if (!n && !o && !i && !a) return e;
|
|
1953
|
-
const c = { ...e };
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
if (l) {
|
|
1966
|
-
const d = Rt;
|
|
1967
|
-
c.maxFeePerGas = "0x" + (BigInt(l) + BigInt(d)).toString(16), c.maxPriorityFeePerGas = d, u.log("[CROSSx] Dynamic 체인 감지 — baseFee:", l, "maxFeePerGas:", c.maxFeePerGas, "maxPriorityFeePerGas: 1 Gwei");
|
|
1964
|
+
const c = { ...e }, l = n ? c.from ?? this.address : void 0;
|
|
1965
|
+
l && d.log("[CROSSx] nonce 비어있음 → eth_getTransactionCount 호출 (from:", l, ")"), o && d.log("[CROSSx] gasLimit 비어있음 → eth_estimateGas 호출"), i && d.log("[CROSSx] gasPrice & maxFeePerGas 비어있음 → baseFee 조회로 Dynamic/Legacy 판별");
|
|
1966
|
+
const [u, h, g] = await Promise.all([
|
|
1967
|
+
l ? this.jsonRpc.call("eth_getTransactionCount", [l, "pending"], s) : null,
|
|
1968
|
+
o ? this.estimateGas(e, s) : null,
|
|
1969
|
+
i ? this.getBaseFeePerGas(s) : null
|
|
1970
|
+
]);
|
|
1971
|
+
if (l && (c.nonce = parseInt(u ?? "0x0", 16), d.log("[CROSSx] nonce 결과:", c.nonce)), o && (c.gasLimit = h, d.log("[CROSSx] estimateGas 결과:", c.gasLimit)), i) {
|
|
1972
|
+
const f = g;
|
|
1973
|
+
if (f) {
|
|
1974
|
+
const w = Rt;
|
|
1975
|
+
c.maxFeePerGas = "0x" + (BigInt(f) + BigInt(w)).toString(16), c.maxPriorityFeePerGas = w, d.log("[CROSSx] Dynamic 체인 감지 — baseFee:", f, "maxFeePerGas:", c.maxFeePerGas, "maxPriorityFeePerGas: 1 Gwei");
|
|
1968
1976
|
} else
|
|
1969
|
-
c.gasPrice = er,
|
|
1977
|
+
c.gasPrice = er, d.log("[CROSSx] Legacy 체인 감지 — gasPrice: 2 Gwei");
|
|
1970
1978
|
}
|
|
1971
|
-
return !i && a && (c.maxPriorityFeePerGas = Rt,
|
|
1979
|
+
return !i && a && (c.maxPriorityFeePerGas = Rt, d.log("[CROSSx] maxPriorityFeePerGas 비어있음 → 1 Gwei 기본값 적용")), c;
|
|
1972
1980
|
}
|
|
1973
1981
|
/**
|
|
1974
1982
|
* EIP-712 signTypedData 호출 시 chainId와 typedData.domain.chainId 정합성 검증.
|
|
@@ -1980,7 +1988,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1980
1988
|
const t = re.extractDomainChainId(s);
|
|
1981
1989
|
if (e === "0") {
|
|
1982
1990
|
if (t !== void 0 && t !== 0)
|
|
1983
|
-
throw new
|
|
1991
|
+
throw new m(
|
|
1984
1992
|
p.TYPED_DATA_CHAIN_ID_MISMATCH,
|
|
1985
1993
|
`오프체인 서명(chainId=0)에서는 typedData.domain.chainId가 없거나 0이어야 합니다. 현재 값: ${t}`
|
|
1986
1994
|
);
|
|
@@ -1990,12 +1998,12 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
1990
1998
|
if (n) {
|
|
1991
1999
|
const o = Number(n[1]);
|
|
1992
2000
|
if (t === void 0)
|
|
1993
|
-
throw new
|
|
2001
|
+
throw new m(
|
|
1994
2002
|
p.TYPED_DATA_CHAIN_ID_MISMATCH,
|
|
1995
2003
|
`온체인 서명(${e})에서는 typedData.domain.chainId가 반드시 있어야 합니다`
|
|
1996
2004
|
);
|
|
1997
2005
|
if (t !== o)
|
|
1998
|
-
throw new
|
|
2006
|
+
throw new m(
|
|
1999
2007
|
p.TYPED_DATA_CHAIN_ID_MISMATCH,
|
|
2000
2008
|
`typedData.domain.chainId (${t})가 chainId (${e}, 예상값: ${o})와 일치하지 않습니다`
|
|
2001
2009
|
);
|
|
@@ -2014,9 +2022,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2014
2022
|
static validateSignatureFormat(e) {
|
|
2015
2023
|
const s = e.startsWith("0x") ? e.slice(2) : e;
|
|
2016
2024
|
if (!/^[0-9a-fA-F]+$/.test(s))
|
|
2017
|
-
throw new
|
|
2025
|
+
throw new m(p.SIGNATURE_FAILED, "유효하지 않은 서명: 올바른 hex 문자열이 아닙니다");
|
|
2018
2026
|
if (s.length !== kt)
|
|
2019
|
-
throw new
|
|
2027
|
+
throw new m(
|
|
2020
2028
|
p.SIGNATURE_FAILED,
|
|
2021
2029
|
`서명 길이가 유효하지 않습니다: ${kt} hex 문자(65 바이트) 예상, 현재 ${s.length}`
|
|
2022
2030
|
);
|
|
@@ -2025,9 +2033,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2025
2033
|
static validateSignedTxFormat(e) {
|
|
2026
2034
|
const s = e.startsWith("0x") ? e.slice(2) : e;
|
|
2027
2035
|
if (!/^[0-9a-fA-F]+$/.test(s))
|
|
2028
|
-
throw new
|
|
2036
|
+
throw new m(p.SIGNATURE_FAILED, "유효하지 않은 서명된 트랜잭션: 올바른 hex 문자열이 아닙니다");
|
|
2029
2037
|
if (s.length < 2)
|
|
2030
|
-
throw new
|
|
2038
|
+
throw new m(p.SIGNATURE_FAILED, "유효하지 않은 서명된 트랜잭션: 너무 짧습니다");
|
|
2031
2039
|
}
|
|
2032
2040
|
/**
|
|
2033
2041
|
* Gateway 서명 응답의 ecrecover 검증 (XF-036)
|
|
@@ -2040,17 +2048,17 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2040
2048
|
try {
|
|
2041
2049
|
const n = this.crypto.recoverPersonalSignSigner(e, s);
|
|
2042
2050
|
if (n.toLowerCase() !== t.toLowerCase())
|
|
2043
|
-
throw
|
|
2051
|
+
throw d.error("[CROSSx] 서명 검증 실패: 서명자 주소 불일치", {
|
|
2044
2052
|
expected: t,
|
|
2045
2053
|
recovered: n
|
|
2046
|
-
}), new
|
|
2054
|
+
}), new m(
|
|
2047
2055
|
p.SIGNATURE_SIGNER_MISMATCH,
|
|
2048
2056
|
`서명자 주소가 일치하지 않습니다: 예상 ${t}, 복원된 주소 ${n}`
|
|
2049
2057
|
);
|
|
2050
|
-
|
|
2058
|
+
d.log("[CROSSx] 서명 ecrecover 검증 성공");
|
|
2051
2059
|
} catch (n) {
|
|
2052
|
-
if (n instanceof
|
|
2053
|
-
|
|
2060
|
+
if (n instanceof m) throw n;
|
|
2061
|
+
d.warn("[CROSSx] ecrecover 검증 중 예외 (무시):", n);
|
|
2054
2062
|
}
|
|
2055
2063
|
}
|
|
2056
2064
|
/** AuthResult를 내부 상태에 반영합니다. */
|
|
@@ -2076,7 +2084,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2076
2084
|
* (서버 세션 종료 API를 호출하면 또 다시 -10002가 날 수 있으므로 스킵)
|
|
2077
2085
|
*/
|
|
2078
2086
|
forceLogout() {
|
|
2079
|
-
this.authenticated && (
|
|
2087
|
+
this.authenticated && (d.warn("[CROSSx] 인증 만료(Gateway -10002) — 강제 로그아웃"), this.clearAuthState());
|
|
2080
2088
|
}
|
|
2081
2089
|
/**
|
|
2082
2090
|
* Firebase sign_in_provider 값을 정규화합니다.
|
|
@@ -2094,8 +2102,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2094
2102
|
if (this.pinStore.has()) return;
|
|
2095
2103
|
const e = await this.confirmation.showPinSetupPrompt();
|
|
2096
2104
|
if (!e)
|
|
2097
|
-
throw new
|
|
2098
|
-
this.pinStore.set(e),
|
|
2105
|
+
throw new m(p.PIN_CANCELLED, "사용자가 PIN 설정을 취소했습니다");
|
|
2106
|
+
this.pinStore.set(e), d.log("[CROSSx] PIN 설정 완료 (메모리 캐시)");
|
|
2099
2107
|
}
|
|
2100
2108
|
/**
|
|
2101
2109
|
* 서명/전송 전 PIN 입력 모달 표시 후 메모리 캐시
|
|
@@ -2108,8 +2116,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2108
2116
|
e && this.pinStore.clear();
|
|
2109
2117
|
const s = await this.confirmation.showPinInputPrompt({ errorMessage: e });
|
|
2110
2118
|
if (!s)
|
|
2111
|
-
throw new
|
|
2112
|
-
this.pinStore.set(s),
|
|
2119
|
+
throw new m(p.PIN_CANCELLED, "사용자가 PIN 입력을 취소했습니다");
|
|
2120
|
+
this.pinStore.set(s), d.log("[CROSSx] PIN 입력 완료 (메모리 캐시)");
|
|
2113
2121
|
}
|
|
2114
2122
|
/**
|
|
2115
2123
|
* PIN 입력 + verify-password API로 서버 검증
|
|
@@ -2129,7 +2137,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2129
2137
|
else if (this.pinStore.has())
|
|
2130
2138
|
return;
|
|
2131
2139
|
if (this._verifyPinMutex && !e) {
|
|
2132
|
-
|
|
2140
|
+
d.log("[CROSSx] ensureVerifiedPin: 진행 중인 검증 대기"), await this._verifyPinMutex;
|
|
2133
2141
|
return;
|
|
2134
2142
|
}
|
|
2135
2143
|
let t, n;
|
|
@@ -2144,8 +2152,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2144
2152
|
lockExpiresAt: s
|
|
2145
2153
|
});
|
|
2146
2154
|
if (!i)
|
|
2147
|
-
throw new
|
|
2148
|
-
this.pinStore.set(i),
|
|
2155
|
+
throw new m(p.PIN_CANCELLED, "사용자가 PIN 입력을 취소했습니다");
|
|
2156
|
+
this.pinStore.set(i), d.log("[CROSSx] PIN 캐시 완료 (verifyPin 미지원, 로컬 전용)"), t();
|
|
2149
2157
|
return;
|
|
2150
2158
|
}
|
|
2151
2159
|
const o = await this.confirmation.showPinInputPrompt({
|
|
@@ -2156,9 +2164,9 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2156
2164
|
var a;
|
|
2157
2165
|
this.pinStore.set(i);
|
|
2158
2166
|
try {
|
|
2159
|
-
return await this.walletProvider.verifyPin(i) ? (
|
|
2167
|
+
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
2168
|
} catch (c) {
|
|
2161
|
-
if (this.pinStore.clear(), c instanceof
|
|
2169
|
+
if (this.pinStore.clear(), c instanceof m) {
|
|
2162
2170
|
if (c.code === p.PIN_WRONG)
|
|
2163
2171
|
return { ok: !1, error: "Incorrect PIN. Please try again." };
|
|
2164
2172
|
if (c.code === p.PIN_INVALID)
|
|
@@ -2171,8 +2179,8 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2171
2179
|
}
|
|
2172
2180
|
});
|
|
2173
2181
|
if (!o)
|
|
2174
|
-
throw new
|
|
2175
|
-
this.pinStore.set(o),
|
|
2182
|
+
throw new m(p.PIN_CANCELLED, "사용자가 PIN 입력을 취소했습니다");
|
|
2183
|
+
this.pinStore.set(o), d.log("[CROSSx] PIN 갱신 완료 (verify 모달 닫힘)"), t();
|
|
2176
2184
|
} catch (o) {
|
|
2177
2185
|
throw n(o), o;
|
|
2178
2186
|
} finally {
|
|
@@ -2189,16 +2197,16 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2189
2197
|
async loadWalletAfterAuth(e) {
|
|
2190
2198
|
if (!this.userId) return;
|
|
2191
2199
|
const s = await this.fetchWalletStatus();
|
|
2192
|
-
if (
|
|
2200
|
+
if (d.log("[CROSSx] loadWalletAfterAuth 지갑 상태:", s), s !== "exists") return;
|
|
2193
2201
|
const t = await this.walletProvider.getAddresses(this.userId);
|
|
2194
2202
|
if (t.length > 0) {
|
|
2195
2203
|
const o = e !== void 0 ? t.find((i) => i.index === e) ?? t[0] : t[0];
|
|
2196
|
-
this.address = o.address, this.activeWalletIndex = o.index,
|
|
2204
|
+
this.address = o.address, this.activeWalletIndex = o.index, d.log("[CROSSx] 캐시된 주소 로드 완료 (비밀번호 불필요):", this.address), this.emit("addressChanged", { address: o.address, index: o.index });
|
|
2197
2205
|
return;
|
|
2198
2206
|
}
|
|
2199
|
-
|
|
2207
|
+
d.log("[CROSSx] 주소 캐시 없음 — 비밀번호 확인 후 address(0) 조회"), await this.ensureVerifiedPin();
|
|
2200
2208
|
const n = await this.walletProvider.getAddress(this.userId, 0);
|
|
2201
|
-
this.address = n.address, this.activeWalletIndex = 0,
|
|
2209
|
+
this.address = n.address, this.activeWalletIndex = 0, d.log("[CROSSx] 세션 복원 후 지갑 주소 로드 완료:", this.address), this.emit("addressChanged", { address: n.address, index: 0 });
|
|
2202
2210
|
}
|
|
2203
2211
|
/**
|
|
2204
2212
|
* PIN_WRONG 에러 시 서버 검증 포함 PIN 재입력 모달을 표시하고 재시도합니다.
|
|
@@ -2218,7 +2226,7 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2218
2226
|
try {
|
|
2219
2227
|
return await e();
|
|
2220
2228
|
} catch (n) {
|
|
2221
|
-
if (n instanceof
|
|
2229
|
+
if (n instanceof m)
|
|
2222
2230
|
if (n.code === p.PIN_WRONG)
|
|
2223
2231
|
s = "Incorrect PIN. Please enter your current PIN.";
|
|
2224
2232
|
else if (n.code === p.PIN_INVALID)
|
|
@@ -2232,11 +2240,11 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2232
2240
|
throw n;
|
|
2233
2241
|
}
|
|
2234
2242
|
for (; ; ) {
|
|
2235
|
-
|
|
2243
|
+
d.warn("[CROSSx] PIN 불일치/잠금 — 재입력 요청:", s), this.pinStore.clear(), await this.ensureVerifiedPin(s, t), t = void 0;
|
|
2236
2244
|
try {
|
|
2237
2245
|
return await e();
|
|
2238
2246
|
} catch (n) {
|
|
2239
|
-
if (n instanceof
|
|
2247
|
+
if (n instanceof m) {
|
|
2240
2248
|
if (n.code === p.PIN_WRONG) {
|
|
2241
2249
|
s = "Incorrect PIN. Please try again.";
|
|
2242
2250
|
continue;
|
|
@@ -2264,21 +2272,21 @@ const Xs = 2e3, Tt = 6e4, Zs = 1e3, Qs = 1e4, er = "0x77359400", Rt = "0x3B9ACA0
|
|
|
2264
2272
|
async resolveAddress(e) {
|
|
2265
2273
|
if (e === void 0 || e === this.activeWalletIndex) {
|
|
2266
2274
|
if (!this.address)
|
|
2267
|
-
throw new
|
|
2275
|
+
throw new m(p.AUTH_NOT_AUTHENTICATED, "활성 지갑 주소를 찾을 수 없습니다");
|
|
2268
2276
|
return { address: this.address, index: this.activeWalletIndex };
|
|
2269
2277
|
}
|
|
2270
2278
|
return { address: (await this.withPinRetry(() => this.walletProvider.getAddress(this.userId, e))).address, index: e };
|
|
2271
2279
|
}
|
|
2272
2280
|
ensureInitialized() {
|
|
2273
2281
|
if (!this.initialized)
|
|
2274
|
-
throw new
|
|
2282
|
+
throw new m(
|
|
2275
2283
|
p.AUTH_NOT_INITIALIZED,
|
|
2276
2284
|
"SDK가 초기화되지 않았습니다. initialize()를 먼저 호출하세요."
|
|
2277
2285
|
);
|
|
2278
2286
|
}
|
|
2279
2287
|
ensureAuthenticated() {
|
|
2280
2288
|
if (this.ensureInitialized(), !this.authenticated)
|
|
2281
|
-
throw new
|
|
2289
|
+
throw new m(
|
|
2282
2290
|
p.AUTH_NOT_AUTHENTICATED,
|
|
2283
2291
|
"인증되지 않은 상태입니다. signIn()을 먼저 호출하세요."
|
|
2284
2292
|
);
|
|
@@ -2321,7 +2329,7 @@ class rr {
|
|
|
2321
2329
|
const t = JSON.stringify(s);
|
|
2322
2330
|
localStorage.setItem(this.prefix + e, t);
|
|
2323
2331
|
} catch (t) {
|
|
2324
|
-
throw
|
|
2332
|
+
throw d.error("Storage set error:", t), t;
|
|
2325
2333
|
}
|
|
2326
2334
|
}
|
|
2327
2335
|
async get(e) {
|
|
@@ -2329,14 +2337,14 @@ class rr {
|
|
|
2329
2337
|
const s = localStorage.getItem(this.prefix + e);
|
|
2330
2338
|
return s ? JSON.parse(s) : null;
|
|
2331
2339
|
} catch (s) {
|
|
2332
|
-
return
|
|
2340
|
+
return d.error("Storage get error:", s), null;
|
|
2333
2341
|
}
|
|
2334
2342
|
}
|
|
2335
2343
|
async remove(e) {
|
|
2336
2344
|
try {
|
|
2337
2345
|
localStorage.removeItem(this.prefix + e);
|
|
2338
2346
|
} catch (s) {
|
|
2339
|
-
throw
|
|
2347
|
+
throw d.error("Storage remove error:", s), s;
|
|
2340
2348
|
}
|
|
2341
2349
|
}
|
|
2342
2350
|
async clear() {
|
|
@@ -2345,7 +2353,7 @@ class rr {
|
|
|
2345
2353
|
s.startsWith(this.prefix) && localStorage.removeItem(s);
|
|
2346
2354
|
});
|
|
2347
2355
|
} catch (e) {
|
|
2348
|
-
throw
|
|
2356
|
+
throw d.error("Storage clear error:", e), e;
|
|
2349
2357
|
}
|
|
2350
2358
|
}
|
|
2351
2359
|
}
|
|
@@ -2415,25 +2423,25 @@ class Ot {
|
|
|
2415
2423
|
async migrateFromLegacyDB() {
|
|
2416
2424
|
if (this.dbName === Xe) return null;
|
|
2417
2425
|
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 = () =>
|
|
2426
|
+
const e = await this.openDB(Xe), s = e.transaction([Se, de], "readonly"), t = s.objectStore(Se).get($e), n = await new Promise((l, u) => {
|
|
2427
|
+
t.onsuccess = () => l(t.result), t.onerror = () => u(t.error);
|
|
2420
2428
|
});
|
|
2421
2429
|
if (!n)
|
|
2422
2430
|
return e.close(), null;
|
|
2423
2431
|
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 = () =>
|
|
2432
|
+
new Promise((l, u) => {
|
|
2433
|
+
o.onsuccess = () => l(o.result), o.onerror = () => u(o.error);
|
|
2426
2434
|
}),
|
|
2427
|
-
new Promise((l,
|
|
2428
|
-
i.onsuccess = () => l(i.result), i.onerror = () =>
|
|
2435
|
+
new Promise((l, u) => {
|
|
2436
|
+
i.onsuccess = () => l(i.result), i.onerror = () => u(i.error);
|
|
2429
2437
|
})
|
|
2430
2438
|
]);
|
|
2431
2439
|
e.close(), await this.idbPut(Se, $e, n);
|
|
2432
2440
|
for (let l = 0; l < c.length; l++)
|
|
2433
2441
|
await this.idbPut(de, String(c[l]), a[l]);
|
|
2434
|
-
return indexedDB.deleteDatabase(Xe),
|
|
2442
|
+
return indexedDB.deleteDatabase(Xe), d.log("[CROSSx] IndexedDB 레거시 DB 마이그레이션 완료"), n;
|
|
2435
2443
|
} catch (e) {
|
|
2436
|
-
return
|
|
2444
|
+
return d.warn("[CROSSx] IndexedDB 레거시 DB 마이그레이션 실패:", e), null;
|
|
2437
2445
|
}
|
|
2438
2446
|
}
|
|
2439
2447
|
async encrypt(e) {
|
|
@@ -2460,7 +2468,7 @@ class Ot {
|
|
|
2460
2468
|
const t = JSON.stringify(s), n = await this.encrypt(t);
|
|
2461
2469
|
await this.idbPut(de, e, n);
|
|
2462
2470
|
} catch (t) {
|
|
2463
|
-
throw
|
|
2471
|
+
throw d.error("[CROSSx] IndexedDB set error:", t), t;
|
|
2464
2472
|
}
|
|
2465
2473
|
}
|
|
2466
2474
|
async get(e) {
|
|
@@ -2471,21 +2479,21 @@ class Ot {
|
|
|
2471
2479
|
const t = await this.decrypt(s);
|
|
2472
2480
|
return JSON.parse(t);
|
|
2473
2481
|
} catch (s) {
|
|
2474
|
-
return
|
|
2482
|
+
return d.error("[CROSSx] IndexedDB get error:", s), null;
|
|
2475
2483
|
}
|
|
2476
2484
|
}
|
|
2477
2485
|
async remove(e) {
|
|
2478
2486
|
try {
|
|
2479
2487
|
await this.ensureReady(), await this.idbDelete(de, e);
|
|
2480
2488
|
} catch (s) {
|
|
2481
|
-
throw
|
|
2489
|
+
throw d.error("[CROSSx] IndexedDB remove error:", s), s;
|
|
2482
2490
|
}
|
|
2483
2491
|
}
|
|
2484
2492
|
async clear() {
|
|
2485
2493
|
try {
|
|
2486
2494
|
await this.ensureReady(), await this.idbClear(de);
|
|
2487
2495
|
} catch (e) {
|
|
2488
|
-
throw
|
|
2496
|
+
throw d.error("[CROSSx] IndexedDB clear error:", e), e;
|
|
2489
2497
|
}
|
|
2490
2498
|
}
|
|
2491
2499
|
/**
|
|
@@ -2662,11 +2670,11 @@ class fr {
|
|
|
2662
2670
|
const a = Ze(e), c = this.outputLen;
|
|
2663
2671
|
if (c % 4)
|
|
2664
2672
|
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
2665
|
-
const l = c / 4,
|
|
2666
|
-
if (l >
|
|
2673
|
+
const l = c / 4, u = this.get();
|
|
2674
|
+
if (l > u.length)
|
|
2667
2675
|
throw new Error("_sha2: outputLen bigger than state");
|
|
2668
2676
|
for (let h = 0; h < l; h++)
|
|
2669
|
-
a.setUint32(4 * h,
|
|
2677
|
+
a.setUint32(4 * h, u[h], o);
|
|
2670
2678
|
}
|
|
2671
2679
|
digest() {
|
|
2672
2680
|
const { buffer: e, outputLen: s } = this;
|
|
@@ -2787,15 +2795,15 @@ class vr extends fr {
|
|
|
2787
2795
|
for (let h = 0; h < 16; h++, s += 4)
|
|
2788
2796
|
we[h] = e.getUint32(s, !1);
|
|
2789
2797
|
for (let h = 16; h < 64; h++) {
|
|
2790
|
-
const
|
|
2798
|
+
const g = we[h - 15], f = we[h - 2], w = ue(g, 7) ^ ue(g, 18) ^ g >>> 3, v = ue(f, 17) ^ ue(f, 19) ^ f >>> 10;
|
|
2791
2799
|
we[h] = v + we[h - 7] + w + we[h - 16] | 0;
|
|
2792
2800
|
}
|
|
2793
|
-
let { A: t, B: n, C: o, D: i, E: a, F: c, G: l, H:
|
|
2801
|
+
let { A: t, B: n, C: o, D: i, E: a, F: c, G: l, H: u } = this;
|
|
2794
2802
|
for (let h = 0; h < 64; h++) {
|
|
2795
|
-
const
|
|
2796
|
-
|
|
2803
|
+
const g = ue(a, 6) ^ ue(a, 11) ^ ue(a, 25), f = 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;
|
|
2804
|
+
u = l, l = c, c = a, a = i + f | 0, i = o, o = n, n = t, t = f + v | 0;
|
|
2797
2805
|
}
|
|
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,
|
|
2806
|
+
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
2807
|
}
|
|
2800
2808
|
roundClean() {
|
|
2801
2809
|
Pe(we);
|
|
@@ -2887,28 +2895,28 @@ function kr(r, e, s) {
|
|
|
2887
2895
|
if (ge(r, "hashLen"), ge(e, "qByteLen"), typeof s != "function")
|
|
2888
2896
|
throw new Error("hmacFn must be a function");
|
|
2889
2897
|
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),
|
|
2898
|
+
let c = t(r), l = t(r), u = 0;
|
|
2891
2899
|
const h = () => {
|
|
2892
|
-
c.fill(1), l.fill(0),
|
|
2893
|
-
},
|
|
2894
|
-
l =
|
|
2900
|
+
c.fill(1), l.fill(0), u = 0;
|
|
2901
|
+
}, g = (...y) => s(l, ve(c, ...y)), f = (y = n) => {
|
|
2902
|
+
l = g(o, y), c = g(), y.length !== 0 && (l = g(i, y), c = g());
|
|
2895
2903
|
}, w = () => {
|
|
2896
|
-
if (
|
|
2904
|
+
if (u++ >= a)
|
|
2897
2905
|
throw new Error("drbg: tried max amount of iterations");
|
|
2898
2906
|
let y = 0;
|
|
2899
2907
|
const S = [];
|
|
2900
2908
|
for (; y < e; ) {
|
|
2901
|
-
c =
|
|
2909
|
+
c = g();
|
|
2902
2910
|
const C = c.slice();
|
|
2903
2911
|
S.push(C), y += c.length;
|
|
2904
2912
|
}
|
|
2905
2913
|
return ve(...S);
|
|
2906
2914
|
};
|
|
2907
2915
|
return (y, S) => {
|
|
2908
|
-
h(),
|
|
2916
|
+
h(), f(y);
|
|
2909
2917
|
let C;
|
|
2910
2918
|
for (; !(C = S(w())); )
|
|
2911
|
-
|
|
2919
|
+
f();
|
|
2912
2920
|
return h(), C;
|
|
2913
2921
|
};
|
|
2914
2922
|
}
|
|
@@ -2977,10 +2985,10 @@ function Or(r, e) {
|
|
|
2977
2985
|
function Cr(r) {
|
|
2978
2986
|
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
2987
|
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(
|
|
2988
|
+
let l = a.pow(c, i), u = a.mul(l, t);
|
|
2989
|
+
const h = a.mul(l, n), g = a.mul(l, o), f = a.eql(a.sqr(u), c), w = a.eql(a.sqr(h), c);
|
|
2990
|
+
l = a.cmov(l, u, f), u = a.cmov(g, h, w);
|
|
2991
|
+
const v = a.eql(a.sqr(u), c), y = a.cmov(l, u, v);
|
|
2984
2992
|
return xt(a, y, c), y;
|
|
2985
2993
|
};
|
|
2986
2994
|
}
|
|
@@ -3004,18 +3012,18 @@ function xs(r) {
|
|
|
3004
3012
|
return l;
|
|
3005
3013
|
if (Bt(c, l) !== 1)
|
|
3006
3014
|
throw new Error("Cannot find square root");
|
|
3007
|
-
let
|
|
3008
|
-
for (; !c.eql(
|
|
3009
|
-
if (c.is0(
|
|
3015
|
+
let u = s, h = c.mul(c.ONE, o), g = c.pow(l, e), f = c.pow(l, i);
|
|
3016
|
+
for (; !c.eql(g, c.ONE); ) {
|
|
3017
|
+
if (c.is0(g))
|
|
3010
3018
|
return c.ZERO;
|
|
3011
|
-
let w = 1, v = c.sqr(
|
|
3019
|
+
let w = 1, v = c.sqr(g);
|
|
3012
3020
|
for (; !c.eql(v, c.ONE); )
|
|
3013
|
-
if (w++, v = c.sqr(v), w ===
|
|
3021
|
+
if (w++, v = c.sqr(v), w === u)
|
|
3014
3022
|
throw new Error("Cannot find square root");
|
|
3015
|
-
const y = ee << BigInt(
|
|
3016
|
-
|
|
3023
|
+
const y = ee << BigInt(u - w - 1), S = c.pow(h, y);
|
|
3024
|
+
u = w, h = c.sqr(S), g = c.mul(g, h), f = c.mul(f, S);
|
|
3017
3025
|
}
|
|
3018
|
-
return
|
|
3026
|
+
return f;
|
|
3019
3027
|
};
|
|
3020
3028
|
}
|
|
3021
3029
|
function Lr(r) {
|
|
@@ -3231,8 +3239,8 @@ function Ht(r, e, s) {
|
|
|
3231
3239
|
const { windowSize: t, mask: n, maxNumber: o, shiftBy: i } = s;
|
|
3232
3240
|
let a = Number(r & n), c = r >> i;
|
|
3233
3241
|
a > t && (a -= o, c += Ae);
|
|
3234
|
-
const l = e * t,
|
|
3235
|
-
return { nextN: c, offset:
|
|
3242
|
+
const l = e * t, u = l + Math.abs(a) - 1, h = a === 0, g = a < 0, f = e % 2 !== 0;
|
|
3243
|
+
return { nextN: c, offset: u, isZero: h, isNeg: g, isNegF: f, offsetF: l };
|
|
3236
3244
|
}
|
|
3237
3245
|
const et = /* @__PURE__ */ new WeakMap(), bs = /* @__PURE__ */ new WeakMap();
|
|
3238
3246
|
function tt(r) {
|
|
@@ -3293,8 +3301,8 @@ class Fr {
|
|
|
3293
3301
|
let n = this.ZERO, o = this.BASE;
|
|
3294
3302
|
const i = Qe(e, this.bits);
|
|
3295
3303
|
for (let a = 0; a < i.windows; a++) {
|
|
3296
|
-
const { nextN: c, offset: l, isZero:
|
|
3297
|
-
t = c,
|
|
3304
|
+
const { nextN: c, offset: l, isZero: u, isNeg: h, isNegF: g, offsetF: f } = Ht(t, a, i);
|
|
3305
|
+
t = c, u ? o = o.add(Ke(g, s[f])) : n = n.add(Ke(h, s[l]));
|
|
3298
3306
|
}
|
|
3299
3307
|
return Ft(t), { p: n, f: o };
|
|
3300
3308
|
}
|
|
@@ -3306,10 +3314,10 @@ class Fr {
|
|
|
3306
3314
|
wNAFUnsafe(e, s, t, n = this.ZERO) {
|
|
3307
3315
|
const o = Qe(e, this.bits);
|
|
3308
3316
|
for (let i = 0; i < o.windows && t !== Ne; i++) {
|
|
3309
|
-
const { nextN: a, offset: c, isZero: l, isNeg:
|
|
3317
|
+
const { nextN: a, offset: c, isZero: l, isNeg: u } = Ht(t, i, o);
|
|
3310
3318
|
if (t = a, !l) {
|
|
3311
3319
|
const h = s[c];
|
|
3312
|
-
n = n.add(
|
|
3320
|
+
n = n.add(u ? h.negate() : h);
|
|
3313
3321
|
}
|
|
3314
3322
|
}
|
|
3315
3323
|
return Ft(t), n;
|
|
@@ -3418,13 +3426,13 @@ Ss.create = (r, e) => new vs(r, e);
|
|
|
3418
3426
|
const Wt = (r, e) => (r + (r >= 0 ? e : -e) / Es) / e;
|
|
3419
3427
|
function Kr(r, e, s) {
|
|
3420
3428
|
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 >=
|
|
3429
|
+
let l = r - a * t - c * o, u = -a * n - c * i;
|
|
3430
|
+
const h = l < _e, g = u < _e;
|
|
3431
|
+
h && (l = -l), g && (u = -u);
|
|
3432
|
+
const f = ft(Math.ceil(Rr(s) / 2)) + Re;
|
|
3433
|
+
if (l < _e || l >= f || u < _e || u >= f)
|
|
3426
3434
|
throw new Error("splitScalar (endomorphism): failed, k=" + r);
|
|
3427
|
-
return { k1neg: h, k1: l, k2neg:
|
|
3435
|
+
return { k1neg: h, k1: l, k2neg: g, k2: u };
|
|
3428
3436
|
}
|
|
3429
3437
|
function ct(r) {
|
|
3430
3438
|
if (!["compact", "recovered", "der"].includes(r))
|
|
@@ -3482,8 +3490,8 @@ const ye = {
|
|
|
3482
3490
|
throw new s("tlv.decode: length bytes not complete");
|
|
3483
3491
|
if (l[0] === 0)
|
|
3484
3492
|
throw new s("tlv.decode(long): zero leftmost byte");
|
|
3485
|
-
for (const
|
|
3486
|
-
i = i << 8 |
|
|
3493
|
+
for (const u of l)
|
|
3494
|
+
i = i << 8 | u;
|
|
3487
3495
|
if (t += c, i < 128)
|
|
3488
3496
|
throw new s("tlv.decode(long): not minimal encoding");
|
|
3489
3497
|
}
|
|
@@ -3520,8 +3528,8 @@ const ye = {
|
|
|
3520
3528
|
const { Err: e, _int: s, _tlv: t } = ye, n = z(r, void 0, "signature"), { v: o, l: i } = t.decode(48, n);
|
|
3521
3529
|
if (i.length)
|
|
3522
3530
|
throw new e("invalid signature: left bytes after parsing");
|
|
3523
|
-
const { v: a, l: c } = t.decode(2, o), { v: l, l:
|
|
3524
|
-
if (
|
|
3531
|
+
const { v: a, l: c } = t.decode(2, o), { v: l, l: u } = t.decode(2, c);
|
|
3532
|
+
if (u.length)
|
|
3525
3533
|
throw new e("invalid signature: left bytes after parsing");
|
|
3526
3534
|
return { r: s.decode(a), s: s.decode(l) };
|
|
3527
3535
|
},
|
|
@@ -3546,23 +3554,23 @@ function jr(r, e = {}) {
|
|
|
3546
3554
|
if (c && (!t.is0(o.a) || typeof c.beta != "bigint" || !Array.isArray(c.basises)))
|
|
3547
3555
|
throw new Error('invalid endo: expected "beta": bigint and "basises": array');
|
|
3548
3556
|
const l = As(t, n);
|
|
3549
|
-
function
|
|
3557
|
+
function u() {
|
|
3550
3558
|
if (!t.isOdd)
|
|
3551
3559
|
throw new Error("compression is not supported: Field does not have .isOdd()");
|
|
3552
3560
|
}
|
|
3553
|
-
function h(A,
|
|
3554
|
-
const { x: b, y: E } =
|
|
3555
|
-
if (qe(
|
|
3556
|
-
|
|
3561
|
+
function h(A, _, x) {
|
|
3562
|
+
const { x: b, y: E } = _.toAffine(), M = t.toBytes(b);
|
|
3563
|
+
if (qe(x, "isCompressed"), x) {
|
|
3564
|
+
u();
|
|
3557
3565
|
const O = !t.isOdd(E);
|
|
3558
3566
|
return ve(Is(O), M);
|
|
3559
3567
|
} else
|
|
3560
3568
|
return ve(Uint8Array.of(4), M, t.toBytes(E));
|
|
3561
3569
|
}
|
|
3562
|
-
function
|
|
3570
|
+
function g(A) {
|
|
3563
3571
|
z(A, void 0, "Point");
|
|
3564
|
-
const { publicKey:
|
|
3565
|
-
if (b ===
|
|
3572
|
+
const { publicKey: _, publicKeyUncompressed: x } = l, b = A.length, E = A[0], M = A.subarray(1);
|
|
3573
|
+
if (b === _ && (E === 2 || E === 3)) {
|
|
3566
3574
|
const O = t.fromBytes(M);
|
|
3567
3575
|
if (!t.isValid(O))
|
|
3568
3576
|
throw new Error("bad point: is not on curve, wrong x");
|
|
@@ -3574,35 +3582,35 @@ function jr(r, e = {}) {
|
|
|
3574
3582
|
const K = J instanceof Error ? ": " + J.message : "";
|
|
3575
3583
|
throw new Error("bad point: is not on curve, sqrt error" + K);
|
|
3576
3584
|
}
|
|
3577
|
-
|
|
3585
|
+
u();
|
|
3578
3586
|
const B = t.isOdd(T);
|
|
3579
3587
|
return (E & 1) === 1 !== B && (T = t.neg(T)), { x: O, y: T };
|
|
3580
|
-
} else if (b ===
|
|
3588
|
+
} else if (b === x && E === 4) {
|
|
3581
3589
|
const O = t.BYTES, $ = t.fromBytes(M.subarray(0, O)), T = t.fromBytes(M.subarray(O, O * 2));
|
|
3582
3590
|
if (!y($, T))
|
|
3583
3591
|
throw new Error("bad point: is not on curve");
|
|
3584
3592
|
return { x: $, y: T };
|
|
3585
3593
|
} else
|
|
3586
|
-
throw new Error(`bad point: got length ${b}, expected compressed=${
|
|
3594
|
+
throw new Error(`bad point: got length ${b}, expected compressed=${_} or uncompressed=${x}`);
|
|
3587
3595
|
}
|
|
3588
|
-
const
|
|
3596
|
+
const f = e.toBytes || h, w = e.fromBytes || g;
|
|
3589
3597
|
function v(A) {
|
|
3590
|
-
const
|
|
3591
|
-
return t.add(t.add(
|
|
3598
|
+
const _ = t.sqr(A), x = t.mul(_, A);
|
|
3599
|
+
return t.add(t.add(x, t.mul(A, o.a)), o.b);
|
|
3592
3600
|
}
|
|
3593
|
-
function y(A,
|
|
3594
|
-
const
|
|
3595
|
-
return t.eql(
|
|
3601
|
+
function y(A, _) {
|
|
3602
|
+
const x = t.sqr(_), b = v(A);
|
|
3603
|
+
return t.eql(x, b);
|
|
3596
3604
|
}
|
|
3597
3605
|
if (!y(o.Gx, o.Gy))
|
|
3598
3606
|
throw new Error("bad curve params: generator point");
|
|
3599
3607
|
const S = t.mul(t.pow(o.a, He), zr), C = t.mul(t.sqr(o.b), BigInt(27));
|
|
3600
3608
|
if (t.is0(t.add(S, C)))
|
|
3601
3609
|
throw new Error("bad curve params: a or b");
|
|
3602
|
-
function U(A,
|
|
3603
|
-
if (!t.isValid(
|
|
3610
|
+
function U(A, _, x = !1) {
|
|
3611
|
+
if (!t.isValid(_) || x && t.is0(_))
|
|
3604
3612
|
throw new Error(`bad point coordinate ${A}`);
|
|
3605
|
-
return
|
|
3613
|
+
return _;
|
|
3606
3614
|
}
|
|
3607
3615
|
function N(A) {
|
|
3608
3616
|
if (!(A instanceof D))
|
|
@@ -3613,13 +3621,13 @@ function jr(r, e = {}) {
|
|
|
3613
3621
|
throw new Error("no endo");
|
|
3614
3622
|
return Kr(A, c.basises, n.ORDER);
|
|
3615
3623
|
}
|
|
3616
|
-
const W = Mt((A,
|
|
3617
|
-
const { X:
|
|
3624
|
+
const W = Mt((A, _) => {
|
|
3625
|
+
const { X: x, Y: b, Z: E } = A;
|
|
3618
3626
|
if (t.eql(E, t.ONE))
|
|
3619
|
-
return { x
|
|
3627
|
+
return { x, y: b };
|
|
3620
3628
|
const M = A.is0();
|
|
3621
|
-
|
|
3622
|
-
const O = t.mul(
|
|
3629
|
+
_ == null && (_ = M ? t.ONE : t.inv(E));
|
|
3630
|
+
const O = t.mul(x, _), $ = t.mul(b, _), T = t.mul(E, _);
|
|
3623
3631
|
if (M)
|
|
3624
3632
|
return { x: t.ZERO, y: t.ZERO };
|
|
3625
3633
|
if (!t.eql(T, t.ONE))
|
|
@@ -3631,44 +3639,44 @@ function jr(r, e = {}) {
|
|
|
3631
3639
|
return;
|
|
3632
3640
|
throw new Error("bad point: ZERO");
|
|
3633
3641
|
}
|
|
3634
|
-
const { x:
|
|
3635
|
-
if (!t.isValid(
|
|
3642
|
+
const { x: _, y: x } = A.toAffine();
|
|
3643
|
+
if (!t.isValid(_) || !t.isValid(x))
|
|
3636
3644
|
throw new Error("bad point: x or y not field elements");
|
|
3637
|
-
if (!y(
|
|
3645
|
+
if (!y(_, x))
|
|
3638
3646
|
throw new Error("bad point: equation left != right");
|
|
3639
3647
|
if (!A.isTorsionFree())
|
|
3640
3648
|
throw new Error("bad point: not in prime-order subgroup");
|
|
3641
3649
|
return !0;
|
|
3642
3650
|
});
|
|
3643
|
-
function k(A,
|
|
3644
|
-
return
|
|
3651
|
+
function k(A, _, x, b, E) {
|
|
3652
|
+
return x = new D(t.mul(x.X, A), x.Y, x.Z), _ = Ke(b, _), x = Ke(E, x), _.add(x);
|
|
3645
3653
|
}
|
|
3646
3654
|
const R = class R {
|
|
3647
3655
|
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
3648
|
-
constructor(
|
|
3656
|
+
constructor(_, x, b) {
|
|
3649
3657
|
I(this, "X");
|
|
3650
3658
|
I(this, "Y");
|
|
3651
3659
|
I(this, "Z");
|
|
3652
|
-
this.X = U("x",
|
|
3660
|
+
this.X = U("x", _), this.Y = U("y", x, !0), this.Z = U("z", b), Object.freeze(this);
|
|
3653
3661
|
}
|
|
3654
3662
|
static CURVE() {
|
|
3655
3663
|
return o;
|
|
3656
3664
|
}
|
|
3657
3665
|
/** Does NOT validate if the point is valid. Use `.assertValidity()`. */
|
|
3658
|
-
static fromAffine(
|
|
3659
|
-
const { x
|
|
3660
|
-
if (!
|
|
3666
|
+
static fromAffine(_) {
|
|
3667
|
+
const { x, y: b } = _ || {};
|
|
3668
|
+
if (!_ || !t.isValid(x) || !t.isValid(b))
|
|
3661
3669
|
throw new Error("invalid affine point");
|
|
3662
|
-
if (
|
|
3670
|
+
if (_ instanceof R)
|
|
3663
3671
|
throw new Error("projective point not allowed");
|
|
3664
|
-
return t.is0(
|
|
3672
|
+
return t.is0(x) && t.is0(b) ? R.ZERO : new R(x, b, t.ONE);
|
|
3665
3673
|
}
|
|
3666
|
-
static fromBytes(
|
|
3667
|
-
const
|
|
3668
|
-
return
|
|
3674
|
+
static fromBytes(_) {
|
|
3675
|
+
const x = R.fromAffine(w(z(_, void 0, "point")));
|
|
3676
|
+
return x.assertValidity(), x;
|
|
3669
3677
|
}
|
|
3670
|
-
static fromHex(
|
|
3671
|
-
return R.fromBytes(We(
|
|
3678
|
+
static fromHex(_) {
|
|
3679
|
+
return R.fromBytes(We(_));
|
|
3672
3680
|
}
|
|
3673
3681
|
get x() {
|
|
3674
3682
|
return this.toAffine().x;
|
|
@@ -3682,8 +3690,8 @@ function jr(r, e = {}) {
|
|
|
3682
3690
|
* @param isLazy true will defer table computation until the first multiplication
|
|
3683
3691
|
* @returns
|
|
3684
3692
|
*/
|
|
3685
|
-
precompute(
|
|
3686
|
-
return L.createCache(this,
|
|
3693
|
+
precompute(_ = 8, x = !0) {
|
|
3694
|
+
return L.createCache(this, _), x || this.multiply(He), this;
|
|
3687
3695
|
}
|
|
3688
3696
|
// TODO: return `this`
|
|
3689
3697
|
/** A point on curve is valid if it conforms to equation. */
|
|
@@ -3691,15 +3699,15 @@ function jr(r, e = {}) {
|
|
|
3691
3699
|
P(this);
|
|
3692
3700
|
}
|
|
3693
3701
|
hasEvenY() {
|
|
3694
|
-
const { y:
|
|
3702
|
+
const { y: _ } = this.toAffine();
|
|
3695
3703
|
if (!t.isOdd)
|
|
3696
3704
|
throw new Error("Field doesn't support isOdd");
|
|
3697
|
-
return !t.isOdd(
|
|
3705
|
+
return !t.isOdd(_);
|
|
3698
3706
|
}
|
|
3699
3707
|
/** Compare one point to another. */
|
|
3700
|
-
equals(
|
|
3701
|
-
N(
|
|
3702
|
-
const { X:
|
|
3708
|
+
equals(_) {
|
|
3709
|
+
N(_);
|
|
3710
|
+
const { X: x, Y: b, Z: E } = this, { X: M, Y: O, Z: $ } = _, T = t.eql(t.mul(x, $), t.mul(M, E)), B = t.eql(t.mul(b, $), t.mul(O, E));
|
|
3703
3711
|
return T && B;
|
|
3704
3712
|
}
|
|
3705
3713
|
/** Flips point to one corresponding to (x, -y) in Affine coordinates. */
|
|
@@ -3711,26 +3719,26 @@ function jr(r, e = {}) {
|
|
|
3711
3719
|
// https://eprint.iacr.org/2015/1060, algorithm 3
|
|
3712
3720
|
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
|
|
3713
3721
|
double() {
|
|
3714
|
-
const { a:
|
|
3722
|
+
const { a: _, b: x } = o, b = t.mul(x, He), { X: E, Y: M, Z: O } = this;
|
|
3715
3723
|
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
|
-
return F = t.add(F, F), B = t.mul(E, O), B = t.add(B, B), $ = t.mul(
|
|
3724
|
+
return F = t.add(F, F), B = t.mul(E, O), B = t.add(B, B), $ = t.mul(_, 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(_, K), F = t.sub(G, K), F = t.mul(_, 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
3725
|
}
|
|
3718
3726
|
// Renes-Costello-Batina exception-free addition formula.
|
|
3719
3727
|
// There is 30% faster Jacobian formula, but it is not complete.
|
|
3720
3728
|
// https://eprint.iacr.org/2015/1060, algorithm 1
|
|
3721
3729
|
// Cost: 12M + 0S + 3*a + 3*b3 + 23add.
|
|
3722
|
-
add(
|
|
3723
|
-
N(
|
|
3724
|
-
const { X:
|
|
3730
|
+
add(_) {
|
|
3731
|
+
N(_);
|
|
3732
|
+
const { X: x, Y: b, Z: E } = this, { X: M, Y: O, Z: $ } = _;
|
|
3725
3733
|
let T = t.ZERO, B = t.ZERO, G = t.ZERO;
|
|
3726
3734
|
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(
|
|
3735
|
+
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);
|
|
3736
|
+
oe = t.mul(oe, j), j = t.add(F, X), oe = t.sub(oe, j), j = t.add(x, E);
|
|
3729
3737
|
let Q = t.add(M, $);
|
|
3730
3738
|
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
3739
|
}
|
|
3732
|
-
subtract(
|
|
3733
|
-
return this.add(
|
|
3740
|
+
subtract(_) {
|
|
3741
|
+
return this.add(_.negate());
|
|
3734
3742
|
}
|
|
3735
3743
|
is0() {
|
|
3736
3744
|
return this.equals(R.ZERO);
|
|
@@ -3744,17 +3752,17 @@ function jr(r, e = {}) {
|
|
|
3744
3752
|
* @param scalar by which the point would be multiplied
|
|
3745
3753
|
* @returns New point
|
|
3746
3754
|
*/
|
|
3747
|
-
multiply(
|
|
3748
|
-
const { endo:
|
|
3749
|
-
if (!n.isValidNot0(
|
|
3755
|
+
multiply(_) {
|
|
3756
|
+
const { endo: x } = e;
|
|
3757
|
+
if (!n.isValidNot0(_))
|
|
3750
3758
|
throw new Error("invalid scalar: out of range");
|
|
3751
3759
|
let b, E;
|
|
3752
3760
|
const M = (O) => L.cached(this, O, ($) => Ut(R, $));
|
|
3753
|
-
if (
|
|
3754
|
-
const { k1neg: O, k1: $, k2neg: T, k2: B } = V(
|
|
3755
|
-
E = J.add(F), b = k(
|
|
3761
|
+
if (x) {
|
|
3762
|
+
const { k1neg: O, k1: $, k2neg: T, k2: B } = V(_), { p: G, f: J } = M($), { p: K, f: F } = M(B);
|
|
3763
|
+
E = J.add(F), b = k(x.beta, G, K, O, T);
|
|
3756
3764
|
} else {
|
|
3757
|
-
const { p: O, f: $ } = M(
|
|
3765
|
+
const { p: O, f: $ } = M(_);
|
|
3758
3766
|
b = O, E = $;
|
|
3759
3767
|
}
|
|
3760
3768
|
return Ut(R, [b, E])[0];
|
|
@@ -3764,49 +3772,49 @@ function jr(r, e = {}) {
|
|
|
3764
3772
|
* It's faster, but should only be used when you don't care about
|
|
3765
3773
|
* an exposed secret key e.g. sig verification, which works over *public* keys.
|
|
3766
3774
|
*/
|
|
3767
|
-
multiplyUnsafe(
|
|
3768
|
-
const { endo:
|
|
3769
|
-
if (!n.isValid(
|
|
3775
|
+
multiplyUnsafe(_) {
|
|
3776
|
+
const { endo: x } = e, b = this;
|
|
3777
|
+
if (!n.isValid(_))
|
|
3770
3778
|
throw new Error("invalid scalar: out of range");
|
|
3771
|
-
if (
|
|
3779
|
+
if (_ === _e || b.is0())
|
|
3772
3780
|
return R.ZERO;
|
|
3773
|
-
if (
|
|
3781
|
+
if (_ === Re)
|
|
3774
3782
|
return b;
|
|
3775
3783
|
if (L.hasCache(this))
|
|
3776
|
-
return this.multiply(
|
|
3777
|
-
if (
|
|
3778
|
-
const { k1neg: E, k1: M, k2neg: O, k2: $ } = V(
|
|
3779
|
-
return k(
|
|
3784
|
+
return this.multiply(_);
|
|
3785
|
+
if (x) {
|
|
3786
|
+
const { k1neg: E, k1: M, k2neg: O, k2: $ } = V(_), { p1: T, p2: B } = Gr(R, b, M, $);
|
|
3787
|
+
return k(x.beta, T, B, E, O);
|
|
3780
3788
|
} else
|
|
3781
|
-
return L.unsafe(b,
|
|
3789
|
+
return L.unsafe(b, _);
|
|
3782
3790
|
}
|
|
3783
3791
|
/**
|
|
3784
3792
|
* Converts Projective point to affine (x, y) coordinates.
|
|
3785
3793
|
* @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch
|
|
3786
3794
|
*/
|
|
3787
|
-
toAffine(
|
|
3788
|
-
return W(this,
|
|
3795
|
+
toAffine(_) {
|
|
3796
|
+
return W(this, _);
|
|
3789
3797
|
}
|
|
3790
3798
|
/**
|
|
3791
3799
|
* Checks whether Point is free of torsion elements (is in prime subgroup).
|
|
3792
3800
|
* Always torsion-free for cofactor=1 curves.
|
|
3793
3801
|
*/
|
|
3794
3802
|
isTorsionFree() {
|
|
3795
|
-
const { isTorsionFree:
|
|
3796
|
-
return i === Re ? !0 :
|
|
3803
|
+
const { isTorsionFree: _ } = e;
|
|
3804
|
+
return i === Re ? !0 : _ ? _(R, this) : L.unsafe(this, a).is0();
|
|
3797
3805
|
}
|
|
3798
3806
|
clearCofactor() {
|
|
3799
|
-
const { clearCofactor:
|
|
3800
|
-
return i === Re ? this :
|
|
3807
|
+
const { clearCofactor: _ } = e;
|
|
3808
|
+
return i === Re ? this : _ ? _(R, this) : this.multiplyUnsafe(i);
|
|
3801
3809
|
}
|
|
3802
3810
|
isSmallOrder() {
|
|
3803
3811
|
return this.multiplyUnsafe(i).is0();
|
|
3804
3812
|
}
|
|
3805
|
-
toBytes(
|
|
3806
|
-
return qe(
|
|
3813
|
+
toBytes(_ = !0) {
|
|
3814
|
+
return qe(_, "isCompressed"), this.assertValidity(), f(R, this, _);
|
|
3807
3815
|
}
|
|
3808
|
-
toHex(
|
|
3809
|
-
return Me(this.toBytes(
|
|
3816
|
+
toHex(_ = !0) {
|
|
3817
|
+
return Me(this.toBytes(_));
|
|
3810
3818
|
}
|
|
3811
3819
|
toString() {
|
|
3812
3820
|
return `<Point ${this.is0() ? "ZERO" : this.toHex()}>`;
|
|
@@ -3836,50 +3844,50 @@ function As(r, e) {
|
|
|
3836
3844
|
}
|
|
3837
3845
|
function Yr(r, e = {}) {
|
|
3838
3846
|
const { Fn: s } = r, t = e.randomBytes || os, n = Object.assign(As(r.Fp, s), { seed: ws(s.ORDER) });
|
|
3839
|
-
function o(
|
|
3847
|
+
function o(f) {
|
|
3840
3848
|
try {
|
|
3841
|
-
const w = s.fromBytes(
|
|
3849
|
+
const w = s.fromBytes(f);
|
|
3842
3850
|
return s.isValidNot0(w);
|
|
3843
3851
|
} catch {
|
|
3844
3852
|
return !1;
|
|
3845
3853
|
}
|
|
3846
3854
|
}
|
|
3847
|
-
function i(
|
|
3855
|
+
function i(f, w) {
|
|
3848
3856
|
const { publicKey: v, publicKeyUncompressed: y } = n;
|
|
3849
3857
|
try {
|
|
3850
|
-
const S =
|
|
3851
|
-
return w === !0 && S !== v || w === !1 && S !== y ? !1 : !!r.fromBytes(
|
|
3858
|
+
const S = f.length;
|
|
3859
|
+
return w === !0 && S !== v || w === !1 && S !== y ? !1 : !!r.fromBytes(f);
|
|
3852
3860
|
} catch {
|
|
3853
3861
|
return !1;
|
|
3854
3862
|
}
|
|
3855
3863
|
}
|
|
3856
|
-
function a(
|
|
3857
|
-
return Hr(z(
|
|
3864
|
+
function a(f = t(n.seed)) {
|
|
3865
|
+
return Hr(z(f, n.seed, "seed"), s.ORDER);
|
|
3858
3866
|
}
|
|
3859
|
-
function c(
|
|
3860
|
-
return r.BASE.multiply(s.fromBytes(
|
|
3867
|
+
function c(f, w = !0) {
|
|
3868
|
+
return r.BASE.multiply(s.fromBytes(f)).toBytes(w);
|
|
3861
3869
|
}
|
|
3862
|
-
function l(
|
|
3870
|
+
function l(f) {
|
|
3863
3871
|
const { secretKey: w, publicKey: v, publicKeyUncompressed: y } = n;
|
|
3864
|
-
if (!ut(
|
|
3872
|
+
if (!ut(f) || "_lengths" in s && s._lengths || w === v)
|
|
3865
3873
|
return;
|
|
3866
|
-
const S = z(
|
|
3874
|
+
const S = z(f, void 0, "key").length;
|
|
3867
3875
|
return S === v || S === y;
|
|
3868
3876
|
}
|
|
3869
|
-
function
|
|
3870
|
-
if (l(
|
|
3877
|
+
function u(f, w, v = !0) {
|
|
3878
|
+
if (l(f) === !0)
|
|
3871
3879
|
throw new Error("first arg must be private key");
|
|
3872
3880
|
if (l(w) === !1)
|
|
3873
3881
|
throw new Error("second arg must be public key");
|
|
3874
|
-
const y = s.fromBytes(
|
|
3882
|
+
const y = s.fromBytes(f);
|
|
3875
3883
|
return r.fromBytes(w).multiply(y).toBytes(v);
|
|
3876
3884
|
}
|
|
3877
3885
|
const h = {
|
|
3878
3886
|
isValidSecretKey: o,
|
|
3879
3887
|
isValidPublicKey: i,
|
|
3880
3888
|
randomSecretKey: a
|
|
3881
|
-
},
|
|
3882
|
-
return Object.freeze({ getPublicKey: c, getSharedSecret:
|
|
3889
|
+
}, g = qr(a, c);
|
|
3890
|
+
return Object.freeze({ getPublicKey: c, getSharedSecret: u, keygen: g, Point: r, utils: h, lengths: n });
|
|
3883
3891
|
}
|
|
3884
3892
|
function Jr(r, e, s = {}) {
|
|
3885
3893
|
ts(e), _t(s, {}, {
|
|
@@ -3889,70 +3897,70 @@ function Jr(r, e, s = {}) {
|
|
|
3889
3897
|
bits2int: "function",
|
|
3890
3898
|
bits2int_modN: "function"
|
|
3891
3899
|
}), s = Object.assign({}, s);
|
|
3892
|
-
const t = s.randomBytes || os, n = s.hmac || ((
|
|
3900
|
+
const t = s.randomBytes || os, n = s.hmac || ((_, x) => Ss(e, _, x)), { Fp: o, Fn: i } = r, { ORDER: a, BITS: c } = i, { keygen: l, getPublicKey: u, getSharedSecret: h, utils: g, lengths: f } = Yr(r, s), w = {
|
|
3893
3901
|
prehash: !0,
|
|
3894
3902
|
lowS: typeof s.lowS == "boolean" ? s.lowS : !0,
|
|
3895
3903
|
format: "compact",
|
|
3896
3904
|
extraEntropy: !1
|
|
3897
3905
|
}, v = a * Es < o.ORDER;
|
|
3898
|
-
function y(
|
|
3899
|
-
const
|
|
3900
|
-
return
|
|
3906
|
+
function y(_) {
|
|
3907
|
+
const x = a >> Re;
|
|
3908
|
+
return _ > x;
|
|
3901
3909
|
}
|
|
3902
|
-
function S(
|
|
3903
|
-
if (!i.isValidNot0(
|
|
3904
|
-
throw new Error(`invalid signature ${
|
|
3905
|
-
return
|
|
3910
|
+
function S(_, x) {
|
|
3911
|
+
if (!i.isValidNot0(x))
|
|
3912
|
+
throw new Error(`invalid signature ${_}: out of range 1..Point.Fn.ORDER`);
|
|
3913
|
+
return x;
|
|
3906
3914
|
}
|
|
3907
3915
|
function C() {
|
|
3908
3916
|
if (v)
|
|
3909
3917
|
throw new Error('"recovered" sig type is not supported for cofactor >2 curves');
|
|
3910
3918
|
}
|
|
3911
|
-
function U(
|
|
3912
|
-
ct(
|
|
3913
|
-
const b =
|
|
3914
|
-
return z(
|
|
3919
|
+
function U(_, x) {
|
|
3920
|
+
ct(x);
|
|
3921
|
+
const b = f.signature, E = x === "compact" ? b : x === "recovered" ? b + 1 : void 0;
|
|
3922
|
+
return z(_, E);
|
|
3915
3923
|
}
|
|
3916
3924
|
class N {
|
|
3917
|
-
constructor(
|
|
3925
|
+
constructor(x, b, E) {
|
|
3918
3926
|
I(this, "r");
|
|
3919
3927
|
I(this, "s");
|
|
3920
3928
|
I(this, "recovery");
|
|
3921
|
-
if (this.r = S("r",
|
|
3929
|
+
if (this.r = S("r", x), this.s = S("s", b), E != null) {
|
|
3922
3930
|
if (C(), ![0, 1, 2, 3].includes(E))
|
|
3923
3931
|
throw new Error("invalid recovery id");
|
|
3924
3932
|
this.recovery = E;
|
|
3925
3933
|
}
|
|
3926
3934
|
Object.freeze(this);
|
|
3927
3935
|
}
|
|
3928
|
-
static fromBytes(
|
|
3929
|
-
U(
|
|
3936
|
+
static fromBytes(x, b = w.format) {
|
|
3937
|
+
U(x, b);
|
|
3930
3938
|
let E;
|
|
3931
3939
|
if (b === "der") {
|
|
3932
|
-
const { r: T, s: B } = ye.toSig(z(
|
|
3940
|
+
const { r: T, s: B } = ye.toSig(z(x));
|
|
3933
3941
|
return new N(T, B);
|
|
3934
3942
|
}
|
|
3935
|
-
b === "recovered" && (E =
|
|
3936
|
-
const M =
|
|
3943
|
+
b === "recovered" && (E = x[0], b = "compact", x = x.subarray(1));
|
|
3944
|
+
const M = f.signature / 2, O = x.subarray(0, M), $ = x.subarray(M, M * 2);
|
|
3937
3945
|
return new N(i.fromBytes(O), i.fromBytes($), E);
|
|
3938
3946
|
}
|
|
3939
|
-
static fromHex(
|
|
3940
|
-
return this.fromBytes(We(
|
|
3947
|
+
static fromHex(x, b) {
|
|
3948
|
+
return this.fromBytes(We(x), b);
|
|
3941
3949
|
}
|
|
3942
3950
|
assertRecovery() {
|
|
3943
|
-
const { recovery:
|
|
3944
|
-
if (
|
|
3951
|
+
const { recovery: x } = this;
|
|
3952
|
+
if (x == null)
|
|
3945
3953
|
throw new Error("invalid recovery id: must be present");
|
|
3946
|
-
return
|
|
3954
|
+
return x;
|
|
3947
3955
|
}
|
|
3948
|
-
addRecoveryBit(
|
|
3949
|
-
return new N(this.r, this.s,
|
|
3956
|
+
addRecoveryBit(x) {
|
|
3957
|
+
return new N(this.r, this.s, x);
|
|
3950
3958
|
}
|
|
3951
|
-
recoverPublicKey(
|
|
3959
|
+
recoverPublicKey(x) {
|
|
3952
3960
|
const { r: b, s: E } = this, M = this.assertRecovery(), O = M === 2 || M === 3 ? b + a : b;
|
|
3953
3961
|
if (!o.isValid(O))
|
|
3954
3962
|
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(
|
|
3963
|
+
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
3964
|
if (F.is0())
|
|
3957
3965
|
throw new Error("invalid recovery: point at infinify");
|
|
3958
3966
|
return F.assertValidity(), F;
|
|
@@ -3961,39 +3969,39 @@ function Jr(r, e, s = {}) {
|
|
|
3961
3969
|
hasHighS() {
|
|
3962
3970
|
return y(this.s);
|
|
3963
3971
|
}
|
|
3964
|
-
toBytes(
|
|
3965
|
-
if (ct(
|
|
3972
|
+
toBytes(x = w.format) {
|
|
3973
|
+
if (ct(x), x === "der")
|
|
3966
3974
|
return We(ye.hexFromSig(this));
|
|
3967
3975
|
const { r: b, s: E } = this, M = i.toBytes(b), O = i.toBytes(E);
|
|
3968
|
-
return
|
|
3976
|
+
return x === "recovered" ? (C(), ve(Uint8Array.of(this.assertRecovery()), M, O)) : ve(M, O);
|
|
3969
3977
|
}
|
|
3970
|
-
toHex(
|
|
3971
|
-
return Me(this.toBytes(
|
|
3978
|
+
toHex(x) {
|
|
3979
|
+
return Me(this.toBytes(x));
|
|
3972
3980
|
}
|
|
3973
3981
|
}
|
|
3974
|
-
const V = s.bits2int || function(
|
|
3975
|
-
if (
|
|
3982
|
+
const V = s.bits2int || function(x) {
|
|
3983
|
+
if (x.length > 8192)
|
|
3976
3984
|
throw new Error("input is too large");
|
|
3977
|
-
const b = ze(
|
|
3985
|
+
const b = ze(x), E = x.length * 8 - c;
|
|
3978
3986
|
return E > 0 ? b >> BigInt(E) : b;
|
|
3979
|
-
}, W = s.bits2int_modN || function(
|
|
3980
|
-
return i.create(V(
|
|
3987
|
+
}, W = s.bits2int_modN || function(x) {
|
|
3988
|
+
return i.create(V(x));
|
|
3981
3989
|
}, P = ft(c);
|
|
3982
|
-
function k(
|
|
3983
|
-
return Tr("num < 2^" + c,
|
|
3990
|
+
function k(_) {
|
|
3991
|
+
return Tr("num < 2^" + c, _, _e, P), i.toBytes(_);
|
|
3984
3992
|
}
|
|
3985
|
-
function D(
|
|
3986
|
-
return z(
|
|
3993
|
+
function D(_, x) {
|
|
3994
|
+
return z(_, void 0, "message"), x ? z(e(_), void 0, "prehashed message") : _;
|
|
3987
3995
|
}
|
|
3988
|
-
function q(
|
|
3996
|
+
function q(_, x, b) {
|
|
3989
3997
|
const { lowS: E, prehash: M, extraEntropy: O } = st(b, w);
|
|
3990
|
-
|
|
3991
|
-
const $ = W(
|
|
3998
|
+
_ = D(_, M);
|
|
3999
|
+
const $ = W(_), T = i.fromBytes(x);
|
|
3992
4000
|
if (!i.isValidNot0(T))
|
|
3993
4001
|
throw new Error("invalid private key");
|
|
3994
4002
|
const B = [k(T), k($)];
|
|
3995
4003
|
if (O != null && O !== !1) {
|
|
3996
|
-
const F = O === !0 ? t(
|
|
4004
|
+
const F = O === !0 ? t(f.secretKey) : O;
|
|
3997
4005
|
B.push(z(F, void 0, "extraEntropy"));
|
|
3998
4006
|
}
|
|
3999
4007
|
const G = ve(...B), J = $;
|
|
@@ -4012,37 +4020,37 @@ function Jr(r, e, s = {}) {
|
|
|
4012
4020
|
}
|
|
4013
4021
|
return { seed: G, k2sig: K };
|
|
4014
4022
|
}
|
|
4015
|
-
function L(
|
|
4016
|
-
const { seed: E, k2sig: M } = q(
|
|
4023
|
+
function L(_, x, b = {}) {
|
|
4024
|
+
const { seed: E, k2sig: M } = q(_, x, b);
|
|
4017
4025
|
return kr(e.outputLen, i.BYTES, n)(E, M).toBytes(b.format);
|
|
4018
4026
|
}
|
|
4019
|
-
function R(
|
|
4027
|
+
function R(_, x, b, E = {}) {
|
|
4020
4028
|
const { lowS: M, prehash: O, format: $ } = st(E, w);
|
|
4021
|
-
if (b = z(b, void 0, "publicKey"),
|
|
4022
|
-
const T =
|
|
4029
|
+
if (b = z(b, void 0, "publicKey"), x = D(x, O), !ut(_)) {
|
|
4030
|
+
const T = _ instanceof N ? ", use sig.toBytes()" : "";
|
|
4023
4031
|
throw new Error("verify expects Uint8Array signature" + T);
|
|
4024
4032
|
}
|
|
4025
|
-
U(
|
|
4033
|
+
U(_, $);
|
|
4026
4034
|
try {
|
|
4027
|
-
const T = N.fromBytes(
|
|
4035
|
+
const T = N.fromBytes(_, $), B = r.fromBytes(b);
|
|
4028
4036
|
if (M && T.hasHighS())
|
|
4029
4037
|
return !1;
|
|
4030
|
-
const { r: G, s: J } = T, K = W(
|
|
4038
|
+
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
4039
|
return oe.is0() ? !1 : i.create(oe.x) === G;
|
|
4032
4040
|
} catch {
|
|
4033
4041
|
return !1;
|
|
4034
4042
|
}
|
|
4035
4043
|
}
|
|
4036
|
-
function A(
|
|
4044
|
+
function A(_, x, b = {}) {
|
|
4037
4045
|
const { prehash: E } = st(b, w);
|
|
4038
|
-
return
|
|
4046
|
+
return x = D(x, E), N.fromBytes(_, "recovered").recoverPublicKey(x).toBytes();
|
|
4039
4047
|
}
|
|
4040
4048
|
return Object.freeze({
|
|
4041
4049
|
keygen: l,
|
|
4042
|
-
getPublicKey:
|
|
4050
|
+
getPublicKey: u,
|
|
4043
4051
|
getSharedSecret: h,
|
|
4044
|
-
utils:
|
|
4045
|
-
lengths:
|
|
4052
|
+
utils: g,
|
|
4053
|
+
lengths: f,
|
|
4046
4054
|
Point: r,
|
|
4047
4055
|
sign: L,
|
|
4048
4056
|
verify: R,
|
|
@@ -4068,7 +4076,7 @@ const gt = {
|
|
|
4068
4076
|
]
|
|
4069
4077
|
}, qt = /* @__PURE__ */ BigInt(2);
|
|
4070
4078
|
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,
|
|
4079
|
+
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, f = ae(g, qt, e) * l % e, w = ae(f, n, e) * f % 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
4080
|
if (!lt.eql(lt.sqr(W), r))
|
|
4073
4081
|
throw new Error("Cannot find square root");
|
|
4074
4082
|
return W;
|
|
@@ -4091,14 +4099,14 @@ function ln(r, e = 24) {
|
|
|
4091
4099
|
for (let i = 0; i < 10; i++)
|
|
4092
4100
|
s[i] = r[i] ^ r[i + 10] ^ r[i + 20] ^ r[i + 30] ^ r[i + 40];
|
|
4093
4101
|
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 +
|
|
4102
|
+
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];
|
|
4103
|
+
for (let f = 0; f < 50; f += 10)
|
|
4104
|
+
r[i + f] ^= h, r[i + f + 1] ^= g;
|
|
4097
4105
|
}
|
|
4098
4106
|
let n = r[2], o = r[3];
|
|
4099
4107
|
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[
|
|
4108
|
+
const a = Rs[i], c = Kt(n, o, a), l = Vt(n, o, a), u = Ts[i];
|
|
4109
|
+
n = r[u], o = r[u + 1], r[u] = c, r[u + 1] = l;
|
|
4102
4110
|
}
|
|
4103
4111
|
for (let i = 0; i < 50; i += 10) {
|
|
4104
4112
|
for (let a = 0; a < 10; a++)
|
|
@@ -4193,46 +4201,46 @@ class hn {
|
|
|
4193
4201
|
}
|
|
4194
4202
|
setJWKSEndpoint(e) {
|
|
4195
4203
|
try {
|
|
4196
|
-
this.jwks = Ms(new URL(e)),
|
|
4204
|
+
this.jwks = Ms(new URL(e)), d.log("[CROSSx] JWKS 엔드포인트 설정:", e);
|
|
4197
4205
|
} catch (s) {
|
|
4198
|
-
|
|
4206
|
+
d.warn("[CROSSx] JWKS 엔드포인트 URL 파싱 실패:", s);
|
|
4199
4207
|
}
|
|
4200
4208
|
}
|
|
4201
4209
|
async verifyJWT(e, s) {
|
|
4202
4210
|
try {
|
|
4203
4211
|
const t = this.decodeJWT(e);
|
|
4204
|
-
|
|
4212
|
+
d.log("[CROSSx] JWT 디코딩 성공:", {
|
|
4205
4213
|
sub: t.sub,
|
|
4206
4214
|
exp: t.exp,
|
|
4207
4215
|
iat: t.iat
|
|
4208
4216
|
});
|
|
4209
4217
|
const n = Math.floor(Date.now() / 1e3);
|
|
4210
4218
|
if (t.exp && t.exp + un < n)
|
|
4211
|
-
return
|
|
4219
|
+
return d.warn("[CROSSx] 토큰 만료:", {
|
|
4212
4220
|
exp: t.exp,
|
|
4213
4221
|
now: n,
|
|
4214
4222
|
만료시간: new Date(t.exp * 1e3).toISOString()
|
|
4215
4223
|
}), { payload: t, valid: !1, signatureVerified: !1 };
|
|
4216
4224
|
if (!t.sub)
|
|
4217
|
-
return
|
|
4225
|
+
return d.warn("[CROSSx] JWT에 sub(사용자ID) 없음"), { payload: t, valid: !1, signatureVerified: !1 };
|
|
4218
4226
|
if (this.jwks)
|
|
4219
4227
|
try {
|
|
4220
4228
|
const { payload: o } = await $s(e, this.jwks, {
|
|
4221
4229
|
algorithms: ["RS256", "ES256"]
|
|
4222
4230
|
});
|
|
4223
|
-
return
|
|
4231
|
+
return d.log("[CROSSx] JWT 서명 검증 성공"), {
|
|
4224
4232
|
payload: o,
|
|
4225
4233
|
valid: !0,
|
|
4226
4234
|
signatureVerified: !0
|
|
4227
4235
|
};
|
|
4228
4236
|
} catch (o) {
|
|
4229
4237
|
if (o instanceof Error && (o.name === "JWSSignatureVerificationFailed" || o.name === "JWTClaimValidationFailed"))
|
|
4230
|
-
return
|
|
4231
|
-
|
|
4238
|
+
return d.error("[CROSSx] JWT 서명 검증 실패:", o), { payload: t, valid: !1, signatureVerified: !1 };
|
|
4239
|
+
d.warn("[CROSSx] JWKS 엔드포인트 접근 불가 — 서명 미검증 모드로 전환");
|
|
4232
4240
|
}
|
|
4233
|
-
return
|
|
4241
|
+
return d.log("[CROSSx] JWT 검증 성공 (서명 미검증 — JWKS 미설정 또는 접근 불가)"), { payload: t, valid: !0, signatureVerified: !1 };
|
|
4234
4242
|
} catch (t) {
|
|
4235
|
-
throw
|
|
4243
|
+
throw d.error("[CROSSx] JWT 검증 중 에러:", t), t;
|
|
4236
4244
|
}
|
|
4237
4245
|
}
|
|
4238
4246
|
decodeJWT(e) {
|
|
@@ -4254,10 +4262,10 @@ ${t.length}`
|
|
|
4254
4262
|
const i = zt(o), a = s.startsWith("0x") ? s.slice(2) : s;
|
|
4255
4263
|
if (a.length !== 130)
|
|
4256
4264
|
throw new Error(`서명 길이가 유효하지 않습니다: 130 hex 문자 예상, 현재 ${a.length}`);
|
|
4257
|
-
const c = pn(a), l = c.slice(0, 32),
|
|
4265
|
+
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
4266
|
jt(l),
|
|
4259
|
-
jt(
|
|
4260
|
-
).addRecoveryBit(
|
|
4267
|
+
jt(u)
|
|
4268
|
+
).addRecoveryBit(g).recoverPublicKey(i).toBytes(!1).slice(1), y = zt(v);
|
|
4261
4269
|
return "0x" + Me(y.slice(12));
|
|
4262
4270
|
}
|
|
4263
4271
|
}
|
|
@@ -4349,21 +4357,21 @@ class be {
|
|
|
4349
4357
|
*/
|
|
4350
4358
|
static async verifyIdTokenNonce(e, s) {
|
|
4351
4359
|
const t = be.parseJwtPayload(e), n = t.nonce, o = typeof t.iss == "string" ? t.iss : "(unknown)";
|
|
4352
|
-
if (
|
|
4360
|
+
if (d.log("[CROSSx] nonce 검증 시작 —", {
|
|
4353
4361
|
iss: o,
|
|
4354
4362
|
nonceClaimType: typeof n,
|
|
4355
4363
|
nonceClaimPresent: typeof n == "string" && n !== "",
|
|
4356
4364
|
// Apple의 nonce_supported 플래그 확인 (false면 서버가 nonce를 전달하지 않은 것)
|
|
4357
4365
|
appleNonceSupported: t.nonce_supported ?? "(field absent)"
|
|
4358
4366
|
}), o.includes("securetoken.google.com")) {
|
|
4359
|
-
|
|
4367
|
+
d.log(
|
|
4360
4368
|
"[CROSSx] Firebase ID Token 감지 — nonce 검증 skip.",
|
|
4361
4369
|
"서버 측에서 Google/Apple nonce 검증이 완료된 것으로 간주합니다."
|
|
4362
4370
|
);
|
|
4363
4371
|
return;
|
|
4364
4372
|
}
|
|
4365
4373
|
if (typeof n != "string" || n === "")
|
|
4366
|
-
throw
|
|
4374
|
+
throw d.error("[CROSSx] nonce claim 누락 — JWT payload 전체 키 목록:", Object.keys(t)), d.error(
|
|
4367
4375
|
"[CROSSx] 원인 추정: OAuth 서버가 Google/Apple 인증 요청에 nonce 파라미터를 포함하지 않았을 수 있습니다.",
|
|
4368
4376
|
"서버 로그에서 /auth/google, /auth/apple 요청 URL에 nonce 쿼리가 있는지 확인하세요."
|
|
4369
4377
|
), new Error(
|
|
@@ -4371,43 +4379,43 @@ class be {
|
|
|
4371
4379
|
);
|
|
4372
4380
|
if (o.includes("appleid.apple.com")) {
|
|
4373
4381
|
const i = await be.sha256Hex(s);
|
|
4374
|
-
if (
|
|
4382
|
+
if (d.log("[CROSSx] Apple nonce 검증 —", {
|
|
4375
4383
|
expectedHashLength: i.length,
|
|
4376
4384
|
receivedHashLength: n.length,
|
|
4377
4385
|
match: n === i
|
|
4378
4386
|
}), n !== i)
|
|
4379
4387
|
throw new Error("ID Token nonce 불일치 — replay attack 가능성이 있습니다");
|
|
4380
|
-
} else if (
|
|
4388
|
+
} else if (d.log("[CROSSx] Google nonce 검증 —", {
|
|
4381
4389
|
expectedLength: s.length,
|
|
4382
4390
|
receivedLength: n.length,
|
|
4383
4391
|
match: n === s
|
|
4384
4392
|
}), n !== s)
|
|
4385
4393
|
throw new Error("ID Token nonce 불일치 — replay attack 가능성이 있습니다");
|
|
4386
|
-
|
|
4394
|
+
d.log("[CROSSx] nonce 검증 성공 —", { iss: o });
|
|
4387
4395
|
}
|
|
4388
4396
|
openAuth(e) {
|
|
4389
4397
|
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
|
-
|
|
4398
|
+
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}`;
|
|
4399
|
+
d.log("[CROSSx] OAuth 팝업 열기 — state, nonce 생성 완료:", {
|
|
4392
4400
|
stateLength: c.length,
|
|
4393
4401
|
nonceLength: l.length,
|
|
4394
4402
|
authUrlBase: e.authUrl
|
|
4395
4403
|
});
|
|
4396
|
-
const
|
|
4404
|
+
const g = window.open(
|
|
4397
4405
|
h,
|
|
4398
4406
|
"CROSSx OAuth",
|
|
4399
4407
|
`width=${n},height=${o},left=${i},top=${a}`
|
|
4400
4408
|
);
|
|
4401
|
-
if (!
|
|
4409
|
+
if (!g) {
|
|
4402
4410
|
t(new Error("팝업 창을 열 수 없습니다. 팝업 차단을 해제해 주세요."));
|
|
4403
4411
|
return;
|
|
4404
4412
|
}
|
|
4405
|
-
const
|
|
4406
|
-
|
|
4413
|
+
const f = setTimeout(() => {
|
|
4414
|
+
d.warn("[CROSSx] OAuth 타임아웃 (5분) — postMessage를 수신하지 못했습니다"), N(), t(new Error("Authentication timeout"));
|
|
4407
4415
|
}, 5 * 60 * 1e3), w = 10, v = 30;
|
|
4408
4416
|
let y = 0, S = null;
|
|
4409
4417
|
const C = () => {
|
|
4410
|
-
clearInterval(U),
|
|
4418
|
+
clearInterval(U), d.warn("[CROSSx] COOP 감지 — OAuth 서버 응답을 " + v + "초간 대기합니다"), S = setTimeout(() => {
|
|
4411
4419
|
N(), t(new Error(
|
|
4412
4420
|
"OAuth 서버로부터 응답을 받지 못했습니다. 브라우저 보안 정책(COOP)으로 인해 팝업 통신이 차단되었을 수 있습니다. 다시 시도해 주세요."
|
|
4413
4421
|
));
|
|
@@ -4415,44 +4423,44 @@ class be {
|
|
|
4415
4423
|
}, U = setInterval(() => {
|
|
4416
4424
|
y++;
|
|
4417
4425
|
try {
|
|
4418
|
-
|
|
4426
|
+
g.closed && (y <= w ? C() : (N(), t(new Error("로그인이 취소되었습니다"))));
|
|
4419
4427
|
} catch {
|
|
4420
4428
|
C();
|
|
4421
4429
|
}
|
|
4422
4430
|
}, 1e3), N = () => {
|
|
4423
|
-
clearTimeout(
|
|
4431
|
+
clearTimeout(f), clearInterval(U), S && clearTimeout(S), window.removeEventListener("message", V);
|
|
4424
4432
|
}, V = (W) => {
|
|
4425
4433
|
var k, D, q, L, R;
|
|
4426
4434
|
if (W.origin !== e.expectedOrigin) return;
|
|
4427
4435
|
if (!gn.has(W.origin)) {
|
|
4428
|
-
|
|
4436
|
+
d.error("[CROSSx] postMessage origin이 허용 목록에 없음:", W.origin), N(), t(new Error("Unauthorized OAuth origin"));
|
|
4429
4437
|
return;
|
|
4430
4438
|
}
|
|
4431
|
-
N(),
|
|
4439
|
+
N(), d.log("[CROSSx] OAuth postMessage 수신 — status:", W.data.status);
|
|
4432
4440
|
const P = W.data.state ?? ((k = W.data.data) == null ? void 0 : k.state);
|
|
4433
4441
|
if (!P || P !== c) {
|
|
4434
4442
|
t(new Error("OAuth state mismatch — possible CSRF attack"));
|
|
4435
4443
|
return;
|
|
4436
4444
|
}
|
|
4437
4445
|
if (W.data.status === "success") {
|
|
4438
|
-
const A = (D = W.data.data) == null ? void 0 : D.idToken,
|
|
4439
|
-
if (
|
|
4440
|
-
hasAccessToken: !!
|
|
4446
|
+
const A = (D = W.data.data) == null ? void 0 : D.idToken, _ = (q = W.data.data) == null ? void 0 : q.accessToken, x = _ ?? A;
|
|
4447
|
+
if (d.log("[CROSSx] OAuth 토큰 수신:", {
|
|
4448
|
+
hasAccessToken: !!_,
|
|
4441
4449
|
hasIdToken: !!A
|
|
4442
|
-
}), !
|
|
4443
|
-
|
|
4450
|
+
}), !x) {
|
|
4451
|
+
d.error("[CROSSx] 토큰을 찾을 수 없음:", W.data), t(new Error("Token not found in response"));
|
|
4444
4452
|
return;
|
|
4445
4453
|
}
|
|
4446
|
-
A ? be.verifyIdTokenNonce(A, l).then(() => s(
|
|
4447
|
-
|
|
4448
|
-
}) :
|
|
4449
|
-
|
|
4450
|
-
}) : (
|
|
4454
|
+
A ? be.verifyIdTokenNonce(A, l).then(() => s(x)).catch((b) => {
|
|
4455
|
+
d.error("[CROSSx] nonce 검증 실패:", b), t(b instanceof Error ? b : new Error("nonce verification failed"));
|
|
4456
|
+
}) : _ ? _.split(".").length === 3 ? be.verifyIdTokenNonce(_, l).then(() => s(x)).catch((E) => {
|
|
4457
|
+
d.error("[CROSSx] accessToken nonce 검증 실패:", E), t(E instanceof Error ? E : new Error("nonce verification failed"));
|
|
4458
|
+
}) : (d.warn(
|
|
4451
4459
|
"[CROSSx] opaque accessToken만 수신 (idToken 없음) — nonce 검증 불가.",
|
|
4452
4460
|
"서버 측 nonce 검증이 필요합니다."
|
|
4453
|
-
), s(
|
|
4461
|
+
), s(x)) : t(new Error("Token not found in response"));
|
|
4454
4462
|
} else
|
|
4455
|
-
|
|
4463
|
+
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
4464
|
};
|
|
4457
4465
|
window.addEventListener("message", V);
|
|
4458
4466
|
});
|
|
@@ -4471,9 +4479,9 @@ class mn {
|
|
|
4471
4479
|
*/
|
|
4472
4480
|
async checkWallet() {
|
|
4473
4481
|
if (this.migrateScenario !== void 0)
|
|
4474
|
-
return
|
|
4482
|
+
return d.log("[Mock] checkWallet → migration_required"), "migration_required";
|
|
4475
4483
|
const s = await this.storage.get(Ce) ? "exists" : "not_found";
|
|
4476
|
-
return
|
|
4484
|
+
return d.log(`[Mock] checkWallet → ${s}`), s;
|
|
4477
4485
|
}
|
|
4478
4486
|
async getOrCreateWallet(e) {
|
|
4479
4487
|
var s;
|
|
@@ -4488,9 +4496,9 @@ class mn {
|
|
|
4488
4496
|
};
|
|
4489
4497
|
await this.storage.set(Ce, n);
|
|
4490
4498
|
const o = (s = this.pinStore) == null ? void 0 : s.get();
|
|
4491
|
-
return o && (await this.storage.set(Te, o),
|
|
4499
|
+
return o && (await this.storage.set(Te, o), d.log("[Mock] 지갑 생성 — PIN 저장됨")), n;
|
|
4492
4500
|
} catch (t) {
|
|
4493
|
-
throw new
|
|
4501
|
+
throw new m(p.WALLET_CREATION_FAILED, "지갑 생성에 실패했습니다", t);
|
|
4494
4502
|
}
|
|
4495
4503
|
}
|
|
4496
4504
|
/** GET /mnemonic/addresses 모킹 — PIN 불필요, 캐시된 주소 반환 */
|
|
@@ -4506,21 +4514,21 @@ class mn {
|
|
|
4506
4514
|
}
|
|
4507
4515
|
async prepare(e, s) {
|
|
4508
4516
|
const t = "mock-" + crypto.randomUUID();
|
|
4509
|
-
return
|
|
4517
|
+
return d.log(`[Mock] prepare action=${e} → uuid=${t}`), { uuid: t, expiresAt: new Date(Date.now() + 5 * 6e4).toISOString() };
|
|
4510
4518
|
}
|
|
4511
4519
|
async signMessage(e, s, t, n = 0, o, i) {
|
|
4512
|
-
return
|
|
4520
|
+
return d.log(`[Mock] signMessage chainId=${s} index=${n} uuid=${o} from=${i}: "${t}"`), { chainId: s, signature: this.generateMockSignature(), format: "hex" };
|
|
4513
4521
|
}
|
|
4514
4522
|
async signTypedData(e, s, t, n = 0, o, i) {
|
|
4515
|
-
return
|
|
4523
|
+
return d.log(`[Mock] signTypedData chainId=${s} index=${n} uuid=${o} from=${i}`), { chainId: s, signature: this.generateMockSignature(), format: "hex" };
|
|
4516
4524
|
}
|
|
4517
4525
|
async signTransaction(e, s, t, n = 0, o) {
|
|
4518
|
-
|
|
4526
|
+
d.log(`[Mock] signTransaction chainId=${s} index=${n} uuid=${o}:`, t);
|
|
4519
4527
|
const i = "0x" + Array(64).fill(0).map(() => Math.floor(Math.random() * 16).toString(16)).join("");
|
|
4520
4528
|
return { chainId: s, signature: this.generateMockSignature(), txHash: i, format: "hex" };
|
|
4521
4529
|
}
|
|
4522
4530
|
async sendTransaction(e, s, t, n) {
|
|
4523
|
-
return
|
|
4531
|
+
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
4532
|
}
|
|
4525
4533
|
/**
|
|
4526
4534
|
* POST /mnemonic/verify-password 모킹
|
|
@@ -4528,10 +4536,10 @@ class mn {
|
|
|
4528
4536
|
*/
|
|
4529
4537
|
async verifyPin(e) {
|
|
4530
4538
|
var t;
|
|
4531
|
-
if (
|
|
4539
|
+
if (d.log("[Mock] verifyPin"), this.pinScenario === "wrong")
|
|
4532
4540
|
return !1;
|
|
4533
4541
|
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),
|
|
4542
|
+
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
4543
|
}
|
|
4536
4544
|
/**
|
|
4537
4545
|
* POST /mnemonic/change-password 모킹
|
|
@@ -4539,17 +4547,17 @@ class mn {
|
|
|
4539
4547
|
*/
|
|
4540
4548
|
async changePin(e, s) {
|
|
4541
4549
|
var o;
|
|
4542
|
-
if (
|
|
4543
|
-
throw new
|
|
4550
|
+
if (d.log("[Mock] changePin"), this.pinScenario === "wrong")
|
|
4551
|
+
throw new m(p.PIN_WRONG, "Incorrect PIN.");
|
|
4544
4552
|
const t = (o = this.pinStore) == null ? void 0 : o.get(), n = await this.storage.get(Te);
|
|
4545
4553
|
if (n && t && n !== t)
|
|
4546
|
-
throw new
|
|
4547
|
-
await this.storage.set(Te, s),
|
|
4554
|
+
throw new m(p.PIN_WRONG, "Incorrect PIN.");
|
|
4555
|
+
await this.storage.set(Te, s), d.log("[Mock] changePin 완료");
|
|
4548
4556
|
}
|
|
4549
4557
|
async migrateWallet(e, s) {
|
|
4550
4558
|
var o;
|
|
4551
|
-
if (
|
|
4552
|
-
throw new
|
|
4559
|
+
if (d.log(`[Mock] migrateWallet pin=${e} sub=${s}`), this.migrateScenario === "wrong_pin")
|
|
4560
|
+
throw new m(p.MIGRATION_FAILED, "Incorrect PIN.", {
|
|
4553
4561
|
permanent: !1,
|
|
4554
4562
|
lockExpiresAt: 0,
|
|
4555
4563
|
remainingAttempts: 4,
|
|
@@ -4563,7 +4571,7 @@ class mn {
|
|
|
4563
4571
|
maxAttempts: 5,
|
|
4564
4572
|
...this.migrateScenario.locked
|
|
4565
4573
|
};
|
|
4566
|
-
throw new
|
|
4574
|
+
throw new m(
|
|
4567
4575
|
p.MIGRATION_PIN_LOCKED,
|
|
4568
4576
|
"Too many incorrect PIN attempts. Your account has been temporarily locked.",
|
|
4569
4577
|
a
|
|
@@ -4577,21 +4585,21 @@ class mn {
|
|
|
4577
4585
|
};
|
|
4578
4586
|
await this.storage.set(Ce, t);
|
|
4579
4587
|
const n = (o = this.pinStore) == null ? void 0 : o.get();
|
|
4580
|
-
return n && (await this.storage.set(Te, n),
|
|
4588
|
+
return n && (await this.storage.set(Te, n), d.log("[Mock] 마이그레이션 — PIN 저장됨")), t;
|
|
4581
4589
|
}
|
|
4582
4590
|
/**
|
|
4583
4591
|
* POST /mnemonic/share-c 모킹
|
|
4584
4592
|
* 새로운 Share-C 문자열을 반환합니다.
|
|
4585
4593
|
*/
|
|
4586
4594
|
async getShareC() {
|
|
4587
|
-
return
|
|
4595
|
+
return d.log("[Mock] getShareC"), "mock-share-c-" + crypto.randomUUID();
|
|
4588
4596
|
}
|
|
4589
4597
|
/**
|
|
4590
4598
|
* POST /mnemonic/verify-recovery-pin 모킹
|
|
4591
4599
|
* CROSSx 4자리 복구 PIN 검증
|
|
4592
4600
|
*/
|
|
4593
4601
|
async verifyRecoveryPin(e, s) {
|
|
4594
|
-
return
|
|
4602
|
+
return d.log("[Mock] verifyRecoveryPin"), { valid: !0 };
|
|
4595
4603
|
}
|
|
4596
4604
|
generateMockEvmAddress() {
|
|
4597
4605
|
return "0x" + Array(40).fill(0).map(
|
|
@@ -4621,7 +4629,7 @@ class Le {
|
|
|
4621
4629
|
getAuthToken() {
|
|
4622
4630
|
const e = this.tokenStore.get();
|
|
4623
4631
|
if (!e)
|
|
4624
|
-
throw new
|
|
4632
|
+
throw new m(
|
|
4625
4633
|
p.AUTH_NOT_AUTHENTICATED,
|
|
4626
4634
|
"인증 토큰을 찾을 수 없습니다. 먼저 로그인해 주세요."
|
|
4627
4635
|
);
|
|
@@ -4635,40 +4643,40 @@ class Le {
|
|
|
4635
4643
|
"X-Project-Id": this.projectId
|
|
4636
4644
|
};
|
|
4637
4645
|
try {
|
|
4638
|
-
const
|
|
4646
|
+
const u = (await this.transport.request({
|
|
4639
4647
|
url: o,
|
|
4640
4648
|
method: e,
|
|
4641
4649
|
headers: i,
|
|
4642
4650
|
body: t ?? void 0
|
|
4643
4651
|
})).data;
|
|
4644
|
-
if (
|
|
4645
|
-
if (
|
|
4646
|
-
const h =
|
|
4647
|
-
|
|
4648
|
-
code:
|
|
4652
|
+
if (u && typeof u.code == "number") {
|
|
4653
|
+
if (u.code < 0 || u.code >= 400) {
|
|
4654
|
+
const h = u.message || u.data || "API 요청에 실패했습니다";
|
|
4655
|
+
d.error("[CROSSx] Wallet Gateway API 에러 (HTTP 200):", {
|
|
4656
|
+
code: u.code,
|
|
4649
4657
|
message: h,
|
|
4650
4658
|
url: o,
|
|
4651
4659
|
method: e
|
|
4652
4660
|
});
|
|
4653
|
-
const
|
|
4654
|
-
throw
|
|
4661
|
+
const g = Le.mapGatewayError(u.code, u.data), f = Le.getGatewayErrorMessage(u.code, h), w = u.data, v = g === p.PIN_LOCKED ? Le.extractLockDetails(w) : w ?? void 0, y = new m(g, f, v);
|
|
4662
|
+
throw g === p.AUTH_NOT_AUTHENTICATED && this._onUnauthorized && (d.warn("[CROSSx] Gateway -10002 감지 — 강제 로그아웃 실행"), this._onUnauthorized()), y;
|
|
4655
4663
|
}
|
|
4656
|
-
return
|
|
4664
|
+
return d.log("[CROSSx] Wallet Gateway API 성공:", { code: u.code, url: o, method: e }), u.data ?? u;
|
|
4657
4665
|
}
|
|
4658
|
-
return
|
|
4666
|
+
return u;
|
|
4659
4667
|
} catch (l) {
|
|
4660
|
-
if (l instanceof
|
|
4668
|
+
if (l instanceof m) throw l;
|
|
4661
4669
|
if ((a = l.response) != null && a.data) {
|
|
4662
|
-
const
|
|
4663
|
-
throw
|
|
4664
|
-
code:
|
|
4670
|
+
const u = l.response.data, h = u.message || u.data || "API 요청에 실패했습니다", g = u.code || "UNKNOWN";
|
|
4671
|
+
throw d.error("[CROSSx] Wallet Gateway API 에러 (HTTP 에러):", {
|
|
4672
|
+
code: g,
|
|
4665
4673
|
message: h,
|
|
4666
4674
|
url: o,
|
|
4667
4675
|
method: e,
|
|
4668
4676
|
status: (c = l.response) == null ? void 0 : c.status
|
|
4669
|
-
}), new
|
|
4677
|
+
}), new m(
|
|
4670
4678
|
p.UNKNOWN_ERROR,
|
|
4671
|
-
`Wallet Gateway 오류 (${
|
|
4679
|
+
`Wallet Gateway 오류 (${g}): ${h}`
|
|
4672
4680
|
);
|
|
4673
4681
|
}
|
|
4674
4682
|
throw l;
|
|
@@ -4679,9 +4687,9 @@ class Le {
|
|
|
4679
4687
|
* 결과를 내부 캐시에 저장하여 getOrCreateWallet에서 재사용합니다.
|
|
4680
4688
|
*/
|
|
4681
4689
|
async checkWallet() {
|
|
4682
|
-
|
|
4690
|
+
d.log("[CROSSx] GET /mnemonic/check");
|
|
4683
4691
|
const e = await this.request("GET", "/mnemonic/check");
|
|
4684
|
-
return
|
|
4692
|
+
return d.log("[CROSSx] /mnemonic/check 결과:", e.result), this._walletStatusCache = e.result, e.result;
|
|
4685
4693
|
}
|
|
4686
4694
|
/**
|
|
4687
4695
|
* 지갑 생성 또는 로드
|
|
@@ -4692,24 +4700,24 @@ class Le {
|
|
|
4692
4700
|
*/
|
|
4693
4701
|
async getOrCreateWallet(e) {
|
|
4694
4702
|
let s;
|
|
4695
|
-
if (this._walletStatusCache !== null ? (s = this._walletStatusCache, this._walletStatusCache = null,
|
|
4696
|
-
throw
|
|
4703
|
+
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")
|
|
4704
|
+
throw d.log("[CROSSx] migration_required → MIGRATION_BACKUP_EXISTS throw"), new m(
|
|
4697
4705
|
p.MIGRATION_BACKUP_EXISTS,
|
|
4698
4706
|
"CROSSx 백업이 존재합니다. 마이그레이션을 진행해 주세요."
|
|
4699
4707
|
);
|
|
4700
4708
|
if (s === "exists") {
|
|
4701
|
-
|
|
4709
|
+
d.log("[CROSSx] 기존 지갑 발견 — POST /mnemonic/address(0)로 주소 조회");
|
|
4702
4710
|
const o = await this.getAddress(e, 0);
|
|
4703
|
-
return
|
|
4711
|
+
return d.log("[CROSSx] 주소 조회 완료 — address:", o.address), {
|
|
4704
4712
|
id: e,
|
|
4705
4713
|
address: o.address,
|
|
4706
4714
|
derivationPath: "m/44'/60'/0'/0/0",
|
|
4707
4715
|
createdAt: Date.now()
|
|
4708
4716
|
};
|
|
4709
4717
|
}
|
|
4710
|
-
|
|
4718
|
+
d.log("[CROSSx] POST /mnemonic/create — 신규 지갑 생성");
|
|
4711
4719
|
const t = { ignoreBackup: !1, password: this.requirePin() }, n = await this.request("POST", "/mnemonic/create", t);
|
|
4712
|
-
return
|
|
4720
|
+
return d.log("[CROSSx] /mnemonic/create 완료 — address:", n.address), {
|
|
4713
4721
|
id: e,
|
|
4714
4722
|
address: n.address,
|
|
4715
4723
|
derivationPath: "m/44'/60'/0'/0/0",
|
|
@@ -4736,15 +4744,15 @@ class Le {
|
|
|
4736
4744
|
switch (e) {
|
|
4737
4745
|
case "sign":
|
|
4738
4746
|
case "send":
|
|
4739
|
-
if (!s.tx) throw new
|
|
4747
|
+
if (!s.tx) throw new m(p.TX_INVALID_PARAMS, "prepare: tx가 필요합니다");
|
|
4740
4748
|
t = { unsignedTx: this.buildUnsignedTx(s.tx) };
|
|
4741
4749
|
break;
|
|
4742
4750
|
case "sign-message":
|
|
4743
|
-
if (!s.message) throw new
|
|
4751
|
+
if (!s.message) throw new m(p.TX_INVALID_PARAMS, "prepare: message가 필요합니다");
|
|
4744
4752
|
t = { message: s.message }, s.from && (t.from = s.from);
|
|
4745
4753
|
break;
|
|
4746
4754
|
case "sign-typed-data":
|
|
4747
|
-
if (!s.typedData) throw new
|
|
4755
|
+
if (!s.typedData) throw new m(p.TX_INVALID_PARAMS, "prepare: typedData가 필요합니다");
|
|
4748
4756
|
t = { typedData: s.typedData }, s.from && (t.from = s.from);
|
|
4749
4757
|
break;
|
|
4750
4758
|
}
|
|
@@ -4803,13 +4811,13 @@ class Le {
|
|
|
4803
4811
|
)).txHash };
|
|
4804
4812
|
}
|
|
4805
4813
|
async migrateWallet(e, s) {
|
|
4806
|
-
|
|
4814
|
+
d.log("[CROSSx][Migration Phase 4] POST /mnemonic/migrate 호출");
|
|
4807
4815
|
const t = { recoveryPin: e, sub: s, password: this.requirePin() }, n = await this.request(
|
|
4808
4816
|
"POST",
|
|
4809
4817
|
"/mnemonic/migrate",
|
|
4810
4818
|
t
|
|
4811
4819
|
);
|
|
4812
|
-
return
|
|
4820
|
+
return d.log("[CROSSx][Migration Phase 4] /mnemonic/migrate 완료 — address:", n.address), {
|
|
4813
4821
|
id: s,
|
|
4814
4822
|
address: n.address,
|
|
4815
4823
|
derivationPath: "m/44'/60'/0'/0/0",
|
|
@@ -4860,7 +4868,7 @@ class Le {
|
|
|
4860
4868
|
requirePin() {
|
|
4861
4869
|
const e = this.getPin();
|
|
4862
4870
|
if (!e)
|
|
4863
|
-
throw new
|
|
4871
|
+
throw new m(
|
|
4864
4872
|
p.PIN_NOT_SET,
|
|
4865
4873
|
"PIN이 설정되지 않았습니다. PIN을 입력해 주세요."
|
|
4866
4874
|
);
|
|
@@ -5044,7 +5052,7 @@ class De {
|
|
|
5044
5052
|
handleEnvelopeError(e) {
|
|
5045
5053
|
if (e.code < 0) {
|
|
5046
5054
|
const s = typeof e.data == "string" ? e.data : e.message ?? "체인 레지스트리 요청에 실패했습니다";
|
|
5047
|
-
throw new
|
|
5055
|
+
throw new m(
|
|
5048
5056
|
De.mapErrorCode(e.code),
|
|
5049
5057
|
s
|
|
5050
5058
|
);
|
|
@@ -5055,7 +5063,7 @@ class De {
|
|
|
5055
5063
|
(t) => t.chainId === e
|
|
5056
5064
|
);
|
|
5057
5065
|
if (s) return s;
|
|
5058
|
-
throw new
|
|
5066
|
+
throw new m(
|
|
5059
5067
|
p.CHAIN_NOT_SUPPORTED,
|
|
5060
5068
|
`지원하지 않는 체인: ${e}`
|
|
5061
5069
|
);
|
|
@@ -6260,6 +6268,79 @@ const yn = `
|
|
|
6260
6268
|
transform: none !important;
|
|
6261
6269
|
}
|
|
6262
6270
|
|
|
6271
|
+
/* ── Connect Other Wallets (Login Selector) ───────────────── */
|
|
6272
|
+
.__crossx-login-or-divider {
|
|
6273
|
+
display: flex;
|
|
6274
|
+
align-items: center;
|
|
6275
|
+
gap: 16px;
|
|
6276
|
+
width: 100%;
|
|
6277
|
+
}
|
|
6278
|
+
.__crossx-login-or-divider hr {
|
|
6279
|
+
flex: 1;
|
|
6280
|
+
border: none;
|
|
6281
|
+
border-top: 1px solid var(--cx-border);
|
|
6282
|
+
margin: 0;
|
|
6283
|
+
}
|
|
6284
|
+
.__crossx-login-or-divider span {
|
|
6285
|
+
font-size: 16px;
|
|
6286
|
+
font-weight: 400;
|
|
6287
|
+
line-height: 1.3;
|
|
6288
|
+
color: var(--cx-hint);
|
|
6289
|
+
font-family: 'Sora', 'Pretendard', -apple-system, sans-serif;
|
|
6290
|
+
white-space: nowrap;
|
|
6291
|
+
flex-shrink: 0;
|
|
6292
|
+
}
|
|
6293
|
+
.__crossx-connect-other-btn {
|
|
6294
|
+
display: flex;
|
|
6295
|
+
gap: 8px;
|
|
6296
|
+
align-items: center;
|
|
6297
|
+
width: 100%;
|
|
6298
|
+
padding: 16px;
|
|
6299
|
+
background: var(--cx-pill-bg);
|
|
6300
|
+
border: 1px solid var(--cx-border);
|
|
6301
|
+
border-radius: 20px;
|
|
6302
|
+
cursor: pointer;
|
|
6303
|
+
appearance: none;
|
|
6304
|
+
-webkit-appearance: none;
|
|
6305
|
+
-webkit-tap-highlight-color: transparent;
|
|
6306
|
+
box-shadow: none;
|
|
6307
|
+
outline: none;
|
|
6308
|
+
}
|
|
6309
|
+
.__crossx-connect-other-btn:hover,
|
|
6310
|
+
.__crossx-connect-other-btn:focus,
|
|
6311
|
+
.__crossx-connect-other-btn:active {
|
|
6312
|
+
opacity: 1 !important;
|
|
6313
|
+
box-shadow: none !important;
|
|
6314
|
+
outline: none !important;
|
|
6315
|
+
filter: none !important;
|
|
6316
|
+
transform: none !important;
|
|
6317
|
+
background: var(--cx-pill-bg) !important;
|
|
6318
|
+
}
|
|
6319
|
+
.__crossx-connect-other-text {
|
|
6320
|
+
display: flex;
|
|
6321
|
+
flex: 1;
|
|
6322
|
+
flex-direction: column;
|
|
6323
|
+
align-items: flex-start;
|
|
6324
|
+
justify-content: center;
|
|
6325
|
+
min-width: 0;
|
|
6326
|
+
}
|
|
6327
|
+
.__crossx-connect-other-title {
|
|
6328
|
+
font-size: 18px;
|
|
6329
|
+
font-weight: 700;
|
|
6330
|
+
line-height: 1.3;
|
|
6331
|
+
color: var(--cx-value);
|
|
6332
|
+
font-family: 'Pretendard', 'Sora', -apple-system, sans-serif;
|
|
6333
|
+
text-align: left;
|
|
6334
|
+
}
|
|
6335
|
+
.__crossx-connect-other-desc {
|
|
6336
|
+
font-size: 14px;
|
|
6337
|
+
font-weight: 400;
|
|
6338
|
+
line-height: 1.4;
|
|
6339
|
+
color: var(--cx-subtitle);
|
|
6340
|
+
font-family: 'Pretendard', 'Sora', -apple-system, sans-serif;
|
|
6341
|
+
text-align: left;
|
|
6342
|
+
}
|
|
6343
|
+
|
|
6263
6344
|
/* ── Wallet Selector Modal ─────────────────────────────────── */
|
|
6264
6345
|
.__crossx-wallet-list {
|
|
6265
6346
|
display: flex;
|
|
@@ -7028,8 +7109,8 @@ function Tn(r, e) {
|
|
|
7028
7109
|
}
|
|
7029
7110
|
function Rn(r, e) {
|
|
7030
7111
|
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
|
|
7112
|
+
<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");
|
|
7113
|
+
return u.id = te, u.innerHTML = `
|
|
7033
7114
|
<div class="__crossx-card __crossx-card--migration __crossx-card--send-tx" style="${ce(s)}" role="dialog" aria-modal="true" aria-labelledby="__crossx-ttl">
|
|
7034
7115
|
<div class="__crossx-header">
|
|
7035
7116
|
<p class="__crossx-title" id="__crossx-ttl">Approve transaction</p>
|
|
@@ -7054,7 +7135,7 @@ function Rn(r, e) {
|
|
|
7054
7135
|
<button class="__crossx-approve-btn" id="__crossx-confirm-btn">Approve</button>
|
|
7055
7136
|
</div>
|
|
7056
7137
|
</div>
|
|
7057
|
-
`,
|
|
7138
|
+
`, u;
|
|
7058
7139
|
}
|
|
7059
7140
|
function Ye(r) {
|
|
7060
7141
|
var e;
|
|
@@ -7143,8 +7224,8 @@ function Cn(r, e, s) {
|
|
|
7143
7224
|
if (!a) return;
|
|
7144
7225
|
const c = e.from ? Y("From", `<span class="__crossx-addr-text">${se(e.from)}</span>
|
|
7145
7226
|
<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>`) : "",
|
|
7227
|
+
<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>
|
|
7228
|
+
<button class="__crossx-copy-btn" data-copy="${H(e.txHash)}" title="Copy hash">${xe}</button>`) : "", f = e.total ? `<div class="__crossx-total-pill">
|
|
7148
7229
|
<span class="__crossx-total-label">Total<br>(including fees)</span>
|
|
7149
7230
|
<span class="__crossx-total-amount">${H(e.total)}</span>
|
|
7150
7231
|
</div>` : "";
|
|
@@ -7152,11 +7233,11 @@ function Cn(r, e, s) {
|
|
|
7152
7233
|
<div class="__crossx-rows">
|
|
7153
7234
|
${c}
|
|
7154
7235
|
${l}
|
|
7155
|
-
${
|
|
7236
|
+
${u}
|
|
7156
7237
|
${h}
|
|
7157
|
-
${
|
|
7238
|
+
${g}
|
|
7158
7239
|
</div>
|
|
7159
|
-
${
|
|
7240
|
+
${f}
|
|
7160
7241
|
<button class="__crossx-approve-btn" id="__crossx-done-btn">${t ? "All Done" : "Done"}</button>
|
|
7161
7242
|
`, a.querySelectorAll(".__crossx-copy-btn").forEach((w) => {
|
|
7162
7243
|
w.addEventListener("click", (v) => {
|
|
@@ -7215,13 +7296,13 @@ function Dn(r, e) {
|
|
|
7215
7296
|
<span class="__crossx-td-label">Primary Type</span>
|
|
7216
7297
|
<span class="__crossx-td-value">${H(o)}</span>
|
|
7217
7298
|
</div>`;
|
|
7218
|
-
for (const [l,
|
|
7219
|
-
const h = Pn(
|
|
7220
|
-
<button class="__crossx-copy-btn" data-copy="${H(String(
|
|
7299
|
+
for (const [l, u] of Object.entries(i)) {
|
|
7300
|
+
const h = Pn(u), f = kn(u) ? `<span class="__crossx-addr-text">${se(u)}</span>
|
|
7301
|
+
<button class="__crossx-copy-btn" data-copy="${H(String(u))}" title="Copy">${xe}</button>` : `<span>${h}</span>`;
|
|
7221
7302
|
a += `
|
|
7222
7303
|
<div class="__crossx-td-row">
|
|
7223
7304
|
<span class="__crossx-td-label">${H(l)}</span>
|
|
7224
|
-
<div class="__crossx-td-value">${
|
|
7305
|
+
<div class="__crossx-td-value">${f}</div>
|
|
7225
7306
|
</div>`;
|
|
7226
7307
|
}
|
|
7227
7308
|
const c = document.createElement("div");
|
|
@@ -7308,14 +7389,23 @@ const Bn = `<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="h
|
|
|
7308
7389
|
<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
7390
|
<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
7391
|
</svg>`;
|
|
7311
|
-
function Hn(r) {
|
|
7312
|
-
const
|
|
7313
|
-
|
|
7314
|
-
|
|
7392
|
+
function Hn(r, e = !1) {
|
|
7393
|
+
const s = r, t = e ? `
|
|
7394
|
+
<div class="__crossx-login-or-divider">
|
|
7395
|
+
<hr><span>or</span><hr>
|
|
7396
|
+
</div>
|
|
7397
|
+
<button class="__crossx-connect-other-btn" id="__crossx-connect-btn" type="button">
|
|
7398
|
+
<div class="__crossx-connect-other-text">
|
|
7399
|
+
<span class="__crossx-connect-other-title">Connect with Other Wallets</span>
|
|
7400
|
+
<span class="__crossx-connect-other-desc">Connect your existing Web3 wallet to manage your assets.</span>
|
|
7401
|
+
</div>
|
|
7402
|
+
</button>` : "", n = document.createElement("div");
|
|
7403
|
+
return n.id = te, n.innerHTML = `
|
|
7404
|
+
<div class="__crossx-card __crossx-card--migration" style="${ce(s)}" role="dialog" aria-modal="true" aria-labelledby="__crossx-ttl">
|
|
7315
7405
|
<div class="__crossx-header">
|
|
7316
7406
|
<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">
|
|
7407
|
+
<p class="__crossx-title" id="__crossx-ttl" style="padding-right:0;">CROSS Wallet</p>
|
|
7408
|
+
<p class="__crossx-subtitle">Sign in instantly with your social account</p>
|
|
7319
7409
|
</div>
|
|
7320
7410
|
<button class="__crossx-close" id="__crossx-close-btn" aria-label="Close">${ie}</button>
|
|
7321
7411
|
</div>
|
|
@@ -7330,14 +7420,13 @@ function Hn(r) {
|
|
|
7330
7420
|
<span class="__crossx-login-icon">${Un}</span>
|
|
7331
7421
|
<span class="__crossx-login-btn-label">Sign in with Google</span>
|
|
7332
7422
|
</button>
|
|
7333
|
-
</div
|
|
7334
|
-
<hr class="__crossx-divider">
|
|
7423
|
+
</div>${t}
|
|
7335
7424
|
<p class="__crossx-login-terms">
|
|
7336
7425
|
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
7426
|
</p>
|
|
7338
7427
|
</div>
|
|
7339
7428
|
</div>
|
|
7340
|
-
`,
|
|
7429
|
+
`, n;
|
|
7341
7430
|
}
|
|
7342
7431
|
function Fn(r, e = !0) {
|
|
7343
7432
|
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 +7453,7 @@ function Fn(r, e = !0) {
|
|
|
7364
7453
|
`, o;
|
|
7365
7454
|
}
|
|
7366
7455
|
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>' : "",
|
|
7456
|
+
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
7457
|
return h.id = te, h.innerHTML = `
|
|
7369
7458
|
<div class="__crossx-card __crossx-card--migration" style="${ce(s)}" role="dialog" aria-modal="true" aria-labelledby="__crossx-ttl">
|
|
7370
7459
|
<div class="__crossx-header">
|
|
@@ -7382,7 +7471,7 @@ function Gn(r, e) {
|
|
|
7382
7471
|
<input class="__crossx-pin-input${a}" type="tel" maxlength="1" inputmode="numeric" pattern="[0-9]" autocomplete="off">
|
|
7383
7472
|
</div>
|
|
7384
7473
|
<p class="__crossx-pin-hint">Enter your 4-digit PIN to recover your wallet.</p>
|
|
7385
|
-
${
|
|
7474
|
+
${u}
|
|
7386
7475
|
</div>
|
|
7387
7476
|
</div>
|
|
7388
7477
|
`, h;
|
|
@@ -7464,7 +7553,7 @@ function nt(r) {
|
|
|
7464
7553
|
<span id="__crossx-pin6-lock-countdown"></span>
|
|
7465
7554
|
</p>` : "", a = e ? " --locked" : "", c = Array.from(
|
|
7466
7555
|
{ length: 6 },
|
|
7467
|
-
(l,
|
|
7556
|
+
(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
7557
|
).join("");
|
|
7469
7558
|
return `
|
|
7470
7559
|
<div class="__crossx-header">
|
|
@@ -7506,15 +7595,15 @@ function zn(r) {
|
|
|
7506
7595
|
function ot(r, e, s, t, n, o) {
|
|
7507
7596
|
var V, W;
|
|
7508
7597
|
let i = !!(o && o > Date.now()), a = !1;
|
|
7509
|
-
const c = () => Array.from(r.querySelectorAll(".__crossx-pin6-box")), l = () => r.querySelector("#__crossx-pin6-boxes"),
|
|
7598
|
+
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"), f = () => r.querySelector(".__crossx-pin6-body"), w = () => c().map((P) => P.value).join(""), v = (P) => {
|
|
7510
7599
|
i = P, c().forEach((k) => {
|
|
7511
7600
|
k.disabled = P, k.classList.toggle("--locked", P);
|
|
7512
7601
|
});
|
|
7513
7602
|
}, y = () => {
|
|
7514
|
-
const P =
|
|
7603
|
+
const P = u();
|
|
7515
7604
|
P && (P.textContent = "");
|
|
7516
7605
|
}, S = (P) => {
|
|
7517
|
-
const k =
|
|
7606
|
+
const k = u();
|
|
7518
7607
|
k && (k.textContent = P);
|
|
7519
7608
|
const D = l();
|
|
7520
7609
|
D == null || D.classList.add("--shake"), setTimeout(() => D == null ? void 0 : D.classList.remove("--shake"), 500), c().forEach((q) => {
|
|
@@ -7528,20 +7617,20 @@ function ot(r, e, s, t, n, o) {
|
|
|
7528
7617
|
v(!0), c().forEach((A) => {
|
|
7529
7618
|
A.value = "";
|
|
7530
7619
|
});
|
|
7531
|
-
const k =
|
|
7620
|
+
const k = u();
|
|
7532
7621
|
if (k && (k.textContent = "Too many failed attempts. Please wait."), !h()) {
|
|
7533
7622
|
const A = document.createElement("p");
|
|
7534
7623
|
A.className = "__crossx-pin6-lock-msg", A.id = "__crossx-pin6-lock-msg", A.innerHTML = `${Cs}<span id="__crossx-pin6-lock-countdown"></span>`;
|
|
7535
|
-
const
|
|
7536
|
-
|
|
7624
|
+
const _ = u();
|
|
7625
|
+
_ ? _.insertAdjacentElement("afterend", A) : (R = f()) == null || R.appendChild(A);
|
|
7537
7626
|
}
|
|
7538
7627
|
const D = () => {
|
|
7539
|
-
var
|
|
7540
|
-
const A = P - Date.now(),
|
|
7541
|
-
A <= 0 ? (clearInterval(q), v(!1), (
|
|
7628
|
+
var x;
|
|
7629
|
+
const A = P - Date.now(), _ = g();
|
|
7630
|
+
A <= 0 ? (clearInterval(q), v(!1), (x = h()) == null || x.remove(), k && (k.textContent = ""), setTimeout(() => {
|
|
7542
7631
|
var b;
|
|
7543
7632
|
return (b = c()[0]) == null ? void 0 : b.focus();
|
|
7544
|
-
}, 50)) :
|
|
7633
|
+
}, 50)) : _ && (_.textContent = ` ${zn(A)}`);
|
|
7545
7634
|
}, q = setInterval(D, 1e3);
|
|
7546
7635
|
D();
|
|
7547
7636
|
const L = new MutationObserver(() => {
|
|
@@ -7581,7 +7670,7 @@ function ot(r, e, s, t, n, o) {
|
|
|
7581
7670
|
};
|
|
7582
7671
|
(V = l()) == null || V.addEventListener("click", (P) => {
|
|
7583
7672
|
P.target.classList.contains("__crossx-pin6-box") || N();
|
|
7584
|
-
}), (W =
|
|
7673
|
+
}), (W = f()) == null || W.addEventListener("click", (P) => {
|
|
7585
7674
|
const k = P.target;
|
|
7586
7675
|
k.classList.contains("__crossx-pin6-box") || k.closest("button") || N();
|
|
7587
7676
|
}), c().forEach((P, k) => {
|
|
@@ -7605,8 +7694,8 @@ function ot(r, e, s, t, n, o) {
|
|
|
7605
7694
|
const q = (((R = D.clipboardData) == null ? void 0 : R.getData("text")) ?? "").replace(/\D/g, "").slice(0, 6);
|
|
7606
7695
|
if (!q) return;
|
|
7607
7696
|
const L = c();
|
|
7608
|
-
q.split("").forEach((
|
|
7609
|
-
L[
|
|
7697
|
+
q.split("").forEach((_, x) => {
|
|
7698
|
+
L[x] && (L[x].value = _);
|
|
7610
7699
|
}), (A = L[Math.min(q.length - 1, 5)]) == null || A.focus(), y(), w().length === 6 && setTimeout(U, 80);
|
|
7611
7700
|
}), P.addEventListener("focus", () => P.select());
|
|
7612
7701
|
});
|
|
@@ -7625,7 +7714,7 @@ function Jn(r, e, s) {
|
|
|
7625
7714
|
i.addEventListener("input", () => {
|
|
7626
7715
|
const c = i.value.replace(/\D/g, "");
|
|
7627
7716
|
i.value = c ? c[0] : "", c && a < 3 && t[a + 1].focus();
|
|
7628
|
-
const l = Array.from(t).map((
|
|
7717
|
+
const l = Array.from(t).map((u) => u.value).join("");
|
|
7629
7718
|
l.length === 4 && setTimeout(() => e(l), 200);
|
|
7630
7719
|
}), i.addEventListener("keydown", (c) => {
|
|
7631
7720
|
c.key === "Backspace" && !i.value && a > 0 && (t[a - 1].focus(), t[a - 1].value = ""), c.key === "Escape" && s();
|
|
@@ -7636,11 +7725,11 @@ function Jn(r, e, s) {
|
|
|
7636
7725
|
c.preventDefault();
|
|
7637
7726
|
const l = (((h = c.clipboardData) == null ? void 0 : h.getData("text")) ?? "").replace(/\D/g, "").slice(0, 4);
|
|
7638
7727
|
if (!l) return;
|
|
7639
|
-
l.split("").forEach((
|
|
7640
|
-
t[
|
|
7728
|
+
l.split("").forEach((g, f) => {
|
|
7729
|
+
t[f] && (t[f].value = g);
|
|
7641
7730
|
});
|
|
7642
|
-
const
|
|
7643
|
-
t[
|
|
7731
|
+
const u = Math.min(l.length, 3);
|
|
7732
|
+
t[u].focus(), l.length === 4 && setTimeout(() => e(l), 200);
|
|
7644
7733
|
});
|
|
7645
7734
|
});
|
|
7646
7735
|
const n = r.querySelector(".__crossx-pin-inputs");
|
|
@@ -7678,7 +7767,7 @@ class Xn {
|
|
|
7678
7767
|
let c = !1;
|
|
7679
7768
|
const l = () => {
|
|
7680
7769
|
c || (c = !0, i.remove(), document.body.style.overflow = a);
|
|
7681
|
-
},
|
|
7770
|
+
}, u = (y) => {
|
|
7682
7771
|
l(), n(y);
|
|
7683
7772
|
}, h = () => {
|
|
7684
7773
|
l(), n(null);
|
|
@@ -7687,24 +7776,24 @@ class Xn {
|
|
|
7687
7776
|
i.querySelectorAll(".__crossx-wallet-item").forEach((y) => {
|
|
7688
7777
|
y.addEventListener("click", () => {
|
|
7689
7778
|
const S = y.dataset.walletAddress ?? "", C = parseInt(y.dataset.walletIndex ?? "0", 10);
|
|
7690
|
-
|
|
7779
|
+
u({ address: S, index: C });
|
|
7691
7780
|
});
|
|
7692
7781
|
});
|
|
7693
7782
|
})();
|
|
7694
|
-
const
|
|
7695
|
-
|
|
7696
|
-
|
|
7783
|
+
const f = i.querySelector("#__crossx-add-wallet-btn");
|
|
7784
|
+
f && f.addEventListener("click", async () => {
|
|
7785
|
+
f.disabled = !0;
|
|
7697
7786
|
try {
|
|
7698
7787
|
const y = await s();
|
|
7699
7788
|
o.push(y);
|
|
7700
7789
|
const S = i.querySelector("#__crossx-wallet-list");
|
|
7701
7790
|
if (S) {
|
|
7702
7791
|
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", () =>
|
|
7792
|
+
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
7793
|
}
|
|
7705
7794
|
} catch {
|
|
7706
7795
|
} finally {
|
|
7707
|
-
|
|
7796
|
+
f.disabled = !1;
|
|
7708
7797
|
}
|
|
7709
7798
|
}), (v = i.querySelector("#__crossx-close-btn")) == null || v.addEventListener("click", h), i.addEventListener("click", (y) => {
|
|
7710
7799
|
y.target === i && h();
|
|
@@ -7716,30 +7805,31 @@ class Xn {
|
|
|
7716
7805
|
});
|
|
7717
7806
|
}
|
|
7718
7807
|
/**
|
|
7719
|
-
* 로그인 프로바이더 선택 팝업: "
|
|
7808
|
+
* 로그인 프로바이더 선택 팝업: "CROSS Wallet"
|
|
7720
7809
|
* Apple / Google 버튼을 표시하고 선택된 프로바이더를 반환합니다.
|
|
7721
|
-
*
|
|
7810
|
+
* showConnectOtherWallets가 true이면 "Connect with Other Wallets" 버튼도 표시합니다.
|
|
7811
|
+
* @returns 'google' | 'apple' | 'external' | null(취소)
|
|
7722
7812
|
*/
|
|
7723
|
-
showLoginSelector() {
|
|
7724
|
-
return new Promise((
|
|
7725
|
-
var
|
|
7813
|
+
showLoginSelector(e) {
|
|
7814
|
+
return new Promise((s) => {
|
|
7815
|
+
var c, l, u, h;
|
|
7726
7816
|
he();
|
|
7727
|
-
const
|
|
7728
|
-
pe(
|
|
7729
|
-
const
|
|
7730
|
-
|
|
7731
|
-
},
|
|
7732
|
-
|
|
7817
|
+
const t = Hn(this.tokens, e == null ? void 0 : e.showConnectOtherWallets);
|
|
7818
|
+
pe(t);
|
|
7819
|
+
const n = () => t.remove(), o = (g) => {
|
|
7820
|
+
n(), s(g);
|
|
7821
|
+
}, i = () => {
|
|
7822
|
+
n(), s(null);
|
|
7733
7823
|
};
|
|
7734
|
-
(
|
|
7735
|
-
|
|
7736
|
-
}),
|
|
7737
|
-
|
|
7824
|
+
(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) => {
|
|
7825
|
+
g.target === t && i();
|
|
7826
|
+
}), t.querySelectorAll(".__crossx-login-terms-link").forEach((g) => {
|
|
7827
|
+
g.addEventListener("click", (f) => f.stopPropagation());
|
|
7738
7828
|
});
|
|
7739
|
-
const
|
|
7740
|
-
|
|
7829
|
+
const a = (g) => {
|
|
7830
|
+
g.key === "Escape" && (document.removeEventListener("keydown", a), i());
|
|
7741
7831
|
};
|
|
7742
|
-
document.addEventListener("keydown",
|
|
7832
|
+
document.addEventListener("keydown", a);
|
|
7743
7833
|
});
|
|
7744
7834
|
}
|
|
7745
7835
|
/**
|
|
@@ -7758,14 +7848,14 @@ class Xn {
|
|
|
7758
7848
|
o(), t("recover");
|
|
7759
7849
|
};
|
|
7760
7850
|
if ((a = n.querySelector("#__crossx-recover-btn")) == null || a.addEventListener("click", i), s) {
|
|
7761
|
-
const
|
|
7851
|
+
const u = () => {
|
|
7762
7852
|
o(), t("skip");
|
|
7763
7853
|
};
|
|
7764
|
-
(c = n.querySelector("#__crossx-skip-btn")) == null || c.addEventListener("click",
|
|
7765
|
-
|
|
7854
|
+
(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) => {
|
|
7855
|
+
g.target === n && u();
|
|
7766
7856
|
});
|
|
7767
|
-
const h = (
|
|
7768
|
-
|
|
7857
|
+
const h = (g) => {
|
|
7858
|
+
g.key === "Escape" && (document.removeEventListener("keydown", h), u());
|
|
7769
7859
|
};
|
|
7770
7860
|
document.addEventListener("keydown", h);
|
|
7771
7861
|
}
|
|
@@ -7801,13 +7891,13 @@ class Xn {
|
|
|
7801
7891
|
}, a = Zt(this.tokens, Kn(n)), c = document.body.style.overflow;
|
|
7802
7892
|
document.body.style.overflow = "hidden", pe(a);
|
|
7803
7893
|
let l = !1;
|
|
7804
|
-
const
|
|
7894
|
+
const u = () => {
|
|
7805
7895
|
l || (l = !0, a.remove(), document.body.style.overflow = c);
|
|
7806
7896
|
}, h = (C) => {
|
|
7807
|
-
|
|
7808
|
-
},
|
|
7809
|
-
|
|
7810
|
-
},
|
|
7897
|
+
u(), s(C);
|
|
7898
|
+
}, g = () => {
|
|
7899
|
+
u(), s(null);
|
|
7900
|
+
}, f = a.querySelector(".__crossx-card"), w = {
|
|
7811
7901
|
tooShort: (t == null ? void 0 : t.pinValidation_tooShort) ?? "Please enter a 6-digit PIN.",
|
|
7812
7902
|
numbersOnly: (t == null ? void 0 : t.pinValidation_numbersOnly) ?? "Only numbers (0-9) are allowed.",
|
|
7813
7903
|
repeatingDigit: (t == null ? void 0 : t.pinValidation_repeatingDigit) ?? "Cannot use the same number 3+ times in a row.",
|
|
@@ -7815,27 +7905,27 @@ class Xn {
|
|
|
7815
7905
|
alternatingPattern: (t == null ? void 0 : t.pinValidation_alternatingPattern) ?? "Repeating patterns (e.g., 121212) are not allowed."
|
|
7816
7906
|
}, v = (C) => {
|
|
7817
7907
|
var U;
|
|
7818
|
-
|
|
7908
|
+
f.innerHTML = nt({
|
|
7819
7909
|
title: i.title,
|
|
7820
7910
|
headerSubtitle: i.headerSubtitle
|
|
7821
|
-
}), (U =
|
|
7911
|
+
}), (U = f.querySelector("#__crossx-close-btn")) == null || U.addEventListener("click", g), ot(f, (N) => {
|
|
7822
7912
|
N === C ? h(C) : y(o.mismatchError);
|
|
7823
|
-
},
|
|
7913
|
+
}, g);
|
|
7824
7914
|
}, y = (C) => {
|
|
7825
7915
|
var U;
|
|
7826
|
-
|
|
7916
|
+
f.innerHTML = nt({
|
|
7827
7917
|
title: o.title,
|
|
7828
7918
|
headerSubtitle: o.headerSubtitle,
|
|
7829
7919
|
subtitle: o.subtitle,
|
|
7830
7920
|
errorMessage: C
|
|
7831
|
-
}), (U =
|
|
7921
|
+
}), (U = f.querySelector("#__crossx-close-btn")) == null || U.addEventListener("click", g), ot(f, (N) => {
|
|
7832
7922
|
const V = Vn(N, w);
|
|
7833
7923
|
V ? y(V) : v(N);
|
|
7834
|
-
},
|
|
7924
|
+
}, g);
|
|
7835
7925
|
};
|
|
7836
7926
|
(() => {
|
|
7837
7927
|
var q;
|
|
7838
|
-
const C = Array.from(
|
|
7928
|
+
const C = Array.from(f.querySelectorAll(".__crossx-pw-notice-item")), U = f.querySelector("#__crossx-pin-notice-next"), N = /* @__PURE__ */ new Set();
|
|
7839
7929
|
U.removeAttribute("disabled");
|
|
7840
7930
|
const V = U.dataset.nextLabel ?? "Next", W = U.dataset.submitLabel ?? "I Understand", P = () => {
|
|
7841
7931
|
const L = N.size === C.length;
|
|
@@ -7862,17 +7952,17 @@ class Xn {
|
|
|
7862
7952
|
return;
|
|
7863
7953
|
}
|
|
7864
7954
|
const L = C.find((A) => {
|
|
7865
|
-
const
|
|
7866
|
-
return !N.has(
|
|
7955
|
+
const _ = parseInt(A.dataset.checkIndex ?? "0", 10);
|
|
7956
|
+
return !N.has(_);
|
|
7867
7957
|
});
|
|
7868
7958
|
if (!L) return;
|
|
7869
7959
|
const R = parseInt(L.dataset.checkIndex ?? "0", 10);
|
|
7870
7960
|
L.scrollIntoView({ behavior: "smooth", block: "nearest" }), L.classList.add("--highlight"), setTimeout(() => {
|
|
7871
7961
|
L.classList.remove("--highlight"), k(L, R);
|
|
7872
7962
|
}, 400);
|
|
7873
|
-
}), (q =
|
|
7963
|
+
}), (q = f.querySelector("#__crossx-close-btn")) == null || q.addEventListener("click", g);
|
|
7874
7964
|
})(), a.addEventListener("click", (C) => {
|
|
7875
|
-
C.target === a &&
|
|
7965
|
+
C.target === a && g();
|
|
7876
7966
|
});
|
|
7877
7967
|
});
|
|
7878
7968
|
}
|
|
@@ -7895,18 +7985,18 @@ class Xn {
|
|
|
7895
7985
|
})
|
|
7896
7986
|
), l = document.body.style.overflow;
|
|
7897
7987
|
document.body.style.overflow = "hidden", pe(c);
|
|
7898
|
-
let
|
|
7988
|
+
let u = !1;
|
|
7899
7989
|
const h = () => {
|
|
7900
|
-
|
|
7901
|
-
},
|
|
7990
|
+
u || (u = !0, c.remove(), document.body.style.overflow = l);
|
|
7991
|
+
}, g = (S) => {
|
|
7902
7992
|
h(), s(S);
|
|
7903
|
-
},
|
|
7993
|
+
}, f = () => {
|
|
7904
7994
|
h(), s(null);
|
|
7905
7995
|
}, w = (S) => {
|
|
7906
7996
|
h(), t(S);
|
|
7907
7997
|
}, v = c.querySelector(".__crossx-card");
|
|
7908
|
-
(y = v.querySelector("#__crossx-close-btn")) == null || y.addEventListener("click",
|
|
7909
|
-
S.target === c &&
|
|
7998
|
+
(y = v.querySelector("#__crossx-close-btn")) == null || y.addEventListener("click", f), ot(v, g, f, w, e == null ? void 0 : e.onSubmit, e == null ? void 0 : e.lockExpiresAt), c.addEventListener("click", (S) => {
|
|
7999
|
+
S.target === c && f();
|
|
7910
8000
|
});
|
|
7911
8001
|
});
|
|
7912
8002
|
}
|
|
@@ -7950,8 +8040,8 @@ class Xn {
|
|
|
7950
8040
|
}, a = () => {
|
|
7951
8041
|
i(), t();
|
|
7952
8042
|
}, c = o(a);
|
|
7953
|
-
(l = n.querySelector("#__crossx-close-btn")) == null || l.addEventListener("click", a), n.addEventListener("click", (
|
|
7954
|
-
|
|
8043
|
+
(l = n.querySelector("#__crossx-close-btn")) == null || l.addEventListener("click", a), n.addEventListener("click", (u) => {
|
|
8044
|
+
u.target === n && a();
|
|
7955
8045
|
});
|
|
7956
8046
|
});
|
|
7957
8047
|
}
|
|
@@ -7969,11 +8059,11 @@ class Xn {
|
|
|
7969
8059
|
n(), s();
|
|
7970
8060
|
};
|
|
7971
8061
|
(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
|
-
|
|
8062
|
+
l.addEventListener("click", (u) => {
|
|
8063
|
+
var g;
|
|
8064
|
+
u.stopPropagation();
|
|
7975
8065
|
const h = l.dataset.copy;
|
|
7976
|
-
h && ((
|
|
8066
|
+
h && ((g = navigator.clipboard) == null || g.writeText(h).catch(() => {
|
|
7977
8067
|
}));
|
|
7978
8068
|
});
|
|
7979
8069
|
}), t.addEventListener("click", (l) => {
|
|
@@ -7999,12 +8089,12 @@ class Xn {
|
|
|
7999
8089
|
const a = () => {
|
|
8000
8090
|
i || (i = !0, o(), t());
|
|
8001
8091
|
}, c = () => {
|
|
8002
|
-
var
|
|
8003
|
-
(
|
|
8004
|
-
|
|
8092
|
+
var u, h;
|
|
8093
|
+
(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) => {
|
|
8094
|
+
g.target === n && a();
|
|
8005
8095
|
});
|
|
8006
|
-
const l = (
|
|
8007
|
-
|
|
8096
|
+
const l = (g) => {
|
|
8097
|
+
g.key === "Escape" && (document.removeEventListener("keydown", l), a());
|
|
8008
8098
|
};
|
|
8009
8099
|
document.addEventListener("keydown", l);
|
|
8010
8100
|
};
|
|
@@ -8015,7 +8105,7 @@ class Xn {
|
|
|
8015
8105
|
}
|
|
8016
8106
|
requestConfirmation(e) {
|
|
8017
8107
|
return new Promise((s) => {
|
|
8018
|
-
var c, l,
|
|
8108
|
+
var c, l, u;
|
|
8019
8109
|
he();
|
|
8020
8110
|
let t;
|
|
8021
8111
|
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 +8114,12 @@ class Xn {
|
|
|
8024
8114
|
}, i = () => {
|
|
8025
8115
|
n(), s(!1);
|
|
8026
8116
|
};
|
|
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", (
|
|
8117
|
+
(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) => {
|
|
8118
|
+
h.addEventListener("click", (g) => {
|
|
8029
8119
|
var w;
|
|
8030
|
-
|
|
8031
|
-
const
|
|
8032
|
-
|
|
8120
|
+
g.stopPropagation();
|
|
8121
|
+
const f = h.dataset.copy;
|
|
8122
|
+
f && ((w = navigator.clipboard) == null || w.writeText(f).catch(() => {
|
|
8033
8123
|
}));
|
|
8034
8124
|
});
|
|
8035
8125
|
}), t.addEventListener("click", (h) => {
|
|
@@ -8076,21 +8166,21 @@ function so(r, e) {
|
|
|
8076
8166
|
gatewayUrl: s.walletGatewayUrl,
|
|
8077
8167
|
projectId: r.projectId
|
|
8078
8168
|
}, o = t.authMode !== "cookie" && Ot.isAvailable();
|
|
8079
|
-
!o && t.authMode !== "cookie" &&
|
|
8169
|
+
!o && t.authMode !== "cookie" && d.warn(
|
|
8080
8170
|
"[CROSSx] IndexedDB 사용 불가 — LocalStorage fallback 사용 중.",
|
|
8081
8171
|
"refresh_token이 평문 저장되지 않도록 세션 영속성이 제한됩니다.",
|
|
8082
8172
|
"IndexedDB를 지원하는 브라우저 사용을 권장합니다."
|
|
8083
8173
|
), 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 ? (
|
|
8174
|
+
const i = o ? new Ot(r.projectId) : new rr(), a = new hn(), c = new xn(), l = new be(), u = new Zn(), h = new es();
|
|
8175
|
+
let g;
|
|
8176
|
+
r.useMockWallet ? (d.log("[CROSSx] Mock Wallet Provider 사용"), g = new mn(i, h)) : (d.log("[CROSSx] Remote Wallet Provider 사용"), g = new Le(
|
|
8087
8177
|
n,
|
|
8088
8178
|
i,
|
|
8089
8179
|
c,
|
|
8090
|
-
|
|
8180
|
+
u,
|
|
8091
8181
|
h
|
|
8092
8182
|
));
|
|
8093
|
-
const
|
|
8183
|
+
const f = new De(n, c), w = new Xn(r.theme ?? "light", r.themeTokens), v = e != null && e.wrapConfirmation ? e.wrapConfirmation(w) : w;
|
|
8094
8184
|
return new it(
|
|
8095
8185
|
t,
|
|
8096
8186
|
n,
|
|
@@ -8098,15 +8188,15 @@ function so(r, e) {
|
|
|
8098
8188
|
a,
|
|
8099
8189
|
c,
|
|
8100
8190
|
l,
|
|
8101
|
-
|
|
8102
|
-
|
|
8191
|
+
g,
|
|
8192
|
+
u,
|
|
8103
8193
|
v,
|
|
8104
|
-
|
|
8194
|
+
f,
|
|
8105
8195
|
h
|
|
8106
8196
|
);
|
|
8107
8197
|
}
|
|
8108
8198
|
export {
|
|
8109
|
-
|
|
8199
|
+
m as CROSSxError,
|
|
8110
8200
|
Fs as CROSSxEthereumProvider,
|
|
8111
8201
|
it as CROSSxSDK,
|
|
8112
8202
|
to as ChainId,
|