diff --git a/src/blockchain/types.ts b/src/blockchain/types.ts index 7b6fa0b..c4c22c3 100644 --- a/src/blockchain/types.ts +++ b/src/blockchain/types.ts @@ -19,6 +19,7 @@ export type Event = { export type Action = { accountUpdateId: string; + eventElementId: string; transactionInfo: TransactionInfo; data: string[]; }; diff --git a/src/blockchain/utils.ts b/src/blockchain/utils.ts index e3de336..ca62fe5 100644 --- a/src/blockchain/utils.ts +++ b/src/blockchain/utils.ts @@ -42,11 +42,13 @@ export function createEvent( export function createAction( accountUpdateId: string, + eventElementId: string, data: string[], transactionInfo: TransactionInfo ): Action { return { accountUpdateId, + eventElementId, data, transactionInfo, }; diff --git a/src/db/sql/events-actions/queries.ts b/src/db/sql/events-actions/queries.ts index 73ca386..5b0823f 100644 --- a/src/db/sql/events-actions/queries.ts +++ b/src/db/sql/events-actions/queries.ts @@ -136,7 +136,8 @@ function emittedEventsCTE(db_client: postgres.Sql) { SELECT *, zke.id AS zkapp_event_id, - zke.element_ids AS zkapp_event_element_ids, + zkf.id AS zkapp_event_element_id, + zkfa.element_ids AS zkapp_event_element_ids, zkfa.id AS zkapp_event_array_id FROM emitted_zkapp_commands diff --git a/src/db/sql/events-actions/types.ts b/src/db/sql/events-actions/types.ts index 31f2ae6..cd225c3 100644 --- a/src/db/sql/events-actions/types.ts +++ b/src/db/sql/events-actions/types.ts @@ -45,6 +45,9 @@ export type ArchiveNodeDatabaseRow = { // Unique identifier for the zkapp account update. zkapp_account_update_id: number; + // Unique identifier for the event element within an account update. + zkapp_event_id: number; + // List of identifiers inside a zkapp account update. zkapp_account_updates_ids: number[]; diff --git a/src/services/actions-service/actions-service.ts b/src/services/actions-service/actions-service.ts index e12a937..e910502 100644 --- a/src/services/actions-service/actions-service.ts +++ b/src/services/actions-service/actions-service.ts @@ -121,7 +121,7 @@ class ActionsService implements IActionsService { ); for (let i = 0; i < blockTransactionEntries.length; i++) { const transactions = blockTransactionEntries[i][1]; - const transaction = transactions.values().next().value[0]; + const transaction = transactions.values().next().value![0]; const blockInfo = createBlockInfo(transaction); const { action_state_value1, @@ -169,14 +169,28 @@ class ActionsService implements IActionsService { ); } - // Sort by account update index if sequence number is the same - const aIndex = a.transactionInfo.zkappAccountUpdateIds.indexOf( - Number(a.accountUpdateId) + // Sort by account update index within the transaction + const aAccountUpdateIndex = + a.transactionInfo.zkappAccountUpdateIds.indexOf( + Number(a.accountUpdateId) + ); + const bAccountUpdateIndex = + b.transactionInfo.zkappAccountUpdateIds.indexOf( + Number(b.accountUpdateId) + ); + if (aAccountUpdateIndex !== bAccountUpdateIndex) { + return aAccountUpdateIndex - bAccountUpdateIndex; + } + + // Sort by element index within the account update + const aEventIndex = a.transactionInfo.zkappEventElementIds.indexOf( + Number(a.eventElementId) ); - const bIndex = b.transactionInfo.zkappAccountUpdateIds.indexOf( - Number(b.accountUpdateId) + const bEventIndex = b.transactionInfo.zkappEventElementIds.indexOf( + Number(b.eventElementId) ); - return aIndex - bIndex; + + return aEventIndex - bEventIndex; }); } } diff --git a/src/services/data-adapters/database-row-adapters.ts b/src/services/data-adapters/database-row-adapters.ts index e8100a1..2af4855 100644 --- a/src/services/data-adapters/database-row-adapters.ts +++ b/src/services/data-adapters/database-row-adapters.ts @@ -210,9 +210,10 @@ function mapActionOrEvent( const event = createEvent(elementIdToFieldValues, transactionInfo); data.push(event); } else { - const { zkapp_account_update_id } = rows[i]; + const { zkapp_account_update_id, zkapp_event_id } = rows[i]; const action = createAction( zkapp_account_update_id.toString(), + zkapp_event_id.toString(), elementIdToFieldValues, transactionInfo ); diff --git a/tests/resolvers.test.ts b/tests/resolvers.test.ts index 7b142c9..75bf00f 100644 --- a/tests/resolvers.test.ts +++ b/tests/resolvers.test.ts @@ -5,7 +5,7 @@ import { loadSchemaSync } from '@graphql-tools/load'; import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader'; import { buildHTTPExecutor } from '@graphql-tools/executor-http'; import { parse } from 'graphql'; -import { PrivateKey, Lightnet, Mina } from 'o1js'; +import { Lightnet, Mina } from 'o1js'; import { resolvers } from '../src/resolvers.js'; import { buildContext, GraphQLContext } from '../src/context.js'; import { @@ -201,7 +201,9 @@ describe('Query Resolvers', async () => { document: parse(`${eventsQuery}`), }); const events = results.data.events; + console.log(events); const lastEvent = events[events.length - 1]; + console.log(lastEvent); assert.strictEqual(lastEvent.eventData.length, 3); }); }); @@ -295,7 +297,7 @@ describe('Query Resolvers', async () => { for (const block of actions) { const actionData = block.actionData; for (const action of actionData) { - assert.ok(action.transactionInfo.sequenceNumber); + assert(typeof action.transactionInfo.sequenceNumber === 'number'); assert(action.transactionInfo.zkappAccountUpdateIds.length > 0); } } diff --git a/tests/services/actions-service/actions-service.test.ts b/tests/services/actions-service/actions-service.test.ts index 65fb635..d93bb65 100644 --- a/tests/services/actions-service/actions-service.test.ts +++ b/tests/services/actions-service/actions-service.test.ts @@ -85,6 +85,45 @@ describe('ActionsService', () => { assert.strictEqual(sortedActions[2].accountUpdateId, '2'); }); }); + describe('with actions with the same account update id', () => { + const accountUpdateId = '1'; + const zkappAccountUpdateIds = [1]; + describe('with actions with different event element ids', () => { + const zkappEventElementIds = [1, 3, 2]; + before(() => { + actions = [ + dummyAction({ + sequenceNumber, + accountUpdateId, + zkappAccountUpdateIds, + zkappEventElementIds, + eventElementId: '2', + }), + dummyAction({ + sequenceNumber, + accountUpdateId, + zkappAccountUpdateIds, + zkappEventElementIds, + eventElementId: '1', + }), + dummyAction({ + sequenceNumber, + accountUpdateId, + zkappAccountUpdateIds, + zkappEventElementIds, + eventElementId: '3', + }), + ]; + }); + + test('it sorts actions by their event element index', () => { + const sortedActions = actionsService.sortActions(actions); + assert.strictEqual(sortedActions[0].eventElementId, '1'); + assert.strictEqual(sortedActions[1].eventElementId, '3'); + assert.strictEqual(sortedActions[2].eventElementId, '2'); + }); + }); + }); }); }); }); @@ -92,19 +131,24 @@ describe('ActionsService', () => { function dummyAction({ sequenceNumber = 1, accountUpdateId = '1', + eventElementId = '1', zkappAccountUpdateIds = [1], + zkappEventElementIds = [1], }: { sequenceNumber?: number; accountUpdateId?: string; + eventElementId?: string; zkappAccountUpdateIds?: number[]; + zkappEventElementIds?: number[]; }): Action { return { - accountUpdateId: accountUpdateId, + accountUpdateId, + eventElementId, data: ['dummy'], transactionInfo: { sequenceNumber, zkappAccountUpdateIds, - zkappEventElementIds: [], + zkappEventElementIds, authorizationKind: 'dummy', hash: 'dummy', memo: 'dummy', diff --git a/tests/utils.test.ts b/tests/utils.test.ts index 4b0d93b..9bcf0ae 100644 --- a/tests/utils.test.ts +++ b/tests/utils.test.ts @@ -136,6 +136,7 @@ describe('utils', () => { { element_ids: [1, 2], zkapp_account_update_id: 123, + zkapp_event_id: 456, }, ];