@tempoxyz/id 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/server/.vite/manifest.json +65 -65
- package/dist/app/server/assets/Grant-D_tun0mF.js.map +1 -1
- package/dist/app/server/assets/authorize-DXYo-K2n-B-6vqhvc.js +56 -0
- package/dist/app/server/assets/authorize-DXYo-K2n-B-6vqhvc.js.map +1 -0
- package/dist/app/server/assets/core-FSS9-r35.js +56 -0
- package/dist/app/server/assets/core-FSS9-r35.js.map +1 -0
- package/dist/app/server/assets/default-u_dwuiYb-Bby14ucv.js +2 -0
- package/dist/app/server/assets/{default-u_dwuiYb-DOrMMcg9.js.map → default-u_dwuiYb-Bby14ucv.js.map} +1 -1
- package/dist/app/server/assets/{dist-CoH0hD1s.js → dist-B9KiBJYw.js} +2 -2
- package/dist/app/server/assets/{dist-CoH0hD1s.js.map → dist-B9KiBJYw.js.map} +1 -1
- package/dist/app/server/assets/{dist-DcICI3fd.js → dist-CU1NXSiz.js} +2 -2
- package/dist/app/server/assets/{dist-DcICI3fd.js.map → dist-CU1NXSiz.js.map} +1 -1
- package/dist/app/server/assets/dist-CetH4JSY.js +1 -0
- package/dist/app/server/assets/{effect-QlVUlMFu-mXPkuQTb.js → effect-QlVUlMFu-Cm-eTtaO.js} +2 -2
- package/dist/app/server/assets/{effect-QlVUlMFu-mXPkuQTb.js.map → effect-QlVUlMFu-Cm-eTtaO.js.map} +1 -1
- package/dist/app/server/assets/factory-g3i_Ffi5.js +5 -0
- package/dist/app/server/assets/{factory-dvoOlKer.js.map → factory-g3i_Ffi5.js.map} +1 -1
- package/dist/app/server/assets/get-id-field-BpOAoqqI.js +6 -0
- package/dist/app/server/assets/get-id-field-BpOAoqqI.js.map +1 -0
- package/dist/app/server/assets/{index-CLddUTqr-CC33CMvS.js → index-CLddUTqr-CmgkbWi9.js} +2 -2
- package/dist/app/server/assets/{index-CLddUTqr-CC33CMvS.js.map → index-CLddUTqr-CmgkbWi9.js.map} +1 -1
- package/dist/app/server/assets/{index-DZEfthgZ-Ec2MMQ_e.js → index-DZEfthgZ-BnPmps9O.js} +2 -2
- package/dist/app/server/assets/{index-DZEfthgZ-Ec2MMQ_e.js.map → index-DZEfthgZ-BnPmps9O.js.map} +1 -1
- package/dist/app/server/assets/kysely-adapter-B8VoPArC.js +1 -0
- package/dist/app/server/assets/{schema-check-oLqvHR8y.js → schema-check-Bgwl1v0_.js} +2 -2
- package/dist/app/server/assets/{schema-check-oLqvHR8y.js.map → schema-check-Bgwl1v0_.js.map} +1 -1
- package/dist/app/server/assets/{sury-CWZTCd75-CDaOS2oM.js → sury-CWZTCd75-Bd_PzqCV.js} +2 -2
- package/dist/app/server/assets/{sury-CWZTCd75-CDaOS2oM.js.map → sury-CWZTCd75-Bd_PzqCV.js.map} +1 -1
- package/dist/app/server/assets/{valibot--1zFm7rT-CIKoH3MS.js → valibot--1zFm7rT-Dd2aEhWG.js} +2 -2
- package/dist/app/server/assets/{valibot--1zFm7rT-CIKoH3MS.js.map → valibot--1zFm7rT-Dd2aEhWG.js.map} +1 -1
- package/dist/app/server/assets/{valibot-D_HTw1Gn-BdPyLkXt.js → valibot-D_HTw1Gn-C1l3va6F.js} +2 -2
- package/dist/app/server/assets/{valibot-D_HTw1Gn-BdPyLkXt.js.map → valibot-D_HTw1Gn-C1l3va6F.js.map} +1 -1
- package/dist/app/server/assets/{zod-Bwrt9trS-BezI5Gi1.js → zod-Bwrt9trS-Dry2w0in.js} +2 -2
- package/dist/app/server/assets/{zod-Bwrt9trS-BezI5Gi1.js.map → zod-Bwrt9trS-Dry2w0in.js.map} +1 -1
- package/dist/app/server/assets/{zod-DSgpEGAE-DZ7M_Q33.js → zod-DSgpEGAE-BZMP86UA.js} +2 -2
- package/dist/app/server/assets/{zod-DSgpEGAE-DZ7M_Q33.js.map → zod-DSgpEGAE-BZMP86UA.js.map} +1 -1
- package/dist/app/server/index.js +35 -35
- package/dist/app/server/index.js.map +1 -1
- package/dist/client/Auth.d.ts +1 -1
- package/dist/client/Auth.d.ts.map +1 -1
- package/dist/client/Auth.js.map +1 -1
- package/dist/client/Decorator.d.ts +3 -1
- package/dist/client/Decorator.d.ts.map +1 -1
- package/dist/client/Decorator.js +1 -0
- package/dist/client/Decorator.js.map +1 -1
- package/dist/client/actions/passkey.d.ts +63 -2
- package/dist/client/actions/passkey.d.ts.map +1 -1
- package/dist/client/actions/passkey.js +121 -3
- package/dist/client/actions/passkey.js.map +1 -1
- package/dist/internal/Apps.d.ts +14 -0
- package/dist/internal/Apps.d.ts.map +1 -1
- package/dist/internal/Apps.js +14 -2
- package/dist/internal/Apps.js.map +1 -1
- package/dist/internal/Auth.d.ts +7 -0
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +2 -1
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Authorize.d.ts.map +1 -1
- package/dist/internal/Authorize.js +13 -13
- package/dist/internal/Authorize.js.map +1 -1
- package/dist/internal/ErrorResponse.d.ts +5 -0
- package/dist/internal/ErrorResponse.d.ts.map +1 -1
- package/dist/internal/ErrorResponse.js +8 -0
- package/dist/internal/ErrorResponse.js.map +1 -1
- package/dist/internal/KeyAuthorization.d.ts.map +1 -1
- package/dist/internal/KeyAuthorization.js +28 -28
- package/dist/internal/KeyAuthorization.js.map +1 -1
- package/dist/internal/Owner.d.ts +16 -0
- package/dist/internal/Owner.d.ts.map +1 -1
- package/dist/internal/Owner.js.map +1 -1
- package/dist/internal/Passkey.d.ts +66 -4
- package/dist/internal/Passkey.d.ts.map +1 -1
- package/dist/internal/Passkey.js +66 -30
- package/dist/internal/Passkey.js.map +1 -1
- package/dist/internal/Privy.d.ts +27 -0
- package/dist/internal/Privy.d.ts.map +1 -1
- package/dist/internal/Privy.js +82 -0
- package/dist/internal/Privy.js.map +1 -1
- package/dist/internal/TempoAccount.d.ts +57 -0
- package/dist/internal/TempoAccount.d.ts.map +1 -1
- package/dist/internal/TempoAccount.js +118 -5
- package/dist/internal/TempoAccount.js.map +1 -1
- package/dist/internal/owners/Privy.d.ts.map +1 -1
- package/dist/internal/owners/Privy.js +11 -2
- package/dist/internal/owners/Privy.js.map +1 -1
- package/package.json +1 -1
- package/src/api/account.ts +140 -103
- package/src/api/authenticate.ts +48 -51
- package/src/api/authorize.ts +35 -36
- package/src/api/device.ts +20 -23
- package/src/api/health.ts +1 -2
- package/src/api/lib/AccountStep.ts +75 -0
- package/src/api/lib/Auth.ts +6 -0
- package/src/api/lib/Cors.ts +3 -0
- package/src/api/lib/KeySigner.ts +1 -1
- package/src/api/oauth.ts +23 -22
- package/src/client/Auth.ts +1 -0
- package/src/client/Decorator.ts +6 -1
- package/src/client/actions/passkey.ts +197 -3
- package/src/internal/Apps.ts +26 -2
- package/src/internal/Auth.ts +4 -0
- package/src/internal/Authorize.ts +13 -15
- package/src/internal/ErrorResponse.ts +10 -0
- package/src/internal/KeyAuthorization.ts +28 -31
- package/src/internal/OpenApi.ts +35 -0
- package/src/internal/Owner.ts +16 -0
- package/src/internal/Passkey.ts +99 -34
- package/src/internal/Privy.ts +128 -0
- package/src/internal/TempoAccount.ts +221 -7
- package/src/internal/owners/Privy.ts +19 -6
- package/dist/app/server/assets/authorize-DXYo-K2n-rmQQ42x1.js +0 -56
- package/dist/app/server/assets/authorize-DXYo-K2n-rmQQ42x1.js.map +0 -1
- package/dist/app/server/assets/core-BBrZXfrB.js +0 -56
- package/dist/app/server/assets/core-BBrZXfrB.js.map +0 -1
- package/dist/app/server/assets/default-u_dwuiYb-DOrMMcg9.js +0 -2
- package/dist/app/server/assets/dist-CR6FW-yS.js +0 -1
- package/dist/app/server/assets/factory-dvoOlKer.js +0 -5
- package/dist/app/server/assets/get-id-field-OwLpfjj2.js +0 -6
- package/dist/app/server/assets/get-id-field-OwLpfjj2.js.map +0 -1
- package/dist/app/server/assets/kysely-adapter-B8tQwTcu.js +0 -1
package/src/api/account.ts
CHANGED
|
@@ -52,7 +52,7 @@ namespace schema {
|
|
|
52
52
|
export const query = z.object({
|
|
53
53
|
chain: Chain.schema.optional().meta({
|
|
54
54
|
description:
|
|
55
|
-
|
|
55
|
+
"The chain to read each account's balance on, such as `mainnet` or `testnet`. Without it, the response carries no balances.",
|
|
56
56
|
examples: ['testnet'],
|
|
57
57
|
}),
|
|
58
58
|
client_id: z
|
|
@@ -62,7 +62,7 @@ namespace schema {
|
|
|
62
62
|
.optional()
|
|
63
63
|
.meta({
|
|
64
64
|
description:
|
|
65
|
-
"The app
|
|
65
|
+
"The app whose realms select the accounts. Without it, or from a page outside the app's redirect URI origins, the `default` realm.",
|
|
66
66
|
examples: ['client_01JZ8Q6W3N1R5B4V7C2X9K0M3T'],
|
|
67
67
|
}),
|
|
68
68
|
})
|
|
@@ -75,20 +75,19 @@ namespace schema {
|
|
|
75
75
|
}),
|
|
76
76
|
id: z.string().meta({
|
|
77
77
|
description:
|
|
78
|
-
"The user's ID, which is the `sub` of
|
|
78
|
+
"The user's ID, which is the `sub` claim of the user's tokens.",
|
|
79
79
|
examples: ['user_01JZ8Q6W3N1R5B4V7C2X9K0M3T'],
|
|
80
80
|
}),
|
|
81
81
|
name: z
|
|
82
82
|
.string()
|
|
83
83
|
.nullable()
|
|
84
84
|
.meta({
|
|
85
|
-
description:
|
|
86
|
-
"The user's name, or `null` for a user who signed up without one.",
|
|
85
|
+
description: "The user's name, or `null` if the user has none.",
|
|
87
86
|
examples: ['Ada Lovelace'],
|
|
88
87
|
}),
|
|
89
88
|
passkeys: z.boolean().meta({
|
|
90
89
|
description:
|
|
91
|
-
|
|
90
|
+
'Whether the realms of the request accept passkeys that sign in on Tempo ID.',
|
|
92
91
|
examples: [true],
|
|
93
92
|
}),
|
|
94
93
|
tempo: z
|
|
@@ -96,14 +95,14 @@ namespace schema {
|
|
|
96
95
|
TempoAccount.schema.tempoAccount.extend({
|
|
97
96
|
balance: Balance.schema.balance.nullable().optional().meta({
|
|
98
97
|
description:
|
|
99
|
-
"The USD value of the account's verified
|
|
98
|
+
"The USD value of the account's verified tokens on `chain`. Absent without `chain`, and `null` if the balance cannot be read.",
|
|
100
99
|
}),
|
|
101
100
|
}),
|
|
102
101
|
)
|
|
103
102
|
.readonly()
|
|
104
103
|
.meta({
|
|
105
104
|
description:
|
|
106
|
-
"The user's Tempo Accounts
|
|
105
|
+
"The user's Tempo Accounts: the account that the user selected for the app first, then oldest first.",
|
|
107
106
|
}),
|
|
108
107
|
})
|
|
109
108
|
.meta({ id: 'Account' })
|
|
@@ -125,30 +124,29 @@ namespace schema {
|
|
|
125
124
|
publicKey: z
|
|
126
125
|
.object({
|
|
127
126
|
attestation: z.literal('none').meta({
|
|
128
|
-
description:
|
|
129
|
-
'Tempo ID requests no attestation statement from the authenticator.',
|
|
127
|
+
description: 'Requests no attestation from the authenticator.',
|
|
130
128
|
}),
|
|
131
129
|
authenticatorSelection: z
|
|
132
130
|
.object({
|
|
133
131
|
requireResidentKey: z.literal(true).meta({
|
|
134
132
|
description:
|
|
135
|
-
'
|
|
133
|
+
'Requires a discoverable passkey, which signs in without an email.',
|
|
136
134
|
}),
|
|
137
135
|
residentKey: z.literal('required').meta({
|
|
138
136
|
description:
|
|
139
|
-
'
|
|
137
|
+
'Requires a discoverable passkey, which signs in without an email.',
|
|
140
138
|
}),
|
|
141
139
|
userVerification: z.literal('required').meta({
|
|
142
140
|
description:
|
|
143
|
-
'
|
|
141
|
+
'Requires user verification, such as a biometric or PIN.',
|
|
144
142
|
}),
|
|
145
143
|
})
|
|
146
144
|
.meta({
|
|
147
|
-
description: 'The
|
|
145
|
+
description: 'The requirements for the authenticator.',
|
|
148
146
|
}),
|
|
149
147
|
challenge: z.templateLiteral(['0x', z.string()]).meta({
|
|
150
148
|
description:
|
|
151
|
-
'The single-use challenge, as hex
|
|
149
|
+
'The single-use challenge, as hex, which expires after 5 minutes.',
|
|
152
150
|
examples: [
|
|
153
151
|
'0xf6310589abb21116acc6e123967ed0a125b5041c43f8e157237093e07eaa354c',
|
|
154
152
|
],
|
|
@@ -166,13 +164,13 @@ namespace schema {
|
|
|
166
164
|
}),
|
|
167
165
|
})
|
|
168
166
|
.meta({
|
|
169
|
-
description: 'A passkey that the user
|
|
167
|
+
description: 'A passkey that the user already has.',
|
|
170
168
|
}),
|
|
171
169
|
)
|
|
172
170
|
.optional()
|
|
173
171
|
.meta({
|
|
174
172
|
description:
|
|
175
|
-
"The user's passkeys
|
|
173
|
+
"The user's existing passkeys, which the authenticator does not register again. Absent if the user has none.",
|
|
176
174
|
}),
|
|
177
175
|
pubKeyCredParams: z
|
|
178
176
|
.array(
|
|
@@ -187,12 +185,11 @@ namespace schema {
|
|
|
187
185
|
})
|
|
188
186
|
.meta({
|
|
189
187
|
description:
|
|
190
|
-
'
|
|
188
|
+
'A P-256 key, the only key type that a Tempo Account accepts.',
|
|
191
189
|
}),
|
|
192
190
|
)
|
|
193
191
|
.meta({
|
|
194
|
-
description:
|
|
195
|
-
'The key types the passkey may use: P-256 alone, which a Tempo Account verifies.',
|
|
192
|
+
description: 'The key types that the passkey can use.',
|
|
196
193
|
}),
|
|
197
194
|
rp: z
|
|
198
195
|
.object({
|
|
@@ -201,21 +198,21 @@ namespace schema {
|
|
|
201
198
|
examples: ['tempo.xyz'],
|
|
202
199
|
}),
|
|
203
200
|
name: z.string().meta({
|
|
204
|
-
description:
|
|
201
|
+
description: 'The display name of the `default` realm.',
|
|
205
202
|
examples: ['Tempo'],
|
|
206
203
|
}),
|
|
207
204
|
})
|
|
208
|
-
.meta({ description: 'The relying party.' }),
|
|
205
|
+
.meta({ description: 'The relying party of the passkey.' }),
|
|
209
206
|
user: z
|
|
210
207
|
.object({
|
|
211
208
|
displayName: z.string().meta({
|
|
212
209
|
description:
|
|
213
|
-
"The user's name, or the email address
|
|
210
|
+
"The user's name, or the email address if the user has none.",
|
|
214
211
|
examples: ['Ada Lovelace'],
|
|
215
212
|
}),
|
|
216
213
|
id: z.string().meta({
|
|
217
214
|
description:
|
|
218
|
-
'A random user handle
|
|
215
|
+
'A random user handle, base64url. A new handle for each passkey stops the authenticator from replacing another passkey.',
|
|
219
216
|
examples: ['3q2-7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'],
|
|
220
217
|
}),
|
|
221
218
|
name: z.email().meta({
|
|
@@ -225,16 +222,16 @@ namespace schema {
|
|
|
225
222
|
})
|
|
226
223
|
.meta({
|
|
227
224
|
description:
|
|
228
|
-
'The user
|
|
225
|
+
'The user that the authenticator shows with the passkey.',
|
|
229
226
|
}),
|
|
230
227
|
})
|
|
231
228
|
.meta({
|
|
232
229
|
description:
|
|
233
|
-
'The `PublicKeyCredentialCreationOptions`,
|
|
230
|
+
'The `PublicKeyCredentialCreationOptions`, with the challenge as hex.',
|
|
234
231
|
}),
|
|
235
232
|
})
|
|
236
233
|
.meta({
|
|
237
|
-
description: 'The
|
|
234
|
+
description: 'The argument for `navigator.credentials.create()`.',
|
|
238
235
|
}),
|
|
239
236
|
})
|
|
240
237
|
}
|
|
@@ -268,11 +265,11 @@ namespace schema {
|
|
|
268
265
|
)
|
|
269
266
|
.meta({
|
|
270
267
|
description:
|
|
271
|
-
'The new passkey, the only
|
|
268
|
+
'The new passkey, which is the only passkey that the browser offers.',
|
|
272
269
|
}),
|
|
273
270
|
challenge: z.templateLiteral(['0x', z.string()]).meta({
|
|
274
271
|
description:
|
|
275
|
-
'The single-use
|
|
272
|
+
'The single-use challenge, as hex, which expires after 5 minutes.',
|
|
276
273
|
examples: [
|
|
277
274
|
'0xf6310589abb21116acc6e123967ed0a125b5041c43f8e157237093e07eaa354c',
|
|
278
275
|
],
|
|
@@ -283,25 +280,25 @@ namespace schema {
|
|
|
283
280
|
}),
|
|
284
281
|
userVerification: z.literal('required').meta({
|
|
285
282
|
description:
|
|
286
|
-
'
|
|
283
|
+
'Requires user verification, such as a biometric or PIN.',
|
|
287
284
|
}),
|
|
288
285
|
})
|
|
289
286
|
.meta({
|
|
290
287
|
description:
|
|
291
|
-
'The `PublicKeyCredentialRequestOptions`,
|
|
288
|
+
'The `PublicKeyCredentialRequestOptions`, with the challenge as hex.',
|
|
292
289
|
}),
|
|
293
290
|
})
|
|
294
291
|
.meta({
|
|
295
|
-
description: 'The
|
|
292
|
+
description: 'The argument for `navigator.credentials.get()`.',
|
|
296
293
|
}),
|
|
297
294
|
type: z.literal('passkey').meta({
|
|
298
295
|
description:
|
|
299
|
-
'Sign the
|
|
296
|
+
'Sign the challenge with the new passkey, then send the assertion to `POST /v1/account/passkey/verify`.',
|
|
300
297
|
}),
|
|
301
298
|
})
|
|
302
299
|
.meta({
|
|
303
300
|
description:
|
|
304
|
-
|
|
301
|
+
'The next step: a signature of the new passkey, which proves that the authenticator holds its private key.',
|
|
305
302
|
}),
|
|
306
303
|
})
|
|
307
304
|
}
|
|
@@ -310,21 +307,20 @@ namespace schema {
|
|
|
310
307
|
export const json = z.object({
|
|
311
308
|
account: address.optional().meta({
|
|
312
309
|
description:
|
|
313
|
-
|
|
310
|
+
'A configurable Tempo Account of the user, which the passkey joins as a second owner. Without it, the passkey owns a new account.',
|
|
314
311
|
examples: ['0x7a3f9c2b1e5d8a4f6c0b3e7d9a2f5c8b1e4d7a0f'],
|
|
315
312
|
}),
|
|
316
313
|
assertion: Passkey.schema.assertion,
|
|
317
314
|
chain: Chain.schema.optional().meta({
|
|
318
315
|
description:
|
|
319
|
-
|
|
316
|
+
'The chain with configurable accounts where the passkey joins `account`. Defaults to the first such chain.',
|
|
320
317
|
examples: ['local'],
|
|
321
318
|
}),
|
|
322
319
|
})
|
|
323
320
|
|
|
324
321
|
export const response = z.object({
|
|
325
322
|
address: z.string().meta({
|
|
326
|
-
description:
|
|
327
|
-
"The address of the Tempo Account that the passkey owns: `account`, or the passkey's own account on `chain`.",
|
|
323
|
+
description: 'The address of the Tempo Account that the passkey owns.',
|
|
328
324
|
examples: ['0x7a3f9c2b1e5d8a4f6c0b3e7d9a2f5c8b1e4d7a0f'],
|
|
329
325
|
}),
|
|
330
326
|
id: Passkey.schema.credentialId.meta({
|
|
@@ -340,12 +336,12 @@ namespace schema {
|
|
|
340
336
|
export const response = z.object({
|
|
341
337
|
passkeys: z.boolean().meta({
|
|
342
338
|
description:
|
|
343
|
-
"Whether
|
|
339
|
+
"Whether passkey sign-in for the app works on the page that sends the request. `false` without `client_id`, or on Tempo ID's own page.",
|
|
344
340
|
examples: [true],
|
|
345
341
|
}),
|
|
346
342
|
realms: z.array(TempoAccount.schema.realm).readonly().meta({
|
|
347
343
|
description:
|
|
348
|
-
"The
|
|
344
|
+
"The app's realms, in order. A user's first account is in the first realm.",
|
|
349
345
|
}),
|
|
350
346
|
})
|
|
351
347
|
}
|
|
@@ -362,20 +358,20 @@ namespace schema {
|
|
|
362
358
|
}),
|
|
363
359
|
configurable: z.boolean().meta({
|
|
364
360
|
description:
|
|
365
|
-
'Whether Tempo Accounts
|
|
361
|
+
'Whether Tempo Accounts on the chain are configurable (TIP-1107).',
|
|
366
362
|
examples: [false],
|
|
367
363
|
}),
|
|
368
364
|
name: Chain.schema.meta({
|
|
369
|
-
description: 'The
|
|
365
|
+
description: 'The value of the `chain` parameter.',
|
|
370
366
|
examples: ['testnet'],
|
|
371
367
|
}),
|
|
372
368
|
})
|
|
373
|
-
.meta({ description: 'A chain
|
|
369
|
+
.meta({ description: 'A chain.' })
|
|
374
370
|
|
|
375
371
|
export const response = z.object({
|
|
376
372
|
chains: z.array(entry).readonly().meta({
|
|
377
373
|
description:
|
|
378
|
-
|
|
374
|
+
'The chains: `mainnet`, `testnet`, then the chains that the deployment adds.',
|
|
379
375
|
}),
|
|
380
376
|
})
|
|
381
377
|
}
|
|
@@ -392,12 +388,12 @@ namespace schema {
|
|
|
392
388
|
examples: [true],
|
|
393
389
|
}),
|
|
394
390
|
})
|
|
395
|
-
.meta({ description: 'A chain
|
|
391
|
+
.meta({ description: 'A chain.' }),
|
|
396
392
|
)
|
|
397
393
|
.readonly()
|
|
398
394
|
.meta({
|
|
399
395
|
description:
|
|
400
|
-
|
|
396
|
+
'The chains: `mainnet`, `testnet`, then the chains that the deployment adds.',
|
|
401
397
|
}),
|
|
402
398
|
})
|
|
403
399
|
}
|
|
@@ -422,7 +418,7 @@ namespace schema {
|
|
|
422
418
|
examples: [1337],
|
|
423
419
|
}),
|
|
424
420
|
name: Chain.schema.meta({
|
|
425
|
-
description: 'The
|
|
421
|
+
description: 'The value of the `chain` parameter.',
|
|
426
422
|
examples: ['local'],
|
|
427
423
|
}),
|
|
428
424
|
node: z.enum(['down', 'up']).meta({
|
|
@@ -446,14 +442,13 @@ namespace schema {
|
|
|
446
442
|
address: z
|
|
447
443
|
.templateLiteral(['0x', z.string().regex(/^[0-9a-fA-F]{40}$/)])
|
|
448
444
|
.meta({
|
|
449
|
-
description:
|
|
450
|
-
"The Tempo Account that receives the tokens, one of the user's accounts in the `default` realm.",
|
|
445
|
+
description: "The user's Tempo Account that receives the tokens.",
|
|
451
446
|
examples: ['0x7a3f9c2b1e5d8a4f6c0b3e7d9a2f5c8b1e4d7a0f'],
|
|
452
447
|
pattern: '^0x[0-9a-fA-F]{40}$',
|
|
453
448
|
}),
|
|
454
449
|
chain: Chain.schema.meta({
|
|
455
450
|
description:
|
|
456
|
-
'The test chain whose faucet
|
|
451
|
+
'The test chain whose faucet sends the tokens. Tempo mainnet has no faucet.',
|
|
457
452
|
examples: ['testnet'],
|
|
458
453
|
}),
|
|
459
454
|
})
|
|
@@ -470,8 +465,7 @@ namespace schema {
|
|
|
470
465
|
)
|
|
471
466
|
.readonly()
|
|
472
467
|
.meta({
|
|
473
|
-
description:
|
|
474
|
-
'The hashes of the transfers, one for each token that the faucet drips, each one landed.',
|
|
468
|
+
description: 'The hashes of the transfers, one for each token.',
|
|
475
469
|
examples: [
|
|
476
470
|
[
|
|
477
471
|
'0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
|
|
@@ -486,12 +480,12 @@ namespace schema {
|
|
|
486
480
|
.object({
|
|
487
481
|
account: address.optional().meta({
|
|
488
482
|
description:
|
|
489
|
-
|
|
483
|
+
'The Tempo Account to upgrade, which a wallet.tempo passkey of the user owns. Absent with `credentialId`.',
|
|
490
484
|
examples: ['0x7a3f9c2b1e5d8a4f6c0b3e7d9a2f5c8b1e4d7a0f'],
|
|
491
485
|
}),
|
|
492
486
|
chain: Chain.schema.optional().meta({
|
|
493
487
|
description:
|
|
494
|
-
'The chain
|
|
488
|
+
'The chain with configurable accounts where the upgrade runs. Defaults to the first such chain.',
|
|
495
489
|
examples: ['local'],
|
|
496
490
|
}),
|
|
497
491
|
client_id: z
|
|
@@ -501,12 +495,12 @@ namespace schema {
|
|
|
501
495
|
.optional()
|
|
502
496
|
.meta({
|
|
503
497
|
description:
|
|
504
|
-
'The app whose realms hold the account.
|
|
498
|
+
'The app whose realms hold the account. Defaults to the `default` realm.',
|
|
505
499
|
examples: ['client_01JZ8Q6W3N1R5B4V7C2X9K0M3T'],
|
|
506
500
|
}),
|
|
507
501
|
credentialId: Passkey.schema.credentialId.optional().meta({
|
|
508
502
|
description:
|
|
509
|
-
"A wallet.tempo passkey of the user's email that
|
|
503
|
+
"A wallet.tempo passkey of the user's email that is not linked yet, which the upgrade links. Absent with `account`.",
|
|
510
504
|
examples: ['KEbWNCc7NgaYnUyrNeFGX9_3Y-8'],
|
|
511
505
|
}),
|
|
512
506
|
key: z
|
|
@@ -520,7 +514,7 @@ namespace schema {
|
|
|
520
514
|
})
|
|
521
515
|
.meta({
|
|
522
516
|
description:
|
|
523
|
-
"The access key's
|
|
517
|
+
"The access key's signature of `step.key.digest`, as a serialized signature envelope.",
|
|
524
518
|
examples: [
|
|
525
519
|
'0x997c61aa10e2330c076d6ba7abca1e71703a8f039291db103a62e085c9b2cf0d3f7e31ec9028229acc83093fbb722fa700fd6e4ea15d584df1bf384eb0051e0d1c',
|
|
526
520
|
],
|
|
@@ -529,11 +523,11 @@ namespace schema {
|
|
|
529
523
|
.optional()
|
|
530
524
|
.meta({
|
|
531
525
|
description:
|
|
532
|
-
"The access key's signature of its registration,
|
|
526
|
+
"The access key's signature of its registration, for a step with `key`.",
|
|
533
527
|
}),
|
|
534
528
|
key_authorization: KeyAuthorization.schema.rpc.optional().meta({
|
|
535
529
|
description:
|
|
536
|
-
|
|
530
|
+
'A key that the passkey signed before the upgrade, such as with `skip_upgrade`. Tempo ID registers it first, so it keeps working after the upgrade.',
|
|
537
531
|
}),
|
|
538
532
|
passkey: z
|
|
539
533
|
.object({
|
|
@@ -542,7 +536,7 @@ namespace schema {
|
|
|
542
536
|
.optional()
|
|
543
537
|
.meta({
|
|
544
538
|
description:
|
|
545
|
-
"The passkey
|
|
539
|
+
"The passkey's assertion over the step's challenge. Absent on the first request.",
|
|
546
540
|
}),
|
|
547
541
|
})
|
|
548
542
|
.refine(
|
|
@@ -585,11 +579,11 @@ namespace schema {
|
|
|
585
579
|
)
|
|
586
580
|
.meta({
|
|
587
581
|
description:
|
|
588
|
-
"The account's passkey, the only
|
|
582
|
+
"The account's passkey, which is the only passkey that the browser offers.",
|
|
589
583
|
}),
|
|
590
584
|
challenge: z.templateLiteral(['0x', z.string()]).meta({
|
|
591
585
|
description:
|
|
592
|
-
'The digest of the transaction
|
|
586
|
+
'The digest of the upgrade transaction, as hex, which expires after 5 minutes.',
|
|
593
587
|
examples: [
|
|
594
588
|
'0xf6310589abb21116acc6e123967ed0a125b5041c43f8e157237093e07eaa354c',
|
|
595
589
|
],
|
|
@@ -600,22 +594,23 @@ namespace schema {
|
|
|
600
594
|
}),
|
|
601
595
|
userVerification: z.literal('required').meta({
|
|
602
596
|
description:
|
|
603
|
-
'
|
|
597
|
+
'Requires user verification, such as a biometric or PIN.',
|
|
604
598
|
}),
|
|
605
599
|
})
|
|
606
600
|
.meta({
|
|
607
601
|
description:
|
|
608
|
-
'The `PublicKeyCredentialRequestOptions`,
|
|
602
|
+
'The `PublicKeyCredentialRequestOptions`, with the challenge as hex.',
|
|
609
603
|
}),
|
|
610
604
|
})
|
|
611
605
|
.meta({
|
|
612
|
-
description:
|
|
606
|
+
description:
|
|
607
|
+
'The argument for `navigator.credentials.get()`.',
|
|
613
608
|
}),
|
|
614
609
|
key: z
|
|
615
610
|
.object({
|
|
616
611
|
digest: z.templateLiteral(['0x', z.string()]).meta({
|
|
617
612
|
description:
|
|
618
|
-
|
|
613
|
+
"The digest of the key's registration transaction, for the access key to sign. Tempo ID pays its fee.",
|
|
619
614
|
examples: [
|
|
620
615
|
'0x3c8a5e1f0b7d2c946a1e8f3b5d7c9a2e4f6b8d0c1e3a5f7b9d2c4e6a8f0b1d3c',
|
|
621
616
|
],
|
|
@@ -624,16 +619,16 @@ namespace schema {
|
|
|
624
619
|
.optional()
|
|
625
620
|
.meta({
|
|
626
621
|
description:
|
|
627
|
-
"The key's registration,
|
|
622
|
+
"The key's registration, if `key_authorization` names a key that the chain does not hold yet. Repeat the request with `key.signature`.",
|
|
628
623
|
}),
|
|
629
624
|
type: z.literal('passkey').meta({
|
|
630
625
|
description:
|
|
631
|
-
'Sign the
|
|
626
|
+
'Sign the challenge with the passkey, then repeat the request with `passkey.assertion`.',
|
|
632
627
|
}),
|
|
633
628
|
})
|
|
634
629
|
.meta({
|
|
635
630
|
description:
|
|
636
|
-
"The next step: the passkey's signature of the transaction
|
|
631
|
+
"The next step: the passkey's signature of the upgrade transaction.",
|
|
637
632
|
}),
|
|
638
633
|
})
|
|
639
634
|
.meta({ description: 'The passkey step.' }),
|
|
@@ -647,8 +642,7 @@ namespace schema {
|
|
|
647
642
|
z
|
|
648
643
|
.object({
|
|
649
644
|
address: address.meta({
|
|
650
|
-
description:
|
|
651
|
-
"The address of the passkey's Tempo Account, which its public key derives.",
|
|
645
|
+
description: "The address of the passkey's Tempo Account.",
|
|
652
646
|
examples: ['0x7a3f9c2b1e5d8a4f6c0b3e7d9a2f5c8b1e4d7a0f'],
|
|
653
647
|
}),
|
|
654
648
|
credentialId: Passkey.schema.credentialId.meta({
|
|
@@ -661,7 +655,7 @@ namespace schema {
|
|
|
661
655
|
.readonly()
|
|
662
656
|
.meta({
|
|
663
657
|
description:
|
|
664
|
-
"The
|
|
658
|
+
"The wallet.tempo passkeys of the user's email that are not linked yet, oldest first.",
|
|
665
659
|
}),
|
|
666
660
|
})
|
|
667
661
|
}
|
|
@@ -670,7 +664,7 @@ namespace schema {
|
|
|
670
664
|
export const query = z.object({
|
|
671
665
|
chain: Chain.schema.meta({
|
|
672
666
|
description:
|
|
673
|
-
'The chain to list upgrades on
|
|
667
|
+
'The chain to list upgrades on. A chain without configurable accounts lists none.',
|
|
674
668
|
examples: ['t14'],
|
|
675
669
|
}),
|
|
676
670
|
})
|
|
@@ -716,8 +710,7 @@ namespace schema {
|
|
|
716
710
|
)
|
|
717
711
|
.readonly()
|
|
718
712
|
.meta({
|
|
719
|
-
description:
|
|
720
|
-
'The upgrades, linked accounts first, in the order of the chains. Empty without a chain whose accounts are configurable.',
|
|
713
|
+
description: 'The upgrades, linked accounts first.',
|
|
721
714
|
}),
|
|
722
715
|
})
|
|
723
716
|
}
|
|
@@ -735,7 +728,7 @@ export const account = new Hono<Env>()
|
|
|
735
728
|
'/v1/account',
|
|
736
729
|
OpenApi.describeRoute({
|
|
737
730
|
description:
|
|
738
|
-
'
|
|
731
|
+
'Returns the signed-in user and their Tempo Accounts in the realms of the `client_id` app, or of the `default` realm.',
|
|
739
732
|
responses: OpenApi.responses({
|
|
740
733
|
errors: [
|
|
741
734
|
...OpenApi.validate.errors,
|
|
@@ -858,7 +851,7 @@ export const account = new Hono<Env>()
|
|
|
858
851
|
'/v1/account',
|
|
859
852
|
OpenApi.describeRoute({
|
|
860
853
|
description:
|
|
861
|
-
'Returns the signed-in user and their Tempo Accounts, as `GET /v1/account` does
|
|
854
|
+
'Returns the signed-in user and their Tempo Accounts, as `GET /v1/account` does, and first creates a Tempo Account for a user who has none. Only the pages of first-party apps can send it.',
|
|
862
855
|
responses: OpenApi.responses({
|
|
863
856
|
errors: [
|
|
864
857
|
...BodyLimit.errors,
|
|
@@ -988,7 +981,7 @@ export const account = new Hono<Env>()
|
|
|
988
981
|
'/v1/account/passkey/options',
|
|
989
982
|
OpenApi.describeRoute({
|
|
990
983
|
description:
|
|
991
|
-
"
|
|
984
|
+
"Passkey registration, step 1 of 3: returns the options for `navigator.credentials.create()`. Requires a sign-in within the last 10 minutes, on Tempo ID's own page or the page of a first-party app with the `tempo-id:sign` scope.",
|
|
992
985
|
responses: OpenApi.responses({
|
|
993
986
|
errors: [
|
|
994
987
|
...BodyLimit.errors,
|
|
@@ -999,6 +992,7 @@ export const account = new Hono<Env>()
|
|
|
999
992
|
Passkey.LimitError,
|
|
1000
993
|
Passkey.NotPermittedError,
|
|
1001
994
|
Passkey.ReauthenticationRequiredError,
|
|
995
|
+
Passkey.RegisterNotPermittedError,
|
|
1002
996
|
],
|
|
1003
997
|
success: {
|
|
1004
998
|
description: 'The creation options.',
|
|
@@ -1010,9 +1004,18 @@ export const account = new Hono<Env>()
|
|
|
1010
1004
|
}),
|
|
1011
1005
|
OpenApi.validate('json', schema.passkeyOptions.json),
|
|
1012
1006
|
async (c) => {
|
|
1013
|
-
// The ceremony runs at Tempo ID's origin,
|
|
1014
|
-
|
|
1007
|
+
// The ceremony runs at Tempo ID's origin, or at a first-party app's page, which the challenge
|
|
1008
|
+
// stores. `Cors.firstParty` refuses any other page's write before the route runs.
|
|
1009
|
+
const page = Cors.appOrigin(c)
|
|
1010
|
+
if (page && !c.var.firstParty?.length)
|
|
1015
1011
|
return ErrorResponse.json(c, new ErrorResponse.CrossSiteRequestError())
|
|
1012
|
+
// A registered passkey signs in as the user, so an app's page registers one only for an app
|
|
1013
|
+
// that the deployment trusts with its own challenges.
|
|
1014
|
+
if (page && !c.var.firstParty?.some((app) => app.sign))
|
|
1015
|
+
return ErrorResponse.json(
|
|
1016
|
+
c,
|
|
1017
|
+
new Passkey.RegisterNotPermittedError({ origin: page }),
|
|
1018
|
+
)
|
|
1016
1019
|
|
|
1017
1020
|
const session = await Timing.measure(c, Session.get(c), 'Session.get')
|
|
1018
1021
|
if (!session)
|
|
@@ -1062,14 +1065,26 @@ export const account = new Hono<Env>()
|
|
|
1062
1065
|
}),
|
|
1063
1066
|
'Realm.withDefaults',
|
|
1064
1067
|
)
|
|
1065
|
-
|
|
1068
|
+
// The relying party must cover the page beside Tempo ID, so the page shares a site with Tempo
|
|
1069
|
+
// ID, and the browser sends the session cookie on the page's requests.
|
|
1070
|
+
const relyingParty = Passkey.relyingParty(realms, {
|
|
1071
|
+
origin: env.URL,
|
|
1072
|
+
page,
|
|
1073
|
+
})
|
|
1066
1074
|
const realm = realms.find((entry) => entry.id === relyingParty?.realmId)
|
|
1067
1075
|
if (!relyingParty || !realm)
|
|
1068
|
-
return ErrorResponse.json(
|
|
1076
|
+
return ErrorResponse.json(
|
|
1077
|
+
c,
|
|
1078
|
+
new Passkey.NotPermittedError({ origin: page }),
|
|
1079
|
+
)
|
|
1069
1080
|
|
|
1070
1081
|
const challenge = await Timing.measure(
|
|
1071
1082
|
c,
|
|
1072
|
-
Passkey.requestRegistration(db, {
|
|
1083
|
+
Passkey.requestRegistration(db, {
|
|
1084
|
+
origin: page,
|
|
1085
|
+
rpId: relyingParty.rpId,
|
|
1086
|
+
userId,
|
|
1087
|
+
}),
|
|
1073
1088
|
'Passkey.requestRegistration',
|
|
1074
1089
|
)
|
|
1075
1090
|
const excluded = held.flatMap((key) =>
|
|
@@ -1102,7 +1117,7 @@ export const account = new Hono<Env>()
|
|
|
1102
1117
|
'/v1/account/passkey',
|
|
1103
1118
|
OpenApi.describeRoute({
|
|
1104
1119
|
description:
|
|
1105
|
-
|
|
1120
|
+
'Passkey registration, step 2 of 3: verifies the credential from `navigator.credentials.create()`, and returns a challenge for the new passkey to sign. The signature proves that the authenticator holds the private key.',
|
|
1106
1121
|
responses: OpenApi.responses({
|
|
1107
1122
|
errors: [
|
|
1108
1123
|
...BodyLimit.errors,
|
|
@@ -1113,6 +1128,7 @@ export const account = new Hono<Env>()
|
|
|
1113
1128
|
ErrorResponse.CrossSiteRequestError,
|
|
1114
1129
|
Passkey.LimitError,
|
|
1115
1130
|
Passkey.ReauthenticationRequiredError,
|
|
1131
|
+
Passkey.RegisterNotPermittedError,
|
|
1116
1132
|
Passkey.WebAuthnRejectedError,
|
|
1117
1133
|
],
|
|
1118
1134
|
success: {
|
|
@@ -1125,8 +1141,16 @@ export const account = new Hono<Env>()
|
|
|
1125
1141
|
}),
|
|
1126
1142
|
OpenApi.validate('json', schema.passkey.json),
|
|
1127
1143
|
async (c) => {
|
|
1128
|
-
|
|
1144
|
+
const page = Cors.appOrigin(c)
|
|
1145
|
+
if (page && !c.var.firstParty?.length)
|
|
1129
1146
|
return ErrorResponse.json(c, new ErrorResponse.CrossSiteRequestError())
|
|
1147
|
+
// A registered passkey signs in as the user, so an app's page registers one only for an app
|
|
1148
|
+
// that the deployment trusts with its own challenges.
|
|
1149
|
+
if (page && !c.var.firstParty?.some((app) => app.sign))
|
|
1150
|
+
return ErrorResponse.json(
|
|
1151
|
+
c,
|
|
1152
|
+
new Passkey.RegisterNotPermittedError({ origin: page }),
|
|
1153
|
+
)
|
|
1130
1154
|
|
|
1131
1155
|
const session = await Timing.measure(c, Session.get(c), 'Session.get')
|
|
1132
1156
|
if (!session)
|
|
@@ -1157,13 +1181,15 @@ export const account = new Hono<Env>()
|
|
|
1157
1181
|
}),
|
|
1158
1182
|
'Passkey.takeRegistration',
|
|
1159
1183
|
)
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1184
|
+
// A challenge serves only the page that requested it, and the browser must report that page.
|
|
1185
|
+
const verified =
|
|
1186
|
+
challenge && challenge.origin === page
|
|
1187
|
+
? Passkey.verifyRegistration(credential, {
|
|
1188
|
+
challenge: challenge.challenge,
|
|
1189
|
+
origin: challenge.origin ?? new URL(env.URL).origin,
|
|
1190
|
+
rpId: challenge.rpId,
|
|
1191
|
+
})
|
|
1192
|
+
: undefined
|
|
1167
1193
|
if (!challenge || !verified)
|
|
1168
1194
|
return ErrorResponse.json(c, new Passkey.WebAuthnRejectedError())
|
|
1169
1195
|
|
|
@@ -1209,6 +1235,7 @@ export const account = new Hono<Env>()
|
|
|
1209
1235
|
c,
|
|
1210
1236
|
Passkey.requestProof(db, {
|
|
1211
1237
|
credential: verified,
|
|
1238
|
+
origin: challenge.origin,
|
|
1212
1239
|
rpId: challenge.rpId,
|
|
1213
1240
|
userId,
|
|
1214
1241
|
}),
|
|
@@ -1230,7 +1257,7 @@ export const account = new Hono<Env>()
|
|
|
1230
1257
|
'/v1/account/passkey/verify',
|
|
1231
1258
|
OpenApi.describeRoute({
|
|
1232
1259
|
description:
|
|
1233
|
-
"
|
|
1260
|
+
"Passkey registration, step 3 of 3: verifies the new passkey's assertion from `navigator.credentials.get()`, and stores the passkey. The passkey owns a new Tempo Account, or joins `account` as a second owner.",
|
|
1234
1261
|
responses: OpenApi.responses({
|
|
1235
1262
|
errors: [
|
|
1236
1263
|
...BodyLimit.errors,
|
|
@@ -1244,6 +1271,7 @@ export const account = new Hono<Env>()
|
|
|
1244
1271
|
ErrorResponse.CrossSiteRequestError,
|
|
1245
1272
|
Passkey.LimitError,
|
|
1246
1273
|
Passkey.ReauthenticationRequiredError,
|
|
1274
|
+
Passkey.RegisterNotPermittedError,
|
|
1247
1275
|
Passkey.WebAuthnRejectedError,
|
|
1248
1276
|
],
|
|
1249
1277
|
success: {
|
|
@@ -1256,8 +1284,16 @@ export const account = new Hono<Env>()
|
|
|
1256
1284
|
}),
|
|
1257
1285
|
OpenApi.validate('json', schema.passkeyVerify.json),
|
|
1258
1286
|
async (c) => {
|
|
1259
|
-
|
|
1287
|
+
const page = Cors.appOrigin(c)
|
|
1288
|
+
if (page && !c.var.firstParty?.length)
|
|
1260
1289
|
return ErrorResponse.json(c, new ErrorResponse.CrossSiteRequestError())
|
|
1290
|
+
// A registered passkey signs in as the user, so an app's page registers one only for an app
|
|
1291
|
+
// that the deployment trusts with its own challenges.
|
|
1292
|
+
if (page && !c.var.firstParty?.some((app) => app.sign))
|
|
1293
|
+
return ErrorResponse.json(
|
|
1294
|
+
c,
|
|
1295
|
+
new Passkey.RegisterNotPermittedError({ origin: page }),
|
|
1296
|
+
)
|
|
1261
1297
|
|
|
1262
1298
|
const session = await Timing.measure(c, Session.get(c), 'Session.get')
|
|
1263
1299
|
if (!session)
|
|
@@ -1291,10 +1327,11 @@ export const account = new Hono<Env>()
|
|
|
1291
1327
|
// Only the attested public key verifies the proof, so the user holds its private key.
|
|
1292
1328
|
if (
|
|
1293
1329
|
!proof ||
|
|
1330
|
+
proof.origin !== page ||
|
|
1294
1331
|
assertion.id !== proof.id ||
|
|
1295
1332
|
!Passkey.verify(assertion, {
|
|
1296
1333
|
challenge: proof.challenge,
|
|
1297
|
-
origin: new URL(env.URL).origin,
|
|
1334
|
+
origin: proof.origin ?? new URL(env.URL).origin,
|
|
1298
1335
|
publicKey: proof.publicKey,
|
|
1299
1336
|
rpId: proof.rpId,
|
|
1300
1337
|
})
|
|
@@ -1399,7 +1436,7 @@ export const account = new Hono<Env>()
|
|
|
1399
1436
|
'/v1/realms',
|
|
1400
1437
|
OpenApi.describeRoute({
|
|
1401
1438
|
description:
|
|
1402
|
-
'Lists the realms of the
|
|
1439
|
+
'Lists the realms of the `client_id` app, and whether passkey sign-in works on the page that sends the request.',
|
|
1403
1440
|
responses: OpenApi.responses({
|
|
1404
1441
|
errors: [...OpenApi.validate.errors],
|
|
1405
1442
|
success: {
|
|
@@ -1459,7 +1496,7 @@ export const account = new Hono<Env>()
|
|
|
1459
1496
|
'/v1/chains',
|
|
1460
1497
|
OpenApi.describeRoute({
|
|
1461
1498
|
description:
|
|
1462
|
-
'Lists the chains that the `chain` parameter
|
|
1499
|
+
'Lists the chains that the `chain` parameter accepts, with their chain IDs.',
|
|
1463
1500
|
responses: OpenApi.responses({
|
|
1464
1501
|
success: {
|
|
1465
1502
|
description: 'The chains.',
|
|
@@ -1474,7 +1511,7 @@ export const account = new Hono<Env>()
|
|
|
1474
1511
|
'/i/chains',
|
|
1475
1512
|
OpenApi.describeRoute({
|
|
1476
1513
|
description:
|
|
1477
|
-
"Lists the chains
|
|
1514
|
+
"Lists the chains, as `GET /v1/chains` does, with whether each has a faucet. Internal to Tempo ID's own pages.",
|
|
1478
1515
|
// Internal routes stay out of `/openapi.json` and `/docs`.
|
|
1479
1516
|
hide: true,
|
|
1480
1517
|
responses: OpenApi.responses({
|
|
@@ -1504,7 +1541,7 @@ export const account = new Hono<Env>()
|
|
|
1504
1541
|
'/i/chains/status',
|
|
1505
1542
|
OpenApi.describeRoute({
|
|
1506
1543
|
description:
|
|
1507
|
-
"Returns whether the node and the Tempo API of each chain
|
|
1544
|
+
"Returns whether the node and the Tempo API of each added chain respond. Internal to Tempo ID's own pages.",
|
|
1508
1545
|
// Internal routes stay out of `/openapi.json` and `/docs`.
|
|
1509
1546
|
hide: true,
|
|
1510
1547
|
responses: OpenApi.responses({
|
|
@@ -1555,7 +1592,7 @@ export const account = new Hono<Env>()
|
|
|
1555
1592
|
'/i/account/fund',
|
|
1556
1593
|
OpenApi.describeRoute({
|
|
1557
1594
|
description:
|
|
1558
|
-
"Funds one of the
|
|
1595
|
+
"Funds one of the user's Tempo Accounts from the faucet of a test chain, and waits for the transfers. Internal to Tempo ID's own pages.",
|
|
1559
1596
|
// Internal routes stay out of `/openapi.json` and `/docs`.
|
|
1560
1597
|
hide: true,
|
|
1561
1598
|
responses: OpenApi.responses({
|
|
@@ -1670,7 +1707,7 @@ export const account = new Hono<Env>()
|
|
|
1670
1707
|
'/v1/account/upgrade',
|
|
1671
1708
|
OpenApi.describeRoute({
|
|
1672
1709
|
description:
|
|
1673
|
-
"Upgrades a wallet.tempo passkey's Tempo Account
|
|
1710
|
+
"Upgrades a wallet.tempo passkey's Tempo Account to a configurable account (TIP-1113) at the same address. The first request returns a passkey step, and the repeat with `passkey.assertion` sends the upgrade.",
|
|
1674
1711
|
responses: OpenApi.responses({
|
|
1675
1712
|
errors: [
|
|
1676
1713
|
...BodyLimit.errors,
|
|
@@ -1884,7 +1921,7 @@ export const account = new Hono<Env>()
|
|
|
1884
1921
|
'/i/account/passkeys',
|
|
1885
1922
|
OpenApi.describeRoute({
|
|
1886
1923
|
description:
|
|
1887
|
-
"Lists the wallet.tempo passkeys of the
|
|
1924
|
+
"Lists the wallet.tempo passkeys of the user's email that are not linked yet, for `POST /v1/account/upgrade`. Internal to Tempo ID's own pages.",
|
|
1888
1925
|
// Internal routes stay out of `/openapi.json` and `/docs`.
|
|
1889
1926
|
hide: true,
|
|
1890
1927
|
responses: OpenApi.responses({
|
|
@@ -1942,7 +1979,7 @@ export const account = new Hono<Env>()
|
|
|
1942
1979
|
'/i/account/upgrades',
|
|
1943
1980
|
OpenApi.describeRoute({
|
|
1944
1981
|
description:
|
|
1945
|
-
"Lists the
|
|
1982
|
+
"Lists the user's pending upgrades on `chain`, for `POST /v1/account/upgrade`. Internal to Tempo ID's own pages.",
|
|
1946
1983
|
// Internal routes stay out of `/openapi.json` and `/docs`.
|
|
1947
1984
|
hide: true,
|
|
1948
1985
|
responses: OpenApi.responses({
|