@apibara/evm 2.1.0-beta.23 → 2.1.0-beta.24

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/src/common.ts CHANGED
@@ -1,123 +1,86 @@
1
- import { Schema } from "@effect/schema";
2
- import { hexToBytes, pad } from "viem";
1
+ import type { Codec, CodecType } from "@apibara/protocol/codec";
2
+ import type * as proto from "./proto";
3
3
 
4
4
  const MAX_U64 = 0xffffffffffffffffn;
5
-
6
- const _Address = Schema.TemplateLiteral(Schema.Literal("0x"), Schema.String);
7
-
8
- /** Wire representation of `Address`. */
9
- const AddressProto = Schema.Struct({
10
- x0: Schema.BigIntFromSelf,
11
- x1: Schema.BigIntFromSelf,
12
- x2: Schema.Number,
13
- });
5
+ const MAX_U32 = 0xffffffffn;
14
6
 
15
7
  /** An Ethereum address. */
16
- export const Address = Schema.transform(AddressProto, _Address, {
17
- decode(value) {
18
- const x0 = value.x0.toString(16).padStart(16, "0");
19
- const x1 = value.x1.toString(16).padStart(16, "0");
20
- const x2 = value.x2.toString(16).padStart(8, "0");
21
- return `0x${x0}${x1}${x2}` as `0x${string}`;
8
+ export const Address: Codec<`0x${string}`, proto.common.Address> = {
9
+ encode(x) {
10
+ const bn = BigInt(x);
11
+ // Ethereum address is 20 bytes (160 bits)
12
+ // Splitting into two 64-bit chunks and one 32-bit chunk
13
+ const x2 = bn & MAX_U32;
14
+ const x1 = (bn >> 32n) & MAX_U64;
15
+ const x0 = (bn >> 96n) & MAX_U64;
16
+ return { x0, x1, x2: Number(x2) };
22
17
  },
23
- encode(value) {
24
- const bytes = hexToBytes(pad(value, { size: 20, dir: "left" }));
25
- const dv = new DataView(bytes.buffer);
26
- const x0 = dv.getBigUint64(0);
27
- const x1 = dv.getBigUint64(8);
28
- const x2 = dv.getUint32(16);
29
- return { x0, x1, x2 };
18
+ decode(p) {
19
+ const x0 = p.x0 ?? 0n;
20
+ const x1 = p.x1 ?? 0n;
21
+ const x2 = BigInt(p.x2 ?? 0);
22
+ const bn = x2 + (x1 << 32n) + (x0 << 96n);
23
+ return `0x${bn.toString(16).padStart(40, "0")}` as `0x${string}`;
30
24
  },
31
- });
32
-
33
- export type Address = typeof Address.Type;
34
-
35
- const _B256 = Schema.TemplateLiteral(Schema.Literal("0x"), Schema.String);
25
+ };
36
26
 
37
- /** Wire representation of `B256`. */
38
- export const B256Proto = Schema.Struct({
39
- x0: Schema.BigIntFromSelf,
40
- x1: Schema.BigIntFromSelf,
41
- x2: Schema.BigIntFromSelf,
42
- x3: Schema.BigIntFromSelf,
43
- });
27
+ export type Address = CodecType<typeof Address>;
44
28
 
45
29
  /** Data with length 256 bits. */
46
- export const B256 = Schema.transform(B256Proto, _B256, {
47
- decode(value) {
48
- const x0 = value.x0.toString(16).padStart(16, "0");
49
- const x1 = value.x1.toString(16).padStart(16, "0");
50
- const x2 = value.x2.toString(16).padStart(16, "0");
51
- const x3 = value.x3.toString(16).padStart(16, "0");
52
- return `0x${x0}${x1}${x2}${x3}` as `0x${string}`;
53
- },
54
- encode(value) {
55
- const bytes = hexToBytes(pad(value, { size: 32, dir: "left" }));
56
- const dv = new DataView(bytes.buffer);
57
- const x0 = dv.getBigUint64(0);
58
- const x1 = dv.getBigUint64(8);
59
- const x2 = dv.getBigUint64(16);
60
- const x3 = dv.getBigUint64(24);
30
+ export const B256: Codec<`0x${string}`, proto.common.B256> = {
31
+ encode(x) {
32
+ const bn = BigInt(x);
33
+ const x3 = bn & MAX_U64;
34
+ const x2 = (bn >> 64n) & MAX_U64;
35
+ const x1 = (bn >> 128n) & MAX_U64;
36
+ const x0 = (bn >> 192n) & MAX_U64;
61
37
  return { x0, x1, x2, x3 };
62
38
  },
63
- });
64
-
65
- export type B256 = typeof B256.Type;
66
-
67
- export const b256ToProto = Schema.encodeSync(B256);
68
- export const b256FromProto = Schema.decodeSync(B256);
39
+ decode(p) {
40
+ const x0 = p.x0 ?? 0n;
41
+ const x1 = p.x1 ?? 0n;
42
+ const x2 = p.x2 ?? 0n;
43
+ const x3 = p.x3 ?? 0n;
44
+ const bn = x3 + (x2 << 64n) + (x1 << 128n) + (x0 << 192n);
45
+ return `0x${bn.toString(16).padStart(64, "0")}` as `0x${string}`;
46
+ },
47
+ };
69
48
 
70
- /** Wire representation of `U256`. */
71
- const U256Proto = Schema.Struct({
72
- x0: Schema.BigIntFromSelf,
73
- x1: Schema.BigIntFromSelf,
74
- x2: Schema.BigIntFromSelf,
75
- x3: Schema.BigIntFromSelf,
76
- });
49
+ export type B256 = CodecType<typeof B256>;
77
50
 
78
51
  /** Data with length 256 bits. */
79
- export const U256 = Schema.transform(U256Proto, Schema.BigIntFromSelf, {
80
- decode(value) {
81
- return (
82
- (value.x0 << (8n * 24n)) +
83
- (value.x1 << (8n * 16n)) +
84
- (value.x2 << (8n * 8n)) +
85
- value.x3
86
- );
87
- },
88
- encode(value) {
89
- const x0 = (value >> (8n * 24n)) & MAX_U64;
90
- const x1 = (value >> (8n * 16n)) & MAX_U64;
91
- const x2 = (value >> (8n * 8n)) & MAX_U64;
92
- const x3 = value & MAX_U64;
52
+ export const U256: Codec<bigint, proto.common.U256> = {
53
+ encode(x) {
54
+ const bn = BigInt(x);
55
+ const x3 = bn & MAX_U64;
56
+ const x2 = (bn >> 64n) & MAX_U64;
57
+ const x1 = (bn >> 128n) & MAX_U64;
58
+ const x0 = (bn >> 192n) & MAX_U64;
93
59
  return { x0, x1, x2, x3 };
94
60
  },
95
- });
96
-
97
- export type U256 = typeof U256.Type;
98
-
99
- export const u256ToProto = Schema.encodeSync(U256);
100
- export const u256FromProto = Schema.decodeSync(U256);
61
+ decode(p) {
62
+ const x0 = p.x0 ?? 0n;
63
+ const x1 = p.x1 ?? 0n;
64
+ const x2 = p.x2 ?? 0n;
65
+ const x3 = p.x3 ?? 0n;
66
+ return x3 + (x2 << 64n) + (x1 << 128n) + (x0 << 192n);
67
+ },
68
+ };
101
69
 
102
- /** Wire representation of `U128`. */
103
- const U128Proto = Schema.Struct({
104
- x0: Schema.BigIntFromSelf,
105
- x1: Schema.BigIntFromSelf,
106
- });
70
+ export type U256 = CodecType<typeof U256>;
107
71
 
108
72
  /** Data with length 128 bits. */
109
- export const U128 = Schema.transform(U128Proto, Schema.BigIntFromSelf, {
110
- decode(value) {
111
- return (value.x0 << (8n * 8n)) + value.x1;
112
- },
113
- encode(value) {
114
- const x0 = (value >> (8n * 8n)) & MAX_U64;
115
- const x1 = value & MAX_U64;
73
+ export const U128: Codec<bigint, proto.common.U128> = {
74
+ encode(x) {
75
+ const x1 = x & MAX_U64;
76
+ const x0 = (x >> 64n) & MAX_U64;
116
77
  return { x0, x1 };
117
78
  },
118
- });
119
-
120
- export type U128 = typeof U128.Type;
79
+ decode(p) {
80
+ const x0 = p.x0 ?? 0n;
81
+ const x1 = p.x1 ?? 0n;
82
+ return x1 + (x0 << 64n);
83
+ },
84
+ };
121
85
 
122
- export const u128ToProto = Schema.encodeSync(U128);
123
- export const u128FromProto = Schema.decodeSync(U128);
86
+ export type U128 = CodecType<typeof U128>;
package/src/filter.ts CHANGED
@@ -1,164 +1,154 @@
1
- import { Schema } from "@effect/schema";
2
-
3
- import { Address, B256, B256Proto } from "./common";
4
-
1
+ import { Address, B256 } from "./common";
2
+
3
+ import {
4
+ ArrayCodec,
5
+ BooleanCodec,
6
+ type Codec,
7
+ type CodecType,
8
+ MessageCodec,
9
+ NumberCodec,
10
+ OptionalCodec,
11
+ } from "@apibara/protocol/codec";
5
12
  import * as proto from "./proto";
6
13
 
7
- const OptionalArray = <TSchema extends Schema.Schema.Any>(schema: TSchema) =>
8
- Schema.optional(Schema.Array(schema));
9
-
10
14
  /** Header options.
11
15
  *
12
16
  * - `always`: receive all block headers.
13
17
  * - `on_data`: receive headers only if any other filter matches.
14
18
  * - `on_data_or_on_new_block`: receive headers only if any other filter matches and for "live" blocks.
15
19
  */
16
- export const HeaderFilter = Schema.transform(
17
- Schema.Enums(proto.filter.HeaderFilter),
18
- Schema.Literal("always", "on_data", "on_data_or_on_new_block", "unknown"),
19
- {
20
- decode(value) {
21
- const enumMap = {
22
- [proto.filter.HeaderFilter.ALWAYS]: "always",
23
- [proto.filter.HeaderFilter.ON_DATA]: "on_data",
24
- [proto.filter.HeaderFilter.ON_DATA_OR_ON_NEW_BLOCK]:
25
- "on_data_or_on_new_block",
26
- [proto.filter.HeaderFilter.UNSPECIFIED]: "unknown",
27
- [proto.filter.HeaderFilter.UNRECOGNIZED]: "unknown",
28
- } as const;
29
- return enumMap[value] ?? "unknown";
30
- },
31
- encode(value) {
32
- switch (value) {
33
- case "always":
34
- return proto.filter.HeaderFilter.ALWAYS;
35
- case "on_data":
36
- return proto.filter.HeaderFilter.ON_DATA;
37
- case "on_data_or_on_new_block":
38
- return proto.filter.HeaderFilter.ON_DATA_OR_ON_NEW_BLOCK;
39
- default:
40
- return proto.filter.HeaderFilter.UNSPECIFIED;
41
- }
42
- },
20
+ export const HeaderFilter: Codec<
21
+ "always" | "on_data" | "on_data_or_on_new_block" | "unknown",
22
+ proto.filter.HeaderFilter
23
+ > = {
24
+ encode(x) {
25
+ switch (x) {
26
+ case "always":
27
+ return proto.filter.HeaderFilter.ALWAYS;
28
+ case "on_data":
29
+ return proto.filter.HeaderFilter.ON_DATA;
30
+ case "on_data_or_on_new_block":
31
+ return proto.filter.HeaderFilter.ON_DATA_OR_ON_NEW_BLOCK;
32
+ default:
33
+ return proto.filter.HeaderFilter.UNSPECIFIED;
34
+ }
43
35
  },
44
- );
36
+ decode(p) {
37
+ const enumMap = {
38
+ [proto.filter.HeaderFilter.ALWAYS]: "always",
39
+ [proto.filter.HeaderFilter.ON_DATA]: "on_data",
40
+ [proto.filter.HeaderFilter.ON_DATA_OR_ON_NEW_BLOCK]:
41
+ "on_data_or_on_new_block",
42
+ [proto.filter.HeaderFilter.UNSPECIFIED]: "unknown",
43
+ [proto.filter.HeaderFilter.UNRECOGNIZED]: "unknown",
44
+ } as const;
45
+ return enumMap[p] ?? "unknown";
46
+ },
47
+ };
45
48
 
46
- export type HeaderFilter = typeof HeaderFilter.Type;
49
+ export type HeaderFilter = CodecType<typeof HeaderFilter>;
47
50
 
48
- export const WithdrawalFilter = Schema.Struct({
49
- id: Schema.optional(Schema.Number),
50
- validatorIndex: Schema.optional(Schema.Number),
51
- address: Schema.optional(Address),
51
+ export const WithdrawalFilter = MessageCodec({
52
+ id: OptionalCodec(NumberCodec),
53
+ validatorIndex: OptionalCodec(NumberCodec),
54
+ address: OptionalCodec(Address),
52
55
  });
53
56
 
54
- export type WithdrawalFilter = typeof WithdrawalFilter.Type;
55
-
56
- export const TransactionStatusFilter = Schema.transform(
57
- Schema.Enums(proto.filter.TransactionStatusFilter),
58
- Schema.Literal("succeeded", "reverted", "all", "unknown"),
59
- {
60
- decode(value) {
61
- const enumMap = {
62
- [proto.filter.TransactionStatusFilter.SUCCEEDED]: "succeeded",
63
- [proto.filter.TransactionStatusFilter.REVERTED]: "reverted",
64
- [proto.filter.TransactionStatusFilter.ALL]: "all",
65
- [proto.filter.TransactionStatusFilter.UNSPECIFIED]: "unknown",
66
- [proto.filter.TransactionStatusFilter.UNRECOGNIZED]: "unknown",
67
- } as const;
68
- return enumMap[value] ?? "unknown";
69
- },
70
- encode(value) {
71
- switch (value) {
72
- case "succeeded":
73
- return proto.filter.TransactionStatusFilter.SUCCEEDED;
74
- case "reverted":
75
- return proto.filter.TransactionStatusFilter.REVERTED;
76
- case "all":
77
- return proto.filter.TransactionStatusFilter.ALL;
78
- default:
79
- return proto.filter.TransactionStatusFilter.UNSPECIFIED;
80
- }
81
- },
57
+ export type WithdrawalFilter = CodecType<typeof WithdrawalFilter>;
58
+
59
+ export const TransactionStatusFilter: Codec<
60
+ "succeeded" | "reverted" | "all" | "unknown",
61
+ proto.filter.TransactionStatusFilter
62
+ > = {
63
+ decode(value) {
64
+ const enumMap = {
65
+ [proto.filter.TransactionStatusFilter.SUCCEEDED]: "succeeded",
66
+ [proto.filter.TransactionStatusFilter.REVERTED]: "reverted",
67
+ [proto.filter.TransactionStatusFilter.ALL]: "all",
68
+ [proto.filter.TransactionStatusFilter.UNSPECIFIED]: "unknown",
69
+ [proto.filter.TransactionStatusFilter.UNRECOGNIZED]: "unknown",
70
+ } as const;
71
+ return enumMap[value] ?? "unknown";
72
+ },
73
+ encode(value) {
74
+ switch (value) {
75
+ case "succeeded":
76
+ return proto.filter.TransactionStatusFilter.SUCCEEDED;
77
+ case "reverted":
78
+ return proto.filter.TransactionStatusFilter.REVERTED;
79
+ case "all":
80
+ return proto.filter.TransactionStatusFilter.ALL;
81
+ default:
82
+ return proto.filter.TransactionStatusFilter.UNSPECIFIED;
83
+ }
82
84
  },
83
- );
84
-
85
- export type TransactionStatusFilter = typeof TransactionStatusFilter.Type;
86
-
87
- export const Topic = Schema.transform(
88
- Schema.Struct({ value: Schema.UndefinedOr(B256Proto) }),
89
- Schema.NullOr(B256),
90
- {
91
- decode({ value }) {
92
- if (value === undefined) {
93
- return null;
94
- }
95
- return value;
96
- },
97
- encode(value) {
98
- if (value === null) {
99
- return { value: undefined };
100
- }
101
- return { value };
102
- },
85
+ };
86
+
87
+ export type TransactionStatusFilter = CodecType<typeof TransactionStatusFilter>;
88
+
89
+ export const Topic: Codec<
90
+ B256 | null,
91
+ { value?: proto.common.B256 | undefined }
92
+ > = {
93
+ encode(x) {
94
+ if (x === null) {
95
+ return { value: undefined };
96
+ }
97
+ return { value: B256.encode(x) };
103
98
  },
104
- );
105
-
106
- export type Topic = typeof Topic.Type;
107
-
108
- export const LogFilter = Schema.Struct({
109
- id: Schema.optional(Schema.Number),
110
- address: Schema.optional(Address),
111
- topics: OptionalArray(Topic),
112
- strict: Schema.optional(Schema.Boolean),
113
- transactionStatus: Schema.optional(TransactionStatusFilter),
114
- includeTransaction: Schema.optional(Schema.Boolean),
115
- includeReceipt: Schema.optional(Schema.Boolean),
116
- includeTransactionTrace: Schema.optional(Schema.Boolean),
99
+ decode({ value }) {
100
+ if (value === undefined) {
101
+ return null;
102
+ }
103
+ return B256.decode(value);
104
+ },
105
+ };
106
+
107
+ export type Topic = CodecType<typeof Topic>;
108
+
109
+ export const LogFilter = MessageCodec({
110
+ id: OptionalCodec(NumberCodec),
111
+ address: OptionalCodec(Address),
112
+ topics: OptionalCodec(ArrayCodec(Topic)),
113
+ strict: OptionalCodec(BooleanCodec),
114
+ transactionStatus: OptionalCodec(TransactionStatusFilter),
115
+ includeTransaction: OptionalCodec(BooleanCodec),
116
+ includeReceipt: OptionalCodec(BooleanCodec),
117
+ includeTransactionTrace: OptionalCodec(BooleanCodec),
117
118
  });
118
119
 
119
- export type LogFilter = typeof LogFilter.Type;
120
-
121
- export const TransactionFilter = Schema.Struct({
122
- id: Schema.optional(Schema.Number),
123
- from: Schema.optional(Address),
124
- to: Schema.optional(Address),
125
- create: Schema.optional(Schema.Boolean),
126
- transactionStatus: Schema.optional(TransactionStatusFilter),
127
- includeReceipt: Schema.optional(Schema.Boolean),
128
- includeLogs: Schema.optional(Schema.Boolean),
129
- includeTransactionTrace: Schema.optional(Schema.Boolean),
120
+ export type LogFilter = Readonly<CodecType<typeof LogFilter>>;
121
+
122
+ export const TransactionFilter = MessageCodec({
123
+ id: OptionalCodec(NumberCodec),
124
+ from: OptionalCodec(Address),
125
+ to: OptionalCodec(Address),
126
+ create: OptionalCodec(BooleanCodec),
127
+ transactionStatus: OptionalCodec(TransactionStatusFilter),
128
+ includeReceipt: OptionalCodec(BooleanCodec),
129
+ includeLogs: OptionalCodec(BooleanCodec),
130
+ includeTransactionTrace: OptionalCodec(BooleanCodec),
130
131
  });
131
132
 
132
- export type TransactionFilter = typeof TransactionFilter.Type;
133
+ export type TransactionFilter = Readonly<CodecType<typeof TransactionFilter>>;
133
134
 
134
- export const Filter = Schema.Struct({
135
- header: Schema.optional(HeaderFilter),
136
- withdrawals: OptionalArray(WithdrawalFilter),
137
- transactions: OptionalArray(TransactionFilter),
138
- logs: OptionalArray(LogFilter),
135
+ export const Filter = MessageCodec({
136
+ header: OptionalCodec(HeaderFilter),
137
+ withdrawals: OptionalCodec(ArrayCodec(WithdrawalFilter)),
138
+ transactions: OptionalCodec(ArrayCodec(TransactionFilter)),
139
+ logs: OptionalCodec(ArrayCodec(LogFilter)),
139
140
  });
140
141
 
141
- export type Filter = typeof Filter.Type;
142
-
143
- export const filterToProto = Schema.encodeSync(Filter);
144
- export const filterFromProto = Schema.decodeSync(Filter);
145
-
146
- export const FilterFromBytes = Schema.transform(
147
- Schema.Uint8ArrayFromSelf,
148
- Filter,
149
- {
150
- strict: false,
151
- decode(value) {
152
- return proto.filter.Filter.decode(value);
153
- },
154
- encode(value) {
155
- return proto.filter.Filter.encode(value).finish();
156
- },
157
- },
158
- );
142
+ export type Filter = Readonly<CodecType<typeof Filter>>;
159
143
 
160
- export const filterToBytes = Schema.encodeSync(FilterFromBytes);
161
- export const filterFromBytes = Schema.decodeSync(FilterFromBytes);
144
+ export const FilterFromBytes: Codec<Filter, Uint8Array> = {
145
+ encode(x) {
146
+ return proto.filter.Filter.encode(Filter.encode(x)).finish();
147
+ },
148
+ decode(p) {
149
+ return Filter.decode(proto.filter.Filter.decode(p));
150
+ },
151
+ };
162
152
 
163
153
  export function mergeFilter(a: Filter, b: Filter): Filter {
164
154
  const header = mergeHeaderFilter(a.header, b.header);
@@ -1,79 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
-
3
- import { Schema } from "@effect/schema";
4
- import { pad } from "viem";
5
-
6
- import { Address, B256, U128, U256 } from "./common";
7
-
8
- describe("Address", () => {
9
- const encode = Schema.encodeSync(Address);
10
- const decode = Schema.decodeSync(Address);
11
-
12
- it("should convert to and from proto", () => {
13
- const address = "0x27504265a9bc4330e3fe82061a60cd8b6369b4dc";
14
-
15
- const message = encode(address);
16
-
17
- expect(message.x0).toBeDefined();
18
- expect(message.x1).toBeDefined();
19
- expect(message.x2).toBeDefined();
20
-
21
- const back = decode(message);
22
- expect(back).toEqual(pad(address, { size: 20 }));
23
- });
24
- });
25
-
26
- describe("B256", () => {
27
- const encode = Schema.encodeSync(B256);
28
- const decode = Schema.decodeSync(B256);
29
-
30
- it("should convert to and from proto", () => {
31
- const value =
32
- "0x9df92d765b5aa041fd4bbe8d5878eb89290efa78e444c1a603eecfae2ea05fa4";
33
- const message = encode(value);
34
-
35
- expect(message.x0).toBeDefined();
36
- expect(message.x1).toBeDefined();
37
- expect(message.x2).toBeDefined();
38
- expect(message.x3).toBeDefined();
39
-
40
- const back = decode(message);
41
- expect(back).toEqual(pad(value, { size: 32 }));
42
- });
43
- });
44
-
45
- describe("U256", () => {
46
- const encode = Schema.encodeSync(U256);
47
- const decode = Schema.decodeSync(U256);
48
-
49
- it("should convert to and from proto", () => {
50
- const value = BigInt(
51
- "0x9df92d765b5aa041fd4bbe8d5878eb89290efa78e444c1a603eecfae2ea05fa4",
52
- );
53
- const message = encode(value);
54
-
55
- expect(message.x0).toBeDefined();
56
- expect(message.x1).toBeDefined();
57
- expect(message.x2).toBeDefined();
58
- expect(message.x3).toBeDefined();
59
-
60
- const back = decode(message);
61
- expect(back).toEqual(value);
62
- });
63
- });
64
-
65
- describe("U128", () => {
66
- const encode = Schema.encodeSync(U128);
67
- const decode = Schema.decodeSync(U128);
68
-
69
- it("should convert to and from proto", () => {
70
- const value = BigInt("0x090efa78e444c1a603eecfae2ea05fa4");
71
- const message = encode(value);
72
-
73
- expect(message.x0).toBeDefined();
74
- expect(message.x1).toBeDefined();
75
-
76
- const back = decode(message);
77
- expect(back).toEqual(value);
78
- });
79
- });