ox 0.14.12 → 0.14.14

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.
@@ -0,0 +1,70 @@
1
+ import type * as Block from '../core/Block.js';
2
+ import type * as BlockOverrides from '../core/BlockOverrides.js';
3
+ import type * as Hex from '../core/Hex.js';
4
+ import type * as Log from '../core/Log.js';
5
+ import type * as RpcSchema from '../core/RpcSchema.js';
6
+ import type * as StateOverrides from '../core/StateOverrides.js';
7
+ import type * as TransactionRequest from './TransactionRequest.js';
8
+ /**
9
+ * Union of all JSON-RPC Methods for the `tempo_` namespace.
10
+ *
11
+ * @example
12
+ * ```ts twoslash
13
+ * import { RpcSchema } from 'ox/tempo'
14
+ *
15
+ * type Schema = RpcSchema.Tempo
16
+ * // ^?
17
+ *
18
+ *
19
+ *
20
+ *
21
+ *
22
+ *
23
+ *
24
+ *
25
+ *
26
+ *
27
+ *
28
+ * ```
29
+ */
30
+ export type Tempo = RpcSchema.From<{
31
+ Request: {
32
+ method: 'tempo_simulateV1';
33
+ params: [
34
+ {
35
+ blockStateCalls: readonly {
36
+ blockOverrides?: BlockOverrides.Rpc | undefined;
37
+ calls?: readonly TransactionRequest.Rpc[] | undefined;
38
+ stateOverrides?: StateOverrides.Rpc | undefined;
39
+ }[];
40
+ returnFullTransactions?: boolean | undefined;
41
+ traceTransfers?: boolean | undefined;
42
+ validation?: boolean | undefined;
43
+ },
44
+ block: Block.Number<Hex.Hex> | Block.Tag | Block.Hash | Block.Identifier
45
+ ];
46
+ };
47
+ ReturnType: {
48
+ blocks: readonly (Block.Rpc & {
49
+ calls?: readonly {
50
+ error?: {
51
+ data?: Hex.Hex | undefined;
52
+ code: number;
53
+ message: string;
54
+ } | undefined;
55
+ logs?: readonly Log.Rpc[] | undefined;
56
+ gasUsed: Hex.Hex;
57
+ returnData: Hex.Hex;
58
+ status: Hex.Hex;
59
+ }[] | undefined;
60
+ })[];
61
+ tokenMetadata: {
62
+ [address: Hex.Hex]: {
63
+ name: string;
64
+ symbol: string;
65
+ currency: string;
66
+ };
67
+ };
68
+ };
69
+ }>;
70
+ //# sourceMappingURL=RpcSchema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RpcSchema.d.ts","sourceRoot":"","sources":["../../tempo/RpcSchema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,KAAK,cAAc,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,KAAK,GAAG,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,KAAK,GAAG,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,KAAK,cAAc,MAAM,2BAA2B,CAAA;AAChE,OAAO,KAAK,KAAK,kBAAkB,MAAM,yBAAyB,CAAA;AAElE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC;IACjC,OAAO,EAAE;QACP,MAAM,EAAE,kBAAkB,CAAA;QAC1B,MAAM,EAAE;YACN;gBACE,eAAe,EAAE,SAAS;oBACxB,cAAc,CAAC,EAAE,cAAc,CAAC,GAAG,GAAG,SAAS,CAAA;oBAC/C,KAAK,CAAC,EAAE,SAAS,kBAAkB,CAAC,GAAG,EAAE,GAAG,SAAS,CAAA;oBACrD,cAAc,CAAC,EAAE,cAAc,CAAC,GAAG,GAAG,SAAS,CAAA;iBAChD,EAAE,CAAA;gBACH,sBAAsB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;gBAC5C,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;gBACpC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;aACjC;YACD,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,UAAU;SACzE,CAAA;KACF,CAAA;IACD,UAAU,EAAE;QACV,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,GAAG;YAC5B,KAAK,CAAC,EACF,SAAS;gBACP,KAAK,CAAC,EACF;oBACE,IAAI,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,SAAS,CAAA;oBAC1B,IAAI,EAAE,MAAM,CAAA;oBACZ,OAAO,EAAE,MAAM,CAAA;iBAChB,GACD,SAAS,CAAA;gBACb,IAAI,CAAC,EAAE,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,SAAS,CAAA;gBACrC,OAAO,EAAE,GAAG,CAAC,GAAG,CAAA;gBAChB,UAAU,EAAE,GAAG,CAAC,GAAG,CAAA;gBACnB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAA;aAChB,EAAE,GACH,SAAS,CAAA;SACd,CAAC,EAAE,CAAA;QACJ,aAAa,EAAE;YACb,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,GAAG;gBAClB,IAAI,EAAE,MAAM,CAAA;gBACZ,MAAM,EAAE,MAAM,CAAA;gBACd,QAAQ,EAAE,MAAM,CAAA;aACjB,CAAA;SACF,CAAA;KACF,CAAA;CACF,CAAC,CAAA"}
@@ -123,6 +123,25 @@ export * as Period from './Period.js';
123
123
  * @category Reference
