Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
7439ec2
feat(cross-app-connect): add whitelabel Privy cross-app provider host
Agilulfo1820 May 15, 2026
bfe136f
chore(deps): bump @privy-io/cross-app-connect from 0.2.2 to 0.5.8
Agilulfo1820 May 15, 2026
ae43018
feat(cross-app-connect): custom sign-in UI without Privy modal
Agilulfo1820 May 15, 2026
6de1228
feat(cross-app): pass login intent through to whitelabel connect page
Agilulfo1820 May 15, 2026
c02fa3d
feat(login): allow google/apple/email login methods without privy prop
Agilulfo1820 May 15, 2026
39c8d00
fix(login): show google/apple/email buttons when no privy prop
Agilulfo1820 May 15, 2026
ca157e0
fix(cross-app-connect): break OAuth redirect loop on intent flow
Agilulfo1820 May 15, 2026
b3288a5
feat(cross-app-connect): auto-accept connection after sign-in
Agilulfo1820 May 15, 2026
5016d98
refactor(login): route useLoginWithOAuth fallback inside the hook
Agilulfo1820 May 15, 2026
4ca19de
fix(cross-app-connect): only auto-accept when the user just authentic…
Agilulfo1820 May 15, 2026
25d81c0
feat(login): all 10 privy oauth providers fall back to cross-app
Agilulfo1820 May 15, 2026
8e7a990
feat(cross-app-connect): support all 10 privy oauth providers in sign…
Agilulfo1820 May 15, 2026
7f48072
chore(examples): list all 10 oauth providers + update notes
Agilulfo1820 May 15, 2026
087d9b2
chore(login): trim oauth list to providers actually enabled in vechai…
Agilulfo1820 May 15, 2026
8a2bba1
docs(login): reflect cross-app fallback in login-modal page
Agilulfo1820 May 15, 2026
4474d8a
fix(cross-app-connect): honor intent when an old session already exists
Agilulfo1820 May 15, 2026
05f189e
fix(cross-app-connect): phase machine + honor matching session
Agilulfo1820 May 15, 2026
88bc9e7
feat(cross-app-connect): vechain brand theme + system color mode
Agilulfo1820 May 15, 2026
e93437b
feat(cross-app-connect): privy-style sign-in panel + recent badge
Agilulfo1820 May 15, 2026
9499da6
feat(cross-app-connect): apply vechain branding to transact page
Agilulfo1820 May 15, 2026
3dc9167
fix(cross-app-connect): suppress body hydration warning + add debug t…
Agilulfo1820 May 15, 2026
a1e6de4
fix(cross-app-connect): make color-mode toggle visible everywhere
Agilulfo1820 May 15, 2026
4b27f5a
chore(cross-app-connect): move color-mode toggle to top-left
Agilulfo1820 May 15, 2026
8acab11
feat(cross-app-connect): rework sign-in list per vechain config
Agilulfo1820 May 15, 2026
ccba48b
fix(login): email requires privy again; add phone/farcaster intents
Agilulfo1820 May 15, 2026
445a7e6
fix(cross-app-connect): logo flicker + cancel button invisibility
Agilulfo1820 May 15, 2026
7c20727
refactor(cross-app-connect): mirror vechain-kit's design tokens
Agilulfo1820 May 15, 2026
1fc7dde
refactor(cross-app-connect): polish sign-in UX (chip, link, dot, labels)
Agilulfo1820 May 15, 2026
40fde85
chore(cross-app-connect): chromatic glyphs for discord/tiktok/line/phone
Agilulfo1820 May 15, 2026
52cf8b9
feat(cross-app-connect): translate transactions into plain language
Agilulfo1820 May 15, 2026
6a4f447
feat: simulate on homepage
Agilulfo1820 May 15, 2026
183d960
feat(cross-app-connect): resolve unknown ERC-20 metadata from thor
Agilulfo1820 May 15, 2026
7fc1551
feat: yarn
Agilulfo1820 May 15, 2026
4471de1
feat(cross-app-connect): balance change preview on the transact screen
Agilulfo1820 May 15, 2026
54c4867
feat(cross-app-connect): label known contracts, hide dev noise
Agilulfo1820 May 15, 2026
9ea4c98
fix: remove more
Agilulfo1820 May 15, 2026
b5491d0
fix: build
Agilulfo1820 May 15, 2026
c14257c
feat(cross-app-connect): account chip, shield title, friendly labels
Agilulfo1820 May 15, 2026
9e6836f
feat(cross-app-connect): resolve .vet domain + avatar via kit hooks
Agilulfo1820 May 15, 2026
e798d70
revert(cross-app-connect): drop balance change simulation
Agilulfo1820 May 15, 2026
f2e5dc5
fix(provider): fall back to VECHAIN_PRIVY_APP_ID when no privy prop
Agilulfo1820 May 15, 2026
c1b70e6
feat(cross-app-connect): risk-adaptive shield, specific titles, more
Agilulfo1820 May 15, 2026
ee06f2f
chore(cross-app-connect): hide color-mode toggle by default
Agilulfo1820 May 15, 2026
09048c5
chore(cross-app-connect): swap wordmark for logomark in the header
Agilulfo1820 May 15, 2026
1aa4180
style: content
Agilulfo1820 May 15, 2026
31db629
feat(cross-app-connect): identity row + force light mode
Agilulfo1820 May 15, 2026
2e13914
feat(cross-app-connect): app-hub verification + identity polish
Agilulfo1820 May 15, 2026
440d69b
chore(cross-app-connect): tighten unverified-app warning copy
Agilulfo1820 May 15, 2026
2bb3b43
feat(cross-app-connect): swap in-place spinners for skeletons
Agilulfo1820 May 15, 2026
b074ddd
style(cross-app-connect): align transact card with the connect pattern
Agilulfo1820 May 15, 2026
9abe319
chore(cross-app-connect): retitle picker to "Log in to your wallet"
Agilulfo1820 May 15, 2026
3f0a11f
chore(cross-app-connect): apply default title to VechainHeader
Agilulfo1820 May 15, 2026
0da6985
feat(cross-app-connect): support personal_sign and generic eth_signTy…
Agilulfo1820 May 15, 2026
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
13 changes: 13 additions & 0 deletions cross-app-connect/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Privy app this host represents
# Default = VeChain's mainnet Privy app (mirrors VECHAIN_PRIVY_APP_ID in vechain-kit)
NEXT_PUBLIC_PRIVY_APP_ID=cm4wxxujb022fyujl7g0thb21
NEXT_PUBLIC_PRIVY_CLIENT_ID=
# REQUIRED. Whitelabel Privy auth subdomain provisioned for your app in the
# Privy dashboard. Must include scheme, e.g. https://privy.your-app.privy.dev
# This is NOT the public auth.privy.io host.
NEXT_PUBLIC_PRIVY_DOMAIN=

