Skip to content

Commit 8b84ca9

Browse files
fix(api): update txn receipts api (#1336)
1 parent d03d174 commit 8b84ca9

File tree

9 files changed

+213
-41
lines changed

9 files changed

+213
-41
lines changed

apps/api/src/sql/queries/blocks/blocks.sql

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ WITH
55
block_height,
66
block_hash,
77
gas_price,
8-
author_account_id,
9-
prev_block_hash
8+
author_account_id
109
FROM
1110
blocks
1211
WHERE
@@ -40,10 +39,8 @@ SELECT
4039
bs.block_hash,
4140
bs.author_account_id,
4241
bs.gas_price,
43-
bs.prev_block_hash,
4442
c.chunks_agg,
45-
t.transactions_agg,
46-
r.receipts_agg
43+
t.transactions_agg
4744
FROM
4845
blocks_selected bs
4946
LEFT JOIN LATERAL (
@@ -93,25 +90,5 @@ FROM
9390
)
9491
AND included_in_block_hash = bs.block_hash
9592
) t ON TRUE
96-
LEFT JOIN LATERAL (
97-
SELECT
98-
JSONB_BUILD_OBJECT('count', COUNT(*)) AS receipts_agg
99-
FROM
100-
receipts
101-
WHERE
102-
included_in_block_timestamp >= (
103-
SELECT
104-
MIN(b.block_timestamp)
105-
FROM
106-
blocks_selected b
107-
)
108-
AND included_in_block_timestamp <= (
109-
SELECT
110-
MAX(b.block_timestamp) + 300000000000 -- 5m in ns
111-
FROM
112-
blocks_selected b
113-
)
114-
AND included_in_block_hash = bs.block_hash
115-
) r ON TRUE
11693
ORDER BY
11794
bs.block_timestamp ${direction:raw}

apps/api/src/sql/queries/txns/txn.sql

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,20 @@ FROM
4040
LEFT JOIN LATERAL (
4141
SELECT
4242
JSONB_AGG(
43-
JSONB_BUILD_OBJECT('action', action_kind, 'method', method)
43+
JSONB_BUILD_OBJECT(
44+
'action',
45+
action_kind,
46+
'method',
47+
method,
48+
'gas',
49+
args ->> 'gas'::TEXT,
50+
'deposit',
51+
args ->> 'deposit'::TEXT,
52+
'args',
53+
args -> 'args_json',
54+
'args_base64',
55+
args ->> 'args_base64'::TEXT
56+
)
4457
ORDER BY
4558
index_in_action_receipt
4659
) AS actions

apps/frontend/src/components/home/blocks.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Fragment } from 'react';
44
import { use } from 'react';
55
import { LuBox, LuFuel } from 'react-icons/lu';
66

7-
import { Block } from 'nb-schemas';
7+
import { BlockListItem } from 'nb-schemas';
88

99
import { Link } from '@/components/link';
1010
import { SkeletonSlot } from '@/components/skeleton';
@@ -19,7 +19,7 @@ import { Separator } from '@/ui/separator';
1919
import { Skeleton } from '@/ui/skeleton';
2020

2121
type Props = {
22-
blocksPromise?: Promise<Block[] | null>;
22+
blocksPromise?: Promise<BlockListItem[] | null>;
2323
loading?: boolean;
2424
};
2525

apps/frontend/src/components/home/txns.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Fragment } from 'react';
44
import { use } from 'react';
55
import { LuArrowLeftRight } from 'react-icons/lu';
66

7-
import { Txn } from 'nb-schemas';
7+
import { TxnListItem } from 'nb-schemas';
88

99
import { Link } from '@/components/link';
1010
import { SkeletonSlot } from '@/components/skeleton';
@@ -21,7 +21,7 @@ import { Skeleton } from '@/ui/skeleton';
2121

2222
type Props = {
2323
loading?: boolean;
24-
txnsPromise?: Promise<null | Txn[]>;
24+
txnsPromise?: Promise<null | TxnListItem[]>;
2525
};
2626