124
124
  */
125
125
  export * as PoolId from './PoolId.js';
126
+ /**
127
+ * Union of all JSON-RPC Methods for the `tempo_` namespace.
128
+ *
129
+ * @example
130
+ * ```ts twoslash
131
+ * import { Provider, RpcSchema } from 'ox'
132
+ * import { RpcSchema as TempoRpcSchema } from 'ox/tempo'
133
+ *
134
+ * const schema = RpcSchema.from<
135
+ * | RpcSchema.Default
136
+ * | TempoRpcSchema.Tempo
137
+ * >()
138
+ *
139
+ * const provider = Provider.from(window.ethereum!, { schema })
140
+ * ```
141
+ *
142
+ * @category Reference
143
+ */
144
+ export * as RpcSchema from './RpcSchema.js';
126
145
  /**
127
146
  * Signature envelope utilities for secp256k1, P256, WebAuthn, and keychain signatures.
128
147
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../tempo/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,YAAY,EAAE,CAAA;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAA;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAA;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AAErC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AAErC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAA;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAA;AAEjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAA;AAC7D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAA;AAC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../tempo/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,YAAY,EAAE,CAAA;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAA;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAA;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AAErC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AAErC;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAE3C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAA;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAA;AAEjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAA;AAC7D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAA;AAC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA"}
@@ -1,3 +1,3 @@
1
1
  /** @internal */
2
- export declare const version = "0.14.12";
2
+ export declare const version = "0.14.14";
3
3
  //# sourceMappingURL=version.d.ts.map
package/core/RpcSchema.ts CHANGED
@@ -271,3 +271,88 @@ export type Default = ResolvedRegister['RpcSchema']
271
271
  export type MethodNameGeneric<schema extends Generic = Generic> =
272
272
  | schema['Request']['method']
273
273
  | (string & {})
