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

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

This file was deleted.

16 changes: 16 additions & 0 deletions crates/datastore/migrations/1757444171_create_bundles_table.sql
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'bundle_state') THEN
CREATE TYPE bundle_state AS ENUM (
'Ready',
'BundleLimit',
'AccountLimits',
'GlobalLimits',
'IncludedInFlashblock',
'IncludedInBlock'
);
END IF;
END$$;


-- Create bundles table
CREATE TABLE IF NOT EXISTS bundles (
id UUID PRIMARY KEY,
"state" bundle_state NOT NULL,

senders CHAR(42)[],
minimum_base_fee BIGINT, -- todo find a larger type
Expand Down
23 changes: 19 additions & 4 deletions crates/datastore/src/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ use sqlx::PgPool;
use tracing::info;
use uuid::Uuid;

#[derive(Debug, Clone, sqlx::Type)]
#[sqlx(type_name = "bundle_state", rename_all = "PascalCase")]
pub enum BundleState {
Ready,
BundleLimit,
AccountLimits,
GlobalLimits,
IncludedInFlashblock,
IncludedInBlock,
}

#[derive(sqlx::FromRow, Debug)]
struct BundleRow {
senders: Option<Vec<String>>,
Expand All @@ -22,6 +33,7 @@ struct BundleRow {
block_number: Option<i64>,
min_timestamp: Option<i64>,
max_timestamp: Option<i64>,
state: BundleState,
}

/// Filter criteria for selecting bundles
Expand Down Expand Up @@ -60,6 +72,7 @@ pub struct BundleWithMetadata {
pub txn_hashes: Vec<TxHash>,
pub senders: Vec<Address>,
pub min_base_fee: i64,
pub state: BundleState,
}

/// PostgreSQL implementation of the BundleDatastore trait
Expand Down Expand Up @@ -137,6 +150,7 @@ impl PostgresDatastore {
txn_hashes: parsed_txn_hashes?,
senders: parsed_senders?,
min_base_fee: row.minimum_base_fee.unwrap_or(0),
state: row.state,
})
}

