Skip to content
Closed
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ db.sqlite*
.pnpm-store
/deploy
.envs/
.vercel
32 changes: 32 additions & 0 deletions .vercelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Reduce deployment size (Vercel 10MB request limit)
# Dependencies and build outputs
**/node_modules/
**/.pnpm-store/
**/dist/
**/.turbo/
**/out/
**/cache/
**/artifacts/

# Foundry / contracts (lib is recreated by install-foundry.sh on Vercel)
contracts/lib/
contracts/out/
contracts/cache/
contracts/broadcast/
contracts/report/
contracts/coverage/
contracts/docs/

# Other large dirs
lodestar/
polkadot-sdk/
relaychain/
go/
control/target/
gas-estimator/target/
**/.git/
**/.cargo/
**/.rustup/
**/states/
**/deploy/
**/.vercel/
2 changes: 2 additions & 0 deletions web/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.deps
.pnpm-store
.turbo
.vercel
scripts/.foundry
10 changes: 10 additions & 0 deletions web/.vercelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Keep deployment under Vercel 10MB limit
node_modules/
.turbo/
**/dist/
**/.next/
.foundry/
scripts/.foundry/
*.log
.env*.local
.vercel/
20 changes: 20 additions & 0 deletions web/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Vercel serverless API

## `/api/monitor`

Runs the Snowbridge monitor (bridge status, channel status, relayer/sovereign balances, indexer status) and sends metrics to CloudWatch. Used by Vercel Cron for periodic runs.

- **Cron**: Every 15 minutes (`*/15 * * * *`). Configure in `vercel.json`; change `schedule` to adjust.
- **Auth**: Set `CRON_SECRET` in Vercel (Project → Settings → Environment Variables). Vercel sends it as `Authorization: Bearer <CRON_SECRET>` when invoking the cron.
- **Env**: Same as the CLI monitor: `NODE_ENV`, RPC URLs (`BEACON_RPC_URL`, `ETHEREUM_RPC_URL_*`, `PARACHAIN_RPC_URL_*`, `RELAY_CHAIN_RPC_URL`), and AWS/CloudWatch vars used by `sendMetrics` in `packages/operations`.

Build must produce `packages/operations/dist/` (e.g. run `pnpm build` from repo root or `web` so that `@snowbridge/operations` is built).

### Build (contract-types + Foundry)

The build depends on `@snowbridge/contract-types`, which runs `forge build` in `contracts/` then typechain. So Foundry must be available in the Vercel build.

- **Root Directory**: Keep as **`web`**. The full repo is cloned, so from `web/packages/contract-types`, `../../../contracts` correctly points at the repo’s `contracts/` folder.
- **Node**: Use **Node 20.x** (set in Project → Settings → General). Needed for GLIBC compatibility with Foundry binaries.
- **Install / Build**: `vercel.json` uses `installCommand: pnpm install && bash scripts/install-foundry.sh` and `buildCommand: pnpm run build:vercel`. The install script downloads the official Foundry nightly tarball from GitHub (`foundry_nightly_linux_amd64.tar.gz`) into `web/scripts/.foundry/bin` (on CI/Vercel), installs forge deps in `contracts/`, and runs `forge build`. The build script adds `scripts/.foundry/bin`, `.foundry/bin`, and `~/.foundry/bin` to PATH so `forge` is found, then runs `forge build` in `../contracts` and the full turbo build.
- If Foundry install fails (e.g. network), the install script exits non‑zero (due to `set -e`) and the Vercel build fails. `@snowbridge/contract-types` will only run `tsc` without invoking `forge` if pre-generated `src/` already exists and the build reaches that step.
37 changes: 37 additions & 0 deletions web/api/monitor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import "dotenv/config";
import type { VercelRequest, VercelResponse } from "@vercel/node";
import { monitor } from "../packages/operations/dist/src/monitor";

export const config = {
maxDuration: 60,
};

export default async function handler(req: VercelRequest, res: VercelResponse) {
if (req.method !== "GET") {
res.setHeader("Allow", "GET");
return res.status(405).json({ error: "Method not allowed" });
}

const cronSecret = process.env.CRON_SECRET;
if (!cronSecret) {
return res.status(503).json({
error: "Service unavailable",
message: "CRON_SECRET is not configured",
});
}
const authHeader = req.headers.authorization;
if (authHeader !== `Bearer ${cronSecret}`) {
return res.status(401).json({ error: "Unauthorized" });
}

try {
const metrics = await monitor();
return res.status(200).json({ ok: true, name: metrics.name });
} catch (error) {
console.error("Monitor error:", error);
return res.status(500).json({
error: "Monitor failed",
message: "Monitor failed",
});
}
}
24 changes: 22 additions & 2 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,39 @@
},
"scripts": {
"preinstall": "npx only-allow pnpm",
"build": "turbo run build --concurrency=1 --no-cache",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is --no-cache removed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise, the Vercel build process will fail. I can't find the detailed error messages right now, but there are also some warning messages in my local setup, which suggest that this option parameter may be deprecated.

(base) ➜  web git:(ron/monitor-by-vercel) pnpm build
> @snowbridge/web@ build /Users/yangrong/Projects/snowbridge/web
> turbo run build --concurrency=1 --no-cache
 WARNING  --no-cache is deprecated and will be removed in a future major version. Use --cache=local:r,remote:r

"build": "turbo run build --concurrency=1",
"build:vercel": "export PATH=\"$(pwd)/scripts/.foundry/bin:$(pwd)/.foundry/bin:${HOME}/.foundry/bin:${PATH}\" && pnpm run build",
"test": "turbo run test",
"lint": "turbo run lint",
"format": "turbo run format",
"size": "turbo run size",
"coverage": "turbo run coverage",
"remixd": "./node_modules/.bin/remixd"
},
"dependencies": {
"@aws-sdk/client-cloudwatch": "^3.901.0",
"@polkadot/api": "16.5.4",
"@polkadot/keyring": "14.0.1",
"@polkadot/types": "16.5.4",
"@polkadot/types-codec": "16.5.4",
"@polkadot/util": "14.0.1",
"@polkadot/util-crypto": "14.0.1",
"@snowbridge/api": "workspace:*",
"@snowbridge/base-types": "workspace:*",
"@snowbridge/contract-types": "workspace:*",
"@snowbridge/registry": "workspace:*",
"dotenv": "^17.2.3",
"ethers": "^6.16.0",
"lodash": "^4.17.21",
"pino": "^10.0.0",
"pino-pretty": "^13.1.1"
},
Comment thread
yrong marked this conversation as resolved.
"devDependencies": {
"ts-node": "10.9.2",
"tsconfig-paths": "4.2.0",
"turbo": "2.5.8",
"typescript": "5.9.3"
"typescript": "5.9.3",
"@vercel/node": "^3.2.0"
},
"packageManager": "pnpm@10.6.4+sha512.da3d715bfd22a9a105e6e8088cfc7826699332ded60c423b14ec613a185f1602206702ff0fe4c438cb15c979081ce4cb02568e364b15174503a63c7a8e2a5f6c"
}
Loading
Loading