accounts 0.6.1 → 0.6.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/CHANGELOG.md +8 -0
- package/dist/core/Schema.d.ts +12 -12
- package/dist/core/adapters/dialog.d.ts.map +1 -1
- package/dist/core/adapters/dialog.js +3 -1
- package/dist/core/adapters/dialog.js.map +1 -1
- package/dist/core/zod/rpc.d.ts +9 -9
- package/dist/core/zod/rpc.js +1 -1
- package/dist/core/zod/rpc.js.map +1 -1
- package/dist/server/CliAuth.d.ts +11 -11
- package/dist/server/CliAuth.js +1 -1
- package/dist/server/CliAuth.js.map +1 -1
- package/dist/server/Handler.d.ts +4 -252
- package/dist/server/Handler.d.ts.map +1 -1
- package/dist/server/Handler.js +4 -573
- package/dist/server/Handler.js.map +1 -1
- package/dist/server/internal/handlers/codeAuth.d.ts +41 -0
- package/dist/server/internal/handlers/codeAuth.d.ts.map +1 -0
- package/dist/server/internal/handlers/codeAuth.js +104 -0
- package/dist/server/internal/handlers/codeAuth.js.map +1 -0
- package/dist/server/internal/handlers/feePayer.d.ts +73 -0
- package/dist/server/internal/handlers/feePayer.d.ts.map +1 -0
- package/dist/server/internal/handlers/feePayer.js +184 -0
- package/dist/server/internal/handlers/feePayer.js.map +1 -0
- package/dist/server/internal/handlers/relay.d.ts +148 -0
- package/dist/server/internal/handlers/relay.d.ts.map +1 -0
- package/dist/server/internal/handlers/relay.js +600 -0
- package/dist/server/internal/handlers/relay.js.map +1 -0
- package/dist/server/internal/handlers/utils.d.ts +12 -0
- package/dist/server/internal/handlers/utils.d.ts.map +1 -0
- package/dist/server/internal/handlers/utils.js +80 -0
- package/dist/server/internal/handlers/utils.js.map +1 -0
- package/dist/server/internal/handlers/webAuthn.d.ts +57 -0
- package/dist/server/internal/handlers/webAuthn.d.ts.map +1 -0
- package/dist/server/internal/handlers/webAuthn.js +143 -0
- package/dist/server/internal/handlers/webAuthn.js.map +1 -0
- package/package.json +2 -2
- package/src/core/Provider.connect.browser.test.ts +23 -2
- package/src/core/adapters/dialog.ts +6 -1
- package/src/core/zod/rpc.ts +1 -1
- package/src/server/CliAuth.ts +1 -1
- package/src/server/Handler.test.ts +3 -418
- package/src/server/Handler.ts +5 -766
- package/src/server/internal/handlers/codeAuth.ts +148 -0
- package/src/server/internal/handlers/feePayer.test.ts +335 -0
- package/src/server/internal/handlers/feePayer.ts +271 -0
- package/src/server/internal/handlers/relay.test.ts +767 -0
- package/src/server/internal/handlers/relay.ts +817 -0
- package/src/server/internal/handlers/utils.ts +96 -0
- package/src/server/internal/handlers/webAuthn.test.ts +170 -0
- package/src/server/internal/handlers/webAuthn.ts +213 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Hex, RpcRequest, RpcResponse } from 'ox';
|
|
2
|
+
import { Transaction as core_Transaction } from 'ox/tempo';
|
|
3
|
+
import * as z from 'zod/mini';
|
|
4
|
+
export function resolveChainId(value) {
|
|
5
|
+
if (typeof value === 'number')
|
|
6
|
+
return value;
|
|
7
|
+
if (typeof value === 'bigint')
|
|
8
|
+
return Number(value);
|
|
9
|
+
if (typeof value === 'string' && Hex.validate(value))
|
|
10
|
+
return Hex.toNumber(value);
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
export function formatFillTransactionRequest(client, value) {
|
|
14
|
+
const format = client.chain?.formatters?.transactionRequest?.format;
|
|
15
|
+
if (!format)
|
|
16
|
+
return value;
|
|
17
|
+
return format({ ...value }, 'fillTransaction');
|
|
18
|
+
}
|
|
19
|
+
export function normalizeFillTransactionRequest(value) {
|
|
20
|
+
if (typeof value.to !== 'undefined' || typeof value.data !== 'undefined')
|
|
21
|
+
return value;
|
|
22
|
+
if (!Array.isArray(value.calls) || value.calls.length !== 1)
|
|
23
|
+
return value;
|
|
24
|
+
const [call] = value.calls;
|
|
25
|
+
const { calls: _, ...rest } = value;
|
|
26
|
+
return {
|
|
27
|
+
...rest,
|
|
28
|
+
...(typeof call?.data !== 'undefined' ? { data: call.data } : {}),
|
|
29
|
+
...(typeof call?.to !== 'undefined' ? { to: call.to } : {}),
|
|
30
|
+
...(typeof call?.value !== 'undefined' ? { value: normalizeFillValue(call.value) } : {}),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function normalizeFillValue(value) {
|
|
34
|
+
if (typeof value !== 'string' || !value.startsWith('0x'))
|
|
35
|
+
return value;
|
|
36
|
+
return BigInt(value === '0x' ? '0x0' : value);
|
|
37
|
+
}
|
|
38
|
+
export function normalizeTempoTransaction(value) {
|
|
39
|
+
if (!value)
|
|
40
|
+
throw new Error('Expected `tx` in eth_fillTransaction response.');
|
|
41
|
+
return core_Transaction.fromRpc({ type: '0x76', ...value });
|
|
42
|
+
}
|
|
43
|
+
export function rpcError(request, error) {
|
|
44
|
+
if (error instanceof RpcResponse.InvalidParamsError)
|
|
45
|
+
return Response.json(RpcResponse.from({ error }, { request }));
|
|
46
|
+
if (error instanceof RpcResponse.MethodNotSupportedError)
|
|
47
|
+
return Response.json(RpcResponse.from({ error }, { request }));
|
|
48
|
+
if (error.name === 'ZodError')
|
|
49
|
+
return Response.json(RpcResponse.from({
|
|
50
|
+
error: new RpcResponse.InvalidParamsError({
|
|
51
|
+
message: error.message,
|
|
52
|
+
}),
|
|
53
|
+
}, { request }));
|
|
54
|
+
const inner = resolveError(error);
|
|
55
|
+
const message = inner.message ?? error.message;
|
|
56
|
+
const code = inner.code ?? -32603;
|
|
57
|
+
const data = inner.data;
|
|
58
|
+
return Response.json(RpcResponse.from({
|
|
59
|
+
error: { code, message, ...(data ? { data } : {}) },
|
|
60
|
+
}, { request }));
|
|
61
|
+
}
|
|
62
|
+
export function rpcResult(request, result) {
|
|
63
|
+
return Response.json(RpcResponse.from({ result }, { request }));
|
|
64
|
+
}
|
|
65
|
+
export const parseParams = z.readonly(z.tuple([z.record(z.string(), z.unknown())]));
|
|
66
|
+
function resolveError(error) {
|
|
67
|
+
if (!error || typeof error !== 'object')
|
|
68
|
+
return {};
|
|
69
|
+
const e = error;
|
|
70
|
+
// Walk to the innermost cause with a numeric code (raw RPC error).
|
|
71
|
+
if (e.cause && typeof e.cause === 'object') {
|
|
72
|
+
const inner = resolveError(e.cause);
|
|
73
|
+
if (inner.message)
|
|
74
|
+
return inner;
|
|
75
|
+
}
|
|
76
|
+
if (typeof e.code === 'number' && typeof e.message === 'string')
|
|
77
|
+
return { message: e.message, code: e.code, data: e.data };
|
|
78
|
+
return {};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/server/internal/handlers/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type Handler, from } from '../../Handler.js';
|
|
2
|
+
import * as Kv from '../../Kv.js';
|
|
3
|
+
/**
|
|
4
|
+
* Instantiates a WebAuthn ceremony handler that manages registration and
|
|
5
|
+
* authentication flows server-side.
|
|
6
|
+
*
|
|
7
|
+
* Exposes 4 POST endpoints following the webauthx convention:
|
|
8
|
+
* - `POST /register/options` — generate credential creation options
|
|
9
|
+
* - `POST /register` — verify registration and store credential
|
|
10
|
+
* - `POST /login/options` — generate credential request options
|
|
11
|
+
* - `POST /login` — verify authentication
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { Handler, Kv } from 'accounts/server'
|
|
16
|
+
*
|
|
17
|
+
* const handler = Handler.webAuthn({
|
|
18
|
+
* kv: Kv.memory(),
|
|
19
|
+
* origin: 'https://example.com',
|
|
20
|
+
* rpId: 'example.com',
|
|
21
|
+
* })
|
|
22
|
+
*
|
|
23
|
+
* export default handler
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @param options - Options.
|
|
27
|
+
* @returns Request handler.
|
|
28
|
+
*/
|
|
29
|
+
export declare function webAuthn(options: webAuthn.Options): Handler;
|
|
30
|
+
export declare namespace webAuthn {
|
|
31
|
+
type Options = from.Options & {
|
|
32
|
+
/** Maximum age of a challenge in seconds before it expires. @default 300 */
|
|
33
|
+
challengeTtl?: number | undefined;
|
|
34
|
+
/** Key-value store for challenges and credentials. */
|
|
35
|
+
kv: Kv.Kv;
|
|
36
|
+
/** Called after a successful registration. The returned response is merged onto the default JSON response. */
|
|
37
|
+
onRegister?: (parameters: {
|
|
38
|
+
credentialId: string;
|
|
39
|
+
publicKey: string;
|
|
40
|
+
request: Request;
|
|
41
|
+
}) => Response | Promise<Response> | void | Promise<void>;
|
|
42
|
+
/** Called after a successful authentication. The returned response is merged onto the default JSON response. */
|
|
43
|
+
onAuthenticate?: (parameters: {
|
|
44
|
+
credentialId: string;
|
|
45
|
+
publicKey: string;
|
|
46
|
+
userId?: string | undefined;
|
|
47
|
+
request: Request;
|
|
48
|
+
}) => Response | Promise<Response> | void | Promise<void>;
|
|
49
|
+
/** Expected origin(s) (e.g. `"https://example.com"` or `["https://a.com", "https://b.com"]`). */
|
|
50
|
+
origin: string | readonly string[];
|
|
51
|
+
/** Path prefix for the WebAuthn endpoints (e.g. `"/webauthn"`). @default "" */
|
|
52
|
+
path?: string | undefined;
|
|
53
|
+
/** Relying Party ID (e.g. `"example.com"`). */
|
|
54
|
+
rpId: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=webAuthn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webAuthn.d.ts","sourceRoot":"","sources":["../../../../src/server/internal/handlers/webAuthn.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,KAAK,EAAE,MAAM,aAAa,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAqI3D;AAED,MAAM,CAAC,OAAO,WAAW,QAAQ,CAAC;IAChC,KAAK,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG;QAC5B,4EAA4E;QAC5E,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QACjC,sDAAsD;QACtD,EAAE,EAAE,EAAE,CAAC,EAAE,CAAA;QACT,8GAA8G;QAC9G,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE;YACxB,YAAY,EAAE,MAAM,CAAA;YACpB,SAAS,EAAE,MAAM,CAAA;YACjB,OAAO,EAAE,OAAO,CAAA;SACjB,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QACzD,gHAAgH;QAChH,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE;YAC5B,YAAY,EAAE,MAAM,CAAA;YACpB,SAAS,EAAE,MAAM,CAAA;YACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAC3B,OAAO,EAAE,OAAO,CAAA;SACjB,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QACzD,iGAAiG;QACjG,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;QAClC,+EAA+E;QAC/E,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QACzB,+CAA+C;QAC/C,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;CACF"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Base64, Bytes, Hex } from 'ox';
|
|
2
|
+
import { Credential } from 'ox/webauthn';
|
|
3
|
+
import { Authentication, Registration, } from 'webauthx/server';
|
|
4
|
+
import { from } from '../../Handler.js';
|
|
5
|
+
import * as Kv from '../../Kv.js';
|
|
6
|
+
/**
|
|
7
|
+
* Instantiates a WebAuthn ceremony handler that manages registration and
|
|
8
|
+
* authentication flows server-side.
|
|
9
|
+
*
|
|
10
|
+
* Exposes 4 POST endpoints following the webauthx convention:
|
|
11
|
+
* - `POST /register/options` — generate credential creation options
|
|
12
|
+
* - `POST /register` — verify registration and store credential
|
|
13
|
+
* - `POST /login/options` — generate credential request options
|
|
14
|
+
* - `POST /login` — verify authentication
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { Handler, Kv } from 'accounts/server'
|
|
19
|
+
*
|
|
20
|
+
* const handler = Handler.webAuthn({
|
|
21
|
+
* kv: Kv.memory(),
|
|
22
|
+
* origin: 'https://example.com',
|
|
23
|
+
* rpId: 'example.com',
|
|
24
|
+
* })
|
|
25
|
+
*
|
|
26
|
+
* export default handler
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @param options - Options.
|
|
30
|
+
* @returns Request handler.
|
|
31
|
+
*/
|
|
32
|
+
export function webAuthn(options) {
|
|
33
|
+
const { challengeTtl = 300, kv, onAuthenticate, onRegister, path = '', rpId, ...rest } = options;
|
|
34
|
+
const origin = options.origin;
|
|
35
|
+
const router = from(rest);
|
|
36
|
+
router.post(`${path}/register/options`, async (c) => {
|
|
37
|
+
try {
|
|
38
|
+
const body = await c.req.raw.json();
|
|
39
|
+
const { excludeCredentialIds, name, userId } = body;
|
|
40
|
+
const { challenge, options } = Registration.getOptions({
|
|
41
|
+
excludeCredentialIds,
|
|
42
|
+
name,
|
|
43
|
+
rp: { id: rpId, name: rpId },
|
|
44
|
+
...(userId ? { user: { id: new TextEncoder().encode(userId), name } } : undefined),
|
|
45
|
+
});
|
|
46
|
+
await kv.set(`challenge:${challenge}`, Date.now());
|
|
47
|
+
return Response.json({ options });
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return Response.json({ error: error.message }, { status: 400 });
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
router.post(`${path}/register`, async (c) => {
|
|
54
|
+
try {
|
|
55
|
+
const credential = (await c.req.raw.json());
|
|
56
|
+
const deserialized = Credential.deserialize(credential);
|
|
57
|
+
const clientData = JSON.parse(Bytes.toString(new Uint8Array(deserialized.clientDataJSON)));
|
|
58
|
+
const challenge = Hex.fromBytes(Base64.toBytes(clientData.challenge));
|
|
59
|
+
const stored = await kv.get(`challenge:${challenge}`);
|
|
60
|
+
if (!stored || Date.now() - stored > challengeTtl * 1_000)
|
|
61
|
+
throw new Error('Missing or expired challenge');
|
|
62
|
+
await kv.delete(`challenge:${challenge}`);
|
|
63
|
+
const result = Registration.verify(credential, {
|
|
64
|
+
challenge,
|
|
65
|
+
origin,
|
|
66
|
+
rpId,
|
|
67
|
+
});
|
|
68
|
+
const { publicKey } = result.credential;
|
|
69
|
+
const credentialId = credential.id;
|
|
70
|
+
await kv.set(`credential:${credentialId}`, { publicKey });
|
|
71
|
+
const json = { credentialId, publicKey };
|
|
72
|
+
const hook = await onRegister?.({ credentialId, publicKey, request: c.req.raw });
|
|
73
|
+
return mergeResponse(json, hook);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return Response.json({ error: error.message }, { status: 400 });
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
router.post(`${path}/login/options`, async (c) => {
|
|
80
|
+
try {
|
|
81
|
+
const body = await c.req.raw.json();
|
|
82
|
+
const { allowCredentialIds, challenge: requestChallenge, credentialId, mediation, } = body;
|
|
83
|
+
const { challenge, options: authOptions } = Authentication.getOptions({
|
|
84
|
+
challenge: requestChallenge,
|
|
85
|
+
credentialId: allowCredentialIds ?? credentialId,
|
|
86
|
+
rpId,
|
|
87
|
+
});
|
|
88
|
+
const options = mediation ? { ...authOptions, mediation } : authOptions;
|
|
89
|
+
await kv.set(`challenge:${challenge}`, Date.now());
|
|
90
|
+
return Response.json({ options });
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
return Response.json({ error: error.message }, { status: 400 });
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
router.post(`${path}/login`, async (c) => {
|
|
97
|
+
try {
|
|
98
|
+
const response = (await c.req.raw.json());
|
|
99
|
+
const clientData = JSON.parse(response.metadata.clientDataJSON);
|
|
100
|
+
const challenge = Hex.fromBytes(Base64.toBytes(clientData.challenge));
|
|
101
|
+
const stored = await kv.get(`challenge:${challenge}`);
|
|
102
|
+
if (!stored || Date.now() - stored > challengeTtl * 1_000)
|
|
103
|
+
throw new Error('Missing or expired challenge');
|
|
104
|
+
await kv.delete(`challenge:${challenge}`);
|
|
105
|
+
const credentialData = await kv.get(`credential:${response.id}`);
|
|
106
|
+
if (!credentialData)
|
|
107
|
+
throw new Error('Unknown credential');
|
|
108
|
+
const valid = Authentication.verify(response, {
|
|
109
|
+
challenge,
|
|
110
|
+
origin,
|
|
111
|
+
publicKey: credentialData.publicKey,
|
|
112
|
+
rpId,
|
|
113
|
+
});
|
|
114
|
+
if (!valid)
|
|
115
|
+
throw new Error('Authentication failed');
|
|
116
|
+
const rawResponse = response.raw?.response;
|
|
117
|
+
const userHandle = rawResponse?.userHandle;
|
|
118
|
+
const json = {
|
|
119
|
+
credentialId: response.id,
|
|
120
|
+
publicKey: credentialData.publicKey,
|
|
121
|
+
...(userHandle && userHandle.length > 0 ? { userId: userHandle } : undefined),
|
|
122
|
+
};
|
|
123
|
+
const hook = await onAuthenticate?.({ ...json, request: c.req.raw });
|
|
124
|
+
return mergeResponse(json, hook);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
return Response.json({ error: error.message }, { status: 400 });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return router;
|
|
131
|
+
}
|
|
132
|
+
async function mergeResponse(json, hook) {
|
|
133
|
+
if (!hook)
|
|
134
|
+
return Response.json(json);
|
|
135
|
+
const extra = (await hook.json().catch(() => ({})));
|
|
136
|
+
const headers = new Headers(hook.headers);
|
|
137
|
+
headers.set('content-type', 'application/json');
|
|
138
|
+
return new Response(JSON.stringify({ ...json, ...extra }), {
|
|
139
|
+
headers,
|
|
140
|
+
status: hook.status,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=webAuthn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webAuthn.js","sourceRoot":"","sources":["../../../../src/server/internal/handlers/webAuthn.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"name": "accounts",
|
|
3
3
|
"description": "Tempo Accounts SDK",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.6.
|
|
5
|
+
"version": "0.6.2",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"hono": "^4.12.12",
|
|
8
8
|
"idb-keyval": "^6.2.2",
|
|
9
9
|
"mipd": "^0.0.7",
|
|
10
10
|
"mppx": "^0.5.10",
|
|
11
|
-
"ox": "~0.14.
|
|
11
|
+
"ox": "~0.14.15",
|
|
12
12
|
"webauthx": "~0.1.0",
|
|
13
13
|
"zod": "^4.3.6",
|
|
14
14
|
"zustand": "^5.0.11"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Hex } from 'ox'
|
|
1
|
+
import { Hex, WebCryptoP256 } from 'ox'
|
|
2
2
|
import { type Address, createClient, defineChain, parseUnits } from 'viem'
|
|
3
3
|
import { tempoLocalnet, tempoModerato } from 'viem/chains'
|
|
4
|
-
import { Actions, Addresses } from 'viem/tempo'
|
|
4
|
+
import { Account as TempoAccount, Actions, Addresses } from 'viem/tempo'
|
|
5
5
|
import { afterEach, beforeAll, describe, expect, test } from 'vp/test'
|
|
6
6
|
|
|
7
7
|
import { accounts, http } from '../../test/config.js'
|
|
@@ -311,6 +311,27 @@ describe('wallet_authorizeAccessKey', () => {
|
|
|
311
311
|
)
|
|
312
312
|
expect(result.keyAuthorization.address).toMatch(/^0x[0-9a-fA-F]{40}$/)
|
|
313
313
|
})
|
|
314
|
+
|
|
315
|
+
test('behavior: authorizes an external p256 access key via iframe confirm', async () => {
|
|
316
|
+
provider = getProvider()
|
|
317
|
+
await connectViaIframe(provider)
|
|
318
|
+
|
|
319
|
+
const keyPair = await WebCryptoP256.createKeyPair()
|
|
320
|
+
const accessKeyAccount = TempoAccount.fromWebCryptoP256(keyPair)
|
|
321
|
+
|
|
322
|
+
const result = await interact(
|
|
323
|
+
provider.request({
|
|
324
|
+
method: 'wallet_authorizeAccessKey',
|
|
325
|
+
params: [{ ...accessKeyAccount, expiry: Expiry.days(1) }],
|
|
326
|
+
}),
|
|
327
|
+
async (iframe) => {
|
|
328
|
+
await iframe.getByTestId('confirm').click()
|
|
329
|
+
},
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
expect(result.keyAuthorization.keyId).toBe(accessKeyAccount.address)
|
|
333
|
+
expect(result.keyAuthorization.keyType).toMatchInlineSnapshot(`"p256"`)
|
|
334
|
+
})
|
|
314
335
|
})
|
|
315
336
|
|
|
316
337
|
describe('wallet_revokeAccessKey', () => {
|
|
@@ -368,7 +368,12 @@ export function dialog(options: dialog.Options = {}): Adapter.Adapter {
|
|
|
368
368
|
|
|
369
369
|
const result = await provider.request({
|
|
370
370
|
...request,
|
|
371
|
-
params: [
|
|
371
|
+
params: [
|
|
372
|
+
z.encode(
|
|
373
|
+
Rpc.wallet_connect.authorizeAccessKey,
|
|
374
|
+
accessKey ? accessKey.request : parameters,
|
|
375
|
+
)!,
|
|
376
|
+
],
|
|
372
377
|
})
|
|
373
378
|
|
|
374
379
|
if (accessKey) {
|
package/src/core/zod/rpc.ts
CHANGED
|
@@ -48,7 +48,7 @@ export const keyType = z.union([z.literal('secp256k1'), z.literal('p256'), z.lit
|
|
|
48
48
|
export const keyAuthorization = z.object({
|
|
49
49
|
address: u.address(),
|
|
50
50
|
chainId: u.bigint(),
|
|
51
|
-
expiry: z.
|
|
51
|
+
expiry: z.union([u.number(), z.null(), z.undefined()]),
|
|
52
52
|
keyId: u.address(),
|
|
53
53
|
keyType,
|
|
54
54
|
limits: z.optional(z.readonly(z.array(z.object({ token: u.address(), limit: u.bigint() })))),
|
package/src/server/CliAuth.ts
CHANGED
|
@@ -17,7 +17,7 @@ export const keyType = z.union([z.literal('secp256k1'), z.literal('p256'), z.lit
|
|
|
17
17
|
export const keyAuthorization = z.object({
|
|
18
18
|
address: u.address(),
|
|
19
19
|
chainId: u.bigint(),
|
|
20
|
-
expiry: z.
|
|
20
|
+
expiry: z.union([u.number(), z.null(), z.undefined()]),
|
|
21
21
|
keyId: u.address(),
|
|
22
22
|
keyType,
|
|
23
23
|
limits: z.optional(z.readonly(z.array(z.object({ token: u.address(), limit: u.bigint() })))),
|