diff --git a/.github/workflows/deploy-randomness.yml b/.github/workflows/deploy-randomness.yml new file mode 100644 index 0000000000..6a3837794e --- /dev/null +++ b/.github/workflows/deploy-randomness.yml @@ -0,0 +1,91 @@ +name: Deploy Randomness + +on: + workflow_dispatch: + +env: + REGISTRY: ghcr.io + ORGANIZATION: happychaindevs + PM2_PROCESS_NAME: randomness + RANDOMNESS_DB_PATH: /home/randomness/randomness.sqlite + TXM_DB_PATH: /home/randomness/txm.sqlite + + +jobs: + deploy: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout code + uses: actions/checkout@v4.2.0 + + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Build code + run: | + make randomness.build + + - name: Copy files to server + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + key: ${{ secrets.SERVER_KEY }} + port: ${{ secrets.SERVER_PORT }} + source: "apps/randomness/build/*,node_modules/better-sqlite3,node_modules/bindings,node_modules/file-uri-to-path" + target: /home/deployer/randomness + strip_components: 1 + rm: true + + - name: Deploy randomness to server + uses: appleboy/ssh-action@v1.1.0 + with: + host: ${{ secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USERNAME }} + key: ${{ secrets.SERVER_KEY }} + port: ${{ secrets.SERVER_PORT }} + # We copy better-sqlite3, bindings, and file-uri-to-path separately because the bundled file does not include + # better-sqlite3 and its dependencies + script: | + chmod -R o+rX /home/deployer/randomness + mv /home/deployer/randomness /tmp + sudo -u randomness bash -c ' + rm -rf /home/randomness/build + rm -rf /home/randomness/node_modules + cp -r /tmp/randomness/randomness/build /home/randomness/build + + mkdir -p /home/randomness/node_modules + cp -r /tmp/randomness/better-sqlite3 /home/randomness/node_modules/better-sqlite3 + cp -r /tmp/randomness/bindings /home/randomness/node_modules/bindings + cp -r /tmp/randomness/file-uri-to-path /home/randomness/node_modules/file-uri-to-path + + cd /home/randomness + + rm -f .env + + cat > .env <<-EOF + export PRIVATE_KEY=${{ secrets.RANDOMNESS_PRIVATE_KEY }} + export TXM_DB_PATH=${{ env.TXM_DB_PATH }} + export RANDOMNESS_DB_PATH=${{ env.RANDOMNESS_DB_PATH }} + export ${{vars.RANDOMNESS_ENV}} + EOF + + npm rebuild + + pm2 delete ${{ env.PM2_PROCESS_NAME }} + + source .env && node ./build/migrate.es.js + + source .env && pm2 start ./build/index.es.js \ + --name ${{ env.PM2_PROCESS_NAME }} + pm2 save + ' + rm -rf /tmp/randomness \ No newline at end of file diff --git a/Makefile b/Makefile index a3f327a0d7..56ee5ce415 100644 --- a/Makefile +++ b/Makefile @@ -339,6 +339,11 @@ contracts.build: cd contracts && make build .PHONY: contracts.build +randomness.build: setup.ts shared.build + cd packages/txm && make build + cd apps/randomness && make build +.PHONY: randomness.build + # ================================================================================================== # DOCS diff --git a/apps/randomness/Makefile b/apps/randomness/Makefile index d5913ff6df..f1bc6abca8 100644 --- a/apps/randomness/Makefile +++ b/apps/randomness/Makefile @@ -18,8 +18,8 @@ start: ## Starts the randomness service .PHONY: start migrate: ## Runs pending migrations - tsx --env-file=.env src/migrate.ts -.PHONY: migrate + node --env-file=.env dist/migrate.es.js +PHONY: migrate link-anvil: rm src/ABI/random.ts diff --git a/apps/randomness/migrations/Migration20241210123000.ts b/apps/randomness/src/db/migrations/Migration20241210123000.ts similarity index 85% rename from apps/randomness/migrations/Migration20241210123000.ts rename to apps/randomness/src/db/migrations/Migration20241210123000.ts index c7661f7a34..ed6b224e36 100644 --- a/apps/randomness/migrations/Migration20241210123000.ts +++ b/apps/randomness/src/db/migrations/Migration20241210123000.ts @@ -1,5 +1,5 @@ import type { Kysely } from "kysely" -import type { Database } from "../src/db/types" +import type { Database } from "../types" export async function up(db: Kysely) { await db.schema @@ -12,3 +12,5 @@ export async function up(db: Kysely) { .addColumn("status", "text", (col) => col.notNull()) .execute() } + +export const migration20241210123000 = { up } diff --git a/apps/randomness/migrations/Migration20241219104500.ts b/apps/randomness/src/db/migrations/Migration20241219104500.ts similarity index 80% rename from apps/randomness/migrations/Migration20241219104500.ts rename to apps/randomness/src/db/migrations/Migration20241219104500.ts index 7dca9c8df6..4fba013cb2 100644 --- a/apps/randomness/migrations/Migration20241219104500.ts +++ b/apps/randomness/src/db/migrations/Migration20241219104500.ts @@ -1,5 +1,5 @@ import type { Kysely } from "kysely" -import type { Database } from "../src/db/types" +import type { Database } from "../types" export async function up(db: Kysely) { await db.schema @@ -10,3 +10,5 @@ export async function up(db: Kysely) { .addColumn("transactionIntentId", "text") .execute() } + +export const migration20241219104500 = { up } diff --git a/apps/randomness/src/db/migrations/index.ts b/apps/randomness/src/db/migrations/index.ts new file mode 100644 index 0000000000..afd8329be5 --- /dev/null +++ b/apps/randomness/src/db/migrations/index.ts @@ -0,0 +1,7 @@ +import { migration20241210123000 } from "./Migration20241210123000" +import { migration20241219104500 } from "./Migration20241219104500" + +export const migrations = { + "20241210123000": migration20241210123000, + "20241219104500": migration20241219104500, +} diff --git a/apps/randomness/src/index.ts b/apps/randomness/src/index.ts index 870db1bec2..3a9669ba7b 100644 --- a/apps/randomness/src/index.ts +++ b/apps/randomness/src/index.ts @@ -27,7 +27,9 @@ class RandomnessService { rpc: { url: env.RPC_URL, allowDebug: true, + pollingInterval: 250, }, + maxPriorityFeePerGas: 10n, }) this.transactionFactory = new TransactionFactory(this.txm, env.RANDOM_CONTRACT_ADDRESS, env.PRECOMMIT_DELAY) this.drandService = new DrandService(this.drandRepository, this.transactionFactory) diff --git a/apps/randomness/src/migrate.ts b/apps/randomness/src/migrate.ts index c69b1f3af4..4fdbaef2ff 100644 --- a/apps/randomness/src/migrate.ts +++ b/apps/randomness/src/migrate.ts @@ -1,19 +1,20 @@ -import { promises as fs } from "node:fs" -import path from "node:path" -import { fileURLToPath } from "node:url" -import { FileMigrationProvider, Migrator } from "kysely" +import { type Migration, type MigrationProvider, Migrator } from "kysely" import { db } from "./db/driver" +import { migrations } from "./db/migrations" +import "@happy.tech/txm/migrate" -const dirname = path.dirname(fileURLToPath(import.meta.url)) +class ObjectMigrationProvider implements MigrationProvider { + constructor(private migrations: Record) {} + + async getMigrations(): Promise> { + return this.migrations + } +} async function migrateToLatest() { const migrator = new Migrator({ db, - provider: new FileMigrationProvider({ - fs, - path, - migrationFolder: path.join(dirname, "../migrations"), - }), + provider: new ObjectMigrationProvider(migrations), }) const { error, results } = await migrator.migrateToLatest() diff --git a/apps/randomness/tsconfig.json b/apps/randomness/tsconfig.json index c183c225b5..626aea6852 100644 --- a/apps/randomness/tsconfig.json +++ b/apps/randomness/tsconfig.json @@ -1,4 +1,4 @@ { "extends": ["../../support/configs/tsconfig.base.json"], - "include": ["*.ts", "src", "migrations"] + "include": ["*.ts", "src"] } diff --git a/packages/txm/build.config.ts b/packages/txm/build.config.ts index 3697d32c09..1ee0717c15 100644 --- a/packages/txm/build.config.ts +++ b/packages/txm/build.config.ts @@ -1,6 +1,7 @@ import { defineConfig } from "@happy.tech/happybuild" export default defineConfig({ + exports: [".", "./migrate"], bunConfig: { minify: false, target: "node", diff --git a/packages/txm/lib/NonceManager.ts b/packages/txm/lib/NonceManager.ts index 776543d6e8..861986f2b7 100644 --- a/packages/txm/lib/NonceManager.ts +++ b/packages/txm/lib/NonceManager.ts @@ -41,6 +41,7 @@ export class NonceManager { const blockchainNonce = await this.txmgr.viemClient.getTransactionCount({ address: address, + blockTag: "pending", }) const highestDbNonce = this.txmgr.transactionRepository.getHighestNonce() diff --git a/packages/txm/migrations/Migration20241111163800.ts b/packages/txm/lib/db/migrations/Migration20241111163800.ts similarity index 84% rename from packages/txm/migrations/Migration20241111163800.ts rename to packages/txm/lib/db/migrations/Migration20241111163800.ts index 068afd2da0..62c78f623d 100644 --- a/packages/txm/migrations/Migration20241111163800.ts +++ b/packages/txm/lib/db/migrations/Migration20241111163800.ts @@ -1,7 +1,7 @@ import type { Kysely } from "kysely" -import type { Database } from "../lib/db/types" +import type { Database } from "../types" -export async function up(db: Kysely) { +async function up(db: Kysely) { await db.schema .createTable("transaction") .addColumn("intentId", "text", (col) => col.notNull()) @@ -16,3 +16,5 @@ export async function up(db: Kysely) { .addColumn("metadata", "json") .execute() } + +export const migration20241111163800 = { up } diff --git a/packages/txm/migrations/Migration20241111223000.ts b/packages/txm/lib/db/migrations/Migration20241111223000.ts similarity index 78% rename from packages/txm/migrations/Migration20241111223000.ts rename to packages/txm/lib/db/migrations/Migration20241111223000.ts index 0a8766c8a9..a188ce93e5 100644 --- a/packages/txm/migrations/Migration20241111223000.ts +++ b/packages/txm/lib/db/migrations/Migration20241111223000.ts @@ -1,13 +1,15 @@ import type { Kysely } from "kysely" -import type { Database } from "../lib/db/types" +import type { Database } from "../types" /* SQLite does not have native time types. The SQL interface allows arbitrary type names including "DATE" and "DATETIME", but this is invalid in this API, and results in "NUMERIC" affinity instead of "INTEGER" affinity, which is the one we want here */ -export async function up(db: Kysely) { +async function up(db: Kysely) { await db.schema.alterTable("transaction").addColumn("createdAt", "integer").execute() await db.schema.alterTable("transaction").addColumn("updatedAt", "integer").execute() } + +export const migration20241111223000 = { up } diff --git a/packages/txm/migrations/Migration20241205104400.ts b/packages/txm/lib/db/migrations/Migration20241205104400.ts similarity index 57% rename from packages/txm/migrations/Migration20241205104400.ts rename to packages/txm/lib/db/migrations/Migration20241205104400.ts index ca6208919e..ee07e57120 100644 --- a/packages/txm/migrations/Migration20241205104400.ts +++ b/packages/txm/lib/db/migrations/Migration20241205104400.ts @@ -1,9 +1,11 @@ import type { Kysely } from "kysely" -import type { Database } from "../lib/db/types" +import type { Database } from "../types" -export async function up(db: Kysely) { +async function up(db: Kysely) { await db.schema .alterTable("transaction") .addColumn("from", "text", (col) => col.notNull()) .execute() } + +export const migration20241205104400 = { up } diff --git a/packages/txm/migrations/Migration20250121110600.ts b/packages/txm/lib/db/migrations/Migration20250121110600.ts similarity index 67% rename from packages/txm/migrations/Migration20250121110600.ts rename to packages/txm/lib/db/migrations/Migration20250121110600.ts index 137b0e4228..ebb61706af 100644 --- a/packages/txm/migrations/Migration20250121110600.ts +++ b/packages/txm/lib/db/migrations/Migration20250121110600.ts @@ -1,6 +1,8 @@ import type { Kysely } from "kysely" -import type { Database } from "../lib/db/types" +import type { Database } from "../types" export async function up(db: Kysely) { await db.schema.alterTable("transaction").addColumn("collectionBlock", "integer").execute() } + +export const migration20250121110600 = { up } diff --git a/packages/txm/lib/db/migrations/index.ts b/packages/txm/lib/db/migrations/index.ts new file mode 100644 index 0000000000..532b081b40 --- /dev/null +++ b/packages/txm/lib/db/migrations/index.ts @@ -0,0 +1,11 @@ +import { migration20241111163800 } from "./Migration20241111163800" +import { migration20241111223000 } from "./Migration20241111223000" +import { migration20241205104400 } from "./Migration20241205104400" +import { migration20250121110600 } from "./Migration20250121110600" + +export const migrations = { + "20241111163800": migration20241111163800, + "20241111223000": migration20241111223000, + "20241205104400": migration20241205104400, + "20250121110600": migration20250121110600, +} diff --git a/packages/txm/lib/migrate.ts b/packages/txm/lib/migrate.ts index c69b1f3af4..2aa47651a3 100644 --- a/packages/txm/lib/migrate.ts +++ b/packages/txm/lib/migrate.ts @@ -1,19 +1,19 @@ -import { promises as fs } from "node:fs" -import path from "node:path" -import { fileURLToPath } from "node:url" -import { FileMigrationProvider, Migrator } from "kysely" +import { type Migration, type MigrationProvider, Migrator } from "kysely" import { db } from "./db/driver" +import { migrations } from "./db/migrations" -const dirname = path.dirname(fileURLToPath(import.meta.url)) +class ObjectMigrationProvider implements MigrationProvider { + constructor(private migrations: Record) {} -async function migrateToLatest() { + async getMigrations(): Promise> { + return this.migrations + } +} + +export async function migrateToLatest() { const migrator = new Migrator({ db, - provider: new FileMigrationProvider({ - fs, - path, - migrationFolder: path.join(dirname, "../migrations"), - }), + provider: new ObjectMigrationProvider(migrations), }) const { error, results } = await migrator.migrateToLatest() diff --git a/packages/txm/package.json b/packages/txm/package.json index dc62c63e67..4eefdde484 100644 --- a/packages/txm/package.json +++ b/packages/txm/package.json @@ -10,6 +10,10 @@ ".": { "default": "./dist/index.es.js", "types": "./dist/index.es.d.ts" + }, + "./migrate": { + "default": "./dist/migrate.es.js", + "types": "./dist/migrate.es.d.ts" } }, "dependencies": { diff --git a/packages/txm/tsconfig.json b/packages/txm/tsconfig.json index b3f850fd63..fe5aa3c2d0 100644 --- a/packages/txm/tsconfig.json +++ b/packages/txm/tsconfig.json @@ -9,5 +9,5 @@ "ts-node": ["./node_modules/ts-node/dist/bin.js"] } }, - "include": ["lib", "*.ts", "package.json", "migrations"] + "include": ["lib", "*.ts", "package.json"] }