{"_id":"@altscodex/sdk","_rev":"4-f52b5155f9ee0c89ac33523cd57a020f","name":"@altscodex/sdk","dist-tags":{"latest":"3.0.0"},"versions":{"2.0.0":{"name":"@altscodex/sdk","version":"2.0.0","keywords":["altscodex","deoauth","oauth","sdk","blockchain","login","jwt","account-abstraction"],"author":{"name":"altscodex"},"license":"MIT","_id":"@altscodex/sdk@2.0.0","maintainers":[{"name":"banstorm","email":"cgman119@naver.com"}],"homepage":"https://developers.altscodex.com","bugs":{"url":"https://developers.altscodex.com"},"dist":{"shasum":"bc888e873032a886862c4a67c1d42165c93635f5","tarball":"https://registry.npmjs.org/@altscodex/sdk/-/sdk-2.0.0.tgz","fileCount":4,"integrity":"sha512-bbnsD7XnVs2PMHXq68RnQ4h9NYpIrtdFSCPnPCcIMLdkqXeEqPqw1wTJmcSG4PMRiyunbp+TkzWtzIN7b+bu3Q==","signatures":[{"sig":"MEYCIQCt4ZUCf1kOIHutVWHwADT7itxRKR8/5SlbNXplN4crWwIhAJzKn6ACaQ3NkveIbE8trQOTBnGaORmmSDLRrXlNECsi","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28152},"main":"src/index.js","exports":{".":"./src/index.js","./backend":"./src/backend.js"},"gitHead":"d8806a64008292a7e0576450d89c58d2b1589c59","scripts":{"test":"jest --verbose"},"_npmUser":{"name":"banstorm","email":"cgman119@naver.com"},"_npmVersion":"10.8.2","description":"AltsCodex DeOAuth SDK — integrate AltsCodex decentralized OAuth login into any app","directories":{},"_nodeVersion":"18.20.8","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0"},"peerDependencies":{"express":">=4.0.0"},"peerDependenciesMeta":{"express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sdk_2.0.0_1777792549964_0.33601820558665874","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@altscodex/sdk","version":"2.1.0","keywords":["altscodex","deoauth","oauth","sdk","blockchain","login","jwt","account-abstraction"],"author":{"name":"altscodex"},"license":"MIT","_id":"@altscodex/sdk@2.1.0","maintainers":[{"name":"banstorm","email":"cgman119@naver.com"}],"homepage":"https://developers.altscodex.com","bugs":{"url":"https://developers.altscodex.com"},"dist":{"shasum":"b7ceb12abeec40197fbb31cdf7fe7179dc36e608","tarball":"https://registry.npmjs.org/@altscodex/sdk/-/sdk-2.1.0.tgz","fileCount":4,"integrity":"sha512-Mj0U4MUtMreesGQsGzOyZTs2bvLX5sB4H7vbofxCwJ/KK7f8P90dMhf57Ilqdww+s301x5UGEYANYMDKhuAciQ==","signatures":[{"sig":"MEUCIQDw1gDt37QcJBr+afwc4RhD2qVmEbitDJ9djYWK0yWqwgIgVuS6Nkxz1KBdHy8Ers4ZuzBOVtSW4bF533unPnK3FEA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":32470},"main":"src/index.js","exports":{".":"./src/index.js","./backend":"./src/backend.js"},"gitHead":"3b950029372d76ecf5f8f3288e19089afaf82cc0","scripts":{"test":"jest --verbose"},"_npmUser":{"name":"banstorm","email":"cgman119@naver.com"},"_npmVersion":"10.8.2","description":"AltsCodex DeOAuth SDK — integrate AltsCodex decentralized OAuth login into any app","directories":{},"_nodeVersion":"18.20.8","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0"},"peerDependencies":{"express":">=4.0.0"},"peerDependenciesMeta":{"express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sdk_2.1.0_1777858355072_0.9332972058198461","host":"s3://npm-registry-packages-npm-production"}},"2.1.1":{"name":"@altscodex/sdk","version":"2.1.1","keywords":["altscodex","deoauth","oauth","sdk","blockchain","login","jwt","account-abstraction"],"author":{"name":"altscodex"},"license":"MIT","_id":"@altscodex/sdk@2.1.1","maintainers":[{"name":"banstorm","email":"cgman119@naver.com"}],"homepage":"https://developers.altscodex.com","bugs":{"url":"https://developers.altscodex.com"},"dist":{"shasum":"96863234d5b4cd4f50591170b57e62a8899daaa3","tarball":"https://registry.npmjs.org/@altscodex/sdk/-/sdk-2.1.1.tgz","fileCount":4,"integrity":"sha512-DI+IaW6pe7hlj9n5OxiAy1AFEWwW9Ll1rphce+kXNVFa5m7oTrsr3iu8GZOe+dExxTYWvdbQ4cKNYAY63dBJMw==","signatures":[{"sig":"MEUCIBJSwphu7vSFlLImym2YT59v0L8xP4uACzhf6UKZeh3HAiEAkfOcJxLRABhqDTyif1Ji6ZqURHANmXCrIRKHKcfGZlc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33294},"main":"src/index.js","exports":{".":"./src/index.js","./backend":"./src/backend.js"},"gitHead":"3b950029372d76ecf5f8f3288e19089afaf82cc0","scripts":{"test":"jest --verbose"},"_npmUser":{"name":"banstorm","email":"cgman119@naver.com"},"_npmVersion":"10.8.2","description":"AltsCodex DeOAuth SDK — integrate AltsCodex decentralized OAuth login into any app","directories":{},"_nodeVersion":"18.20.8","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0"},"peerDependencies":{"express":">=4.0.0"},"peerDependenciesMeta":{"express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sdk_2.1.1_1781177290651_0.5380044278022327","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@altscodex/sdk","version":"3.0.0","description":"AltsCodex DeOAuth SDK — integrate AltsCodex decentralized OAuth login into any app","main":"src/index.js","exports":{".":"./src/index.js","./backend":"./src/backend.js"},"publishConfig":{"access":"public"},"peerDependencies":{"express":">=4.0.0"},"peerDependenciesMeta":{"express":{"optional":true}},"devDependencies":{"jest":"^29.0.0"},"scripts":{"test":"jest --verbose"},"keywords":["altscodex","deoauth","oauth","sdk","blockchain","login","jwt","account-abstraction"],"author":{"name":"altscodex"},"license":"MIT","homepage":"https://developers.altscodex.com","bugs":{"url":"https://developers.altscodex.com"},"_id":"@altscodex/sdk@3.0.0","gitHead":"d129c0b6f41fda4d62534018c5f25bd7be8a538c","_nodeVersion":"18.20.8","_npmVersion":"10.8.2","dist":{"integrity":"sha512-nAc3sNuR8kETtZj5K0V/5Grtpd9owAjnR7S0NvYwnNEP6+Vta1rEDfTeVFkM7GJHr9DNS88b7SwzK1tSUBEtJQ==","shasum":"06b0c538730200434ce14831c66b82869e63ed13","tarball":"https://registry.npmjs.org/@altscodex/sdk/-/sdk-3.0.0.tgz","fileCount":4,"unpackedSize":37945,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCx8yGyDOFEUloKwARHlk/K3YUS6dsTukkLFDGn5qw8vAIhAP7lE25G7kVOpduZFJR3scAFZXQPtG0+O8mL87jTUvFu"}]},"_npmUser":{"name":"banstorm","email":"cgman119@naver.com"},"directories":{},"maintainers":[{"name":"banstorm","email":"cgman119@naver.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_3.0.0_1782979587091_0.7202133314594976"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-03T07:15:49.697Z","modified":"2026-07-02T08:06:27.358Z","2.0.0":"2026-05-03T07:15:50.100Z","2.1.0":"2026-05-04T01:32:35.216Z","2.1.1":"2026-06-11T11:28:10.854Z","3.0.0":"2026-07-02T08:06:27.227Z"},"bugs":{"url":"https://developers.altscodex.com"},"author":{"name":"altscodex"},"license":"MIT","homepage":"https://developers.altscodex.com","keywords":["altscodex","deoauth","oauth","sdk","blockchain","login","jwt","account-abstraction"],"description":"AltsCodex DeOAuth SDK — integrate AltsCodex decentralized OAuth login into any app","maintainers":[{"name":"banstorm","email":"cgman119@naver.com"}],"readme":"# @altscodex/sdk\n\nOfficial SDK for integrating **AltsCodex DeOAuth** into your application.\n\n> 📚 **Docs · Support · Sign up** — everything for developers lives at **[developers.altscodex.com](https://developers.altscodex.com)**.\n> The platform itself runs at **[altscodex.com](https://altscodex.com)**.\n\nAltsCodex DeOAuth is a decentralized identity authentication system that bridges OAuth with blockchain — giving users true ownership of their digital accounts.\n\n- **Frontend SDK** — opens a DeOAuth login popup and returns a JWT\n- **Backend SDK** — verifies the JWT and retrieves the user's slot (account) info from the DeOAuth server\n\n---\n\n## Installation\n\n```bash\nnpm install @altscodex/sdk\n```\n\n---\n\n## Base URLs\n\n| SDK | Default URL | Description |\n|-----|-------------|-------------|\n| Frontend | `https://altscodex.com` | AltsCodex platform server |\n| Backend | `https://api.altscodex.com` | DeOAuth server (A-Server) |\n\nBoth defaults point to production. Override them for local development or staging.\n\n---\n\n## Quick Start\n\n### Frontend (Browser)\n\n```js\nimport AltsCodex from '@altscodex/sdk';\n\nconst sdk = new AltsCodex({\n  clientId:    'YOUR_CLIENT_ID',\n  redirectUri: 'https://yourapp.com/callback',\n  // altscodexUrl: 'https://altscodex.com' — default, can be omitted\n});\n\nconst { jwt } = await sdk.login();\n```\n\n### Backend (Node.js / Express)\n\n```js\nconst AltsCodexBackend = require('@altscodex/sdk/backend');\n\nconst sdk = new AltsCodexBackend({\n  clientId:     'YOUR_CLIENT_ID',\n  clientSecret: process.env.CLIENT_SECRET,\n  redirectUri:  'https://yourapp.com/getinfo',\n  // authServerUrl: 'https://api.altscodex.com' — default, can be omitted\n});\n\n// Mount callback route at your redirectUri path\napp.post('/getinfo', (req, res) => sdk.handleCallback(req, res));\n\n// In your login handler\napp.post('/login', async (req, res) => {\n  const slotInfo = await sdk.getSlotInfo(req.body.jwt);\n  res.json({ success: true, user: slotInfo });\n});\n```\n\n---\n\n## Full Auth Flow\n\n```\n[Browser]                  [Your Backend]           [DeOAuth Server]\n    |                            |                         |\n    |-- sdk.login() -----------> popup                     |\n    |<-- { jwt } via postMessage                           |\n    |                            |                         |\n    |-- POST /login { jwt } ---> |                         |\n    |                            |-- getSlotInfo(jwt) ---> |\n    |                            |<-- slotInfo ------------|\n    |                            |                         |\n    |<-- session / game data ----|\n```\n\n---\n\n## Frontend SDK\n\n**Environment**: Browser only. Requires `window`, `localStorage`, `postMessage`.\n\n### Constructor\n\n```js\nnew AltsCodex({\n  clientId:     string,   // required — from Developer Center\n  redirectUri:  string,   // required — registered callback URL\n  altscodexUrl:   string,   // optional — default: 'https://altscodex.com'\n  responseType: string,   // optional — default: 'code'\n  popupWidth:   number,   // optional — default: 600\n  popupHeight:  number,   // optional — default: 500\n})\n```\n\n### Methods\n\n#### `login(options?)` → `Promise<{ jwt: string }>`\n\nOpens the DeOAuth login popup. Stores the returned JWT in `localStorage`.\n\n```js\nconst { jwt } = await sdk.login({\n  state:   'optional-csrf-state',\n  timeout: 120000,  // ms, default 120s\n});\n```\n\n#### `logout(options?)` → `Promise<void>`\n\nCalls `POST /oauth/logout` then clears all `altscodex_*` keys from `localStorage`.\n\nLocal token cleanup is **guaranteed**: server or network failures are logged as\n`console.warn` and never throw, so the user can always log out locally.\n(Changed in v3.0.0 — v2 threw on server errors and skipped local cleanup.)\n\n```js\nawait sdk.logout();\n```\n\n#### `getToken()` → `string | null`\n\nReturns the stored access token.\n\n#### `isLoggedIn()` → `boolean`\n\nReturns `true` if a **non-expired** access token exists in `localStorage`.\n\nSince v3.0.0, the JWT `exp` claim is decoded and checked: an expired token\nreturns `false` (so your UI can prompt re-login instead of showing a logged-in\nstate whose API calls all fail). Tokens without `exp`, or tokens that fail to\ndecode, conservatively return `true` (v2 behavior). No signature verification\nis performed — this is a display hint; authorization decisions always belong\nto your server.\n\n#### `refresh(options)` → `Promise<{ accessToken, refreshToken, code }>`\n\n> **Deprecated since v3.0.0, will be removed in v4.0.0.**\n> The popup `login()` flow never stores a `refresh_token`, so this method\n> always fails in the official flow — and requiring `clientSecret` in browser\n> code leaks your secret to the client. Refresh tokens server-side instead\n> (Go SDK: `Backend.RefreshTokens()`; JS/Python backend equivalents planned).\n\nExchanges the stored refresh token for a new access token. Calling it logs a\ndeprecation warning; behavior is otherwise unchanged from v2.\n\n```js\nconst tokens = await sdk.refresh({ clientSecret: 'YOUR_SECRET' });\n```\n\n> ⚠️ Do not use `refresh()` in browser code with a real `clientSecret`. Use it only in secure server-side environments.\n\n### Error Messages\n\n| Message | Cause |\n|---------|-------|\n| `Popup blocked. Please allow popups.` | Browser blocked the popup |\n| `User closed the login window` | User dismissed the popup |\n| `Login failed: {reason}` | DeOAuth server returned an error |\n| `Login timeout` | No response within timeout |\n\n---\n\n## Backend SDK\n\n**Environment**: Node.js only. Import from `@altscodex/sdk/backend`.\n\n### Constructor\n\n```js\nnew AltsCodexBackend({\n  clientId:      string,  // required — from Developer Center\n  clientSecret:  string,  // required — stored in closure only, never exposed\n  redirectUri:   string,  // required — must match Developer Center registration exactly\n  authServerUrl: string,  // optional — default: 'https://api.altscodex.com'\n})\n```\n\n### Methods\n\n#### `getSlotInfo(jwt, options?)` → `Promise<SlotInfo>`\n\nRuns the full DeOAuth flow: authorize → wait for callback → exchange code for slot info.\n\n```js\nconst slotInfo = await sdk.getSlotInfo(jwt, { timeout: 15000 });\n```\n\n#### `handleCallback(req, res)`\n\nExpress route handler for the DeOAuth callback. Mount at your `redirectUri` path.\n\n```js\napp.post('/getinfo', (req, res) => sdk.handleCallback(req, res));\n```\n\n> Must be `app.post`, not `app.get`. The DeOAuth server sends callbacks via POST.\n\n#### `shutdown()`\n\nRejects all pending promises and clears internal state. Call on server shutdown.\n\n```js\nprocess.on('SIGTERM', () => { sdk.shutdown(); process.exit(0); });\n```\n\n### SlotInfo Object\n\n```ts\n{\n  id:              string   // Unique slot ID — use as your user identifier\n  access_token:    string   // DeOAuth access token\n  content_address: string   // Blockchain wallet address\n  token_nickname:  string   // Slot nickname\n  tr_cnt:          number   // Transfer count\n  code:            string   // OAuth authorization code\n}\n```\n\n### Error Codes\n\n| Error | Recommended HTTP Status |\n|-------|------------------------|\n| `authorize callback timeout` | 408 |\n| `authorize failed (EXPIRED_TOKEN)` | 401 |\n| `authorize failed (AUTHORIZE_ERROR)` | 502 |\n| `authorize callback rejected` | 502 |\n| `shutdown` | 503 |\n\n---\n\n## Security\n\n- **Never put `clientSecret` in frontend code** — it will be visible to anyone\n- `clientSecret` in `AltsCodexBackend` is stored in a closure, not on the instance\n- `redirectUri` must match the Developer Center registration exactly (protocol, host, port, path)\n- `handleCallback` must use `app.post`, not `app.get`\n\n---\n\n## Local Development\n\nOverride base URLs to point at local servers:\n\n```js\n// Frontend\nconst sdk = new AltsCodex({\n  altscodexUrl:  'http://localhost:3000',\n  clientId:    'YOUR_CLIENT_ID',\n  redirectUri: 'http://localhost:3070/getinfo',\n});\n\n// Backend\nconst sdk = new AltsCodexBackend({\n  authServerUrl: 'http://localhost:3000',\n  clientId:      'YOUR_CLIENT_ID',\n  clientSecret:  'YOUR_SECRET',\n  redirectUri:   'http://localhost:3070/getinfo',\n});\n```\n\n---\n\n## Environment Setup\n\nThe SDK does not read `process.env` or `import.meta.env` itself — it accepts plain options. Inject them from your build environment so secrets stay out of source code.\n\n### Vite (frontend SPA)\n\n```bash\n# .env.production\nVITE_ALTSCODEX_URL=https://altscodex.com\nVITE_CLIENT_ID=your-registered-client-id\nVITE_REDIRECT_URI=https://yourapp.com/callback\n```\n\n```js\n// AuthContext.tsx\nimport AltsCodex from '@altscodex/sdk';\n\nconst sdk = new AltsCodex({\n  altscodexUrl: import.meta.env.VITE_ALTSCODEX_URL,\n  clientId:     import.meta.env.VITE_CLIENT_ID,\n  redirectUri:  import.meta.env.VITE_REDIRECT_URI,\n});\n```\n\n### Next.js / Node backend\n\n```bash\n# .env.local (server side)\nALTSCODEX_AUTH_SERVER_URL=https://api.altscodex.com\nALTSCODEX_CLIENT_ID=your-registered-client-id\nALTSCODEX_CLIENT_SECRET=your-client-secret    # NEVER expose to the browser\nALTSCODEX_REDIRECT_URI=https://yourapp.com/getinfo\n```\n\n```js\nconst AltsCodexBackend = require('@altscodex/sdk/backend');\n\nconst sdk = new AltsCodexBackend({\n  authServerUrl: process.env.ALTSCODEX_AUTH_SERVER_URL,\n  clientId:      process.env.ALTSCODEX_CLIENT_ID,\n  clientSecret:  process.env.ALTSCODEX_CLIENT_SECRET,\n  redirectUri:   process.env.ALTSCODEX_REDIRECT_URI,\n});\n```\n\n> Per environment (local / staging / production), use a separate `.env.<mode>` file. Vite picks the file based on `--mode`; Next.js picks based on `NODE_ENV`.\n\n---\n\n## ⚠️ Common Pitfalls\n\n### 1. Use the registered hosts only\n\n| Purpose          | Production                              | Local development              |\n|------------------|-----------------------------------------|--------------------------------|\n| Frontend         | `https://altscodex.com` (or `www.`)     | `http://localhost:3000` (etc.) |\n| Backend / API    | `https://api.altscodex.com`             | `http://localhost:3000`        |\n| Developer Center | `https://developers.altscodex.com`      | —                              |\n\nDo **NOT** invent subdomains like `login.altscodex.com`, `oauth.altscodex.com`, `auth.altscodex.com`. They resolve to **NXDOMAIN** and the popup silently fails with `User closed the login window` after a long timeout.\n\n### 2. `clientId` and `redirectUri` must be registered first\n\nRegister your application at [developers.altscodex.com](https://developers.altscodex.com) to obtain a `clientId` and `clientSecret`. Hard-coding values that are not registered (or a `redirectUri` that does not exactly match the registered value — including trailing slash) results in `invalid_client` / `redirect_uri mismatch` 401 errors.\n\n### 3. Migrating from `@webxcom/sdk` v1.x\n\nOld → New mapping:\n\n| Old (`@webxcom/sdk` v1.x) | New (`@altscodex/sdk` v2.x) |\n|---------------------------|------------------------------|\n| `import WebXCOM from '@webxcom/sdk'` | `import AltsCodex from '@altscodex/sdk'` |\n| `new WebXCOM({ webxcomUrl: ... })` | `new AltsCodex({ altscodexUrl: ... })` |\n| `WebXCOMBackend` (backend) | `AltsCodexBackend` (backend) |\n| `webxcom_*` localStorage keys | `altscodex_*` localStorage keys |\n\nCoexistence: the platform server emits postMessage in **dual-broadcast** mode — one message with `from: \"altscodex\"` (consumed by v2.x SDK) and a second with `from: \"webxcom\"` (consumed by v1.x SDK). Existing v1.x apps continue to work unchanged during your gradual migration.\n\n### 4. Cross-Origin-Opener-Policy (COOP) caveat\n\nIf your hosting page sets `Cross-Origin-Opener-Policy: same-origin`, the browser may block the SDK's `popup.closed` poll, causing a console warning. The SDK degrades gracefully (it stops polling and relies on `postMessage` + `timeout` instead), but a user closing the popup with the X button may not be detected. Recommended COOP for pages that open the OAuth popup: `same-origin-allow-popups` or `unsafe-none`.\n\n---\n\n## Resources\n\n| Resource | URL | Description |\n|----------|-----|-------------|\n| Platform | [altscodex.com](https://altscodex.com) | Main AltsCodex platform — sign up, manage your Alts, marketplace |\n| Developer Center | [developers.altscodex.com](https://developers.altscodex.com) | Documentation, API reference, client credentials, SDK guides |\n| API Server | `https://api.altscodex.com` | DeOAuth backend (used by the Backend SDK) |\n| Blockchain Explorer | [scan.xotown.com](https://scan.xotown.com) | On-chain transaction and account explorer |\n\n---\n\n## Support\n\nHave a question, found a bug, or need help integrating the SDK?\n\n- **Documentation & Q&A** — visit the [Developer Center](https://developers.altscodex.com) for full SDK documentation, integration guides, and the support forum.\n- **Issues & Feature Requests** — submit them through the [Developer Center](https://developers.altscodex.com).\n- **Get your credentials** — register your application at [developers.altscodex.com](https://developers.altscodex.com) to obtain your `clientId` and `clientSecret`.\n\n> All technical questions, support requests, and SDK updates are handled through **[developers.altscodex.com](https://developers.altscodex.com)** — your single point of contact for AltsCodex integration.\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}