Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 40 additions & 36 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,20 @@ jobs:
with:
node-version-file: ".nvmrc"

# https://github.com/actions/cache/blob/main/examples.md#node---npm
- name: Get npm cache directory
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}

- name: Cache node modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
with:
path: |
~/.npm
**/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
${{ runner.os }}-node-

- name: Install deps
run: npm ci --audit=false
Expand Down Expand Up @@ -75,19 +76,20 @@ jobs:
with:
node-version-file: ".nvmrc"

# https://github.com/actions/cache/blob/main/examples.md#node---npm
- name: Get npm cache directory
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}

- name: Cache node modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
with:
path: |
~/.npm
**/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
${{ runner.os }}-node-

- name: Install deps
run: npm ci --audit=false
Expand Down Expand Up @@ -157,19 +159,20 @@ jobs:
with:
node-version-file: ".nvmrc"

# https://github.com/actions/cache/blob/main/examples.md#node---npm
- name: Get npm cache directory
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}

- name: Cache node modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
with:
path: |
~/.npm
**/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
${{ runner.os }}-node-

- name: Install deps
run: npm ci --audit=false
Expand Down Expand Up @@ -220,19 +223,20 @@ jobs:
with:
node-version-file: ".nvmrc"

# https://github.com/actions/cache/blob/main/examples.md#node---npm
- name: Get npm cache directory
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}

- name: Cache node modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
with:
path: |
~/.npm
**/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
${{ runner.os }}-node-

- name: Install deps
run: npm ci --audit=false
Expand Down
25 changes: 13 additions & 12 deletions .github/workflows/vercel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,29 @@ jobs:
url: ${{ github.ref_name == 'master' && 'https://stacks-blockchain-api.vercel.app/' || 'https://stacks-blockchain-api-pbcblockstack-blockstack.vercel.app/' }}

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Use Node.js
uses: actions/setup-node@v2
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'

# https://github.com/actions/cache/blob/main/examples.md#node---npm
- name: Get npm cache directory
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}

- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
uses: actions/cache@v4
id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
with:
path: |
~/.npm
**/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
${{ runner.os }}-node-

- name: Install deps
run: npm ci --audit=false
Expand Down
164 changes: 164 additions & 0 deletions migrations/1741805265249_principal_activity_txs_idx-sort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// @ts-check
/** @param { import("node-pg-migrate").MigrationBuilder } pgm */
exports.up = pgm => {
/**
* A previous migration used `order` instead of `sort` in the index definition which caused it to be ignored and default to ASC.
* The `@ts-check` directive at the top of the file will catch these errors in the future.
*/

pgm.dropIndex('principal_stx_txs', [], { name: 'idx_principal_stx_txs_optimized' });
pgm.dropIndex('ft_events', [], { name: 'idx_ft_events_optimized' });
pgm.dropIndex('nft_events', [], { name: 'idx_nft_events_optimized' });
pgm.dropIndex('mempool_txs', [], { name: 'idx_mempool_txs_optimized' });

pgm.createIndex(
'principal_stx_txs',
[
'principal',
{ name: 'block_height', sort: 'DESC' },
{ name: 'microblock_sequence', sort: 'DESC' },
{ name: 'tx_index', sort: 'DESC' }],
{
name: 'idx_principal_stx_txs_optimized',
where: 'canonical = TRUE AND microblock_canonical = TRUE',
}
);

pgm.createIndex(
'nft_events',
[
'sender',
'recipient',
{ name: 'block_height', sort: 'DESC' },
{ name: 'microblock_sequence', sort: 'DESC' },
{ name: 'tx_index', sort: 'DESC' },
{ name: 'event_index', sort: 'DESC' }
],
{
name: 'idx_nft_events_optimized',
where: 'canonical = TRUE AND microblock_canonical = TRUE',
}
);

pgm.createIndex(
'ft_events',
[
'sender',
{ name: 'block_height', sort: 'DESC' },
{ name: 'microblock_sequence', sort: 'DESC' },
{ name: 'tx_index', sort: 'DESC' },
{ name: 'event_index', sort: 'DESC' }
],
{
name: 'idx_ft_events_optimized_sender',
where: 'canonical = TRUE AND microblock_canonical = TRUE',
}
);

pgm.createIndex(
'ft_events',
[
'recipient',
{ name: 'block_height', sort: 'DESC' },
{ name: 'microblock_sequence', sort: 'DESC' },
{ name: 'tx_index', sort: 'DESC' },
{ name: 'event_index', sort: 'DESC' }
],
{
name: 'idx_ft_events_optimized_recipient',
where: 'canonical = TRUE AND microblock_canonical = TRUE',
}
);

pgm.createIndex(
'mempool_txs',
[
{ name: 'receipt_time', sort: 'DESC' }
],
{
name: 'idx_mempool_txs_optimized',
where: 'pruned = FALSE',
}
);

};

