@@ -36,6 +36,7 @@ import {
36
36
PoxCycleQueryResult ,
37
37
DbPoxCycleSigner ,
38
38
DbPoxCycleSignerStacker ,
39
+ DbCursorPaginatedResult ,
39
40
} from './common' ;
40
41
import {
41
42
BLOCK_COLUMNS ,
@@ -59,37 +60,97 @@ async function assertTxIdExists(sql: PgSqlClient, tx_id: string) {
59
60
}
60
61
61
62
export class PgStoreV2 extends BasePgStoreModule {
62
- async getBlocks ( args : BlockPaginationQueryParams ) : Promise < DbPaginatedResult < DbBlock > > {
63
+ async getBlocks ( args : {
64
+ limit : number ;
65
+ offset ?: number ;
66
+ cursor ?: string ;
67
+ } ) : Promise < DbCursorPaginatedResult < DbBlock > > {
63
68
return await this . sqlTransaction ( async sql => {
64
- const limit = args . limit ?? BlockLimitParamSchema . default ;
69
+ const limit = args . limit ;
65
70
const offset = args . offset ?? 0 ;
66
- const blocksQuery = await sql < ( BlockQueryResult & { total : number } ) [ ] > `
67
- WITH block_count AS (
68
- SELECT block_count AS count FROM chain_tip
71
+ const cursor = args . cursor ?? null ;
72
+
73
+ const blocksQuery = await sql <
74
+ ( BlockQueryResult & { total : number ; next_block_hash : string ; prev_block_hash : string } ) [ ]
75
+ > `
76
+ WITH cursor_block AS (
77
+ WITH ordered_blocks AS (
78
+ SELECT *, LEAD(block_height, ${ offset } ) OVER (ORDER BY block_height DESC) offset_block_height
79
+ FROM blocks
80
+ WHERE canonical = true
81
+ ORDER BY block_height DESC
69
82
)
70
- SELECT
71
- ${ sql ( BLOCK_COLUMNS ) } ,
72
- (SELECT count FROM block_count)::int AS total
83
+ SELECT offset_block_height as block_height
84
+ FROM ordered_blocks
85
+ WHERE index_block_hash = ${ cursor ?? sql `(SELECT index_block_hash FROM chain_tip LIMIT 1)` }
86
+ LIMIT 1
87
+ ),
88
+ selected_blocks AS (
89
+ SELECT ${ sql ( BLOCK_COLUMNS ) }
73
90
FROM blocks
74
91
WHERE canonical = true
92
+ AND block_height <= (SELECT block_height FROM cursor_block)
75
93
ORDER BY block_height DESC
76
94
LIMIT ${ limit }
77
- OFFSET ${ offset }
95
+ ),
96
+ prev_page AS (
97
+ SELECT index_block_hash as prev_block_hash
98
+ FROM blocks
99
+ WHERE canonical = true
100
+ AND block_height < (
101
+ SELECT block_height
102
+ FROM selected_blocks
103
+ ORDER BY block_height DESC
104
+ LIMIT 1
105
+ )
106
+ ORDER BY block_height DESC
107
+ OFFSET ${ limit - 1 }
108
+ LIMIT 1
109
+ ),
110
+ next_page AS (
111
+ SELECT index_block_hash as next_block_hash
112
+ FROM blocks
113
+ WHERE canonical = true
114
+ AND block_height > (
115
+ SELECT block_height
116
+ FROM selected_blocks
117
+ ORDER BY block_height DESC
118
+ LIMIT 1
119
+ )
120
+ ORDER BY block_height ASC
121
+ OFFSET ${ limit - 1 }
122
+ LIMIT 1
123
+ )
124
+ SELECT
125
+ (SELECT block_count FROM chain_tip)::int AS total,
126
+ sb.*,
127
+ nb.next_block_hash,
128
+ pb.prev_block_hash
129
+ FROM selected_blocks sb
130
+ LEFT JOIN next_page nb ON true
131
+ LEFT JOIN prev_page pb ON true
132
+ ORDER BY sb.block_height DESC
78
133
` ;
79
- if ( blocksQuery . count === 0 )
80
- return {
81
- limit,
82
- offset,
83
- results : [ ] ,
84
- total : 0 ,
85
- } ;
134
+
135
+ // Parse blocks
86
136
const blocks = blocksQuery . map ( b => parseBlockQueryResult ( b ) ) ;
87
- return {
137
+ const total = blocksQuery [ 0 ] ?. total ?? 0 ;
138
+
139
+ // Determine cursors
140
+ const nextCursor = blocksQuery [ 0 ] ?. next_block_hash ?? null ;
141
+ const prevCursor = blocksQuery [ 0 ] ?. prev_block_hash ?? null ;
142
+ const currentCursor = blocksQuery [ 0 ] ?. index_block_hash ?? null ;
143
+
144
+ const result : DbCursorPaginatedResult < DbBlock > = {
88
145
limit,
89
- offset,
146
+ offset : offset ,
90
147
results : blocks ,
91
- total : blocksQuery [ 0 ] . total ,
148
+ total : total ,
149
+ next_cursor : nextCursor ,
150
+ prev_cursor : prevCursor ,
151
+ current_cursor : currentCursor ,
92
152
} ;
153
+ return result ;
93
154
} ) ;
94
155
}
95
156
0 commit comments