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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.26.1] - 2026-10-21

### Fixed
- Installed wget in the decoder image so the compose healthcheck can probe /live.

## [0.26.0] - 2026-10-20

### Added
Expand Down
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ RUN npm ci --omit=dev

FROM node:22-bookworm-slim@sha256:c3de60bf2f9dd0ac6370e6117950ff62d6e339527e7472301c9c78a017978392 AS decoder
WORKDIR /XChainDecoder
# wget is not in node:22-bookworm-slim. The compose healthcheck (owned by
# xchain-node) probes GET /live with wget, so without it every decoder reads
# unhealthy while /live answers 200 healthy.
RUN apt-get update \
&& apt-get install -y --no-install-recommends wget \
&& rm -rf /var/lib/apt/lists/*
COPY ./package.json /XChainDecoder/package.json
COPY ./package-lock.json /XChainDecoder/package-lock.json
COPY --from=dependencies /XChainDecoder/node_modules /XChainDecoder/node_modules
Expand Down
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "xchain-decoder",
"description": "xchain-decoder decodes XChain platform transactions from a given blockchain and populates a database with the decoded data.",
"version": "0.26.0",
"version": "0.26.1",
"license": "AGPL-3.0-or-later",
"repository": {
"type": "git",
Expand Down
23 changes: 23 additions & 0 deletions test/unit/sql_no_timestamp_columns.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,23 @@ const Database = require('../../src/db.js');
const ROOT_DIR = path.join(__dirname, '..', '..');
const SQL_DIR = path.join(ROOT_DIR, 'src', 'sql');
const MIGRATION_STATEMENTS = path.join(ROOT_DIR, 'src', 'db', 'migration_statements.js');
const MIGRATION_LEDGER = path.join(ROOT_DIR, 'src', 'db', 'migration_ledger.js');
const FIRST_SEEN_MIGRATION = path.join(
SQL_DIR,
'migrations',
'2026-09-27-mempool-first-seen-datetime.sql'
);

function assertLedgerAlterDeclaresDatetime(source){
const code = source
.replace(/\/\*[\s\S]*?\*\//g, '')
.replace(/^\s*\/\/.*$/gm, '');
const alter = code.match(/ALTER\s+TABLE\s+schema_migrations\s+MODIFY\s+applied_at\s+([A-Za-z]+)/i);

assert.ok(alter, 'missing ALTER TABLE schema_migrations MODIFY applied_at');
assert.strictEqual(alter[1].toUpperCase(), 'DATETIME', `applied_at ALTER declares ${alter[1]}`);
}

describe('SQL DATETIME completeness', function () {
it('declares no TIMESTAMP columns in top-level SQL definitions', function () {
const offenders = [];
Expand Down Expand Up @@ -75,3 +86,15 @@ describe('SQL DATETIME completeness', function () {
assert.strictEqual(db.connectionParams.timezone, 'Z');
});
});

describe('migration ledger applied_at ALTER', function () {
it('declares the migration_ledger.js applied_at ALTER as DATETIME', function () {
assertLedgerAlterDeclaresDatetime(fs.readFileSync(MIGRATION_LEDGER, 'utf8'));
});

it('rejects a migration_ledger.js applied_at ALTER declared as TIMESTAMP', function () {
const fixture = "await conn.query('ALTER TABLE schema_migrations MODIFY applied_at TIMESTAMP NOT NULL');";

assert.throws(() => assertLedgerAlterDeclaresDatetime(fixture), /TIMESTAMP/);
});
});
Loading