From 172e6a2123bec4366fd41258a0914a03ffa3e015 Mon Sep 17 00:00:00 2001 From: M Hassan Tariq <47666766+MHassanTariq@users.noreply.github.com> Date: Wed, 24 Nov 2021 14:49:08 +0500 Subject: [PATCH] fix: removed empty events array from response #668 --- .../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 | 30 ++++++++++++------- src/tests/api-tests.ts | 22 +++++--------- src/tests/microblocks-tests.ts | 7 +++-- 7 files changed, 66 insertions(+), 41 deletions(-) create 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 03d4fa95..fa57b1f2 100644 --- a/docs/entities/transactions/abstract-transaction.schema.json +++ b/docs/entities/transactions/abstract-transaction.schema.json @@ -19,7 +19,6 @@ "canonical", "tx_status", "tx_result", - "events", "event_count", "parent_block_hash", "is_unanchored", @@ -129,13 +128,6 @@ "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 new file mode 100644 index 00000000..25f813f6 --- /dev/null +++ b/docs/entities/transactions/transaction-with-events.schema.json @@ -0,0 +1,24 @@ +{ + "$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 0b65c1b4..05777e16 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -233,6 +233,7 @@ export type SchemaMergeRootStub = | TransactionNotFound | TransactionStatus1 | TransactionType + | TransactionWithEvents | Transaction | InboundStxTransfer | RpcAddressBalanceNotificationParams @@ -484,10 +485,6 @@ export type AbstractTransaction = BaseTransaction & { * Execution cost write length. */ execution_cost_write_length: number; - /** - * List of transaction events - */ - events: TransactionEvent[]; }; export type PostConditionMode = "allow" | "deny"; /** @@ -768,6 +765,15 @@ 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 40fac726..748030e4 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -305,7 +305,7 @@ paths: content: application/json: schema: - $ref: ./entities/transactions/transaction.schema.json + $ref: ./entities/transactions/transaction-with-events.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 c4b459a1..6387d3be 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -27,6 +27,7 @@ import { SmartContractTransaction, SmartContractTransactionMetadata, TokenTransferTransactionMetadata, + TransactionWithEvents, Transaction, TransactionAnchorModeType, TransactionEvent, @@ -168,11 +169,14 @@ export function getTxStatus(txStatus: DbTxStatus | string): string { } } -type HasEventTransaction = SmartContractTransaction | ContractCallTransaction; +type EventTypeString = + | 'smart_contract_log' + | 'stx_asset' + | 'fungible_token_asset' + | 'non_fungible_token_asset' + | 'stx_lock'; -export function getEventTypeString( - eventTypeId: DbEventTypeId -): ElementType>['event_type'] { +export function getEventTypeString(eventTypeId: DbEventTypeId): EventTypeString { switch (eventTypeId) { case DbEventTypeId.SmartContractLog: return 'smart_contract_log'; @@ -734,7 +738,6 @@ 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, @@ -813,7 +816,7 @@ export async function getMempoolTxsFromDataStore( export async function getTxsFromDataStore( db: DataStore, args: GetTxsArgs | GetTxsWithEventsArgs -): Promise { +): Promise { // fetching all requested transactions from db const txQuery = await db.getTxListDetails({ txIds: args.txIds, @@ -861,12 +864,16 @@ export async function getTxsFromDataStore( // 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. - parsedTxs.forEach( + const txsWithEvents: TransactionWithEvents[] = parsedTxs.map(ptx => { + return { ...ptx, events: [] }; + }); + txsWithEvents.forEach( ptx => (ptx.events = events .filter(event => event.tx_id === ptx.tx_id) .map(event => parseDbEvent(event))) ); + return txsWithEvents; } return parsedTxs; } @@ -874,7 +881,7 @@ export async function getTxsFromDataStore( export async function getTxFromDataStore( db: DataStore, args: GetTxArgs | GetTxWithEventsArgs | GetTxFromDbTxArgs -): Promise> { +): Promise> { let dbTx: DbTx; if ('dbTx' in args) { dbTx = args.dbTx; @@ -902,15 +909,16 @@ 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, }); - parsedTx.events = eventsQuery.results.map(event => parseDbEvent(event)); + txWithEvents.events = eventsQuery.results.map(event => parseDbEvent(event)); + return { found: true, result: txWithEvents }; } - return { found: true, result: parsedTx, @@ -1079,7 +1087,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 d672fbd2..3182d89d 100644 --- a/src/tests/api-tests.ts +++ b/src/tests/api-tests.ts @@ -2484,7 +2484,6 @@ describe('api tests', () => { amount: '35', memo: '0x6869', }, - events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -2565,7 +2564,6 @@ describe('api tests', () => { amount: '250', memo: '0x6869', }, - events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -2623,7 +2621,6 @@ describe('api tests', () => { amount: '100', memo: '0x6869', }, - events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -2704,7 +2701,6 @@ describe('api tests', () => { amount: '35', memo: '0x6869', }, - events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -2776,7 +2772,6 @@ describe('api tests', () => { amount: '35', memo: '0x6869', }, - events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -2857,7 +2852,6 @@ describe('api tests', () => { amount: '15', memo: '0x6869', }, - events: [], event_count: 0, execution_cost_read_count: 1, execution_cost_read_length: 2, @@ -3414,7 +3408,6 @@ describe('api tests', () => { memo: '0x6869', }, event_count: 0, - events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -3455,7 +3448,6 @@ describe('api tests', () => { memo: '0x6869', }, event_count: 0, - events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -3496,7 +3488,6 @@ describe('api tests', () => { memo: '0x6869', }, event_count: 0, - events: [], execution_cost_read_count: 0, execution_cost_read_length: 0, execution_cost_runtime: 0, @@ -3959,12 +3950,12 @@ describe('api tests', () => { execution_cost_write_count: 0, execution_cost_write_length: 0, }; - expect(txQuery.result).toEqual(expectedResp); - + 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); }); test('tx store and processing', async () => { @@ -4172,7 +4163,8 @@ describe('api tests', () => { execution_cost_write_count: 0, execution_cost_write_length: 0, }; - expect(txQuery.result).toEqual(expectedResp); + const { events, ...excludedEvents } = expectedResp; + expect(txQuery.result).toEqual(excludedEvents); const fetchTx = await supertest(api.server).get(`/extended/v1/tx/${dbTx.tx_id}`); expect(fetchTx.status).toBe(200); @@ -4296,7 +4288,8 @@ describe('api tests', () => { execution_cost_write_count: 0, execution_cost_write_length: 0, }; - expect(txQuery.result).toEqual(expectedResp); + const { events, ...excludedEvents } = expectedResp; + expect(txQuery.result).toEqual(excludedEvents); const fetchTx = await supertest(api.server).get(`/extended/v1/tx/${dbTx.tx_id}`); expect(fetchTx.status).toBe(200); @@ -4420,7 +4413,8 @@ describe('api tests', () => { execution_cost_write_count: 0, execution_cost_write_length: 0, }; - expect(txQuery.result).toEqual(expectedResp); + const { events, ...excludedEvents } = expectedResp; + expect(txQuery.result).toEqual(excludedEvents); 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 36a702d2..9bf46c1b 100644 --- a/src/tests/microblocks-tests.ts +++ b/src/tests/microblocks-tests.ts @@ -25,6 +25,7 @@ import { MicroblockListResponse, Transaction, TransactionResults, + TransactionWithEvents, } from '@stacks/stacks-blockchain-api-types'; import { useWithCleanup } from './test-helpers'; import { startEventServer } from '../event-stream/event-server'; @@ -149,7 +150,7 @@ describe('microblock tests', () => { } } const txResult2 = await supertest(api.server).get(`/extended/v1/tx/${lostTx}`); - const { body: txBody }: { body: Transaction } = txResult2; + const { body: txBody }: { body: TransactionWithEvents } = txResult2; expect(txBody.canonical).toBe(true); expect(txBody.microblock_canonical).toBe(true); expect(txBody.tx_id).toBe(lostTx); @@ -215,7 +216,7 @@ describe('microblock tests', () => { } } const txResult2 = await supertest(api.server).get(`/extended/v1/tx/${lostTx}`); - const { body: txBody }: { body: Transaction } = txResult2; + const { body: txBody }: { body: TransactionWithEvents } = txResult2; expect(txBody.canonical).toBe(true); expect(txBody.microblock_canonical).toBe(true); expect(txBody.tx_id).toBe(lostTx); @@ -440,7 +441,7 @@ describe('microblock tests', () => { const txResult2 = await supertest(api.server).get( `/extended/v1/tx/${mbTx1.tx_id}?unanchored` ); - const { body: txBody2 }: { body: Transaction } = txResult2; + const { body: txBody2 }: { body: TransactionWithEvents } = txResult2; expect(txBody2.tx_id).toBe(mbTx1.tx_id); expect(txBody2.tx_status).toBe('success'); expect(txBody2.events).toHaveLength(1);