/** @param { import("node-pg-migrate").MigrationBuilder } pgm */
exports.down = pgm => {
pgm.dropIndex('principal_stx_txs', [], { name: 'idx_principal_stx_txs_optimized' });
pgm.dropIndex('ft_events', [], { name: 'idx_ft_events_optimized_sender' });
pgm.dropIndex('ft_events', [], { name: 'idx_ft_events_optimized_recipient' });
pgm.dropIndex('nft_events', [], { name: 'idx_nft_events_optimized' });
pgm.dropIndex('mempool_txs', [], { name: 'idx_mempool_txs_optimized' });

pgm.createIndex(
'principal_stx_txs',
[
'principal',
// @ts-ignore
{ name: 'block_height', order: 'DESC' },
// @ts-ignore
{ name: 'microblock_sequence', order: 'DESC' },
// @ts-ignore
{ name: 'tx_index', order: 'DESC' }],
{
name: 'idx_principal_stx_txs_optimized',
where: 'canonical = TRUE AND microblock_canonical = TRUE',
}
);

pgm.createIndex(
'ft_events',
[
'sender',
'recipient',
// @ts-ignore
{ name: 'block_height', order: 'DESC' },
// @ts-ignore
{ name: 'microblock_sequence', order: 'DESC' },
// @ts-ignore
{ name: 'tx_index', order: 'DESC' },
// @ts-ignore
{ name: 'event_index', order: 'DESC' }
],
{
name: 'idx_ft_events_optimized',
where: 'canonical = TRUE AND microblock_canonical = TRUE',
}
);

pgm.createIndex(
'nft_events',
[
'sender',
'recipient',
// @ts-ignore
{ name: 'block_height', order: 'DESC' },
// @ts-ignore
{ name: 'microblock_sequence', order: 'DESC' },
// @ts-ignore
{ name: 'tx_index', order: 'DESC' },
// @ts-ignore
{ name: 'event_index', order: 'DESC' }
],
{
name: 'idx_nft_events_optimized',
where: 'canonical = TRUE AND microblock_canonical = TRUE',
}
);

pgm.createIndex(
'mempool_txs',
[
'sender_address',
'sponsor_address',
'token_transfer_recipient_address',
// @ts-ignore
{ name: 'receipt_time', order: 'DESC' }
],
{
name: 'idx_mempool_txs_optimized',
where: 'pruned = FALSE',
}
);
};
4 changes: 2 additions & 2 deletions src/api/controllers/cache-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { BlockParams } from '../routes/v2/schemas';
* state of the chain depending on the type of information being requested by the endpoint.
* This entry will have an `ETag` string as the value.
*/
enum ETagType {
export enum ETagType {
/** ETag based on the latest `index_block_hash` or `microblock_hash`. */
chainTip = 'chain_tip',
/** ETag based on a digest of all pending mempool `tx_id`s. */
Expand Down Expand Up @@ -149,7 +149,7 @@ async function calculateETag(
}
}

async function handleCache(type: ETagType, request: FastifyRequest, reply: FastifyReply) {
export async function handleCache(type: ETagType, request: FastifyRequest, reply: FastifyReply) {
const metrics = getETagMetrics();
const ifNoneMatch = parseIfNoneMatchHeader(request.headers['if-none-match']);
const etag = await calculateETag(request.server.db, type, request);
Expand Down
5 changes: 5 additions & 0 deletions src/api/pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export enum ResourceType {
PoxCycle,
TokenHolders,
BlockSignerSignature,
FtBalance,
}

export const pagingQueryLimits: Record<ResourceType, { defaultLimit: number; maxLimit: number }> = {
Expand Down Expand Up @@ -99,6 +100,10 @@ export const pagingQueryLimits: Record<ResourceType, { defaultLimit: number; max
defaultLimit: 500,
maxLimit: 1000,
},
[ResourceType.FtBalance]: {
defaultLimit: 100,
maxLimit: 200,
},
};

export function getPagingQueryLimit(
Expand Down
10 changes: 8 additions & 2 deletions src/api/routes/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,12 @@ export const AddressRoutes: FastifyPluginAsync<
{
preHandler: handlePrincipalMempoolCache,
schema: {
deprecated: true,
operationId: 'get_account_stx_balance',
summary: 'Get account STX balance',
description: `Retrieves STX token balance for a given Address or Contract Identifier.`,
description: `**NOTE:** This endpoint is deprecated in favor of [Get address STX balance](/api/get-principal-stx-balance).

Retrieves STX token balance for a given Address or Contract Identifier.`,
tags: ['Accounts'],
params: Type.Object({
principal: PrincipalSchema,
Expand Down Expand Up @@ -159,9 +162,12 @@ export const AddressRoutes: FastifyPluginAsync<
{
preHandler: handlePrincipalMempoolCache,
schema: {
deprecated: true,
operationId: 'get_account_balance',
summary: 'Get account balances',
description: `Retrieves total account balance information for a given Address or Contract Identifier. This includes the balances of STX Tokens, Fungible Tokens and Non-Fungible Tokens for the account.`,
description: `**NOTE:** This endpoint is deprecated in favor of [Get address FT balances](/api/get-principal-ft-balances).

Retrieves total account balance information for a given Address or Contract Identifier. This includes the balances of STX Tokens, Fungible Tokens and Non-Fungible Tokens for the account.`,
tags: ['Accounts'],
params: Type.Object({
principal: PrincipalSchema,
Expand Down
Loading
Loading