Skip to content

Commit a490d67

Browse files
rafaelcrzone117x
andauthored
refactor: remove old token metadata processor (#1747)
* refactor: remove old processor, start fetching data from contract * refactor: remove old tests * fix: tests and lint * fix: use lru cache * chore: delete old tables * chore: fix comments [skip ci] * fix: env comment block [skip ci] * chore: avoid duplicate RPC lookups * fix: make an incremental migration to drop tables * fix: re-add metadata processing ENV flag --------- Co-authored-by: Matthew Little <[email protected]>
1 parent 872bcbd commit a490d67

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+427
-3143
lines changed

.env

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -122,34 +122,17 @@ STACKS_NODE_TYPE=L1
122122
# Override the default file path for the proxy cache control file
123123
# STACKS_API_PROXY_CACHE_CONTROL_FILE=/path/to/.proxy-cache-control.json
124124

125-
# Enable token metadata processing. Disabled by default.
125+
# Enable FT metadata processing for Rosetta operations display. Disabled by default.
126126
# STACKS_API_ENABLE_FT_METADATA=1
127-
# STACKS_API_ENABLE_NFT_METADATA=1
128-
129-
# If token metadata processing is enabled, this variable determines how the API reacts to metadata processing failures.
130-
# When strict mode is enabled, any failures caused by recoverable errors will be retried indefinitely. Otherwise,
131-
# the API will give up after `STACKS_API_TOKEN_METADATA_MAX_RETRIES` is reached for that smart contract.
132-
# STACKS_API_TOKEN_METADATA_STRICT_MODE=1
133-
134-
# Maximum number of times we'll try processing FT/NFT metadata for a specific smart contract if we've failed
135-
# because of a recoverable error.
136-
# Only used if `STACKS_API_TOKEN_METADATA_STRICT_MODE` is disabled.
137-
# STACKS_API_TOKEN_METADATA_MAX_RETRIES=5
138-
139-
# Controls the token metadata error handling mode. The possible values are:
140-
# * `warning`: If required metadata is not found, the API will issue a warning and not display data for that token.
141-
# * `error`: If required metadata is not found, the API will throw an error.
142-
# If not specified or any other value is provided, the mode will be set to `warning`.
143-
# STACKS_API_TOKEN_METADATA_ERROR_MODE=warning
144127

145-
# Configure a script to handle image URLs during token metadata processing.
146-
# This example script uses the `imgix.net` service to create CDN URLs.
147-
# Must be an executable script that accepts the URL as the first program argument
148-
# and outputs a result URL to stdout.
149-
# STACKS_API_IMAGE_CACHE_PROCESSOR=./config/token-metadata-image-cache-imgix.js
150-
# Env vars needed for the above sample `imgix` script:
151-
# IMGIX_DOMAIN=https://<your domain>.imgix.net
152-
# IMGIX_TOKEN=<your token>
128+
# The Rosetta API endpoints require FT metadata to display operations with the proper `symbol` and
129+
# `decimals` values. If FT metadata is enabled, this variable controls the token metadata error
130+
# handling mode when metadata is not found.
131+
# The possible values are:
132+
# * `warning`: The API will issue a warning and not display data for that token.
133+
# * `error`: The API will throw an error. If not specified or any other value is provided, the mode
134+
# will be set to `warning`.
135+
# STACKS_API_TOKEN_METADATA_ERROR_MODE=warning
153136

154137
# Web Socket ping interval to determine client availability, in seconds.
155138
# STACKS_API_WS_PING_INTERVAL=5

.github/workflows/ci.yml

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -848,96 +848,6 @@ jobs:
848848
flag-name: run-${{ github.job }}
849849
parallel: true
850850

851-
test-tokens-metadata:
852-
runs-on: ubuntu-latest
853-
steps:
854-
- uses: actions/checkout@v3
855-
856-
- name: Use Node.js
857-
uses: actions/setup-node@v4
858-
with:
859-
node-version-file: ".nvmrc"
860-
861-
- name: Install deps
862-
run: npm ci
863-
864-
- name: Setup env vars
865-
run: echo "STACKS_CORE_EVENT_HOST=http://0.0.0.0" >> $GITHUB_ENV
866-
867-
- name: Setup integration environment
868-
run: |
869-
sudo ufw disable
870-
npm run devenv:deploy-krypton -- -d
871-
npm run devenv:logs-krypton -- --no-color &> docker-compose-logs.txt &
872-
873-
- name: Run tokens tests
874-
run: npm run test:tokens-metadata
875-
876-
- name: Print integration environment logs
877-
run: cat docker-compose-logs.txt
878-
if: failure()
879-
880-
- name: Teardown integration environment
881-
run: npm run devenv:stop-krypton
882-
if: always()
883-
884-
- name: Upload coverage to Codecov
885-
uses: codecov/codecov-action@v3
886-
if: always()
887-
888-
- name: Upload coverage to Coveralls
889-
uses: coverallsapp/github-action@master
890-
if: ${{ false }}
891-
with:
892-
github-token: ${{ secrets.github_token }}
893-
flag-name: run-${{ github.job }}
894-
parallel: true
895-
896-
test-tokens-strict:
897-
runs-on: ubuntu-latest
898-
steps:
899-
- uses: actions/checkout@v3
900-
901-
- name: Use Node.js
902-
uses: actions/setup-node@v4
903-
with:
904-
node-version-file: ".nvmrc"
905-
906-
- name: Install deps
907-
run: npm ci
908-
909-
- name: Setup env vars
910-
run: echo "STACKS_CORE_EVENT_HOST=http://0.0.0.0" >> $GITHUB_ENV
911-
912-
- name: Setup integration environment
913-
run: |
914-
sudo ufw disable
915-
npm run devenv:deploy-krypton -- -d
916-
npm run devenv:logs-krypton -- --no-color &> docker-compose-logs.txt &
917-
918-
- name: Run tokens tests
919-
run: npm run test:tokens-strict
920-
921-
- name: Print integration environment logs
922-
run: cat docker-compose-logs.txt
923-
if: failure()
924-
925-
- name: Teardown integration environment
926-
run: npm run devenv:stop-krypton
927-
if: always()
928-
929-
- name: Upload coverage to Codecov
930-
uses: codecov/codecov-action@v3
931-
if: always()
932-
933-
- name: Upload coverage to Coveralls
934-
uses: coverallsapp/github-action@master
935-
if: ${{ false }}
936-
with:
937-
github-token: ${{ secrets.github_token }}
938-
flag-name: run-${{ github.job }}
939-
parallel: true
940-
941851
build-publish:
942852
runs-on: ubuntu-latest
943853
needs:
@@ -948,7 +858,6 @@ jobs:
948858
- test-bns
949859
- test-rosetta
950860
- test-rosetta-cli-construction
951-
- test-tokens-strict
952861
steps:
953862
- uses: actions/checkout@v3
954863
with:

.vscode/launch.json

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -346,40 +346,6 @@
346346
"preLaunchTask": "deploy:krypton",
347347
"postDebugTask": "stop:krypton",
348348
},
349-
{
350-
"type": "node",
351-
"request": "launch",
352-
"name": "Jest: Tokens - strict mode",
353-
"program": "${workspaceFolder}/node_modules/.bin/jest",
354-
"args": [
355-
"--testTimeout=3600000",
356-
"--runInBand",
357-
"--no-cache",
358-
"--config",
359-
"${workspaceRoot}/tests/jest.config.tokens-strict.js",
360-
],
361-
"outputCapture": "std",
362-
"console": "integratedTerminal",
363-
"preLaunchTask": "deploy:krypton",
364-
"postDebugTask": "stop:krypton",
365-
},
366-
{
367-
"type": "node",
368-
"request": "launch",
369-
"name": "Jest: Tokens - metadata",
370-
"program": "${workspaceFolder}/node_modules/.bin/jest",
371-
"args": [
372-
"--testTimeout=3600000",
373-
"--runInBand",
374-
"--no-cache",
375-
"--config",
376-
"${workspaceRoot}/tests/jest.config.tokens-metadata.js",
377-
],
378-
"outputCapture": "std",
379-
"console": "integratedTerminal",
380-
"preLaunchTask": "deploy:krypton",
381-
"postDebugTask": "stop:krypton",
382-
},
383349
{
384350
"type": "node",
385351
"request": "launch",
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/* eslint-disable camelcase */
2+
3+
exports.shorthands = undefined;
4+
5+
exports.up = pgm => {
6+
pgm.dropTable('token_metadata_queue');
7+
pgm.dropTable('nft_metadata');
8+
pgm.dropTable('ft_metadata');
9+
};
10+
11+
exports.down = pgm => {
12+
pgm.createTable('token_metadata_queue', {
13+
queue_id: {
14+
type: 'serial',
15+
primaryKey: true,
16+
},
17+
tx_id: {
18+
type: 'bytea',
19+
notNull: true,
20+
},
21+
contract_id: {
22+
type: 'string',
23+
notNull: true,
24+
},
25+
contract_abi: {
26+
type: 'string',
27+
notNull: true,
28+
},
29+
block_height: {
30+
type: 'integer',
31+
notNull: true,
32+
},
33+
processed: {
34+
type: 'boolean',
35+
notNull: true,
36+
},
37+
retry_count: {
38+
type: 'integer',
39+
notNull: true,
40+
default: 0,
41+
}
42+
});
43+
pgm.createIndex('token_metadata_queue', [{ name: 'block_height', sort: 'DESC' }]);
44+
pgm.createTable('nft_metadata', {
45+
id: {
46+
type: 'serial',
47+
primaryKey: true,
48+
},
49+
name: {
50+
type: 'string',
51+
notNull: true,
52+
},
53+
token_uri: {
54+
type: 'string',
55+
notNull: true,
56+
},
57+
description: {
58+
type: 'string',
59+
notNull: true,
60+
},
61+
image_uri: {
62+
type: 'string',
63+
notNull: true,
64+
},
65+
image_canonical_uri: {
66+
type: 'string',
67+
notNull: true,
68+
},
69+
contract_id: {
70+
type: 'string',
71+
notNull: true,
72+
unique: true,
73+
},
74+
tx_id: {
75+
type: 'bytea',
76+
notNull: true,
77+
},
78+
sender_address: {
79+
type: 'string',
80+
notNull: true,
81+
}
82+
});
83+
pgm.createIndex('nft_metadata', 'contract_id', { method: 'hash' });
84+
pgm.createTable('ft_metadata', {
85+
id: {
86+
type: 'serial',
87+
primaryKey: true,
88+
},
89+
name: {
90+
type: 'string',
91+
notNull: true,
92+
},
93+
token_uri: {
94+
type: 'string',
95+
notNull: true,
96+
},
97+
description: {
98+
type: 'string',
99+
notNull: true,
100+
},
101+
image_uri: {
102+
type: 'string',
103+
notNull: true,
104+
},
105+
image_canonical_uri: {
106+
type: 'string',
107+
notNull: true,
108+
},
109+
contract_id: {
110+
type: 'string',
111+
notNull: true,
112+
unique: true,
113+
},
114+
symbol: {
115+
type: 'string',
116+
notNull: true,
117+
},
118+
decimals: {
119+
type: 'integer',
120+
notNull: true,
121+
},
122+
tx_id: {
123+
type: 'bytea',
124+
notNull: true,
125+
},
126+
sender_address: {
127+
type: 'string',
128+
notNull: true,
129+
}
130+
});
131+
pgm.createIndex('ft_metadata', 'contract_id', { method: 'hash' });
132+
}

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
"test:integration:rosetta-cli:construction": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-construction.js --no-cache --runInBand; npm run devenv:stop-krypton\"",
3232
"test:integration:bns": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.bns.js --no-cache --runInBand; npm run devenv:stop-krypton\"",
3333
"test:integration:bns-e2e": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.bns-e2e.js --no-cache --runInBand; npm run devenv:stop-krypton\"",
34-
"test:integration:tokens-strict": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.tokens-strict.js --no-cache --runInBand; npm run devenv:stop-krypton\"",
35-
"test:integration:tokens-metadata": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.tokens-metadata.js --no-cache --runInBand; npm run devenv:stop-krypton\"",
3634
"test:integration:rpc": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.rpc.js --no-cache --runInBand; npm run devenv:stop-krypton\"",
3735
"test:integration:event-replay": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.event-replay.js --no-cache --runInBand; npm run devenv:stop\"",
3836
"test:integration:btc-faucet": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.bitcoind.yml up --force-recreate -V\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.btc-faucet.js --no-cache --runInBand; npm run devenv:stop\"",

src/api/controllers/db-controller.ts

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ import {
6363
} from '../../datastore/common';
6464
import { unwrapOptional, FoundOrNot, unixEpochToIso, EMPTY_HASH_256, ChainID } from '../../helpers';
6565
import { serializePostCondition, serializePostConditionMode } from '../serializers/post-conditions';
66-
import { getOperations, parseTransactionMemo } from '../../rosetta-helpers';
66+
import { getOperations, parseTransactionMemo } from '../../rosetta/rosetta-helpers';
6767
import { PgStore } from '../../datastore/pg-store';
6868
import { Pox2EventName } from '../../pox-helpers';
6969
import { logger } from '../../logger';
@@ -164,30 +164,6 @@ export function getTxStatus(txStatus: DbTxStatus | string): string {
164164
}
165165
}
166166

