@o1-labs/mina-archive-node-graphql 0.0.6

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 (138) hide show
  1. package/README.md +321 -0
  2. package/build/benchmark/setup.js +32 -0
  3. package/build/benchmark/setup.js.map +1 -0
  4. package/build/src/blockchain/constants.js +2 -0
  5. package/build/src/blockchain/constants.js.map +1 -0
  6. package/build/src/blockchain/types.js +7 -0
  7. package/build/src/blockchain/types.js.map +1 -0
  8. package/build/src/blockchain/utils.js +39 -0
  9. package/build/src/blockchain/utils.js.map +1 -0
  10. package/build/src/consensus/mina-consensus.js +59 -0
  11. package/build/src/consensus/mina-consensus.js.map +1 -0
  12. package/build/src/context.js +10 -0
  13. package/build/src/context.js.map +1 -0
  14. package/build/src/db/archive-node-adapter/archive-node-adapter.interface.js +2 -0
  15. package/build/src/db/archive-node-adapter/archive-node-adapter.interface.js.map +1 -0
  16. package/build/src/db/archive-node-adapter/archive-node-adapter.js +47 -0
  17. package/build/src/db/archive-node-adapter/archive-node-adapter.js.map +1 -0
  18. package/build/src/db/sql/events-actions/queries.js +438 -0
  19. package/build/src/db/sql/events-actions/queries.js.map +1 -0
  20. package/build/src/db/sql/events-actions/types.js +2 -0
  21. package/build/src/db/sql/events-actions/types.js.map +1 -0
  22. package/build/src/errors/error.js +17 -0
  23. package/build/src/errors/error.js.map +1 -0
  24. package/build/src/index.js +27 -0
  25. package/build/src/index.js.map +1 -0
  26. package/build/src/resolvers-types.js +8 -0
  27. package/build/src/resolvers-types.js.map +1 -0
  28. package/build/src/resolvers.js +67 -0
  29. package/build/src/resolvers.js.map +1 -0
  30. package/build/src/server/plugins.js +39 -0
  31. package/build/src/server/plugins.js.map +1 -0
  32. package/build/src/server/server.js +25 -0
  33. package/build/src/server/server.js.map +1 -0
  34. package/build/src/services/actions-service/actions-service.interface.js +2 -0
  35. package/build/src/services/actions-service/actions-service.interface.js.map +1 -0
  36. package/build/src/services/actions-service/actions-service.js +94 -0
  37. package/build/src/services/actions-service/actions-service.js.map +1 -0
  38. package/build/src/services/blocks-service/blocks-service.interface.js +2 -0
  39. package/build/src/services/blocks-service/blocks-service.interface.js.map +1 -0
  40. package/build/src/services/blocks-service/blocks-service.js +263 -0
  41. package/build/src/services/blocks-service/blocks-service.js.map +1 -0
  42. package/build/src/services/data-adapters/database-row-adapters.js +116 -0
  43. package/build/src/services/data-adapters/database-row-adapters.js.map +1 -0
  44. package/build/src/services/events-service/events-service.interface.js +2 -0
  45. package/build/src/services/events-service/events-service.interface.js.map +1 -0
  46. package/build/src/services/events-service/events-service.js +64 -0
  47. package/build/src/services/events-service/events-service.js.map +1 -0
  48. package/build/src/services/network-service/network-service.interface.js +2 -0
  49. package/build/src/services/network-service/network-service.interface.js.map +1 -0
  50. package/build/src/services/network-service/network-service.js +31 -0
  51. package/build/src/services/network-service/network-service.js.map +1 -0
  52. package/build/src/tracing/jaeger-setup.js +39 -0
  53. package/build/src/tracing/jaeger-setup.js.map +1 -0
  54. package/build/src/tracing/jaeger-tracing.js +29 -0
  55. package/build/src/tracing/jaeger-tracing.js.map +1 -0
  56. package/build/src/tracing/tracer.js +31 -0
  57. package/build/src/tracing/tracer.js.map +1 -0
  58. package/build/tests/__mocks__/generate_mock_data.js +13 -0
  59. package/build/tests/__mocks__/generate_mock_data.js.map +1 -0
  60. package/build/tests/consensus/run-compare.js +40 -0
  61. package/build/tests/consensus/run-compare.js.map +1 -0
  62. package/build/tests/consensus/select-consensus-precomputed.js +80 -0
  63. package/build/tests/consensus/select-consensus-precomputed.js.map +1 -0
  64. package/build/tests/consensus/types.js +15 -0
  65. package/build/tests/consensus/types.js.map +1 -0
  66. package/build/tests/devnet-dump/devnet-dump.test.js +311 -0
  67. package/build/tests/devnet-dump/devnet-dump.test.js.map +1 -0
  68. package/build/tests/devnet-dump/setup.js +58 -0
  69. package/build/tests/devnet-dump/setup.js.map +1 -0
  70. package/build/tests/integration/integration.test.js +226 -0
  71. package/build/tests/integration/integration.test.js.map +1 -0
  72. package/build/tests/integration/setup.js +82 -0
  73. package/build/tests/integration/setup.js.map +1 -0
  74. package/build/tests/live-api/actions.test.js +4 -0
  75. package/build/tests/live-api/actions.test.js.map +1 -0
  76. package/build/tests/live-api/blocks.test.js +116 -0
  77. package/build/tests/live-api/blocks.test.js.map +1 -0
  78. package/build/tests/live-api/events.test.js +97 -0
  79. package/build/tests/live-api/events.test.js.map +1 -0
  80. package/build/tests/live-api/networkState.test.js +27 -0
  81. package/build/tests/live-api/networkState.test.js.map +1 -0
  82. package/build/tests/live-network/live-network.test.js +144 -0
  83. package/build/tests/live-network/live-network.test.js.map +1 -0
  84. package/build/tests/live-network/setup.js +206 -0
  85. package/build/tests/live-network/setup.js.map +1 -0
  86. package/build/tests/resolvers.test.js +475 -0
  87. package/build/tests/resolvers.test.js.map +1 -0
  88. package/build/tests/services/actions-service/actions-service.test.js +124 -0
  89. package/build/tests/services/actions-service/actions-service.test.js.map +1 -0
  90. package/build/tests/services/blocks-service/blocks-service.test.js +348 -0
  91. package/build/tests/services/blocks-service/blocks-service.test.js.map +1 -0
  92. package/build/tests/services/events-service/events-service.test.js +185 -0
  93. package/build/tests/services/events-service/events-service.test.js.map +1 -0
  94. package/build/tests/test-helpers.js +11 -0
  95. package/build/tests/test-helpers.js.map +1 -0
  96. package/build/tests/unit/blockchain-utils.test.js +106 -0
  97. package/build/tests/unit/blockchain-utils.test.js.map +1 -0
  98. package/build/tests/unit/consensus.test.js +154 -0
  99. package/build/tests/unit/consensus.test.js.map +1 -0
  100. package/build/tests/unit/error-handling.test.js +52 -0
  101. package/build/tests/unit/error-handling.test.js.map +1 -0
  102. package/build/tests/utils.test.js +313 -0
  103. package/build/tests/utils.test.js.map +1 -0
  104. package/build/zkapp/contract.js +144 -0
  105. package/build/zkapp/contract.js.map +1 -0
  106. package/build/zkapp/utils.js +174 -0
  107. package/build/zkapp/utils.js.map +1 -0
  108. package/package.json +85 -0
  109. package/schema.graphql +221 -0
  110. package/src/blockchain/constants.ts +2 -0
  111. package/src/blockchain/types.ts +121 -0
  112. package/src/blockchain/utils.ts +54 -0
  113. package/src/consensus/mina-consensus.ts +137 -0
  114. package/src/context.ts +18 -0
  115. package/src/db/archive-node-adapter/archive-node-adapter.interface.ts +23 -0
  116. package/src/db/archive-node-adapter/archive-node-adapter.ts +101 -0
  117. package/src/db/sql/events-actions/queries.ts +490 -0
  118. package/src/db/sql/events-actions/types.ts +208 -0
  119. package/src/envionment.d.ts +18 -0
  120. package/src/errors/error.ts +20 -0
  121. package/src/index.ts +31 -0
  122. package/src/resolvers-types.ts +754 -0
  123. package/src/resolvers.ts +102 -0
  124. package/src/server/plugins.ts +56 -0
  125. package/src/server/server.ts +30 -0
  126. package/src/services/actions-service/actions-service.interface.ts +9 -0
  127. package/src/services/actions-service/actions-service.ts +195 -0
  128. package/src/services/blocks-service/blocks-service.interface.ts +11 -0
  129. package/src/services/blocks-service/blocks-service.ts +407 -0
  130. package/src/services/data-adapters/database-row-adapters.ts +261 -0
  131. package/src/services/events-service/events-service.interface.ts +6 -0
  132. package/src/services/events-service/events-service.ts +118 -0
  133. package/src/services/network-service/network-service.interface.ts +5 -0
  134. package/src/services/network-service/network-service.ts +53 -0
  135. package/src/tracing/jaeger-setup.ts +65 -0
  136. package/src/tracing/jaeger-tracing.ts +44 -0
  137. package/src/tracing/tracer.ts +52 -0
  138. package/tsconfig.json +104 -0
