@effectstream/sm 0.101.1 → 0.103.0

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.
Files changed (26) hide show
  1. package/LICENSE-APACHE +201 -0
  2. package/LICENSE-MIT +21 -0
  3. package/package.json +10 -10
  4. package/primitives/Primitive.ts +4 -1
  5. package/primitives/src/builtin.ts +24 -3
  6. package/primitives/src/grammar.ts +8 -0
  7. package/primitives/src/midnight-nullifier-and-commitment/midnight-nullifier-and-commitment-grammar.ts +37 -0
  8. package/primitives/src/{midnight-nullifier/midnight-nullifier.ts → midnight-nullifier-and-commitment/midnight-nullifier-and-commitment.ts} +37 -14
  9. package/primitives/src/midnight-token-mint/midnight-token-mint-grammar.ts +12 -4
  10. package/primitives/src/midnight-token-mint/midnight-token-mint-ivm.ts +105 -0
  11. package/primitives/src/midnight-token-mint/midnight-token-mint.test.ts +150 -0
  12. package/primitives/src/midnight-token-mint/midnight-token-mint.ts +80 -23
  13. package/primitives/src/midnight-unshielded-create/midnight-unshielded-create-grammar.ts +14 -1
  14. package/primitives/src/midnight-unshielded-create/midnight-unshielded-create.ts +4 -1
  15. package/primitives/src/midnight-unshielded-spend/midnight-unshielded-spend-grammar.ts +14 -1
  16. package/primitives/src/midnight-unshielded-spend/midnight-unshielded-spend.ts +4 -1
  17. package/primitives/src/mod.ts +17 -4
  18. package/primitives/src/solana-account-balance/solana-account-balance-grammar.ts +7 -0
  19. package/primitives/src/solana-account-balance/solana-account-balance-primitive.ts +108 -0
  20. package/primitives/src/solana-program-log/solana-program-log-grammar.ts +7 -0
  21. package/primitives/src/solana-program-log/solana-program-log-primitive.test.ts +128 -0
  22. package/primitives/src/solana-program-log/solana-program-log-primitive.ts +108 -0
  23. package/primitives/src/solana-token-account/solana-token-account-grammar.ts +13 -0
  24. package/primitives/src/solana-token-account/solana-token-account-primitive.test.ts +117 -0
  25. package/primitives/src/solana-token-account/solana-token-account-primitive.ts +156 -0
  26. package/primitives/src/midnight-nullifier/midnight-nullifier-grammar.ts +0 -8
