@rhinestone/1auth 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -34
- package/dist/{chunk-THKG3FAG.mjs → chunk-UXBBB7AV.mjs} +4 -4
- package/dist/{client-F4DnFM8d.d.mts → client-DvtGr2xn.d.mts} +2 -2
- package/dist/{client-B_CzDa_I.d.ts → client-Ewr_7x-d.d.ts} +2 -2
- package/dist/headless.d.mts +2 -2
- package/dist/headless.d.ts +2 -2
- package/dist/headless.js +1 -1
- package/dist/headless.js.map +1 -1
- package/dist/headless.mjs +1 -1
- package/dist/headless.mjs.map +1 -1
- package/dist/index.d.mts +9 -50
- package/dist/index.d.ts +9 -50
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -10
- package/dist/index.mjs.map +1 -1
- package/dist/{provider-Cd7Ip5L-.d.ts → provider-BRHZoB8U.d.ts} +2 -2
- package/dist/{provider-IvYXPMpk.d.mts → provider-NYl0jlHw.d.mts} +2 -2
- package/dist/react.d.mts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/server.d.mts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/server.js +54 -5
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +4 -0
- package/dist/server.mjs.map +1 -1
- package/dist/{types-U_dwxbtS.d.mts → types-C0jKNT_t.d.mts} +1 -1
- package/dist/{types-U_dwxbtS.d.ts → types-C0jKNT_t.d.ts} +1 -1
- package/dist/{verify-BLgZzwmJ.d.ts → verify-CnOwPq78.d.ts} +44 -3
- package/dist/{verify-C8-a5c3K.d.mts → verify-aWdi5O2z.d.mts} +44 -3
- package/dist/wagmi.d.mts +3 -3
- package/dist/wagmi.d.ts +3 -3
- package/dist/wagmi.mjs +2 -2
- package/package.json +1 -1
- /package/dist/{chunk-THKG3FAG.mjs.map → chunk-UXBBB7AV.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -26,10 +26,11 @@ The SDK provides multiple entry points for different use cases:
|
|
|
26
26
|
|
|
27
27
|
| Entry Point | Import | Use Case |
|
|
28
28
|
|-------------|--------|----------|
|
|
29
|
-
| Default | `@rhinestone/1auth` | Core client, provider, types |
|
|
30
|
-
| React | `@rhinestone/1auth/react` | PayButton component |
|
|
31
|
-
| Server | `@rhinestone/1auth/server` | JWT
|
|
29
|
+
| Default | `@rhinestone/1auth` | Core client, provider, batch components, registry, types |
|
|
30
|
+
| React | `@rhinestone/1auth/react` | `PayButton` component + `useSponsorship` hook |
|
|
31
|
+
| Server | `@rhinestone/1auth/server` | JWT sponsorship signers for app-sponsored intents |
|
|
32
32
|
| Wagmi | `@rhinestone/1auth/wagmi` | Wagmi connector integration |
|
|
33
|
+
| Headless | `@rhinestone/1auth/headless` | Headless client without dialog UI |
|
|
33
34
|
|
|
34
35
|
## Quick Start
|
|
35
36
|
|
|
@@ -40,25 +41,34 @@ import { OneAuthClient, createOneAuthProvider } from '@rhinestone/1auth';
|
|
|
40
41
|
|
|
41
42
|
// Create the client
|
|
42
43
|
const client = new OneAuthClient({
|
|
43
|
-
|
|
44
|
+
providerUrl: 'https://passkey.1auth.app',
|
|
44
45
|
});
|
|
45
46
|
|
|
46
|
-
// Create an EIP-1193 compatible provider
|
|
47
|
-
const provider = createOneAuthProvider(client);
|
|
47
|
+
// Create an EIP-1193 compatible provider (chainId is required)
|
|
48
|
+
const provider = createOneAuthProvider({ client, chainId: 8453 }); // Base
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
### React Integration
|
|
51
52
|
|
|
52
53
|
```tsx
|
|
53
54
|
import { PayButton } from '@rhinestone/1auth/react';
|
|
55
|
+
import { OneAuthClient } from '@rhinestone/1auth';
|
|
56
|
+
|
|
57
|
+
const client = new OneAuthClient({ providerUrl: 'https://passkey.1auth.app' });
|
|
54
58
|
|
|
55
59
|
function CheckoutPage() {
|
|
56
60
|
return (
|
|
57
61
|
<PayButton
|
|
58
|
-
|
|
62
|
+
client={client}
|
|
63
|
+
intent={{
|
|
64
|
+
targetChain: 8453, // Base
|
|
65
|
+
calls: [{ to: '0xRecipient', data: '0x', value: '1000000' }],
|
|
66
|
+
}}
|
|
59
67
|
onSuccess={(result) => console.log('Payment successful', result)}
|
|
60
68
|
onError={(error) => console.error('Payment failed', error)}
|
|
61
|
-
|
|
69
|
+
>
|
|
70
|
+
Pay $5 USDC
|
|
71
|
+
</PayButton>
|
|
62
72
|
);
|
|
63
73
|
}
|
|
64
74
|
```
|
|
@@ -67,15 +77,17 @@ function CheckoutPage() {
|
|
|
67
77
|
|
|
68
78
|
```typescript
|
|
69
79
|
import { oneAuth } from '@rhinestone/1auth/wagmi';
|
|
80
|
+
import { OneAuthClient } from '@rhinestone/1auth';
|
|
70
81
|
import { createConfig, http } from 'wagmi';
|
|
71
82
|
import { mainnet, sepolia } from 'wagmi/chains';
|
|
72
83
|
|
|
84
|
+
// The connector wraps a configured OneAuthClient.
|
|
85
|
+
const client = new OneAuthClient({ providerUrl: 'https://passkey.1auth.app' });
|
|
86
|
+
|
|
73
87
|
const config = createConfig({
|
|
74
88
|
chains: [mainnet, sepolia],
|
|
75
89
|
connectors: [
|
|
76
|
-
oneAuth({
|
|
77
|
-
passkeyServerUrl: 'https://passkey.1auth.box',
|
|
78
|
-
}),
|
|
90
|
+
oneAuth({ client }),
|
|
79
91
|
],
|
|
80
92
|
transports: {
|
|
81
93
|
[mainnet.id]: http(),
|
|
@@ -87,19 +99,15 @@ const config = createConfig({
|
|
|
87
99
|
### Server-Side JWT Sponsorship
|
|
88
100
|
|
|
89
101
|
```typescript
|
|
90
|
-
import {
|
|
102
|
+
import { createSponsorshipSigner } from '@rhinestone/1auth/server';
|
|
91
103
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
projectId: process.env.RHINESTONE_PROJECT_ID,
|
|
96
|
-
appId: process.env.RHINESTONE_APP_ID,
|
|
97
|
-
keyId: process.env.RHINESTONE_KEY_ID,
|
|
98
|
-
});
|
|
104
|
+
// Reads RHINESTONE_JWT_PRIVATE_KEY / _INTEGRATOR_ID / _PROJECT_ID / _APP_ID / _KEY_ID
|
|
105
|
+
// from process.env. Pass `{ credentials }` to supply them explicitly instead.
|
|
106
|
+
const signer = createSponsorshipSigner();
|
|
99
107
|
|
|
100
108
|
// Use in your API routes
|
|
101
109
|
const accessToken = await signer.accessToken();
|
|
102
|
-
const extensionToken = await signer.
|
|
110
|
+
const extensionToken = await signer.extensionToken(intentOp); // accepts the JSON-stringified intentOp
|
|
103
111
|
```
|
|
104
112
|
|
|
105
113
|
## Core Exports
|
|
@@ -108,22 +116,27 @@ const extensionToken = await signer.getIntentExtensionToken(intentInput);
|
|
|
108
116
|
|
|
109
117
|
- `OneAuthClient` - Main client for passkey operations
|
|
110
118
|
- `createOneAuthProvider()` - EIP-1193 compatible provider factory
|
|
111
|
-
- `createPasskeyWalletClient()` - viem WalletClient with passkey support
|
|
112
|
-
- `
|
|
113
|
-
- `
|
|
114
|
-
-
|
|
119
|
+
- `createPasskeyAccount()`, `createPasskeyWalletClient()` - viem account / WalletClient with passkey support
|
|
120
|
+
- `definePermissions()`, `createCrossChainPermission()` - Session-key permission helpers
|
|
121
|
+
- `BatchQueueProvider`, `useBatchQueue()`, `BatchQueueWidget` - Batch queue context, hook, and widget
|
|
122
|
+
- `getSupportedChains()`, `getSupportedTokens()`, `getAllSupportedChainsAndTokens()` - Chain/token registry
|
|
123
|
+
- `hashMessage()`, `verifyMessageHash()` - Message verification
|
|
124
|
+
- Type exports for intents, accounts, sponsorship, and more
|
|
115
125
|
|
|
116
126
|
### `@rhinestone/1auth/react`
|
|
117
127
|
|
|
118
|
-
- `PayButton` - Pre-built payment/intent button component
|
|
119
|
-
- `
|
|
120
|
-
|
|
121
|
-
|
|
128
|
+
- `PayButton` - Pre-built payment/intent button component (requires a `client` prop)
|
|
129
|
+
- `useSponsorship()` - Hook that builds a sponsorship config from token endpoint URLs with an expiry-aware access-token cache
|
|
130
|
+
|
|
131
|
+
> Batch components (`BatchQueueProvider`, `BatchQueueWidget`, `useBatchQueue`) are exported from the **main** `@rhinestone/1auth` entry, not from `/react`.
|
|
122
132
|
|
|
123
133
|
### `@rhinestone/1auth/server`
|
|
124
134
|
|
|
125
|
-
- `
|
|
126
|
-
- `
|
|
135
|
+
- `createSponsorshipSigner()` - **Recommended.** Framework-agnostic signer that reads credentials from env and exposes `accessToken()` / `extensionToken(intentOp)`
|
|
136
|
+
- `createJwtSigner()` - Lower-level escape hatch for custom claims; takes `{ jwt, shouldSponsor? }`
|
|
137
|
+
- `verifyOneAuthAccount()` - Server-side check that an address belongs to a known 1auth account
|
|
138
|
+
- `hashMessage()`, `verifyMessageHash()`, `encodeWebAuthnSignature()` - Verification / signing utilities
|
|
139
|
+
- `JwtSignerConfig`, `JwtCredentials`, `SponsorshipSigner` - Configuration types
|
|
127
140
|
|
|
128
141
|
### `@rhinestone/1auth/wagmi`
|
|
129
142
|
|
|
@@ -131,7 +144,19 @@ const extensionToken = await signer.getIntentExtensionToken(intentInput);
|
|
|
131
144
|
|
|
132
145
|
## App-Sponsored Intents
|
|
133
146
|
|
|
134
|
-
|
|
147
|
+
### What the JWT is for
|
|
148
|
+
|
|
149
|
+
Every intent needs someone to pay its fees. **By default, 1auth pays** using its own orchestrator API key — you don't have to do anything. App sponsorship lets *your app* take over that bill instead: you mint a short-lived JWT, signed with a private key Rhinestone issued to your project, and the orchestrator charges your account for any intent that JWT authorizes.
|
|
150
|
+
|
|
151
|
+
The JWT is purely a **billing authorization** — it says "this app vouches for paying this intent." It does **not** authenticate the user or authorize the transaction itself; that's the passkey/WebAuthn signature, which is independent. Sponsorship and signing happen in parallel.
|
|
152
|
+
|
|
153
|
+
The private key must **never** reach the browser, so the tokens are always minted server-side. You have two ways to wire that up:
|
|
154
|
+
|
|
155
|
+
1. **Self-host the signer (full control).** Run `createSponsorshipSigner()` (or the lower-level `createJwtSigner()`) from `@rhinestone/1auth/server` behind two endpoints on your own backend, gated by your existing session auth. This is where you enforce per-user policy — spending limits, allowlists, the `shouldSponsor` filter. You decide exactly when and for whom a token is minted.
|
|
156
|
+
|
|
157
|
+
2. **Let the SDK drive it.** Point `OneAuthClient` at those two endpoint URLs (the `SponsorshipUrlConfig` form) and the SDK handles fetching, caching, expiry, and retry for you — including the `useSponsorship` React hook. You still host the endpoints (the signing key lives there), but you don't write any client-side token plumbing.
|
|
158
|
+
|
|
159
|
+
In short: the **signing** always lives on your backend; the **fetching** can either be your code (callback form) or the SDK's (URL form). Pick based on how much of the token lifecycle you want to own.
|
|
135
160
|
|
|
136
161
|
### How It Works
|
|
137
162
|
|
|
@@ -165,13 +190,103 @@ sequenceDiagram
|
|
|
165
190
|
PS-->>SDK: { intentId }
|
|
166
191
|
```
|
|
167
192
|
|
|
193
|
+
### The two tokens
|
|
194
|
+
|
|
195
|
+
App sponsorship is authorized by two short-lived JWTs your backend mints with `createSponsorshipSigner()` (or `createJwtSigner()`). Both are signed with your Rhinestone JWK — `ES256` for an EC key, `RS256` for RSA — and carry your `integratorId` (issuer), `projectId` (subject), and `appId`.
|
|
196
|
+
|
|
197
|
+
| Token | `typ` | TTL | Purpose |
|
|
198
|
+
|-------|-------|-----|---------|
|
|
199
|
+
| **Access token** | `access` | 1 hour | Identifies your app to the orchestrator. Not bound to any intent, so it's safe to cache and reuse across many intents (the SDK's `useSponsorship` hook does exactly this). |
|
|
200
|
+
| **Extension token** | `intent_extension` | 5 minutes | Authorizes sponsorship of **one specific intent**. Minted fresh per intent. |
|
|
201
|
+
|
|
202
|
+
The extension token is what makes sponsorship safe to expose to the browser: its `policy.sponsorship.intent_input.digest` claim is a **JCS-canonicalized ([RFC 8785](https://www.rfc-editor.org/rfc/rfc8785)) SHA-256 hash of the exact `intentOp`** being signed. The orchestrator recomputes that digest from the intent it receives and rejects the token if they differ — so a token minted for "send $5 to Alice" cannot be replayed to authorize "send $5000 to Mallory". Each extension token also carries a unique `jti`.
|
|
203
|
+
|
|
204
|
+
Because the digest pins the token to one intent, your backend's `extension-token` endpoint is the natural place to enforce per-user policy (spending limits, allowlists) — see the `shouldSponsor` filter on `createJwtSigner` / `createSponsorshipSigner`, which can veto by chain, account, or calls before a token is ever minted.
|
|
205
|
+
|
|
206
|
+
#### What the tokens actually contain
|
|
207
|
+
|
|
208
|
+
If you decode the JWTs your backend mints (e.g. paste into [jwt.io](https://jwt.io)), this is the shape. Both share the same header and `iss`/`sub`/`aud` claims — only `typ`, lifetime, and the intent-binding differ.
|
|
209
|
+
|
|
210
|
+
```jsonc
|
|
211
|
+
// Header (both tokens) — alg is ES256 for an EC key, RS256 for RSA
|
|
212
|
+
{ "alg": "ES256", "kid": "<keyId>" }
|
|
213
|
+
|
|
214
|
+
// Access token payload — app identity, reusable for 1h
|
|
215
|
+
{
|
|
216
|
+
"typ": "access",
|
|
217
|
+
"app_id": "<appId>",
|
|
218
|
+
"iss": "<integratorId>", // setIssuer
|
|
219
|
+
"sub": "<projectId>", // setSubject
|
|
220
|
+
"aud": "rhinestone-api", // override via JwtCredentials.audience
|
|
221
|
+
"iat": 1719300000,
|
|
222
|
+
"exp": 1719303600 // iat + 1h
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Extension token payload — authorizes ONE intent, expires in 5m
|
|
226
|
+
{
|
|
227
|
+
"typ": "intent_extension",
|
|
228
|
+
"app_id": "<appId>",
|
|
229
|
+
"jti": "f47ac10b-58cc-4372-a567-0e02b2c3d479", // unique per token
|
|
230
|
+
"policy": {
|
|
231
|
+
"sponsorship": {
|
|
232
|
+
"scope": "intent",
|
|
233
|
+
"intent_input": {
|
|
234
|
+
// JCS-canonicalized SHA-256 of the exact intentOp; the orchestrator
|
|
235
|
+
// recomputes this and rejects the token if it doesn't match.
|
|
236
|
+
"digest": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
"iss": "<integratorId>",
|
|
241
|
+
"sub": "<projectId>",
|
|
242
|
+
"aud": "rhinestone-api",
|
|
243
|
+
"iat": 1719300000,
|
|
244
|
+
"exp": 1719300300 // iat + 5m
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### Token lifecycle & caching
|
|
249
|
+
|
|
250
|
+
The access token is reusable, so re-minting it on every intent is wasteful — but serving a *stale* one is worse. `useSponsorship` / `createCachedSponsorship` hold the access token in a closure and only reuse it while its `exp` is comfortably in the future:
|
|
251
|
+
|
|
252
|
+
- A **60-second safety margin** (`ACCESS_TOKEN_EXPIRY_MARGIN_MS`) is subtracted from `exp` before deciding a cached token is still usable. This absorbs clock skew between your app server and the orchestrator's verifier plus the in-flight time of the `prepare` call — a token that looks valid locally can still be rejected downstream if it expires mid-request.
|
|
253
|
+
- A token that can't be decoded, or carries no numeric `exp`, is treated as unusable so a malformed cache entry never gets served indefinitely.
|
|
254
|
+
- If the **extension-token** endpoint returns `401`, the cached access token is dropped immediately, so the next call re-mints rather than retrying with a token the orchestrator just rejected.
|
|
255
|
+
- The **extension token is never cached** — it binds to a specific `intentOp`, so a fresh one is minted per intent.
|
|
256
|
+
|
|
257
|
+
Both fetches use `credentials: "include"` so your app's own session cookie authenticates the user; no separate auth channel is needed.
|
|
258
|
+
|
|
259
|
+
#### Troubleshooting
|
|
260
|
+
|
|
261
|
+
| Symptom | Likely cause | Fix |
|
|
262
|
+
|---------|--------------|-----|
|
|
263
|
+
| `"Failed to get quote from orchestrator"` (a 401 surfacing as a quote failure) | The access token's `exp` lapsed before the orchestrator verified it (`"exp" claim timestamp check failed`) — usually a long-lived tab serving a stale cached token, or large clock skew | Use `useSponsorship` / `createCachedSponsorship` (they re-mint with the 60s margin) rather than hand-rolling a cache; check server clock sync |
|
|
264
|
+
| `401` from your own `access-token` / `extension-token` endpoint | Your session guard rejected the request (user not logged in, cookie not sent cross-origin) | Ensure the endpoints are **same-origin** with your app and that the client sends credentials; gate with your existing session auth |
|
|
265
|
+
| Sponsorship silently denied / `SponsorshipDeniedError` | A `shouldSponsor` filter vetoed the intent (chain/account/calls not allowed) | Confirm the intent matches your policy, or relax the filter |
|
|
266
|
+
| Orchestrator rejects the extension token despite a valid signature | `intent_input.digest` doesn't match — the `intentOp` was mutated between `prepare` and `execute`, or you minted the token from a different object than the SDK sent | Mint the extension token from the exact `intentOp` string the SDK posts to your endpoint; don't re-serialize or reorder it |
|
|
267
|
+
| `Unsupported JWK kty` / `Unsupported EC curve` at startup | The private key JWK isn't an EC (`P-256`/`P-384`/`P-521`) or RSA key | Use the JWK Rhinestone issued; `ES256` (EC P-256) is the common case |
|
|
268
|
+
|
|
168
269
|
### Why this shape
|
|
169
270
|
|
|
170
271
|
The SDK calls your token endpoints **from the browser, same-origin**. Your app's session cookie naturally authenticates the request — no need to pass bearer tokens through the SDK. The passkey service never fetches from your backend on your behalf, so there's no SSRF surface and no CORS config to worry about.
|
|
171
272
|
|
|
172
273
|
### Setup
|
|
173
274
|
|
|
174
|
-
**1.
|
|
275
|
+
**1. Get a signing key from the Rhinestone dashboard**
|
|
276
|
+
|
|
277
|
+
Create a Rhinestone app in the [Rhinestone dashboard](https://dashboard.rhinestone.dev) to generate a JWT signing key, then copy these values into your **server** environment (never the browser):
|
|
278
|
+
|
|
279
|
+
| Variable | Description |
|
|
280
|
+
|----------|-------------|
|
|
281
|
+
| `RHINESTONE_JWT_PRIVATE_KEY` | JSON-encoded JWK (EC P-256 / `ES256` recommended, RSA accepted) |
|
|
282
|
+
| `RHINESTONE_INTEGRATOR_ID` | Your integrator handle — becomes the JWT `iss` |
|
|
283
|
+
| `RHINESTONE_PROJECT_ID` | Project the app belongs to — becomes the JWT `sub` |
|
|
284
|
+
| `RHINESTONE_APP_ID` | App ID — becomes the JWT `app_id` claim |
|
|
285
|
+
| `RHINESTONE_KEY_ID` | Key ID registered with the orchestrator — the `kid` header |
|
|
286
|
+
|
|
287
|
+
`createSponsorshipSigner()` reads all five automatically; pass `{ credentials: { ... } }` to supply them explicitly instead.
|
|
288
|
+
|
|
289
|
+
**2. Create two endpoints on your backend, on the same origin as your app**
|
|
175
290
|
|
|
176
291
|
Gate these with your existing session auth — the user's cookie rides along automatically.
|
|
177
292
|
|
|
@@ -215,13 +330,13 @@ export async function handleExtensionToken(req, res) {
|
|
|
215
330
|
}
|
|
216
331
|
```
|
|
217
332
|
|
|
218
|
-
**
|
|
333
|
+
**3. Configure `OneAuthClient` with the URL form**
|
|
219
334
|
|
|
220
335
|
```typescript
|
|
221
336
|
import { OneAuthClient, createOneAuthProvider } from '@rhinestone/1auth';
|
|
222
337
|
|
|
223
338
|
const client = new OneAuthClient({
|
|
224
|
-
providerUrl: 'https://passkey.1auth.
|
|
339
|
+
providerUrl: 'https://passkey.1auth.app',
|
|
225
340
|
sponsorship: {
|
|
226
341
|
accessTokenUrl: '/api/sponsorship/access-token',
|
|
227
342
|
extensionTokenUrl: '/api/sponsorship/extension-token',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getSupportedChainIds
|
|
3
|
-
} from "./chunk-GUAI55LL.mjs";
|
|
4
1
|
import {
|
|
5
2
|
encodeWebAuthnSignature
|
|
6
3
|
} from "./chunk-N6KE5CII.mjs";
|
|
4
|
+
import {
|
|
5
|
+
getSupportedChainIds
|
|
6
|
+
} from "./chunk-GUAI55LL.mjs";
|
|
7
7
|
|
|
8
8
|
// src/provider.ts
|
|
9
9
|
import {
|
|
@@ -526,4 +526,4 @@ function createOneAuthProvider(options) {
|
|
|
526
526
|
export {
|
|
527
527
|
createOneAuthProvider
|
|
528
528
|
};
|
|
529
|
-
//# sourceMappingURL=chunk-
|
|
529
|
+
//# sourceMappingURL=chunk-UXBBB7AV.mjs.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PasskeyProviderConfig, S as SponsorshipConfig, aa as ThemeConfig, a6 as GetAssetsOptions, a9 as AssetsResponse, v as AuthWithModalOptions, A as AuthResult, L as LoginWithModalOptions, w as CreateAccountWithModalOptions, y as ConnectResult, ad as CheckConsentOptions, ae as CheckConsentResult, af as RequestConsentOptions, ag as RequestConsentResult, ah as GrantPermissionsOptions, ai as GrantPermissionsResult, aj as ListSessionGrantsOptions, ak as ListSessionGrantsResult, z as AuthenticateOptions, B as AuthenticateResult, m as SigningRequestOptions, n as SigningResult, Y as SendIntentOptions, i as SendIntentResult, aq as SendBatchIntentOptions, ar as SendBatchIntentResult, a3 as IntentHistoryOptions, a5 as IntentHistoryResult, F as SignMessageOptions, G as SignMessageResult, J as SignTypedDataOptions, K as SignTypedDataResult, E as EmbedOptions, t as PasskeyCredential } from './types-
|
|
1
|
+
import { P as PasskeyProviderConfig, S as SponsorshipConfig, aa as ThemeConfig, a6 as GetAssetsOptions, a9 as AssetsResponse, v as AuthWithModalOptions, A as AuthResult, L as LoginWithModalOptions, w as CreateAccountWithModalOptions, y as ConnectResult, ad as CheckConsentOptions, ae as CheckConsentResult, af as RequestConsentOptions, ag as RequestConsentResult, ah as GrantPermissionsOptions, ai as GrantPermissionsResult, aj as ListSessionGrantsOptions, ak as ListSessionGrantsResult, z as AuthenticateOptions, B as AuthenticateResult, m as SigningRequestOptions, n as SigningResult, Y as SendIntentOptions, i as SendIntentResult, aq as SendBatchIntentOptions, ar as SendBatchIntentResult, a3 as IntentHistoryOptions, a5 as IntentHistoryResult, F as SignMessageOptions, G as SignMessageResult, J as SignTypedDataOptions, K as SignTypedDataResult, E as EmbedOptions, t as PasskeyCredential } from './types-C0jKNT_t.mjs';
|
|
2
2
|
|
|
3
3
|
declare class OneAuthClient {
|
|
4
4
|
private config;
|
|
@@ -125,7 +125,7 @@ declare class OneAuthClient {
|
|
|
125
125
|
* Falls back to the raw dialog URL string if URL parsing fails (e.g. during
|
|
126
126
|
* unit tests with non-standard URL formats).
|
|
127
127
|
*
|
|
128
|
-
* @returns The scheme + host + optional port of the dialog app (e.g. `"https://passkey.1auth.
|
|
128
|
+
* @returns The scheme + host + optional port of the dialog app (e.g. `"https://passkey.1auth.app"`).
|
|
129
129
|
*/
|
|
130
130
|
private getDialogOrigin;
|
|
131
131
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PasskeyProviderConfig, S as SponsorshipConfig, aa as ThemeConfig, a6 as GetAssetsOptions, a9 as AssetsResponse, v as AuthWithModalOptions, A as AuthResult, L as LoginWithModalOptions, w as CreateAccountWithModalOptions, y as ConnectResult, ad as CheckConsentOptions, ae as CheckConsentResult, af as RequestConsentOptions, ag as RequestConsentResult, ah as GrantPermissionsOptions, ai as GrantPermissionsResult, aj as ListSessionGrantsOptions, ak as ListSessionGrantsResult, z as AuthenticateOptions, B as AuthenticateResult, m as SigningRequestOptions, n as SigningResult, Y as SendIntentOptions, i as SendIntentResult, aq as SendBatchIntentOptions, ar as SendBatchIntentResult, a3 as IntentHistoryOptions, a5 as IntentHistoryResult, F as SignMessageOptions, G as SignMessageResult, J as SignTypedDataOptions, K as SignTypedDataResult, E as EmbedOptions, t as PasskeyCredential } from './types-
|
|
1
|
+
import { P as PasskeyProviderConfig, S as SponsorshipConfig, aa as ThemeConfig, a6 as GetAssetsOptions, a9 as AssetsResponse, v as AuthWithModalOptions, A as AuthResult, L as LoginWithModalOptions, w as CreateAccountWithModalOptions, y as ConnectResult, ad as CheckConsentOptions, ae as CheckConsentResult, af as RequestConsentOptions, ag as RequestConsentResult, ah as GrantPermissionsOptions, ai as GrantPermissionsResult, aj as ListSessionGrantsOptions, ak as ListSessionGrantsResult, z as AuthenticateOptions, B as AuthenticateResult, m as SigningRequestOptions, n as SigningResult, Y as SendIntentOptions, i as SendIntentResult, aq as SendBatchIntentOptions, ar as SendBatchIntentResult, a3 as IntentHistoryOptions, a5 as IntentHistoryResult, F as SignMessageOptions, G as SignMessageResult, J as SignTypedDataOptions, K as SignTypedDataResult, E as EmbedOptions, t as PasskeyCredential } from './types-C0jKNT_t.js';
|
|
2
2
|
|
|
3
3
|
declare class OneAuthClient {
|
|
4
4
|
private config;
|
|
@@ -125,7 +125,7 @@ declare class OneAuthClient {
|
|
|
125
125
|
* Falls back to the raw dialog URL string if URL parsing fails (e.g. during
|
|
126
126
|
* unit tests with non-standard URL formats).
|
|
127
127
|
*
|
|
128
|
-
* @returns The scheme + host + optional port of the dialog app (e.g. `"https://passkey.1auth.
|
|
128
|
+
* @returns The scheme + host + optional port of the dialog app (e.g. `"https://passkey.1auth.app"`).
|
|
129
129
|
*/
|
|
130
130
|
private getDialogOrigin;
|
|
131
131
|
/**
|
package/dist/headless.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PasskeyProviderConfig, S as SponsorshipConfig, H as HeadlessIntentOptions, a as HeadlessPrepareResult, b as HeadlessSubmitOptions, c as HeadlessSubmitResult, d as HeadlessIntentStatusResult, I as InstallSmartSessionOptions, e as InstallSmartSessionResult, f as SessionKeyHandle } from './types-
|
|
2
|
-
export { g as SmartSessionEnableRequest } from './types-
|
|
1
|
+
import { P as PasskeyProviderConfig, S as SponsorshipConfig, H as HeadlessIntentOptions, a as HeadlessPrepareResult, b as HeadlessSubmitOptions, c as HeadlessSubmitResult, d as HeadlessIntentStatusResult, I as InstallSmartSessionOptions, e as InstallSmartSessionResult, f as SessionKeyHandle } from './types-C0jKNT_t.mjs';
|
|
2
|
+
export { g as SmartSessionEnableRequest } from './types-C0jKNT_t.mjs';
|
|
3
3
|
import * as _rhinestone_sdk from '@rhinestone/sdk';
|
|
4
4
|
import { Hex, Address } from 'viem';
|
|
5
5
|
|
package/dist/headless.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PasskeyProviderConfig, S as SponsorshipConfig, H as HeadlessIntentOptions, a as HeadlessPrepareResult, b as HeadlessSubmitOptions, c as HeadlessSubmitResult, d as HeadlessIntentStatusResult, I as InstallSmartSessionOptions, e as InstallSmartSessionResult, f as SessionKeyHandle } from './types-
|
|
2
|
-
export { g as SmartSessionEnableRequest } from './types-
|
|
1
|
+
import { P as PasskeyProviderConfig, S as SponsorshipConfig, H as HeadlessIntentOptions, a as HeadlessPrepareResult, b as HeadlessSubmitOptions, c as HeadlessSubmitResult, d as HeadlessIntentStatusResult, I as InstallSmartSessionOptions, e as InstallSmartSessionResult, f as SessionKeyHandle } from './types-C0jKNT_t.js';
|
|
2
|
+
export { g as SmartSessionEnableRequest } from './types-C0jKNT_t.js';
|
|
3
3
|
import * as _rhinestone_sdk from '@rhinestone/sdk';
|
|
4
4
|
import { Hex, Address } from 'viem';
|
|
5
5
|
|
package/dist/headless.js
CHANGED
|
@@ -60,7 +60,7 @@ async function tokenFetchError(label, response) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// src/headless-client.ts
|
|
63
|
-
var DEFAULT_PROVIDER_URL = "https://passkey.1auth.
|
|
63
|
+
var DEFAULT_PROVIDER_URL = "https://passkey.1auth.app";
|
|
64
64
|
var MISSING_APP_CREDENTIALS_MESSAGE = "No sponsorship configured on OneAuthHeadlessClient. Every user intent must carry the app's JWT \u2014 pass `sponsorship: { accessToken, getExtensionToken }` (or URL form) to the constructor.";
|
|
65
65
|
function normalizeSponsorship(config) {
|
|
66
66
|
if (!config) return null;
|
package/dist/headless.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/headless.ts","../src/sponsorship-fetch.ts","../src/headless-client.ts","../src/smart-session-signatures.ts","../src/registry.ts"],"sourcesContent":["/**\n * Public entry point for the headless 1auth SDK.\n *\n * Exposes {@link OneAuthHeadlessClient} plus the request/response types\n * an integrating app needs when using its own ERC-7579 validator (e.g.\n * the experimental SmartSession from `@rhinestone/sdk`) to sign intents\n * locally instead of going through the passkey dialog.\n */\n\nexport { OneAuthHeadlessClient } from \"./headless-client\";\nexport {\n buildSmartSessionHeadlessSignatures,\n type BuildSmartSessionHeadlessSignaturesOptions,\n} from \"./smart-session-signatures\";\n\nexport type {\n HeadlessIntentStatusResult,\n HeadlessIntentOptions,\n HeadlessPrepareResult,\n HeadlessSubmitOptions,\n HeadlessSubmitResult,\n InstallSmartSessionOptions,\n InstallSmartSessionResult,\n SessionKeyHandle,\n SmartSessionEnableRequest,\n} from \"./types\";\n","/**\n * Shared helpers for fetching sponsorship tokens (access + extension) from an\n * integrator's backend endpoints.\n *\n * The integrator's token routes return their failure reason in the JSON body\n * (`{ error: \"createSponsorshipSigner: missing env var(s): ...\" }`). Surfacing\n * only the HTTP status — \"Failed to fetch access token (500 ...)\" — hides that\n * reason and turns every misconfiguration into the same opaque dialog error.\n * These helpers read the body and fold the server's message into the thrown\n * Error so the actual cause (missing env var, bad JWK, expired session) is\n * visible at the call site and in the dialog.\n */\n\n/**\n * Pull a human-readable reason out of a failed token response. Tries the JSON\n * `error`/`message` fields first, then falls back to a short text snippet, then\n * to the HTTP status text. Never throws — diagnostics must not mask the original\n * failure with a parse error.\n */\nasync function extractServerReason(response: Response): Promise<string> {\n try {\n // Clone so a JSON parse failure can still fall back to reading text.\n const text = await response.clone().text();\n if (!text) return response.statusText;\n try {\n const data = JSON.parse(text) as { error?: unknown; message?: unknown };\n const reason = data.error ?? data.message;\n if (typeof reason === \"string\" && reason.trim()) return reason;\n } catch {\n // Body wasn't JSON — fall through to the raw text snippet.\n }\n // Cap the snippet so an HTML error page doesn't flood the message.\n return text.slice(0, 200);\n } catch {\n return response.statusText;\n }\n}\n\n/**\n * Build an Error for a failed token fetch that includes the server's reason.\n * `label` names the token kind, e.g. \"access token\" or \"extension token\".\n */\nexport async function tokenFetchError(\n label: string,\n response: Response,\n): Promise<Error> {\n const reason = await extractServerReason(response);\n const suffix = reason ? `: ${reason}` : \"\";\n return new Error(\n `Failed to fetch ${label} (${response.status} ${response.statusText})${suffix}`,\n );\n}\n","/**\n * Headless 1auth client.\n *\n * Used by integrators that hold their own ECDSA signer in localStorage\n * and produce signatures for an ERC-7579 validator other than the\n * passkey one (typically `@rhinestone/sdk` experimental SmartSession).\n *\n * Responsibilities:\n * - Fetch sponsorship JWTs from the app's own backend.\n * - Call `/api/intent/prepare?signingMode=headless` to get an\n * orchestrator-quoted `intentOp` + `digestResult`.\n * - Forward pre-encoded validator-prefixed signatures to the new\n * `/api/intent/headless-execute` route.\n * - Drive the existing passkey dialog (via {@link OneAuthClient}) for\n * the one-time SmartSession install ceremony.\n *\n * 1auth itself stays ignorant of session keys — the on-chain\n * SmartSession validator is the only authority over what a session key\n * may sign for. The host app persists `{ sessionKeyAddress, permissionId,\n * accountAddress, permissions }` in its own storage.\n */\n\nimport type {\n HeadlessIntentOptions,\n HeadlessIntentStatusResult,\n HeadlessPrepareResult,\n HeadlessSubmitOptions,\n HeadlessSubmitResult,\n InstallSmartSessionOptions,\n InstallSmartSessionResult,\n IntentTokenRequest,\n PasskeyProviderConfig,\n SponsorshipCallbackConfig,\n SponsorshipConfig,\n} from \"./types\";\nimport { tokenFetchError } from \"./sponsorship-fetch\";\n\nconst DEFAULT_PROVIDER_URL = \"https://passkey.1auth.box\";\n\nconst MISSING_APP_CREDENTIALS_MESSAGE =\n \"No sponsorship configured on OneAuthHeadlessClient. Every user intent must carry the app's JWT — pass `sponsorship: { accessToken, getExtensionToken }` (or URL form) to the constructor.\";\n\ntype AccessTokenFetchResult =\n | { ok: true; accessToken: string }\n | { ok: false; code?: \"MISSING_APP_CREDENTIALS\"; message: string };\n\ntype ExtensionTokenFetchResult =\n | { ok: true; extensionToken: string | undefined }\n | { ok: false; message: string };\n\n/**\n * Mirrors `normalizeSponsorship` in `client.ts`. Kept local so the\n * headless entry point doesn't pull in the whole OneAuthClient module\n * graph for callers that only need the headless surface.\n */\nfunction normalizeSponsorship(\n config: SponsorshipConfig | undefined,\n): SponsorshipCallbackConfig | null {\n if (!config) return null;\n if (\"accessToken\" in config && \"getExtensionToken\" in config) {\n return config;\n }\n const { accessTokenUrl, extensionTokenUrl } = config;\n return {\n accessToken: async () => {\n const response = await fetch(accessTokenUrl, { credentials: \"include\" });\n if (!response.ok) {\n throw await tokenFetchError(\"access token\", response);\n }\n const data = (await response.json()) as { token?: string };\n if (!data.token) {\n throw new Error(\"Access token response missing `token` field\");\n }\n return data.token;\n },\n getExtensionToken: async (intentOp: string) => {\n const response = await fetch(extensionTokenUrl, {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ intentOp }),\n });\n if (!response.ok) {\n throw await tokenFetchError(\"extension token\", response);\n }\n const data = (await response.json()) as { token?: string };\n if (!data.token) {\n throw new Error(\"Extension token response missing `token` field\");\n }\n return data.token;\n },\n };\n}\n\nexport class OneAuthHeadlessClient {\n private providerUrl: string;\n private clientId?: string;\n private sponsorship: SponsorshipCallbackConfig | null;\n\n constructor(config: PasskeyProviderConfig) {\n this.providerUrl = config.providerUrl || DEFAULT_PROVIDER_URL;\n this.clientId = config.clientId;\n this.sponsorship = normalizeSponsorship(config.sponsorship);\n }\n\n setSponsorship(sponsorship: SponsorshipConfig | undefined): void {\n this.sponsorship = normalizeSponsorship(sponsorship);\n }\n\n // ---------------------------------------------------------------------------\n // Sponsorship JWT fetchers\n // ---------------------------------------------------------------------------\n\n private async fetchAccessToken(): Promise<AccessTokenFetchResult> {\n if (!this.sponsorship) {\n return {\n ok: false,\n code: \"MISSING_APP_CREDENTIALS\",\n message: MISSING_APP_CREDENTIALS_MESSAGE,\n };\n }\n try {\n const accessToken = await this.sponsorship.accessToken();\n return { ok: true, accessToken };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n private async fetchExtensionToken(\n intentOp: string,\n sponsor: boolean,\n ): Promise<ExtensionTokenFetchResult> {\n if (!sponsor) return { ok: true, extensionToken: undefined };\n if (!this.sponsorship) {\n return { ok: false, message: MISSING_APP_CREDENTIALS_MESSAGE };\n }\n try {\n const token = await this.sponsorship.getExtensionToken(intentOp);\n return { ok: true, extensionToken: token };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // Intent prepare / submit\n // ---------------------------------------------------------------------------\n\n /**\n * Quote an intent without opening any dialog. Returns the orchestrator's\n * `intentOp` plus the digest the caller must sign with their own\n * validator (e.g. SmartSession). The caller is responsible for\n * encoding signatures and submitting via {@link submitIntent}.\n */\n async prepareIntent(options: HeadlessIntentOptions): Promise<HeadlessPrepareResult> {\n if (!options.username && !options.accountAddress) {\n throw new Error(\"prepareIntent requires either `username` or `accountAddress`\");\n }\n\n const accessTokenResult = await this.fetchAccessToken();\n if (!accessTokenResult.ok) {\n throw new Error(`Sponsorship access token fetch failed: ${accessTokenResult.message}`);\n }\n\n // bigint → string conversion for token requests; matches what the\n // dialog flow does before serializing requestBody.\n const tokenRequests = options.tokenRequests?.map((tr: IntentTokenRequest) => ({\n token: tr.token,\n amount: tr.amount.toString(),\n }));\n\n const body = {\n username: options.username,\n accountAddress: options.accountAddress,\n targetChain: options.targetChain,\n calls: options.calls,\n tokenRequests,\n sourceAssets: options.sourceAssets,\n sourceChainId: options.sourceChainId,\n sessionKeyHandle: options.sessionKeyHandle,\n clientId: this.clientId,\n signingMode: \"headless\" as const,\n auth: { accessToken: accessTokenResult.accessToken },\n };\n\n const response = await fetch(`${this.providerUrl}/api/intent/prepare`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as { error?: string };\n throw new Error(errorData.error || `Prepare failed (${response.status})`);\n }\n\n return (await response.json()) as HeadlessPrepareResult;\n }\n\n /**\n * Forward a pre-signed intent to the orchestrator. The caller has\n * already encoded validator-prefixed origin + destination signatures\n * (one origin signature per intent element); 1auth treats them as\n * opaque bytes.\n *\n * If `sponsor` is omitted or `true`, an extension token is fetched\n * just-in-time and bound to the intent. Pass `sponsor: false` for\n * self-paying intents.\n */\n async submitIntent(options: HeadlessSubmitOptions): Promise<HeadlessSubmitResult> {\n const sponsor = options.sponsor ?? true;\n const accessTokenResult = await this.fetchAccessToken();\n if (!accessTokenResult.ok) {\n throw new Error(`Sponsorship access token fetch failed: ${accessTokenResult.message}`);\n }\n\n const extensionResult = await this.fetchExtensionToken(options.intentOp, sponsor);\n if (!extensionResult.ok) {\n throw new Error(`Sponsorship extension token fetch failed: ${extensionResult.message}`);\n }\n\n const body = {\n intentOp: options.intentOp,\n accountAddress: options.accountAddress,\n targetChain: options.targetChain,\n calls: options.calls,\n expiresAt: options.expiresAt,\n originSignatures: options.originSignatures,\n destinationSignature: options.destinationSignature,\n targetExecutionSignature: options.targetExecutionSignature,\n auth: {\n accessToken: accessTokenResult.accessToken,\n ...(extensionResult.extensionToken && { extensionToken: extensionResult.extensionToken }),\n },\n };\n\n const response = await fetch(`${this.providerUrl}/api/intent/headless-execute`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as { error?: string };\n throw new Error(errorData.error || `Headless execute failed (${response.status})`);\n }\n\n return (await response.json()) as HeadlessSubmitResult;\n }\n\n // ---------------------------------------------------------------------------\n // Status / wait — proxies to the existing routes (no headless variant needed).\n // ---------------------------------------------------------------------------\n\n /**\n * Fetch the latest known status for a submitted headless intent.\n * This is a non-blocking read and may return `pending` before a\n * solver has produced a fill transaction hash.\n */\n async getIntentStatus(intentId: string): Promise<HeadlessIntentStatusResult> {\n const response = await fetch(`${this.providerUrl}/api/intent/status/${intentId}`);\n if (!response.ok) {\n throw new Error(`Status fetch failed (${response.status})`);\n }\n return (await response.json()) as HeadlessIntentStatusResult;\n }\n\n /**\n * Wait for a submitted headless intent to produce a status update and,\n * when available, the final fill transaction hash. The wait endpoint\n * needs the opaque `transactionResult` returned by submit because 1auth\n * does not persist that SDK object in its database.\n */\n async waitForIntent(\n intentId: string,\n transactionResult: unknown,\n ): Promise<HeadlessIntentStatusResult> {\n if (!transactionResult) {\n throw new Error(\"waitForIntent requires submitResult.transactionResult\");\n }\n\n const response = await fetch(`${this.providerUrl}/api/intent/wait/${intentId}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ transactionResult }),\n });\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n details?: string;\n };\n throw new Error(\n errorData.details || errorData.error || `Wait fetch failed (${response.status})`,\n );\n }\n return (await response.json()) as HeadlessIntentStatusResult;\n }\n\n // ---------------------------------------------------------------------------\n // SmartSession install (one-time, passkey-signed)\n // ---------------------------------------------------------------------------\n\n /**\n * Resolve the SmartSession install call(s) for `sessionKeyAddress`\n * with the supplied `permissions`.\n *\n * Returns `{ install, sessionKeyHandle }`:\n *\n * - `install` is a `{ targetChain, calls }` pair the caller feeds\n * straight into `OneAuthClient.sendIntent({ targetChain, calls })`\n * so the user passkey-signs the install via the existing dialog.\n * - `sessionKeyHandle` contains the deterministic `permissionId`\n * plus metadata to persist in localStorage. Persist this BEFORE\n * submitting the install so a refresh during signing doesn't\n * lose the handle.\n *\n * If the validator is already installed on the user's account,\n * `install.calls` is empty and `install.alreadyInstalled` is true.\n * The caller should still persist `sessionKeyHandle` — the on-chain\n * session enabling happens at first headless use via SmartSession's\n * ENABLE-mode signature wrapping (see follow-up).\n */\n async installSmartSession(\n options: InstallSmartSessionOptions,\n ): Promise<InstallSmartSessionResult> {\n if (!options.username && !options.accountAddress) {\n throw new Error(\n \"installSmartSession requires either `username` or `accountAddress`\",\n );\n }\n\n const accessTokenResult = await this.fetchAccessToken();\n if (!accessTokenResult.ok) {\n throw new Error(\n `Sponsorship access token fetch failed: ${accessTokenResult.message}`,\n );\n }\n\n const body = {\n username: options.username,\n accountAddress: options.accountAddress,\n targetChain: options.targetChain,\n sessionKeyAddress: options.sessionKeyAddress,\n permissions: options.permissions,\n validUntil: options.validUntil,\n validAfter: options.validAfter,\n maxUses: options.maxUses,\n enableSessionSignature: options.enableSessionSignature,\n label: options.label,\n auth: { accessToken: accessTokenResult.accessToken },\n };\n\n const response = await fetch(`${this.providerUrl}/api/sessions/install`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(errorData.error || `Install failed (${response.status})`);\n }\n\n return (await response.json()) as InstallSmartSessionResult;\n }\n}\n","import { type Address, type Hex } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport {\n createRhinestoneAccount,\n type Session,\n type SignData,\n type SignerSet,\n} from \"@rhinestone/sdk\";\nimport { toSession } from \"@rhinestone/sdk/smart-sessions\";\nimport { getChainById } from \"./registry\";\nimport type { HeadlessPrepareResult, SessionKeyHandle } from \"./types\";\n\n/** Restores bigint sentinel strings emitted by 1auth's JSON transport. */\nfunction reviveBigIntStrings<T>(value: T): T {\n if (Array.isArray(value)) return value.map((entry) => reviveBigIntStrings(entry)) as T;\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [key, reviveBigIntStrings(entry)]),\n ) as T;\n }\n if (typeof value === \"string\" && value.startsWith(\"__bigint:\")) {\n return BigInt(value.slice(\"__bigint:\".length)) as T;\n }\n if (typeof value === \"string\" && /^\\d+$/.test(value)) return BigInt(value) as T;\n return value;\n}\n\n/** Parses the prepared transaction enough to recover the SDK-native SignData. */\nfunction parsePreparedSignData(value: string): SignData {\n const prepared = JSON.parse(value, (_key, nested) => reviveBigIntStrings(nested)) as {\n quotes?: { best?: { signData?: SignData } };\n };\n const signData = prepared.quotes?.best?.signData;\n if (!signData) {\n throw new Error(\"Prepared headless intent is missing quotes.best.signData\");\n }\n return signData;\n}\n\n/** Reads the numeric EIP-712 chain id from a typed-data domain. */\nfunction chainIdFromSignDataDomain(domainChainId: unknown): number | undefined {\n if (typeof domainChainId === \"number\" && Number.isSafeInteger(domainChainId)) {\n return domainChainId;\n }\n if (typeof domainChainId === \"bigint\") return Number(domainChainId);\n if (typeof domainChainId === \"string\" && /^\\d+$/.test(domainChainId)) {\n return Number(domainChainId);\n }\n return undefined;\n}\n\n/** Rebuilds the SDK SmartSession object from the persisted grant handle. */\nfunction buildSessionForChain(args: {\n privateKey: Hex;\n handle: SessionKeyHandle;\n chainId: number;\n}): Session {\n return toSession(\n {\n chain: getChainById(args.chainId),\n owners: { type: \"ecdsa\", accounts: [privateKeyToAccount(args.privateKey)] },\n permissions: reviveBigIntStrings(args.handle.permissions ?? []),\n crossChainPermits: reviveBigIntStrings(args.handle.crossChainPermits ?? []),\n },\n // The production SmartSession module is deployed on testnets too. Never opt\n // into SDK dev contracts for 1auth headless permissions.\n { useDevContracts: false },\n );\n}\n\n/** Builds a per-chain SmartSession signer set for every chain in SignData. */\nfunction buildSessionSigners(args: {\n privateKey: Hex;\n handle: SessionKeyHandle;\n prepared: HeadlessPrepareResult;\n signData: SignData;\n}): SignerSet {\n const chainIds = new Set<number>([args.prepared.targetChain]);\n for (const typedData of args.signData.origin) {\n const chainId = chainIdFromSignDataDomain(typedData.domain?.chainId);\n if (chainId) chainIds.add(chainId);\n }\n const targetExecutionChainId = chainIdFromSignDataDomain(\n args.signData.targetExecution?.domain?.chainId,\n );\n if (targetExecutionChainId) chainIds.add(targetExecutionChainId);\n\n return {\n type: \"experimental_session\",\n sessions: Object.fromEntries(\n [...chainIds].map((chainId) => [\n chainId,\n {\n session: buildSessionForChain({\n privateKey: args.privateKey,\n handle: args.handle,\n chainId,\n }),\n },\n ]),\n ),\n };\n}\n\nexport interface BuildSmartSessionHeadlessSignaturesOptions {\n /** ECDSA private key for the locally-held SmartSession signer. */\n privateKey: Hex;\n /** Smart account address the SmartSession is scoped to. */\n accountAddress: Address;\n /** Persisted handle returned by `grantPermissions` / SmartSession install. */\n sessionKeyHandle: SessionKeyHandle;\n /** Prepared headless intent returned by `OneAuthHeadlessClient.prepareIntent`. */\n prepared: HeadlessPrepareResult;\n}\n\n/**\n * Builds SmartSession signatures for `OneAuthHeadlessClient.submitIntent`.\n *\n * This intentionally delegates signing and SmartSession signature packing to\n * `@rhinestone/sdk`. 1auth only rebuilds the persisted session descriptor and\n * supplies the SDK-native `SignData` returned by the orchestrator quote.\n */\nexport async function buildSmartSessionHeadlessSignatures(\n options: BuildSmartSessionHeadlessSignaturesOptions,\n) {\n const signData = parsePreparedSignData(options.prepared.intentOp);\n const account = await createRhinestoneAccount({\n initData: { address: options.accountAddress },\n owners: {\n type: \"ecdsa\",\n accounts: [privateKeyToAccount(options.privateKey)],\n },\n experimental_sessions: { enabled: true },\n });\n\n return account.signIntent(\n signData,\n getChainById(options.prepared.targetChain),\n buildSessionSigners({\n privateKey: options.privateKey,\n handle: options.sessionKeyHandle,\n prepared: options.prepared,\n signData,\n }),\n );\n}\n","/**\n * @file Chain and token registry for the 1auth SDK.\n *\n * Wraps `@rhinestone/shared-configs` chain/token data and combines it with\n * viem's chain definitions to expose a filtered, testnet-aware registry.\n * Consumers can look up supported chains and tokens, resolve token addresses\n * by symbol, and retrieve chain metadata such as explorer URLs and default RPC\n * endpoints.\n *\n * Testnet inclusion is controlled by the `includeTestnets` option on each\n * function or, as a project-wide default, by the environment variables\n * `NEXT_PUBLIC_ORCHESTRATOR_USE_TESTNETS` or `ORCHESTRATOR_USE_TESTNETS`.\n */\n\nimport type { Address, Chain } from \"viem\";\nimport { isAddress } from \"viem\";\nimport * as viemChains from \"viem/chains\";\nimport { chainRegistry } from \"@rhinestone/shared-configs\";\n\nexport type TokenConfig = {\n symbol: string;\n address: Address;\n decimals: number;\n};\n\nexport type ChainFilterOptions = {\n includeTestnets?: boolean;\n chainIds?: number[];\n};\n\ntype ChainRegistryEntry = (typeof chainRegistry)[keyof typeof chainRegistry];\n\nconst env: Record<string, string | undefined> =\n typeof process !== \"undefined\" ? process.env : {};\n\n// Build a chain-ID-to-Chain map from viem, resolving collisions by preferring\n// mainnet definitions over testnets. viem exports duplicate numeric IDs (e.g.\n// zoraTestnet and hyperEvm both use 999); a naive Map would silently keep\n// whichever entry happens to appear last in iteration order, which may be the\n// testnet. The loop below only overwrites an existing entry when the incoming\n// chain is NOT a testnet and the existing one IS, ensuring the production chain\n// always wins while still falling back to a testnet entry when no mainnet\n// definition exists for a given ID.\nconst VIEM_CHAIN_BY_ID = new Map<number, Chain>();\nfor (const value of Object.values(viemChains)) {\n if (typeof value !== \"object\" || value === null || !(\"id\" in value) || !(\"name\" in value)) continue;\n const chain = value as Chain;\n const existing = VIEM_CHAIN_BY_ID.get(chain.id);\n if (!existing || (existing.testnet && !chain.testnet)) {\n VIEM_CHAIN_BY_ID.set(chain.id, chain);\n }\n}\n\nfunction isEvmRegistryEntry(\n entry: ChainRegistryEntry | undefined,\n): entry is ChainRegistryEntry & { vmType: \"evm\" } {\n return entry?.vmType === \"evm\";\n}\n\nfunction getEvmRegistryEntry(\n chainId: number,\n): (ChainRegistryEntry & { vmType: \"evm\" }) | undefined {\n const entry = chainRegistry[String(chainId) as keyof typeof chainRegistry];\n return isEvmRegistryEntry(entry) ? entry : undefined;\n}\n\n// The shared-configs registry includes non-EVM chains (Solana, Tron). Filter\n// to EVM entries before exposing supported chains — downstream consumers\n// (viem clients, wallet_getCapabilities, RPC proxy) only handle eip155 chains.\nconst REGISTRY_CHAIN_IDS = Object.entries(chainRegistry)\n .filter(([, entry]) => isEvmRegistryEntry(entry))\n .map(([id]) => Number(id));\nconst SUPPORTED_CHAIN_IDS = new Set(REGISTRY_CHAIN_IDS);\n\nfunction tokensForChain(chainId: number): TokenConfig[] {\n const entry = getEvmRegistryEntry(chainId);\n if (!entry) return [];\n return entry.tokens.map((token) => ({\n symbol: token.symbol,\n address: token.address as Address,\n decimals: token.decimals,\n }));\n}\n\n/** Treat any 20-byte hex string as an address; checksum casing is optional for user inputs. */\nfunction isAddressInput(value: string): value is Address {\n return isAddress(value, { strict: false });\n}\n\n/**\n * Parse a string environment variable into a boolean, returning `undefined`\n * when the value is absent or not a recognised truthy/falsy literal.\n *\n * Accepted truthy values: `\"true\"`, `\"1\"`.\n * Accepted falsy values: `\"false\"`, `\"0\"`.\n */\nfunction parseBool(value?: string): boolean | undefined {\n if (value === \"true\" || value === \"1\") return true;\n if (value === \"false\" || value === \"0\") return false;\n return undefined;\n}\n\n/**\n * Determine whether testnet chains should be included in registry results.\n *\n * Precedence (highest to lowest):\n * 1. `explicit` argument — a caller-supplied boolean always wins.\n * 2. `NEXT_PUBLIC_ORCHESTRATOR_USE_TESTNETS` env var — checked first so\n * Next.js browser bundles (which only expose `NEXT_PUBLIC_*` variables)\n * can configure testnet mode without a server-side env var.\n * 3. `ORCHESTRATOR_USE_TESTNETS` env var — server-side / Node.js fallback.\n * 4. Defaults to `false` (testnets excluded) when none of the above is set.\n */\nfunction resolveIncludeTestnets(explicit?: boolean): boolean {\n if (explicit !== undefined) return explicit;\n const envValue =\n parseBool(env.NEXT_PUBLIC_ORCHESTRATOR_USE_TESTNETS) ??\n parseBool(env.ORCHESTRATOR_USE_TESTNETS);\n return envValue ?? false;\n}\n\nfunction applyChainFilters(chainIds: number[], options?: ChainFilterOptions): number[] {\n const includeTestnets = resolveIncludeTestnets(options?.includeTestnets);\n const allowlist = options?.chainIds;\n let filtered = chainIds;\n\n if (!includeTestnets) {\n filtered = filtered.filter((chainId) => !isTestnet(chainId));\n }\n\n if (allowlist) {\n const allowed = new Set(allowlist);\n filtered = filtered.filter((chainId) => allowed.has(chainId));\n }\n\n return filtered;\n}\n\nexport function getSupportedChainIds(options?: ChainFilterOptions): number[] {\n return applyChainFilters(REGISTRY_CHAIN_IDS, options);\n}\n\nexport function getSupportedChains(options?: ChainFilterOptions): Chain[] {\n return getSupportedChainIds(options)\n .map((chainId) => VIEM_CHAIN_BY_ID.get(chainId))\n .filter((chain): chain is Chain => Boolean(chain));\n}\n\nexport function getAllSupportedChainsAndTokens(options?: ChainFilterOptions): Array<{\n chainId: number;\n tokens: TokenConfig[];\n}> {\n return getSupportedChainIds(options).map((chainId) => ({\n chainId,\n tokens: tokensForChain(chainId),\n }));\n}\n\nexport function getChainById(chainId: number): Chain {\n if (!SUPPORTED_CHAIN_IDS.has(chainId)) {\n throw new Error(`Unsupported chain ID: ${chainId}`);\n }\n const chain = VIEM_CHAIN_BY_ID.get(chainId);\n if (!chain) {\n throw new Error(`Unsupported chain ID: ${chainId}`);\n }\n return chain;\n}\n\nexport function getChainName(chainId: number): string {\n try {\n return getChainById(chainId).name;\n } catch {\n return `Chain ${chainId}`;\n }\n}\n\nexport function getChainExplorerUrl(chainId: number): string | undefined {\n try {\n return getChainById(chainId).blockExplorers?.default?.url;\n } catch {\n return undefined;\n }\n}\n\nexport function getChainRpcUrl(chainId: number): string | undefined {\n try {\n const chain = getChainById(chainId);\n return chain.rpcUrls?.default?.http?.[0] || chain.rpcUrls?.public?.http?.[0];\n } catch {\n return undefined;\n }\n}\n\nexport function getSupportedTokens(chainId: number): TokenConfig[] {\n return tokensForChain(chainId);\n}\n\nexport function getSupportedTokenSymbols(chainId: number): string[] {\n return getSupportedTokens(chainId).map((token) => token.symbol);\n}\n\nexport function getTokenAddress(symbolOrAddress: string, chainId: number): Address {\n if (isAddressInput(symbolOrAddress)) {\n return symbolOrAddress;\n }\n const match = getSupportedTokens(chainId).find(\n (t) => t.symbol.toUpperCase() === symbolOrAddress.toUpperCase()\n );\n if (!match) {\n throw new Error(`Unsupported token \"${symbolOrAddress}\" on chain ${chainId}`);\n }\n return match.address;\n}\n\nexport function getTokenDecimals(symbolOrAddress: string, chainId: number): number {\n const match = getSupportedTokens(chainId).find(\n (t) =>\n isAddressInput(symbolOrAddress)\n ? t.address.toLowerCase() === symbolOrAddress.toLowerCase()\n : t.symbol.toUpperCase() === symbolOrAddress.toUpperCase()\n );\n if (!match && isAddressInput(symbolOrAddress) && SUPPORTED_CHAIN_IDS.has(chainId)) {\n return 18;\n }\n if (!match) {\n throw new Error(`Unsupported token \"${symbolOrAddress}\" on chain ${chainId}`);\n }\n return match.decimals;\n}\n\nexport function resolveTokenAddress(token: string, chainId: number): Address {\n if (isAddressInput(token)) {\n return token;\n }\n return getTokenAddress(token, chainId);\n}\n\nexport function isTestnet(chainId: number): boolean {\n try {\n return getChainById(chainId).testnet ?? false;\n } catch {\n return false;\n }\n}\n\nexport function getTokenSymbol(tokenAddress: Address, chainId: number): string {\n const token = getSupportedTokens(chainId).find(\n (entry) => entry.address.toLowerCase() === tokenAddress.toLowerCase()\n );\n if (token) {\n return token.symbol;\n }\n if (!SUPPORTED_CHAIN_IDS.has(chainId)) {\n throw new Error(`Unsupported chain ID: ${chainId}`);\n }\n return \"Token\";\n}\n\nexport function isTokenAddressSupported(tokenAddress: Address, chainId: number): boolean {\n return isAddressInput(tokenAddress) && SUPPORTED_CHAIN_IDS.has(chainId);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/headless.ts","../src/sponsorship-fetch.ts","../src/headless-client.ts","../src/smart-session-signatures.ts","../src/registry.ts"],"sourcesContent":["/**\n * Public entry point for the headless 1auth SDK.\n *\n * Exposes {@link OneAuthHeadlessClient} plus the request/response types\n * an integrating app needs when using its own ERC-7579 validator (e.g.\n * the experimental SmartSession from `@rhinestone/sdk`) to sign intents\n * locally instead of going through the passkey dialog.\n */\n\nexport { OneAuthHeadlessClient } from \"./headless-client\";\nexport {\n buildSmartSessionHeadlessSignatures,\n type BuildSmartSessionHeadlessSignaturesOptions,\n} from \"./smart-session-signatures\";\n\nexport type {\n HeadlessIntentStatusResult,\n HeadlessIntentOptions,\n HeadlessPrepareResult,\n HeadlessSubmitOptions,\n HeadlessSubmitResult,\n InstallSmartSessionOptions,\n InstallSmartSessionResult,\n SessionKeyHandle,\n SmartSessionEnableRequest,\n} from \"./types\";\n","/**\n * Shared helpers for fetching sponsorship tokens (access + extension) from an\n * integrator's backend endpoints.\n *\n * The integrator's token routes return their failure reason in the JSON body\n * (`{ error: \"createSponsorshipSigner: missing env var(s): ...\" }`). Surfacing\n * only the HTTP status — \"Failed to fetch access token (500 ...)\" — hides that\n * reason and turns every misconfiguration into the same opaque dialog error.\n * These helpers read the body and fold the server's message into the thrown\n * Error so the actual cause (missing env var, bad JWK, expired session) is\n * visible at the call site and in the dialog.\n */\n\n/**\n * Pull a human-readable reason out of a failed token response. Tries the JSON\n * `error`/`message` fields first, then falls back to a short text snippet, then\n * to the HTTP status text. Never throws — diagnostics must not mask the original\n * failure with a parse error.\n */\nasync function extractServerReason(response: Response): Promise<string> {\n try {\n // Clone so a JSON parse failure can still fall back to reading text.\n const text = await response.clone().text();\n if (!text) return response.statusText;\n try {\n const data = JSON.parse(text) as { error?: unknown; message?: unknown };\n const reason = data.error ?? data.message;\n if (typeof reason === \"string\" && reason.trim()) return reason;\n } catch {\n // Body wasn't JSON — fall through to the raw text snippet.\n }\n // Cap the snippet so an HTML error page doesn't flood the message.\n return text.slice(0, 200);\n } catch {\n return response.statusText;\n }\n}\n\n/**\n * Build an Error for a failed token fetch that includes the server's reason.\n * `label` names the token kind, e.g. \"access token\" or \"extension token\".\n */\nexport async function tokenFetchError(\n label: string,\n response: Response,\n): Promise<Error> {\n const reason = await extractServerReason(response);\n const suffix = reason ? `: ${reason}` : \"\";\n return new Error(\n `Failed to fetch ${label} (${response.status} ${response.statusText})${suffix}`,\n );\n}\n","/**\n * Headless 1auth client.\n *\n * Used by integrators that hold their own ECDSA signer in localStorage\n * and produce signatures for an ERC-7579 validator other than the\n * passkey one (typically `@rhinestone/sdk` experimental SmartSession).\n *\n * Responsibilities:\n * - Fetch sponsorship JWTs from the app's own backend.\n * - Call `/api/intent/prepare?signingMode=headless` to get an\n * orchestrator-quoted `intentOp` + `digestResult`.\n * - Forward pre-encoded validator-prefixed signatures to the new\n * `/api/intent/headless-execute` route.\n * - Drive the existing passkey dialog (via {@link OneAuthClient}) for\n * the one-time SmartSession install ceremony.\n *\n * 1auth itself stays ignorant of session keys — the on-chain\n * SmartSession validator is the only authority over what a session key\n * may sign for. The host app persists `{ sessionKeyAddress, permissionId,\n * accountAddress, permissions }` in its own storage.\n */\n\nimport type {\n HeadlessIntentOptions,\n HeadlessIntentStatusResult,\n HeadlessPrepareResult,\n HeadlessSubmitOptions,\n HeadlessSubmitResult,\n InstallSmartSessionOptions,\n InstallSmartSessionResult,\n IntentTokenRequest,\n PasskeyProviderConfig,\n SponsorshipCallbackConfig,\n SponsorshipConfig,\n} from \"./types\";\nimport { tokenFetchError } from \"./sponsorship-fetch\";\n\nconst DEFAULT_PROVIDER_URL = \"https://passkey.1auth.app\";\n\nconst MISSING_APP_CREDENTIALS_MESSAGE =\n \"No sponsorship configured on OneAuthHeadlessClient. Every user intent must carry the app's JWT — pass `sponsorship: { accessToken, getExtensionToken }` (or URL form) to the constructor.\";\n\ntype AccessTokenFetchResult =\n | { ok: true; accessToken: string }\n | { ok: false; code?: \"MISSING_APP_CREDENTIALS\"; message: string };\n\ntype ExtensionTokenFetchResult =\n | { ok: true; extensionToken: string | undefined }\n | { ok: false; message: string };\n\n/**\n * Mirrors `normalizeSponsorship` in `client.ts`. Kept local so the\n * headless entry point doesn't pull in the whole OneAuthClient module\n * graph for callers that only need the headless surface.\n */\nfunction normalizeSponsorship(\n config: SponsorshipConfig | undefined,\n): SponsorshipCallbackConfig | null {\n if (!config) return null;\n if (\"accessToken\" in config && \"getExtensionToken\" in config) {\n return config;\n }\n const { accessTokenUrl, extensionTokenUrl } = config;\n return {\n accessToken: async () => {\n const response = await fetch(accessTokenUrl, { credentials: \"include\" });\n if (!response.ok) {\n throw await tokenFetchError(\"access token\", response);\n }\n const data = (await response.json()) as { token?: string };\n if (!data.token) {\n throw new Error(\"Access token response missing `token` field\");\n }\n return data.token;\n },\n getExtensionToken: async (intentOp: string) => {\n const response = await fetch(extensionTokenUrl, {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ intentOp }),\n });\n if (!response.ok) {\n throw await tokenFetchError(\"extension token\", response);\n }\n const data = (await response.json()) as { token?: string };\n if (!data.token) {\n throw new Error(\"Extension token response missing `token` field\");\n }\n return data.token;\n },\n };\n}\n\nexport class OneAuthHeadlessClient {\n private providerUrl: string;\n private clientId?: string;\n private sponsorship: SponsorshipCallbackConfig | null;\n\n constructor(config: PasskeyProviderConfig) {\n this.providerUrl = config.providerUrl || DEFAULT_PROVIDER_URL;\n this.clientId = config.clientId;\n this.sponsorship = normalizeSponsorship(config.sponsorship);\n }\n\n setSponsorship(sponsorship: SponsorshipConfig | undefined): void {\n this.sponsorship = normalizeSponsorship(sponsorship);\n }\n\n // ---------------------------------------------------------------------------\n // Sponsorship JWT fetchers\n // ---------------------------------------------------------------------------\n\n private async fetchAccessToken(): Promise<AccessTokenFetchResult> {\n if (!this.sponsorship) {\n return {\n ok: false,\n code: \"MISSING_APP_CREDENTIALS\",\n message: MISSING_APP_CREDENTIALS_MESSAGE,\n };\n }\n try {\n const accessToken = await this.sponsorship.accessToken();\n return { ok: true, accessToken };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n private async fetchExtensionToken(\n intentOp: string,\n sponsor: boolean,\n ): Promise<ExtensionTokenFetchResult> {\n if (!sponsor) return { ok: true, extensionToken: undefined };\n if (!this.sponsorship) {\n return { ok: false, message: MISSING_APP_CREDENTIALS_MESSAGE };\n }\n try {\n const token = await this.sponsorship.getExtensionToken(intentOp);\n return { ok: true, extensionToken: token };\n } catch (err) {\n return {\n ok: false,\n message: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // Intent prepare / submit\n // ---------------------------------------------------------------------------\n\n /**\n * Quote an intent without opening any dialog. Returns the orchestrator's\n * `intentOp` plus the digest the caller must sign with their own\n * validator (e.g. SmartSession). The caller is responsible for\n * encoding signatures and submitting via {@link submitIntent}.\n */\n async prepareIntent(options: HeadlessIntentOptions): Promise<HeadlessPrepareResult> {\n if (!options.username && !options.accountAddress) {\n throw new Error(\"prepareIntent requires either `username` or `accountAddress`\");\n }\n\n const accessTokenResult = await this.fetchAccessToken();\n if (!accessTokenResult.ok) {\n throw new Error(`Sponsorship access token fetch failed: ${accessTokenResult.message}`);\n }\n\n // bigint → string conversion for token requests; matches what the\n // dialog flow does before serializing requestBody.\n const tokenRequests = options.tokenRequests?.map((tr: IntentTokenRequest) => ({\n token: tr.token,\n amount: tr.amount.toString(),\n }));\n\n const body = {\n username: options.username,\n accountAddress: options.accountAddress,\n targetChain: options.targetChain,\n calls: options.calls,\n tokenRequests,\n sourceAssets: options.sourceAssets,\n sourceChainId: options.sourceChainId,\n sessionKeyHandle: options.sessionKeyHandle,\n clientId: this.clientId,\n signingMode: \"headless\" as const,\n auth: { accessToken: accessTokenResult.accessToken },\n };\n\n const response = await fetch(`${this.providerUrl}/api/intent/prepare`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as { error?: string };\n throw new Error(errorData.error || `Prepare failed (${response.status})`);\n }\n\n return (await response.json()) as HeadlessPrepareResult;\n }\n\n /**\n * Forward a pre-signed intent to the orchestrator. The caller has\n * already encoded validator-prefixed origin + destination signatures\n * (one origin signature per intent element); 1auth treats them as\n * opaque bytes.\n *\n * If `sponsor` is omitted or `true`, an extension token is fetched\n * just-in-time and bound to the intent. Pass `sponsor: false` for\n * self-paying intents.\n */\n async submitIntent(options: HeadlessSubmitOptions): Promise<HeadlessSubmitResult> {\n const sponsor = options.sponsor ?? true;\n const accessTokenResult = await this.fetchAccessToken();\n if (!accessTokenResult.ok) {\n throw new Error(`Sponsorship access token fetch failed: ${accessTokenResult.message}`);\n }\n\n const extensionResult = await this.fetchExtensionToken(options.intentOp, sponsor);\n if (!extensionResult.ok) {\n throw new Error(`Sponsorship extension token fetch failed: ${extensionResult.message}`);\n }\n\n const body = {\n intentOp: options.intentOp,\n accountAddress: options.accountAddress,\n targetChain: options.targetChain,\n calls: options.calls,\n expiresAt: options.expiresAt,\n originSignatures: options.originSignatures,\n destinationSignature: options.destinationSignature,\n targetExecutionSignature: options.targetExecutionSignature,\n auth: {\n accessToken: accessTokenResult.accessToken,\n ...(extensionResult.extensionToken && { extensionToken: extensionResult.extensionToken }),\n },\n };\n\n const response = await fetch(`${this.providerUrl}/api/intent/headless-execute`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as { error?: string };\n throw new Error(errorData.error || `Headless execute failed (${response.status})`);\n }\n\n return (await response.json()) as HeadlessSubmitResult;\n }\n\n // ---------------------------------------------------------------------------\n // Status / wait — proxies to the existing routes (no headless variant needed).\n // ---------------------------------------------------------------------------\n\n /**\n * Fetch the latest known status for a submitted headless intent.\n * This is a non-blocking read and may return `pending` before a\n * solver has produced a fill transaction hash.\n */\n async getIntentStatus(intentId: string): Promise<HeadlessIntentStatusResult> {\n const response = await fetch(`${this.providerUrl}/api/intent/status/${intentId}`);\n if (!response.ok) {\n throw new Error(`Status fetch failed (${response.status})`);\n }\n return (await response.json()) as HeadlessIntentStatusResult;\n }\n\n /**\n * Wait for a submitted headless intent to produce a status update and,\n * when available, the final fill transaction hash. The wait endpoint\n * needs the opaque `transactionResult` returned by submit because 1auth\n * does not persist that SDK object in its database.\n */\n async waitForIntent(\n intentId: string,\n transactionResult: unknown,\n ): Promise<HeadlessIntentStatusResult> {\n if (!transactionResult) {\n throw new Error(\"waitForIntent requires submitResult.transactionResult\");\n }\n\n const response = await fetch(`${this.providerUrl}/api/intent/wait/${intentId}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ transactionResult }),\n });\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n details?: string;\n };\n throw new Error(\n errorData.details || errorData.error || `Wait fetch failed (${response.status})`,\n );\n }\n return (await response.json()) as HeadlessIntentStatusResult;\n }\n\n // ---------------------------------------------------------------------------\n // SmartSession install (one-time, passkey-signed)\n // ---------------------------------------------------------------------------\n\n /**\n * Resolve the SmartSession install call(s) for `sessionKeyAddress`\n * with the supplied `permissions`.\n *\n * Returns `{ install, sessionKeyHandle }`:\n *\n * - `install` is a `{ targetChain, calls }` pair the caller feeds\n * straight into `OneAuthClient.sendIntent({ targetChain, calls })`\n * so the user passkey-signs the install via the existing dialog.\n * - `sessionKeyHandle` contains the deterministic `permissionId`\n * plus metadata to persist in localStorage. Persist this BEFORE\n * submitting the install so a refresh during signing doesn't\n * lose the handle.\n *\n * If the validator is already installed on the user's account,\n * `install.calls` is empty and `install.alreadyInstalled` is true.\n * The caller should still persist `sessionKeyHandle` — the on-chain\n * session enabling happens at first headless use via SmartSession's\n * ENABLE-mode signature wrapping (see follow-up).\n */\n async installSmartSession(\n options: InstallSmartSessionOptions,\n ): Promise<InstallSmartSessionResult> {\n if (!options.username && !options.accountAddress) {\n throw new Error(\n \"installSmartSession requires either `username` or `accountAddress`\",\n );\n }\n\n const accessTokenResult = await this.fetchAccessToken();\n if (!accessTokenResult.ok) {\n throw new Error(\n `Sponsorship access token fetch failed: ${accessTokenResult.message}`,\n );\n }\n\n const body = {\n username: options.username,\n accountAddress: options.accountAddress,\n targetChain: options.targetChain,\n sessionKeyAddress: options.sessionKeyAddress,\n permissions: options.permissions,\n validUntil: options.validUntil,\n validAfter: options.validAfter,\n maxUses: options.maxUses,\n enableSessionSignature: options.enableSessionSignature,\n label: options.label,\n auth: { accessToken: accessTokenResult.accessToken },\n };\n\n const response = await fetch(`${this.providerUrl}/api/sessions/install`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorData = (await response.json().catch(() => ({}))) as {\n error?: string;\n };\n throw new Error(errorData.error || `Install failed (${response.status})`);\n }\n\n return (await response.json()) as InstallSmartSessionResult;\n }\n}\n","import { type Address, type Hex } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport {\n createRhinestoneAccount,\n type Session,\n type SignData,\n type SignerSet,\n} from \"@rhinestone/sdk\";\nimport { toSession } from \"@rhinestone/sdk/smart-sessions\";\nimport { getChainById } from \"./registry\";\nimport type { HeadlessPrepareResult, SessionKeyHandle } from \"./types\";\n\n/** Restores bigint sentinel strings emitted by 1auth's JSON transport. */\nfunction reviveBigIntStrings<T>(value: T): T {\n if (Array.isArray(value)) return value.map((entry) => reviveBigIntStrings(entry)) as T;\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [key, reviveBigIntStrings(entry)]),\n ) as T;\n }\n if (typeof value === \"string\" && value.startsWith(\"__bigint:\")) {\n return BigInt(value.slice(\"__bigint:\".length)) as T;\n }\n if (typeof value === \"string\" && /^\\d+$/.test(value)) return BigInt(value) as T;\n return value;\n}\n\n/** Parses the prepared transaction enough to recover the SDK-native SignData. */\nfunction parsePreparedSignData(value: string): SignData {\n const prepared = JSON.parse(value, (_key, nested) => reviveBigIntStrings(nested)) as {\n quotes?: { best?: { signData?: SignData } };\n };\n const signData = prepared.quotes?.best?.signData;\n if (!signData) {\n throw new Error(\"Prepared headless intent is missing quotes.best.signData\");\n }\n return signData;\n}\n\n/** Reads the numeric EIP-712 chain id from a typed-data domain. */\nfunction chainIdFromSignDataDomain(domainChainId: unknown): number | undefined {\n if (typeof domainChainId === \"number\" && Number.isSafeInteger(domainChainId)) {\n return domainChainId;\n }\n if (typeof domainChainId === \"bigint\") return Number(domainChainId);\n if (typeof domainChainId === \"string\" && /^\\d+$/.test(domainChainId)) {\n return Number(domainChainId);\n }\n return undefined;\n}\n\n/** Rebuilds the SDK SmartSession object from the persisted grant handle. */\nfunction buildSessionForChain(args: {\n privateKey: Hex;\n handle: SessionKeyHandle;\n chainId: number;\n}): Session {\n return toSession(\n {\n chain: getChainById(args.chainId),\n owners: { type: \"ecdsa\", accounts: [privateKeyToAccount(args.privateKey)] },\n permissions: reviveBigIntStrings(args.handle.permissions ?? []),\n crossChainPermits: reviveBigIntStrings(args.handle.crossChainPermits ?? []),\n },\n // The production SmartSession module is deployed on testnets too. Never opt\n // into SDK dev contracts for 1auth headless permissions.\n { useDevContracts: false },\n );\n}\n\n/** Builds a per-chain SmartSession signer set for every chain in SignData. */\nfunction buildSessionSigners(args: {\n privateKey: Hex;\n handle: SessionKeyHandle;\n prepared: HeadlessPrepareResult;\n signData: SignData;\n}): SignerSet {\n const chainIds = new Set<number>([args.prepared.targetChain]);\n for (const typedData of args.signData.origin) {\n const chainId = chainIdFromSignDataDomain(typedData.domain?.chainId);\n if (chainId) chainIds.add(chainId);\n }\n const targetExecutionChainId = chainIdFromSignDataDomain(\n args.signData.targetExecution?.domain?.chainId,\n );\n if (targetExecutionChainId) chainIds.add(targetExecutionChainId);\n\n return {\n type: \"experimental_session\",\n sessions: Object.fromEntries(\n [...chainIds].map((chainId) => [\n chainId,\n {\n session: buildSessionForChain({\n privateKey: args.privateKey,\n handle: args.handle,\n chainId,\n }),\n },\n ]),\n ),\n };\n}\n\nexport interface BuildSmartSessionHeadlessSignaturesOptions {\n /** ECDSA private key for the locally-held SmartSession signer. */\n privateKey: Hex;\n /** Smart account address the SmartSession is scoped to. */\n accountAddress: Address;\n /** Persisted handle returned by `grantPermissions` / SmartSession install. */\n sessionKeyHandle: SessionKeyHandle;\n /** Prepared headless intent returned by `OneAuthHeadlessClient.prepareIntent`. */\n prepared: HeadlessPrepareResult;\n}\n\n/**\n * Builds SmartSession signatures for `OneAuthHeadlessClient.submitIntent`.\n *\n * This intentionally delegates signing and SmartSession signature packing to\n * `@rhinestone/sdk`. 1auth only rebuilds the persisted session descriptor and\n * supplies the SDK-native `SignData` returned by the orchestrator quote.\n */\nexport async function buildSmartSessionHeadlessSignatures(\n options: BuildSmartSessionHeadlessSignaturesOptions,\n) {\n const signData = parsePreparedSignData(options.prepared.intentOp);\n const account = await createRhinestoneAccount({\n initData: { address: options.accountAddress },\n owners: {\n type: \"ecdsa\",\n accounts: [privateKeyToAccount(options.privateKey)],\n },\n experimental_sessions: { enabled: true },\n });\n\n return account.signIntent(\n signData,\n getChainById(options.prepared.targetChain),\n buildSessionSigners({\n privateKey: options.privateKey,\n handle: options.sessionKeyHandle,\n prepared: options.prepared,\n signData,\n }),\n );\n}\n","/**\n * @file Chain and token registry for the 1auth SDK.\n *\n * Wraps `@rhinestone/shared-configs` chain/token data and combines it with\n * viem's chain definitions to expose a filtered, testnet-aware registry.\n * Consumers can look up supported chains and tokens, resolve token addresses\n * by symbol, and retrieve chain metadata such as explorer URLs and default RPC\n * endpoints.\n *\n * Testnet inclusion is controlled by the `includeTestnets` option on each\n * function or, as a project-wide default, by the environment variables\n * `NEXT_PUBLIC_ORCHESTRATOR_USE_TESTNETS` or `ORCHESTRATOR_USE_TESTNETS`.\n */\n\nimport type { Address, Chain } from \"viem\";\nimport { isAddress } from \"viem\";\nimport * as viemChains from \"viem/chains\";\nimport { chainRegistry } from \"@rhinestone/shared-configs\";\n\nexport type TokenConfig = {\n symbol: string;\n address: Address;\n decimals: number;\n};\n\nexport type ChainFilterOptions = {\n includeTestnets?: boolean;\n chainIds?: number[];\n};\n\ntype ChainRegistryEntry = (typeof chainRegistry)[keyof typeof chainRegistry];\n\nconst env: Record<string, string | undefined> =\n typeof process !== \"undefined\" ? process.env : {};\n\n// Build a chain-ID-to-Chain map from viem, resolving collisions by preferring\n// mainnet definitions over testnets. viem exports duplicate numeric IDs (e.g.\n// zoraTestnet and hyperEvm both use 999); a naive Map would silently keep\n// whichever entry happens to appear last in iteration order, which may be the\n// testnet. The loop below only overwrites an existing entry when the incoming\n// chain is NOT a testnet and the existing one IS, ensuring the production chain\n// always wins while still falling back to a testnet entry when no mainnet\n// definition exists for a given ID.\nconst VIEM_CHAIN_BY_ID = new Map<number, Chain>();\nfor (const value of Object.values(viemChains)) {\n if (typeof value !== \"object\" || value === null || !(\"id\" in value) || !(\"name\" in value)) continue;\n const chain = value as Chain;\n const existing = VIEM_CHAIN_BY_ID.get(chain.id);\n if (!existing || (existing.testnet && !chain.testnet)) {\n VIEM_CHAIN_BY_ID.set(chain.id, chain);\n }\n}\n\nfunction isEvmRegistryEntry(\n entry: ChainRegistryEntry | undefined,\n): entry is ChainRegistryEntry & { vmType: \"evm\" } {\n return entry?.vmType === \"evm\";\n}\n\nfunction getEvmRegistryEntry(\n chainId: number,\n): (ChainRegistryEntry & { vmType: \"evm\" }) | undefined {\n const entry = chainRegistry[String(chainId) as keyof typeof chainRegistry];\n return isEvmRegistryEntry(entry) ? entry : undefined;\n}\n\n// The shared-configs registry includes non-EVM chains (Solana, Tron). Filter\n// to EVM entries before exposing supported chains — downstream consumers\n// (viem clients, wallet_getCapabilities, RPC proxy) only handle eip155 chains.\nconst REGISTRY_CHAIN_IDS = Object.entries(chainRegistry)\n .filter(([, entry]) => isEvmRegistryEntry(entry))\n .map(([id]) => Number(id));\nconst SUPPORTED_CHAIN_IDS = new Set(REGISTRY_CHAIN_IDS);\n\nfunction tokensForChain(chainId: number): TokenConfig[] {\n const entry = getEvmRegistryEntry(chainId);\n if (!entry) return [];\n return entry.tokens.map((token) => ({\n symbol: token.symbol,\n address: token.address as Address,\n decimals: token.decimals,\n }));\n}\n\n/** Treat any 20-byte hex string as an address; checksum casing is optional for user inputs. */\nfunction isAddressInput(value: string): value is Address {\n return isAddress(value, { strict: false });\n}\n\n/**\n * Parse a string environment variable into a boolean, returning `undefined`\n * when the value is absent or not a recognised truthy/falsy literal.\n *\n * Accepted truthy values: `\"true\"`, `\"1\"`.\n * Accepted falsy values: `\"false\"`, `\"0\"`.\n */\nfunction parseBool(value?: string): boolean | undefined {\n if (value === \"true\" || value === \"1\") return true;\n if (value === \"false\" || value === \"0\") return false;\n return undefined;\n}\n\n/**\n * Determine whether testnet chains should be included in registry results.\n *\n * Precedence (highest to lowest):\n * 1. `explicit` argument — a caller-supplied boolean always wins.\n * 2. `NEXT_PUBLIC_ORCHESTRATOR_USE_TESTNETS` env var — checked first so\n * Next.js browser bundles (which only expose `NEXT_PUBLIC_*` variables)\n * can configure testnet mode without a server-side env var.\n * 3. `ORCHESTRATOR_USE_TESTNETS` env var — server-side / Node.js fallback.\n * 4. Defaults to `false` (testnets excluded) when none of the above is set.\n */\nfunction resolveIncludeTestnets(explicit?: boolean): boolean {\n if (explicit !== undefined) return explicit;\n const envValue =\n parseBool(env.NEXT_PUBLIC_ORCHESTRATOR_USE_TESTNETS) ??\n parseBool(env.ORCHESTRATOR_USE_TESTNETS);\n return envValue ?? false;\n}\n\nfunction applyChainFilters(chainIds: number[], options?: ChainFilterOptions): number[] {\n const includeTestnets = resolveIncludeTestnets(options?.includeTestnets);\n const allowlist = options?.chainIds;\n let filtered = chainIds;\n\n if (!includeTestnets) {\n filtered = filtered.filter((chainId) => !isTestnet(chainId));\n }\n\n if (allowlist) {\n const allowed = new Set(allowlist);\n filtered = filtered.filter((chainId) => allowed.has(chainId));\n }\n\n return filtered;\n}\n\nexport function getSupportedChainIds(options?: ChainFilterOptions): number[] {\n return applyChainFilters(REGISTRY_CHAIN_IDS, options);\n}\n\nexport function getSupportedChains(options?: ChainFilterOptions): Chain[] {\n return getSupportedChainIds(options)\n .map((chainId) => VIEM_CHAIN_BY_ID.get(chainId))\n .filter((chain): chain is Chain => Boolean(chain));\n}\n\nexport function getAllSupportedChainsAndTokens(options?: ChainFilterOptions): Array<{\n chainId: number;\n tokens: TokenConfig[];\n}> {\n return getSupportedChainIds(options).map((chainId) => ({\n chainId,\n tokens: tokensForChain(chainId),\n }));\n}\n\nexport function getChainById(chainId: number): Chain {\n if (!SUPPORTED_CHAIN_IDS.has(chainId)) {\n throw new Error(`Unsupported chain ID: ${chainId}`);\n }\n const chain = VIEM_CHAIN_BY_ID.get(chainId);\n if (!chain) {\n throw new Error(`Unsupported chain ID: ${chainId}`);\n }\n return chain;\n}\n\nexport function getChainName(chainId: number): string {\n try {\n return getChainById(chainId).name;\n } catch {\n return `Chain ${chainId}`;\n }\n}\n\nexport function getChainExplorerUrl(chainId: number): string | undefined {\n try {\n return getChainById(chainId).blockExplorers?.default?.url;\n } catch {\n return undefined;\n }\n}\n\nexport function getChainRpcUrl(chainId: number): string | undefined {\n try {\n const chain = getChainById(chainId);\n return chain.rpcUrls?.default?.http?.[0] || chain.rpcUrls?.public?.http?.[0];\n } catch {\n return undefined;\n }\n}\n\nexport function getSupportedTokens(chainId: number): TokenConfig[] {\n return tokensForChain(chainId);\n}\n\nexport function getSupportedTokenSymbols(chainId: number): string[] {\n return getSupportedTokens(chainId).map((token) => token.symbol);\n}\n\nexport function getTokenAddress(symbolOrAddress: string, chainId: number): Address {\n if (isAddressInput(symbolOrAddress)) {\n return symbolOrAddress;\n }\n const match = getSupportedTokens(chainId).find(\n (t) => t.symbol.toUpperCase() === symbolOrAddress.toUpperCase()\n );\n if (!match) {\n throw new Error(`Unsupported token \"${symbolOrAddress}\" on chain ${chainId}`);\n }\n return match.address;\n}\n\nexport function getTokenDecimals(symbolOrAddress: string, chainId: number): number {\n const match = getSupportedTokens(chainId).find(\n (t) =>\n isAddressInput(symbolOrAddress)\n ? t.address.toLowerCase() === symbolOrAddress.toLowerCase()\n : t.symbol.toUpperCase() === symbolOrAddress.toUpperCase()\n );\n if (!match && isAddressInput(symbolOrAddress) && SUPPORTED_CHAIN_IDS.has(chainId)) {\n return 18;\n }\n if (!match) {\n throw new Error(`Unsupported token \"${symbolOrAddress}\" on chain ${chainId}`);\n }\n return match.decimals;\n}\n\nexport function resolveTokenAddress(token: string, chainId: number): Address {\n if (isAddressInput(token)) {\n return token;\n }\n return getTokenAddress(token, chainId);\n}\n\nexport function isTestnet(chainId: number): boolean {\n try {\n return getChainById(chainId).testnet ?? false;\n } catch {\n return false;\n }\n}\n\nexport function getTokenSymbol(tokenAddress: Address, chainId: number): string {\n const token = getSupportedTokens(chainId).find(\n (entry) => entry.address.toLowerCase() === tokenAddress.toLowerCase()\n );\n if (token) {\n return token.symbol;\n }\n if (!SUPPORTED_CHAIN_IDS.has(chainId)) {\n throw new Error(`Unsupported chain ID: ${chainId}`);\n }\n return \"Token\";\n}\n\nexport function isTokenAddressSupported(tokenAddress: Address, chainId: number): boolean {\n return isAddressInput(tokenAddress) && SUPPORTED_CHAIN_IDS.has(chainId);\n}\n"],"mappings":"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","names":[]}
|
package/dist/headless.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-GUAI55LL.mjs";
|
|
7
7
|
|
|
8
8
|
// src/headless-client.ts
|
|
9
|
-
var DEFAULT_PROVIDER_URL = "https://passkey.1auth.
|
|
9
|
+
var DEFAULT_PROVIDER_URL = "https://passkey.1auth.app";
|
|
10
10
|
var MISSING_APP_CREDENTIALS_MESSAGE = "No sponsorship configured on OneAuthHeadlessClient. Every user intent must carry the app's JWT \u2014 pass `sponsorship: { accessToken, getExtensionToken }` (or URL form) to the constructor.";
|
|
11
11
|
function normalizeSponsorship(config) {
|
|
12
12
|
if (!config) return null;
|