Skip to content

Commit a0f3dca

Browse files
authored
Merge pull request #2063 from hirosystems/chore/merge-dev-beta
Cut v8.0.0-beta.6
2 parents fc8657a + 5163a67 commit a0f3dca

20 files changed

+527
-152
lines changed

.github/workflows/ci.yml

+3
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ jobs:
147147
- name: Setup integration environment
148148
run: |
149149
sudo ufw disable
150+
mkdir -p src/tests-event-replay/.tmp/local/
151+
sudo chown 999:999 src/tests-event-replay/.tmp/local/
152+
sudo chmod -R 777 src/tests-event-replay/.tmp/local/
150153
docker compose -f docker/docker-compose.dev.postgres.yml up -d
151154
npm run devenv:logs -- --no-color &> docker-compose-logs.txt &
152155

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@
3737

3838
* refactor from Express to Fastify ([aa0e51e](https://github.com/hirosystems/stacks-blockchain-api/commit/aa0e51e557491daff1a98dd36c4e952e05c58dd4)), closes [#2042](https://github.com/hirosystems/stacks-blockchain-api/issues/2042)
3939

40+
* index on `principal_stx_txs` table for faster `/v1/address/{addr}/transactions` lookups ([#2059](https://github.com/hirosystems/stacks-blockchain-api/issues/2059)) ([ab64ab7](https://github.com/hirosystems/stacks-blockchain-api/commit/ab64ab7148a3656f81f0a3c5a176c40caca3345a))
41+
42+
## [7.14.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.13.2...v7.14.0) (2024-08-20)
43+
44+
45+
### Features
46+
47+
* export events tsv directly to postgres instance ([#2048](https://github.com/hirosystems/stacks-blockchain-api/issues/2048)) ([#2058](https://github.com/hirosystems/stacks-blockchain-api/issues/2058)) ([a1f5b12](https://github.com/hirosystems/stacks-blockchain-api/commit/a1f5b12675118f6d7742c54e3420c38151aef4a7))
48+
4049
## [7.13.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.13.1...v7.13.2) (2024-08-05)
4150

4251

docker/docker-compose.dev.bitcoind.yml

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
version: "3"
21
services:
32
bitcoind:
43
image: "blockstack/bitcoind:v0.20.99.0"
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
version: '3.7'
21
services:
32
postgres:
4-
image: "postgres:14"
3+
image: "postgres:15"
54
ports:
65
- "5490:5432"
76
environment:
87
POSTGRES_USER: postgres
98
POSTGRES_PASSWORD: postgres
109
POSTGRES_DB: stacks_blockchain_api
1110
POSTGRES_PORT: 5432
11+
volumes:
12+
- ../src/tests-event-replay/.tmp/local/:/root/

docker/docker-compose.dev.stacks-blockchain.yml

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
version: '3.7'
21
services:
32
stacks-blockchain:
43
image: 'hirosystems/stacks-api-e2e:stacks3.0-0a2c0e2'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/** @param { import("node-pg-migrate").MigrationBuilder } pgm */
2+
exports.up = pgm => {
3+
pgm.createIndex(
4+
'principal_stx_txs',
5+
[
6+
'principal',
7+
{ name: 'block_height', order: 'DESC' },
8+
{ name: 'microblock_sequence', order: 'DESC' },
9+
{ name: 'tx_index', order: 'DESC' }],
10+
{
11+
name: 'idx_principal_stx_txs_optimized',
12+
where: 'canonical = TRUE AND microblock_canonical = TRUE',
13+
}
14+
);
15+
};
16+
17+
/** @param { import("node-pg-migrate").MigrationBuilder } pgm */
18+
exports.down = pgm => {
19+
pgm.dropIndex('principal_stx_txs', ['principal', 'block_height', 'microblock_sequence', 'tx_index'], {
20+
name: 'idx_principal_stx_txs_optimized',
21+
});
22+
};

package-lock.json

+9-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
"dotenv-flow": "3.2.0",
119119
"duckdb": "0.9.2",
120120
"ecpair": "2.1.0",
121-
"elliptic": "6.5.4",
121+
"elliptic": "6.5.7",
122122
"escape-goat": "3.0.0",
123123
"evt": "1.10.1",
124124
"express": "4.19.2",
@@ -150,7 +150,7 @@
150150
"tiny-secp256k1": "2.2.1",
151151
"ts-unused-exports": "7.0.3",
152152
"uuid": "8.3.2",
153-
"ws": "7.5.9",
153+
"ws": "7.5.10",
154154
"zone-file": "2.0.0-beta.3"
155155
},
156156
"devDependencies": {

src/api/routes/v2/blocks.ts

+18-9
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import { parseDbTx } from '../../../api/controllers/db-controller';
66
import { FastifyPluginAsync } from 'fastify';
77
import { Type, TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
88
import { Server } from 'node:http';
9-
import { LimitParam, OffsetParam } from '../../schemas/params';
10-
import { ResourceType } from '../../pagination';
9+
import { CursorOffsetParam, LimitParam, OffsetParam } from '../../schemas/params';
10+
import { getPagingQueryLimit, pagingQueryLimits, ResourceType } from '../../pagination';
1111
import { PaginatedResponse } from '../../schemas/util';
1212
import { NakamotoBlock, NakamotoBlockSchema } from '../../schemas/entities/block';
1313
import { TransactionSchema } from '../../schemas/entities/transactions';
14+
import { BlockListV2ResponseSchema } from '../../schemas/responses/responses';
1415

1516
export const BlockRoutesV2: FastifyPluginAsync<
1617
Record<never, never>,
@@ -28,21 +29,29 @@ export const BlockRoutesV2: FastifyPluginAsync<
2829
tags: ['Blocks'],
2930
querystring: Type.Object({
3031
limit: LimitParam(ResourceType.Block),
31-
offset: OffsetParam(),
32+
offset: CursorOffsetParam({ resource: ResourceType.Block }),
33+
cursor: Type.Optional(Type.String({ description: 'Cursor for pagination' })),
3234
}),
3335
response: {
34-
200: PaginatedResponse(NakamotoBlockSchema),
36+
200: BlockListV2ResponseSchema,
3537
},
3638
},
3739
},
3840
async (req, reply) => {
3941
const query = req.query;
40-
const { limit, offset, results, total } = await fastify.db.v2.getBlocks(query);
41-
const blocks: NakamotoBlock[] = results.map(r => parseDbNakamotoBlock(r));
42+
const limit = getPagingQueryLimit(ResourceType.Block, req.query.limit);
43+
const blockQuery = await fastify.db.v2.getBlocks({ ...query, limit });
44+
if (query.cursor && !blockQuery.current_cursor) {
45+
throw new NotFoundError('Cursor not found');
46+
}
47+
const blocks: NakamotoBlock[] = blockQuery.results.map(r => parseDbNakamotoBlock(r));
4248
await reply.send({
43-
limit,
44-
offset,
45-
total,
49+
limit: blockQuery.limit,
50+
offset: blockQuery.offset,
51+
total: blockQuery.total,
52+
next_cursor: blockQuery.next_cursor,
53+
prev_cursor: blockQuery.prev_cursor,
54+
cursor: blockQuery.current_cursor,
4655
results: blocks,
4756
});
4857
}

src/api/schemas/params.ts

+17
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@ export const LimitParam = (
2828
})
2929
);
3030

31+
export const CursorOffsetParam = (args: {
32+
resource: ResourceType;
33+
title?: string;
34+
description?: string;
35+
limitOverride?: number;
36+
maxPages?: number;
37+
}) =>
38+
Type.Optional(
39+
Type.Integer({
40+
default: 0,
41+
maximum: pagingQueryLimits[args.resource].maxLimit * (args.maxPages ?? 10),
42+
minimum: -pagingQueryLimits[args.resource].maxLimit * (args.maxPages ?? 10),
43+
title: args.title ?? 'Offset',
44+
description: args.description ?? 'Result offset',
45+
})
46+
);
47+
3148
export const UnanchoredParamSchema = Type.Optional(
3249
Type.Boolean({
3350
default: false,

src/api/schemas/responses/responses.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Static, Type } from '@sinclair/typebox';
2-
import { OptionalNullable, PaginatedResponse } from '../util';
2+
import { Nullable, OptionalNullable, PaginatedCursorResponse, PaginatedResponse } from '../util';
33
import { MempoolStatsSchema } from '../entities/mempool-transactions';
44
import { MempoolTransactionSchema, TransactionSchema } from '../entities/transactions';
55
import { MicroblockSchema } from '../entities/microblock';
@@ -12,6 +12,7 @@ import {
1212
BurnchainRewardSchema,
1313
BurnchainRewardSlotHolderSchema,
1414
} from '../entities/burnchain-rewards';
15+
import { NakamotoBlockSchema } from '../entities/block';
1516

1617
export const ErrorResponseSchema = Type.Object(
1718
{
@@ -178,3 +179,6 @@ export const RunFaucetResponseSchema = Type.Object(
178179
}
179180
);
180181
export type RunFaucetResponse = Static<typeof RunFaucetResponseSchema>;
182+
183+
export const BlockListV2ResponseSchema = PaginatedCursorResponse(NakamotoBlockSchema);
184+
export type BlockListV2Response = Static<typeof BlockListV2ResponseSchema>;

src/api/schemas/util.ts

+14
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,17 @@ export const PaginatedResponse = <T extends TSchema>(type: T, options?: ObjectOp
1212
},
1313
options
1414
);
15+
16+
export const PaginatedCursorResponse = <T extends TSchema>(type: T, options?: ObjectOptions) =>
17+
Type.Object(
18+
{
19+
limit: Type.Integer({ examples: [20] }),
20+
offset: Type.Integer({ examples: [0] }),
21+
total: Type.Integer({ examples: [1] }),
22+
next_cursor: Nullable(Type.String({ description: 'Next page cursor' })),
23+
prev_cursor: Nullable(Type.String({ description: 'Previous page cursor' })),
24+
cursor: Nullable(Type.String({ description: 'Current page cursor' })),
25+
results: Type.Array(type),
26+
},
27+
options
28+
);

src/datastore/common.ts

+10
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,16 @@ export type DbPaginatedResult<T> = {
11431143
results: T[];
11441144
};
11451145

1146+
export type DbCursorPaginatedResult<T> = {
1147+
limit: number;
1148+
offset: number;
1149+
next_cursor: string | null;
1150+
prev_cursor: string | null;
1151+
current_cursor: string | null;
1152+
total: number;
1153+
results: T[];
1154+
};
1155+
11461156
export interface BlocksWithMetadata {
11471157
results: {
11481158
block: DbBlock;

0 commit comments

Comments
 (0)