2727
export const Txns = ({ loading, txnsPromise }: Props) => {

apps/frontend/src/data/home.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import {
2-
Block,
2+
BlockListItem,
33
BlocksRes,
44
DailyStats,
55
DailyStatsRes,
6-
Txn,
6+
TxnListItem,
77
TxnsRes,
88
} from 'nb-schemas';
99

1010
import { fetcher } from '@/lib/fetcher';
1111

12-
export const fetchBlocks = async (): Promise<Block[] | null> => {
12+
export const fetchBlocks = async (): Promise<BlockListItem[] | null> => {
1313
const resp = await fetcher<BlocksRes>('/v3/blocks/latest');
1414
return resp.data;
1515
};
1616

17-
export const fetchTxns = async (): Promise<null | Txn[]> => {
17+
export const fetchTxns = async (): Promise<null | TxnListItem[]> => {
1818
const resp = await fetcher<TxnsRes>('/v3/txns/latest');
1919
return resp.data;
2020
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { upSQL } from 'knex-migrate-sql-file';
2+
3+
export async function up(knex) {
4+
await upSQL(knex);
5+
}
6+
7+
export function down() {}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
CREATE
2+
OR REPLACE FUNCTION receipt_tree (p_receipt_id TEXT, p_timestamp BIGINT) RETURNS JSONB LANGUAGE SQL STABLE AS $$
3+
WITH
4+
receipt_selected AS (
5+
SELECT
6+
r.receipt_id,
7+
r.predecessor_account_id,
8+
r.receiver_account_id,
9+
r.public_key,
10+
r.included_in_block_timestamp,
11+
r.included_in_block_hash
12+
FROM
13+
receipts r
14+
WHERE
15+
r.included_in_block_timestamp >= p_timestamp
16+
AND r.included_in_block_timestamp < (p_timestamp + 300000000000) -- 5m in ns
17+
AND r.receipt_id = p_receipt_id
18+
AND r.receipt_kind = 'ACTION'
19+
),
20+
child_receipts AS (
21+
SELECT
22+
r.receipt_id,
23+
r.included_in_block_timestamp
24+
FROM
25+
execution_outcome_receipts eor
26+
JOIN receipts r ON r.receipt_id = eor.produced_receipt_id
27+
WHERE
28+
eor.executed_receipt_id = p_receipt_id
29+
AND r.included_in_block_timestamp >= p_timestamp
30+
AND r.included_in_block_timestamp < (p_timestamp + 300000000000) -- 5m in ns
31+
)
32+
SELECT
33+
JSONB_BUILD_OBJECT(
34+
'receipt_id',
35+
rs.receipt_id,
36+
'predecessor_account_id',
37+
rs.predecessor_account_id,
38+
'receiver_account_id',
39+
rs.receiver_account_id,
40+
'public_key',
41+
rs.public_key,
42+
'block',
43+
COALESCE(b.block, '{}'::JSONB),
44+
'actions',
45+
COALESCE(a.actions, '[]'::JSONB),
46+
'outcome',
47+
COALESCE(o.outcome, '{}'::JSONB),
48+
'receipts',
49+
(
50+
SELECT
51+
COALESCE(
52+
JSONB_AGG(
53+
receipt_tree (cr.receipt_id, cr.included_in_block_timestamp)
54+
),
55+
'[]'::JSONB
56+
)
57+
FROM
58+
child_receipts cr
59+
)
60+
)
61+
FROM
62+
receipt_selected rs
63+
LEFT JOIN LATERAL (
64+
SELECT
65+
JSONB_BUILD_OBJECT(
66+
'block_hash',
67+
block_hash,
68+
'block_height',
69+
block_height::TEXT,
70+
'block_timestamp',
71+
block_timestamp::TEXT
72+
) AS block
73+
FROM
74+
blocks
75+
WHERE
76+
block_timestamp = (
77+
SELECT
78+
r.included_in_block_timestamp
79+
FROM
80+
receipt_selected r
81+
)
82+
AND block_hash = rs.included_in_block_hash
83+
) b ON TRUE
84+
LEFT JOIN LATERAL (
85+
SELECT
86+
JSONB_AGG(
87+
JSONB_BUILD_OBJECT(
88+
'action',
89+
ara.action_kind,
90+
'method',
91+
method,
92+
'gas',
93+
args ->> 'gas'::TEXT,
94+
'deposit',
95+
args ->> 'deposit'::TEXT,
96+
'args',
97+
args -> 'args_json',
98+
'args_base64',
99+
args ->> 'args_base64'::TEXT,
100+
'rlp_hash',
101+
ara.nep518_rlp_hash
102+
)
103+
ORDER BY
104+
ara.index_in_action_receipt
105+
) AS actions
106+
FROM
107+
action_receipt_actions ara
108+
WHERE
109+
ara.receipt_included_in_block_timestamp = (
110+
SELECT
111+
r.included_in_block_timestamp
112+
FROM
113+
receipt_selected r
114+
)
115+
AND ara.receipt_id = rs.receipt_id
116+
) a ON TRUE
117+
LEFT JOIN LATERAL (
118+
SELECT
119+
JSONB_BUILD_OBJECT(
120+
'gas_burnt',
121+
eo.gas_burnt::TEXT,
122+
'tokens_burnt',
123+
eo.tokens_burnt::TEXT,
124+
'executor_account_id',
125+
eo.executor_account_id,
126+
'status',
127+
(status IN ('SUCCESS_RECEIPT_ID', 'SUCCESS_VALUE')),
128+
'status_key',
129+
status,
130+
'logs',
131+
eo.logs,
132+
'result',
133+
eo.result
134+
) AS outcome
135+
FROM
136+
execution_outcomes eo
137+
WHERE
138+
executed_in_block_timestamp >= (
139+
SELECT
140+
r.included_in_block_timestamp
141+
FROM
142+
receipt_selected r
143+
)
144+
AND executed_in_block_timestamp < (
145+
SELECT
146+
r.included_in_block_timestamp + 300000000000 -- 5m in ns
147+
FROM
148+
receipt_selected r
149+
)
150+
AND receipt_id = rs.receipt_id
151+
) o ON TRUE
152+
$$;

packages/nb-schemas/src/blocks/response.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@ const blockReceiptAgg = v.object({
1616
count: v.number(),
1717
});
1818

19-
const block = v.object({
19+
const blockListItem = v.object({
2020
author_account_id: v.string(),
2121
block_hash: v.string(),
2222
block_height: v.string(),
2323
block_timestamp: v.string(),
2424
chunks_agg: blockChunkAgg,
2525
gas_price: v.string(),
26+
transactions_agg: blockTransactionAgg,
27+
});
28+
29+
const block = v.object({
30+
...blockListItem.entries,
2631
prev_block_hash: v.string(),
2732
receipts_agg: blockReceiptAgg,
28-
transactions_agg: blockTransactionAgg,
2933
});
3034

3135
const blockCount = v.object({
@@ -34,10 +38,11 @@ const blockCount = v.object({
3438
});
3539

3640
const blockResponse = responseSchema(block);
37-
const blocksResponse = responseSchema(v.array(block));
41+
const blocksResponse = responseSchema(v.array(blockListItem));
3842
const blockCountResponse = responseSchema(blockCount);
3943

4044
export type Block = v.InferOutput<typeof block>;
45+
export type BlockListItem = v.InferOutput<typeof blockListItem>;
4146
export type BlockCount = v.InferOutput<typeof blockCount>;
4247

4348
export type BlockRes = v.InferOutput<typeof blockResponse>;

packages/nb-schemas/src/txns/response.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,19 @@ const block = v.object({
1111
block_timestamp: v.optional(v.string()),
1212
});
1313

14-
const action = v.object({
14+
const actionListItem = v.object({
1515
action: v.enum(ActionKind),
1616
method: v.nullable(v.string()),
1717
});
1818

19+
const action = v.object({
20+
...actionListItem.entries,
21+
args: v.nullable(jsonSchema),
22+
args_base64: v.nullable(v.string()),
23+
deposit: v.nullable(v.string()),
24+
gas: v.nullable(v.string()),
25+
});
26+
1927
const actionsAgg = v.object({
2028
deposit: v.string(),
2129
gas_attached: v.string(),
@@ -31,8 +39,8 @@ const outcomesAgg = v.object({
3139
transaction_fee: v.string(),
3240
});
3341

34-
const txn = v.object({
35-
actions: v.array(action),
42+
const txnListItem = v.object({
43+
actions: v.array(actionListItem),
3644
actions_agg: actionsAgg,
3745
block,
3846
block_timestamp: v.string(),
@@ -47,6 +55,11 @@ const txn = v.object({
4755
transaction_hash: v.string(),
4856
});
4957

58+
const txn = v.object({
59+
...txnListItem.entries,
60+
actions: v.array(action),
61+
});
62+
5063
const txnCount = v.object({
5164
cost: v.string(),
5265
count: v.string(),
@@ -55,6 +68,10 @@ const txnCount = v.object({
5568
const actionsReceipts = v.object({
5669
action: v.enum(ActionKind),
5770
args: jsonSchema,
71+
args_base64: v.nullable(v.string()),
72+
deposit: v.nullable(v.string()),
73+
gas: v.nullable(v.string()),
74+
method: v.nullable(v.string()),
5875
rlp_hash: v.nullable(v.string()),
5976
});
6077

@@ -169,13 +186,14 @@ const txnNFT = v.object({
169186
});
170187

171188
const txnResponse = responseSchema(txn);
172-
const txnsResponse = responseSchema(v.array(txn));
189+
const txnsResponse = responseSchema(v.array(txnListItem));
173190
const txnCountResponse = responseSchema(txnCount);
174191
const txnReceiptsResponse = responseSchema(txnReceipt);
175192
const txnFTsResponse = responseSchema(v.array(txnFT));
176193
const txnNFTsResponse = responseSchema(v.array(txnNFT));
177194

178195
export type Txn = v.InferOutput<typeof txn>;
196+
export type TxnListItem = v.InferOutput<typeof txnListItem>;
179197
export type TxnCount = v.InferOutput<typeof txnCount>;
180198
// export type TxnReceipt = v.InferOutput<typeof txnReceipt>;
181199
export type TxnFT = v.InferOutput<typeof txnFT>;

0 commit comments

Comments
 (0)