Expand Down Expand Up @@ -198,14 +212,15 @@ impl BundleDatastore for PostgresDatastore {
sqlx::query!(
r#"
INSERT INTO bundles (
id, senders, minimum_base_fee, txn_hashes,
id, "state", senders, minimum_base_fee, txn_hashes,
txs, reverting_tx_hashes, dropping_tx_hashes,
block_number, min_timestamp, max_timestamp,
created_at, updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, NOW(), NOW())
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, NOW(), NOW())
"#,
id,
BundleState::Ready as BundleState,
&senders,
minimum_base_fee,
&txn_hashes,
Expand All @@ -226,7 +241,7 @@ impl BundleDatastore for PostgresDatastore {
let result = sqlx::query_as::<_, BundleRow>(
r#"
SELECT senders, minimum_base_fee, txn_hashes, txs, reverting_tx_hashes,
dropping_tx_hashes, block_number, min_timestamp, max_timestamp
dropping_tx_hashes, block_number, min_timestamp, max_timestamp, "state"
FROM bundles
WHERE id = $1
"#,
Expand Down Expand Up @@ -266,7 +281,7 @@ impl BundleDatastore for PostgresDatastore {
let rows = sqlx::query_as::<_, BundleRow>(
r#"
SELECT senders, minimum_base_fee, txn_hashes, txs, reverting_tx_hashes,
dropping_tx_hashes, block_number, min_timestamp, max_timestamp
dropping_tx_hashes, block_number, min_timestamp, max_timestamp, "state"
FROM bundles
WHERE minimum_base_fee >= $1
AND (block_number = $2 OR block_number IS NULL OR block_number = 0 OR $2 = 0)
Expand Down
6 changes: 5 additions & 1 deletion crates/datastore/tests/datastore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use testcontainers_modules::{
postgres,
testcontainers::{ContainerAsync, runners::AsyncRunner},
};
use tips_datastore::postgres::BundleFilter;
use tips_datastore::postgres::{BundleFilter, BundleState};
use tips_datastore::{BundleDatastore, PostgresDatastore};

struct TestHarness {
Expand Down Expand Up @@ -96,6 +96,10 @@ async fn insert_and_get() -> eyre::Result<()> {
let metadata = retrieved_bundle_with_metadata.unwrap();
let retrieved_bundle = &metadata.bundle;

assert!(
matches!(metadata.state, BundleState::Ready),
"Bundle should default to Ready state"
);
assert_eq!(retrieved_bundle.txs.len(), test_bundle.txs.len());
assert_eq!(retrieved_bundle.block_number, test_bundle.block_number);
assert_eq!(retrieved_bundle.min_timestamp, test_bundle.min_timestamp);
Expand Down
6 changes: 3 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fix:
cargo fmt --all
cargo clippy --fix --allow-dirty --allow-staged
# UI
cd ui && npx biome check --fix
cd ui && npx biome check --write --unsafe

create-migration name:
touch crates/datastore/migrations/$(date +%s)_{{ name }}.sql
Expand Down Expand Up @@ -72,10 +72,10 @@ start-except programs: stop-all

### RUN SERVICES ###
deps-reset:
docker compose down && docker compose rm && rm -rf data/ && mkdir -p data/postgres data/kafka data/minio && docker compose up -d
COMPOSE_FILE=docker-compose.yml:docker-compose.tips.yml docker compose down && docker compose rm && rm -rf data/ && mkdir -p data/postgres data/kafka data/minio && docker compose up -d

deps:
docker compose down && docker compose rm && docker compose up -d
COMPOSE_FILE=docker-compose.yml:docker-compose.tips.yml docker compose down && docker compose rm && docker compose up -d

audit:
cargo run --bin tips-audit
Expand Down
10 changes: 9 additions & 1 deletion ui/src/app/api/bundles/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ import { bundles } from "@/db/schema";

export interface Bundle {
id: string;
txnHashes: string[] | null;
txnHashes: string[];
state:
| "Ready"
| "BundleLimit"
| "AccountLimits"
| "GlobalLimits"
| "IncludedInFlashblock"
| "IncludedInBlock";
}

export async function GET() {
Expand All @@ -13,6 +20,7 @@ export async function GET() {
.select({
id: bundles.id,
txnHashes: bundles.txnHashes,
state: bundles.state,
})
.from(bundles);

Expand Down
33 changes: 27 additions & 6 deletions ui/src/app/bundles/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,33 @@ export default function BundlesPage() {
href={`/bundles/${bundle.id}`}
className="block p-3 border rounded-lg bg-white/5 hover:bg-white/10 transition-colors"
>
<span className="font-mono text-sm">
{bundle.id}
{" ("}
{bundle.txnHashes?.join(", ") || "No transactions"}
{")"}
</span>
<div className="flex flex-col gap-1">
<span className="font-mono text-sm">{bundle.id}</span>
<div className="flex items-center gap-2 text-xs">
<span
className={`px-2 py-1 rounded font-medium ${
bundle.state === "Ready"
? "bg-blue-100 text-blue-600"
: bundle.state === "BundleLimit"
? "bg-yellow-100 text-yellow-600"
: bundle.state === "AccountLimits"
? "bg-orange-100 text-orange-600"
: bundle.state === "GlobalLimits"
? "bg-red-100 text-red-600"
: bundle.state === "IncludedInFlashblock"
? "bg-purple-100 text-purple-600"
: bundle.state === "IncludedInBlock"
? "bg-green-100 text-green-600"
: "bg-gray-100 text-gray-600"
}`}
>
{bundle.state}
</span>
<span className="text-gray-500">
{bundle.txnHashes?.join(", ") || "No transactions"}
</span>
</div>
</div>
</Link>
</li>
))}
Expand Down
2 changes: 0 additions & 2 deletions ui/src/db/relations.ts
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
import { relations } from "drizzle-orm/relations";
import {} from "./schema";
12 changes: 11 additions & 1 deletion ui/src/db/schema.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import { sql } from "drizzle-orm";
import {
bigint,
char,
pgEnum,
pgTable,
text,
timestamp,
uuid,
} from "drizzle-orm/pg-core";

export const bundleState = pgEnum("bundle_state", [
"Ready",
"BundleLimit",
"AccountLimits",
"GlobalLimits",
"IncludedInFlashblock",
"IncludedInBlock",
]);

export const bundles = pgTable("bundles", {
id: uuid().primaryKey().notNull(),
state: bundleState().notNull(),
senders: char({ length: 42 }).array(),
// You can use { mode: "bigint" } if numbers are exceeding js number limitations
minimumBaseFee: bigint("minimum_base_fee", { mode: "number" }),
Expand Down