274
+
275
+ /**
276
+ * Converts an Ox {@link ox#RpcSchema.Generic} (union of `{ Request, ReturnType }`) to
277
+ * a [Viem-compatible RPC schema](https://viem.sh) (tuple of `{ Method, Parameters, ReturnType }`).
278
+ *
279
+ * @example
280
+ * ```ts twoslash
281
+ * import { RpcSchema } from 'ox'
282
+ *
283
+ * type ViemSchema = RpcSchema.ToViem<
284
+ * | {
285
+ * Request: { method: 'eth_blockNumber'; params?: undefined }
286
+ * ReturnType: `0x${string}`
287
+ * }
288
+ * | {
289
+ * Request: { method: 'eth_chainId'; params?: undefined }
290
+ * ReturnType: `0x${string}`
291
+ * }
292
+ * >
293
+ * // ^? [{ Method: 'eth_blockNumber'; Parameters?: undefined; ReturnType: `0x${string}` }, ...]
294
+ * ```
295
+ */
296
+ export type ToViem<schema extends Generic> = UnionToTuple<
297
+ schema extends schema
298
+ ? {
299
+ Method: schema['Request']['method']
300
+ Parameters: schema['Request']['params']
301
+ ReturnType: schema extends { ReturnType: infer r } ? r : unknown
302
+ }
303
+ : never
304
+ >
305
+
306
+ /**
307
+ * Converts a [Viem-compatible RPC schema](https://viem.sh) (tuple of `{ Method, Parameters, ReturnType }`)
308
+ * to an Ox {@link ox#RpcSchema.Generic} (union of `{ Request, ReturnType }`).
309
+ *
310
+ * @example
311
+ * ```ts twoslash
312
+ * import { RpcSchema } from 'ox'
313
+ *
314
+ * type OxSchema = RpcSchema.FromViem<[
315
+ * { Method: 'eth_blockNumber'; Parameters?: undefined; ReturnType: `0x${string}` },
316
+ * { Method: 'eth_chainId'; Parameters?: undefined; ReturnType: `0x${string}` },
317
+ * ]>
318
+ * // ^? { Request: { method: 'eth_blockNumber'; params?: undefined }; ReturnType: `0x${string}` } | ...
319
+ * ```
320
+ */
321
+ export type FromViem<schema extends readonly ViemSchemaItem[]> = {
322
+ [k in keyof schema]: schema[k] extends ViemSchemaItem
323
+ ? {
324
+ Request: {
325
+ method: schema[k]['Method']
326
+ params: schema[k]['Parameters']
327
+ }
328
+ ReturnType: schema[k]['ReturnType']
329
+ }
330
+ : never
331
+ }[number]
332
+
333
+ /** @internal */
334
+ type ViemSchemaItem = {
335
+ Method: string
336
+ Parameters?: unknown
337
+ ReturnType?: unknown
338
+ }
339
+
340
+ // --- Union-to-tuple helpers (order is not guaranteed, but stable) ---
341
+ /** @internal */
342
+ type UnionToIntersection<union> = (
343
+ union extends unknown
344
+ ? (arg: () => union) => void
345
+ : never
346
+ ) extends (arg: infer intersection) => void
347
+ ? intersection
348
+ : never
349
+
350
+ /** @internal */
351
+ type UnionLast<union> = UnionToIntersection<union> extends () => infer last
352
+ ? last
353
+ : never
354
+
355
+ /** @internal */
356
+ type UnionToTuple<union, last = UnionLast<union>> = [union] extends [never]
357
+ ? []
358
+ : [...UnionToTuple<Exclude<union, last>>, last]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ox",
3
3
  "description": "Ethereum Standard Library",
4
- "version": "0.14.12",
4
+ "version": "0.14.14",
5
5
  "main": "./_cjs/index.js",
6
6
  "module": "./_esm/index.js",
7
7
  "types": "./_types/index.d.ts",
@@ -519,6 +519,11 @@
519
519
  "import": "./_esm/tempo/PoolId.js",
520
520
  "default": "./_cjs/tempo/PoolId.js"
521
521
  },