@@ -0,0 +1,102 @@
1
+ import { makeExecutableSchema } from '@graphql-tools/schema';
2
+ import { Resolvers } from './resolvers-types.js';
3
+ import { visit, print, parse } from 'graphql';
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import {
8
+ TracingState,
9
+ setSpanNameFromGraphQLContext,
10
+ } from './tracing/tracer.js';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+ const schemaPath = path.resolve(__dirname, '../../schema.graphql');
15
+
16
+ const fullResolvers: Resolvers = {
17
+ Query: {
18
+ events: async (_, { input }, context) => {
19
+ const graphQLSpan = setSpanNameFromGraphQLContext(
20
+ context,
21
+ 'events.graphql'
22
+ );
23
+ return context.db_client.getEvents(input, {
24
+ tracingState: new TracingState(graphQLSpan),
25
+ });
26
+ },
27
+ actions: async (_, { input }, context) => {
28
+ const graphQLSpan = setSpanNameFromGraphQLContext(
29
+ context,
30
+ 'actions.graphql'
31
+ );
32
+ return context.db_client.getActions(input, {
33
+ tracingState: new TracingState(graphQLSpan),
34
+ });
35
+ },
36
+ networkState: async (_, __, context) => {
37
+ const graphQLSpan = setSpanNameFromGraphQLContext(
38
+ context,
39
+ 'networkState.graphql'
40
+ );
41
+ return context.db_client.getNetworkState({
42
+ tracingState: new TracingState(graphQLSpan),
43
+ });
44
+ },
45
+ blocks: async (_, { query, limit, sortBy }, context) => {
46
+ const graphQLSpan = setSpanNameFromGraphQLContext(
47
+ context,
48
+ 'blocks.graphql'
49
+ );
50
+ return context.db_client.getBlocks(query, limit, sortBy, {
51
+ tracingState: new TracingState(graphQLSpan),
52
+ });
53
+ },
54
+ },
55
+ };
56
+
57
+ let resolvers: Resolvers = fullResolvers;
58
+ let typeDefs: string | undefined = undefined;
59
+
60
+ // If the ENABLED_QUERIES environment variable is set, filter the schema and resolvers.
61
+ if (process.env.ENABLED_QUERIES !== undefined) {
62
+ const enabledQueries = process.env.ENABLED_QUERIES.split(',').map((q) =>
63
+ q.trim()
64
+ );
65
+
66
+ // If the list is not empty, filter the resolvers.
67
+ if (enabledQueries.length > 0) {
68
+ resolvers = {
69
+ Query: Object.fromEntries(
70
+ Object.entries(fullResolvers.Query || {}).filter(([queryName]) =>
71
+ enabledQueries.includes(queryName)
72
+ )
73
+ ),
74
+ };
75
+
76
+ // Filter the schema AST.
77
+ const typeDefsString = fs.readFileSync(schemaPath, 'utf-8');
78
+ const typeDefsAst = parse(typeDefsString);
79
+ const modifiedAst = visit(typeDefsAst, {
80
+ ObjectTypeDefinition(node) {
81
+ if (node.name.value === 'Query') {
82
+ return {
83
+ ...node,
84
+ fields: node.fields?.filter((field) =>
85
+ enabledQueries.includes(field.name.value)
86
+ ),
87
+ };
88
+ }
89
+ return node;
90
+ },
91
+ });
92
+ typeDefs = print(modifiedAst);
93
+ }
94
+ }
95
+
96
+ // Create the executable schema.
97
+ const schema = makeExecutableSchema({
98
+ resolvers: [resolvers],
99
+ typeDefs: typeDefs || fs.readFileSync(schemaPath, 'utf-8'),
100
+ });
101
+
102
+ export { resolvers, schema };
@@ -0,0 +1,56 @@
1
+ import { useLogger } from '@envelop/core';
2
+ import { useGraphQlJit } from '@envelop/graphql-jit';
3
+ import { useDisableIntrospection } from '@envelop/disable-introspection';
4
+ import { useOpenTelemetry } from '@envelop/opentelemetry';
5
+ import { inspect } from 'node:util';
6
+
7
+ import { initJaegerProvider } from '../tracing/jaeger-tracing.js';
8
+
9
+ export { buildPlugins };
10
+
11
+ async function buildPlugins() {
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ const plugins: any[] = [];
14
+ plugins.push(useGraphQlJit());
15
+
16
+ if (process.env.ENABLE_LOGGING) {
17
+ const provider = await initJaegerProvider();
18
+ plugins.push(
19
+ useOpenTelemetry(
20
+ {
21
+ resolvers: true, // Tracks resolvers calls, and tracks resolvers thrown errors
22
+ variables: true, // Includes the operation variables values as part of the metadata collected
23
+ result: true, // Includes execution result object as part of the metadata collected
24
+ },
25
+ provider
26
+ )
27
+ );
28
+ }
29
+
30
+ if (!process.env.ENABLE_INTROSPECTION) {
31
+ plugins.push(useDisableIntrospection());
32
+ }
33
+
34
+ plugins.push(
35
+ useLogger({
36
+ logFn: (eventName, args) => {
37
+ if (args?.result?.errors) {
38
+ console.debug(
39
+ eventName,
40
+ inspect(args.args.contextValue.params, {
41
+ showHidden: false,
42
+ depth: null,
43
+ colors: true,
44
+ }),
45
+ inspect(args.result.errors, {
46
+ showHidden: false,
47
+ depth: null,
48
+ colors: true,
49
+ })
50
+ );
51
+ }
52
+ },
53
+ })
54
+ );
55
+ return plugins;
56
+ }
@@ -0,0 +1,30 @@
1
+ import { createYoga, LogLevel } from 'graphql-yoga';
2
+ import { createServer } from 'http';
3
+ import { Plugin } from '@envelop/core';
4
+ import { schema } from '../resolvers.js';
5
+ import type { GraphQLContext } from '../context.js';
6
+
7
+ export { BLOCK_RANGE_SIZE, ENABLE_BLOCK_TRANSACTION_DETAILS, buildServer };
8
+
9
+ const LOG_LEVEL = (process.env.LOG_LEVEL as LogLevel) || 'info';
10
+ const BLOCK_RANGE_SIZE = Number(process.env.BLOCK_RANGE_SIZE) || 10000;
11
+ const ENABLE_BLOCK_TRANSACTION_DETAILS =
12
+ process.env.ENABLE_BLOCK_TRANSACTION_DETAILS === 'true';
13
+
14
+ function buildServer(context: GraphQLContext, plugins: Plugin[]) {
15
+ const yoga = createYoga<GraphQLContext>({
16
+ schema,
17
+ logging: LOG_LEVEL,
18
+ graphqlEndpoint: '/',
19
+ landingPage: false,
20
+ healthCheckEndpoint: '/healthcheck',
21
+ graphiql: process.env.ENABLE_GRAPHIQL === 'true' ? true : false,
22
+ plugins,
23
+ cors: {
24
+ origin: process.env.CORS_ORIGIN ?? '*',
25
+ methods: ['GET', 'POST'],
26
+ },
27
+ context,
28
+ });
29
+ return createServer(yoga);
30
+ }
@@ -0,0 +1,9 @@
1
+ import { Actions } from '../../blockchain/types.js';
2
+ import { ActionFilterOptionsInput } from '../../resolvers-types.js';
3
+
4
+ export interface IActionsService {
5
+ getActions(
6
+ input: ActionFilterOptionsInput,
7
+ options: unknown
8
+ ): Promise<Actions>;
9
+ }
@@ -0,0 +1,195 @@
1
+ import type postgres from 'postgres';
2
+
3
+ import {
4
+ BlockStatusFilter,
5
+ BlocksWithTransactionsMap,
6
+ FieldElementIdWithValueMap,
7
+ Action,
8
+ Actions,
9
+ } from '../../blockchain/types.js';
10
+ import type { ActionFilterOptionsInput } from '../../resolvers-types.js';
11
+ import { DEFAULT_TOKEN_ID } from '../../blockchain/constants.js';
12
+ import { createBlockInfo } from '../../blockchain/utils.js';
13
+ import {
14
+ getActionsQuery,
15
+ checkActionState,
16
+ } from '../../db/sql/events-actions/queries.js';
17
+ import {
18
+ partitionBlocks,
19
+ getElementIdFieldValues,
20
+ mapActionOrEvent,
21
+ removeRedundantEmittedFields,
22
+ sortAndFilterBlocks,
23
+ } from '../data-adapters/database-row-adapters.js';
24
+ import { IActionsService } from './actions-service.interface.js';
25
+ import {
26
+ TracingState,
27
+ extractTraceStateFromOptions,
28
+ } from '../../tracing/tracer.js';
29
+ import {
30
+ throwActionStateError,
31
+ throwBlockRangeError,
32
+ } from '../../errors/error.js';
33
+ import { BLOCK_RANGE_SIZE } from '../../server/server.js';
34
+
35
+ export { ActionsService };
36
+
37
+ class ActionsService implements IActionsService {
38
+ private readonly client: postgres.Sql;
39
+
40
+ constructor(client: postgres.Sql) {
41
+ this.client = client;
42
+ }
43
+
44
+ async getActions(
45
+ input: ActionFilterOptionsInput,
46
+ options: unknown
47
+ ): Promise<Actions> {
48
+ const tracingState = extractTraceStateFromOptions(options);
49
+ return (await this.getActionData(input, { tracingState })) ?? [];
50
+ }
51
+
52
+ async getActionData(
53
+ input: ActionFilterOptionsInput,
54
+ { tracingState }: { tracingState: TracingState }
55
+ ): Promise<Actions> {
56
+ const sqlSpan = tracingState.startSpan('actions.SQL');
57
+ const rows = await this.executeActionsQuery(input);
58
+
59
+ sqlSpan.end();
60
+
61
+ const processingSpan = tracingState.startSpan('actions.processing');
62
+ const elementIdFieldValues = getElementIdFieldValues(rows);
63
+ const blocksWithTransactions = partitionBlocks(rows);
64
+ const actionsData = this.blocksToActions(
65
+ blocksWithTransactions,
66
+ elementIdFieldValues
67
+ );
68
+ sortAndFilterBlocks(actionsData);
69
+ processingSpan.end();
70
+ return actionsData;
71
+ }
72
+
73
+ async executeActionsQuery(input: ActionFilterOptionsInput) {
74
+ const { address, to, from, endActionState, fromActionState } = input;
75
+
76
+ // Check if action states exist.
77
+ if (fromActionState) {
78
+ const fromActionStateExists = await checkActionState(
79
+ this.client,
80
+ fromActionState
81
+ );
82
+ if (!fromActionStateExists || !fromActionStateExists.length) {
83
+ throwActionStateError(
84
+ `fromActionState ${fromActionState} does not exist`
85
+ );
86
+ }
87
+ }
88
+ if (endActionState) {
89
+ const endActionStateExists = await checkActionState(
90
+ this.client,
91
+ endActionState
92
+ );
93
+ if (!endActionStateExists || !endActionStateExists.length) {
94
+ throwActionStateError(
95
+ `endActionState ${endActionState} does not exist`
96
+ );
97
+ }
98
+ }
99
+ let { tokenId, status } = input;
100
+
101
+ tokenId ||= DEFAULT_TOKEN_ID;
102
+ status ||= BlockStatusFilter.all;
103
+ if (to && from && to < from) {
104
+ throwBlockRangeError('to must be greater than from');
105
+ }
106
+ if (to && from && to - from > BLOCK_RANGE_SIZE) {
107
+ throwBlockRangeError(
108
+ `The block range is too large. The maximum range is ${BLOCK_RANGE_SIZE}`
109
+ );
110
+ }
111
+
112
+ return getActionsQuery(
113
+ this.client,
114
+ address,
115
+ tokenId,
116
+ status,
117
+ to?.toString(),
118
+ from?.toString(),
119
+ fromActionState?.toString(),
120
+ endActionState?.toString()
121
+ );
122
+ }
123
+
124
+ blocksToActions(
125
+ blocksWithTransactions: BlocksWithTransactionsMap,
126
+ elementIdFieldValues: FieldElementIdWithValueMap
127
+ ) {
128
+ const actions: Actions = [];
129
+ const blockTransactionEntries = Array.from(
130
+ blocksWithTransactions.entries()
131
+ );
132
+ for (let i = 0; i < blockTransactionEntries.length; i++) {
133
+ const transactions = blockTransactionEntries[i][1];
134
+ const transaction = transactions.values().next().value![0];
135
+ const blockInfo = createBlockInfo(transaction);
136
+ const {
137
+ action_state_value1,
138
+ action_state_value2,
139
+ action_state_value3,
140
+ action_state_value4,
141
+ action_state_value5,
142
+ } = transaction;
143
+
144
+ const actionsData: Action[][] = [];
145
+ for (const [, transaction] of transactions) {
146
+ const filteredBlocks = removeRedundantEmittedFields(transaction);
147
+ const actionData = mapActionOrEvent(
148
+ 'action',
149
+ filteredBlocks,
150
+ elementIdFieldValues
151
+ ) as Action[];
152
+ actionsData.push(actionData);
153
+ }
154
+ actions.push({
155
+ blockInfo,
156
+ actionData: this.sortActions(actionsData.flat()),
157
+ actionState: {
158
+ /* eslint-disable */
159
+ actionStateOne: action_state_value1!,
160
+ actionStateTwo: action_state_value2!,
161
+ actionStateThree: action_state_value3!,
162
+ actionStateFour: action_state_value4!,
163
+ actionStateFive: action_state_value5!,
164
+ /* eslint-enable */
165
+ },
166
+ });
167
+ }
168
+ return actions;
169
+ }
170
+
171
+ sortActions(actions: Action[]): Action[] {
172
+ return actions.sort((a, b) => {
173
+ // Sort by sequence number
174
+ if (
175
+ a.transactionInfo.sequenceNumber !== b.transactionInfo.sequenceNumber
176
+ ) {
177
+ return (
178
+ a.transactionInfo.sequenceNumber - b.transactionInfo.sequenceNumber
179
+ );
180
+ }
181
+
182
+ // Sort by account update index within the transaction
183
+ const aAccountUpdateIndex =
184
+ a.transactionInfo.zkappAccountUpdateIds.indexOf(
185
+ Number(a.accountUpdateId)
186
+ );
187
+ const bAccountUpdateIndex =
188
+ b.transactionInfo.zkappAccountUpdateIds.indexOf(
189
+ Number(b.accountUpdateId)
190
+ );
191
+
192
+ return aAccountUpdateIndex - bAccountUpdateIndex;
193
+ });
194
+ }
195
+ }
@@ -0,0 +1,11 @@
1
+ import { Blocks } from '../../blockchain/types.js';
2
+ import { BlockQueryInput, BlockSortByInput } from '../../resolvers-types.js';
3
+
4
+ export interface IBlocksService {
5
+ getBlocks(
6
+ query: BlockQueryInput | null | undefined,
7
+ limit: number | null | undefined,
8
+ sortBy: BlockSortByInput | null | undefined,
9
+ options: unknown
10
+ ): Promise<Blocks>;
11
+ }