# VeChain network -- main | test | solo
NEXT_PUBLIC_NETWORK_TYPE=main
NEXT_PUBLIC_DELEGATOR_URL=
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=
6 changes: 6 additions & 0 deletions cross-app-connect/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
extends: ['next'],
rules: {
'@typescript-eslint/unbound-method': 'off',
},
};
38 changes: 38 additions & 0 deletions cross-app-connect/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/
/dist/

# production
/build

# misc
.DS_Store
*.pem

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

# local env files
.env
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
44 changes: 44 additions & 0 deletions cross-app-connect/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? process.env.BASE_PATH ?? '';

/** @type {import('next').NextConfig} */
const nextConfig = {
basePath,
assetPrefix: basePath,
output: 'export',
distDir: 'dist',

compiler: {
removeConsole:
process.env.NODE_ENV === 'production'
? {
exclude: ['error', 'warn'],
}
: false,
},

turbopack: {
resolveAlias: {
'@/*': './src/*',
},
},

experimental: {
webpackBuildWorker: true,
optimizePackageImports: ['@chakra-ui/react', '@vechain/vechain-kit'],
},

images: {
unoptimized: true,
},
env: {
basePath,
},
eslint: {
ignoreDuringBuilds: true,
},

poweredByHeader: false,
generateEtags: false,
};