522
+ "./tempo/RpcSchema": {
523
+ "types": "./_types/tempo/RpcSchema.d.ts",
524
+ "import": "./_esm/tempo/RpcSchema.js",
525
+ "default": "./_cjs/tempo/RpcSchema.js"
526
+ },
522
527
  "./tempo/SignatureEnvelope": {
523
528
  "types": "./_types/tempo/SignatureEnvelope.d.ts",
524
529
  "import": "./_esm/tempo/SignatureEnvelope.js",
@@ -1824,7 +1824,7 @@ describe('toTuple', () => {
1824
1824
  type: 'secp256k1',
1825
1825
  scopes: [
1826
1826
  {
1827
- contractAddress: '0x1234567890123456789012345678901234567890',
1827
+ address: '0x1234567890123456789012345678901234567890',
1828
1828
  },
1829
1829
  ],
1830
1830
  })
@@ -1851,7 +1851,7 @@ describe('toTuple', () => {
1851
1851
  const serialized = KeyAuthorization.serialize(authorization)
1852
1852
  const restored = KeyAuthorization.deserialize(serialized)
1853
1853
  expect(restored.scopes).toHaveLength(1)
1854
- expect(restored.scopes?.[0]?.contractAddress).toBe(
1854
+ expect(restored.scopes?.[0]?.address).toBe(
1855
1855
  '0x1234567890123456789012345678901234567890',
1856
1856
  )
1857
1857
  expect(restored.scopes?.[0]?.selector).toBeUndefined()
@@ -1864,11 +1864,11 @@ describe('toTuple', () => {
1864
1864
  type: 'secp256k1',
1865
1865
  scopes: [
1866
1866
  {
1867
- contractAddress: '0x1234567890123456789012345678901234567890',
1867
+ address: '0x1234567890123456789012345678901234567890',
1868
1868
  selector: '0xa9059cbb', // transfer
1869
1869
  },
1870
1870
  {
1871
- contractAddress: '0x1234567890123456789012345678901234567890',
1871
+ address: '0x1234567890123456789012345678901234567890',
1872
1872
  selector: '0x095ea7b3', // approve
1873
1873
  },
1874
1874
  ],
@@ -1889,7 +1889,7 @@ describe('toTuple', () => {
1889
1889
  type: 'secp256k1',
1890
1890
  scopes: [
1891
1891
  {
1892
- contractAddress: token,
1892
+ address: token,
1893
1893
  selector: '0xa9059cbb',
1894
1894
  recipients: [
1895
1895
  '0x1111111111111111111111111111111111111111',
@@ -1952,7 +1952,7 @@ describe('toTuple', () => {
1952
1952
  ],
1953
1953
  scopes: [
1954
1954
  {
1955
- contractAddress: '0x1234567890123456789012345678901234567890',
1955
+ address: '0x1234567890123456789012345678901234567890',
1956
1956
  selector: '0xa9059cbb',
1957
1957
  recipients: ['0x1111111111111111111111111111111111111111'],
1958
1958
  },
@@ -1975,7 +1975,7 @@ describe('toTuple', () => {
1975
1975
  type: 'secp256k1',
1976
1976
  scopes: [
1977
1977
  {
1978
- contractAddress: '0x1234567890123456789012345678901234567890',
1978
+ address: '0x1234567890123456789012345678901234567890',
1979
1979
  selector: '0xa9059cbb',
1980
1980
  },
1981
1981
  ],
@@ -1992,7 +1992,7 @@ describe('toTuple', () => {
1992
1992
  type: 'secp256k1',
1993
1993
  scopes: [
1994
1994
  {
1995
- contractAddress: '0x1234567890123456789012345678901234567890',
1995
+ address: '0x1234567890123456789012345678901234567890',
1996
1996
  selector: '0x095ea7b3',
1997
1997
  },
1998
1998
  ],
@@ -2000,6 +2000,101 @@ describe('toTuple', () => {
2000
2000
  expect(KeyAuthorization.hash(authorization2)).not.toBe(hash1)
2001
2001
  })
2002
2002
 
2003
+ test('call scopes: selector from function signature string', () => {
2004
+ const authorization = KeyAuthorization.from({
2005
+ address,
2006
+ chainId: 1n,
2007
+ type: 'secp256k1',
2008
+ scopes: [
2009
+ {
2010
+ address: '0x1234567890123456789012345678901234567890',
2011
+ selector: 'function transfer(address,uint256)',
2012
+ },
2013
+ {
2014
+ address: '0x1234567890123456789012345678901234567890',
2015
+ selector: 'function approve(address,uint256)',
2016
+ },
2017
+ ],
2018
+ })
2019
+
2020
+ const serialized = KeyAuthorization.serialize(authorization)
2021
+ const restored = KeyAuthorization.deserialize(serialized)
2022
+ expect(restored.scopes).toHaveLength(2)
2023
+ // transfer(address,uint256) => 0xa9059cbb
2024
+ expect(restored.scopes?.[0]?.selector).toBe('0xa9059cbb')
2025
+ // approve(address,uint256) => 0x095ea7b3
2026
+ expect(restored.scopes?.[1]?.selector).toBe('0x095ea7b3')
2027
+ })
2028
+
2029
+ test('call scopes: selector from signature with recipients', () => {
2030
+ const authorization = KeyAuthorization.from({
2031
+ address,
2032
+ chainId: 1n,
2033
+ type: 'secp256k1',
2034
+ scopes: [
2035
+ {
2036
+ address: token,
2037
+ selector: 'function transfer(address,uint256)',
2038
+ recipients: ['0x1111111111111111111111111111111111111111'],
2039
+ },
2040
+ ],
2041
+ })
2042
+
2043
+ const serialized = KeyAuthorization.serialize(authorization)
2044
+ const restored = KeyAuthorization.deserialize(serialized)
2045
+ expect(restored.scopes?.[0]?.selector).toBe('0xa9059cbb')
2046
+ expect(restored.scopes?.[0]?.recipients).toEqual([
2047
+ '0x1111111111111111111111111111111111111111',
2048
+ ])
2049
+ })
2050
+
2051
+ test('call scopes: selector from bare signature (no function prefix)', () => {
2052
+ const authorization = KeyAuthorization.from({
2053
+ address,
2054
+ chainId: 1n,
2055
+ type: 'secp256k1',
2056
+ scopes: [
2057
+ {
2058
+ address: '0x1234567890123456789012345678901234567890',
2059
+ selector: 'transfer(address,uint256)',
2060
+ },
2061
+ {
2062
+ address: '0x1234567890123456789012345678901234567890',
2063
+ selector: 'approve(address,uint256)',
2064
+ },
2065
+ ],
2066
+ })
2067
+
2068
+ const serialized = KeyAuthorization.serialize(authorization)
2069
+ const restored = KeyAuthorization.deserialize(serialized)
2070
+ expect(restored.scopes).toHaveLength(2)
2071
+ expect(restored.scopes?.[0]?.selector).toBe('0xa9059cbb')
2072
+ expect(restored.scopes?.[1]?.selector).toBe('0x095ea7b3')
2073
+ })
2074
+
2075
+ test('call scopes: mixed hex and signature selectors', () => {
2076
+ const authorization = KeyAuthorization.from({
2077
+ address,
2078
+ chainId: 1n,
2079
+ type: 'secp256k1',
2080
+ scopes: [
2081
+ {
2082
+ address: '0x1234567890123456789012345678901234567890',
2083
+ selector: '0xa9059cbb',
2084
+ },
2085
+ {
2086
+ address: '0x1234567890123456789012345678901234567890',
2087
+ selector: 'function approve(address,uint256)',
2088
+ },
2089
+ ],
2090
+ })
2091
+
2092
+ const serialized = KeyAuthorization.serialize(authorization)
2093
+ const restored = KeyAuthorization.deserialize(serialized)
2094
+ expect(restored.scopes?.[0]?.selector).toBe('0xa9059cbb')
2095
+ expect(restored.scopes?.[1]?.selector).toBe('0x095ea7b3')
2096
+ })
2097
+
2003
2098
  test('toRpc/fromRpc roundtrip with period and scopes', () => {
2004
2099
  const authorization = KeyAuthorization.from(
2005
2100
  {
@@ -2016,7 +2111,7 @@ describe('toTuple', () => {
2016
2111
  ],
2017
2112
  scopes: [
2018
2113
  {
2019
- contractAddress: token,
2114
+ address: token,
2020
2115
  selector: '0xa9059cbb',
2021
2116
  recipients: ['0x1111111111111111111111111111111111111111'],
2022
2117
  },
@@ -2031,7 +2126,7 @@ describe('toTuple', () => {
2031
2126
  const restored = KeyAuthorization.fromRpc(rpc)
2032
2127
 
2033
2128
  expect(restored.limits?.[0]?.period).toBe(2592000)
2034
- expect(restored.scopes?.[0]?.contractAddress).toBe(token)
2129
+ expect(restored.scopes?.[0]?.address).toBe(token)
2035
2130
  expect(restored.scopes?.[0]?.selector).toBe('0xa9059cbb')
2036
2131
  expect(restored.scopes?.[0]?.recipients).toEqual([
2037
2132
  '0x1111111111111111111111111111111111111111',
@@ -1,3 +1,4 @@
1
+ import * as AbiItem from '../core/AbiItem.js'
1
2
  import type * as Address from '../core/Address.js'
2
3
  import type * as Errors from '../core/Errors.js'
3
4
  import * as Hash from '../core/Hash.js'
@@ -153,21 +154,25 @@ export type Tuple<signed extends boolean = boolean> = signed extends true
153
154
  /**
154
155
  * Call scope entry restricting which contract, selector, and recipients an access key can use.
155
156
  *
156
- * Multiple entries with the same `contractAddress` are grouped by target on the wire.
157
+ * Multiple entries with the same `address` are grouped by target on the wire.
157
158
  *
158
- * - `{ contractAddress }` = any selector on this contract
159
- * - `{ contractAddress, selector }` = specific selector
160
- * - `{ contractAddress, selector, recipients }` = selector + recipient constraint
159
+ * - `{ address }` = any selector on this contract
160
+ * - `{ address, selector }` = specific selector
161
+ * - `{ address, selector, recipients }` = selector + recipient constraint
161
162
  *
162
163
  * [TIP-1011 Specification](https://docs.tempo.xyz/protocol/transactions/tip-1011)
163
164
  */
164
165
  export type Scope<addressType = Address.Address> = {
165
166
  /** Target contract address. */
166
- contractAddress: addressType
167
+ address: addressType
167
168
  /**
168
- * 4-byte function selector. Omit to allow any selector on this contract.
169
+ * 4-byte function selector, or a human-readable ABI signature
170
+ * (e.g. `'transfer(address,uint256)'` or `'function transfer(address,uint256)'`).
171
+ *
172
+ * Signatures are encoded into a 4-byte selector automatically.
173
+ * Omit to allow any selector on this contract.
169
174
  */
170
- selector?: Hex.Hex | undefined
175
+ selector?: Hex.Hex | string | undefined
171
176
  /**
172
177
  * Recipient allowlist for this selector (first ABI `address` argument).
173
178
  *
@@ -352,8 +357,8 @@ export function from<
352
357
  const auth = authorization as KeyAuthorization & {
353
358
  limits?: readonly { token: TempoAddress.Address; limit: bigint }[]
354
359
  scopes?: readonly {
355
- contractAddress: TempoAddress.Address
356
- selector?: Hex.Hex
360
+ address: TempoAddress.Address
361
+ selector?: Hex.Hex | string
357
362
  recipients?: readonly TempoAddress.Address[]
358
363
  }[]
359
364
  }
@@ -372,7 +377,8 @@ export function from<
372
377
  ? {
373
378
  scopes: auth.scopes.map((scope) => ({
374
379
  ...scope,
375
- contractAddress: TempoAddress.resolve(scope.contractAddress),
380
+ address: TempoAddress.resolve(scope.address),
381
+ selector: resolveSelector(scope.selector),
376
382
  ...(scope.recipients
377
383
  ? {
378
384
  recipients: scope.recipients.map((r) =>
@@ -455,10 +461,10 @@ export function fromRpc(authorization: Rpc): Signed {
455
461
  const scopes = allowedCalls
456
462
  ? allowedCalls.flatMap((callScope) => {
457
463
  if (!callScope.selectorRules || callScope.selectorRules.length === 0)
458
- return [{ contractAddress: callScope.target }] as Scope[]
464
+ return [{ address: callScope.target }] as Scope[]
459
465
  return callScope.selectorRules.map(
460
466
  (rule): Scope => ({
461
- contractAddress: callScope.target,
467
+ address: callScope.target,
462
468
  selector: normalizeSelector(rule.selector),
463
469
  ...(rule.recipients && rule.recipients.length > 0
464
470
  ? { recipients: rule.recipients }
@@ -576,15 +582,15 @@ export function fromTuple<const tuple extends Tuple>(
576
582
  ...(typeof scopes !== 'undefined' && Array.isArray(scopes)
577
583
  ? {
578
584
  scopes: scopes.flatMap((scopeTuple: any) => {
579
- const [contractAddress, selectorRules] = scopeTuple
585
+ const [address, selectorRules] = scopeTuple
580
586
  // If no selector rules, this is an address-only scope
581
587
  if (!Array.isArray(selectorRules) || selectorRules.length === 0)
582
- return [{ contractAddress }]
588
+ return [{ address }]
583
589
  // Flatten each selector rule into a separate scope entry
584
590
  return selectorRules.map((ruleTuple: any) => {
585
591
  const [selector, recipients] = ruleTuple
586
592
  return {
587
- contractAddress,
593
+ address,
588
594
  selector,
589
595
  ...(Array.isArray(recipients) && recipients.length > 0
590
596
  ? { recipients }
@@ -800,16 +806,16 @@ export function toRpc(authorization: Signed): Rpc {
800
806
  const { address, scopes, chainId, expiry, limits, type, signature } =
801
807
  authorization
802
808
 
803
- // Group flat scopes by contractAddress into nested allowedCalls wire format
809
+ // Group flat scopes by address into nested allowedCalls wire format
804
810
  const allowedCalls = (() => {
805
811
  if (!scopes) return undefined
806
812
  const grouped = new Map<string, RpcSelectorRule[]>()
807
813
  for (const scope of scopes) {
808
- const key = scope.contractAddress as string
814
+ const key = scope.address as string
809
815
  if (!grouped.has(key)) grouped.set(key, [])
810
816
  if (scope.selector) {
811
817
  grouped.get(key)!.push({
812
- selector: scope.selector,
818
+ selector: resolveSelector(scope.selector)!,
813
819
  ...(scope.recipients && scope.recipients.length > 0
814
820
  ? { recipients: scope.recipients }
815
821
  : {}),
@@ -899,7 +905,7 @@ export function toTuple<const authorization extends KeyAuthorization>(
899
905
  if (limit.period && limit.period > 0) tuple.push(numberToHex(limit.period))
900
906
  return tuple
901
907
  })
902
- // Group flat scopes by contractAddress for wire format
908
+ // Group flat scopes by address for wire format
903
909
  const callsValue = (() => {
904
910
  if (!scopes) return undefined
905
911
  const grouped = new Map<
@@ -907,20 +913,20 @@ export function toTuple<const authorization extends KeyAuthorization>(
907
913
  [Hex.Hex, (readonly Address.Address[])[]][]
908
914
  >()
909
915
  for (const scope of scopes) {
910
- const key = scope.contractAddress as string
916
+ const key = scope.address as string
911
917
  if (!grouped.has(key)) grouped.set(key, [])
912
918
  if (scope.selector) {
913
919
  grouped
914
920
  .get(key)!
915
921
  .push([
916
- scope.selector,
922
+ resolveSelector(scope.selector)!,
917
923
  (scope.recipients ??
918
924
  []) as unknown as (readonly Address.Address[])[],
919
925
  ])
920
926
  }
921
927
  }
922
- return [...grouped.entries()].map(([contractAddress, selectorRules]) => [
923
- contractAddress,
928
+ return [...grouped.entries()].map(([address, selectorRules]) => [
929
+ address,
924
930
  selectorRules.map(([selector, recipients]) => [selector, recipients]),
925
931
  ])
926
932
  })()
@@ -971,3 +977,11 @@ function normalizeSelector(selector: Hex.Hex | number[]): Hex.Hex {
971
977
  return Hex.fromBytes(new Uint8Array(selector)) as Hex.Hex
972
978
  return selector
973
979
  }
980
+
981
+ function resolveSelector(
982
+ selector: Hex.Hex | string | undefined,
983
+ ): Hex.Hex | undefined {
984
+ if (!selector) return undefined
985
+ if (selector.startsWith('0x')) return selector as Hex.Hex
986
+ return AbiItem.getSelector(selector)
987
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "module",
3
+ "types": "../../_types/tempo/RpcSchema.d.ts",
4
+ "main": "../../_cjs/tempo/RpcSchema.js",
5
+ "module": "../../_esm/tempo/RpcSchema.js"
6
+ }
@@ -0,0 +1,74 @@
1
+ import type * as Block from '../core/Block.js'
2
+ import type * as BlockOverrides from '../core/BlockOverrides.js'
3
+ import type * as Hex from '../core/Hex.js'
4
+ import type * as Log from '../core/Log.js'
5
+ import type * as RpcSchema from '../core/RpcSchema.js'
6
+ import type * as StateOverrides from '../core/StateOverrides.js'
7
+ import type * as TransactionRequest from './TransactionRequest.js'
8
+
9
+ /**
10
+ * Union of all JSON-RPC Methods for the `tempo_` namespace.
11
+ *
12
+ * @example
13
+ * ```ts twoslash
14
+ * import { RpcSchema } from 'ox/tempo'
15
+ *
16
+ * type Schema = RpcSchema.Tempo
17
+ * // ^?
18
+ *
19
+ *
20
+ *
21
+ *
22
+ *
23
+ *
24
+ *
25
+ *
26
+ *
27
+ *
28
+ *
29
+ * ```
30
+ */
31
+ export type Tempo = RpcSchema.From<{
32
+ Request: {
33
+ method: 'tempo_simulateV1'
34
+ params: [
35
+ {
36
+ blockStateCalls: readonly {
37
+ blockOverrides?: BlockOverrides.Rpc | undefined
38
+ calls?: readonly TransactionRequest.Rpc[] | undefined
39
+ stateOverrides?: StateOverrides.Rpc | undefined
40
+ }[]
41
+ returnFullTransactions?: boolean | undefined
42
+ traceTransfers?: boolean | undefined
43
+ validation?: boolean | undefined
44
+ },
45
+ block: Block.Number<Hex.Hex> | Block.Tag | Block.Hash | Block.Identifier,
46
+ ]
47
+ }
48
+ ReturnType: {
49
+ blocks: readonly (Block.Rpc & {
50
+ calls?:
51
+ | readonly {
52
+ error?:
53
+ | {
54
+ data?: Hex.Hex | undefined
55
+ code: number
56
+ message: string
57
+ }
58
+ | undefined
59
+ logs?: readonly Log.Rpc[] | undefined
60
+ gasUsed: Hex.Hex
61
+ returnData: Hex.Hex
62
+ status: Hex.Hex
63
+ }[]
64
+ | undefined
65
+ })[]
66
+ tokenMetadata: {
67
+ [address: Hex.Hex]: {
68
+ name: string
69
+ symbol: string
70
+ currency: string
71
+ }
72
+ }
73
+ }
74
+ }>