Skip to content

Commit a3cbfcb

Browse files
committed
feat(app): add hosted session onboarding app
1 parent cbda656 commit a3cbfcb

81 files changed

Lines changed: 17273 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
NEXT_PUBLIC_CHAIN_ENV=testnet
2+
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=

app/.eslintrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": ["next/core-web-vitals"]
3+
}

app/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# AGW MCP Hosted Onboarding App
2+
3+
This package hosts the browser-side onboarding flow for `agw-mcp init`.
4+
5+
## Entry Point
6+
7+
- Route: `/session/new`
8+
- File: `src/app/session/new/page.tsx`
9+
- Expected query parameters:
10+
- `callback_url`: loopback callback URL (`http://localhost`, `http://127.0.0.1`, `http://[::1]`)
11+
- `chain_id`: supported chains only (`11124`, `2741`)
12+
- `signer`: session signer EVM address generated by the CLI
13+
14+
If validation fails, the page renders a non-retryable parameter error and instructs the user to restart from CLI.
15+
16+
## Callback Contract
17+
18+
After successful session creation, the app redirects to `callback_url` with:
19+
20+
- `session=<base64url(json-bundle)>`
21+
22+
Bundle payload fields:
23+
24+
- `accountAddress`
25+
- `chainId`
26+
- `expiresAt`
27+
- `sessionConfig`
28+
29+
No signer private key or signer reference is ever returned in the redirect.
30+
31+
## State Machine
32+
33+
Wizard state is centralized in `src/stores/useSessionWizardStore.ts`:
34+
35+
- `not_logged_in -> select_policy -> review_policy -> creating -> success`
36+
- Errors transition to `error` and retry goes back to `select_policy`.
37+
38+
All transitions are invoked through explicit store actions (not direct step mutation in components).

app/global.d.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
declare module '*.svg' {
2+
import * as React from 'react';
3+
const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
4+
export default ReactComponent;
5+
}
6+
7+
declare global {
8+
namespace NodeJS {
9+
interface ProcessEnv {
10+
NODE_ENV: string;
11+
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID?: string;
12+
NEXT_PUBLIC_CHAIN_ENV?: string;
13+
}
14+
}
15+
}
16+
17+
export {};

app/next-env.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference types="next" />
2+
/// <reference types="next/image-types/global" />
3+
4+
// NOTE: This file should not be edited
5+
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.

app/next.config.mjs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/** @type {import('next').NextConfig} */
2+
import { dirname, relative } from 'path';
3+
import hash from 'string-hash';
4+
import { fileURLToPath } from 'url';
5+
6+
const __filename = fileURLToPath(import.meta.url);
7+
const __dirname = dirname(__filename);
8+
const context = __dirname;
9+
10+
const nextConfig = {
11+
webpack(config) {
12+
// Grab the existing rule that handles SVG imports
13+
const fileLoaderRule = config.module.rules.find((rule) =>
14+
rule.test?.test?.('.svg'),
15+
);
16+
17+
// SVG Rules.
18+
//
19+
config.module.rules.push(
20+
// Reapply the existing rule, but only for svg imports ending in ?url
21+
{
22+
...fileLoaderRule,
23+
test: /\.svg$/i,
24+
resourceQuery: /url/, // *.svg?url
25+
},
26+
// Apply svgr to svgs and keep their IDs from clashing
27+
{
28+
test: /\.svg$/i,
29+
issuer: {
30+
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
31+
},
32+
// fileLoaderRule.issuer,
33+
resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] },
34+
use: ({ resource }) => ({
35+
loader: '@svgr/webpack',
36+
options: {
37+
prettier: false,
38+
svgo: true,
39+
titleProp: true,
40+
svgoConfig: {
41+
plugins: [
42+
{
43+
name: 'cleanupIds',
44+
params: {
45+
remove: true,
46+
minify: true,
47+
},
48+
},
49+
{
50+
name: 'prefixIds',
51+
params: {
52+
delim: '-',
53+
prefixClassNames: true,
54+
prefixIds: true,
55+
prefix: () => `svg${hash(relative(context, resource))}`,
56+
},
57+
},
58+
// {
59+
// name: 'preset-default',
60+
// params: {
61+
// overrides: { removeViewBox: false },
62+
// },
63+
// },
64+
],
65+
},
66+
},
67+
}),
68+
},
69+
);
70+
71+
// Modify the file loader rule to ignore *.svg, since we have it handled now.
72+
fileLoaderRule.exclude = /\.svg$/i;
73+
74+
return config;
75+
},
76+
};
77+
78+
export default nextConfig;

app/package.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "@abstract-foundation/agw-mcp-app",
3+
"version": "0.1.0",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"dev": "next dev -p 3001",
8+
"build": "next build",
9+
"start": "next start",
10+
"lint": "next lint",
11+
"check-types": "tsc --noEmit",
12+
"test": "vitest run"
13+
},
14+
"engines": {
15+
"node": ">=20.0.0"
16+
},
17+
"dependencies": {
18+
"@abstract-foundation/agw-client": "1.10.0",
19+
"@abstract-foundation/agw-react": "1.10.0",
20+
"@tanstack/react-query": "^5.90.2",
21+
"clsx": "^2.1.1",
22+
"next": "14.2.13",
23+
"react": "^18.3.1",
24+
"react-dom": "^18.3.1",
25+
"sass": "^1.93.3",
26+
"string-hash": "^1.1.3",
27+
"viem": "^2.39.0",
28+
"wagmi": "^2.19.4",
29+
"zustand": "^4.5.7"
30+
},
31+
"devDependencies": {
32+
"@svgr/webpack": "^8.1.0",
33+
"@types/node": "^22.18.1",
34+
"@types/react": "^18.3.23",
35+
"@types/react-dom": "^18.3.7",
36+
"eslint": "^8.57.1",
37+
"eslint-config-next": "14.2.13",
38+
"typescript": "^5.9.2",
39+
"vitest": "^3.2.4"
40+
},
41+
"packageManager": "pnpm@10.12.1"
42+
}

0 commit comments

Comments
 (0)