accounts 0.3.0 → 0.4.1
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 +13 -0
- package/LICENSE +21 -0
- package/README.md +97 -0
- package/dist/core/AccessKey.d.ts +55 -0
- package/dist/core/AccessKey.d.ts.map +1 -0
- package/dist/core/AccessKey.js +69 -0
- package/dist/core/AccessKey.js.map +1 -0
- package/dist/core/Account.d.ts +91 -0
- package/dist/core/Account.d.ts.map +1 -0
- package/dist/core/Account.js +64 -0
- package/dist/core/Account.js.map +1 -0
- package/dist/core/Adapter.d.ts +187 -0
- package/dist/core/Adapter.d.ts.map +1 -0
- package/dist/core/Adapter.js +7 -0
- package/dist/core/Adapter.js.map +1 -0
- package/dist/core/Ceremony.d.ts +109 -0
- package/dist/core/Ceremony.d.ts.map +1 -0
- package/dist/core/Ceremony.js +104 -0
- package/dist/core/Ceremony.js.map +1 -0
- package/dist/core/Client.d.ts +16 -0
- package/dist/core/Client.d.ts.map +1 -0
- package/dist/core/Client.js +18 -0
- package/dist/core/Client.js.map +1 -0
- package/dist/core/Dialog.d.ts +52 -0
- package/dist/core/Dialog.d.ts.map +1 -0
- package/dist/core/Dialog.js +342 -0
- package/dist/core/Dialog.js.map +1 -0
- package/dist/core/Expiry.d.ts +15 -0
- package/dist/core/Expiry.d.ts.map +1 -0
- package/dist/core/Expiry.js +29 -0
- package/dist/core/Expiry.js.map +1 -0
- package/dist/core/Messenger.d.ts +86 -0
- package/dist/core/Messenger.d.ts.map +1 -0
- package/dist/core/Messenger.js +127 -0
- package/dist/core/Messenger.js.map +1 -0
- package/dist/core/Provider.d.ts +69 -0
- package/dist/core/Provider.d.ts.map +1 -0
- package/dist/core/Provider.js +401 -0
- package/dist/core/Provider.js.map +1 -0
- package/dist/core/Remote.d.ts +114 -0
- package/dist/core/Remote.d.ts.map +1 -0
- package/dist/core/Remote.js +116 -0
- package/dist/core/Remote.js.map +1 -0
- package/dist/core/Schema.d.ts +805 -0
- package/dist/core/Schema.d.ts.map +1 -0
- package/dist/core/Schema.js +43 -0
- package/dist/core/Schema.js.map +1 -0
- package/dist/core/Storage.d.ts +42 -0
- package/dist/core/Storage.d.ts.map +1 -0
- package/dist/core/Storage.js +173 -0
- package/dist/core/Storage.js.map +1 -0
- package/dist/core/Store.d.ts +58 -0
- package/dist/core/Store.d.ts.map +1 -0
- package/dist/core/Store.js +58 -0
- package/dist/core/Store.js.map +1 -0
- package/dist/core/adapters/dangerous_secp256k1.d.ts +30 -0
- package/dist/core/adapters/dangerous_secp256k1.d.ts.map +1 -0
- package/dist/core/adapters/dangerous_secp256k1.js +39 -0
- package/dist/core/adapters/dangerous_secp256k1.js.map +1 -0
- package/dist/core/adapters/dialog.d.ts +31 -0
- package/dist/core/adapters/dialog.d.ts.map +1 -0
- package/dist/core/adapters/dialog.js +306 -0
- package/dist/core/adapters/dialog.js.map +1 -0
- package/dist/core/adapters/local.d.ts +33 -0
- package/dist/core/adapters/local.d.ts.map +1 -0
- package/dist/core/adapters/local.js +227 -0
- package/dist/core/adapters/local.js.map +1 -0
- package/dist/core/adapters/webAuthn.d.ts +36 -0
- package/dist/core/adapters/webAuthn.d.ts.map +1 -0
- package/dist/core/adapters/webAuthn.js +93 -0
- package/dist/core/adapters/webAuthn.js.map +1 -0
- package/dist/core/internal/withDedupe.d.ts +12 -0
- package/dist/core/internal/withDedupe.d.ts.map +1 -0
- package/dist/core/internal/withDedupe.js +12 -0
- package/dist/core/internal/withDedupe.js.map +1 -0
- package/dist/core/zod/request.d.ts +31 -0
- package/dist/core/zod/request.d.ts.map +1 -0
- package/dist/core/zod/request.js +41 -0
- package/dist/core/zod/request.js.map +1 -0
- package/dist/core/zod/rpc.d.ts +603 -0
- package/dist/core/zod/rpc.d.ts.map +1 -0
- package/dist/core/zod/rpc.js +293 -0
- package/dist/core/zod/rpc.js.map +1 -0
- package/dist/core/zod/utils.d.ts +18 -0
- package/dist/core/zod/utils.d.ts.map +1 -0
- package/dist/core/zod/utils.js +21 -0
- package/dist/core/zod/utils.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/types.d.ts +284 -0
- package/dist/internal/types.d.ts.map +1 -0
- package/dist/internal/types.js +2 -0
- package/dist/internal/types.js.map +1 -0
- package/dist/server/Handler.d.ts +257 -0
- package/dist/server/Handler.d.ts.map +1 -0
- package/dist/server/Handler.js +433 -0
- package/dist/server/Handler.js.map +1 -0
- package/dist/server/Kv.d.ts +16 -0
- package/dist/server/Kv.d.ts.map +1 -0
- package/dist/server/Kv.js +30 -0
- package/dist/server/Kv.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/internal/requestListener.d.ts +124 -0
- package/dist/server/internal/requestListener.d.ts.map +1 -0
- package/dist/server/internal/requestListener.js +173 -0
- package/dist/server/internal/requestListener.js.map +1 -0
- package/dist/wagmi/Connector.d.ts +93 -0
- package/dist/wagmi/Connector.d.ts.map +1 -0
- package/dist/wagmi/Connector.js +238 -0
- package/dist/wagmi/Connector.js.map +1 -0
- package/dist/wagmi/index.d.ts +3 -0
- package/dist/wagmi/index.d.ts.map +1 -0
- package/dist/wagmi/index.js +3 -0
- package/dist/wagmi/index.js.map +1 -0
- package/package.json +56 -2
- package/src/core/AccessKey.test.ts +257 -0
- package/src/core/AccessKey.ts +123 -0
- package/src/core/Account.test.ts +309 -0
- package/src/core/Account.ts +152 -0
- package/src/core/Adapter.ts +238 -0
- package/src/core/Ceremony.browser.test.ts +239 -0
- package/src/core/Ceremony.test.ts +151 -0
- package/src/core/Ceremony.ts +203 -0
- package/src/core/Client.ts +36 -0
- package/src/core/Dialog.browser.test.ts +309 -0
- package/src/core/Dialog.test-d.ts +19 -0
- package/src/core/Dialog.ts +442 -0
- package/src/core/Expiry.ts +34 -0
- package/src/core/Messenger.ts +206 -0
- package/src/core/Provider.browser.test.ts +774 -0
- package/src/core/Provider.connect.browser.test.ts +415 -0
- package/src/core/Provider.test-d.ts +53 -0
- package/src/core/Provider.test.ts +1566 -0
- package/src/core/Provider.ts +559 -0
- package/src/core/Remote.ts +262 -0
- package/src/core/Schema.test-d.ts +211 -0
- package/src/core/Schema.ts +143 -0
- package/src/core/Storage.ts +213 -0
- package/src/core/Store.test.ts +287 -0
- package/src/core/Store.ts +129 -0
- package/src/core/adapters/dangerous_secp256k1.ts +53 -0
- package/src/core/adapters/dialog.ts +379 -0
- package/src/core/adapters/local.test.ts +97 -0
- package/src/core/adapters/local.ts +277 -0
- package/src/core/adapters/webAuthn.ts +129 -0
- package/src/core/internal/withDedupe.test.ts +116 -0
- package/src/core/internal/withDedupe.ts +20 -0
- package/src/core/mppx.test.ts +83 -0
- package/src/core/zod/request.test.ts +121 -0
- package/src/core/zod/request.ts +70 -0
- package/src/core/zod/rpc.ts +374 -0
- package/src/core/zod/utils.test.ts +69 -0
- package/src/core/zod/utils.ts +40 -0
- package/src/index.ts +14 -0
- package/src/internal/types.ts +378 -0
- package/src/server/Handler.test.ts +1014 -0
- package/src/server/Handler.ts +605 -0
- package/src/server/Kv.ts +46 -0
- package/src/server/index.ts +2 -0
- package/src/server/internal/requestListener.ts +273 -0
- package/src/tsconfig.json +9 -0
- package/src/wagmi/Connector.ts +287 -0
- package/src/wagmi/index.ts +2 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vp/test'
|
|
2
|
+
|
|
3
|
+
import * as Schema from '../Schema.js'
|
|
4
|
+
import * as RpcRequest from './request.js'
|
|
5
|
+
|
|
6
|
+
describe('validate', () => {
|
|
7
|
+
test('default: validates eth_accounts', () => {
|
|
8
|
+
const result = RpcRequest.validate(Schema.Request, {
|
|
9
|
+
method: 'eth_accounts',
|
|
10
|
+
})
|
|
11
|
+
expect(result._decoded).toMatchInlineSnapshot(`
|
|
12
|
+
{
|
|
13
|
+
"method": "eth_accounts",
|
|
14
|
+
}
|
|
15
|
+
`)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('default: validates eth_chainId', () => {
|
|
19
|
+
const result = RpcRequest.validate(Schema.Request, {
|
|
20
|
+
method: 'eth_chainId',
|
|
21
|
+
})
|
|
22
|
+
expect(result._decoded).toMatchInlineSnapshot(`
|
|
23
|
+
{
|
|
24
|
+
"method": "eth_chainId",
|
|
25
|
+
}
|
|
26
|
+
`)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('default: validates wallet_connect without params', () => {
|
|
30
|
+
const result = RpcRequest.validate(Schema.Request, {
|
|
31
|
+
method: 'wallet_connect',
|
|
32
|
+
})
|
|
33
|
+
expect(result._decoded).toMatchInlineSnapshot(`
|
|
34
|
+
{
|
|
35
|
+
"method": "wallet_connect",
|
|
36
|
+
}
|
|
37
|
+
`)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('default: validates wallet_connect with capabilities', () => {
|
|
41
|
+
const result = RpcRequest.validate(Schema.Request, {
|
|
42
|
+
method: 'wallet_connect',
|
|
43
|
+
params: [{ capabilities: { method: 'register' } }],
|
|
44
|
+
})
|
|
45
|
+
expect(result._decoded).toMatchInlineSnapshot(`
|
|
46
|
+
{
|
|
47
|
+
"method": "wallet_connect",
|
|
48
|
+
"params": [
|
|
49
|
+
{
|
|
50
|
+
"capabilities": {
|
|
51
|
+
"method": "register",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
}
|
|
56
|
+
`)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('default: validates wallet_disconnect', () => {
|
|
60
|
+
const result = RpcRequest.validate(Schema.Request, {
|
|
61
|
+
method: 'wallet_disconnect',
|
|
62
|
+
})
|
|
63
|
+
expect(result._decoded).toMatchInlineSnapshot(`
|
|
64
|
+
{
|
|
65
|
+
"method": "wallet_disconnect",
|
|
66
|
+
}
|
|
67
|
+
`)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
test('default: validates wallet_switchEthereumChain with hex chainId', () => {
|
|
71
|
+
const result = RpcRequest.validate(Schema.Request, {
|
|
72
|
+
method: 'wallet_switchEthereumChain',
|
|
73
|
+
params: [{ chainId: '0xa' }],
|
|
74
|
+
})
|
|
75
|
+
expect(result._decoded).toMatchInlineSnapshot(`
|
|
76
|
+
{
|
|
77
|
+
"method": "wallet_switchEthereumChain",
|
|
78
|
+
"params": [
|
|
79
|
+
{
|
|
80
|
+
"chainId": 10,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
}
|
|
84
|
+
`)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('behavior: preserves original request properties', () => {
|
|
88
|
+
const result = RpcRequest.validate(Schema.Request, {
|
|
89
|
+
method: 'eth_accounts',
|
|
90
|
+
id: 1,
|
|
91
|
+
jsonrpc: '2.0',
|
|
92
|
+
})
|
|
93
|
+
expect({ id: (result as any).id, jsonrpc: (result as any).jsonrpc }).toMatchInlineSnapshot(`
|
|
94
|
+
{
|
|
95
|
+
"id": 1,
|
|
96
|
+
"jsonrpc": "2.0",
|
|
97
|
+
}
|
|
98
|
+
`)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('error: throws UnsupportedMethodError for unknown methods', () => {
|
|
102
|
+
expect(() =>
|
|
103
|
+
RpcRequest.validate(Schema.Request, {
|
|
104
|
+
method: 'eth_unknownMethod',
|
|
105
|
+
}),
|
|
106
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
107
|
+
`[Provider.UnsupportedMethodError: Unsupported method "eth_unknownMethod".]`,
|
|
108
|
+
)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('error: throws ProviderRpcError for invalid params', () => {
|
|
112
|
+
expect(() =>
|
|
113
|
+
RpcRequest.validate(Schema.Request, {
|
|
114
|
+
method: 'wallet_switchEthereumChain',
|
|
115
|
+
params: [{ chainId: 'not-hex' }],
|
|
116
|
+
}),
|
|
117
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
118
|
+
`[ProviderRpcError: Invalid params: params.0.chainId: Expected hex value, params.0.chainId: Invalid input]`,
|
|
119
|
+
)
|
|
120
|
+
})
|
|
121
|
+
})
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Provider } from 'ox'
|
|
2
|
+
import * as z from 'zod/mini'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Validates an incoming JSON-RPC request against the provider schema.
|
|
6
|
+
*
|
|
7
|
+
* Returns the original request augmented with a `_decoded` property
|
|
8
|
+
* containing the Zod-parsed output (with codec transforms applied).
|
|
9
|
+
*
|
|
10
|
+
* Throws EIP-1193 errors on validation failure:
|
|
11
|
+
* - `4200` if the method is not in the discriminated union
|
|
12
|
+
* - `-32602` if params fail validation
|
|
13
|
+
*/
|
|
14
|
+
export function validate<const schema extends z.ZodMiniType>(
|
|
15
|
+
schema: schema,
|
|
16
|
+
value: unknown,
|
|
17
|
+
): WithDecoded<schema> {
|
|
18
|
+
const result = z.safeParse(schema, value)
|
|
19
|
+
if (result.error) {
|
|
20
|
+
const issue = result.error.issues.at(0)
|
|
21
|
+
if (issue?.code === 'invalid_union' && (issue as any).note === 'No matching discriminator')
|
|
22
|
+
throw new Provider.UnsupportedMethodError({
|
|
23
|
+
message: `Unsupported method "${(value as any)?.method}".`,
|
|
24
|
+
})
|
|
25
|
+
throw new Provider.ProviderRpcError(
|
|
26
|
+
-32602,
|
|
27
|
+
`Invalid params: ${formatIssues(result.error.issues)}`,
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
return { ...(value as any), _decoded: result.data } as never
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function formatIssues(issues: readonly z.core.$ZodIssue[]): string {
|
|
34
|
+
return issues
|
|
35
|
+
.flatMap((issue) => {
|
|
36
|
+
if (issue.code === 'invalid_union' && issue.errors.length > 0)
|
|
37
|
+
return issue.errors.flatMap((branch) =>
|
|
38
|
+
branch.map(
|
|
39
|
+
(i) =>
|
|
40
|
+
`${[...issue.path, ...i.path].join('.')}: ${i.code === 'invalid_union' && i.errors.length > 0 ? formatIssues([i]) : i.message}`,
|
|
41
|
+
),
|
|
42
|
+
)
|
|
43
|
+
return [`${issue.path.join('.')}: ${issue.message}`]
|
|
44
|
+
})
|
|
45
|
+
.join(', ')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A validated request with the decoded (Zod-parsed) output attached.
|
|
50
|
+
*
|
|
51
|
+
* Distributes over the union so that switching on `method` narrows
|
|
52
|
+
* both the input and `_decoded` properties together.
|
|
53
|
+
*/
|
|
54
|
+
export type WithDecoded<schema extends z.ZodMiniType> =
|
|
55
|
+
z.output<schema> extends infer decoded
|
|
56
|
+
? decoded extends { method: infer m extends string }
|
|
57
|
+
? Extract<z.input<schema>, { method: m }> & { _decoded: decoded }
|
|
58
|
+
: never
|
|
59
|
+
: never
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Encodes a decoded (output) value back to its wire (input) format
|
|
63
|
+
* by running codec `reverseTransform` functions.
|
|
64
|
+
*/
|
|
65
|
+
export function encode<const schema extends z.ZodMiniType>(
|
|
66
|
+
schema: schema,
|
|
67
|
+
value: z.output<schema>,
|
|
68
|
+
): z.input<schema> {
|
|
69
|
+
return (z as never as { encode: typeof encode }).encode(schema, value)
|
|
70
|
+
}
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import type { SignatureEnvelope } from 'ox/tempo'
|
|
2
|
+
import * as z from 'zod/mini'
|
|
3
|
+
|
|
4
|
+
import * as Schema from '../Schema.js'
|
|
5
|
+
import * as u from './utils.js'
|
|
6
|
+
|
|
7
|
+
export const log = z.object({
|
|
8
|
+
address: u.address(),
|
|
9
|
+
blockHash: u.hex(),
|
|
10
|
+
blockNumber: u.bigint(),
|
|
11
|
+
data: u.hex(),
|
|
12
|
+
logIndex: u.number(),
|
|
13
|
+
removed: z.boolean(),
|
|
14
|
+
topics: z.readonly(z.array(u.hex())),
|
|
15
|
+
transactionHash: u.hex(),
|
|
16
|
+
transactionIndex: u.number(),
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export const receipt = z.object({
|
|
20
|
+
blobGasPrice: z.optional(u.bigint()),
|
|
21
|
+
blobGasUsed: z.optional(u.bigint()),
|
|
22
|
+
blockHash: u.hex(),
|
|
23
|
+
blockNumber: u.bigint(),
|
|
24
|
+
contractAddress: z.nullable(u.address()),
|
|
25
|
+
cumulativeGasUsed: u.bigint(),
|
|
26
|
+
effectiveGasPrice: u.bigint(),
|
|
27
|
+
feePayer: z.optional(u.address()),
|
|
28
|
+
feeToken: z.optional(u.address()),
|
|
29
|
+
from: u.address(),
|
|
30
|
+
gasUsed: u.bigint(),
|
|
31
|
+
logs: z.array(log),
|
|
32
|
+
logsBloom: u.hex(),
|
|
33
|
+
root: z.optional(u.hex()),
|
|
34
|
+
status: z.codec(u.hex(), z.enum(['success', 'reverted']), {
|
|
35
|
+
decode: (value) => (value === '0x1' ? 'success' : 'reverted'),
|
|
36
|
+
encode: (value) => (value === 'success' ? '0x1' : '0x0'),
|
|
37
|
+
}),
|
|
38
|
+
to: z.nullable(u.address()),
|
|
39
|
+
transactionHash: u.hex(),
|
|
40
|
+
transactionIndex: u.number(),
|
|
41
|
+
type: u.hex(),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
export const signatureEnvelope = z.custom<SignatureEnvelope.SignatureEnvelopeRpc>()
|
|
45
|
+
|
|
46
|
+
export const keyType = z.union([z.literal('secp256k1'), z.literal('p256'), z.literal('webAuthn')])
|
|
47
|
+
|
|
48
|
+
export const keyAuthorization = z.object({
|
|
49
|
+
address: u.address(),
|
|
50
|
+
chainId: u.bigint(),
|
|
51
|
+
expiry: z.nullish(u.number()),
|
|
52
|
+
keyId: u.address(),
|
|
53
|
+
keyType,
|
|
54
|
+
limits: z.optional(z.readonly(z.array(z.object({ token: u.address(), limit: u.bigint() })))),
|
|
55
|
+
signature: signatureEnvelope,
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
export const call = z.object({
|
|
59
|
+
data: z.optional(u.hex()),
|
|
60
|
+
to: z.optional(u.address()),
|
|
61
|
+
value: z.optional(u.bigint()),
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
export const transactionRequest = z.object({
|
|
65
|
+
accessList: z.optional(
|
|
66
|
+
z.array(z.object({ address: u.address(), storageKeys: z.array(u.hex()) })),
|
|
67
|
+
),
|
|
68
|
+
calls: z.optional(z.readonly(z.array(call))),
|
|
69
|
+
chainId: z.optional(u.number()),
|
|
70
|
+
feePayer: z.optional(z.union([z.boolean(), z.url()])),
|
|
71
|
+
feeToken: z.optional(u.address()),
|
|
72
|
+
from: z.optional(u.address()),
|
|
73
|
+
gas: z.optional(u.bigint()),
|
|
74
|
+
maxFeePerGas: z.optional(u.bigint()),
|
|
75
|
+
maxPriorityFeePerGas: z.optional(u.bigint()),
|
|
76
|
+
nonce: z.optional(u.number()),
|
|
77
|
+
nonceKey: z.optional(u.bigint()),
|
|
78
|
+
validAfter: z.optional(u.number()),
|
|
79
|
+
validBefore: z.optional(u.number()),
|
|
80
|
+
value: z.optional(u.bigint()),
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
export namespace eth_accounts {
|
|
84
|
+
export const schema = Schema.defineItem({
|
|
85
|
+
method: z.literal('eth_accounts'),
|
|
86
|
+
params: undefined,
|
|
87
|
+
returns: z.readonly(z.array(u.address())),
|
|
88
|
+
})
|
|
89
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
90
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export namespace eth_chainId {
|
|
94
|
+
export const schema = Schema.defineItem({
|
|
95
|
+
method: z.literal('eth_chainId'),
|
|
96
|
+
params: undefined,
|
|
97
|
+
returns: u.hex(),
|
|
98
|
+
})
|
|
99
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
100
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export namespace eth_requestAccounts {
|
|
104
|
+
export const schema = Schema.defineItem({
|
|
105
|
+
method: z.literal('eth_requestAccounts'),
|
|
106
|
+
params: undefined,
|
|
107
|
+
returns: z.readonly(z.array(u.address())),
|
|
108
|
+
})
|
|
109
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
110
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export namespace eth_sendTransaction {
|
|
114
|
+
export const schema = Schema.defineItem({
|
|
115
|
+
method: z.literal('eth_sendTransaction'),
|
|
116
|
+
params: z.readonly(z.tuple([transactionRequest])),
|
|
117
|
+
returns: u.hex(),
|
|
118
|
+
})
|
|
119
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
120
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export namespace eth_signTransaction {
|
|
124
|
+
export const schema = Schema.defineItem({
|
|
125
|
+
method: z.literal('eth_signTransaction'),
|
|
126
|
+
params: z.readonly(z.tuple([transactionRequest])),
|
|
127
|
+
returns: u.hex(),
|
|
128
|
+
})
|
|
129
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
130
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export namespace eth_sendTransactionSync {
|
|
134
|
+
export const schema = Schema.defineItem({
|
|
135
|
+
method: z.literal('eth_sendTransactionSync'),
|
|
136
|
+
params: z.readonly(z.tuple([transactionRequest])),
|
|
137
|
+
returns: receipt,
|
|
138
|
+
})
|
|
139
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
140
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export namespace eth_signTypedData_v4 {
|
|
144
|
+
export const schema = Schema.defineItem({
|
|
145
|
+
method: z.literal('eth_signTypedData_v4'),
|
|
146
|
+
params: z.readonly(z.tuple([u.address(), z.string()])),
|
|
147
|
+
returns: u.hex(),
|
|
148
|
+
})
|
|
149
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
150
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export namespace personal_sign {
|
|
154
|
+
export const schema = Schema.defineItem({
|
|
155
|
+
method: z.literal('personal_sign'),
|
|
156
|
+
params: z.readonly(z.tuple([u.hex(), u.address()])),
|
|
157
|
+
returns: u.hex(),
|
|
158
|
+
})
|
|
159
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
160
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const sendCallsCapabilities = z.optional(z.object({ sync: z.optional(z.boolean()) }))
|
|
164
|
+
|
|
165
|
+
export namespace wallet_sendCalls {
|
|
166
|
+
export const schema = Schema.defineItem({
|
|
167
|
+
method: z.literal('wallet_sendCalls'),
|
|
168
|
+
params: z.optional(
|
|
169
|
+
z.readonly(
|
|
170
|
+
z.tuple([
|
|
171
|
+
z.object({
|
|
172
|
+
atomicRequired: z.optional(z.boolean()),
|
|
173
|
+
calls: z.readonly(z.array(call)),
|
|
174
|
+
capabilities: sendCallsCapabilities,
|
|
175
|
+
chainId: z.optional(u.number()),
|
|
176
|
+
from: z.optional(u.address()),
|
|
177
|
+
version: z.optional(z.string()),
|
|
178
|
+
}),
|
|
179
|
+
]),
|
|
180
|
+
),
|
|
181
|
+
),
|
|
182
|
+
returns: z.object({
|
|
183
|
+
atomic: z.optional(z.boolean()),
|
|
184
|
+
capabilities: sendCallsCapabilities,
|
|
185
|
+
chainId: z.optional(u.number()),
|
|
186
|
+
id: z.string(),
|
|
187
|
+
receipts: z.optional(z.array(receipt)),
|
|
188
|
+
status: z.optional(z.number()),
|
|
189
|
+
version: z.optional(z.string()),
|
|
190
|
+
}),
|
|
191
|
+
})
|
|
192
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
193
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export namespace wallet_getBalances {
|
|
197
|
+
export const schema = Schema.defineItem({
|
|
198
|
+
method: z.literal('wallet_getBalances'),
|
|
199
|
+
params: z.optional(
|
|
200
|
+
z.readonly(
|
|
201
|
+
z.tuple([
|
|
202
|
+
z.object({
|
|
203
|
+
account: z.optional(u.address()),
|
|
204
|
+
chainId: z.optional(u.number()),
|
|
205
|
+
tokens: z.optional(z.readonly(z.array(u.address()))),
|
|
206
|
+
}),
|
|
207
|
+
]),
|
|
208
|
+
),
|
|
209
|
+
),
|
|
210
|
+
returns: z.readonly(
|
|
211
|
+
z.array(
|
|
212
|
+
z.object({
|
|
213
|
+
address: u.address(),
|
|
214
|
+
balance: u.bigint(),
|
|
215
|
+
decimals: z.number(),
|
|
216
|
+
display: z.string(),
|
|
217
|
+
name: z.string(),
|
|
218
|
+
symbol: z.string(),
|
|
219
|
+
}),
|
|
220
|
+
),
|
|
221
|
+
),
|
|
222
|
+
})
|
|
223
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
224
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export namespace wallet_getCapabilities {
|
|
228
|
+
export const schema = Schema.defineItem({
|
|
229
|
+
method: z.literal('wallet_getCapabilities'),
|
|
230
|
+
params: z.optional(
|
|
231
|
+
z.readonly(
|
|
232
|
+
z.union([z.tuple([u.address()]), z.tuple([u.address(), z.readonly(z.array(u.hex()))])]),
|
|
233
|
+
),
|
|
234
|
+
),
|
|
235
|
+
returns: z.record(
|
|
236
|
+
u.hex(),
|
|
237
|
+
z.object({
|
|
238
|
+
accessKeys: z.optional(
|
|
239
|
+
z.object({
|
|
240
|
+
status: z.union([z.literal('supported'), z.literal('unsupported')]),
|
|
241
|
+
}),
|
|
242
|
+
),
|
|
243
|
+
atomic: z.object({
|
|
244
|
+
status: z.union([z.literal('supported'), z.literal('ready'), z.literal('unsupported')]),
|
|
245
|
+
}),
|
|
246
|
+
}),
|
|
247
|
+
),
|
|
248
|
+
})
|
|
249
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
250
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export namespace wallet_authorizeAccessKey {
|
|
254
|
+
export const parameters = z.object({
|
|
255
|
+
address: z.optional(u.address()),
|
|
256
|
+
expiry: z.number(),
|
|
257
|
+
keyType: z.optional(keyType),
|
|
258
|
+
limits: z.optional(z.readonly(z.array(z.object({ token: u.address(), limit: u.bigint() })))),
|
|
259
|
+
publicKey: z.optional(u.hex()),
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
export const schema = Schema.defineItem({
|
|
263
|
+
method: z.literal('wallet_authorizeAccessKey'),
|
|
264
|
+
params: z.readonly(z.tuple([parameters])),
|
|
265
|
+
returns: keyAuthorization,
|
|
266
|
+
})
|
|
267
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
268
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export namespace wallet_revokeAccessKey {
|
|
272
|
+
export const schema = Schema.defineItem({
|
|
273
|
+
method: z.literal('wallet_revokeAccessKey'),
|
|
274
|
+
params: z.readonly(
|
|
275
|
+
z.tuple([z.object({ address: u.address(), accessKeyAddress: u.address() })]),
|
|
276
|
+
),
|
|
277
|
+
returns: undefined,
|
|
278
|
+
})
|
|
279
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
280
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export namespace wallet_connect {
|
|
284
|
+
export const authorizeAccessKey = z.optional(wallet_authorizeAccessKey.parameters)
|
|
285
|
+
|
|
286
|
+
export const capabilities = {
|
|
287
|
+
request: z.optional(
|
|
288
|
+
z.union([
|
|
289
|
+
z.object({
|
|
290
|
+
digest: z.optional(u.hex()),
|
|
291
|
+
authorizeAccessKey,
|
|
292
|
+
method: z.literal('register'),
|
|
293
|
+
name: z.optional(z.string()),
|
|
294
|
+
userId: z.optional(z.string()),
|
|
295
|
+
}),
|
|
296
|
+
z.object({
|
|
297
|
+
digest: z.optional(u.hex()),
|
|
298
|
+
credentialId: z.optional(z.string()),
|
|
299
|
+
authorizeAccessKey,
|
|
300
|
+
method: z.optional(z.literal('login')),
|
|
301
|
+
selectAccount: z.optional(z.boolean()),
|
|
302
|
+
}),
|
|
303
|
+
]),
|
|
304
|
+
),
|
|
305
|
+
result: z.object({
|
|
306
|
+
keyAuthorization: z.optional(keyAuthorization),
|
|
307
|
+
signature: z.optional(u.hex()),
|
|
308
|
+
}),
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export const schema = Schema.defineItem({
|
|
312
|
+
method: z.literal('wallet_connect'),
|
|
313
|
+
params: z.optional(
|
|
314
|
+
z.readonly(
|
|
315
|
+
z.tuple([
|
|
316
|
+
z.object({
|
|
317
|
+
capabilities: capabilities.request,
|
|
318
|
+
chainId: z.optional(u.number()),
|
|
319
|
+
version: z.optional(z.string()),
|
|
320
|
+
}),
|
|
321
|
+
]),
|
|
322
|
+
),
|
|
323
|
+
),
|
|
324
|
+
returns: z.object({
|
|
325
|
+
accounts: z.readonly(
|
|
326
|
+
z.array(
|
|
327
|
+
z.object({
|
|
328
|
+
address: u.address(),
|
|
329
|
+
capabilities: capabilities.result,
|
|
330
|
+
}),
|
|
331
|
+
),
|
|
332
|
+
),
|
|
333
|
+
}),
|
|
334
|
+
})
|
|
335
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
336
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export namespace wallet_disconnect {
|
|
340
|
+
export const schema = Schema.defineItem({
|
|
341
|
+
method: z.literal('wallet_disconnect'),
|
|
342
|
+
params: undefined,
|
|
343
|
+
returns: undefined,
|
|
344
|
+
})
|
|
345
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
346
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export namespace wallet_getCallsStatus {
|
|
350
|
+
export const schema = Schema.defineItem({
|
|
351
|
+
method: z.literal('wallet_getCallsStatus'),
|
|
352
|
+
params: z.optional(z.readonly(z.tuple([z.string()]))),
|
|
353
|
+
returns: z.object({
|
|
354
|
+
atomic: z.boolean(),
|
|
355
|
+
chainId: u.number(),
|
|
356
|
+
id: z.string(),
|
|
357
|
+
receipts: z.optional(z.array(receipt)),
|
|
358
|
+
status: z.number(),
|
|
359
|
+
version: z.string(),
|
|
360
|
+
}),
|
|
361
|
+
})
|
|
362
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
363
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export namespace wallet_switchEthereumChain {
|
|
367
|
+
export const schema = Schema.defineItem({
|
|
368
|
+
method: z.literal('wallet_switchEthereumChain'),
|
|
369
|
+
params: z.readonly(z.tuple([z.object({ chainId: u.number() })])),
|
|
370
|
+
returns: undefined,
|
|
371
|
+
})
|
|
372
|
+
export type Encoded = Schema.Encoded<typeof schema>
|
|
373
|
+
export type Decoded = Schema.Decoded<typeof schema>
|
|
374
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vp/test'
|
|
2
|
+
import * as z from 'zod/mini'
|
|
3
|
+
|
|
4
|
+
import * as u from './utils.js'
|
|
5
|
+
|
|
6
|
+
describe('address', () => {
|
|
7
|
+
test('default: accepts valid address', () => {
|
|
8
|
+
const schema = u.address()
|
|
9
|
+
expect(z.parse(schema, '0x0000000000000000000000000000000000000001')).toMatchInlineSnapshot(
|
|
10
|
+
`"0x0000000000000000000000000000000000000001"`,
|
|
11
|
+
)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('error: rejects non-0x string', () => {
|
|
15
|
+
const schema = u.address()
|
|
16
|
+
expect(() => z.parse(schema, 'not-an-address')).toThrow()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('error: rejects non-string', () => {
|
|
20
|
+
const schema = u.address()
|
|
21
|
+
expect(() => z.parse(schema, 123)).toThrow()
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('hex', () => {
|
|
26
|
+
test('default: accepts valid hex', () => {
|
|
27
|
+
const schema = u.hex()
|
|
28
|
+
expect(z.parse(schema, '0xdeadbeef')).toMatchInlineSnapshot(`"0xdeadbeef"`)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('error: rejects non-0x string', () => {
|
|
32
|
+
const schema = u.hex()
|
|
33
|
+
expect(() => z.parse(schema, 'deadbeef')).toThrow()
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
describe('number', () => {
|
|
38
|
+
test('default: decodes hex to number', () => {
|
|
39
|
+
const schema = u.number()
|
|
40
|
+
expect(z.parse(schema, '0xa')).toMatchInlineSnapshot(`10`)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('default: decodes 0x0', () => {
|
|
44
|
+
const schema = u.number()
|
|
45
|
+
expect(z.parse(schema, '0x0')).toMatchInlineSnapshot(`0`)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('error: rejects non-hex', () => {
|
|
49
|
+
const schema = u.number()
|
|
50
|
+
expect(() => z.parse(schema, 'not-hex')).toThrow()
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('bigint', () => {
|
|
55
|
+
test('default: decodes hex to bigint', () => {
|
|
56
|
+
const schema = u.bigint()
|
|
57
|
+
expect(z.parse(schema, '0xff')).toMatchInlineSnapshot(`255n`)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('default: decodes large value', () => {
|
|
61
|
+
const schema = u.bigint()
|
|
62
|
+
expect(z.parse(schema, '0xde0b6b3a7640000')).toMatchInlineSnapshot(`1000000000000000000n`)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('error: rejects non-hex', () => {
|
|
66
|
+
const schema = u.bigint()
|
|
67
|
+
expect(() => z.parse(schema, 'not-hex')).toThrow()
|
|
68
|
+
})
|
|
69
|
+
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Hex } from 'ox'
|
|
2
|
+
import * as z from 'zod/mini'
|
|
3
|
+
import type * as zc from 'zod/v4/core'
|
|
4
|
+
|
|
5
|
+
import type { OneOf } from '../../internal/types.js'
|
|
6
|
+
|
|
7
|
+
/** EVM address (`0x...`). */
|
|
8
|
+
export const address = () => z.templateLiteral(['0x', z.string()], 'Expected address')
|
|
9
|
+
|
|
10
|
+
/** Hex-encoded bigint. Decodes from `0x...` hex or raw `bigint` to `bigint`. */
|
|
11
|
+
export const bigint = () =>
|
|
12
|
+
z.codec(z.union([hex(), z.bigint()]) as never as ReturnType<typeof hex>, z.bigint(), {
|
|
13
|
+
decode: (value) =>
|
|
14
|
+
typeof value === 'bigint' ? value : value === '0x' ? 0n : Hex.toBigInt(value),
|
|
15
|
+
encode: (value) => Hex.fromNumber(value),
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
/** Hex-encoded string (`0x...`). */
|
|
19
|
+
export const hex = () => z.templateLiteral(['0x', z.string()], 'Expected hex value')
|
|
20
|
+
|
|
21
|
+
/** Hex-encoded number. Decodes from `0x...` hex or raw `number` to `number`. */
|
|
22
|
+
export const number = () =>
|
|
23
|
+
z.codec(z.union([hex(), z.number()]) as never as ReturnType<typeof hex>, z.number(), {
|
|
24
|
+
decode: (value) =>
|
|
25
|
+
typeof value === 'number' ? value : value === '0x' ? 0 : Hex.toNumber(value),
|
|
26
|
+
encode: (value) => Hex.fromNumber(value),
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
/** `z.union` that narrows the output type so only one branch is active at a time. */
|
|
30
|
+
export function oneOf<const type extends readonly zc.SomeType[]>(
|
|
31
|
+
options: type,
|
|
32
|
+
): Omit<z.ZodMiniUnion<type>, '_zod'> & {
|
|
33
|
+
_zod: Omit<z.ZodMiniUnion<type>['_zod'], 'output'> & {
|
|
34
|
+
output: z.ZodMiniUnion<type>['_zod']['output'] extends object
|
|
35
|
+
? OneOf<z.ZodMiniUnion<type>['_zod']['output']>
|
|
36
|
+
: z.ZodMiniUnion<type>['_zod']['output']
|
|
37
|
+
}
|
|
38
|
+
} {
|
|
39
|
+
return z.union(options) as never
|
|
40
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * as Ceremony from './core/Ceremony.js'
|
|
2
|
+
export * as Dialog from './core/Dialog.js'
|
|
3
|
+
export * as Messenger from './core/Messenger.js'
|
|
4
|
+
export * as Schema from './core/Schema.js'
|
|
5
|
+
export * as Provider from './core/Provider.js'
|
|
6
|
+
export * as Expiry from './core/Expiry.js'
|
|
7
|
+
export * as Remote from './core/Remote.js'
|
|
8
|
+
export * as Rpc from './core/zod/rpc.js'
|
|
9
|
+
export * as Store from './core/Store.js'
|
|
10
|
+
export * as Storage from './core/Storage.js'
|
|
11
|
+
export { dialog, dialog as tempoWallet } from './core/adapters/dialog.js'
|
|
12
|
+
export { local } from './core/adapters/local.js'
|
|
13
|
+
export { webAuthn } from './core/adapters/webAuthn.js'
|
|
14
|
+
export { dangerous_secp256k1 } from './core/adapters/dangerous_secp256k1.js'
|