{"_id":"@abcwalletio/core","_rev":"3-bf05b42518b4c2b8919acbc0cba92a68","name":"@abcwalletio/core","dist-tags":{"latest":"1.1.1"},"versions":{"1.0.0":{"name":"@abcwalletio/core","version":"1.0.0","keywords":["waas","wallet-as-a-service","mpc","wallet","ethereum","web3","sdk","abc-wallet"],"author":{"name":"Ahnlab Blockchain Company"},"license":"MIT","_id":"@abcwalletio/core@1.0.0","maintainers":[{"name":"abc-admin","email":"abc_it@ahnlab.com"},{"name":"1kko-abc","email":"1kko@ahnlab.com"},{"name":"theo_ahnlabio","email":"theo@ahnlab.com"}],"homepage":"http://abcwaas.com/","dist":{"shasum":"0a06bc277f1af912e21f76643d09e39a942f8365","tarball":"https://registry.npmjs.org/@abcwalletio/core/-/core-1.0.0.tgz","fileCount":9,"integrity":"sha512-p1QzVDIDHHwkTbDsr4mfLh8PPkkscA96HApfxsvAgV1mgFgYZEqV1Py+QhhvL71PsnhoiqYkSLWBwQaUQyW2Vg==","signatures":[{"sig":"MEQCIHJbeCarEnrWhFnvGUPDSxX9aHyrPYIxs0q3NNDFKwDoAiBMMq9fq++hsnDZDIEYKk96tZSLwL7BDrApgHzV0KrMUQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":474745},"main":"./dist/index.cjs","type":"module","_from":"file:abcwalletio-core-1.0.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"theo_ahnlabio","email":"theo@ahnlab.com"},"_resolved":"/private/var/folders/lt/4x5qd11x2wl8sh4gvr7y0pp80000gn/T/b81db225b4c6113e70953e4106d2aee7/abcwalletio-core-1.0.0.tgz","_integrity":"sha512-p1QzVDIDHHwkTbDsr4mfLh8PPkkscA96HApfxsvAgV1mgFgYZEqV1Py+QhhvL71PsnhoiqYkSLWBwQaUQyW2Vg==","_npmVersion":"11.6.2","description":"ABC WaaS core SDK — MPC-based wallet authentication, signing, and storage primitives","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","dependencies":{"crypto-js":"^4.2.0","@noble/curves":"^1.9.2","@noble/hashes":"^1.8.0","eventemitter3":"^5.0.1","@abcwalletio/mpc-wasm":"^0.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.4.0","typescript":"^5.4.0","@types/crypto-js":"^4.2.2"},"_npmOperationalInternal":{"tmp":"tmp/core_1.0.0_1776818558098_0.13354919694107137","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@abcwalletio/core","version":"1.1.0","keywords":["waas","wallet-as-a-service","mpc","wallet","ethereum","web3","sdk","abc-wallet"],"author":{"name":"Ahnlab Blockchain Company"},"license":"MIT","_id":"@abcwalletio/core@1.1.0","maintainers":[{"name":"abc-admin","email":"abc_it@ahnlab.com"},{"name":"1kko-abc","email":"1kko@ahnlab.com"},{"name":"theo_ahnlabio","email":"theo@ahnlab.com"}],"homepage":"http://abcwaas.com/","dist":{"shasum":"63c37fc658127d965c9291092b30277c04ec59f2","tarball":"https://registry.npmjs.org/@abcwalletio/core/-/core-1.1.0.tgz","fileCount":9,"integrity":"sha512-aNLv8H8wH8gCZWvXXCaLbLoPU5smvF0ySOlGfqTwOzUqCYuU1/dIvmff01DELp/3W8G9Fhdj8wOvd8VUlMvojQ==","signatures":[{"sig":"MEUCIG5dLSn5+dm7iiJ2GEoA+3SLvLPhg6AzVF4/jL0nLXtBAiEA3Ld7Skolv6JbNVjL2XtMd+NykKx1VnsXRUNM0Y+xOfw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":479202},"main":"./dist/index.cjs","type":"module","_from":"file:abcwalletio-core-1.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"theo_ahnlabio","email":"theo@ahnlab.com"},"_resolved":"/private/var/folders/lt/4x5qd11x2wl8sh4gvr7y0pp80000gn/T/b269661f7fb2a12bf9c98886bac24f1e/abcwalletio-core-1.1.0.tgz","_integrity":"sha512-aNLv8H8wH8gCZWvXXCaLbLoPU5smvF0ySOlGfqTwOzUqCYuU1/dIvmff01DELp/3W8G9Fhdj8wOvd8VUlMvojQ==","_npmVersion":"11.6.2","description":"ABC WaaS core SDK — MPC-based wallet authentication, signing, and storage primitives","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","dependencies":{"crypto-js":"^4.2.0","@noble/curves":"^1.9.2","@noble/hashes":"^1.8.0","eventemitter3":"^5.0.1","@abcwalletio/mpc-wasm":"^0.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.4.0","typescript":"^5.4.0","@types/crypto-js":"^4.2.2"},"_npmOperationalInternal":{"tmp":"tmp/core_1.1.0_1779846891860_0.5404818413758798","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@abcwalletio/core","version":"1.1.1","description":"ABC WaaS core SDK — MPC-based wallet authentication, signing, and storage primitives","keywords":["waas","wallet-as-a-service","mpc","wallet","ethereum","web3","sdk","abc-wallet"],"license":"MIT","author":{"name":"Ahnlab Blockchain Company"},"homepage":"http://abcwaas.com/","publishConfig":{"access":"public"},"engines":{"node":">=18.0.0"},"sideEffects":false,"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"dependencies":{"@noble/curves":"^1.9.2","@noble/hashes":"^1.8.0","crypto-js":"^4.2.0","eventemitter3":"^5.0.1","@abcwalletio/mpc-wasm":"^0.3.2"},"devDependencies":{"@types/crypto-js":"^4.2.2","tsup":"^8.0.0","typescript":"^5.4.0","vitest":"^1.4.0"},"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","test":"vitest run"},"_id":"@abcwalletio/core@1.1.1","_integrity":"sha512-CR77VLdT1tVCNrP88MieznroS275Qw4WPTFXx3xmMU044ppjS/jba8zXQqjULegQHSN0XsLtVbWtxYSIk/9c7Q==","_resolved":"/private/var/folders/lt/4x5qd11x2wl8sh4gvr7y0pp80000gn/T/e4f93126887d9bd4fd549bf2420ab2e1/abcwalletio-core-1.1.1.tgz","_from":"file:abcwalletio-core-1.1.1.tgz","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-CR77VLdT1tVCNrP88MieznroS275Qw4WPTFXx3xmMU044ppjS/jba8zXQqjULegQHSN0XsLtVbWtxYSIk/9c7Q==","shasum":"880d5bb75edfc4b046a703e21514d0b04a46df63","tarball":"https://registry.npmjs.org/@abcwalletio/core/-/core-1.1.1.tgz","fileCount":9,"unpackedSize":479202,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDa1d7tWAv8JbRDvQIU+ayWPfdNAhyNOzyb0ccOOy15nwIhAPRQPdvFqQtUglt1BlXCj/wrlMNLUAMr4s+MbnDmxcEn"}]},"_npmUser":{"name":"theo_ahnlabio","email":"theo@ahnlab.com"},"directories":{},"maintainers":[{"name":"abc-admin","email":"abc_it@ahnlab.com"},{"name":"1kko-abc","email":"1kko@ahnlab.com"},{"name":"theo_ahnlabio","email":"theo@ahnlab.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/core_1.1.1_1779957956497_0.6901226539961023"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-22T00:42:37.991Z","modified":"2026-05-28T08:45:56.835Z","1.0.0":"2026-04-22T00:42:38.319Z","1.1.0":"2026-05-27T01:54:52.030Z","1.1.1":"2026-05-28T08:45:56.665Z"},"author":{"name":"Ahnlab Blockchain Company"},"license":"MIT","homepage":"http://abcwaas.com/","keywords":["waas","wallet-as-a-service","mpc","wallet","ethereum","web3","sdk","abc-wallet"],"description":"ABC WaaS core SDK — MPC-based wallet authentication, signing, and storage primitives","maintainers":[{"name":"abc-admin","email":"abc_it@ahnlab.com"},{"name":"1kko-abc","email":"1kko@ahnlab.com"},{"name":"theo_ahnlabio","email":"theo@ahnlab.com"}],"readme":"# @abcwalletio/core\n\nABC Wallet-as-a-Service 핵심 SDK입니다. MPC(Multi-Party Computation) 기반 지갑 생성, 인증, 서명 기능을 제공합니다.\n\n## Installation\n\n```bash\npnpm add @abcwalletio/core\n```\n\n## Quick Start\n\n```typescript\nimport { createWaasSDK, MemoryStorage } from '@abcwalletio/core';\n\n// SDK 초기화\nconst sdk = await createWaasSDK({\n  storage: new MemoryStorage(),\n  auth: {\n    v2: {\n      clientId: 'your-client-id',\n      clientSecret: 'your-client-secret',\n    },\n  },\n});\n\n// WASM 초기화 확인\nif (sdk.isReady()) {\n  console.log('SDK is ready!');\n}\n```\n\n## Modules\n\n### Auth Module\n\n인증 모듈은 두 가지 경로를 제공합니다 — 동일 SDK 인스턴스에서 **공존 가능**합니다.\n\n| 경로 | 구조 | 적합한 경우 |\n|------|------|------------|\n| **V2** (Secure Channel) | 브라우저가 이메일/비밀번호를 암호화해 WaaS에 직접 로그인 | 백엔드 없는 SPA, 간단한 통합, PoC |\n| **V3** (TokenProvider 주입) | 고객사 **백엔드**가 `/auth-service/v3/login`으로 토큰을 발급해 프론트로 전달 | 자체 인증 스택이 있는 엔터프라이즈 |\n\n```typescript\n// ─────────────────────────────────────────────────────────\n// V3 인증 — TokenProvider 주입\n// ─────────────────────────────────────────────────────────\n// V3만 사용하면 clientSecret이 브라우저에 필요 없다.\nconst sdk = await createWaasSDK({\n  storage,\n  auth: {\n    v3: {\n      tokenProvider: async () => {\n        // 고객사 백엔드가 자체 세션을 검증하고 WaaS 토큰을 대신 발급\n        const r = await fetch('/api/waas/token', { credentials: 'include' });\n        if (!r.ok) throw new Error('unauthorized');\n        const { access_token, expires_in } = await r.json();\n        return { accessToken: access_token, expiresIn: expires_in };\n      },\n      // 선택: 만료 몇 초 전에 재발급할지 (기본 300초)\n      refreshThresholdSec: 300,\n    },\n  },\n});\n\n// 필요 시 명시적 토큰 확보 (자동 발급 포함)\nconst token = await sdk.auth.v3.getValidAccessToken();\n\n// ─────────────────────────────────────────────────────────\n// V2 인증 — Secure Channel 기반 (이메일/비밀번호)\n// ─────────────────────────────────────────────────────────\nconst result = await sdk.auth.v2.loginWithEmail('user@example.com', 'password');\n\n// 회원가입\nawait sdk.auth.v2.sendVerificationCode('user@example.com');\nawait sdk.auth.v2.registerWithEmail({\n  email: 'user@example.com',\n  password: 'password123',\n  verificationCode: '123456',\n});\n\n// 비밀번호 초기화\nawait sdk.auth.v2.sendResetPasswordCode('user@example.com');\nawait sdk.auth.v2.resetPassword('user@example.com', '123456', 'newPassword');\n\n// ─────────────────────────────────────────────────────────\n// 공통 기능 — V3/V2 어느 쪽이든 인증되면 성립\n// ─────────────────────────────────────────────────────────\n// 로컬 토큰 존재 여부 확인 (서버 왕복 없음)\nconst isAuthV3 = await sdk.auth.v3.isAuthenticated();  // V3 tokenProvider 활성 + 발급 성공\nconst isAuthV2 = await sdk.auth.v2.isAuthenticated();\n\n// 서버 측 세션 유효성까지 검증 (getWalletUser 경로)\nconst serverOk = await sdk.verifyServerSession();\n\n// 현재 사용자 정보 — V3는 user 정보를 보관하지 않으므로 V2만 조회\nconst user = await sdk.auth.v2.getUser();\n\n// Access Token 가져오기 — V3 활성이면 필요 시 자동 발급 후 반환, 아니면 V2 폴백\nconst token = await sdk.auth.getAccessToken();\n\n// SDK 레벨 로그아웃: abc_waas_* prefix 키만 삭제 + v3/v2 토큰 정리 + 'logout' broadcast\nawait sdk.logout();\n\n// 또는 특정 모듈만 정리\nawait sdk.auth.v3.logout();  // V3 메모리 캐시 정리 + 'logout' 이벤트\nawait sdk.auth.v2.logout();\n```\n\n> **서버 세션 무효화 범위**\n> 현재 backend는 refresh token revocation endpoint를 제공하지 않습니다.\n> `logout()` 이후에도 refresh token은 TTL이 만료될 때까지 서버 측에서 유효합니다.\n> 토큰 유출 위험 환경에서는 호출측에서 별도 세션 파기 플로우를 추가하세요.\n\n### MPC Module\n\nMPC 키 생성 및 서명 기능을 제공합니다.\n\n```typescript\n// 키 생성\nconst keyResult = await sdk.mpc.generateKeyShare(\n  'secp256k1', // curve: 'secp256k1' | 'ed25519'\n  'password123' // 비밀번호 (8자 이상)\n);\nconsole.log('Key ID:', keyResult.keyId);\nconsole.log('Public Key:', keyResult.publicKey);\n\n// 키 복구 (기존 키가 있는 경우)\nconst recovered = await sdk.mpc.recoverKeyShare(\n  'secp256k1',\n  'password123'\n);\n\n// 일반 서명 (secp256k1 + ed25519)\nconst signResult = await sdk.mpc.sign(keyId, messageHash, 'password123');\nconsole.log('Signature:', signResult.signature);\n\n// MTA 서명 (secp256k1 전용, 더 효율적)\nconst mtaResult = await sdk.mpc.signMta(keyId, messageHash, 'password123');\nconsole.log('Signature:', mtaResult.signature);\n\n// 자동 서명 — curve에 따라 최적 방식 선택 (secp256k1 → signMta, ed25519 → sign)\nconst autoResult = await sdk.mpc.signAuto(keyId, messageHash, 'password123');\n\n// 공개키 조회\nconst publicKey = await sdk.mpc.getPublicKey(keyId);\n\n// 비밀번호 검증\nconst isValid = await sdk.mpc.validatePassword('password123');\n\n// Share 유효성 검증\nconst shareValid = await sdk.mpc.validateShare('password123');\n```\n\n### Wallet API Module\n\nV3 Wallet API를 호출합니다.\n\n```typescript\n// 지갑 정보 조회\nconst wallet = await sdk.wallet.getWallet();\n\n// 지갑 키 목록 조회\nconst keys = await sdk.wallet.getWalletKeys();\n\n// 지갑 사용자 정보 조회\nconst user = await sdk.wallet.getWalletUser();\n\n// 지갑 토큰 발급 (MPC 노드 인증용)\nconst walletToken = await sdk.wallet.getWalletToken(keyId);\n\n// 새 키 등록\nawait sdk.wallet.registerWalletKey(keyId, curve, publicKey);\n```\n\n## Storage\n\n다양한 Storage 구현체를 제공합니다. 모두 `StorageInterface`를 구현합니다.\n\n### MemoryStorage\n\n인메모리 저장소입니다. 테스트나 SSR 환경에서 사용합니다.\n\n```typescript\nimport { MemoryStorage } from '@abcwalletio/core';\n\nconst storage = new MemoryStorage();\n```\n\n### LocalStorageAdapter\n\n`window.localStorage`를 래핑합니다. 영구 저장이 필요한 브라우저 환경에서 사용합니다.\n\n```typescript\nimport { LocalStorageAdapter } from '@abcwalletio/core';\n\nconst storage = new LocalStorageAdapter();\n```\n\n### SessionStorageAdapter\n\n`window.sessionStorage`를 래핑합니다. 세션 단위 저장이 필요한 경우 사용합니다.\n\n```typescript\nimport { SessionStorageAdapter } from '@abcwalletio/core';\n\nconst storage = new SessionStorageAdapter();\n```\n\n### IndexedDBStorage\n\nIndexedDB 기반 저장소입니다. 대용량 데이터나 더 안전한 저장이 필요한 경우 사용합니다.\n\n```typescript\nimport { IndexedDBStorage } from '@abcwalletio/core';\n\nconst storage = new IndexedDBStorage();\nawait storage.waitForInit(); // 비동기 초기화 대기\n\n// 초기화 상태 확인\nif (storage.ready) {\n  console.log('IndexedDB is ready');\n}\n\n// 사용 후 정리\nstorage.close();\n```\n\n### BridgeStorage\n\n모바일 앱의 웹뷰에서 네이티브 앱과 통신하기 위한 비동기 저장소입니다. `AsyncStorageInterface`를 구현합니다.\n\n```typescript\nimport { BridgeStorage } from '@abcwalletio/core';\n\n// 기본 사용법 (window.abcWaas.storage 자동 참조)\nconst storage = new BridgeStorage();\n\n// 커스텀 storageKey 사용\nconst storage = new BridgeStorage({ storageKey: 'myCustomBridge' });\n\n// 커스텀 핸들러 직접 주입\nconst storage = new BridgeStorage({ handler: myCustomHandler });\n\n// 비동기 API 사용\nconst value = await storage.getItem('key');\nawait storage.setItem('key', 'value');\nawait storage.removeItem('key');\nawait storage.clear();\n```\n\n#### 네이티브 앱 개발자 가이드\n\n네이티브 앱에서 웹뷰에 브릿지를 주입해야 합니다.\n\n**1. window.abcWaas.storage 주입**\n\n```javascript\n// 네이티브 앱에서 웹뷰에 주입할 객체\nwindow.abcWaas = {\n  storage: {\n    // 필수: ABC WaaS 브릿지 마커 메서드\n    isAbcWaasBridge: () => Promise.resolve(true),\n\n    // 필수: Storage 메서드들\n    getItem: (key) => { /* Promise<string | null> 반환 */ },\n    setItem: (key, value) => { /* Promise<void> 반환 */ },\n    removeItem: (key) => { /* Promise<void> 반환 */ },\n\n    // 선택: 추가 메서드\n    clear: () => { /* Promise<void> 반환 */ },\n    getAllKeys: () => { /* Promise<string[]> 반환 */ },\n  }\n};\n```\n\n**2. 필수 메서드**\n\nSDK는 `REQUIRED_BRIDGE_METHODS` 상수로 필수 메서드를 정의합니다:\n\n```typescript\nimport { REQUIRED_BRIDGE_METHODS } from '@abcwalletio/core';\n// ['isAbcWaasBridge', 'getItem', 'setItem', 'removeItem']\n```\n\n- `isAbcWaasBridge()`: 유효한 ABC WaaS 브릿지임을 확인하는 마커 메서드. 반드시 `Promise<true>`를 반환해야 합니다.\n- `getItem(key)`: 키에 해당하는 값을 반환\n- `setItem(key, value)`: 키-값 쌍을 저장\n- `removeItem(key)`: 키에 해당하는 값을 삭제\n\n**3. AsyncBridgeHandler 인터페이스**\n\n```typescript\nimport type { AsyncBridgeHandler } from '@abcwalletio/core';\n\nconst handler: AsyncBridgeHandler = {\n  isAbcWaasBridge: () => Promise.resolve(true),\n  getItem: (key) => nativeStorage.get(key),\n  setItem: (key, value) => nativeStorage.set(key, value),\n  removeItem: (key) => nativeStorage.delete(key),\n  // prefix-aware clear 또는 getAllKeys 중 **하나는 반드시 제공** 필요.\n  // 둘 다 없으면 페이지 새로고침 후 `sdk.logout()`이 영속 키를 못 지움.\n  clear: (prefix) => nativeStorage.clear(prefix),   // 선택 (prefix 인자 받음)\n  getAllKeys: () => nativeStorage.keys(),           // 선택 (권장)\n};\n```\n\n### Custom Storage\n\n`StorageInterface`를 직접 구현할 수도 있습니다. 모든 메서드가 비동기입니다.\n\n```typescript\nimport type { StorageInterface } from '@abcwalletio/core';\n\nclass CustomStorage implements StorageInterface {\n  async getItem(key: string): Promise<string | null> { /* ... */ }\n  async setItem(key: string, value: string): Promise<void> { /* ... */ }\n  async removeItem(key: string): Promise<void> { /* ... */ }\n  /**\n   * prefix가 있으면 해당 prefix로 시작하는 키만, 없으면 전체 삭제.\n   * 빈 문자열 prefix는 throw해야 합니다 (전체와 구분 모호).\n   */\n  async clear(prefix?: string): Promise<void> { /* ... */ }\n}\n```\n\n### AsyncStorageInterface (Deprecated)\n\n`StorageInterface`의 별칭입니다. 하위 호환을 위해 유지되며, 새 코드에서는\n`StorageInterface`를 직접 사용하세요.\n\n## Event System\n\nSDK는 이벤트 시스템을 통해 인증 상태 변화를 알립니다.\n\n### 이벤트 타입\n\n| Event | Payload | Description |\n|-------|---------|-------------|\n| `tokenRefreshed` | `{ accessToken, refreshToken }` | 토큰이 자동 갱신되었을 때 |\n| `authError` | `{ error: WaasError }` | 인증 관련 에러 발생 시 |\n| `logout` | `void` | 로그아웃 시 |\n\n### 이벤트 구독/해제\n\n```typescript\nimport { createWaasSDK, type WaasEventHandler } from '@abcwalletio/core';\n\nconst sdk = await createWaasSDK({ ... });\n\n// 이벤트 핸들러 정의\nconst handleTokenRefreshed: WaasEventHandler<'tokenRefreshed'> = (payload) => {\n  console.log('토큰이 갱신되었습니다:', payload.accessToken);\n};\n\nconst handleAuthError: WaasEventHandler<'authError'> = (payload) => {\n  console.error('인증 에러:', payload.error.message);\n  // 로그인 페이지로 이동 등의 처리\n};\n\nconst handleLogout: WaasEventHandler<'logout'> = () => {\n  console.log('로그아웃되었습니다');\n  // UI 상태 초기화 등\n};\n\n// 이벤트 구독\nsdk.on('tokenRefreshed', handleTokenRefreshed);\nsdk.on('authError', handleAuthError);\nsdk.on('logout', handleLogout);\n\n// 이벤트 해제\nsdk.off('tokenRefreshed', handleTokenRefreshed);\n```\n\n## Auto Token Refresh\n\nSDK는 JWT 토큰 자동 갱신 기능을 제공합니다. `getValidAccessToken()` 메서드를\n사용하면 토큰 만료를 자동으로 처리합니다. V2와 V3의 갱신 방식이 다릅니다.\n\n| 경로 | 갱신 방식 | 저장소 |\n|------|----------|--------|\n| V2 | `refresh_token`을 서버에 제출해 access token 재발급 | Storage(localStorage 등) |\n| V3 | `tokenProvider`를 재호출해 고객사 백엔드에서 새 토큰을 가져옴 | 메모리만 (Storage 미저장) |\n\n### V2 사용법\n\n```typescript\ntry {\n  const accessToken = await sdk.auth.v2.getValidAccessToken();\n  // accessToken을 사용한 API 호출\n} catch (error) {\n  console.error('인증 필요:', error);\n}\n```\n\n### V3 사용법\n\n```typescript\ntry {\n  const accessToken = await sdk.auth.v3.getValidAccessToken();\n  // 만료 임박 시 SDK가 자동으로 tokenProvider를 재호출해 새 토큰을 발급받음\n} catch (error) {\n  console.error('tokenProvider 호출 실패:', error);\n}\n```\n\n### 동작 방식\n\n1. **토큰 유효성 검사**: 현재 Access Token의 만료 시간 확인\n2. **자동 갱신**:\n   - V2 — 만료 5분 전이면 Refresh Token으로 자동 갱신\n   - V3 — 만료 `refreshThresholdSec`초 전(기본 300)이면 `tokenProvider` 재호출\n     (동시 호출은 싱글플라이트로 1회만 실행)\n3. **이벤트 발생**: 갱신 성공 시 `tokenRefreshed` 이벤트 발생\n4. **에러 처리**: 갱신 실패 시 `authError` 이벤트 발생 후 자동 로그아웃\n\n### 자동 갱신 흐름\n\n```\ngetValidAccessToken() 호출\n    │\n    ▼\n토큰 존재 확인 ──No──▶ authError 이벤트 + 에러 throw\n    │\n   Yes\n    ▼\n만료 5분 전? ──No──▶ 현재 토큰 반환\n    │\n   Yes\n    ▼\nrefreshToken() 호출\n    │\n    ├─Success─▶ tokenRefreshed 이벤트 + 새 토큰 반환\n    │\n    └─Failure─▶ authError 이벤트 + logout 이벤트 + 에러 throw\n```\n\n### 수동 토큰 갱신\n\n필요한 경우 수동으로 토큰을 갱신할 수 있습니다.\n\n```typescript\nconst result = await sdk.auth.v2.refreshToken();\n\nif (result.success) {\n  console.log('새 토큰:', result.accessToken);\n} else {\n  console.error('갱신 실패:', result.error);\n  // 갱신 실패 시 자동으로 logout 이벤트가 발생합니다\n}\n```\n\n## Storage Keys\n\nSDK가 내부적으로 사용하는 Storage 키입니다. 모두 `abc_waas_` prefix를 공유하며,\n`sdk.logout()`은 이 prefix 범위만 정리해 호스트 앱의 다른 localStorage 데이터를\n보존합니다.\n\n| Key | Description |\n|-----|-------------|\n| `abc_waas_shares` | MPC 쉐어 번들 (curve별 ShareData를 JSON으로 묶어 저장) |\n| `abc_waas_auth_token` | V2 Access Token |\n| `abc_waas_refresh_token` | V2 Refresh Token |\n| `abc_waas_user` | V2 사용자 정보 |\n\n> V3는 토큰을 Storage에 저장하지 않습니다. 새로고침 시 `tokenProvider`가 다시\n> 호출되어 메모리 캐시를 복구합니다.\n\n## Error Handling\n\nSDK는 `WaasError` 클래스를 통해 에러를 처리합니다.\n\n```typescript\nimport { WaasError, WaasErrorCode } from '@abcwalletio/core';\n\ntry {\n  await sdk.mpc.generateKeyShare('secp256k1', 'password');\n} catch (error) {\n  if (error instanceof WaasError) {\n    console.log('Code:', error.code);\n    console.log('Message:', error.message);\n    console.log('Details:', error.details);\n\n    switch (error.code) {\n      case WaasErrorCode.AUTH_FAILED:\n        // 인증 실패 처리\n        break;\n      case WaasErrorCode.MPC_SHARE_NOT_FOUND:\n        // Share 없음 처리\n        break;\n      // ...\n    }\n  }\n}\n```\n\n### API 레벨 에러 처리\n\nSDK는 HTTP 200 응답이라도 응답 body에 에러 코드가 포함된 경우 자동으로 감지하여 처리합니다.\n\n#### API 에러 응답 형식\n\n서버에서 반환하는 API 레벨 에러 응답 형식:\n\n```typescript\ninterface ApiErrorResponse {\n  code: string;    // \"103\", \"104\" 등 문자열\n  message: string; // \"JWT_EXPIRED\", \"INVALID_TOKEN\" 등\n}\n```\n\n#### 지원하는 API 에러 코드\n\n| API 에러 코드 | 메시지 | SDK 에러 코드 | 설명 |\n|--------------|--------|--------------|------|\n| 103 | JWT_EXPIRED | `AUTH_EXPIRED` | JWT 토큰 만료 - 자동 갱신 시도 |\n| 104 | INVALID_TOKEN | `AUTH_INVALID_TOKEN` | 유효하지 않은 토큰 |\n\n#### HTTP 상태 코드 기반 자동 갱신\n\n| HTTP 상태 코드 | SDK 에러 코드 | 설명 |\n|---------------|--------------|------|\n| 401 Unauthorized | `AUTH_EXPIRED` | 인증 만료 - 자동 갱신 시도 |\n| 403 Forbidden | `AUTH_FAILED` | 접근 권한 없음 - 자동 갱신 시도 |\n\nHTTP 401/403 응답 시에도 JWT 만료와 동일하게 토큰 갱신을 시도합니다.\n\n#### JWT 만료 시 자동 재시도\n\nJWT가 만료된 경우(`code: \"103\"`), SDK는 자동으로 다음 과정을 수행합니다:\n\n1. Refresh Token을 사용하여 새로운 Access Token 발급 시도\n2. 갱신 성공 시 원래 요청을 새 토큰으로 1회 재시도\n3. 갱신 실패 시 `AUTH_EXPIRED` 에러 발생 및 `authError` 이벤트 emit\n\n```\nAPI 요청 → HTTP 200 + { code: \"103\" } 응답\n    │\n    ▼\n토큰 갱신 시도 (refreshToken)\n    │\n    ├─ 성공 → 원래 요청 재시도 (새 토큰으로)\n    │           │\n    │           ├─ 성공 → 정상 결과 반환\n    │           └─ 실패 → 에러 throw\n    │\n    └─ 실패 → authError 이벤트 + AUTH_EXPIRED 에러 throw\n```\n\n#### 에러 처리 예시\n\n```typescript\nimport { WaasError, WaasErrorCode } from '@abcwalletio/core';\n\n// authError 이벤트 구독\nsdk.on('authError', (payload) => {\n  if (payload.error.code === WaasErrorCode.AUTH_EXPIRED) {\n    // 토큰 만료로 인한 갱신 실패\n    // 로그인 페이지로 이동 등의 처리\n    console.log('세션이 만료되었습니다. 다시 로그인해주세요.');\n  }\n});\n\ntry {\n  const walletToken = await sdk.wallet.getWalletToken(keyId);\n} catch (error) {\n  if (error instanceof WaasError) {\n    switch (error.code) {\n      case WaasErrorCode.AUTH_EXPIRED:\n        // JWT 만료 및 갱신 실패\n        break;\n      case WaasErrorCode.AUTH_INVALID_TOKEN:\n        // 유효하지 않은 토큰\n        break;\n    }\n  }\n}\n```\n\n### Error Codes\n\n| Category | Code Range | Description |\n|----------|------------|-------------|\n| AUTH | 1000-1999 | 인증 관련 에러 |\n| WALLET | 2000-2999 | 지갑 관련 에러 |\n| MPC | 3000-3999 | MPC 연산 에러 |\n| STORAGE | 4000-4999 | Storage 에러 |\n| NETWORK | 5000-5999 | 네트워크 에러 |\n| PROVIDER | 6000-6999 | Provider 에러 |\n| WASM | 7000-7999 | WASM 에러 |\n\n## Configuration\n\n### Environment\n\nSDK는 **프로덕션 환경** (`https://api.waas.myabcwallet.com`)에 고정됩니다.\n`environment`는 공개 설정 필드가 아닙니다.\n\n## TypeScript Types\n\n```typescript\nimport type {\n  // SDK\n  WaasSDK,\n  WaasSDKConfig,\n  Environment,\n  CurveType,\n\n  // Auth\n  AuthModule,\n  AuthProvider,\n  User,\n  AuthResult,\n\n  // MPC\n  MpcModule,\n  GenerateShareResult,\n  RecoverShareResult,\n  SignResult,\n\n  // Wallet API\n  WalletApiModule,\n  WalletInfo,\n  WalletKey,\n  WalletUser,\n\n  // Storage\n  StorageInterface,\n  AsyncStorageInterface,\n  AsyncBridgeHandler,\n  BridgeStorageOptions,\n\n  // Error\n  WaasError,\n  WaasErrorCode,\n} from '@abcwalletio/core';\n```\n\n## License\n\nMIT — Copyright (c) 2026 Ahnlab Blockchain Company\n","readmeFilename":"README.md"}