module.exports = nextConfig;
37 changes: 37 additions & 0 deletions cross-app-connect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "cross-app-connect",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "next build",
"clean": "rm -rf .next dist .turbo",
"dev": "next dev --turbopack",
"generate-app-hub": "node scripts/fetch-app-hub.mjs",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@chakra-ui/react": "2.8.2",
"@emotion/react": "^11.13.5",
"@emotion/styled": "^11.13.5",
"@privy-io/cross-app-provider": "^0.3.4",
"@privy-io/react-auth": "2.25.0",
"@tanstack/react-query": "^5.64.2",
"@vechain/dapp-kit-react": "2.1.0-rc.5",
"@vechain/sdk-core": "2.0.7",
"@vechain/sdk-network": "2.0.7",
"@vechain/vechain-kit": "workspace:*",
"next": "~16.2.3",
"react": "^18",
"react-dom": "^18",
"viem": "^2.22.0"
},
"devDependencies": {
"@next/eslint-plugin-next": "^14.1.4",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint": "^9.12.0",
"eslint-config-next": "14.1.4",
"typescript": "5.3.3"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions cross-app-connect/public/brand/vechain-wordmark-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions cross-app-connect/public/brand/vechain-wordmark-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
98 changes: 98 additions & 0 deletions cross-app-connect/scripts/fetch-app-hub.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env node
/**
* Pulls every manifest.json under vechain/app-hub@master into a single
* JSON file at src/app/cross-app/_lib/app-hub.json, keyed by origin so the
* runtime lookup is O(1) ('https://nubila.ai' -> { name: 'Nubila', ... }).
*
* Re-run when the registry adds new apps:
*
* yarn workspace cross-app-connect generate-app-hub
*/
import { mkdirSync, writeFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

const REPO = 'vechain/app-hub';
const BRANCH = 'master';
const OUT_PATH = resolve(
dirname(fileURLToPath(import.meta.url)),
'..',
'src/app/cross-app/_lib/app-hub.json',
);

async function ghFetch(url) {
const res = await fetch(url, {
headers: {
accept: 'application/vnd.github+json',
// Optional: GITHUB_TOKEN env var raises the rate limit from
// 60/hr (anonymous) to 5000/hr.
...(process.env.GITHUB_TOKEN && {
authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
}),
},
});
if (!res.ok) {
throw new Error(`${url} -> ${res.status} ${res.statusText}`);
}
return res.json();
}

function originOf(href) {
try {
return new URL(href).origin;
} catch {
return null;
}
}

const tree = await ghFetch(
`https://api.github.com/repos/${REPO}/git/trees/${BRANCH}?recursive=1`,
);
const manifestPaths = tree.tree
.filter((t) => t.path.endsWith('manifest.json'))
.map((t) => t.path);

console.log(`Found ${manifestPaths.length} manifests`);

const byOrigin = {};
const concurrency = 12;
let completed = 0;
const queue = [...manifestPaths];

async function worker() {
while (queue.length > 0) {
const path = queue.shift();
if (!path) break;
const slug = path.replace(/^apps\//, '').replace(/\/manifest\.json$/, '');
try {
const manifest = await ghFetch(
`https://raw.githubusercontent.com/${REPO}/${BRANCH}/${path}`,
);
const origin = originOf(manifest.href);
if (!origin) continue;
// Prefer the first manifest we see for a given origin.
if (!byOrigin[origin]) {
byOrigin[origin] = {
slug,
name: manifest.name,
category: manifest.category ?? null,
href: manifest.href,
};
}
} catch (e) {
console.warn(`skip ${path}: ${e.message}`);
}
completed++;
if (completed % 25 === 0) {
console.log(` ${completed}/${manifestPaths.length}`);
}
}
}

await Promise.all(Array.from({ length: concurrency }, worker));

mkdirSync(dirname(OUT_PATH), { recursive: true });
writeFileSync(OUT_PATH, JSON.stringify(byOrigin, null, 2) + '\n');
console.log(
`Wrote ${Object.keys(byOrigin).length} entries to ${OUT_PATH}`,
);
Loading
Loading