@@ -0,0 +1,128 @@
1
+ import { test, expect } from "bun:test";
2
+ import { run } from "effection";
3
+ import type { ConfigSyncProtocolType, FlattenSyncProtocolIOFor } from "@effectstream/config";
4
+ import { SolanaProgramLogPrimitive } from "./../mod.ts";
5
+ import { PrimitiveRegistry } from "../../PrimitiveRegistry.ts";
6
+
7
+ const PROGRAM_ID = "11111111111111111111111111111111";
8
+ const PrimitiveTypeSolanaProgramLog = "SOLANA:ProgramLog";
9
+
10
+ function cleanup() {
11
+ PrimitiveRegistry.primitives = {};
12
+ }
13
+
14
+ test("SolanaProgramLogPrimitive - initializes correctly", () => {
15
+ cleanup();
16
+ const primitive = new SolanaProgramLogPrimitive({
17
+ instanceName: "spl",
18
+ startBlockHeight: 0,
19
+ programId: PROGRAM_ID,
20
+ stateMachinePrefix: "solana-program-log",
21
+ });
22
+
23
+ expect(primitive.instanceName).toEqual("spl");
24
+ expect(primitive.startBlockHeight).toEqual(0);
25
+ expect(primitive.programId).toEqual(PROGRAM_ID);
26
+ expect(primitive.internalTypeName).toEqual(PrimitiveTypeSolanaProgramLog);
27
+
28
+ const config = primitive.getConfig();
29
+ expect(config.name).toEqual("spl");
30
+ expect(config.type).toEqual(PrimitiveTypeSolanaProgramLog);
31
+ expect(config.programId).toEqual(PROGRAM_ID);
32
+ expect(config.scheduledPrefix).toEqual("solana-program-log");
33
+ });
34
+
35
+ test("SolanaProgramLogPrimitive - getPayload generates correct state update", async () => {
36
+ cleanup();
37
+ const primitive = new SolanaProgramLogPrimitive({
38
+ instanceName: "spl",
39
+ startBlockHeight: 0,
40
+ programId: PROGRAM_ID,
41
+ stateMachinePrefix: "solana-program-log",
42
+ });
43
+
44
+ const mockTxData = {
45
+ syncProtocol: {
46
+ name: "parallelSolanaRPC",
47
+ blockNumber: 42,
48
+ transactionHash: "5x…signature",
49
+ contractAddress: PROGRAM_ID,
50
+ },
51
+ output: {
52
+ payloadType: "solana:transaction",
53
+ payload: {
54
+ programId: PROGRAM_ID,
55
+ slot: 42,
56
+ logMessages: ["Program log: hi", "Program log: bye"],
57
+ },
58
+ },
59
+ } as unknown as FlattenSyncProtocolIOFor<
60
+ ConfigSyncProtocolType.SOLANA_RPC_PARALLEL
61
+ >;
62
+
63
+ await run(function* () {
64
+ const generator = primitive.getPayload(123, mockTxData);
65
+ const result = generator.next().value;
66
+
67
+ if (!result) throw new Error("No payload generated");
68
+ if (!("isBatched" in result)) {
69
+ throw new Error("Result is not a SyncStateUpdate");
70
+ }
71
+
72
+ expect(result.isBatched).toEqual(false);
73
+ expect(result.data.length).toEqual(1);
74
+
75
+ const item = result.data[0];
76
+ expect(item.accountingPayload.slot).toEqual(42);
77
+ expect(item.accountingPayload.programId).toEqual(PROGRAM_ID);
78
+ expect(item.accountingPayload.logMessages).toEqual([
79
+ "Program log: hi",
80
+ "Program log: bye",
81
+ ]);
82
+
83
+ expect(Array.isArray(item.stateMachinePayload)).toEqual(true);
84
+ // @ts-ignore: safe to access
85
+ expect(item.stateMachinePayload?.[0]).toEqual("solana-program-log");
86
+ });
87
+ });
88
+
89
+ test("SolanaProgramLogPrimitive - getPayload skips state machine payload if no prefix", async () => {
90
+ cleanup();
91
+ const primitive = new SolanaProgramLogPrimitive({
92
+ instanceName: "spl",
93
+ startBlockHeight: 0,
94
+ programId: PROGRAM_ID,
95
+ stateMachinePrefix: undefined,
96
+ });
97
+
98
+ const mockTxData = {
99
+ syncProtocol: {
100
+ name: "parallelSolanaRPC",
101
+ blockNumber: 7,
102
+ transactionHash: "sig",
103
+ contractAddress: PROGRAM_ID,
104
+ },
105
+ output: {
106
+ payload: {
107
+ programId: PROGRAM_ID,
108
+ slot: 7,
109
+ logMessages: ["Program log: x"],
110
+ },
111
+ },
112
+ } as unknown as FlattenSyncProtocolIOFor<
113
+ ConfigSyncProtocolType.SOLANA_RPC_PARALLEL
114
+ >;
115
+
116
+ await run(function* () {
117
+ const generator = primitive.getPayload(123, mockTxData);
118
+ const result = generator.next().value;
119
+
120
+ if (!result) throw new Error("No payload generated");
121
+ if (!("isBatched" in result)) {
122
+ throw new Error("Result is not a SyncStateUpdate");
123
+ }
124
+
125
+ const item = result.data[0];
126
+ expect(item.stateMachinePayload).toEqual(null);
127
+ });
128
+ });
@@ -0,0 +1,108 @@
1
+ import type { StaticDecode } from "@sinclair/typebox";
2
+ import {
3
+ type ConfigSyncProtocolType,
4
+ type FlattenSyncProtocolIOFor,
5
+ type ProtocolPrimitiveMap,
6
+ } from "@effectstream/config";
7
+ import {
8
+ type AddressAndType,
9
+ AddressType,
10
+ type EffectstreamBlockNumber,
11
+ } from "@effectstream/utils";
12
+ import { type JsonObject, Primitive } from "@effectstream/sm";
13
+ import {
14
+ type CommandTuple,
15
+ generateRawStmInput,
16
+ type ParamToData,
17
+ } from "@effectstream/concise";
18
+ import type { StateUpdateStream } from "@effectstream/coroutine";
19
+ import { solanaProgramLogGrammar } from "./solana-program-log-grammar.ts";
20
+ import { PrimitiveTypeSolanaProgramLog } from "../builtin.ts";
21
+
22
+ export class SolanaProgramLogPrimitive extends Primitive<
23
+ ConfigSyncProtocolType.SOLANA_RPC_PARALLEL,
24
+ typeof solanaProgramLogGrammar
25
+ > {
26
+ readonly internalTypeName = PrimitiveTypeSolanaProgramLog;
27
+ override grammar = solanaProgramLogGrammar;
28
+ readonly programId: string;
29
+ readonly eventType: string | undefined;
30
+
31
+ constructor(config: {
32
+ instanceName: string;
33
+ startBlockHeight: number;
34
+ programId: string;
35
+ eventType?: string;
36
+ stateMachinePrefix: string | undefined;
37
+ }) {
38
+ super(config);
39
+ this.programId = config.programId;
40
+ this.eventType = config.eventType;
41
+ }
42
+
43
+ override *getPayload(
44
+ _: EffectstreamBlockNumber,
45
+ primitiveTransactionData: FlattenSyncProtocolIOFor<
46
+ ConfigSyncProtocolType.SOLANA_RPC_PARALLEL
47
+ >,
48
+ ): StateUpdateStream<{
49
+ isBatched: boolean;
50
+ data: {
51
+ fromAddressAndType: AddressAndType;
52
+ stateMachinePayload:
53
+ | StaticDecode<CommandTuple<string, typeof solanaProgramLogGrammar>>
54
+ | null;
55
+ accountingPayload: JsonObject;
56
+ }[];
57
+ }> {
58
+ const { programId, slot, logMessages } =
59
+ primitiveTransactionData.output.payload as {
60
+ programId: string;
61
+ slot: number;
62
+ logMessages: string[];
63
+ };
64
+
65
+ const accountingPayload: ParamToData<typeof solanaProgramLogGrammar> = {
66
+ slot,
67
+ programId,
68
+ logMessages,
69
+ };
70
+
71
+ const stateMachinePayload = this.stateMachinePrefix
72
+ ? generateRawStmInput(
73
+ this.grammar,
74
+ this.stateMachinePrefix,
75
+ accountingPayload,
76
+ )
77
+ : null;
78
+
79
+ return {
80
+ isBatched: false,
81
+ data: [
82
+ {
83
+ fromAddressAndType: {
84
+ type: AddressType.SOLANA,
85
+ address: String(
86
+ primitiveTransactionData.syncProtocol.contractAddress ?? "",
87
+ ),
88
+ },
89
+ accountingPayload,
90
+ stateMachinePayload,
91
+ },
92
+ ],
93
+ };
94
+ }
95
+
96
+ override getConfig(): ProtocolPrimitiveMap[
97
+ ConfigSyncProtocolType.SOLANA_RPC_PARALLEL
98
+ ] {
99
+ return {
100
+ name: this.instanceName,
101
+ type: this.internalTypeName,
102
+ startBlockHeight: this.startBlockHeight,
103
+ programId: this.programId,
104
+ eventType: this.eventType,
105
+ scheduledPrefix: this.stateMachinePrefix,
106
+ };
107
+ }
108
+ }
@@ -0,0 +1,13 @@
1
+ import { Type } from "@sinclair/typebox";
2
+
3
+ export const solanaTokenAccountGrammar = [
4
+ ["tokenAccount", Type.String()],
5
+ ["mint", Type.String()],
6
+ ["owner", Type.String()],
7
+ // SPL amounts are u64 and do not survive a JS number. Carried as the raw base
8
+ // unit string, matching nep141Grammar's `amount` and erc20Grammar's `value`;
9
+ // `decimals` is what turns it into a display value.
10
+ ["amount", Type.String()],
11
+ ["decimals", Type.Number()],
12
+ ["slot", Type.Number()],
13
+ ] as const;
@@ -0,0 +1,117 @@
1
+ import { expect, test } from "bun:test";
2
+ // Via the barrel, not the file directly: mod.ts registers every primitive class, so
3
+ // importing the file first hits a TDZ error on the map entry. Same as
4
+ // solana-program-log-primitive.test.ts.
5
+ import { SolanaTokenAccountPrimitive } from "./../mod.ts";
6
+ import { PrimitiveRegistry } from "../../PrimitiveRegistry.ts";
7
+
8
+ /**
9
+ * Unit coverage for the primitive half of SOLANA:TokenAccount — the config guard and
10
+ * the payload the state machine actually receives. The fetcher half (which balance
11
+ * records match, and lookup-table resolution) is covered in
12
+ * `sync/src/sync-protocols/solana/read-primitives.test.ts`.
13
+ *
14
+ * `getPayload` is a generator that never yields, so one `.next()` drives it to done.
15
+ */
16
+
17
+ const MINT = "Mint111111111111111111111111111111111111111";
18
+ const OWNER = "0wner11111111111111111111111111111111111111";
19
+ const TOKEN_ACCOUNT = "Tok111111111111111111111111111111111111111";
20
+
21
+ function makePrimitive(overrides: Record<string, unknown> = {}) {
22
+ // The Primitive constructor self-registers and PrimitiveRegistry.addPrimitive
23
+ // throws on a duplicate instanceName, so the singleton has to be cleared between
24
+ // constructions.
25
+ PrimitiveRegistry.primitives = {};
26
+ return new SolanaTokenAccountPrimitive({
27
+ instanceName: "WatchedToken",
28
+ startBlockHeight: 0,
29
+ mint: MINT,
30
+ stateMachinePrefix: "solana-token-account",
31
+ ...overrides,
32
+ } as any);
33
+ }
34
+
35
+ function payloadOf(primitive: SolanaTokenAccountPrimitive, payload: unknown) {
36
+ const it = primitive.getPayload(0 as any, { output: { payload } } as any) as any;
37
+ const step = it.next();
38
+ expect(step.done).toBe(true);
39
+ return step.value;
40
+ }
41
+
42
+ const balancePayload = {
43
+ tokenAccount: TOKEN_ACCOUNT,
44
+ mint: MINT,
45
+ owner: OWNER,
46
+ amount: "1500000000",
47
+ decimals: 9,
48
+ slot: 11,
49
+ };
50
+
51
+ test("rejects a config with no mint, owner or tokenAccount", () => {
52
+ // Without a filter it would match every token balance on chain, which is never
53
+ // what was meant — so this fails at construction rather than flooding the STM.
54
+ expect(() =>
55
+ makePrimitive({ mint: undefined })
56
+ ).toThrow(/needs at least one of/);
57
+ });
58
+
59
+ test("accepts a config filtered by owner alone", () => {
60
+ expect(() => makePrimitive({ mint: undefined, owner: OWNER })).not.toThrow();
61
+ });
62
+
63
+ test("accepts a config filtered by tokenAccount alone", () => {
64
+ expect(() =>
65
+ makePrimitive({ mint: undefined, tokenAccount: TOKEN_ACCOUNT })
66
+ ).not.toThrow();
67
+ });
68
+
69
+ test("carries the raw u64 amount through as a string", () => {
70
+ // 2^63 - 1: a value that silently loses precision as a JS number, which is why
71
+ // the grammar types `amount` as a string.
72
+ const huge = "9223372036854775807";
73
+ const out = payloadOf(makePrimitive(), { ...balancePayload, amount: huge });
74
+ expect(out.data[0].accountingPayload.amount).toBe(huge);
75
+ expect(out.data[0].accountingPayload.decimals).toBe(9);
76
+ });
77
+
78
+ test("attributes the event to the owner", () => {
79
+ const out = payloadOf(makePrimitive(), balancePayload);
80
+ expect(out.data[0].fromAddressAndType.address).toBe(OWNER);
81
+ });
82
+
83
+ test("falls back to the token account when the RPC omitted the owner", () => {
84
+ // `owner` is optional in the RPC's token balance record. The balance is still
85
+ // valid state, so it is reported against the token account rather than dropped.
86
+ const out = payloadOf(makePrimitive(), { ...balancePayload, owner: undefined });
87
+ expect(out.data[0].fromAddressAndType.address).toBe(TOKEN_ACCOUNT);
88
+ expect(out.data[0].accountingPayload.owner).toBe("");
89
+ });
90
+
91
+ test("builds a state machine payload prefixed by stateMachinePrefix", () => {
92
+ const out = payloadOf(makePrimitive(), balancePayload);
93
+ expect(out.data[0].stateMachinePayload).not.toBeNull();
94
+ expect(out.data[0].stateMachinePayload[0]).toBe("solana-token-account");
95
+ });
96
+
97
+ test("emits no state machine payload when no prefix is configured", () => {
98
+ // The accounting row is still written; only STM delivery is skipped. This is the
99
+ // documented meaning of omitting the prefix.
100
+ const out = payloadOf(
101
+ makePrimitive({ stateMachinePrefix: undefined }),
102
+ balancePayload,
103
+ );
104
+ expect(out.data[0].stateMachinePayload).toBeNull();
105
+ expect(out.data[0].accountingPayload.mint).toBe(MINT);
106
+ });
107
+
108
+ test("getConfig round-trips the state machine prefix under both names", () => {
109
+ // Every other builtin emits only `scheduledPrefix`, which the Primitive
110
+ // constructor does not read — so a config round-tripped through getConfig() loses
111
+ // its STM routing. Emitting both makes this primitive survive that trip.
112
+ const config = makePrimitive().getConfig() as Record<string, unknown>;
113
+ expect(config.stateMachinePrefix).toBe("solana-token-account");
114
+ expect(config.scheduledPrefix).toBe("solana-token-account");
115
+ expect(config.type).toBe("SOLANA:TokenAccount");
116
+ expect(config.mint).toBe(MINT);
117
+ });
@@ -0,0 +1,156 @@
1
+ import type { StaticDecode } from "@sinclair/typebox";
2
+ import type {
3
+ ConfigSyncProtocolType,
4
+ FlattenSyncProtocolIOFor,
5
+ ProtocolPrimitiveMap,
6
+ } from "@effectstream/config";
7
+ import {
8
+ type AddressAndType,
9
+ AddressType,
10
+ type EffectstreamBlockNumber,
11
+ } from "@effectstream/utils";
12
+ import { type JsonObject, Primitive } from "@effectstream/sm";
13
+ import {
14
+ type CommandTuple,
15
+ generateRawStmInput,
16
+ type ParamToData,
17
+ } from "@effectstream/concise";
18
+ import type { StateUpdateStream } from "@effectstream/coroutine";
19
+ import { solanaTokenAccountGrammar } from "./solana-token-account-grammar.ts";
20
+ import { PrimitiveTypeSolanaTokenAccount } from "../builtin.ts";
21
+
22
+ /**
23
+ * Built-in primitive: tracks the SPL token balance of a watched token account per
24
+ * slot, derived from a transaction's `meta.postTokenBalances` by
25
+ * `SolanaFetcher.readPrimitives`.
26
+ *
27
+ * Narrowed by any combination of `mint`, `owner` and `tokenAccount`; at least one
28
+ * must be set. `tokenProgramId` optionally pins it to classic SPL Token or to
29
+ * Token-2022 rather than accepting both.
30
+ *
31
+ * KNOWN LIMITATION — this reports post-state balances only, matching
32
+ * SOLANA:AccountBalance. A token account that is *closed* appears in
33
+ * `preTokenBalances` and is absent from `postTokenBalances`, so closure produces no
34
+ * event rather than a zero one. Emitting a pre/post delta would cover it and is a
35
+ * deliberate non-goal here; see the Solana chain docs.
36
+ */
37
+ export class SolanaTokenAccountPrimitive extends Primitive<
38
+ ConfigSyncProtocolType.SOLANA_RPC_PARALLEL,
39
+ typeof solanaTokenAccountGrammar
40
+ > {
41
+ readonly internalTypeName = PrimitiveTypeSolanaTokenAccount;
42
+ override grammar = solanaTokenAccountGrammar;
43
+ readonly mint: string | undefined;
44
+ readonly owner: string | undefined;
45
+ readonly tokenAccount: string | undefined;
46
+ readonly tokenProgramId: string | undefined;
47
+
48
+ constructor(config: {
49
+ instanceName: string;
50
+ startBlockHeight: number;
51
+ mint?: string;
52
+ owner?: string;
53
+ tokenAccount?: string;
54
+ tokenProgramId?: string;
55
+ stateMachinePrefix: string | undefined;
56
+ }) {
57
+ super(config);
58
+ // Rejected here rather than in the fetcher because this is the earliest point
59
+ // it can be caught: an entry with no filter at all would match every token
60
+ // balance in every transaction, which is never what was meant.
61
+ if (
62
+ config.mint == null && config.owner == null && config.tokenAccount == null
63
+ ) {
64
+ throw new Error(
65
+ `[${PrimitiveTypeSolanaTokenAccount}] "${config.instanceName}" needs at least one of ` +
66
+ `mint, owner or tokenAccount. Without a filter it would match every token balance on chain.`,
67
+ );
68
+ }
69
+ this.mint = config.mint;
70
+ this.owner = config.owner;
71
+ this.tokenAccount = config.tokenAccount;
72
+ this.tokenProgramId = config.tokenProgramId;
73
+ }
74
+
75
+ override *getPayload(
76
+ _: EffectstreamBlockNumber,
77
+ primitiveTransactionData: FlattenSyncProtocolIOFor<
78
+ ConfigSyncProtocolType.SOLANA_RPC_PARALLEL
79
+ >,
80
+ ): StateUpdateStream<{
81
+ isBatched: boolean;
82
+ data: {
83
+ fromAddressAndType: AddressAndType;
84
+ stateMachinePayload:
85
+ | StaticDecode<CommandTuple<string, typeof solanaTokenAccountGrammar>>
86
+ | null;
87
+ accountingPayload: JsonObject;
88
+ }[];
89
+ }> {
90
+ const payload = primitiveTransactionData.output.payload as {
91
+ tokenAccount?: string;
92
+ mint?: string;
93
+ owner?: string;
94
+ amount?: string;
95
+ decimals?: number;
96
+ slot?: number;
97
+ };
98
+
99
+ const accountingPayload: ParamToData<typeof solanaTokenAccountGrammar> = {
100
+ tokenAccount: String(payload.tokenAccount ?? ""),
101
+ mint: String(payload.mint ?? this.mint ?? ""),
102
+ // `owner` is optional in the RPC's token balance record, so it can genuinely
103
+ // be absent. Empty string rather than a thrown error: the balance itself is
104
+ // still valid state, and the grammar requires a string.
105
+ owner: String(payload.owner ?? this.owner ?? ""),
106
+ amount: String(payload.amount ?? "0"),
107
+ decimals: Number(payload.decimals ?? 0),
108
+ slot: Number(payload.slot ?? 0),
109
+ };
110
+
111
+ const stateMachinePayload = this.stateMachinePrefix
112
+ ? generateRawStmInput(
113
+ this.grammar,
114
+ this.stateMachinePrefix,
115
+ accountingPayload,
116
+ )
117
+ : null;
118
+
119
+ return {
120
+ isBatched: false,
121
+ data: [
122
+ {
123
+ // The owner is the party whose holdings changed, so it is the meaningful
124
+ // actor. Falls back to the token account when the RPC omitted the owner.
125
+ fromAddressAndType: {
126
+ type: AddressType.SOLANA,
127
+ address: accountingPayload.owner || accountingPayload.tokenAccount,
128
+ },
129
+ accountingPayload,
130
+ stateMachinePayload,
131
+ },
132
+ ],
133
+ };
134
+ }
135
+
136
+ override getConfig(): ProtocolPrimitiveMap[
137
+ ConfigSyncProtocolType.SOLANA_RPC_PARALLEL
138
+ ] {
139
+ return {
140
+ name: this.instanceName,
141
+ type: this.internalTypeName,
142
+ startBlockHeight: this.startBlockHeight,
143
+ mint: this.mint,
144
+ owner: this.owner,
145
+ tokenAccount: this.tokenAccount,
146
+ tokenProgramId: this.tokenProgramId,
147
+ // Both names on purpose. Every other builtin emits only `scheduledPrefix`,
148
+ // which the `Primitive` constructor does not read — so a config round-tripped
149
+ // through getConfig() silently loses its state-machine routing. Emitting
150
+ // `stateMachinePrefix` too makes this primitive survive that trip, and
151
+ // `scheduledPrefix` stays for anything still reading the deprecated name.
152
+ stateMachinePrefix: this.stateMachinePrefix,
153
+ scheduledPrefix: this.stateMachinePrefix,
154
+ } as ProtocolPrimitiveMap[ConfigSyncProtocolType.SOLANA_RPC_PARALLEL];
155
+ }
156
+ }
@@ -1,8 +0,0 @@
1
- import { Type } from "@sinclair/typebox";
2
-
3
- export const midnightNullifierGrammar = [
4
- [
5
- "payload",
6
- Type.Any(),
7
- ],
8
- ] as const;