@apibara/starknet 2.1.0-beta.5 → 2.1.0-beta.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1666 -691
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5193 -4382
- package/dist/index.d.mts +5193 -4382
- package/dist/index.d.ts +5193 -4382
- package/dist/index.mjs +1660 -686
- package/dist/index.mjs.map +1 -0
- package/dist/parser.cjs +59 -5
- package/dist/parser.cjs.map +1 -0
- package/dist/parser.d.cts +20 -13
- package/dist/parser.d.mts +20 -13
- package/dist/parser.d.ts +20 -13
- package/dist/parser.mjs +58 -6
- package/dist/parser.mjs.map +1 -0
- package/dist/shared/starknet.e649ecb1.d.cts +40 -0
- package/dist/shared/starknet.e649ecb1.d.mts +40 -0
- package/dist/shared/starknet.e649ecb1.d.ts +40 -0
- package/package.json +5 -7
- package/src/abi-wan-helpers.ts +181 -0
- package/src/abi.ts +6 -0
- package/src/block.ts +907 -423
- package/src/common.ts +20 -35
- package/src/event.ts +192 -44
- package/src/filter.ts +240 -239
- package/src/index.ts +3 -0
- package/src/parser.ts +102 -6
- package/src/proto/data.ts +1104 -2
- package/src/proto/filter.ts +76 -2
- package/dist/shared/starknet.2b19268a.d.cts +0 -32
- package/dist/shared/starknet.2b19268a.d.mts +0 -32
- package/dist/shared/starknet.2b19268a.d.ts +0 -32
- package/src/common.test.ts +0 -21
- package/src/filter.test.ts +0 -832
- package/src/helpers.ts +0 -8
- package/src/parser.test.ts +0 -169
package/src/common.ts
CHANGED
|
@@ -1,40 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Codec, CodecType } from "@apibara/protocol/codec";
|
|
2
|
+
import type * as proto from "./proto";
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
Schema.Literal("0x"),
|
|
5
|
-
Schema.String,
|
|
6
|
-
);
|
|
4
|
+
const MAX_U64 = 0xffffffffffffffffn;
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/** Field element. */
|
|
17
|
-
export const FieldElement = Schema.transform(FieldElementProto, _FieldElement, {
|
|
18
|
-
decode(value) {
|
|
19
|
-
const x0 = value.x0.toString(16).padStart(16, "0");
|
|
20
|
-
const x1 = value.x1.toString(16).padStart(16, "0");
|
|
21
|
-
const x2 = value.x2.toString(16).padStart(16, "0");
|
|
22
|
-
const x3 = value.x3.toString(16).padStart(16, "0");
|
|
23
|
-
return `0x${x0}${x1}${x2}${x3}` as `0x${string}`;
|
|
24
|
-
},
|
|
25
|
-
encode(value) {
|
|
26
|
-
const bn = BigInt(value);
|
|
27
|
-
const hex = bn.toString(16).padStart(64, "0");
|
|
28
|
-
const s = hex.length;
|
|
29
|
-
const x3 = BigInt(`0x${hex.slice(s - 16, s)}`);
|
|
30
|
-
const x2 = BigInt(`0x${hex.slice(s - 32, s - 16)}`);
|
|
31
|
-
const x1 = BigInt(`0x${hex.slice(s - 48, s - 32)}`);
|
|
32
|
-
const x0 = BigInt(`0x${hex.slice(s - 64, s - 48)}`);
|
|
6
|
+
export const FieldElement: Codec<`0x${string}`, proto.common.FieldElement> = {
|
|
7
|
+
encode(x) {
|
|
8
|
+
const bn = BigInt(x);
|
|
9
|
+
const x3 = bn & MAX_U64;
|
|
10
|
+
const x2 = (bn >> 64n) & MAX_U64;
|
|
11
|
+
const x1 = (bn >> 128n) & MAX_U64;
|
|
12
|
+
const x0 = (bn >> 192n) & MAX_U64;
|
|
33
13
|
return { x0, x1, x2, x3 };
|
|
34
14
|
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
15
|
+
decode(p) {
|
|
16
|
+
const x0 = p.x0 ?? 0n;
|
|
17
|
+
const x1 = p.x1 ?? 0n;
|
|
18
|
+
const x2 = p.x2 ?? 0n;
|
|
19
|
+
const x3 = p.x3 ?? 0n;
|
|
20
|
+
const bn = x3 + (x2 << 64n) + (x1 << 128n) + (x0 << 192n);
|
|
21
|
+
return `0x${bn.toString(16).padStart(64, "0")}` as `0x${string}`;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
38
24
|
|
|
39
|
-
export
|
|
40
|
-
export const feltFromProto = Schema.decodeSync(FieldElement);
|
|
25
|
+
export type FieldElement = CodecType<typeof FieldElement>;
|
package/src/event.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Abi } from "abi-wan-kanabi";
|
|
2
2
|
import type {
|
|
3
3
|
AbiEventMember,
|
|
4
|
-
EventToPrimitiveType,
|
|
5
4
|
ExtractAbiEventNames,
|
|
6
5
|
} from "abi-wan-kanabi/kanabi";
|
|
7
6
|
import {
|
|
@@ -11,17 +10,31 @@ import {
|
|
|
11
10
|
getOptionType,
|
|
12
11
|
getSpanType,
|
|
13
12
|
isArrayType,
|
|
13
|
+
isByteArray,
|
|
14
14
|
isEmptyType,
|
|
15
15
|
isOptionType,
|
|
16
16
|
isPrimitiveType,
|
|
17
17
|
isSpanType,
|
|
18
18
|
} from "./abi";
|
|
19
|
+
import {
|
|
20
|
+
type AbiEnum,
|
|
21
|
+
type AbiEvent,
|
|
22
|
+
type AbiEventEnum,
|
|
23
|
+
type AbiEventStruct,
|
|
24
|
+
type AbiMember,
|
|
25
|
+
type EventToPrimitiveType,
|
|
26
|
+
isEnumEventAbi,
|
|
27
|
+
isEventAbi,
|
|
28
|
+
isStructEventAbi,
|
|
29
|
+
} from "./abi-wan-helpers";
|
|
19
30
|
import type { Event } from "./block";
|
|
20
31
|
import {
|
|
21
32
|
ParseError,
|
|
22
33
|
type Parser,
|
|
23
34
|
parseArray,
|
|
35
|
+
parseByteArray,
|
|
24
36
|
parseEmpty,
|
|
37
|
+
parseEnum,
|
|
25
38
|
parseOption,
|
|
26
39
|
parseSpan,
|
|
27
40
|
parseStruct,
|
|
@@ -78,61 +91,184 @@ export function decodeEvent<
|
|
|
78
91
|
(item) => item.name === eventName && item.type === "event",
|
|
79
92
|
);
|
|
80
93
|
|
|
81
|
-
if (!eventAbi || eventAbi
|
|
94
|
+
if (!eventAbi || !isEventAbi(eventAbi)) {
|
|
82
95
|
if (strict) {
|
|
83
96
|
throw new DecodeEventError(`Event ${eventName} not found in ABI`);
|
|
84
97
|
}
|
|
85
|
-
|
|
86
98
|
return null as DecodeEventReturn<TAbi, TEventName, TStrict>;
|
|
87
99
|
}
|
|
88
100
|
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
try {
|
|
102
|
+
if (isStructEventAbi(eventAbi)) {
|
|
103
|
+
return decodeStructEvent(abi, eventAbi, event, eventName);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (isEnumEventAbi(eventAbi)) {
|
|
107
|
+
return decodeEnumEvent(abi, eventAbi, event, eventName);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
throw new DecodeEventError(
|
|
111
|
+
`Unsupported event kind: ${(eventAbi as AbiEvent)?.kind}`,
|
|
112
|
+
);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (
|
|
115
|
+
(error instanceof DecodeEventError || error instanceof ParseError) &&
|
|
116
|
+
!strict
|
|
117
|
+
) {
|
|
118
|
+
return null as DecodeEventReturn<TAbi, TEventName, TStrict>;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
throw error;
|
|
91
122
|
}
|
|
123
|
+
}
|
|
92
124
|
|
|
125
|
+
function decodeStructEvent<
|
|
126
|
+
TAbi extends Abi = Abi,
|
|
127
|
+
TEventName extends ExtractAbiEventNames<TAbi> = ExtractAbiEventNames<TAbi>,
|
|
128
|
+
>(
|
|
129
|
+
abi: TAbi,
|
|
130
|
+
eventAbi: AbiEventStruct,
|
|
131
|
+
event: Event,
|
|
132
|
+
eventName: TEventName,
|
|
133
|
+
): DecodedEvent<TAbi, TEventName> {
|
|
93
134
|
const selector = BigInt(getEventSelector(eventName));
|
|
94
135
|
if ((event.keys && selector !== BigInt(event.keys[0])) || !event.keys) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return null as DecodeEventReturn<TAbi, TEventName, TStrict>;
|
|
136
|
+
throw new DecodeEventError(
|
|
137
|
+
`Selector mismatch. Expected ${selector}, got ${event.keys?.[0]}`,
|
|
138
|
+
);
|
|
102
139
|
}
|
|
103
140
|
|
|
104
141
|
const keysAbi = eventAbi.members.filter((m) => m.kind === "key");
|
|
105
142
|
const dataAbi = eventAbi.members.filter((m) => m.kind === "data");
|
|
106
143
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const dataParser = compileEventMembers(abi, dataAbi);
|
|
110
|
-
|
|
111
|
-
const keysWithoutSelector = event.keys?.slice(1) ?? [];
|
|
112
|
-
const { out: decodedKeys } = keysParser(keysWithoutSelector, 0);
|
|
113
|
-
const { out: decodedData } = dataParser(event.data ?? [], 0);
|
|
114
|
-
|
|
115
|
-
const decoded = {
|
|
116
|
-
...decodedKeys,
|
|
117
|
-
...decodedData,
|
|
118
|
-
} as EventToPrimitiveType<TAbi, TEventName>;
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
...event,
|
|
122
|
-
eventName,
|
|
123
|
-
args: decoded,
|
|
124
|
-
} as DecodedEvent<TAbi, TEventName>;
|
|
125
|
-
} catch (error) {
|
|
126
|
-
if (error instanceof DecodeEventError && !strict) {
|
|
127
|
-
return null as DecodeEventReturn<TAbi, TEventName, TStrict>;
|
|
128
|
-
}
|
|
144
|
+
const keysParser = compileEventMembers(abi, keysAbi);
|
|
145
|
+
const dataParser = compileEventMembers(abi, dataAbi);
|
|
129
146
|
|
|
130
|
-
|
|
131
|
-
|
|
147
|
+
const keysWithoutSelector = event.keys?.slice(1) ?? [];
|
|
148
|
+
|
|
149
|
+
const { out: decodedKeys } = keysParser(keysWithoutSelector, 0);
|
|
150
|
+
const { out: decodedData } = dataParser(event.data ?? [], 0);
|
|
151
|
+
|
|
152
|
+
const decoded = {
|
|
153
|
+
...decodedKeys,
|
|
154
|
+
...decodedData,
|
|
155
|
+
} as EventToPrimitiveType<TAbi, TEventName>;
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
...event,
|
|
159
|
+
eventName,
|
|
160
|
+
args: decoded,
|
|
161
|
+
} as DecodedEvent<TAbi, TEventName>;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function decodeEnumEvent<
|
|
165
|
+
TAbi extends Abi = Abi,
|
|
166
|
+
TEventName extends ExtractAbiEventNames<TAbi> = ExtractAbiEventNames<TAbi>,
|
|
167
|
+
>(
|
|
168
|
+
abi: TAbi,
|
|
169
|
+
eventAbi: AbiEventEnum,
|
|
170
|
+
event: Event,
|
|
171
|
+
eventName: TEventName,
|
|
172
|
+
): DecodedEvent<TAbi, TEventName> {
|
|
173
|
+
if (!event.keys || event.keys.length === 0) {
|
|
174
|
+
throw new DecodeEventError(
|
|
175
|
+
"Event has no keys; cannot determine variant selector",
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const variants = eventAbi.variants;
|
|
180
|
+
|
|
181
|
+
const variantSelector = event.keys[0];
|
|
182
|
+
|
|
183
|
+
// Create a map of all possible selectors to their variant paths
|
|
184
|
+
const selectorToVariant = buildVariantSelectorMap(abi, variants);
|
|
185
|
+
|
|
186
|
+
// Find the matching variant and path
|
|
187
|
+
const matchingVariant = selectorToVariant[variantSelector];
|
|
188
|
+
|
|
189
|
+
if (!matchingVariant) {
|
|
190
|
+
throw new DecodeEventError(
|
|
191
|
+
`No matching variant found for selector: ${variantSelector}`,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const structEventAbi = abi.find(
|
|
196
|
+
(item) =>
|
|
197
|
+
item.name === matchingVariant.variant.type && item.type === "event",
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
if (!structEventAbi || !isStructEventAbi(structEventAbi)) {
|
|
201
|
+
throw new DecodeEventError(
|
|
202
|
+
`Nested event type not found or not a struct: ${matchingVariant.variant.type}`,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const decodedStruct = decodeStructEvent(
|
|
207
|
+
abi,
|
|
208
|
+
structEventAbi,
|
|
209
|
+
event,
|
|
210
|
+
matchingVariant.variant.name,
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
...event,
|
|
215
|
+
eventName,
|
|
216
|
+
args: {
|
|
217
|
+
_tag: matchingVariant.variant.name,
|
|
218
|
+
[matchingVariant.variant.name]: decodedStruct.args,
|
|
219
|
+
},
|
|
220
|
+
} as DecodedEvent<TAbi, TEventName>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
type EnumFlatVariantMap = Record<
|
|
224
|
+
string,
|
|
225
|
+
{ variant: AbiEventMember; path: string[] }
|
|
226
|
+
>;
|
|
227
|
+
|
|
228
|
+
// Helper to build a map of all possible selectors to their variant paths
|
|
229
|
+
function buildVariantSelectorMap(
|
|
230
|
+
abi: Abi,
|
|
231
|
+
variants: AbiEventMember[],
|
|
232
|
+
): EnumFlatVariantMap {
|
|
233
|
+
const selectorMap: EnumFlatVariantMap = {};
|
|
234
|
+
|
|
235
|
+
for (const variant of variants) {
|
|
236
|
+
// For nested events, just map the variant's own selector
|
|
237
|
+
if (variant.kind === "nested") {
|
|
238
|
+
const selector = getEventSelector(variant.name);
|
|
239
|
+
selectorMap[selector] = { variant, path: [variant.name] };
|
|
132
240
|
}
|
|
241
|
+
// For flat events, recursively map all possible selectors from the event hierarchy
|
|
242
|
+
else if (variant.kind === "flat") {
|
|
243
|
+
const flatEventName = variant.type;
|
|
244
|
+
const flatEventAbi = abi.find(
|
|
245
|
+
(item) => item.name === flatEventName && item.type === "event",
|
|
246
|
+
);
|
|
133
247
|
|
|
134
|
-
|
|
248
|
+
// Skip if the flat event type is not found
|
|
249
|
+
if (!flatEventAbi) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (isEnumEventAbi(flatEventAbi)) {
|
|
254
|
+
// For enum events, recursively map all their variants
|
|
255
|
+
const nestedMap = buildVariantSelectorMap(abi, flatEventAbi.variants);
|
|
256
|
+
|
|
257
|
+
// Add this variant to the path for all nested selectors
|
|
258
|
+
for (const [
|
|
259
|
+
nestedSelector,
|
|
260
|
+
{ variant: nestedVariant, path: nestedPath },
|
|
261
|
+
] of Object.entries(nestedMap)) {
|
|
262
|
+
selectorMap[nestedSelector] = {
|
|
263
|
+
variant: nestedVariant,
|
|
264
|
+
path: [variant.name, ...nestedPath],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
135
269
|
}
|
|
270
|
+
|
|
271
|
+
return selectorMap;
|
|
136
272
|
}
|
|
137
273
|
|
|
138
274
|
function compileEventMembers<T extends Record<string, unknown>>(
|
|
@@ -166,6 +302,10 @@ function compileTypeParser(abi: Abi, type: string): Parser<unknown> {
|
|
|
166
302
|
return parseEmpty;
|
|
167
303
|
}
|
|
168
304
|
|
|
305
|
+
if (isByteArray(type)) {
|
|
306
|
+
return parseByteArray;
|
|
307
|
+
}
|
|
308
|
+
|
|
169
309
|
// Not a well-known type. Look it up in the ABI.
|
|
170
310
|
const typeAbi = abi.find((item) => item.name === type);
|
|
171
311
|
if (!typeAbi) {
|
|
@@ -176,18 +316,14 @@ function compileTypeParser(abi: Abi, type: string): Parser<unknown> {
|
|
|
176
316
|
case "struct": {
|
|
177
317
|
return compileStructParser(abi, typeAbi.members);
|
|
178
318
|
}
|
|
179
|
-
case "enum":
|
|
180
|
-
|
|
319
|
+
case "enum": {
|
|
320
|
+
return compileEnumParser(abi, typeAbi);
|
|
321
|
+
}
|
|
181
322
|
default:
|
|
182
323
|
throw new DecodeEventError(`Invalid type ${typeAbi.type}`);
|
|
183
324
|
}
|
|
184
325
|
}
|
|
185
326
|
|
|
186
|
-
type AbiMember = {
|
|
187
|
-
name: string;
|
|
188
|
-
type: string;
|
|
189
|
-
};
|
|
190
|
-
|
|
191
327
|
function compileStructParser(
|
|
192
328
|
abi: Abi,
|
|
193
329
|
members: readonly AbiMember[],
|
|
@@ -202,3 +338,15 @@ function compileStructParser(
|
|
|
202
338
|
}
|
|
203
339
|
return parseStruct(parsers);
|
|
204
340
|
}
|
|
341
|
+
|
|
342
|
+
function compileEnumParser(abi: Abi, enumAbi: AbiEnum): Parser<unknown> {
|
|
343
|
+
const parsers: Record<string, { index: number; parser: Parser<unknown> }> =
|
|
344
|
+
{};
|
|
345
|
+
for (const [index, variant] of enumAbi.variants.entries()) {
|
|
346
|
+
parsers[variant.name] = {
|
|
347
|
+
index,
|
|
348
|
+
parser: compileTypeParser(abi, variant.type),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
return parseEnum(parsers);
|
|
352
|
+
}
|