167-
type EventTypeString =
168-
| 'smart_contract_log'
169-
| 'stx_asset'
170-
| 'fungible_token_asset'
171-
| 'non_fungible_token_asset'
172-
| 'stx_lock';
173-
174-
export function getEventTypeString(eventTypeId: DbEventTypeId): EventTypeString {
175-
switch (eventTypeId) {
176-
case DbEventTypeId.SmartContractLog:
177-
return 'smart_contract_log';
178-
case DbEventTypeId.StxAsset:
179-
return 'stx_asset';
180-
case DbEventTypeId.FungibleTokenAsset:
181-
return 'fungible_token_asset';
182-
case DbEventTypeId.NonFungibleTokenAsset:
183-
return 'non_fungible_token_asset';
184-
case DbEventTypeId.StxLock:
185-
return 'stx_lock';
186-
default:
187-
throw new Error(`Unexpected DbEventTypeId: ${eventTypeId}`);
188-
}
189-
}
190-
191167
export function getAssetEventTypeString(
192168
assetEventTypeId: DbAssetEventTypeId
193169
): 'transfer' | 'mint' | 'burn' {

src/api/init.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import * as expressListEndpoints from 'express-list-endpoints';
3131
import { createMiddleware as createPrometheusMiddleware } from '@promster/express';
3232
import { createMicroblockRouter } from './routes/microblock';
3333
import { createStatusRouter } from './routes/status';
34-
import { createTokenRouter } from './routes/tokens/tokens';
34+
import { createTokenRouter } from './routes/tokens';
3535
import { createFeeRateRouter } from './routes/fee-rate';
3636
import { setResponseNonCacheable } from './controllers/cache-controller';
3737

0 commit comments

Comments
 (0)