Skip to content

Commit

Permalink
build: add ci and docker (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
RetricSu authored Jan 13, 2025
1 parent 66f6ffd commit 3219d95
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 54 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Lint and build

on: [pull_request, push]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v4
with:
version: 9

- name: Install dependencies
run: pnpm install
- name: Lint
run: pnpm lint
- name: Build
run: pnpm build
- run: pnpm fmt
- run: git diff --exit-code
41 changes: 41 additions & 0 deletions .github/workflows/pkg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Build and Publish Docker Image

on:
push:
branches: [ "master" ]

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
46 changes: 46 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Build stage
FROM node:20-alpine as builder

# Set working directory
WORKDIR /app

# Copy package files
COPY package.json pnpm-lock.yaml ./

# Install pnpm
RUN npm install -g pnpm

# Install dependencies
RUN pnpm install

# Copy source code
COPY . .

# Build TypeScript code
RUN pnpm build

# Production stage
FROM node:20-alpine

WORKDIR /app

# Copy package files
COPY package.json pnpm-lock.yaml ./

# Install pnpm
RUN npm install -g pnpm

# Install production dependencies only
RUN pnpm install --prod

# Copy built files from builder stage
COPY --from=builder /app/dist ./dist

# Expose port 3000 (from Config.apiHttpPort)
EXPOSE 3000

# Set environment variables
ENV NODE_ENV=production

# Start the application
CMD ["node", "dist/index.js"]
5 changes: 4 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
"linter": {
"enabled": true,
"rules": {
"recommended": true
"recommended": true,
"suspicious": {
"noShadowRestrictedNames": "warn"
}
}
},
"javascript": {
Expand Down
8 changes: 4 additions & 4 deletions src/api/sever.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express, { Request, Response } from "express";
import { DB } from "../db";
import { Hex } from "@ckb-ccc/core";
import type { Hex } from "@ckb-ccc/core";
import express, { type Request, type Response } from "express";
import type { DB } from "../db";
import { logger } from "../util/logger";

export function createServer(db: DB) {
Expand Down Expand Up @@ -52,7 +52,7 @@ export function createServer(db: DB) {
});

app.get("/tip-block-txs", async (_req: Request, res: Response) => {
const blockHeader: any = db.getTipBlockHeader();
const blockHeader = db.getTipBlockHeader();
if (!blockHeader) {
res.json({
error: "No tip block found",
Expand Down
23 changes: 0 additions & 23 deletions src/core/peer.ts

This file was deleted.

16 changes: 16 additions & 0 deletions src/core/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,19 @@ export interface JsonRpcPoolTransactionEntry {
fee: Hex;
timestamp: Hex;
}

export type DBBlockHeader = {
id: number;
compact_target: Hex;
dao: Hex;
epoch: Hex;
extra_hash: Hex;
block_hash: Hex;
nonce: Hex;
block_number: Hex;
parent_hash: Hex;
proposals_hash: Hex;
timestamp: number;
transactions_root: Hex;
version: Hex;
};
30 changes: 21 additions & 9 deletions src/core/ws.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { DB } from "../db";
import { type JsonRpcBlock } from "@ckb-ccc/core/advancedBarrel";
import {
type JsonRpcBlock,
type JsonRpcTransaction,
JsonRpcTransformers,
} from "@ckb-ccc/core/advancedBarrel";
import { WebSocket } from "ws";
import type { JsonRpcPoolTransactionEntry } from "./type";
import type { DB } from "../db";
import { logger } from "../util/logger";
import type {
JsonRpcPoolTransactionEntry,
JsonRpcTransactionView,
} from "./type";

export interface WebsocketTopicSubscriber {
id: string;
topic: string;
sub_id: string | undefined;
// biome-ignore lint: handler will be multiple types
handler: (data: any) => void;
}

Expand All @@ -30,31 +38,35 @@ export class Subscriber {
sub_id: undefined,
handler: (block: JsonRpcBlock) => {
this.db.saveBlockHeader(block.header);
block.proposals.forEach((txPid) => {
// handle proposals transactions
for (const txPid of block.proposals) {
this.db.updateBlockProposedTransaction(
txPid,
block.header.number,
block.header.hash,
+block.header.timestamp,
);
});
block.transactions.forEach((tx) => {
}
// handle committed transactions
for (const tx of block.transactions) {
this.db.updateCommittedTransaction(
tx,
block.header.number,
block.header.hash,
+block.header.timestamp,
);
});
}

logger.debug(`New block: ${+block.header.number}`);
logger.debug(
`proposal txs: ${block.proposals.length > 0 ? JSON.stringify(block.proposals) : "0"}`,
);
logger.debug(
`committed txs: ${JSON.stringify(
block.transactions.map((tx: any) =>
tx.hash.slice(0, 22),
block.transactions.map((tx) =>
JsonRpcTransformers.transactionTo(tx)
.hash()
.slice(0, 22),
),
)}`,
);
Expand Down
35 changes: 18 additions & 17 deletions src/db/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { type Hex } from "@ckb-ccc/core";
import type { Hex } from "@ckb-ccc/core";
import {
type JsonRpcBlockHeader,
type JsonRpcTransaction,
JsonRpcTransformers,
} from "@ckb-ccc/core/advancedBarrel";
import sqlite3 from "better-sqlite3";
import type { Database } from "better-sqlite3";
import type {
DBBlockHeader,
JsonRpcPoolTransactionEntry,
JsonRpcTransactionView,
} from "../core/type";
import { DepType, HashType, TransactionStatus } from "./type";
import {
JsonRpcBlockHeader,
JsonRpcTransaction,
JsonRpcTransformers,
} from "@ckb-ccc/core/advancedBarrel";
import { getNowTimestamp } from "../util/time";
import { DepType, HashType, TransactionStatus } from "./type";

export class DB {
private db: Database;
Expand Down Expand Up @@ -41,23 +42,23 @@ export class DB {
INSERT INTO cell_dep (transaction_id, o_tx_hash, o_index, dep_type)
VALUES (?, ?, ?, ?)
`);
transaction.cell_deps.forEach((dep) => {
for (const dep of transaction.cell_deps) {
cellDepStmt.run(
txId,
dep.out_point.tx_hash,
+dep.out_point.index,
DepType.fromString(dep.dep_type),
);
});
}

// Insert header deps
const headerDepStmt = this.db.prepare<[DBId, Hex]>(`
INSERT INTO header_dep (transaction_id, header_hash)
VALUES (?, ?)
`);
transaction.header_deps.forEach((hash) => {
for (const hash of transaction.header_deps) {
headerDepStmt.run(txId, hash);
});
}

// Helper function to insert script and return its ID
const insertScript = this.db.prepare<
Expand All @@ -74,14 +75,14 @@ export class DB {
INSERT INTO input (transaction_id, previous_output_tx_hash, previous_output_index, since)
VALUES (?, ?, ?, ?)
`);
transaction.inputs.forEach((input) => {
for (const input of transaction.inputs) {
inputStmt.run(
txId,
input.previous_output.tx_hash,
+input.previous_output.index,
input.since,
);
});
}

// Insert outputs
const outputStmt = this.db.prepare<
Expand Down Expand Up @@ -349,7 +350,7 @@ export class DB {

updateMempoolProposingTransaction(tx: JsonRpcPoolTransactionEntry) {
const getStmt = this.db.prepare<[Hex], { id: DBId }>(
`SELECT id From transactions WHERE tx_hash = ?`,
"SELECT id From transactions WHERE tx_hash = ?",
);
const txId = getStmt.get(tx.transaction.hash)?.id;
if (txId) {
Expand All @@ -373,7 +374,7 @@ export class DB {
reason: string,
) {
const getStmt = this.db.prepare<[Hex], { id: DBId }>(
`SELECT id From transactions WHERE tx_hash = ?`,
"SELECT id From transactions WHERE tx_hash = ?",
);
const txId = getStmt.get(tx.transaction.hash)?.id;
if (txId) {
Expand Down Expand Up @@ -404,7 +405,7 @@ export class DB {
const txHash = JsonRpcTransformers.transactionTo(tx).hash();

const getStmt = this.db.prepare<[Hex], { id: DBId }>(
`SELECT id From transactions WHERE tx_hash = ?`,
"SELECT id From transactions WHERE tx_hash = ?",
);
const txId = getStmt.get(txHash)?.id;
if (txId) {
Expand Down Expand Up @@ -492,7 +493,7 @@ export class DB {
}

getTipBlockHeader() {
const stmt = this.db.prepare(`
const stmt = this.db.prepare<[], DBBlockHeader>(`
SELECT * FROM block_header ORDER BY block_number DESC LIMIT 1
`);
return stmt.get();
Expand Down

0 comments on commit 3219d95

Please sign in to comment.