@apibara/beaconchain 2.0.0-beta.3

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/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # `@apibara/starknet`
2
+
3
+ This package provides types for the Starknet streams on Apibara.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm add @apibara/starknet
9
+ ```
10
+
11
+ ## License
12
+
13
+ Copyright 2024 GNC Labs Limited
14
+
15
+ Licensed under the Apache License, Version 2.0 (the "License");
16
+ you may not use this file except in compliance with the License.
17
+ You may obtain a copy of the License at
18
+
19
+ http://www.apache.org/licenses/LICENSE-2.0
20
+
21
+ Unless required by applicable law or agreed to in writing, software
22
+ distributed under the License is distributed on an "AS IS" BASIS,
23
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
+ See the License for the specific language governing permissions and
25
+ limitations under the License.
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@apibara/beaconchain",
3
+ "version": "2.0.0-beta.3",
4
+ "type": "module",
5
+ "source": "./src/index.ts",
6
+ "main": "./dist/index.mjs",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.cjs",
12
+ "default": "./dist/index.mjs"
13
+ }
14
+ },
15
+ "publishConfig": {},
16
+ "scripts": {
17
+ "build": "pnpm build:proto && unbuild",
18
+ "build:proto": "buf generate proto",
19
+ "typecheck": "tsc --noEmit",
20
+ "test": "vitest",
21
+ "test:ci": "vitest run",
22
+ "lint": "biome check .",
23
+ "lint:fix": "pnpm lint --write",
24
+ "format": "biome format . --write"
25
+ },
26
+ "devDependencies": {
27
+ "@bufbuild/buf": "^1.32.1",
28
+ "@types/long": "^5.0.0",
29
+ "@types/node": "^20.12.12",
30
+ "unbuild": "^2.0.0",
31
+ "vitest": "^1.6.0"
32
+ },
33
+ "dependencies": {
34
+ "@apibara/evm": "2.0.0-beta.3",
35
+ "@apibara/protocol": "2.0.0-beta.3",
36
+ "@effect/schema": "^0.67.15",
37
+ "effect": "^3.2.6",
38
+ "long": "^5.2.1",
39
+ "nice-grpc-common": "^2.0.2",
40
+ "protobufjs": "^7.1.2",
41
+ "viem": "^2.13.8"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "src",
46
+ "README.md"
47
+ ],
48
+ "types": "./dist/index.d.ts"
49
+ }
package/src/block.ts ADDED
@@ -0,0 +1,114 @@
1
+ import { AccessListItem, Signature } from "@apibara/evm";
2
+ import { BytesFromUint8Array } from "@apibara/protocol";
3
+ import { Schema } from "@effect/schema";
4
+
5
+ import { Address, B256, B384, U128, U256, ValidatorStatus } from "./common";
6
+ import * as proto from "./proto";
7
+
8
+ export const ExecutionPayload = Schema.Struct({
9
+ parentHash: Schema.optional(B256),
10
+ feeRecipient: Schema.optional(Address),
11
+ stateRoot: Schema.optional(B256),
12
+ receiptsRoot: Schema.optional(B256),
13
+ logsBloom: BytesFromUint8Array,
14
+ prevRandao: Schema.optional(B256),
15
+ blockNumber: Schema.optional(Schema.BigIntFromSelf),
16
+ timestamp: Schema.optional(Schema.DateFromSelf),
17
+ });
18
+
19
+ export type ExecutionPayload = typeof ExecutionPayload.Type;
20
+
21
+ export const BlockHeader = Schema.Struct({
22
+ slot: Schema.BigIntFromSelf,
23
+ proposerIndex: Schema.Number,
24
+ parentRoot: Schema.optional(B256),
25
+ stateRoot: Schema.optional(B256),
26
+ randaoReveal: BytesFromUint8Array,
27
+ depositCount: Schema.optional(Schema.BigIntFromSelf),
28
+ depositRoot: Schema.optional(B256),
29
+ blockHash: Schema.optional(B256),
30
+ graffiti: Schema.optional(B256),
31
+ executionPayload: Schema.optional(ExecutionPayload),
32
+ blobKzgCommitments: Schema.optional(Schema.Array(B384)),
33
+ });
34
+
35
+ export type BlockHeader = typeof BlockHeader.Type;
36
+
37
+ export const Validator = Schema.Struct({
38
+ filterIds: Schema.optional(Schema.Array(Schema.Number)),
39
+ validatorIndex: Schema.optional(Schema.Number),
40
+ balance: Schema.optional(Schema.BigIntFromSelf),
41
+ status: Schema.optional(ValidatorStatus),
42
+ pubkey: Schema.optional(B384),
43
+ withdrawalCredentials: Schema.optional(B256),
44
+ effectiveBalance: Schema.optional(Schema.BigIntFromSelf),
45
+ slashed: Schema.optional(Schema.Boolean),
46
+ activationEligibilityEpoch: Schema.optional(Schema.BigIntFromSelf),
47
+ activationEpoch: Schema.optional(Schema.BigIntFromSelf),
48
+ exitEpoch: Schema.optional(Schema.BigIntFromSelf),
49
+ withdrawableEpoch: Schema.optional(Schema.BigIntFromSelf),
50
+ });
51
+
52
+ export const Blob = Schema.Struct({
53
+ filterIds: Schema.optional(Schema.Array(Schema.Number)),
54
+ blobIndex: Schema.optional(Schema.Number),
55
+ blob: Schema.optional(Schema.Uint8ArrayFromSelf),
56
+ kzgCommitment: Schema.optional(B384),
57
+ kzgProof: Schema.optional(B384),
58
+ kzgCommitmentInclusionProof: Schema.optional(Schema.Array(B256)),
59
+ blobHash: Schema.optional(B256),
60
+ transactionIndex: Schema.optional(Schema.Number),
61
+ transactionHash: Schema.optional(B256),
62
+ });
63
+
64
+ export const Transaction = Schema.Struct({
65
+ filterIds: Schema.optional(Schema.Array(Schema.Number)),
66
+ transactionHash: Schema.optional(B256),
67
+ nonce: Schema.optional(Schema.BigIntFromSelf),
68
+ transactionIndex: Schema.optional(Schema.Number),
69
+ from: Schema.optional(Address),
70
+ to: Schema.optional(Address),
71
+ value: Schema.optional(U256),
72
+ gasPrice: Schema.optional(U128),
73
+ gasLimit: Schema.optional(U128),
74
+ maxFeePerGas: Schema.optional(U128),
75
+ maxPriorityFeePerGas: Schema.optional(U128),
76
+ input: Schema.optional(Schema.Uint8ArrayFromSelf),
77
+ signature: Schema.optional(Signature),
78
+ chainId: Schema.optional(Schema.BigIntFromSelf),
79
+ accessList: Schema.optional(Schema.Array(AccessListItem)),
80
+ transactionType: Schema.optional(Schema.BigIntFromSelf),
81
+ maxFeePerBlobGas: Schema.optional(U128),
82
+ blobVersionedHashes: Schema.optional(Schema.Array(B256)),
83
+ });
84
+
85
+ export type Transaction = typeof Transaction.Type;
86
+
87
+ export const Block = Schema.Struct({
88
+ header: Schema.optional(BlockHeader),
89
+ validators: Schema.Array(Validator),
90
+ blobs: Schema.Array(Blob),
91
+ transactions: Schema.Array(Transaction),
92
+ });
93
+
94
+ export type Block = typeof Block.Type;
95
+
96
+ export const BlockFromBytes = Schema.transform(
97
+ Schema.Uint8ArrayFromSelf,
98
+ Schema.NullOr(Block),
99
+ {
100
+ strict: false,
101
+ decode(value) {
102
+ if (value.length === 0) {
103
+ return null;
104
+ }
105
+ return proto.data.Block.decode(value);
106
+ },
107
+ encode(value) {
108
+ if (value === null) {
109
+ return new Uint8Array();
110
+ }
111
+ return proto.data.Block.encode(value).finish();
112
+ },
113
+ },
114
+ );
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import { Schema } from "@effect/schema";
4
+ import { pad } from "viem";
5
+
6
+ import { B384 } from "./common";
7
+
8
+ describe("B384", () => {
9
+ const encode = Schema.encodeSync(B384);
10
+ const decode = Schema.decodeSync(B384);
11
+
12
+ it("should convert from and to proto", () => {
13
+ const value =
14
+ "0x9df92d765b5aa041fd4bbe8d5878eb89290efa78e444c1a603eecfae2ea05fa4";
15
+
16
+ const message = encode(value);
17
+
18
+ const back = decode(message);
19
+ expect(back).toEqual(pad(value, { size: 48 }));
20
+ });
21
+ });
package/src/common.ts ADDED
@@ -0,0 +1,95 @@
1
+ import { Schema } from "@effect/schema";
2
+ import { hexToBytes, pad } from "viem";
3
+
4
+ import * as proto from "./proto";
5
+
6
+ // Re-export common types
7
+ export { Address, U128, U256, B256 } from "@apibara/evm";
8
+
9
+ export const ValidatorStatus = Schema.transform(
10
+ Schema.Enums(proto.common.ValidatorStatus),
11
+ Schema.Literal(
12
+ "pending_initialized",
13
+ "pending_queued",
14
+ "active_ongoing",
15
+ "active_exiting",
16
+ "active_slashed",
17
+ "exited_unslashed",
18
+ "exited_slashed",
19
+ "withdrawal_possible",
20
+ "withdrawal_done",
21
+ "unknown",
22
+ ),
23
+ {
24
+ decode(value) {
25
+ const enumMap = {
26
+ [proto.common.ValidatorStatus.PENDING_INITIALIZED]:
27
+ "pending_initialized",
28
+ [proto.common.ValidatorStatus.PENDING_QUEUED]: "pending_queued",
29
+ [proto.common.ValidatorStatus.ACTIVE_ONGOING]: "active_ongoing",
30
+ [proto.common.ValidatorStatus.ACTIVE_EXITING]: "active_exiting",
31
+ [proto.common.ValidatorStatus.ACTIVE_SLASHED]: "active_slashed",
32
+ [proto.common.ValidatorStatus.EXITED_UNSLASHED]: "exited_unslashed",
33
+ [proto.common.ValidatorStatus.EXITED_SLASHED]: "exited_slashed",
34
+ [proto.common.ValidatorStatus.WITHDRAWAL_POSSIBLE]:
35
+ "withdrawal_possible",
36
+ [proto.common.ValidatorStatus.WITHDRAWAL_DONE]: "withdrawal_done",
37
+ [proto.common.ValidatorStatus.UNKNOWN]: "unknown",
38
+ [proto.common.ValidatorStatus.UNRECOGNIZED]: "unknown",
39
+ } as const;
40
+
41
+ return enumMap[value] ?? "unknown";
42
+ },
43
+ encode(value) {
44
+ const enumMap = {
45
+ pending_initialized: proto.common.ValidatorStatus.PENDING_INITIALIZED,
46
+ pending_queued: proto.common.ValidatorStatus.PENDING_QUEUED,
47
+ active_ongoing: proto.common.ValidatorStatus.ACTIVE_ONGOING,
48
+ active_exiting: proto.common.ValidatorStatus.ACTIVE_EXITING,
49
+ active_slashed: proto.common.ValidatorStatus.ACTIVE_SLASHED,
50
+ exited_unslashed: proto.common.ValidatorStatus.EXITED_UNSLASHED,
51
+ exited_slashed: proto.common.ValidatorStatus.EXITED_SLASHED,
52
+ withdrawal_possible: proto.common.ValidatorStatus.WITHDRAWAL_POSSIBLE,
53
+ withdrawal_done: proto.common.ValidatorStatus.WITHDRAWAL_DONE,
54
+ unknown: proto.common.ValidatorStatus.UNKNOWN,
55
+ } as const;
56
+
57
+ return enumMap[value] ?? proto.common.ValidatorStatus.UNKNOWN;
58
+ },
59
+ },
60
+ );
61
+
62
+ const _B384 = Schema.TemplateLiteral(Schema.Literal("0x"), Schema.String);
63
+ const B384Proto = Schema.Struct({
64
+ x0: Schema.BigIntFromSelf,
65
+ x1: Schema.BigIntFromSelf,
66
+ x2: Schema.BigIntFromSelf,
67
+ x3: Schema.BigIntFromSelf,
68
+ x4: Schema.BigIntFromSelf,
69
+ x5: Schema.BigIntFromSelf,
70
+ });
71
+
72
+ export const B384 = Schema.transform(B384Proto, _B384, {
73
+ decode(value) {
74
+ const x0 = value.x0.toString(16).padStart(16, "0");
75
+ const x1 = value.x1.toString(16).padStart(16, "0");
76
+ const x2 = value.x2.toString(16).padStart(16, "0");
77
+ const x3 = value.x3.toString(16).padStart(16, "0");
78
+ const x4 = value.x4.toString(16).padStart(16, "0");
79
+ const x5 = value.x5.toString(16).padStart(16, "0");
80
+ return `0x${x0}${x1}${x2}${x3}${x4}${x5}` as `0x${string}`;
81
+ },
82
+ encode(value) {
83
+ const bytes = hexToBytes(pad(value, { size: 48, dir: "left" }));
84
+ const dv = new DataView(bytes.buffer);
85
+ const x0 = dv.getBigUint64(0);
86
+ const x1 = dv.getBigUint64(8);
87
+ const x2 = dv.getBigUint64(16);
88
+ const x3 = dv.getBigUint64(24);
89
+ const x4 = dv.getBigUint64(32);
90
+ const x5 = dv.getBigUint64(40);
91
+ return { x0, x1, x2, x3, x4, x5 };
92
+ },
93
+ });
94
+
95
+ export type B384 = typeof B384.Type;
package/src/filter.ts ADDED
@@ -0,0 +1,113 @@
1
+ import { Schema } from "@effect/schema";
2
+
3
+ import { Address, ValidatorStatus } from "./common";
4
+ import * as proto from "./proto";
5
+
6
+ /** Header options.
7
+ *
8
+ * Change `always` to `true` to receive headers even if no other data matches.
9
+ */
10
+ export const HeaderFilter = Schema.Struct({
11
+ always: Schema.optional(Schema.Boolean),
12
+ });
13
+
14
+ export type HeaderFilter = typeof HeaderFilter.Type;
15
+
16
+ /** Filter transactions.
17
+ *
18
+ * @prop from Filter transactions by the sender address.
19
+ * @prop to Filter transactions by the target address.
20
+ * @prop includeBlob Include any blob posted by the transaction..
21
+ */
22
+ export const TransactionFilter = Schema.Struct({
23
+ id: Schema.optional(Schema.Number),
24
+ from: Schema.optional(Address),
25
+ to: Schema.optional(Address),
26
+ create: Schema.optional(Schema.Boolean),
27
+ includeBlob: Schema.optional(Schema.Boolean),
28
+ });
29
+
30
+ export type TransactionFilter = typeof TransactionFilter.Type;
31
+
32
+ /** Filter validators.
33
+ *
34
+ * @prop validatorIndex Filter validators by their index.
35
+ * @prop status Filter validators by their status.
36
+ */
37
+ export const ValidatorFilter = Schema.Struct({
38
+ id: Schema.optional(Schema.Number),
39
+ validatorIndex: Schema.optional(Schema.Number),
40
+ status: Schema.optional(ValidatorStatus),
41
+ });
42
+
43
+ export type ValidatorFilter = typeof ValidatorFilter.Type;
44
+
45
+ /** Filter blobs.
46
+ *
47
+ * @prop includeTransaction Include the transaction that posted the blob.
48
+ */
49
+ export const BlobFilter = Schema.Struct({
50
+ id: Schema.optional(Schema.Number),
51
+ includeTransaction: Schema.optional(Schema.Boolean),
52
+ });
53
+
54
+ export type BlobFilter = typeof BlobFilter.Type;
55
+
56
+ /** Filter block data.
57
+ *
58
+ * @prop header Change how block headers are returned.
59
+ * @prop validators Filter validators.
60
+ */
61
+ export const Filter = Schema.Struct({
62
+ header: Schema.optional(HeaderFilter),
63
+ transactions: Schema.optional(Schema.Array(TransactionFilter)),
64
+ validators: Schema.optional(Schema.Array(ValidatorFilter)),
65
+ blobs: Schema.optional(Schema.Array(BlobFilter)),
66
+ });
67
+
68
+ export type Filter = typeof Filter.Type;
69
+
70
+ export const filterToProto = Schema.encodeSync(Filter);
71
+ export const filterFromProto = Schema.decodeSync(Filter);
72
+
73
+ export const FilterFromBytes = Schema.transform(
74
+ Schema.Uint8ArrayFromSelf,
75
+ Filter,
76
+ {
77
+ strict: false,
78
+ decode(value) {
79
+ return proto.filter.Filter.decode(value);
80
+ },
81
+ encode(value) {
82
+ return proto.filter.Filter.encode(value).finish();
83
+ },
84
+ },
85
+ );
86
+
87
+ export const filterToBytes = Schema.encodeSync(FilterFromBytes);
88
+ export const filterFromBytes = Schema.decodeSync(FilterFromBytes);
89
+
90
+ export function mergeFilter(a: Filter, b: Filter): Filter {
91
+ const header = mergeHeaderFilter(a.header, b.header);
92
+ return {
93
+ header,
94
+ transactions: [...(a.transactions ?? []), ...(b.transactions ?? [])],
95
+ validators: [...(a.validators ?? []), ...(b.validators ?? [])],
96
+ blobs: [...(a.blobs ?? []), ...(b.blobs ?? [])],
97
+ };
98
+ }
99
+
100
+ function mergeHeaderFilter(
101
+ a?: HeaderFilter,
102
+ b?: HeaderFilter,
103
+ ): HeaderFilter | undefined {
104
+ if (a === undefined) {
105
+ return b;
106
+ }
107
+ if (b === undefined) {
108
+ return a;
109
+ }
110
+ return {
111
+ always: a.always || b.always,
112
+ };
113
+ }
package/src/index.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { StreamConfig } from "@apibara/protocol";
2
+ import { BlockFromBytes } from "./block";
3
+ import { FilterFromBytes, mergeFilter } from "./filter";
4
+
5
+ export * as proto from "./proto";
6
+
7
+ export * from "./common";
8
+ export * from "./filter";
9
+ export * from "./block";
10
+
11
+ export const BeaconChainStream = new StreamConfig(
12
+ FilterFromBytes,
13
+ BlockFromBytes,
14
+ mergeFilter,
15
+ );