@apibara/starknet 2.1.0-beta.23 → 2.1.0-beta.25
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 +751 -800
- package/dist/index.d.cts +5026 -4858
- package/dist/index.d.mts +5026 -4858
- package/dist/index.d.ts +5026 -4858
- package/dist/index.mjs +752 -793
- package/dist/parser.cjs +6 -5
- package/dist/parser.d.cts +9 -12
- package/dist/parser.d.mts +9 -12
- package/dist/parser.d.ts +9 -12
- package/dist/parser.mjs +6 -5
- 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 +4 -5
- package/src/abi-wan-helpers.ts +140 -0
- package/src/block.ts +827 -565
- package/src/common.ts +20 -35
- package/src/event.ts +174 -44
- package/src/filter.ts +235 -268
- package/src/index.ts +2 -0
- package/src/parser.ts +6 -5
- 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 {
|
|
@@ -16,6 +15,16 @@ import {
|
|
|
16
15
|
isPrimitiveType,
|
|
17
16
|
isSpanType,
|
|
18
17
|
} from "./abi";
|
|
18
|
+
import {
|
|
19
|
+
type AbiEvent,
|
|
20
|
+
type AbiEventEnum,
|
|
21
|
+
type AbiEventStruct,
|
|
22
|
+
type AbiMember,
|
|
23
|
+
type EventToPrimitiveType,
|
|
24
|
+
isEnumEventAbi,
|
|
25
|
+
isEventAbi,
|
|
26
|
+
isStructEventAbi,
|
|
27
|
+
} from "./abi-wan-helpers";
|
|
19
28
|
import type { Event } from "./block";
|
|
20
29
|
import {
|
|
21
30
|
ParseError,
|
|
@@ -78,61 +87,184 @@ export function decodeEvent<
|
|
|
78
87
|
(item) => item.name === eventName && item.type === "event",
|
|
79
88
|
);
|
|
80
89
|
|
|
81
|
-
if (!eventAbi || eventAbi
|
|
90
|
+
if (!eventAbi || !isEventAbi(eventAbi)) {
|
|
82
91
|
if (strict) {
|
|
83
92
|
throw new DecodeEventError(`Event ${eventName} not found in ABI`);
|
|
84
93
|
}
|
|
85
|
-
|
|
86
94
|
return null as DecodeEventReturn<TAbi, TEventName, TStrict>;
|
|
87
95
|
}
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
try {
|
|
98
|
+
if (isStructEventAbi(eventAbi)) {
|
|
99
|
+
return decodeStructEvent(abi, eventAbi, event, eventName);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (isEnumEventAbi(eventAbi)) {
|
|
103
|
+
return decodeEnumEvent(abi, eventAbi, event, eventName);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
throw new DecodeEventError(
|
|
107
|
+
`Unsupported event kind: ${(eventAbi as AbiEvent)?.kind}`,
|
|
108
|
+
);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (
|
|
111
|
+
(error instanceof DecodeEventError || error instanceof ParseError) &&
|
|
112
|
+
!strict
|
|
113
|
+
) {
|
|
114
|
+
return null as DecodeEventReturn<TAbi, TEventName, TStrict>;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
throw error;
|
|
91
118
|
}
|
|
119
|
+
}
|
|
92
120
|
|
|
121
|
+
function decodeStructEvent<
|
|
122
|
+
TAbi extends Abi = Abi,
|
|
123
|
+
TEventName extends ExtractAbiEventNames<TAbi> = ExtractAbiEventNames<TAbi>,
|
|
124
|
+
>(
|
|
125
|
+
abi: TAbi,
|
|
126
|
+
eventAbi: AbiEventStruct,
|
|
127
|
+
event: Event,
|
|
128
|
+
eventName: TEventName,
|
|
129
|
+
): DecodedEvent<TAbi, TEventName> {
|
|
93
130
|
const selector = BigInt(getEventSelector(eventName));
|
|
94
131
|
if ((event.keys && selector !== BigInt(event.keys[0])) || !event.keys) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return null as DecodeEventReturn<TAbi, TEventName, TStrict>;
|
|
132
|
+
throw new DecodeEventError(
|
|
133
|
+
`Selector mismatch. Expected ${selector}, got ${event.keys?.[0]}`,
|
|
134
|
+
);
|
|
102
135
|
}
|
|
103
136
|
|
|
104
137
|
const keysAbi = eventAbi.members.filter((m) => m.kind === "key");
|
|
105
138
|
const dataAbi = eventAbi.members.filter((m) => m.kind === "data");
|
|
106
139
|
|
|
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
|
-
}
|
|
140
|
+
const keysParser = compileEventMembers(abi, keysAbi);
|
|
141
|
+
const dataParser = compileEventMembers(abi, dataAbi);
|
|
129
142
|
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
const keysWithoutSelector = event.keys?.slice(1) ?? [];
|
|
144
|
+
|
|
145
|
+
const { out: decodedKeys } = keysParser(keysWithoutSelector, 0);
|
|
146
|
+
const { out: decodedData } = dataParser(event.data ?? [], 0);
|
|
147
|
+
|
|
148
|
+
const decoded = {
|
|
149
|
+
...decodedKeys,
|
|
150
|
+
...decodedData,
|
|
151
|
+
} as EventToPrimitiveType<TAbi, TEventName>;
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
...event,
|
|
155
|
+
eventName,
|
|
156
|
+
args: decoded,
|
|
157
|
+
} as DecodedEvent<TAbi, TEventName>;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function decodeEnumEvent<
|
|
161
|
+
TAbi extends Abi = Abi,
|
|
162
|
+
TEventName extends ExtractAbiEventNames<TAbi> = ExtractAbiEventNames<TAbi>,
|
|
163
|
+
>(
|
|
164
|
+
abi: TAbi,
|
|
165
|
+
eventAbi: AbiEventEnum,
|
|
166
|
+
event: Event,
|
|
167
|
+
eventName: TEventName,
|
|
168
|
+
): DecodedEvent<TAbi, TEventName> {
|
|
169
|
+
if (!event.keys || event.keys.length === 0) {
|
|
170
|
+
throw new DecodeEventError(
|
|
171
|
+
"Event has no keys; cannot determine variant selector",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const variants = eventAbi.variants;
|
|
176
|
+
|
|
177
|
+
const variantSelector = event.keys[0];
|
|
178
|
+
|
|
179
|
+
// Create a map of all possible selectors to their variant paths
|
|
180
|
+
const selectorToVariant = buildVariantSelectorMap(abi, variants);
|
|
181
|
+
|
|
182
|
+
// Find the matching variant and path
|
|
183
|
+
const matchingVariant = selectorToVariant[variantSelector];
|
|
184
|
+
|
|
185
|
+
if (!matchingVariant) {
|
|
186
|
+
throw new DecodeEventError(
|
|
187
|
+
`No matching variant found for selector: ${variantSelector}`,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const structEventAbi = abi.find(
|
|
192
|
+
(item) =>
|
|
193
|
+
item.name === matchingVariant.variant.type && item.type === "event",
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
if (!structEventAbi || !isStructEventAbi(structEventAbi)) {
|
|
197
|
+
throw new DecodeEventError(
|
|
198
|
+
`Nested event type not found or not a struct: ${matchingVariant.variant.type}`,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const decodedStruct = decodeStructEvent(
|
|
203
|
+
abi,
|
|
204
|
+
structEventAbi,
|
|
205
|
+
event,
|
|
206
|
+
matchingVariant.variant.name,
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
...event,
|
|
211
|
+
eventName,
|
|
212
|
+
args: {
|
|
213
|
+
_tag: matchingVariant.variant.name,
|
|
214
|
+
[matchingVariant.variant.name]: decodedStruct.args,
|
|
215
|
+
},
|
|
216
|
+
} as DecodedEvent<TAbi, TEventName>;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
type EnumFlatVariantMap = Record<
|
|
220
|
+
string,
|
|
221
|
+
{ variant: AbiEventMember; path: string[] }
|
|
222
|
+
>;
|
|
223
|
+
|
|
224
|
+
// Helper to build a map of all possible selectors to their variant paths
|
|
225
|
+
function buildVariantSelectorMap(
|
|
226
|
+
abi: Abi,
|
|
227
|
+
variants: AbiEventMember[],
|
|
228
|
+
): EnumFlatVariantMap {
|
|
229
|
+
const selectorMap: EnumFlatVariantMap = {};
|
|
230
|
+
|
|
231
|
+
for (const variant of variants) {
|
|
232
|
+
// For nested events, just map the variant's own selector
|
|
233
|
+
if (variant.kind === "nested") {
|
|
234
|
+
const selector = getEventSelector(variant.name);
|
|
235
|
+
selectorMap[selector] = { variant, path: [variant.name] };
|
|
132
236
|
}
|
|
237
|
+
// For flat events, recursively map all possible selectors from the event hierarchy
|
|
238
|
+
else if (variant.kind === "flat") {
|
|
239
|
+
const flatEventName = variant.type;
|
|
240
|
+
const flatEventAbi = abi.find(
|
|
241
|
+
(item) => item.name === flatEventName && item.type === "event",
|
|
242
|
+
);
|
|
133
243
|
|
|
134
|
-
|
|
244
|
+
// Skip if the flat event type is not found
|
|
245
|
+
if (!flatEventAbi) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (isEnumEventAbi(flatEventAbi)) {
|
|
250
|
+
// For enum events, recursively map all their variants
|
|
251
|
+
const nestedMap = buildVariantSelectorMap(abi, flatEventAbi.variants);
|
|
252
|
+
|
|
253
|
+
// Add this variant to the path for all nested selectors
|
|
254
|
+
for (const [
|
|
255
|
+
nestedSelector,
|
|
256
|
+
{ variant: nestedVariant, path: nestedPath },
|
|
257
|
+
] of Object.entries(nestedMap)) {
|
|
258
|
+
selectorMap[nestedSelector] = {
|
|
259
|
+
variant: nestedVariant,
|
|
260
|
+
path: [variant.name, ...nestedPath],
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
135
265
|
}
|
|
266
|
+
|
|
267
|
+
return selectorMap;
|
|
136
268
|
}
|
|
137
269
|
|
|
138
270
|
function compileEventMembers<T extends Record<string, unknown>>(
|
|
@@ -176,18 +308,16 @@ function compileTypeParser(abi: Abi, type: string): Parser<unknown> {
|
|
|
176
308
|
case "struct": {
|
|
177
309
|
return compileStructParser(abi, typeAbi.members);
|
|
178
310
|
}
|
|
179
|
-
case "enum":
|
|
180
|
-
|
|
311
|
+
case "enum": {
|
|
312
|
+
// This should never happen anyways as compileTypeParser is only called
|
|
313
|
+
// primitive types or to compile structs parsers.
|
|
314
|
+
throw new DecodeEventError(`Enum types are not supported: ${type}`);
|
|
315
|
+
}
|
|
181
316
|
default:
|
|
182
317
|
throw new DecodeEventError(`Invalid type ${typeAbi.type}`);
|
|
183
318
|
}
|
|
184
319
|
}
|
|
185
320
|
|
|
186
|
-
type AbiMember = {
|
|
187
|
-
name: string;
|
|
188
|
-
type: string;
|
|
189
|
-
};
|
|
190
|
-
|
|
191
321
|
function compileStructParser(
|
|
192
322
|
abi: Abi,
|
|
193
323
|
members: readonly AbiMember[],
|