From a8a87762f4364dff462ed788c75abfc37998f640 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Wed, 15 Dec 2021 13:14:13 +0100 Subject: [PATCH] fix: revert #792, restore `events` array to tx responses (#907) --- .../abstract-transaction.schema.json | 8 +++ .../transaction-with-events.schema.json | 24 ------- docs/generated.d.ts | 14 ++-- docs/openapi.yaml | 2 +- src/api/controllers/db-controller.ts | 64 +++++++++---------- src/tests/api-tests.ts | 30 ++++++--- src/tests/microblocks-tests.ts | 7 +- 7 files changed, 67 insertions(+), 82 deletions(-) delete mode 100644 docs/entities/transactions/transaction-with-events.schema.json diff --git a/docs/entities/transactions/abstract-transaction.schema.json b/docs/entities/transactions/abstract-transaction.schema.json index fa57b1f2..03d4fa95 100644 --- a/docs/entities/transactions/abstract-transaction.schema.json +++ b/docs/entities/transactions/abstract-transaction.schema.json @@ -19,6 +19,7 @@ "canonical", "tx_status", "tx_result", + "events", "event_count", "parent_block_hash", "is_unanchored", @@ -128,6 +129,13 @@ "execution_cost_write_length": { "type": "integer", "description": "Execution cost write length." + }, + "events" : { + "type": "array", + "description": "List of transaction events", + "items": { + "$ref": "../transaction-events/transaction-event.schema.json" + } } } } diff --git a/docs/entities/transactions/transaction-with-events.schema.json b/docs/entities/transactions/transaction-with-events.schema.json deleted file mode 100644 index 25f813f6..00000000 --- a/docs/entities/transactions/transaction-with-events.schema.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "title": "TransactionWithEvents", - "description": "Describes all transaction types on Stacks 2.0 blockchain", - "allOf": [ - { - "$ref": "./transaction.schema.json" - }, - { - "additionalProperties": false, - "required": ["events"], - "properties": { - "events": { - "type": "array", - "description": "List of transaction events", - "items": { - "$ref": "../transaction-events/transaction-event.schema.json" - } - } - } - } - ] -} diff --git a/docs/generated.d.ts b/docs/generated.d.ts index a7e30404..eea2435b 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -235,7 +235,6 @@ export type SchemaMergeRootStub = | TransactionNotFound | TransactionStatus1 | TransactionType - | TransactionWithEvents | Transaction | InboundStxTransfer | RpcAddressBalanceNotificationParams @@ -487,6 +486,10 @@ export type AbstractTransaction = BaseTransaction & { * Execution cost write length. */ execution_cost_write_length: number; + /** + * List of transaction events + */ + events: TransactionEvent[]; }; export type PostConditionMode = "allow" | "deny"; /** @@ -767,15 +770,6 @@ export type TransactionStatus1 = "success" | "abort_by_response" | "abort_by_pos * String literal of all Stacks 2.0 transaction types */ export type TransactionType = "token_transfer" | "smart_contract" | "contract_call" | "poison_microblock" | "coinbase"; -/** - * Describes all transaction types on Stacks 2.0 blockchain - */ -export type TransactionWithEvents = Transaction & { - /** - * List of transaction events - */ - events: TransactionEvent[]; -}; export type RpcSubscriptionType = | "tx_update" | "address_tx_update" diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 14fa11f0..7c5c0692 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -371,7 +371,7 @@ paths: content: application/json: schema: - $ref: ./entities/transactions/transaction-with-events.schema.json + $ref: ./entities/transactions/transaction.schema.json example: $ref: ./entities/transactions/transaction-4-coinbase.example.json 404: diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 2ab140bb..733fa45a 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -28,7 +28,6 @@ import { SmartContractTransaction, SmartContractTransactionMetadata, TokenTransferTransactionMetadata, - TransactionWithEvents, Transaction, TransactionAnchorModeType, TransactionEvent, @@ -754,6 +753,7 @@ function parseDbAbstractTx(dbTx: DbTx, baseTx: BaseTransaction): AbstractTransac microblock_sequence: dbTx.microblock_sequence, microblock_canonical: dbTx.microblock_canonical, event_count: dbTx.event_count, + events: [], execution_cost_read_count: dbTx.execution_cost_read_count, execution_cost_read_length: dbTx.execution_cost_read_length, execution_cost_runtime: dbTx.execution_cost_runtime, @@ -819,7 +819,7 @@ export async function getMempoolTxsFromDataStore( async function getTxsFromDataStore( db: DataStore, args: GetTxsArgs | GetTxsWithEventsArgs -): Promise { +): Promise { // fetching all requested transactions from db const txQuery = await db.getTxListDetails({ txIds: args.txIds, @@ -831,8 +831,10 @@ async function getTxsFromDataStore( return []; } - let events: DbEvent[] = []; + // parsing txQuery + const parsedTxs = txQuery.map(tx => parseDbTx(tx)); + // incase transaction events are requested if ('eventLimit' in args) { const txIdsAndIndexHash = txQuery.map(tx => { return { @@ -840,39 +842,30 @@ async function getTxsFromDataStore( indexBlockHash: tx.index_block_hash, }; }); - events = ( - await db.getTxListEvents({ - txs: txIdsAndIndexHash, - limit: args.eventLimit, - offset: args.eventOffset, - }) - ).results; - } - - // parsing txQuery - const parsedTxs = txQuery.map(tx => parseDbTx(tx)); - - // incase transaction events are requested - if ('eventLimit' in args) { - // this will insert all events in a single parsedTransaction. Only specific ones are to be added. - const txsWithEvents: TransactionWithEvents[] = parsedTxs.map(ptx => { - return { ...ptx, events: [] }; + const txListEvents = await db.getTxListEvents({ + txs: txIdsAndIndexHash, + limit: args.eventLimit, + offset: args.eventOffset, }); - txsWithEvents.forEach( - ptx => - (ptx.events = events + // this will insert all events in a single parsedTransaction. Only specific ones are to be added. + const txsWithEvents: Transaction[] = parsedTxs.map(ptx => { + return { + ...ptx, + events: txListEvents.results .filter(event => event.tx_id === ptx.tx_id) - .map(event => parseDbEvent(event))) - ); + .map(event => parseDbEvent(event)), + }; + }); return txsWithEvents; + } else { + return parsedTxs; } - return parsedTxs; } export async function getTxFromDataStore( db: DataStore, args: GetTxArgs | GetTxWithEventsArgs | GetTxFromDbTxArgs -): Promise> { +): Promise> { let dbTx: DbTx; if ('dbTx' in args) { dbTx = args.dbTx; @@ -888,20 +881,23 @@ export async function getTxFromDataStore( // If tx events are requested if ('eventLimit' in args) { - const txWithEvents: TransactionWithEvents = { ...parsedTx, events: [] }; const eventsQuery = await db.getTxEvents({ txId: args.txId, indexBlockHash: dbTx.index_block_hash, limit: args.eventLimit, offset: args.eventOffset, }); - txWithEvents.events = eventsQuery.results.map(event => parseDbEvent(event)); + const txWithEvents: Transaction = { + ...parsedTx, + events: eventsQuery.results.map(event => parseDbEvent(event)), + }; return { found: true, result: txWithEvents }; + } else { + return { + found: true, + result: parsedTx, + }; } - return { - found: true, - result: parsedTx, - }; } export async function searchTxs( @@ -965,7 +961,7 @@ export async function searchTxs( export async function searchTx( db: DataStore, args: GetTxArgs | GetTxWithEventsArgs -): Promise> { +): Promise> { // First, check the happy path: the tx is mined and in the canonical chain. const minedTxs = await getTxsFromDataStore(db, { ...args, txIds: [args.txId] }); const minedTx = minedTxs[0] ?? undefined; diff --git a/src/tests/api-tests.ts b/src/tests/api-tests.ts index 20ab9f86..90ff0139 100644 --- a/src/tests/api-tests.ts +++ b/src/tests/api-tests.ts @@ -2278,6 +2278,7 @@ describe('api tests', () => { microblock_sequence: 2147483647, microblock_canonical: true, event_count: 0, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -3221,6 +3222,7 @@ describe('api tests', () => { burn_block_time_iso: '1970-02-02T20:12:45.000Z', canonical: true, event_count: 0, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -3545,6 +3547,7 @@ describe('api tests', () => { amount: '35', memo: '0x6869', }, + events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -3631,6 +3634,7 @@ describe('api tests', () => { amount: '250', memo: '0x6869', }, + events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -3691,6 +3695,7 @@ describe('api tests', () => { amount: '100', memo: '0x6869', }, + events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -3774,6 +3779,7 @@ describe('api tests', () => { amount: '35', memo: '0x6869', }, + events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -3845,6 +3851,7 @@ describe('api tests', () => { amount: '35', memo: '0x6869', }, + events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -3931,6 +3938,7 @@ describe('api tests', () => { amount: '15', memo: '0x6869', }, + events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -4594,6 +4602,7 @@ describe('api tests', () => { memo: '0x6869', }, event_count: 0, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -4650,6 +4659,7 @@ describe('api tests', () => { ], }, event_count: 5, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -4690,6 +4700,7 @@ describe('api tests', () => { memo: '0x6869', }, event_count: 0, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -4730,6 +4741,7 @@ describe('api tests', () => { memo: '0x6869', }, event_count: 0, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -4800,6 +4812,7 @@ describe('api tests', () => { ], }, event_count: 5, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -4860,6 +4873,7 @@ describe('api tests', () => { '(define-public (test-contract-fn (amount uint) (desc string-ascii)))', }, event_count: 5, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -4936,6 +4950,7 @@ describe('api tests', () => { '(define-public (test-contract-fn (amount uint) (desc string-ascii)))', }, event_count: 5, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -5016,6 +5031,7 @@ describe('api tests', () => { ], }, event_count: 5, + events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -6891,12 +6907,11 @@ describe('api tests', () => { execution_cost_write_count: 0, execution_cost_write_length: 0, }; - const { events, ...excludedEvents } = expectedResp; const fetchTx = await supertest(api.server).get(`/extended/v1/tx/${dbTx.tx_id}`); expect(fetchTx.status).toBe(200); expect(fetchTx.type).toBe('application/json'); expect(JSON.parse(fetchTx.text)).toEqual(expectedResp); - expect(txQuery.result).toEqual(excludedEvents); + expect(txQuery.result).toEqual(expectedResp); }); test('tx store and processing', async () => { @@ -7104,8 +7119,7 @@ describe('api tests', () => { execution_cost_write_count: 0, execution_cost_write_length: 0, }; - const { events, ...excludedEvents } = expectedResp; - expect(txQuery.result).toEqual(excludedEvents); + expect(txQuery.result).toEqual(expectedResp); const fetchTx = await supertest(api.server).get(`/extended/v1/tx/${dbTx.tx_id}`); expect(fetchTx.status).toBe(200); @@ -7116,7 +7130,7 @@ describe('api tests', () => { limit: 96, offset: 0, total: 1, - results: [excludedEvents], + results: [expectedResp], }; const fetchTxList = await supertest(api.server).get(`/extended/v1/tx`); expect(fetchTxList.status).toBe(200); @@ -7240,8 +7254,7 @@ describe('api tests', () => { execution_cost_write_count: 0, execution_cost_write_length: 0, }; - const { events, ...excludedEvents } = expectedResp; - expect(txQuery.result).toEqual(excludedEvents); + expect(txQuery.result).toEqual(expectedResp); const fetchTx = await supertest(api.server).get(`/extended/v1/tx/${dbTx.tx_id}`); expect(fetchTx.status).toBe(200); @@ -7365,8 +7378,7 @@ describe('api tests', () => { execution_cost_write_count: 0, execution_cost_write_length: 0, }; - const { events, ...excludedEvents } = expectedResp; - expect(txQuery.result).toEqual(excludedEvents); + expect(txQuery.result).toEqual(expectedResp); const fetchTx = await supertest(api.server).get(`/extended/v1/tx/${dbTx.tx_id}`); expect(fetchTx.status).toBe(200); diff --git a/src/tests/microblocks-tests.ts b/src/tests/microblocks-tests.ts index fb0ae71b..166b06aa 100644 --- a/src/tests/microblocks-tests.ts +++ b/src/tests/microblocks-tests.ts @@ -34,7 +34,6 @@ import { MicroblockListResponse, Transaction, TransactionResults, - TransactionWithEvents, } from '@stacks/stacks-blockchain-api-types'; import { useWithCleanup } from './test-helpers'; import { startEventServer } from '../event-stream/event-server'; @@ -160,7 +159,7 @@ describe('microblock tests', () => { } } const txResult2 = await supertest(api.server).get(`/extended/v1/tx/${lostTx}`); - const { body: txBody }: { body: TransactionWithEvents } = txResult2; + const { body: txBody }: { body: Transaction } = txResult2; expect(txBody.canonical).toBe(true); expect(txBody.microblock_canonical).toBe(true); expect(txBody.tx_id).toBe(lostTx); @@ -226,7 +225,7 @@ describe('microblock tests', () => { } } const txResult2 = await supertest(api.server).get(`/extended/v1/tx/${lostTx}`); - const { body: txBody }: { body: TransactionWithEvents } = txResult2; + const { body: txBody }: { body: Transaction } = txResult2; expect(txBody.canonical).toBe(true); expect(txBody.microblock_canonical).toBe(true); expect(txBody.tx_id).toBe(lostTx); @@ -603,7 +602,7 @@ describe('microblock tests', () => { const txResult2 = await supertest(api.server).get( `/extended/v1/tx/${mbTx1.tx_id}?unanchored` ); - const { body: txBody2 }: { body: TransactionWithEvents } = txResult2; + const { body: txBody2 }: { body: Transaction } = txResult2; expect(txBody2.tx_id).toBe(mbTx1.tx_id); expect(txBody2.tx_status).toBe('success'); expect(txBody2.events).toHaveLength(1);