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
11 changes: 10 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,13 @@ TIPS_MAINTENANCE_RPC_NODE=http://localhost:2222
TIPS_MAINTENANCE_KAFKA_BROKERS=localhost:9092
TIPS_MAINTENANCE_KAFKA_TOPIC=tips-audit
TIPS_MAINTENANCE_POLL_INTERVAL_MS=250
TIPS_MAINTENANCE_LOG_LEVEL=info
TIPS_MAINTENANCE_LOG_LEVEL=info

# TIPS UI
TIPS_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
TIPS_UI_AWS_REGION=us-east-1
TIPS_UI_S3_BUCKET_NAME=tips
TIPS_UI_S3_CONFIG_TYPE=manual
TIPS_UI_S3_ENDPOINT=http://localhost:7000
TIPS_UI_S3_ACCESS_KEY_ID=minioadmin
TIPS_UI_S3_SECRET_ACCESS_KEY=minioadmin
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml → .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
name: CI
name: Rust
permissions:
contents: read

on:
push:
Expand Down
54 changes: 54 additions & 0 deletions .github/workflows/ui.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: UI
permissions:
contents: read

on:
push:
branches: [ master ]
paths: ['ui/**']
pull_request:
branches: [ master ]
paths: ['ui/**']

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
cache-dependency-path: ui/yarn.lock
- run: cp .env.example ui/.env
- run: cd ui && yarn install
- run: cd ui && yarn lint

type-check:
name: Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
cache-dependency-path: ui/yarn.lock
- run: cp .env.example ui/.env
- run: cd ui && yarn install
- run: cd ui && npx tsc --noEmit

build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
cache-dependency-path: ui/yarn.lock
- run: cp .env.example ui/.env
- run: cd ui && yarn install
- run: cd ui && yarn build
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Rust
/target/

# NextJS
/ui/.next
/ui/node_modules

# Local Dev
/data/

Expand All @@ -14,4 +18,8 @@ Thumbs.db

# Environment variables
.env
.env.local
/ui/.env

# Claude
/.claude
/ui/.claude
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ The main entry point that provides a JSON-RPC API for receiving transactions and

### 🔨 Maintenance (`crates/maintenance`)
A service that maintains the health of the TIPS DataStore, by removing stale or included bundles.

### 🖥️ UI (`ui`)
A debug UI for viewing the state of the bundle store and S3.
19 changes: 17 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
### DEVELOPMENT COMMANDS ###
ci:
# Rust
cargo fmt --all -- --check
cargo clippy -- -D warnings
cargo build
cargo test
# UI
cd ui && npm run lint
cd ui && npm run build

fix:
# Rust
cargo fmt --all
cargo clippy --fix --allow-dirty --allow-staged
# UI
cd ui && npx biome check --fix

create-migration name:
touch crates/datastore/migrations/$(date +%s)_{{ name }}.sql

sync:
sync: deps-reset
### DATABASE ###
cargo sqlx prepare -D postgresql://postgres:postgres@localhost:5432/postgres --workspace --all --no-dotenv
cd ui && npx drizzle-kit pull --dialect=postgresql --url=postgresql://postgres:postgres@localhost:5432/postgres
cd ui && mv ./drizzle/relations.ts ./src/db/
cd ui && mv ./drizzle/schema.ts ./src/db/
cd ui && rm -rf ./drizzle
### ENV ###
cp .env.example .env
cp .env.example ./ui/.env

### RUN SERVICES ###
deps-reset:
Expand All @@ -32,4 +44,7 @@ ingress:
cargo run --bin tips-ingress

maintenance:
cargo run --bin tips-maintenance
cargo run --bin tips-maintenance

ui:
cd ui && yarn dev
41 changes: 41 additions & 0 deletions ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
37 changes: 37 additions & 0 deletions ui/biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.next", "!dist", "!build"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noUnknownAtRules": "off"
}
},
"domains": {
"next": "recommended",
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
12 changes: 12 additions & 0 deletions ui/drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineConfig } from "drizzle-kit";

export default defineConfig({
schema: "./src/db/schema.ts",
out: "./drizzle",
dialect: "postgresql",
dbCredentials: {
url:
process.env.TIPS_DATABASE_URL ||
"postgresql://postgres:postgres@localhost:5432/postgres",
},
});
7 changes: 7 additions & 0 deletions ui/next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
/* config options here */
};

export default nextConfig;
31 changes: 31 additions & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "ui",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack",
"start": "next start",
"lint": "biome check",
"format": "biome format --write"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.888.0",
"drizzle-kit": "^0.31.4",
"drizzle-orm": "^0.44.5",
"next": "15.5.3",
"pg": "^8.16.3",
"react": "19.1.0",
"react-dom": "19.1.0"
},
"devDependencies": {
"@biomejs/biome": "2.2.0",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/pg": "^8.15.5",
"@types/react": "^19",
"@types/react-dom": "^19",
"tailwindcss": "^4",
"typescript": "^5"
}
}
5 changes: 5 additions & 0 deletions ui/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const config = {
plugins: ["@tailwindcss/postcss"],
};

export default config;
34 changes: 34 additions & 0 deletions ui/src/app/api/bundle/[uuid]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { type NextRequest, NextResponse } from "next/server";
import { type BundleEvent, getBundleHistory } from "@/lib/s3";

export interface BundleHistoryResponse {
uuid: string;
history: BundleEvent[];
}

export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ uuid: string }> },
) {
try {
const { uuid } = await params;

const bundle = await getBundleHistory(uuid);
if (!bundle) {
return NextResponse.json({ error: "Bundle not found" }, { status: 404 });
}

const response: BundleHistoryResponse = {
uuid,
history: bundle.history,
};

return NextResponse.json(response);
} catch (error) {
console.error("Error fetching bundle data:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
);
}
}
15 changes: 15 additions & 0 deletions ui/src/app/api/bundles/all/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { NextResponse } from "next/server";
import { listAllBundleKeys } from "@/lib/s3";

export async function GET() {
try {
const bundleKeys = await listAllBundleKeys();
return NextResponse.json(bundleKeys);
} catch (error) {
console.error("Error fetching all bundle keys:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
);
}
}
27 changes: 27 additions & 0 deletions ui/src/app/api/bundles/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { NextResponse } from "next/server";
import { db } from "@/db";
import { bundles } from "@/db/schema";

export interface Bundle {
id: string;
txnHashes: string[] | null;
}

export async function GET() {
try {
const allBundles = await db
.select({
id: bundles.id,
txnHashes: bundles.txnHashes,
})
.from(bundles);

return NextResponse.json(allBundles);
} catch (error) {
console.error("Error fetching bundles:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
);
}
}
Loading