Skip to content

Commit d308e46

Browse files
authored
fix: include address transactions with no stx transfers (#1887)
1 parent 786f5ea commit d308e46

File tree

2 files changed

+87
-35
lines changed

2 files changed

+87
-35
lines changed

src/datastore/pg-store-v2.ts

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -304,23 +304,32 @@ export class PgStoreV2 extends BasePgStoreModule {
304304
const offset = args.offset ?? 0;
305305

306306
const eventCond = sql`
307-
tx_id = stx_txs.tx_id
308-
AND index_block_hash = stx_txs.index_block_hash
309-
AND microblock_hash = stx_txs.microblock_hash
307+
tx_id = address_txs.tx_id
308+
AND index_block_hash = address_txs.index_block_hash
309+
AND microblock_hash = address_txs.microblock_hash
310310
`;
311311
const eventAcctCond = sql`
312312
${eventCond} AND (sender = ${args.address} OR recipient = ${args.address})
313313
`;
314314
const resultQuery = await sql<(AddressTransfersTxQueryResult & { count: number })[]>`
315-
WITH stx_txs AS (
316-
SELECT tx_id, index_block_hash, microblock_hash, (COUNT(*) OVER())::int AS count
317-
FROM principal_stx_txs
318-
WHERE principal = ${args.address}
319-
AND canonical = TRUE
320-
AND microblock_canonical = TRUE
321-
ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC
322-
LIMIT ${limit}
323-
OFFSET ${offset}
315+
WITH address_txs AS (
316+
(
317+
SELECT tx_id, index_block_hash, microblock_hash
318+
FROM principal_stx_txs
319+
WHERE principal = ${args.address}
320+
)
321+
UNION
322+
(
323+
SELECT tx_id, index_block_hash, microblock_hash
324+
FROM ft_events
325+
WHERE sender = ${args.address} OR recipient = ${args.address}
326+
)
327+
UNION
328+
(
329+
SELECT tx_id, index_block_hash, microblock_hash
330+
FROM nft_events
331+
WHERE sender = ${args.address} OR recipient = ${args.address}
332+
)
324333
)
325334
SELECT
326335
${sql(TX_COLUMNS)},
@@ -370,9 +379,13 @@ export class PgStoreV2 extends BasePgStoreModule {
370379
SELECT COUNT(*)::int FROM nft_events
371380
WHERE ${eventAcctCond} AND asset_event_type_id = ${DbAssetEventTypeId.Burn}
372381
) AS nft_burn,
373-
count
374-
FROM stx_txs
382+
(COUNT(*) OVER())::int AS count
383+
FROM address_txs
375384
INNER JOIN txs USING (tx_id, index_block_hash, microblock_hash)
385+
WHERE canonical = TRUE AND microblock_canonical = TRUE
386+
ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC
387+
LIMIT ${limit}
388+
OFFSET ${offset}
376389
`;
377390
const total = resultQuery.length > 0 ? resultQuery[0].count : 0;
378391
const parsed = resultQuery.map(r => parseAccountTransferSummaryTxQueryResult(r));

src/tests/address-tests.ts

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ describe('address tests', () => {
6969
const testAddr2 = 'ST1HB64MAJ1MBV4CQ80GF01DZS4T1DSMX20ADCRA4';
7070
const testContractAddr = 'ST27W5M8BRKA7C5MZE2R1S1F4XTPHFWFRNHA9M04Y.hello-world';
7171
const testAddr4 = 'ST3DWSXBPYDB484QXFTR81K4AWG4ZB5XZNFF3H70C';
72-
const testTxId = '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890006';
72+
const testTxId = '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890008';
7373

7474
const block: DbBlock = {
7575
block_hash: '0x1234',
@@ -99,7 +99,8 @@ describe('address tests', () => {
9999
canonical: boolean = true,
100100
stxEventCount = 1,
101101
ftEventCount = 1,
102-
nftEventCount = 1
102+
nftEventCount = 1,
103+
eventAddressesOnly = false
103104
): [DbTxRaw, DbStxEvent[], DbFtEvent[], DbNftEvent[]] => {
104105
const tx: DbTxRaw = {
105106
tx_id:
@@ -117,7 +118,7 @@ describe('address tests', () => {
117118
type_id: DbTxTypeId.TokenTransfer,
118119
token_transfer_amount: BigInt(amount),
119120
token_transfer_memo: bufferToHex(Buffer.from('hi')),
120-
token_transfer_recipient_address: recipient,
121+
token_transfer_recipient_address: eventAddressesOnly ? '' : recipient,
121122
status: 1,
122123
raw_result: '0x0100000000000000000000000000000001', // u1
123124
canonical,
@@ -130,7 +131,7 @@ describe('address tests', () => {
130131
fee_rate: 1234n,
131132
sponsored: false,
132133
sponsor_address: undefined,
133-
sender_address: sender,
134+
sender_address: eventAddressesOnly ? '' : sender,
134135
origin_hash_mode: 1,
135136
event_count: 0,
136137
execution_cost_read_count: 1,
@@ -193,6 +194,8 @@ describe('address tests', () => {
193194
return [tx, stxEvents, ftEvents, nftEvents];
194195
};
195196
const txs = [
197+
createStxTx(testAddr4, testAddr2, 0, true, 0, 1, 0, true),
198+
createStxTx(testAddr4, testAddr2, 0, true, 0, 0, 1, true),
196199
createStxTx(testAddr1, testAddr2, 100_000, true, 1, 1, 1),
197200
createStxTx(testAddr2, testContractAddr, 100, true, 1, 2, 1),
198201
createStxTx(testAddr2, testContractAddr, 250, true, 1, 0, 1),
@@ -228,11 +231,11 @@ describe('address tests', () => {
228231
const expected1 = {
229232
limit: 3,
230233
offset: 0,
231-
total: 4,
234+
total: 6,
232235
results: [
233236
{
234237
tx: {
235-
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890006',
238+
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890008',
236239
tx_type: 'token_transfer',
237240
nonce: 0,
238241
anchor_mode: 'any',
@@ -254,7 +257,7 @@ describe('address tests', () => {
254257
parent_block_hash: '0x',
255258
parent_burn_block_time: 1626122935,
256259
parent_burn_block_time_iso: '2021-07-12T20:48:55.000Z',
257-
tx_index: 6,
260+
tx_index: 8,
258261
tx_result: { hex: '0x0100000000000000000000000000000001', repr: 'u1' },
259262
token_transfer: {
260263
recipient_address: 'ST3DWSXBPYDB484QXFTR81K4AWG4ZB5XZNFF3H70C',
@@ -319,7 +322,7 @@ describe('address tests', () => {
319322
},
320323
{
321324
tx: {
322-
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890003',
325+
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890005',
323326
tx_type: 'token_transfer',
324327
nonce: 0,
325328
anchor_mode: 'any',
@@ -341,7 +344,7 @@ describe('address tests', () => {
341344
parent_block_hash: '0x',
342345
parent_burn_block_time: 1626122935,
343346
parent_burn_block_time_iso: '2021-07-12T20:48:55.000Z',
344-
tx_index: 3,
347+
tx_index: 5,
345348
tx_result: { hex: '0x0100000000000000000000000000000001', repr: 'u1' },
346349
token_transfer: {
347350
recipient_address: 'ST27W5M8BRKA7C5MZE2R1S1F4XTPHFWFRNHA9M04Y.hello-world',
@@ -380,7 +383,7 @@ describe('address tests', () => {
380383
},
381384
{
382385
tx: {
383-
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890002',
386+
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890004',
384387
tx_type: 'token_transfer',
385388
nonce: 0,
386389
anchor_mode: 'any',
@@ -402,7 +405,7 @@ describe('address tests', () => {
402405
parent_block_hash: '0x',
403406
parent_burn_block_time: 1626122935,
404407
parent_burn_block_time_iso: '2021-07-12T20:48:55.000Z',
405-
tx_index: 2,
408+
tx_index: 4,
406409
tx_result: { hex: '0x0100000000000000000000000000000001', repr: 'u1' },
407410
token_transfer: {
408411
recipient_address: 'ST27W5M8BRKA7C5MZE2R1S1F4XTPHFWFRNHA9M04Y.hello-world',
@@ -454,7 +457,8 @@ describe('address tests', () => {
454457
},
455458
],
456459
};
457-
expect(JSON.parse(fetch1.text)).toEqual(expected1);
460+
const fetch1Json = JSON.parse(fetch1.text);
461+
expect(fetch1Json).toEqual(expected1);
458462

459463
// Test v2 endpoints
460464
const v2Fetch1 = await supertest(api.server).get(
@@ -463,6 +467,7 @@ describe('address tests', () => {
463467
expect(v2Fetch1.status).toBe(200);
464468
expect(v2Fetch1.type).toBe('application/json');
465469
const v2Fetch1Json = JSON.parse(v2Fetch1.text);
470+
expect(v2Fetch1Json.total).toBe(6);
466471
expect(v2Fetch1Json.results[0].tx).toStrictEqual(expected1.results[0].tx);
467472
expect(v2Fetch1Json.results[0].stx_sent).toBe('1339');
468473
expect(v2Fetch1Json.results[0].stx_received).toBe('0');
@@ -517,6 +522,40 @@ describe('address tests', () => {
517522
mint: 0,
518523
burn: 0,
519524
});
525+
expect(v2Fetch1Json.results[4].stx_sent).toBe('1234');
526+
expect(v2Fetch1Json.results[4].stx_received).toBe('0');
527+
expect(v2Fetch1Json.results[4].events.stx).toStrictEqual({
528+
transfer: 0,
529+
mint: 0,
530+
burn: 0,
531+
});
532+
expect(v2Fetch1Json.results[4].events.ft).toStrictEqual({
533+
transfer: 0,
534+
mint: 0,
535+
burn: 0,
536+
});
537+
expect(v2Fetch1Json.results[4].events.nft).toStrictEqual({
538+
transfer: 1,
539+
mint: 0,
540+
burn: 0,
541+
});
542+
expect(v2Fetch1Json.results[5].stx_sent).toBe('1234');
543+
expect(v2Fetch1Json.results[5].stx_received).toBe('0');
544+
expect(v2Fetch1Json.results[5].events.stx).toStrictEqual({
545+
transfer: 0,
546+
mint: 0,
547+
burn: 0,
548+
});
549+
expect(v2Fetch1Json.results[5].events.ft).toStrictEqual({
550+
transfer: 1,
551+
mint: 0,
552+
burn: 0,
553+
});
554+
expect(v2Fetch1Json.results[5].events.nft).toStrictEqual({
555+
transfer: 0,
556+
mint: 0,
557+
burn: 0,
558+
});
520559

521560
const v2Fetch2 = await supertest(api.server).get(
522561
`/extended/v2/addresses/${testAddr2}/transactions/${v2Fetch1Json.results[0].tx.tx_id}/events?limit=3`
@@ -620,7 +659,7 @@ describe('address tests', () => {
620659
expect(fetchSingleTxInformation.type).toBe('application/json');
621660
const expectedSingleTxInformation = {
622661
tx: {
623-
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890006',
662+
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890008',
624663
tx_type: 'token_transfer',
625664
nonce: 0,
626665
anchor_mode: 'any',
@@ -642,7 +681,7 @@ describe('address tests', () => {
642681
parent_block_hash: '0x',
643682
parent_burn_block_time: 1626122935,
644683
parent_burn_block_time_iso: '2021-07-12T20:48:55.000Z',
645-
tx_index: 6,
684+
tx_index: 8,
646685
tx_result: { hex: '0x0100000000000000000000000000000001', repr: 'u1' },
647686
token_transfer: {
648687
recipient_address: 'ST3DWSXBPYDB484QXFTR81K4AWG4ZB5XZNFF3H70C',
@@ -681,18 +720,18 @@ describe('address tests', () => {
681720

682721
// testing for multiple tx_ids given a single stx addr
683722
const fetch2 = await supertest(api.server).get(
684-
`/extended/v1/address/${testAddr4}/transactions_with_transfers`
723+
`/extended/v1/address/${testAddr4}/transactions_with_transfers?limit=2`
685724
);
686725
expect(fetch2.status).toBe(200);
687726
expect(fetch2.type).toBe('application/json');
688727
const expected2 = {
689-
limit: 20,
728+
limit: 2,
690729
offset: 0,
691-
total: 2,
730+
total: 4,
692731
results: [
693732
{
694733
tx: {
695-
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890006',
734+
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890008',
696735
tx_type: 'token_transfer',
697736
nonce: 0,
698737
anchor_mode: 'any',
@@ -714,7 +753,7 @@ describe('address tests', () => {
714753
parent_block_hash: '0x',
715754
parent_burn_block_time: 1626122935,
716755
parent_burn_block_time_iso: '2021-07-12T20:48:55.000Z',
717-
tx_index: 6,
756+
tx_index: 8,
718757
tx_result: { hex: '0x0100000000000000000000000000000001', repr: 'u1' },
719758
token_transfer: {
720759
recipient_address: 'ST3DWSXBPYDB484QXFTR81K4AWG4ZB5XZNFF3H70C',
@@ -779,7 +818,7 @@ describe('address tests', () => {
779818
},
780819
{
781820
tx: {
782-
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890005',
821+
tx_id: '0x03807fdb726b3cb843e0330c564a4974037be8f9ea58ec7f8ebe03c34b890007',
783822
tx_type: 'token_transfer',
784823
nonce: 0,
785824
anchor_mode: 'any',
@@ -801,7 +840,7 @@ describe('address tests', () => {
801840
parent_block_hash: '0x',
802841
parent_burn_block_time: 1626122935,
803842
parent_burn_block_time_iso: '2021-07-12T20:48:55.000Z',
804-
tx_index: 5,
843+
tx_index: 7,
805844
tx_result: { hex: '0x0100000000000000000000000000000001', repr: 'u1' },
806845
token_transfer: {
807846
recipient_address: 'ST3DWSXBPYDB484QXFTR81K4AWG4ZB5XZNFF3H70C',

0 commit comments

Comments
 (0)