diff --git a/.gitignore b/.gitignore
index fe97056833b..c592bfb3724 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,4 +20,5 @@
npm-debug.log*
.vercel
.envrc
-.env
\ No newline at end of file
+.env
+.integrationBuilderCache
\ No newline at end of file
diff --git a/docusaurus.config.js b/docusaurus.config.js
index 4c67292f8fb..fe1c8335c39 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -12,23 +12,21 @@ const {
MM_RPC_URL,
} = require('./src/plugins/plugin-json-rpc')
const codeTheme = themes.dracula
-const helpDropdown = fs.readFileSync('./src/components/NavDropdown/DeveloperTools.html', 'utf-8')
-const connectDropdown = fs.readFileSync(
- './src/components/NavDropdown/ConnectMetaMask.html',
+const productsDropdown = fs.readFileSync(
+ './src/components/NavDropdown/Products.html',
'utf-8'
)
-const embedDropdown = fs.readFileSync('./src/components/NavDropdown/EmbedMetaMask.html', 'utf-8')
-const extendDropdown = fs.readFileSync('./src/components/NavDropdown/ExtendScale.html', 'utf-8')
+const baseUrl = process.env.DEST || '/';
+const siteUrl = 'https://docs.metamask.io';
+
const npm2yarnPlugin = [require('@docusaurus/remark-plugin-npm2yarn'), { sync: true }]
/** @type {import('@docusaurus/types').Config} */
-const siteUrl = 'https://docs.metamask.io'
-const baseUrl = process.env.DEST || '/'
const fullUrl = new URL(baseUrl, siteUrl).toString()
const config = {
title: 'MetaMask developer documentation',
// tagline: '',
url: 'https://docs.metamask.io',
- baseUrl: process.env.DEST || '/', // overwritten in github action for staging / latest
+ baseUrl, // overwritten in github action for staging / latest
onBrokenLinks: 'warn',
onBrokenMarkdownLinks: 'warn',
favicon: 'img/favicons/favicon-96x96.png',
@@ -110,6 +108,16 @@ const config = {
trailingSlash: true,
scripts: [
+ {
+ src: baseUrl + "js/fix-trailing-slash.js",
+ async: false,
+ defer: false,
+ },
+ {
+ src: baseUrl + "js/code-focus.js",
+ async: false,
+ defer: true,
+ },
{
src: 'https://cmp.osano.com/AzZMxHTbQDOQD8c1J/84e64bce-4a70-4dcc-85cb-7958f22b2371/osano.js',
},
@@ -133,6 +141,20 @@ const config = {
breadcrumbs: false,
remarkPlugins: [npm2yarnPlugin],
},
+ pages: {
+ path: 'src/pages',
+ routeBasePath: '/',
+ include: ['**/**.{js,jsx,ts,tsx,md,mdx}'],
+ exclude: [
+ '**/_*.{js,jsx,ts,tsx,md,mdx}',
+ '**/_*/**',
+ '**/*.test.{js,jsx,ts,tsx}',
+ '**/__tests__/**',
+ '**/quickstart/**', // Exclude quickstart directory from pages plugin
+ ],
+ mdxPageComponent: '@theme/MDXPage',
+ remarkPlugins: [npm2yarnPlugin],
+ },
theme: {
customCss: require.resolve('./src/scss/custom.scss'),
},
@@ -140,6 +162,8 @@ const config = {
],
],
plugins: [
+ ['./src/plugins/docusaurus-plugin-virtual-files', { rootDir: '.integrationBuilderCache' }],
+ './src/plugins/docusaurus-plugin-guides',
'docusaurus-plugin-sass',
'./src/plugins/mm-scss-utils',
[
@@ -336,54 +360,39 @@ const config = {
items: [
{
type: 'dropdown',
- label: 'Connect to MetaMask',
+ label: 'Products',
items: [
{
type: 'html',
- value: connectDropdown,
+ value: productsDropdown,
},
],
},
{
- type: 'dropdown',
- label: 'Embed MetaMask',
- items: [
- {
- type: 'html',
- value: embedDropdown,
- },
- ],
+ label: 'Quick Start',
+ to: '/quickstart',
+ position: 'left',
},
{
- type: 'dropdown',
- label: 'Extend and scale',
- items: [
- {
- type: 'html',
- value: extendDropdown,
- },
- ],
+ label: "Guides",
+ to: "/guides",
+ position: "left",
},
{
- type: 'dropdown',
- label: 'Developer tools',
- items: [
- {
- type: 'html',
- value: helpDropdown,
- },
- ],
- },
- {
- to: 'whats-new',
- label: "What's new?",
+ to: 'developer-tools/faucet/',
+ label: "Faucet",
position: 'right',
},
{
- type: 'custom-navbarWallet',
+ to: 'https://community.metamask.io/',
+ label: "Help ↗",
position: 'right',
- includeUrl: REF_ALLOW_LOGIN_PATH,
},
+ // {
+ // type: 'custom-navbarWallet',
+ // position: 'right',
+ // includeUrl: REF_ALLOW_LOGIN_PATH,
+ // },
/* Language drop down
{
type: "localeDropdown",
@@ -524,6 +533,21 @@ const config = {
theme: codeTheme,
additionalLanguages: ['csharp', 'gradle', 'bash', 'json'],
magicComments: [
+ {
+ className: 'theme-code-block-highlighted-line',
+ line: 'highlight-next-line',
+ block: { start: 'highlight-start', end: 'highlight-end' },
+ },
+ {
+ className: "code-unfocus",
+ line: "unfocus-next-line",
+ block: { start: "unfocus-start", end: "unfocus-end" },
+ },
+ {
+ className: "code-focus",
+ line: "focus-next-line",
+ block: { start: "focus-start", end: "focus-end" },
+ },
{
className: 'git-diff-remove',
line: 'remove-next-line',
@@ -554,7 +578,7 @@ const config = {
// Optional: Replace parts of the item URLs from Algolia. Useful when using the same search index for multiple deployments using a different baseUrl. You can use regexp or string in the `from` param. For example: localhost:3000 vs myCompany.com/docs
replaceSearchResultPathname: {
from: '/',
- to: process.env.DEST || '/',
+ to: baseUrl,
},
// Optional: Algolia search parameters
diff --git a/package-lock.json b/package-lock.json
index 75e976dbfc6..7c51c866fa9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,7 +30,9 @@
"@rjsf/validator-ajv8": "^5.24.12",
"@sentry/browser": "^8.51.0",
"@types/react": "^18.3.3",
+ "classnames": "^2.5.1",
"clsx": "^2.1.1",
+ "copy-to-clipboard": "^3.3.3",
"docusaurus-plugin-sass": "^0.2.5",
"dotenv": "^16.4.7",
"ethers": "^6.13.5",
@@ -41,14 +43,19 @@
"lodash.debounce": "^4.0.8",
"lodash.isplainobject": "^4.0.6",
"node-polyfill-webpack-plugin": "^2.0.1",
+ "playwright": "^1.54.2",
"prettier": "^3.3.3",
"prism-react-renderer": "^2.1.0",
"react": "^18.0.0",
"react-alert": "^7.0.3",
+ "react-bookmark": "^0.8.2",
"react-dom": "^18.0.0",
"react-dropdown-select": "^4.12.2",
+ "react-icons": "^5.5.0",
"react-modal": "^3.16.3",
"react-player": "^3.3.1",
+ "react-spinners": "^0.17.0",
+ "react-spring": "^10.0.1",
"react-tippy": "^1.4.0",
"remark-codesandbox": "^0.10.1",
"remark-docusaurus-tabs": "^0.2.0",
@@ -375,13 +382,15 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.27.5",
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz",
+ "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==",
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.27.5",
- "@babel/types": "^7.27.3",
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25",
+ "@babel/parser": "^7.28.0",
+ "@babel/types": "^7.28.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
},
"engines": {
@@ -481,6 +490,16 @@
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-member-expression-to-functions": {
"version": "7.27.1",
"license": "MIT",
@@ -621,10 +640,12 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.27.5",
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
+ "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.27.3"
+ "@babel/types": "^7.28.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -712,6 +733,61 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-dynamic-import": {
"version": "7.8.3",
"license": "MIT",
@@ -748,6 +824,32 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-jsx": {
"version": "7.27.1",
"license": "MIT",
@@ -761,6 +863,116 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-typescript": {
"version": "7.27.1",
"license": "MIT",
@@ -1770,8 +1982,30 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/traverse--for-generate-function-map": {
+ "name": "@babel/traverse",
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
+ "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.0",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/types": {
- "version": "7.27.6",
+ "version": "7.28.1",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz",
+ "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@@ -5311,98 +5545,316 @@
"version": "0.0.14",
"license": "MIT"
},
- "node_modules/@jest/schemas": {
- "version": "29.6.3",
- "license": "MIT",
- "dependencies": {
- "@sinclair/typebox": "^0.27.8"
- },
+ "node_modules/@isaacs/ttlcache": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
+ "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==",
+ "license": "ISC",
+ "peer": true,
"engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ "node": ">=12"
}
},
- "node_modules/@jest/types": {
- "version": "29.6.3",
- "license": "MIT",
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "license": "ISC",
+ "peer": true,
"dependencies": {
- "@jest/schemas": "^29.6.3",
- "@types/istanbul-lib-coverage": "^2.0.0",
- "@types/istanbul-reports": "^3.0.0",
- "@types/node": "*",
- "@types/yargs": "^17.0.8",
- "chalk": "^4.0.0"
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
},
"engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ "node": ">=8"
}
},
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.5",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "@jridgewell/set-array": "^1.2.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
+ "sprintf-js": "~1.0.2"
}
},
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"license": "MIT",
+ "peer": true,
"engines": {
- "node": ">=6.0.0"
+ "node": ">=6"
}
},
- "node_modules/@jridgewell/set-array": {
- "version": "1.2.1",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
"engines": {
- "node": ">=6.0.0"
+ "node": ">=8"
}
},
- "node_modules/@jridgewell/source-map": {
- "version": "0.3.6",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25"
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.0",
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.25",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@keystonehq/alias-sampling": {
- "version": "0.1.2",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"license": "MIT",
- "peer": true
+ "peer": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
- "node_modules/@keystonehq/base-eth-keyring": {
- "version": "0.14.1",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"license": "MIT",
"peer": true,
"dependencies": {
- "@ethereumjs/tx": "^4.0.2",
- "@ethereumjs/util": "^8.0.0",
- "@keystonehq/bc-ur-registry-eth": "^0.19.1",
- "hdkey": "^2.0.1",
- "rlp": "^3.0.0",
- "uuid": "^8.3.2"
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@keystonehq/base-eth-keyring/node_modules/rlp": {
- "version": "3.0.0",
- "license": "MPL-2.0",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz",
+ "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform/node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.12",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
+ "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.6",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.29",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
+ "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@keystonehq/alias-sampling": {
+ "version": "0.1.2",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@keystonehq/base-eth-keyring": {
+ "version": "0.14.1",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ethereumjs/tx": "^4.0.2",
+ "@ethereumjs/util": "^8.0.0",
+ "@keystonehq/bc-ur-registry-eth": "^0.19.1",
+ "hdkey": "^2.0.1",
+ "rlp": "^3.0.0",
+ "uuid": "^8.3.2"
+ }
+ },
+ "node_modules/@keystonehq/base-eth-keyring/node_modules/rlp": {
+ "version": "3.0.0",
+ "license": "MPL-2.0",
"peer": true,
"bin": {
"rlp": "bin/rlp"
@@ -8172,109 +8624,397 @@
"version": "1.0.0-next.28",
"license": "MIT"
},
- "node_modules/@rjsf/core": {
- "version": "5.24.10",
- "license": "Apache-2.0",
- "dependencies": {
- "lodash": "^4.17.21",
- "lodash-es": "^4.17.21",
- "markdown-to-jsx": "^7.4.1",
- "nanoid": "^3.3.7",
- "prop-types": "^15.8.1"
- },
+ "node_modules/@react-native/assets-registry": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.80.1.tgz",
+ "integrity": "sha512-T3C8OthBHfpFIjaGFa0q6rc58T2AsJ+jKAa+qPquMKBtYGJMc75WgNbk/ZbPBxeity6FxZsmg3bzoUaWQo4Mow==",
+ "license": "MIT",
+ "peer": true,
"engines": {
- "node": ">=14"
- },
- "peerDependencies": {
- "@rjsf/utils": "^5.24.x",
- "react": "^16.14.0 || >=17"
+ "node": ">=18"
}
},
- "node_modules/@rjsf/utils": {
- "version": "5.24.12",
- "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.24.12.tgz",
- "integrity": "sha512-fDwQB0XkjZjpdFUz5UAnuZj8nnbxDbX5tp+jTOjjJKw2TMQ9gFFYCQ12lSpdhezA2YgEGZfxyYTGW0DKDL5Drg==",
- "license": "Apache-2.0",
+ "node_modules/@react-native/codegen": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.80.1.tgz",
+ "integrity": "sha512-CFhOYkXmExOeZDZnd0UJCK9A4AOSAyFBoVgmFZsf+fv8JqnwIx/SD6RxY1+Jzz9EWPQcH2v+WgwPP/4qVmjtKw==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "json-schema-merge-allof": "^0.8.1",
- "jsonpointer": "^5.0.1",
- "lodash": "^4.17.21",
- "lodash-es": "^4.17.21",
- "react-is": "^18.2.0"
+ "glob": "^7.1.1",
+ "hermes-parser": "0.28.1",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "yargs": "^17.6.2"
},
"engines": {
- "node": ">=14"
+ "node": ">=18"
},
"peerDependencies": {
- "react": "^16.14.0 || >=17"
+ "@babel/core": "*"
}
},
- "node_modules/@rjsf/validator-ajv8": {
- "version": "5.24.12",
- "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.24.12.tgz",
- "integrity": "sha512-IMXdCjvDNdvb+mDgZC3AlAtr0pjYKq5s0GcLECjG5PuiX7Ib4JaDQHZY5ZJdKblMfgzhsn8AAOi573jXAt7BHQ==",
+ "node_modules/@react-native/community-cli-plugin": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.80.1.tgz",
+ "integrity": "sha512-M1lzLvZUz6zb6rn4Oyc3HUY72wye8mtdm1bJSYIBoK96ejMvQGoM+Lih/6k3c1xL7LSruNHfsEXXePLjCbhE8Q==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "ajv": "^8.12.0",
- "ajv-formats": "^2.1.1",
- "lodash": "^4.17.21",
- "lodash-es": "^4.17.21"
+ "@react-native/dev-middleware": "0.80.1",
+ "chalk": "^4.0.0",
+ "debug": "^4.4.0",
+ "invariant": "^2.2.4",
+ "metro": "^0.82.2",
+ "metro-config": "^0.82.2",
+ "metro-core": "^0.82.2",
+ "semver": "^7.1.3"
},
"engines": {
- "node": ">=14"
+ "node": ">=18"
},
"peerDependencies": {
- "@rjsf/utils": "^5.24.x"
+ "@react-native-community/cli": "*"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-community/cli": {
+ "optional": true
+ }
}
},
- "node_modules/@rjsf/validator-ajv8/node_modules/ajv": {
- "version": "8.17.1",
+ "node_modules/@react-native/community-cli-plugin/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
+ "ms": "^2.1.3"
},
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@rjsf/validator-ajv8/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "license": "MIT"
- },
- "node_modules/@scure/base": {
- "version": "1.1.9",
- "license": "MIT",
- "funding": {
- "url": "https://paulmillr.com/funding/"
+ "node_modules/@react-native/debugger-frontend": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.80.1.tgz",
+ "integrity": "sha512-5dQJdX1ZS4dINNw51KNsDIL+A06sZQd2hqN2Pldq5SavxAwEJh5NxAx7K+lutKhwp1By5gxd6/9ruVt+9NCvKA==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@scure/bip32": {
- "version": "1.4.0",
+ "node_modules/@react-native/dev-middleware": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.80.1.tgz",
+ "integrity": "sha512-EBnZ3s6+hGAlUggDvo9uI37Xh0vG55H2rr3A6l6ww7+sgNuUz+wEJ63mGINiU6DwzQSgr6av7rjrVERxKH6vxg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "@noble/curves": "~1.4.0",
- "@noble/hashes": "~1.4.0",
- "@scure/base": "~1.1.6"
+ "@isaacs/ttlcache": "^1.4.1",
+ "@react-native/debugger-frontend": "0.80.1",
+ "chrome-launcher": "^0.15.2",
+ "chromium-edge-launcher": "^0.2.0",
+ "connect": "^3.6.5",
+ "debug": "^4.4.0",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "open": "^7.0.3",
+ "serve-static": "^1.16.2",
+ "ws": "^6.2.3"
},
- "funding": {
- "url": "https://paulmillr.com/funding/"
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@scure/bip32/node_modules/@noble/curves": {
- "version": "1.4.2",
+ "node_modules/@react-native/dev-middleware/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "@noble/hashes": "1.4.0"
+ "ms": "^2.1.3"
},
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@scure/bip32/node_modules/@noble/hashes": {
- "version": "1.4.0",
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@react-native/dev-middleware/node_modules/open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@react-native/dev-middleware/node_modules/ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "node_modules/@react-native/gradle-plugin": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.80.1.tgz",
+ "integrity": "sha512-6B7bWUk27ne/g/wCgFF4MZFi5iy6hWOcBffqETJoab6WURMyZ6nU+EAMn+Vjhl5ishhUvTVSrJ/1uqrxxYQO2Q==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native/js-polyfills": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.80.1.tgz",
+ "integrity": "sha512-cWd5Cd2kBMRM37dor8N9Ck4X0NzjYM3m8K6HtjodcOdOvzpXfrfhhM56jdseTl5Z4iB+pohzPJpSmFJctmuIpA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native/normalize-colors": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.80.1.tgz",
+ "integrity": "sha512-YP12bjz0bzo2lFxZDOPkRJSOkcqAzXCQQIV1wd7lzCTXE0NJNwoaeNBobJvcPhiODEWUYCXPANrZveFhtFu5vw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@react-spring/animated": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-10.0.1.tgz",
+ "integrity": "sha512-BGL3hA66Y8Qm3KmRZUlfG/mFbDPYajgil2/jOP0VXf2+o2WPVmcDps/eEgdDqgf5Pv9eBbyj7LschLMuSjlW3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/shared": "~10.0.1",
+ "@react-spring/types": "~10.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@react-spring/core": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-10.0.1.tgz",
+ "integrity": "sha512-KaMMsN1qHuVTsFpg/5ajAVye7OEqhYbCq0g4aKM9bnSZlDBBYpO7Uf+9eixyXN8YEbF+YXaYj9eoWDs+npZ+sA==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/animated": "~10.0.1",
+ "@react-spring/shared": "~10.0.1",
+ "@react-spring/types": "~10.0.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-spring/donate"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@react-spring/konva": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/konva/-/konva-10.0.1.tgz",
+ "integrity": "sha512-mxy9dmfq2gcY3fisWBqGkbks5EmNDvwU5ya8w44xjVcDm7fI7ANsoDjJSS6d51JElO5fL3LYaAFi1urqQ2BjrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/animated": "~10.0.1",
+ "@react-spring/core": "~10.0.1",
+ "@react-spring/shared": "~10.0.1",
+ "@react-spring/types": "~10.0.1"
+ },
+ "peerDependencies": {
+ "konva": ">=2.6",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-konva": "^19"
+ }
+ },
+ "node_modules/@react-spring/rafz": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-10.0.1.tgz",
+ "integrity": "sha512-UrzG/d6Is+9i0aCAjsjWRqIlFFiC4lFqFHrH63zK935z2YDU95TOFio4VKGISJ5SG0xq4ULy7c1V3KU+XvL+Yg==",
+ "license": "MIT"
+ },
+ "node_modules/@react-spring/shared": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-10.0.1.tgz",
+ "integrity": "sha512-KR2tmjDShPruI/GGPfAZOOLvDgkhFseabjvxzZFFggJMPkyICLjO0J6mCIoGtdJSuHywZyc4Mmlgi+C88lS00g==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/rafz": "~10.0.1",
+ "@react-spring/types": "~10.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@react-spring/types": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-10.0.1.tgz",
+ "integrity": "sha512-Fk1wYVAKL+ZTYK+4YFDpHf3Slsy59pfFFvnnTfRjQQFGlyIo4VejPtDs3CbDiuBjM135YztRyZjIH2VbycB+ZQ==",
+ "license": "MIT"
+ },
+ "node_modules/@react-spring/web": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-10.0.1.tgz",
+ "integrity": "sha512-FgQk02OqFrYyJBTTnBTWAU0WPzkHkKXauc6aeexcvATvLapUxwnfGuLlsLYF8BYjEVfkivPT04ziAue6zyRBtQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/animated": "~10.0.1",
+ "@react-spring/core": "~10.0.1",
+ "@react-spring/shared": "~10.0.1",
+ "@react-spring/types": "~10.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@react-spring/zdog": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/zdog/-/zdog-10.0.1.tgz",
+ "integrity": "sha512-yEU2vf4C5FPxcnbYqnYtEMLElaoaepL5l9oAZI5/hK40EAQjo9uW6rtznOvbmL8z8RLM0PUCym0FtNHTlu0Ysw==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/animated": "~10.0.1",
+ "@react-spring/core": "~10.0.1",
+ "@react-spring/shared": "~10.0.1",
+ "@react-spring/types": "~10.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-zdog": ">=1.0",
+ "zdog": ">=1.0"
+ }
+ },
+ "node_modules/@rjsf/core": {
+ "version": "5.24.10",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "markdown-to-jsx": "^7.4.1",
+ "nanoid": "^3.3.7",
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@rjsf/utils": "^5.24.x",
+ "react": "^16.14.0 || >=17"
+ }
+ },
+ "node_modules/@rjsf/utils": {
+ "version": "5.24.12",
+ "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.24.12.tgz",
+ "integrity": "sha512-fDwQB0XkjZjpdFUz5UAnuZj8nnbxDbX5tp+jTOjjJKw2TMQ9gFFYCQ12lSpdhezA2YgEGZfxyYTGW0DKDL5Drg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "json-schema-merge-allof": "^0.8.1",
+ "jsonpointer": "^5.0.1",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "react-is": "^18.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": "^16.14.0 || >=17"
+ }
+ },
+ "node_modules/@rjsf/validator-ajv8": {
+ "version": "5.24.12",
+ "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.24.12.tgz",
+ "integrity": "sha512-IMXdCjvDNdvb+mDgZC3AlAtr0pjYKq5s0GcLECjG5PuiX7Ib4JaDQHZY5ZJdKblMfgzhsn8AAOi573jXAt7BHQ==",
+ "dependencies": {
+ "ajv": "^8.12.0",
+ "ajv-formats": "^2.1.1",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@rjsf/utils": "^5.24.x"
+ }
+ },
+ "node_modules/@rjsf/validator-ajv8/node_modules/ajv": {
+ "version": "8.17.1",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@rjsf/validator-ajv8/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "license": "MIT"
+ },
+ "node_modules/@scure/base": {
+ "version": "1.1.9",
+ "license": "MIT",
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip32": {
+ "version": "1.4.0",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "~1.4.0",
+ "@noble/hashes": "~1.4.0",
+ "@scure/base": "~1.1.6"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip32/node_modules/@noble/curves": {
+ "version": "1.4.2",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.4.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip32/node_modules/@noble/hashes": {
+ "version": "1.4.0",
"license": "MIT",
"engines": {
"node": ">= 16"
@@ -8396,6 +9136,26 @@
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
"node_modules/@slorber/remark-comment": {
"version": "1.0.0",
"license": "MIT",
@@ -8699,6 +9459,51 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.7",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
+ "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
"node_modules/@types/bn.js": {
"version": "5.1.6",
"license": "MIT",
@@ -8983,6 +9788,16 @@
"version": "7946.0.16",
"license": "MIT"
},
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/gtag.js": {
"version": "0.0.12",
"license": "MIT"
@@ -9139,6 +9954,16 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-reconciler": {
+ "version": "0.32.0",
+ "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.32.0.tgz",
+ "integrity": "sha512-+WHarFkJevhH1s655qeeSEf/yxFST0dVRsmSqUgxG8mMOKqycgYBv2wVpyubBY7MX8KiX5FQ03rNIwrxfm7Bmw==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-router": {
"version": "5.1.20",
"license": "MIT",
@@ -9220,6 +10045,20 @@
"@types/node": "*"
}
},
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/stylis": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
+ "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"license": "MIT",
@@ -9234,6 +10073,13 @@
"license": "MIT",
"peer": true
},
+ "node_modules/@types/webxr": {
+ "version": "0.5.22",
+ "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.22.tgz",
+ "integrity": "sha512-Vr6Stjv5jPRqH690f5I5GLjVk8GSsoQSYJ2FVd/3jJF7KaqfwPi3ehfBS96mlQ2kPCwZaX6U0rG2+NGHBKkA/A==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@types/ws": {
"version": "8.5.12",
"license": "MIT",
@@ -9688,6 +10534,13 @@
"algoliasearch": ">= 3.1 < 6"
}
},
+ "node_modules/anser": {
+ "version": "1.4.10",
+ "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz",
+ "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/ansi-align": {
"version": "3.0.1",
"license": "ISC",
@@ -9923,6 +10776,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/asn1.js": {
"version": "4.10.1",
"license": "MIT",
@@ -9962,6 +10822,13 @@
"node": ">= 0.4"
}
},
+ "node_modules/async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/async-mutex": {
"version": "0.5.0",
"license": "MIT",
@@ -10031,6 +10898,28 @@
"license": "Apache-2.0",
"peer": true
},
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
"node_modules/babel-loader": {
"version": "9.2.1",
"license": "MIT",
@@ -10053,6 +10942,39 @@
"object.assign": "^4.1.0"
}
},
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/babel-plugin-macros": {
"version": "3.1.0",
"license": "MIT",
@@ -10127,6 +11049,60 @@
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
+ "node_modules/babel-plugin-syntax-hermes-parser": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.28.1.tgz",
+ "integrity": "sha512-meT17DOuUElMNsL5LZN56d+KBp22hb0EfxWfuPUeoSi54e40v1W4C2V36P75FpsH9fVEfDKpw5Nnkahc8haSsQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "hermes-parser": "0.28.1"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz",
+ "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
"node_modules/bail": {
"version": "2.0.2",
"license": "MIT",
@@ -10557,6 +11533,16 @@
"safe-buffer": "^5.1.2"
}
},
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
"node_modules/buffer": {
"version": "5.7.1",
"funding": [
@@ -10743,6 +11729,42 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "callsites": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/caller-callsite/node_modules/callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "caller-callsite": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/callsites": {
"version": "3.1.0",
"license": "MIT",
@@ -10796,6 +11818,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/caniuse-api": {
"version": "3.0.0",
"license": "MIT",
@@ -11004,6 +12036,25 @@
"version": "1.1.4",
"license": "ISC"
},
+ "node_modules/chrome-launcher": {
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
+ "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0"
+ },
+ "bin": {
+ "print-chrome-path": "bin/print-chrome-path.js"
+ },
+ "engines": {
+ "node": ">=12.13.0"
+ }
+ },
"node_modules/chrome-trace-event": {
"version": "1.0.4",
"license": "MIT",
@@ -11011,6 +12062,34 @@
"node": ">=6.0"
}
},
+ "node_modules/chromium-edge-launcher": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz",
+ "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0",
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "node_modules/chromium-edge-launcher/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/ci-info": {
"version": "3.9.0",
"funding": [
@@ -11032,6 +12111,12 @@
"safe-buffer": "^5.0.1"
}
},
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
+ "license": "MIT"
+ },
"node_modules/clean-css": {
"version": "5.3.3",
"license": "MIT",
@@ -11106,6 +12191,71 @@
"version": "2.2.1",
"license": "ISC"
},
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/cliui/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/clone-deep": {
"version": "4.0.1",
"license": "MIT",
@@ -11870,6 +13020,22 @@
"typedarray-to-buffer": "^3.1.5"
}
},
+ "node_modules/connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
"node_modules/connect-history-api-fallback": {
"version": "2.0.0",
"license": "MIT",
@@ -11877,6 +13043,23 @@
"node": ">=0.8"
}
},
+ "node_modules/connect/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/connect/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/consola": {
"version": "3.4.2",
"license": "MIT",
@@ -11952,6 +13135,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "license": "MIT",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
"node_modules/copy-webpack-plugin": {
"version": "11.0.0",
"license": "MIT",
@@ -12244,6 +13436,16 @@
"node": ">=4"
}
},
+ "node_modules/css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/css-declaration-sorter": {
"version": "7.2.0",
"license": "ISC",
@@ -12427,6 +13629,18 @@
"url": "https://github.com/sponsors/fb55"
}
},
+ "node_modules/css-to-react-native": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
"node_modules/css-tree": {
"version": "2.3.1",
"license": "MIT",
@@ -13822,6 +15036,16 @@
"is-arrayish": "^0.2.1"
}
},
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
"node_modules/es-abstract": {
"version": "1.23.9",
"dev": true,
@@ -14722,6 +15946,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/exponential-backoff": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
+ "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==",
+ "license": "Apache-2.0",
+ "peer": true
+ },
"node_modules/express": {
"version": "4.21.2",
"license": "MIT",
@@ -14982,6 +16213,16 @@
"node": ">=0.8.0"
}
},
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
"node_modules/feed": {
"version": "4.2.2",
"license": "MIT",
@@ -15090,22 +16331,58 @@
"node": ">=8"
}
},
- "node_modules/find-cache-dir": {
- "version": "4.0.0",
+ "node_modules/finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "common-path-prefix": "^3.0.0",
- "pkg-dir": "^7.0.0"
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
},
"engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">= 0.8"
}
},
- "node_modules/find-file-up": {
- "version": "0.1.3",
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/find-cache-dir": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "common-path-prefix": "^3.0.0",
+ "pkg-dir": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-file-up": {
+ "version": "0.1.3",
"license": "MIT",
"dependencies": {
"fs-exists-sync": "^0.1.0",
@@ -15169,6 +16446,13 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/flow-enums-runtime": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz",
+ "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/flush-write-stream": {
"version": "1.1.1",
"license": "MIT",
@@ -15432,6 +16716,16 @@
"node": ">=6.9.0"
}
},
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
"node_modules/get-intrinsic": {
"version": "1.2.7",
"license": "MIT",
@@ -15466,6 +16760,16 @@
"version": "3.0.2",
"license": "ISC"
},
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/get-proto": {
"version": "1.0.1",
"license": "MIT",
@@ -16105,6 +17409,23 @@
"he": "bin/he"
}
},
+ "node_modules/hermes-estree": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.28.1.tgz",
+ "integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.28.1.tgz",
+ "integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "hermes-estree": "0.28.1"
+ }
+ },
"node_modules/history": {
"version": "4.10.1",
"license": "MIT",
@@ -17066,6 +18387,16 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-docker": {
"version": "2.2.1",
"license": "MIT",
@@ -17456,6 +18787,43 @@
"node": ">=0.10.0"
}
},
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/istextorbinary": {
"version": "2.6.0",
"license": "MIT",
@@ -17487,6 +18855,106 @@
"node": ">= 0.4"
}
},
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/jest-util": {
"version": "29.7.0",
"license": "MIT",
@@ -17502,6 +18970,24 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/jest-worker": {
"version": "29.7.0",
"license": "MIT",
@@ -17576,6 +19062,13 @@
"license": "Apache-2.0",
"peer": true
},
+ "node_modules/jsc-safe-url": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz",
+ "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==",
+ "license": "0BSD",
+ "peer": true
+ },
"node_modules/jsesc": {
"version": "3.1.0",
"license": "MIT",
@@ -17788,6 +19281,27 @@
"version": "1.8.0",
"license": "MIT"
},
+ "node_modules/konva": {
+ "version": "9.3.22",
+ "resolved": "https://registry.npmjs.org/konva/-/konva-9.3.22.tgz",
+ "integrity": "sha512-yQI5d1bmELlD/fowuyfOp9ff+oamg26WOCkyqUyc+nczD/lhRa3EvD2MZOoc4c1293TAubW9n34fSQLgSeEgSw==",
+ "funding": [
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/lavrton"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/konva"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/lavrton"
+ }
+ ],
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/langium": {
"version": "3.3.1",
"license": "MIT",
@@ -17883,6 +19397,34 @@
"immediate": "~3.0.5"
}
},
+ "node_modules/lighthouse-logger": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz",
+ "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "debug": "^2.6.9",
+ "marky": "^1.2.2"
+ }
+ },
+ "node_modules/lighthouse-logger/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/lighthouse-logger/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/lilconfig": {
"version": "3.1.3",
"license": "MIT",
@@ -18007,6 +19549,13 @@
"version": "4.1.1",
"license": "MIT"
},
+ "node_modules/lodash.throttle": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+ "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/lodash.truncate": {
"version": "4.4.2",
"dev": true,
@@ -18220,6 +19769,16 @@
"version": "2.1.2",
"license": "ISC"
},
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
"node_modules/map-obj": {
"version": "4.3.0",
"dev": true,
@@ -18269,6 +19828,13 @@
"node": ">= 18"
}
},
+ "node_modules/marky": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz",
+ "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==",
+ "license": "Apache-2.0",
+ "peer": true
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"license": "MIT",
@@ -18687,6 +20253,13 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/memoize-one": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/meow": {
"version": "10.1.5",
"dev": true,
@@ -18836,44 +20409,574 @@
"node": ">= 0.6"
}
},
- "node_modules/micro-ftch": {
- "version": "0.3.1",
- "license": "MIT"
- },
- "node_modules/micromark": {
- "version": "4.0.2",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro/-/metro-0.82.5.tgz",
+ "integrity": "sha512-8oAXxL7do8QckID/WZEKaIFuQJFUTLzfVcC48ghkHhNK2RGuQq8Xvf4AVd+TUA0SZtX0q8TGNXZ/eba1ckeGCg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "@types/debug": "^4.0.0",
- "debug": "^4.0.0",
- "decode-named-character-reference": "^1.0.0",
- "devlop": "^1.0.0",
- "micromark-core-commonmark": "^2.0.0",
- "micromark-factory-space": "^2.0.0",
- "micromark-util-character": "^2.0.0",
- "micromark-util-chunked": "^2.0.0",
- "micromark-util-combine-extensions": "^2.0.0",
- "micromark-util-decode-numeric-character-reference": "^2.0.0",
- "micromark-util-encode": "^2.0.0",
- "micromark-util-normalize-identifier": "^2.0.0",
- "micromark-util-resolve-all": "^2.0.0",
- "micromark-util-sanitize-uri": "^2.0.0",
- "micromark-util-subtokenize": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
+ "@babel/code-frame": "^7.24.7",
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/parser": "^7.25.3",
+ "@babel/template": "^7.25.0",
+ "@babel/traverse": "^7.25.3",
+ "@babel/types": "^7.25.2",
+ "accepts": "^1.3.7",
+ "chalk": "^4.0.0",
+ "ci-info": "^2.0.0",
+ "connect": "^3.6.5",
+ "debug": "^4.4.0",
+ "error-stack-parser": "^2.0.6",
+ "flow-enums-runtime": "^0.0.6",
+ "graceful-fs": "^4.2.4",
+ "hermes-parser": "0.29.1",
+ "image-size": "^1.0.2",
+ "invariant": "^2.2.4",
+ "jest-worker": "^29.7.0",
+ "jsc-safe-url": "^0.2.2",
+ "lodash.throttle": "^4.1.1",
+ "metro-babel-transformer": "0.82.5",
+ "metro-cache": "0.82.5",
+ "metro-cache-key": "0.82.5",
+ "metro-config": "0.82.5",
+ "metro-core": "0.82.5",
+ "metro-file-map": "0.82.5",
+ "metro-resolver": "0.82.5",
+ "metro-runtime": "0.82.5",
+ "metro-source-map": "0.82.5",
+ "metro-symbolicate": "0.82.5",
+ "metro-transform-plugins": "0.82.5",
+ "metro-transform-worker": "0.82.5",
+ "mime-types": "^2.1.27",
+ "nullthrows": "^1.1.1",
+ "serialize-error": "^2.1.0",
+ "source-map": "^0.5.6",
+ "throat": "^5.0.0",
+ "ws": "^7.5.10",
+ "yargs": "^17.6.2"
+ },
+ "bin": {
+ "metro": "src/cli.js"
+ },
+ "engines": {
+ "node": ">=18.18"
}
},
- "node_modules/micromark-core-commonmark": {
+ "node_modules/metro-babel-transformer": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.82.5.tgz",
+ "integrity": "sha512-W/scFDnwJXSccJYnOFdGiYr9srhbHPdxX9TvvACOFsIXdLilh3XuxQl/wXW6jEJfgIb0jTvoTlwwrqvuwymr6Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "hermes-parser": "0.29.1",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-babel-transformer/node_modules/hermes-estree": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
+ "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-babel-transformer/node_modules/hermes-parser": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
+ "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "hermes-estree": "0.29.1"
+ }
+ },
+ "node_modules/metro-cache": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.82.5.tgz",
+ "integrity": "sha512-AwHV9607xZpedu1NQcjUkua8v7HfOTKfftl6Vc9OGr/jbpiJX6Gpy8E/V9jo/U9UuVYX2PqSUcVNZmu+LTm71Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "exponential-backoff": "^3.1.1",
+ "flow-enums-runtime": "^0.0.6",
+ "https-proxy-agent": "^7.0.5",
+ "metro-core": "0.82.5"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-cache-key": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.82.5.tgz",
+ "integrity": "sha512-qpVmPbDJuRLrT4kcGlUouyqLGssJnbTllVtvIgXfR7ZuzMKf0mGS+8WzcqzNK8+kCyakombQWR0uDd8qhWGJcA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-cache/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/metro-cache/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/metro-config": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.82.5.tgz",
+ "integrity": "sha512-/r83VqE55l0WsBf8IhNmc/3z71y2zIPe5kRSuqA5tY/SL/ULzlHUJEMd1szztd0G45JozLwjvrhAzhDPJ/Qo/g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "connect": "^3.6.5",
+ "cosmiconfig": "^5.0.5",
+ "flow-enums-runtime": "^0.0.6",
+ "jest-validate": "^29.7.0",
+ "metro": "0.82.5",
+ "metro-cache": "0.82.5",
+ "metro-core": "0.82.5",
+ "metro-runtime": "0.82.5"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/metro-config/node_modules/cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/metro-config/node_modules/import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/metro-config/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/metro-config/node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/metro-config/node_modules/resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/metro-core": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.82.5.tgz",
+ "integrity": "sha512-OJL18VbSw2RgtBm1f2P3J5kb892LCVJqMvslXxuxjAPex8OH7Eb8RBfgEo7VZSjgb/LOf4jhC4UFk5l5tAOHHA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "lodash.throttle": "^4.1.1",
+ "metro-resolver": "0.82.5"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-file-map": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.82.5.tgz",
+ "integrity": "sha512-vpMDxkGIB+MTN8Af5hvSAanc6zXQipsAUO+XUx3PCQieKUfLwdoa8qaZ1WAQYRpaU+CJ8vhBcxtzzo3d9IsCIQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "debug": "^4.4.0",
+ "fb-watchman": "^2.0.0",
+ "flow-enums-runtime": "^0.0.6",
+ "graceful-fs": "^4.2.4",
+ "invariant": "^2.2.4",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "nullthrows": "^1.1.1",
+ "walker": "^1.0.7"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/metro-minify-terser": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.82.5.tgz",
+ "integrity": "sha512-v6Nx7A4We6PqPu/ta1oGTqJ4Usz0P7c+3XNeBxW9kp8zayS3lHUKR0sY0wsCHInxZlNAEICx791x+uXytFUuwg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "terser": "^5.15.0"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-resolver": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.82.5.tgz",
+ "integrity": "sha512-kFowLnWACt3bEsuVsaRNgwplT8U7kETnaFHaZePlARz4Fg8tZtmRDUmjaD68CGAwc0rwdwNCkWizLYpnyVcs2g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-runtime": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.82.5.tgz",
+ "integrity": "sha512-rQZDoCUf7k4Broyw3Ixxlq5ieIPiR1ULONdpcYpbJQ6yQ5GGEyYjtkztGD+OhHlw81LCR2SUAoPvtTus2WDK5g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/runtime": "^7.25.0",
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-source-map": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.82.5.tgz",
+ "integrity": "sha512-wH+awTOQJVkbhn2SKyaw+0cd+RVSCZ3sHVgyqJFQXIee/yLs3dZqKjjeKKhhVeudgjXo7aE/vSu/zVfcQEcUfw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.3",
+ "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3",
+ "@babel/types": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "invariant": "^2.2.4",
+ "metro-symbolicate": "0.82.5",
+ "nullthrows": "^1.1.1",
+ "ob1": "0.82.5",
+ "source-map": "^0.5.6",
+ "vlq": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-source-map/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/metro-symbolicate": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.82.5.tgz",
+ "integrity": "sha512-1u+07gzrvYDJ/oNXuOG1EXSvXZka/0JSW1q2EYBWerVKMOhvv9JzDGyzmuV7hHbF2Hg3T3S2uiM36sLz1qKsiw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "invariant": "^2.2.4",
+ "metro-source-map": "0.82.5",
+ "nullthrows": "^1.1.1",
+ "source-map": "^0.5.6",
+ "vlq": "^1.0.0"
+ },
+ "bin": {
+ "metro-symbolicate": "src/index.js"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-symbolicate/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/metro-transform-plugins": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.82.5.tgz",
+ "integrity": "sha512-57Bqf3rgq9nPqLrT2d9kf/2WVieTFqsQ6qWHpEng5naIUtc/Iiw9+0bfLLWSAw0GH40iJ4yMjFcFJDtNSYynMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/template": "^7.25.0",
+ "@babel/traverse": "^7.25.3",
+ "flow-enums-runtime": "^0.0.6",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-transform-worker": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.82.5.tgz",
+ "integrity": "sha512-mx0grhAX7xe+XUQH6qoHHlWedI8fhSpDGsfga7CpkO9Lk9W+aPitNtJWNGrW8PfjKEWbT9Uz9O50dkI8bJqigw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/parser": "^7.25.3",
+ "@babel/types": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "metro": "0.82.5",
+ "metro-babel-transformer": "0.82.5",
+ "metro-cache": "0.82.5",
+ "metro-cache-key": "0.82.5",
+ "metro-minify-terser": "0.82.5",
+ "metro-source-map": "0.82.5",
+ "metro-transform-plugins": "0.82.5",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro/node_modules/ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/metro/node_modules/hermes-estree": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
+ "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro/node_modules/hermes-parser": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
+ "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "hermes-estree": "0.29.1"
+ }
+ },
+ "node_modules/metro/node_modules/image-size": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz",
+ "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "queue": "6.0.2"
+ },
+ "bin": {
+ "image-size": "bin/image-size.js"
+ },
+ "engines": {
+ "node": ">=16.x"
+ }
+ },
+ "node_modules/metro/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/metro/node_modules/ws": {
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/micro-ftch": {
+ "version": "0.3.1",
+ "license": "MIT"
+ },
+ "node_modules/micromark": {
+ "version": "4.0.2",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/debug": "^4.0.0",
+ "debug": "^4.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-core-commonmark": {
"version": "2.0.3",
"funding": [
{
@@ -20843,6 +22946,13 @@
"node-gyp-build-test": "build-test.js"
}
},
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/node-polyfill-webpack-plugin": {
"version": "2.0.1",
"license": "MIT",
@@ -21070,6 +23180,26 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/nullthrows": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
+ "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/ob1": {
+ "version": "0.82.5",
+ "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.82.5.tgz",
+ "integrity": "sha512-QyQQ6e66f+Ut/qUVjEce0E/wux5nAGLXYZDn1jr15JWstHsCH3l6VVrg8NKDptW9NEiBXKOJeGF/ydxeSDF3IQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
"node_modules/obj-multiplex": {
"version": "1.0.0",
"license": "ISC",
@@ -21214,6 +23344,19 @@
"version": "1.1.2",
"license": "MIT"
},
+ "node_modules/on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/on-headers": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
@@ -21420,6 +23563,16 @@
"node": ">=8"
}
},
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/package-json": {
"version": "8.1.1",
"license": "MIT",
@@ -21770,7 +23923,6 @@
},
"node_modules/path-exists": {
"version": "4.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -21889,6 +24041,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/pkg-dir": {
"version": "7.0.0",
"license": "MIT",
@@ -21981,6 +24143,12 @@
"pathe": "^2.0.3"
}
},
+ "node_modules/platform": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz",
+ "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==",
+ "license": "MIT"
+ },
"node_modules/player.style": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/player.style/-/player.style-0.1.9.tgz",
@@ -21997,6 +24165,50 @@
"media-chrome": "~4.11.0"
}
},
+ "node_modules/playwright": {
+ "version": "1.54.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.2.tgz",
+ "integrity": "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.54.2"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.54.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.2.tgz",
+ "integrity": "sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==",
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/playwright/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/points-on-curve": {
"version": "0.2.0",
"license": "MIT"
@@ -23748,6 +25960,34 @@
"renderkid": "^3.0.0"
}
},
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
"node_modules/pretty-time": {
"version": "1.1.0",
"license": "MIT",
@@ -23784,6 +26024,16 @@
"version": "2.0.1",
"license": "MIT"
},
+ "node_modules/promise": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
+ "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "asap": "~2.0.6"
+ }
+ },
"node_modules/promise-inflight": {
"version": "1.0.1",
"license": "ISC"
@@ -23958,6 +26208,16 @@
"node": ">=0.4.x"
}
},
+ "node_modules/queue": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
+ "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "inherits": "~2.0.3"
+ }
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"funding": [
@@ -24062,22 +26322,73 @@
"version": "18.3.1",
"license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-alert": {
+ "version": "7.0.3",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.7.2",
+ "react-transition-group": "^4.4.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.1 || ^17",
+ "react-dom": "^16.8.1 || ^17"
+ }
+ },
+ "node_modules/react-bookmark": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/react-bookmark/-/react-bookmark-0.8.2.tgz",
+ "integrity": "sha512-79iXtvwrPBjdvpJGfIYHY2f8/+eA9Gn2bhTbuc0vx8fyElM1QaQoL9VVWsKSfOcMH9Fxfz8BZbXc9RaMRGJjAA==",
+ "license": "MIT",
+ "dependencies": {
+ "platform": "^1.3.4",
+ "prop-types": "^15.5.10"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "react": ">=15.0.0",
+ "react-dom": ">=15.0.0",
+ "styled-components": ">=1.0.0"
+ }
+ },
+ "node_modules/react-devtools-core": {
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.5.tgz",
+ "integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "shell-quote": "^1.6.1",
+ "ws": "^7"
}
},
- "node_modules/react-alert": {
- "version": "7.0.3",
+ "node_modules/react-devtools-core/node_modules/ws": {
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
"license": "MIT",
- "dependencies": {
- "prop-types": "^15.7.2",
- "react-transition-group": "^4.4.1"
+ "peer": true,
+ "engines": {
+ "node": ">=8.3.0"
},
"peerDependencies": {
- "react": "^16.8.1 || ^17",
- "react-dom": "^16.8.1 || ^17"
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
}
},
"node_modules/react-dom": {
@@ -24126,6 +26437,15 @@
"react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
+ "node_modules/react-icons": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
+ "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
"node_modules/react-is": {
"version": "18.3.1",
"license": "MIT"
@@ -24140,6 +26460,84 @@
"react": "^18.0.0 || ^19.0.0"
}
},
+ "node_modules/react-konva": {
+ "version": "19.0.7",
+ "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-19.0.7.tgz",
+ "integrity": "sha512-uYWCpSv4ajLymTh8S8fV9396fHDX7eDTWiLGkYlBuawud5MoNiuGjapPhA5Avdy/Jfh9P2KaWuNf4i9PI1F9HQ==",
+ "funding": [
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/lavrton"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/konva"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/lavrton"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/react-reconciler": "^0.32.0",
+ "its-fine": "^2.0.0",
+ "react-reconciler": "0.32.0",
+ "scheduler": "0.26.0"
+ },
+ "peerDependencies": {
+ "konva": "^8.0.1 || ^7.2.5 || ^9.0.0",
+ "react": "^18.3.1 || ^19.0.0",
+ "react-dom": "^18.3.1 || ^19.0.0"
+ }
+ },
+ "node_modules/react-konva/node_modules/its-fine": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-2.0.0.tgz",
+ "integrity": "sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/react-reconciler": "^0.28.9"
+ },
+ "peerDependencies": {
+ "react": "^19.0.0"
+ }
+ },
+ "node_modules/react-konva/node_modules/its-fine/node_modules/@types/react-reconciler": {
+ "version": "0.28.9",
+ "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.9.tgz",
+ "integrity": "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/react-konva/node_modules/react-reconciler": {
+ "version": "0.32.0",
+ "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.32.0.tgz",
+ "integrity": "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "scheduler": "^0.26.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "peerDependencies": {
+ "react": "^19.1.0"
+ }
+ },
+ "node_modules/react-konva/node_modules/scheduler": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/react-lifecycles-compat": {
"version": "3.0.4",
"license": "MIT"
@@ -24206,6 +26604,16 @@
"react-dom": "^17.0.2 || ^18 || ^19"
}
},
+ "node_modules/react-refresh": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
+ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/react-router": {
"version": "5.3.4",
"license": "MIT",
@@ -24255,6 +26663,316 @@
"version": "16.13.1",
"license": "MIT"
},
+ "node_modules/react-spinners": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.17.0.tgz",
+ "integrity": "sha512-L/8HTylaBmIWwQzIjMq+0vyaRXuoAevzWoD35wKpNTxxtYXWZp+xtgkfD7Y4WItuX0YvdxMPU79+7VhhmbmuTQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/react-spring": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-10.0.1.tgz",
+ "integrity": "sha512-N4TGwmMYtqC6DX6AcMbldH0WCvZm3r7OuilNFSjeP6sijwKLjMFmHpdXOSnbKBdg1LQudLRmk9uqpguf2oa/sg==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/core": "~10.0.1",
+ "@react-spring/konva": "~10.0.1",
+ "@react-spring/native": "~10.0.1",
+ "@react-spring/three": "~10.0.1",
+ "@react-spring/web": "~10.0.1",
+ "@react-spring/zdog": "~10.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/react-spring/node_modules/@react-spring/native": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/native/-/native-10.0.1.tgz",
+ "integrity": "sha512-uslIO25XugK9SugvQRVsmXoSiApmQzV2JWWcbhPJUvArqPyZ1yuPQvgNqjvHubauu5kXWWOya9MIuVEo7EMKUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/animated": "~10.0.1",
+ "@react-spring/core": "~10.0.1",
+ "@react-spring/shared": "~10.0.1",
+ "@react-spring/types": "~10.0.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-native": ">=0.78"
+ }
+ },
+ "node_modules/react-spring/node_modules/@react-spring/three": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-10.0.1.tgz",
+ "integrity": "sha512-JAgA573EqG1WkDGameWv0HYlPL5KYwVCRhXroBq5Ed0Chc9xXuAZU8fyNg9/uup8Pc32iGSW0PHRt0msvPNg+w==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-spring/animated": "~10.0.1",
+ "@react-spring/core": "~10.0.1",
+ "@react-spring/shared": "~10.0.1",
+ "@react-spring/types": "~10.0.1"
+ },
+ "peerDependencies": {
+ "@react-three/fiber": ">=6.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "three": ">=0.126"
+ }
+ },
+ "node_modules/react-spring/node_modules/@react-three/fiber": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.2.0.tgz",
+ "integrity": "sha512-esZe+E9T/aYEM4HlBkirr/yRE8qWTp9WUsLISyHHMCHKlJv85uc5N4wwKw+Ay0QeTSITw6T9Q3Svpu383Q+CSQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/runtime": "^7.17.8",
+ "@types/react-reconciler": "^0.28.9",
+ "@types/webxr": "*",
+ "base64-js": "^1.5.1",
+ "buffer": "^6.0.3",
+ "its-fine": "^2.0.0",
+ "react-reconciler": "^0.31.0",
+ "react-use-measure": "^2.1.7",
+ "scheduler": "^0.25.0",
+ "suspend-react": "^0.1.3",
+ "use-sync-external-store": "^1.4.0",
+ "zustand": "^5.0.3"
+ },
+ "peerDependencies": {
+ "expo": ">=43.0",
+ "expo-asset": ">=8.4",
+ "expo-file-system": ">=11.0",
+ "expo-gl": ">=11.0",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "react-native": ">=0.78",
+ "three": ">=0.156"
+ },
+ "peerDependenciesMeta": {
+ "expo": {
+ "optional": true
+ },
+ "expo-asset": {
+ "optional": true
+ },
+ "expo-file-system": {
+ "optional": true
+ },
+ "expo-gl": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-spring/node_modules/@react-three/fiber/node_modules/its-fine": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-2.0.0.tgz",
+ "integrity": "sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/react-reconciler": "^0.28.9"
+ },
+ "peerDependencies": {
+ "react": "^19.0.0"
+ }
+ },
+ "node_modules/react-spring/node_modules/@react-three/fiber/node_modules/react-reconciler": {
+ "version": "0.31.0",
+ "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.31.0.tgz",
+ "integrity": "sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "scheduler": "^0.25.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "peerDependencies": {
+ "react": "^19.0.0"
+ }
+ },
+ "node_modules/react-spring/node_modules/@types/react": {
+ "version": "19.1.8",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
+ "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/react-spring/node_modules/@types/react-reconciler": {
+ "version": "0.28.9",
+ "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.9.tgz",
+ "integrity": "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/react-spring/node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/react-spring/node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/react-spring/node_modules/react-native": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.80.1.tgz",
+ "integrity": "sha512-cIiJiPItdC2+Z9n30FmE2ef1y4522kgmOjMIoDtlD16jrOMNTUdB2u+CylLTy3REkWkWTS6w8Ub7skUthkeo5w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/create-cache-key-function": "^29.7.0",
+ "@react-native/assets-registry": "0.80.1",
+ "@react-native/codegen": "0.80.1",
+ "@react-native/community-cli-plugin": "0.80.1",
+ "@react-native/gradle-plugin": "0.80.1",
+ "@react-native/js-polyfills": "0.80.1",
+ "@react-native/normalize-colors": "0.80.1",
+ "@react-native/virtualized-lists": "0.80.1",
+ "abort-controller": "^3.0.0",
+ "anser": "^1.4.9",
+ "ansi-regex": "^5.0.0",
+ "babel-jest": "^29.7.0",
+ "babel-plugin-syntax-hermes-parser": "0.28.1",
+ "base64-js": "^1.5.1",
+ "chalk": "^4.0.0",
+ "commander": "^12.0.0",
+ "flow-enums-runtime": "^0.0.6",
+ "glob": "^7.1.1",
+ "invariant": "^2.2.4",
+ "jest-environment-node": "^29.7.0",
+ "memoize-one": "^5.0.0",
+ "metro-runtime": "^0.82.2",
+ "metro-source-map": "^0.82.2",
+ "nullthrows": "^1.1.1",
+ "pretty-format": "^29.7.0",
+ "promise": "^8.3.0",
+ "react-devtools-core": "^6.1.1",
+ "react-refresh": "^0.14.0",
+ "regenerator-runtime": "^0.13.2",
+ "scheduler": "0.26.0",
+ "semver": "^7.1.3",
+ "stacktrace-parser": "^0.1.10",
+ "whatwg-fetch": "^3.0.0",
+ "ws": "^6.2.3",
+ "yargs": "^17.6.2"
+ },
+ "bin": {
+ "react-native": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.1.0",
+ "react": "^19.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-spring/node_modules/react-native/node_modules/@react-native/virtualized-lists": {
+ "version": "0.80.1",
+ "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.80.1.tgz",
+ "integrity": "sha512-nqQAeHheSNZBV+syhLVMgKBZv+FhCANfxAWVvfEXZa4rm5jGHsj3yA9vqrh2lcJL3pjd7PW5nMX7TcuJThEAgQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.0.0",
+ "react": "*",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-spring/node_modules/react-native/node_modules/scheduler": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-spring/node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-spring/node_modules/scheduler": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
+ "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-spring/node_modules/ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "async-limiter": "~1.0.0"
+ }
+ },
"node_modules/react-tippy": {
"version": "1.4.0",
"license": "MIT",
@@ -24280,8 +26998,36 @@
"version": "5.2.1",
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.8.7",
- "csstype": "^3.0.2"
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/react-use-measure": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz",
+ "integrity": "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "react": ">=16.13",
+ "react-dom": ">=16.13"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-zdog": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/react-zdog/-/react-zdog-1.2.2.tgz",
+ "integrity": "sha512-Ix7ALha91aOEwiHuxumCeYbARS5XNpc/w0v145oGkM6poF/CvhKJwzLhM5sEZbtrghMA+psAhOJkCTzJoseicA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "resize-observer-polyfill": "^1.5.1"
}
},
"node_modules/read-pkg": {
@@ -25079,6 +27825,16 @@
"node": ">=0.10"
}
},
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/require-from-string": {
"version": "2.0.2",
"license": "MIT",
@@ -25101,6 +27857,13 @@
"license": "MIT",
"peer": true
},
+ "node_modules/resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/resolve": {
"version": "1.22.8",
"license": "MIT",
@@ -25707,6 +28470,16 @@
"node": ">= 0.8"
}
},
+ "node_modules/serialize-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
+ "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/serialize-javascript": {
"version": "6.0.2",
"license": "BSD-3-Clause",
@@ -26295,6 +29068,59 @@
"safe-buffer": "^5.1.0"
}
},
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/stacktrace-parser": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz",
+ "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "type-fest": "^0.7.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/stacktrace-parser/node_modules/type-fest": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
+ "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
+ "license": "(MIT OR CC0-1.0)",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/statuses": {
"version": "1.5.0",
"license": "MIT",
@@ -26600,6 +29426,102 @@
"inline-style-parser": "0.2.4"
}
},
+ "node_modules/styled-components": {
+ "version": "6.1.19",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.19.tgz",
+ "integrity": "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@emotion/is-prop-valid": "1.2.2",
+ "@emotion/unitless": "0.8.1",
+ "@types/stylis": "4.2.5",
+ "css-to-react-native": "3.2.0",
+ "csstype": "3.1.3",
+ "postcss": "8.4.49",
+ "shallowequal": "1.1.0",
+ "stylis": "4.3.2",
+ "tslib": "2.6.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/styled-components"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0",
+ "react-dom": ">= 16.8.0"
+ }
+ },
+ "node_modules/styled-components/node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
+ "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/styled-components/node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/styled-components/node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/styled-components/node_modules/postcss": {
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/styled-components/node_modules/stylis": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
+ "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/styled-components/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "license": "0BSD",
+ "peer": true
+ },
"node_modules/stylehacks": {
"version": "6.1.1",
"license": "MIT",
@@ -26822,6 +29744,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/suspend-react": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz",
+ "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "react": ">=17.0"
+ }
+ },
"node_modules/svg-parser": {
"version": "2.0.4",
"license": "MIT"
@@ -27230,6 +30162,45 @@
"version": "2.20.3",
"license": "MIT"
},
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/test-exclude/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/test-exclude/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/text-decoder": {
"version": "1.2.3",
"license": "Apache-2.0",
@@ -27248,6 +30219,20 @@
"url": "https://bevry.me/fund"
}
},
+ "node_modules/three": {
+ "version": "0.178.0",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.178.0.tgz",
+ "integrity": "sha512-ybFIB0+x8mz0wnZgSGy2MO/WCO6xZhQSZnmfytSPyNpM0sBafGRVhdaj+erYh5U+RhQOAg/eXqw5uVDiM2BjhQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/throat": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
+ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/through": {
"version": "2.3.8",
"license": "MIT"
@@ -27344,6 +30329,13 @@
"node": ">=0.6.0"
}
},
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "license": "BSD-3-Clause",
+ "peer": true
+ },
"node_modules/to-buffer": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
@@ -27434,6 +30426,12 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==",
+ "license": "MIT"
+ },
"node_modules/toidentifier": {
"version": "1.0.1",
"license": "MIT",
@@ -27556,6 +30554,16 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/type-fest": {
"version": "2.19.0",
"license": "(MIT OR CC0-1.0)",
@@ -28078,6 +31086,16 @@
"version": "1.4.1",
"license": "MIT"
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "license": "MIT",
+ "peer": true,
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/utf-8-validate": {
"version": "5.0.10",
"hasInstallScript": true,
@@ -28231,6 +31249,13 @@
"@vimeo/player": "2.29.0"
}
},
+ "node_modules/vlq": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
+ "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/vm-browserify": {
"version": "1.1.2",
"license": "MIT"
@@ -28272,6 +31297,16 @@
"version": "3.0.8",
"license": "MIT"
},
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
"node_modules/warning": {
"version": "4.0.3",
"license": "MIT",
@@ -28940,6 +31975,25 @@
"version": "3.1.1",
"license": "ISC"
},
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/yargs-parser": {
"version": "20.2.9",
"dev": true,
@@ -28948,6 +32002,58 @@
"node": ">=10"
}
},
+ "node_modules/yargs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/yargs/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"dev": true,
@@ -28965,6 +32071,43 @@
"integrity": "sha512-FDRgXlPxpe1bh6HlhL6GfJVcvVNaZKCcLEZ90X1G3Iu+z2g2cIhm2OWj9abPZq1Zqit6SY7Gwh13H9g7acoBnQ==",
"license": "MIT"
},
+ "node_modules/zdog": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/zdog/-/zdog-1.1.3.tgz",
+ "integrity": "sha512-raRj6r0gPzopFm5XWBJZr/NuV4EEnT4iE+U3dp5FV5pCb588Gmm3zLIp/j9yqqcMiHH8VNQlerLTgOqL7krh6w==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/zustand": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.6.tgz",
+ "integrity": "sha512-ihAqNeUVhe0MAD+X8M5UzqyZ9k3FFZLBTtqo6JLPwV53cbRB/mJwBI0PxcIgqhBBHlEs8G45OTDTMq3gNcLq3A==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=12.20.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=18.0.0",
+ "immer": ">=9.0.6",
+ "react": ">=18.0.0",
+ "use-sync-external-store": ">=1.2.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "immer": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "use-sync-external-store": {
+ "optional": true
+ }
+ }
+ },
"node_modules/zwitch": {
"version": "2.0.4",
"license": "MIT",
diff --git a/package.json b/package.json
index be1d1bc34ce..c12f81b9091 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,9 @@
"@rjsf/validator-ajv8": "^5.24.12",
"@sentry/browser": "^8.51.0",
"@types/react": "^18.3.3",
+ "classnames": "^2.5.1",
"clsx": "^2.1.1",
+ "copy-to-clipboard": "^3.3.3",
"docusaurus-plugin-sass": "^0.2.5",
"dotenv": "^16.4.7",
"ethers": "^6.13.5",
@@ -60,14 +62,19 @@
"lodash.debounce": "^4.0.8",
"lodash.isplainobject": "^4.0.6",
"node-polyfill-webpack-plugin": "^2.0.1",
+ "playwright": "^1.54.2",
"prettier": "^3.3.3",
"prism-react-renderer": "^2.1.0",
"react": "^18.0.0",
"react-alert": "^7.0.3",
+ "react-bookmark": "^0.8.2",
"react-dom": "^18.0.0",
"react-dropdown-select": "^4.12.2",
+ "react-icons": "^5.5.0",
"react-modal": "^3.16.3",
"react-player": "^3.3.1",
+ "react-spinners": "^0.17.0",
+ "react-spring": "^10.0.1",
"react-tippy": "^1.4.0",
"remark-codesandbox": "^0.10.1",
"remark-docusaurus-tabs": "^0.2.0",
diff --git a/src/components/Button/button.module.scss b/src/components/Button/button.module.scss
index de71208ae00..5aed34a667f 100644
--- a/src/components/Button/button.module.scss
+++ b/src/components/Button/button.module.scss
@@ -1,4 +1,4 @@
-:root[data-theme="dark"] {
+:root[data-theme='dark'] {
--button-primary-background-color: #1098fc;
--button-secondary-background-color: transparent;
--button-background-color: #1098fc;
@@ -6,10 +6,10 @@
--button-hover-background-color: #036ab5;
--button-hover-shadow: 0px 2px 8px 0px rgba(16, 152, 252, 0.4);
--button-active-background-color: #3baafd;
- --button-danger: #e88f97
+ --button-danger: #e88f97;
}
-:root[data-theme="light"] {
+:root[data-theme='light'] {
--button-primary-background-color: #0376c9;
--button-secondary-background-color: transparent;
--button-background-color: #0376c9;
@@ -17,7 +17,7 @@
--button-hover-background-color: #036ab5;
--button-hover-shadow: 0px 2px 8px 0px rgba(3, 118, 201, 0.2);
--button-active-background-color: #025ea1;
- --button-danger: #D73847
+ --button-danger: #d73847;
}
:root {
@@ -50,7 +50,7 @@ a.button {
justify-content: center;
align-items: center;
min-width: 145px;
- transition-property: "box-shadow", "background-color";
+ transition-property: 'box-shadow', 'background-color';
transition-duration: 0.2s;
transition-timing-function: ease;
@@ -61,12 +61,18 @@ a.button {
--button-hover-background-color: #26a2fc;
}
+ /* Dark mode: Ensure primary buttons use proper dark theme colors */
+ [data-theme='dark'] &.primary {
+ background-color: var(--button-primary-background-color);
+ color: var(--button-color);
+ }
+
&.secondary {
border: 1px solid rgba(3, 118, 201, 1);
--button-color: rgba(3, 118, 201, 1);
background-color: var(--button-secondary-background-color);
&:hover {
- --button-color: #141618
+ --button-color: #141618;
}
}
diff --git a/src/components/CardSection.module.scss b/src/components/CardSection.module.scss
index ddb32ab5e51..a07d470d84c 100644
--- a/src/components/CardSection.module.scss
+++ b/src/components/CardSection.module.scss
@@ -46,6 +46,13 @@
gap: 4rem;
align-items: start;
}
+
+ // When there's no title or description, use full width for cards
+ &.cards-only {
+ @include bp('desktop') {
+ grid-template-columns: 1fr;
+ }
+ }
}
.content-column {
@@ -61,6 +68,10 @@
@include bp('tablet') {
grid-template-columns: repeat(2, 1fr);
}
+
+ @include bp('desktop') {
+ grid-template-columns: repeat(3, 1fr);
+ }
}
.card-column {
diff --git a/src/components/CardSection.tsx b/src/components/CardSection.tsx
index 00f71ca0977..bdda1f32fea 100644
--- a/src/components/CardSection.tsx
+++ b/src/components/CardSection.tsx
@@ -30,13 +30,16 @@ export default function CardSection({
-
diff --git a/src/components/DiscourseComment/index.jsx b/src/components/DiscourseComment/index.jsx
new file mode 100644
index 00000000000..884da416393
--- /dev/null
+++ b/src/components/DiscourseComment/index.jsx
@@ -0,0 +1,32 @@
+import { useEffect } from 'react'
+
+export default function DiscourseComment(props) {
+ // eslint-disable-next-line react/prop-types
+ const { postUrl } = props
+ useEffect(() => {
+ const url = window.location.href
+ if (!url.includes('https://web3auth.io/')) {
+ return
+ } else {
+ window.DiscourseEmbed = {
+ discourseUrl: 'https://web3auth.io/community/',
+ discourseEmbedUrl: postUrl,
+ }
+
+ const d = document.createElement('script')
+ d.type = 'text/javascript'
+ d.async = true
+ d.src = `${window.DiscourseEmbed.discourseUrl}javascripts/embed.js`
+ ;(
+ document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]
+ ).appendChild(d)
+ }
+ }, [])
+
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/src/components/GuidesPage/CustomSelect.module.css b/src/components/GuidesPage/CustomSelect.module.css
new file mode 100644
index 00000000000..0dae0445fc4
--- /dev/null
+++ b/src/components/GuidesPage/CustomSelect.module.css
@@ -0,0 +1,270 @@
+.customSelect {
+ position: relative;
+ min-width: 200px;
+ max-width: 300px;
+ width: 100%;
+ font-weight: 400;
+ font-size: 14px;
+ line-height: 125%;
+}
+
+.control {
+ background: var(--ifm-background-surface-color);
+ color: var(--ifm-font-color-base);
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: 10px;
+ min-height: 48px;
+ height: 48px;
+ max-height: none;
+ box-shadow: none;
+ margin: 0;
+ align-self: center;
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ transition: all 0.15s ease;
+ box-sizing: border-box;
+}
+
+.control:hover {
+ border-color: var(--ifm-color-emphasis-400);
+}
+
+.controlFocused {
+ box-shadow: 0 0 0 2px rgba(var(--ifm-color-primary-r), var(--ifm-color-primary-g), var(--ifm-color-primary-b), 0.2);
+ border-color: var(--ifm-color-primary);
+}
+
+.controlFocused:hover {
+ border-color: var(--ifm-color-primary);
+}
+
+.controlExpanded {
+ height: auto;
+ align-items: flex-start;
+}
+
+.valueContainer {
+ padding: 8px 12px;
+ height: 30px;
+ overflow: hidden;
+ box-sizing: border-box;
+ flex: 1;
+ display: flex;
+ align-items: center;
+ flex-wrap: nowrap;
+ gap: 4px;
+}
+
+.valueContainerExpanded {
+ height: auto;
+ overflow: visible;
+ align-items: flex-start;
+ flex-wrap: wrap;
+}
+
+.multiValueContainer {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ align-items: flex-start;
+ width: 100%;
+ overflow: visible;
+}
+
+.multiValue {
+ color: var(--ifm-color-primary);
+ background-color: var(--ifm-color-primary-lightest);
+ font-weight: 500;
+ font-size: 14px;
+ line-height: 1.2;
+ border: none;
+ border-radius: 6px;
+ margin: 2px;
+ display: flex;
+ align-items: center;
+ max-width: 100%;
+}
+
+.multiValueLabel {
+ color: var(--ifm-color-primary);
+ font-weight: 500;
+ font-size: 14px;
+ padding: 4px 8px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.multiValueRemove {
+ color: var(--ifm-color-primary);
+ border-radius: 0 6px 6px 0;
+ background: none;
+ border: none;
+ padding: 4px 8px;
+ cursor: pointer;
+ font-size: 16px;
+ font-weight: bold;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.15s ease;
+}
+
+.multiValueRemove:hover {
+ background-color: var(--ifm-color-primary-lighter);
+ color: var(--ifm-color-primary-dark);
+}
+
+.placeholder {
+ color: var(--ifm-color-emphasis-600);
+ font-size: 14px;
+ padding: 4px 8px;
+ line-height: 30px;
+}
+
+.indicatorsContainer {
+ height: 46px;
+ padding: 0 8px;
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+}
+
+.indicatorsContainerExpanded {
+ align-items: flex-start;
+ padding: 8px;
+ height: auto;
+}
+
+.clearIndicator {
+ color: var(--ifm-color-emphasis-600);
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 16px;
+ font-weight: bold;
+ padding: 4px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.15s ease;
+}
+
+.clearIndicator:hover {
+ color: var(--ifm-color-danger);
+}
+
+.dropdownIndicator {
+ color: var(--ifm-color-emphasis-600);
+ font-size: 12px;
+ transition: transform 0.15s ease, color 0.15s ease;
+ user-select: none;
+}
+
+.dropdownIndicatorRotated {
+ transform: rotate(180deg);
+}
+
+.dropdownIndicator:hover {
+ color: var(--ifm-color-primary);
+}
+
+.menu {
+ background: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: 10px;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+ z-index: 1000;
+ position: absolute;
+ top: 100%;
+ left: 0;
+ right: 0;
+ margin-top: 4px;
+ max-height: 300px;
+ overflow-y: auto;
+}
+
+.menuList {
+ padding: 4px 0;
+}
+
+.option {
+ padding: 8px 12px;
+ cursor: pointer;
+ background-color: transparent;
+ color: var(--ifm-font-color-base);
+ font-size: 14px;
+ transition: background-color 0.15s ease;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.option:hover {
+ background-color: var(--ifm-color-primary-lightest);
+}
+
+.optionSelected {
+ background-color: var(--ifm-color-primary);
+ color: white;
+}
+
+.optionSelected:hover {
+ background-color: var(--ifm-color-primary-dark);
+}
+
+.optionLabel {
+ flex: 1;
+ text-align: left;
+}
+
+.optionRemove {
+ background: none;
+ border: none;
+ color: white;
+ cursor: pointer;
+ font-size: 16px;
+ font-weight: bold;
+ padding: 2px 6px;
+ margin-left: 8px;
+ border-radius: 3px;
+ transition: all 0.15s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 20px;
+ height: 20px;
+}
+
+.optionRemove:hover {
+ background-color: rgba(255, 255, 255, 0.2);
+}
+
+/* Mobile responsive styles */
+@media (max-width: 768px) {
+ .customSelect {
+ min-width: 100%;
+ max-width: 100%;
+ width: 100%;
+ }
+
+ .control {
+ width: 100%;
+ min-width: 100%;
+ max-width: 100%;
+ min-height: 48px;
+ height: 48px;
+ max-height: none;
+ }
+
+ .controlExpanded {
+ height: auto;
+ }
+
+ .menu {
+ width: 100%;
+ min-width: 100%;
+ }
+}
\ No newline at end of file
diff --git a/src/components/GuidesPage/CustomSelect.tsx b/src/components/GuidesPage/CustomSelect.tsx
new file mode 100644
index 00000000000..9fe3a80d933
--- /dev/null
+++ b/src/components/GuidesPage/CustomSelect.tsx
@@ -0,0 +1,163 @@
+import React, { useState, useRef, useEffect } from 'react';
+import styles from './CustomSelect.module.css';
+
+export interface OptionType {
+ label: string;
+ value: string;
+}
+
+interface CustomSelectProps {
+ options: OptionType[];
+ placeholder: string;
+ onChange: (selectedOptions: OptionType[]) => void;
+ value?: OptionType[];
+ isMulti?: boolean;
+}
+
+const CustomSelect: React.FC
= ({
+ options,
+ placeholder,
+ onChange,
+ value = [],
+ isMulti = true
+}) => {
+ const [isOpen, setIsOpen] = useState(false);
+ const [selectedOptions, setSelectedOptions] = useState(value);
+ const dropdownRef = useRef(null);
+
+ useEffect(() => {
+ setSelectedOptions(value);
+ }, [value]);
+
+ useEffect(() => {
+ const handleClickOutside = (event: MouseEvent) => {
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
+ setIsOpen(false);
+ }
+ };
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => {
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, []);
+
+ const handleOptionClick = (option: OptionType) => {
+ let newSelectedOptions: OptionType[];
+
+ if (isMulti) {
+ const isSelected = selectedOptions.some(selected => selected.value === option.value);
+ if (isSelected) {
+ newSelectedOptions = selectedOptions.filter(selected => selected.value !== option.value);
+ } else {
+ newSelectedOptions = [...selectedOptions, option];
+ }
+ } else {
+ newSelectedOptions = [option];
+ setIsOpen(false);
+ }
+
+ setSelectedOptions(newSelectedOptions);
+ onChange(newSelectedOptions);
+ };
+
+ const handleRemoveOption = (optionToRemove: OptionType, event: React.MouseEvent) => {
+ event.stopPropagation();
+ const newSelectedOptions = selectedOptions.filter(selected => selected.value !== optionToRemove.value);
+ setSelectedOptions(newSelectedOptions);
+ onChange(newSelectedOptions);
+ };
+
+ const handleClearAll = (event: React.MouseEvent) => {
+ event.stopPropagation();
+ setSelectedOptions([]);
+ onChange([]);
+ };
+
+ const toggleDropdown = () => {
+ setIsOpen(!isOpen);
+ };
+
+ const isOptionSelected = (option: OptionType) => {
+ return selectedOptions.some(selected => selected.value === option.value);
+ };
+
+ const hasMultipleSelections = selectedOptions.length >= 2;
+
+ return (
+
+
+
+ {selectedOptions.length === 0 ? (
+
{placeholder}
+ ) : (
+
+ {selectedOptions.map(option => (
+
+ {option.label}
+
+
+ ))}
+
+ )}
+
+
+ {selectedOptions.length > 0 && (
+
+ )}
+
+ ▼
+
+
+
+
+ {isOpen && (
+
+
+ {options.map(option => (
+
handleOptionClick(option)}
+ >
+ {option.label}
+ {isOptionSelected(option) && (
+
+ )}
+
+ ))}
+
+
+ )}
+
+ );
+};
+
+export default CustomSelect;
diff --git a/src/components/GuidesPage/GuideCard.module.css b/src/components/GuidesPage/GuideCard.module.css
new file mode 100644
index 00000000000..f40fd7147f4
--- /dev/null
+++ b/src/components/GuidesPage/GuideCard.module.css
@@ -0,0 +1,137 @@
+:root {
+ --card-border-radius: 12px;
+ --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+ --card-shadow-hover: 0 4px 16px rgba(0, 0, 0, 0.1);
+ --card-padding: 24px;
+ --card-gap: 16px;
+}
+
+.card {
+ background-color: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: var(--card-border-radius);
+ box-shadow: var(--card-shadow);
+ overflow: hidden;
+ transition: all 0.2s ease-in-out;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+.card:hover {
+ box-shadow: var(--card-shadow-hover);
+ transform: translateY(-2px);
+ border-color: var(--ifm-color-emphasis-300);
+}
+
+.cardLink {
+ text-decoration: none;
+ color: inherit;
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+}
+
+.cardLink:hover {
+ text-decoration: none;
+ color: inherit;
+}
+
+.imageContainer {
+ width: 100%;
+ height: 200px;
+ overflow: hidden;
+ background-color: var(--ifm-color-emphasis-100);
+}
+
+.image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ transition: transform 0.2s ease-in-out;
+}
+
+.card:hover .image {
+ transform: scale(1.02);
+}
+
+.content {
+ padding: var(--card-padding);
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: var(--card-gap);
+}
+
+.typeContainer {
+ margin-bottom: 8px;
+}
+
+.title {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.4;
+ color: var(--ifm-font-color-base);
+ margin: 0;
+ margin-bottom: 12px;
+}
+
+.description {
+ font-size: 16px;
+ line-height: 1.5;
+ color: var(--ifm-color-emphasis-700);
+ margin: 0;
+ flex: 1;
+}
+
+.tagsContainer {
+ padding: 0 var(--card-padding) var(--card-padding);
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.meta {
+ padding: 0 var(--card-padding) var(--card-padding);
+ font-size: 14px;
+ color: var(--ifm-color-emphasis-600);
+ border-top: 1px solid var(--ifm-color-emphasis-200);
+ padding-top: 16px;
+}
+
+/* Search highlight styling */
+mark {
+ background-color: #fef3c7;
+ color: #92400e;
+ padding: 2px 4px;
+ border-radius: 4px;
+ font-weight: 500;
+}
+
+/* Dark theme adjustments */
+html[data-theme='dark'] {
+ --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+ --card-shadow-hover: 0 4px 16px rgba(0, 0, 0, 0.3);
+}
+
+html[data-theme='dark'] .card {
+ background-color: var(--ifm-background-surface-color);
+ border-color: var(--ifm-color-emphasis-300);
+}
+
+html[data-theme='dark'] .card:hover {
+ border-color: var(--ifm-color-emphasis-400);
+}
+
+html[data-theme='dark'] .imageContainer {
+ background-color: var(--ifm-color-emphasis-200);
+}
+
+html[data-theme='dark'] .meta {
+ border-top-color: var(--ifm-color-emphasis-300);
+}
+
+html[data-theme='dark'] mark {
+ background-color: #451a03;
+ color: #fbbf24;
+}
\ No newline at end of file
diff --git a/src/components/GuidesPage/GuideCard.tsx b/src/components/GuidesPage/GuideCard.tsx
new file mode 100644
index 00000000000..44a9d789560
--- /dev/null
+++ b/src/components/GuidesPage/GuideCard.tsx
@@ -0,0 +1,119 @@
+import React from 'react';
+import Link from '@docusaurus/Link';
+import Badge from '@site/src/components/Badge';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import styles from './GuideCard.module.css';
+
+interface GuideCardProps {
+ title: string;
+ description: string;
+ link: string;
+ image?: string;
+ tags?: string[];
+ author?: string;
+ date?: string;
+ type?: string;
+ searchInput?: string;
+ activeTags?: string[];
+}
+
+export default function GuideCard({
+ title,
+ description,
+ link,
+ image,
+ tags = [],
+ author,
+ date,
+ type,
+ searchInput = '',
+ activeTags = []
+}: GuideCardProps) {
+ const { siteConfig } = useDocusaurusContext();
+ const { baseUrl } = siteConfig;
+
+ function highlightSearchText(text: string) {
+ if (!searchInput.trim()) {
+ return text;
+ }
+
+ const searchTerms = searchInput.trim().split(/\s+/);
+ const regex = new RegExp(`(${searchTerms.join("|")})`, "gi");
+
+ // Use replace to find matches and build result
+ let lastIndex = 0;
+ const elements: React.ReactNode[] = [];
+ let match;
+
+ // Reset regex lastIndex to avoid stateful issues
+ regex.lastIndex = 0;
+
+ while ((match = regex.exec(text)) !== null) {
+ // Add text before the match
+ if (match.index > lastIndex) {
+ elements.push(text.slice(lastIndex, match.index));
+ }
+
+ // Add the highlighted match
+ elements.push({match[0]});
+
+ lastIndex = match.index + match[0].length;
+
+ // Prevent infinite loop with zero-length matches
+ if (match.index === regex.lastIndex) {
+ regex.lastIndex++;
+ }
+ }
+
+ // Add remaining text after last match
+ if (lastIndex < text.length) {
+ elements.push(text.slice(lastIndex));
+ }
+
+ return {elements};
+ }
+
+ return (
+
+
+ {image && (
+
+

+
+ )}
+
+
+ {type && (
+
+
+
+ )}
+
+
{highlightSearchText(title)}
+
+
+ {highlightSearchText(description)}
+
+
+
+
+ {tags.length > 0 && (
+
+ {tags.map((tag) => (
+
+ ))}
+
+ )}
+
+ {(author || date) && (
+
+ {author && date && `${author} | ${date}`}
+
+ )}
+
+ );
+}
diff --git a/src/components/GuidesPage/index.tsx b/src/components/GuidesPage/index.tsx
new file mode 100644
index 00000000000..efc772c34aa
--- /dev/null
+++ b/src/components/GuidesPage/index.tsx
@@ -0,0 +1,211 @@
+/* eslint-disable no-restricted-globals */
+/* eslint-disable react/no-array-index-key */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import Layout from "@theme/Layout";
+import { GuidesInterface, platformMap, productMap } from "../../utils/guides-map";
+
+
+import { useState, useEffect } from "react";
+import SEO from "../../components/SEO";
+import Hero from "@site/src/components/Hero/Hero";
+import Input from "@site/src/components/Input";
+import GuideCard from "./GuideCard";
+import CustomSelect, { OptionType } from "./CustomSelect";
+import styles from "./styles.module.css";
+
+export default function Guides({ content = {} }: GuidesInterface) {
+ const safeContent = content || {};
+
+ const completeGuides = Object.entries(safeContent)
+ .map(([key, value]) => {
+ if (value && value.type === "guide") return { ...value, link: `/guides/${key}` };
+ return null;
+ })
+ .filter(Boolean)
+ .sort((a: any, b: any) => {
+ if (a.pinned && !b.pinned) return -1;
+ if (!a.pinned && b.pinned) return 1;
+ const aDate = new Date(a.date);
+ const bDate = new Date(b.date);
+ return +bDate - +aDate;
+ });
+
+ const [searchInput, setSearchInput] = useState("");
+ const [tags, setTags] = useState([]);
+ const [productFilter, setProductFilter] = useState([]);
+ const [platformFilter, setPlatformFilter] = useState([]);
+ const [selectedProducts, setSelectedProducts] = useState([]);
+ const [selectedPlatforms, setSelectedPlatforms] = useState([]);
+ const [filteredGuides, setFilteredGuides] = useState(completeGuides);
+ const { siteConfig } = useDocusaurusContext();
+ const { baseUrl } = siteConfig;
+
+ // Apply tag filters first
+ useEffect(() => {
+ let filtered = completeGuides;
+
+ if (productFilter.length > 0 || platformFilter.length > 0) {
+ filtered = completeGuides.filter((item) => {
+ if (!item || !item.tags || !Array.isArray(item.tags)) return false;
+
+ const prodFil =
+ productFilter.length === 0 || productFilter.some((tag) => item.tags.includes(tag));
+ const platFil =
+ platformFilter.length === 0 || platformFilter.some((tag) => item.tags.includes(tag));
+
+ return prodFil && platFil;
+ });
+ }
+
+ setFilteredGuides(filtered);
+ }, [productFilter, platformFilter, completeGuides]);
+
+ const onChangeProduct = (selectedOptions: OptionType[]) => {
+ const filterValue = selectedOptions ? selectedOptions.map((item) => item.value) : [];
+ setSelectedProducts(selectedOptions);
+ setProductFilter(filterValue);
+ setTags([...platformFilter, ...filterValue]);
+ };
+
+ const onChangePlatform = (selectedOptions: OptionType[]) => {
+ const filterValue = selectedOptions ? selectedOptions.map((item) => item.value) : [];
+ setSelectedPlatforms(selectedOptions);
+ setPlatformFilter(filterValue);
+ setTags([...productFilter, ...filterValue]);
+ };
+
+ function highlightSearchText(text) {
+ if (!searchInput.trim()) {
+ return text;
+ }
+
+ const searchTerms = searchInput.trim().split(/\s+/);
+ const regex = new RegExp(`(${searchTerms.join("|")})`, "gi");
+
+ // Use replace to find matches and build result
+ let lastIndex = 0;
+ const elements = [];
+ let match;
+
+ // Reset regex lastIndex to avoid stateful issues
+ regex.lastIndex = 0;
+
+ while ((match = regex.exec(text)) !== null) {
+ // Add text before the match
+ if (match.index > lastIndex) {
+ elements.push(text.slice(lastIndex, match.index));
+ }
+
+ // Add the highlighted match
+ elements.push({match[0]});
+
+ lastIndex = match.index + match[0].length;
+
+ // Prevent infinite loop with zero-length matches
+ if (match.index === regex.lastIndex) {
+ regex.lastIndex++;
+ }
+ }
+
+ // Add remaining text after last match
+ if (lastIndex < text.length) {
+ elements.push(text.slice(lastIndex));
+ }
+
+ return {elements};
+ }
+
+ function onChangeSearch(input) {
+ setSearchInput(input);
+ }
+
+ // Filter the already filtered guides based on search
+ const displayedGuides = filteredGuides.filter((item) => {
+ if (!item) return false; // Skip null items
+ if (!searchInput.trim()) return true;
+
+ const searchTerms = searchInput.toLowerCase().trim().split(/\s+/);
+ return searchTerms.every(
+ (term) =>
+ (item.title && item.title.toLowerCase().includes(term)) ||
+ (item.description && item.description.toLowerCase().includes(term)) ||
+ (item.tags && Array.isArray(item.tags) && item.tags.some((tag) => tag.toLowerCase().includes(term))),
+ );
+ });
+
+ // No transformation needed - we'll render GuideCard directly
+
+ return (
+
+
+
+
+
+
+
+
+ {displayedGuides.length > 0 ? (
+
+ {displayedGuides.map((item: any) => (
+
+ ))}
+
+ ) : (
+
+ )}
+
+
+ );
+}
+
+
diff --git a/src/components/GuidesPage/styles.module.css b/src/components/GuidesPage/styles.module.css
new file mode 100644
index 00000000000..ae00b8759ee
--- /dev/null
+++ b/src/components/GuidesPage/styles.module.css
@@ -0,0 +1,670 @@
+.header {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: space-between;
+ padding-top: 5%;
+ padding-right: 5%;
+ padding-bottom: 16px;
+ padding-left: 5%;
+}
+
+.header h1 {
+ font-weight: 700;
+ font-size: 48px;
+ line-height: 150%;
+}
+
+.header h1:after {
+ display: none;
+}
+
+.header p {
+ color: var(--w3a-color-icon-gray);
+ font-weight: 500;
+ font-size: 14px;
+ line-height: 150%;
+}
+
+.container {
+ width: 90%;
+ display: flex;
+ flex-flow: row wrap;
+ margin: 5%;
+ margin-top: 20px;
+ margin-bottom: 60px;
+ justify-content: space-between;
+}
+
+.article {
+ width: 90%;
+ color: var(--ifm-font-color-base);
+ text-decoration: none;
+ padding: 0 8px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ max-width: 550px;
+}
+
+.article img {
+ top: 0px;
+ left: 0px;
+ opacity: 1;
+ border-radius: 20px;
+ margin-bottom: 8px;
+}
+
+.article:hover {
+ text-decoration: none;
+}
+
+.articleContent:hover img {
+ opacity: 0.7;
+ cursor: pointer;
+}
+
+.article .contentContainer {
+ padding: 0 8px;
+}
+
+.article h3 {
+ font-family: var(--ifm-font-family-base);
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 30px;
+ color: var(--ifm-font-color-base);
+}
+
+.article p {
+ font-family: var(--ifm-font-family-base);
+ font-size: 16px;
+ line-height: 20px;
+ color: var(--ifm-font-color-base);
+}
+
+.date {
+ color: var(--ifm-color-emphasis-500);
+ font-size: 14px;
+ padding: 2px;
+}
+
+.tagContainer {
+ width: 100%;
+ max-width: 550px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ flex-direction: row;
+ overflow-x: scroll;
+ overflow-y: hidden;
+ gap: 5px;
+}
+
+/* Hide scrollbar for Chrome, Safari and Opera */
+.tagContainer::-webkit-scrollbar {
+ display: none;
+}
+
+/* Hide scrollbar for IE, Edge and Firefox */
+.tagContainer {
+ -ms-overflow-style: none;
+ /* IE and Edge */
+ scrollbar-width: none;
+ /* Firefox */
+}
+
+.tag {
+ font-weight: 500;
+ font-size: 12px;
+ line-height: 150%;
+ padding: 2px 10px;
+ height: 22px;
+ background-color: var(--ifm-color-emphasis-200);
+ color: var(--ifm-color-emphasis-600);
+ border-radius: 30px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: visible;
+ white-space: nowrap;
+}
+
+.tagActive {
+ font-weight: 500;
+ font-size: 12px;
+ line-height: 150%;
+ padding: 2px 10px;
+ height: 22px;
+ background-color: var(--w3a-color-indigo-background);
+ color: var(--w3a-color-indigo);
+ border-radius: 30px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: visible;
+ white-space: nowrap;
+}
+
+.headerInteractionArea {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ margin-top: 32px;
+ margin-bottom: 48px;
+ align-items: flex-start;
+ gap: 24px;
+ padding: 0 8px;
+}
+
+.searchArea {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: flex-start;
+ gap: 16px;
+ flex-wrap: wrap;
+}
+
+.searchInput {
+ flex: 1;
+ min-width: 280px;
+ max-width: 400px;
+ align-self: center;
+ display: flex;
+ align-items: center;
+ margin: 0;
+ padding: 0;
+}
+
+/* Target the Input component wrapper specifically */
+.searchInput>label {
+ margin: 0 !important;
+ width: 100%;
+ align-self: center;
+ display: flex;
+ align-items: center;
+}
+
+/* Ensure input component has same baseline as selects */
+.searchInput input {
+ margin: 0 !important;
+ vertical-align: top !important;
+ border-color: var(--ifm-color-emphasis-300) !important;
+ background-color: var(--ifm-background-surface-color) !important;
+ box-sizing: border-box !important;
+ flex: 1;
+}
+
+/* Ensure consistent minimum heights for all form elements */
+.searchArea input {
+ height: 48px;
+ min-height: 48px;
+ max-height: 48px;
+}
+
+.searchArea>div {
+ min-height: 48px;
+ height: auto;
+ max-height: none;
+}
+
+/* Style the custom select components to match */
+.searchArea .customSelect {
+ min-width: 200px;
+ max-width: 300px;
+ flex-shrink: 0;
+ margin: 0;
+ align-self: center;
+}
+
+/* Add focus states for better accessibility */
+.searchArea input:focus {
+ border-color: var(--ifm-color-primary) !important;
+ box-shadow: 0 0 0 2px rgba(var(--ifm-color-primary-r), var(--ifm-color-primary-g), var(--ifm-color-primary-b), 0.2) !important;
+ outline: none !important;
+}
+
+
+
+@media (max-width: 768px) {
+ .searchArea {
+ flex-direction: column;
+ align-items: stretch;
+ gap: 12px;
+ }
+
+ .searchInput {
+ min-width: 100%;
+ max-width: 100%;
+ width: 100%;
+ }
+
+ .searchInput input {
+ width: 100% !important;
+ }
+
+ .searchArea .customSelect {
+ min-width: 100% !important;
+ max-width: 100% !important;
+ width: 100% !important;
+ }
+}
+
+mark {
+ background-color: #fef3c7;
+ color: #92400e;
+ padding: 2px 4px;
+ border-radius: 4px;
+ font-weight: 500;
+}
+
+html[data-theme='dark'] mark {
+ background-color: #451a03;
+ color: #fbbf24;
+}
+
+.filterButton {
+ width: 100%;
+ max-width: 175px;
+ height: 42px;
+ padding: 10px;
+ background-color: var(--ifm-background-surface-color);
+ align-items: center;
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: 20.5px;
+ padding: 10px;
+ font-style: normal;
+ font-weight: 400;
+ font-size: 14px;
+ line-height: 125%;
+ color: var(--w3a-color-icon-gray);
+}
+
+.filterButton:hover {
+ background-color: var(--ifm-footer-background-color);
+ cursor: pointer;
+}
+
+.filterButton:active {
+ border-width: 2px;
+ padding: 9px;
+}
+
+.searchBox {
+ width: 100%;
+ max-width: 276px;
+ height: 42px;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ border-style: solid;
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: 8px;
+ padding: 10px;
+ background-color: var(--ifm-background-surface-color);
+ color: var(--ifm-font-color-base);
+}
+
+.searchIcon {
+ height: 18px;
+ width: 18px;
+ color: var(--w3a-color-icon-gray);
+}
+
+.searchBox:focus-within {
+ border-width: 2px;
+ padding: 9px;
+}
+
+.searchTerm {
+ width: 100%;
+ padding: 5px;
+ padding-left: 12px;
+ height: 24px;
+ border: 0;
+ outline: none;
+ font-style: normal;
+ font-weight: 400;
+ font-size: 14px;
+ line-height: 125%;
+ background-color: var(--ifm-background-surface-color);
+ color: var(--ifm-font-color-base);
+}
+
+.searchClearButton {
+ border: 0;
+ background-color: var(--ifm-background-surface-color);
+ padding: 5px;
+ align-items: center;
+ display: flex;
+ height: 24px;
+ width: 24px;
+}
+
+.cardsGrid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
+ gap: 24px;
+ margin-top: 0;
+ padding: 0px 8px 16px 8px;
+}
+
+@media (max-width: 768px) {
+ .cardsGrid {
+ grid-template-columns: 1fr;
+ gap: 20px;
+ padding: 0;
+ }
+}
+
+@media (min-width: 1200px) {
+ .cardsGrid {
+ grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
+ gap: 32px;
+ }
+}
+
+.noResults {
+ width: 100%;
+ text-align: center;
+ font-size: 20px;
+ font-weight: 700;
+ color: var(--ifm-font-color-base);
+ margin-top: 40px;
+ padding: 40px 20px;
+ background-color: var(--ifm-color-emphasis-100);
+ border-radius: 12px;
+}
+
+.modalHeader {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 10px;
+ padding-bottom: 0;
+ border-width: 0;
+ border-color: var(--ifm-footer-background-color);
+ border-style: solid;
+ border-bottom-width: 2px;
+ height: 60px;
+}
+
+.modalHeader h2 {
+ font-family: var(--ifm-font-family-base);
+ font-weight: 900;
+ font-size: 24px;
+ text-align: center;
+}
+
+.modalBody {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ justify-content: space-between;
+ padding: 20px;
+ padding-top: 5px;
+ overflow: scroll;
+ height: calc(80vh - 120px);
+}
+
+.modalTagList {
+ width: 300px;
+}
+
+.modalTagList h3 {
+ font-family: var(--ifm-font-family-base);
+ font-weight: 500;
+ font-size: 20px;
+ text-align: left;
+ padding: 5px;
+ padding-top: 20px;
+}
+
+.checkBoxContainer {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: flex-start;
+ padding: 7px;
+ padding-left: 0;
+ border-radius: 5px;
+}
+
+.checkBoxContainer:hover {
+ cursor: pointer;
+ background-color: rgba(var(--ifm-color-primary-r), var(--ifm-color-primary-g), var(--ifm-color-primary-b), 0.3);
+}
+
+.checkBoxInputContainer {
+ width: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.checkBox {
+ width: 20px;
+ height: 20px;
+ border-color: var(--ifm-footer-background-color);
+ background-color: var(--ifm-background-surface-color);
+}
+
+.checkBoxLabelContainer {
+ color: var(--ifm-font-color-base);
+ font-size: 17px;
+ font-weight: 400;
+ text-align: left;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.modalFooter {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ padding: 10px;
+ height: 60px;
+ position: fixed;
+}
+
+.modalClearButton {
+ background-color: var(--ifm-background-surface-color);
+ font-size: 17px;
+ border: none;
+ color: var(--ifm-color-primary);
+ padding: 10px;
+}
+
+.modalClearButton:hover {
+ color: var(--ifm-font-color-base);
+ cursor: pointer;
+}
+
+.modalClearButton:active {
+ color: var(--ifm-color-primary-dark);
+}
+
+.modalSaveButton {
+ padding: 10px;
+ padding-left: 20px;
+ padding-right: 20px;
+ background-color: var(--ifm-color-primary-dark);
+ align-items: center;
+ border-style: none;
+ border-radius: 100px;
+ font-size: 17px;
+ line-height: 24px;
+ font-weight: 500;
+ color: #ffffff;
+}
+
+.modalSaveButton:hover {
+ background-color: var(--ifm-color-primary-darker);
+ cursor: pointer;
+}
+
+.modalSaveButton:active {
+ background-color: var(--ifm-color-primary-darkest);
+}
+
+.buttonGroup {
+ display: flex;
+ width: 100%;
+ font-size: 0.875rem;
+ line-height: 1.25rem;
+ font-weight: 500;
+ gap: 6px;
+}
+
+.tab {
+ display: flex;
+ width: fit-content;
+ align-items: flex-start;
+ text-align: center;
+ justify-content: center;
+ border-width: 0;
+ border-bottom-width: 2px;
+ border-color: transparent;
+ border-style: solid;
+ font-style: normal;
+ font-weight: 500;
+ font-size: 16px;
+ line-height: 125%;
+ padding: 0px 16px 30px;
+ gap: 6px;
+ color: var(--w3a-color-icon-gray);
+ cursor: pointer;
+}
+
+.tab:hover {
+ border-width: 0;
+ border-bottom-width: 2px;
+ border-color: var(--ifm-color-primary);
+ color: var(--ifm-color-primary);
+ border-style: solid;
+}
+
+.activeTab {
+ display: flex;
+ align-items: flex-start;
+ text-align: center;
+ justify-content: center;
+ border-width: 0;
+ border-bottom-width: 2px;
+ border-color: var(--ifm-color-primary);
+ color: var(--ifm-color-primary);
+ border-style: solid;
+ font-style: normal;
+ font-weight: 500;
+ font-size: 16px;
+ line-height: 125%;
+ padding: 0px 16px 30px;
+ gap: 6px;
+ cursor: pointer;
+}
+
+.tabIconContainer {
+ height: 18px;
+ width: 18px;
+ padding: 1px;
+}
+
+.pillContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ /* white */
+ background: var(--w3a-color-indigo-background);
+ border-radius: 8px;
+ text-decoration: none;
+ padding: 0;
+ margin: 0;
+ margin-bottom: 7px;
+ width: max-content;
+ overflow: hidden;
+ flex-wrap: wrap;
+}
+
+.pill {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ text-align: center;
+ align-items: center;
+ width: max-content;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ padding-left: 12px;
+ padding-right: 12px;
+ margin: 0;
+ font-weight: 500 !important;
+ font-size: 12px;
+ text-transform: uppercase;
+ line-height: 150%;
+ color: var(--w3a-color-indigo);
+ flex-wrap: wrap;
+}
+
+@media only screen and (max-width: 1046px) {
+ .headerInteractionArea {
+ flex-direction: column;
+ gap: 50px;
+ }
+
+ .searchArea {
+ justify-content: flex-start;
+ }
+}
+
+@media only screen and (max-width: 889px) {
+ .header {
+ text-align: center;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .headerInteractionArea {
+ align-items: center;
+ justify-content: center;
+ }
+
+ .buttonGroup {
+ width: 100%;
+ overflow: scroll;
+ }
+
+ .searchArea {
+ flex-direction: column;
+ }
+
+ .container {
+ justify-content: center;
+ }
+}
+
+@media only screen and (min-width: 889px) {
+ .article {
+ width: 45%;
+ }
+}
+
+@media only screen and (min-width: 1334px) {
+ .article {
+ width: 30%;
+ }
+}
+
+@media only screen and (max-width: 750px) {
+ .modalBody {
+ flex-direction: column;
+ }
+}
\ No newline at end of file
diff --git a/src/components/NavDropdown/ConnectMetaMask.html b/src/components/NavDropdown/ConnectMetaMask.html
deleted file mode 100644
index 0476aba2472..00000000000
--- a/src/components/NavDropdown/ConnectMetaMask.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
diff --git a/src/components/NavDropdown/DeveloperTools.html b/src/components/NavDropdown/DeveloperTools.html
deleted file mode 100644
index 18c9c77a15d..00000000000
--- a/src/components/NavDropdown/DeveloperTools.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
diff --git a/src/components/NavDropdown/EmbedMetaMask.html b/src/components/NavDropdown/EmbedMetaMask.html
deleted file mode 100644
index a3115126a66..00000000000
--- a/src/components/NavDropdown/EmbedMetaMask.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
diff --git a/src/components/NavDropdown/ExtendScale.html b/src/components/NavDropdown/ExtendScale.html
deleted file mode 100644
index 29e4596148c..00000000000
--- a/src/components/NavDropdown/ExtendScale.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
diff --git a/src/components/NavDropdown/Products.html b/src/components/NavDropdown/Products.html
new file mode 100644
index 00000000000..a89e905a1b0
--- /dev/null
+++ b/src/components/NavDropdown/Products.html
@@ -0,0 +1,335 @@
+
\ No newline at end of file
diff --git a/src/components/NavbarWallet/index.tsx b/src/components/NavbarWallet/index.tsx
index c6eaf559676..195494c18b5 100644
--- a/src/components/NavbarWallet/index.tsx
+++ b/src/components/NavbarWallet/index.tsx
@@ -118,17 +118,17 @@ const NavbarWalletComponent: FC = ({ includeUrl = [] }: INavbarWalletComponent)
style={
colorMode === 'dark'
? {
- '--button-color': 'var(--consumer-orange)',
- '--button-text-color': 'var(--general-black)',
- '--button-color-hover': 'var(--general-white)',
- '--button-text-color-hover': 'var(--general-black)',
- }
+ '--button-color': 'var(--consumer-orange)',
+ '--button-text-color': 'var(--general-black)',
+ '--button-color-hover': 'var(--general-white)',
+ '--button-text-color-hover': 'var(--general-black)',
+ }
: {
- '--button-color': 'var(--consumer-orange)',
- '--button-text-color': 'var(--general-black)',
- '--button-color-hover': 'var(--general-black)',
- '--button-text-color-hover': 'var(--general-white)',
- }
+ '--button-color': 'var(--consumer-orange)',
+ '--button-text-color': 'var(--general-black)',
+ '--button-color-hover': 'var(--general-black)',
+ '--button-text-color-hover': 'var(--general-white)',
+ }
}
/>
) : (
@@ -200,6 +200,14 @@ const NavbarWallet = props => {
const [loginEnabled, setLoginEnabled] = useState(false)
useEffect(() => {
+ // Handle case where ldClient is null (when LaunchDarkly isn't initialized)
+ if (!ldClient) {
+ console.warn('LaunchDarkly client not available, disabling login feature');
+ setLdReady(true);
+ setLoginEnabled(false);
+ return;
+ }
+
ldClient.waitUntilReady().then(() => {
setLoginEnabled(ldClient.variation(LOGIN_FF, false))
setLdReady(true)
diff --git a/src/components/SEO/index.tsx b/src/components/SEO/index.tsx
new file mode 100644
index 00000000000..9ef34af7212
--- /dev/null
+++ b/src/components/SEO/index.tsx
@@ -0,0 +1,90 @@
+import Head from "@docusaurus/Head";
+
+export default function SEO(props) {
+ // eslint-disable-next-line react/prop-types
+ const { title, description, image, slug, keywords } = props;
+
+ return (
+
+ {title ? {title} | Web3Auth : Documentation | Web3Auth}
+ {description ? (
+
+ ) : (
+
+ )}
+
+ {/* Add keywords to meta from an array of keywords */}
+ {keywords ? (
+ keywords.length > 0 && (
+
+ )
+ ) : (
+
+ )}
+
+ {/* Open Graph Meta Tags */}
+
+
+ {title ? : }
+ {description ? (
+
+ ) : (
+
+ )}
+ {slug ? : }
+
+ {image ? (
+
+ ) : (
+
+ )}
+
+ {/* Twitter Meta Tags */}
+
+
+
+
+ {/* {title ? : }
+ {description ? (
+
+ ) : (
+
+ )} */}
+ {image ? (
+
+ ) : (
+
+ )}
+
+ {/* Google / Search Engine Tags */}
+ {title ? : }
+ {description ? (
+
+ ) : (
+
+ )}
+ {image ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+}
diff --git a/src/pages/guides/android-wallet.mdx b/src/pages/guides/android-wallet.mdx
new file mode 100644
index 00000000000..74a836bc5ee
--- /dev/null
+++ b/src/pages/guides/android-wallet.mdx
@@ -0,0 +1,1091 @@
+---
+title: Create an Ethereum Web3 wallet in Android
+image: 'img/guides/guides-banners/android-wallet.png'
+description: Empower your Android app with a Ethereum Web3 wallet using the Web3Auth PnP SDK.
+type: guide
+tags: [embedded wallets, android, evm, kotlin, secp256k1, web3auth]
+date: May 27, 2024
+author: Web3Auth Team
+---
+
+import SEO from '@site/src/components/SEO'
+import TabItem from '@theme/TabItem'
+import Tabs from '@theme/Tabs'
+import WalletPreview from '@site/static/img/guides/android-wallet-preview.png'
+
+
+
+In this guide, we'll talk about how we can use Web3Auth to build your Ethereum Web3 wallet in Android. The wallet will only support the Ethereum ecosystem, but functionality can be extended with any blockchain ecosystem.
+
+As an overview, the app is quite simple, with functionality to log in, display user details, and perform blockchain interactions. The signing of the blockchain transactions is done through the Web3Auth embedded wallet. You can check out the infrastructure docs, ["Web3Auth Wallet Management Infrastructure"](/docs/infrastructure) for a high-level overview of the Web3Auth architecture and implementation. For those who want to skip straight to the code, you can find it on [GitHub](https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-playground).
+
+Here are a few screenshots of the application.
+
+
+
+## How to set up Web3Auth Dashboard
+
+If you haven't already, sign up on the Web3Auth platform. It is free and gives you access to the Web3Auth's base plan. After the basic setup, explore other features and functionalities offered by the Web3Auth Dashboard. It includes custom verifiers, whitelabeling, analytics, and more. Head to [Web3Auth's documentation](/docs/dashboard) page for detailed instructions on setting up the Web3Auth Dashboard.
+
+## Integrating Web3Auth in Android
+
+Once, you have set up the Web3Auth Dashboard, and created a new project, it's time to integrate Web3Auth in your Android application. For the implementation, we'll use the ["web3auth-android-sdk"](https://github.com/Web3Auth/web3auth-android-sdk) SDK. This SDK facilitates integration with Web3Auth. This way you can easily manage an embedded wallet in your Android application.
+
+### Installation
+
+To install the web3auth-android-sdk SDK,in your module-level `build.gradle` or `settings.gradle` file, add JitPack repository.
+
+```groovy
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ // focus-next-line
+ maven { url "https://jitpack.io" } // <-- Add this line
+ }
+}
+```
+
+Once, you have added the JitPack repository, then in your app-level `build.gradle` dependencies section, add the `web3auth-android-sdk`.
+
+```groovy
+dependencies {
+ // ...
+ // focus-next-line
+ implementation 'com.github.web3auth:web3auth-android-sdk:7.4.0'
+}
+```
+
+For the prerequisites, and other mandatory configuration of the SDK, please head to our [installation documentation](/docs/sdk/mobile/pnp/android/install).
+
+### Initialization
+
+After successfully installing the package, the next step is to initialize Web3Auth in your Android app. This sets up the necessary configurations using Client Id and prepares Web3Auth. [Learn more about Web3Auth Initialization](/docs/sdk/mobile/pnp/android/initialize).
+
+Since we are using the MVVM architecture for the wallet, along with dependency injection, we have defined a `Web3AuthHelper` to interact with a `Web3Auth` instance, which also makes it easier to write mocks for unit testing.
+
+```kotlin
+class Web3AuthHelperImpl(
+ private val web3Auth: Web3Auth
+): Web3AuthHelper {
+
+ // Performs the login to authenticate the user with Web3Auth netowrk.
+ override suspend fun login(loginParams: LoginParams): CompletableFuture {
+ return web3Auth.login(loginParams)
+ }
+
+ // Logout of the current active session.
+ override suspend fun logOut(): CompletableFuture {
+ return web3Auth.logout()
+ }
+
+ // Returns the Ethereum compatible private key.
+ override fun getPrivateKey(): String {
+ return web3Auth.getPrivkey()
+ }
+
+ // Returns the user information such as name, email, profile image, and etc.
+ // For more details, please checkout UserInfo.
+ override fun getUserInfo(): UserInfo {
+ try {
+ return web3Auth.getUserInfo()!!
+ } catch (e: Exception) {
+ throw e
+ }
+ }
+
+ override suspend fun initialize(): CompletableFuture {
+ return web3Auth.initialize()
+ }
+
+ override suspend fun setResultUrl(uri: Uri?) {
+ return web3Auth.setResultUrl(uri)
+ }
+
+ override suspend fun isUserAuthenticated(): Boolean {
+ return web3Auth.getPrivkey().isNotEmpty()
+ }
+}
+```
+
+Once we have the created `Web3AuthHelper`, the next is to initialize the `Web3Auth` instance in the Koin module and make it a singleton component.
+
+```kotlin
+val appModule = module {
+ // focus-start
+ single {
+ getWeb3AuthHelper(get())
+ }
+ // focus-end
+
+ // Additional code
+
+ viewModel { MainViewModel(get()) }
+}
+
+private fun getWeb3AuthHelper(context: Context): Web3AuthHelper {
+ // focus-start
+ val web3Auth = Web3Auth(
+ Web3AuthOptions(
+ clientId = "WEB3AUTH_CLIENT_ID",
+ context = context,
+ network = Network.SAPPHIRE_MAINNET,
+ redirectUrl = Uri.parse("w3a://com.example.android_playground/auth")
+ )
+ )
+ // focus-end
+
+ return Web3AuthHelperImpl(web3Auth)
+}
+```
+
+### Session Management
+
+To check whether the user is authenticated, you can use the `getPrivateKey` or `getEd25519PrivKey` method. For a user already authenticated, the result would be a non-empty `String`. You can navigate to different views based on the result. If the user is already authenticated, we'll generate and prepare the `Credentials`, important to interact with the blockchain. Along with that, we'll retrieve user info, and navigate them to `HomeScreen`. In case of no active session, we'll navigate to `LoginScreen` to authenticate again. [Learn more about Web3Auth session management](/docs/features/session-management).
+
+Since we are using the MVVM architecture, we'll create a `ViewModel` class to encapsulate the business logic for Web3Auth and Ethereum chain interaction.
+
+```kotlin
+class MainViewModel(private val web3AuthHelper: Web3AuthHelper) : ViewModel() {
+
+ // _isLoggedIn can be used in the UI to know whether the user is logged.
+ private val _isLoggedIn: MutableStateFlow = MutableStateFlow(false)
+ val isLoggedIn: StateFlow = _isLoggedIn
+
+ lateinit var credentials: Credentials
+ lateinit var userInfo: UserInfo
+
+ // Additional code
+
+ // Function to retrieve private key.
+ private fun privateKey(): String {
+ // focus-next-line
+ return web3AuthHelper.getPrivateKey()
+ }
+
+ // prepareCredentials uses the private key to create Ethereum credentials which
+ // can be used to retrieve the EOA address, and sign the transactions.
+ private fun prepareCredentials() {
+ // focus-next-line
+ credentials = Credentials.create(privateKey())
+ }
+
+ private fun prepareUserInfo() {
+ // focus-next-line
+ userInfo = web3AuthHelper.getUserInfo()
+ }
+
+ // Additional code
+
+ fun initialise() {
+ viewModelScope.launch {
+ web3AuthHelper.initialize().await()
+ isUserLoggedIn()
+ }
+ }
+
+ private fun isUserLoggedIn() {
+ viewModelScope.launch {
+ try {
+ // focus-start
+ val isLoggedIn = web3AuthHelper.isUserAuthenticated()
+ if (isLoggedIn) {
+ prepareCredentials()
+ prepareUserInfo()
+ }
+ _isLoggedIn.emit(isLoggedIn)
+ // focus-end
+ } catch (e: Exception) {
+ _isLoggedIn.emit(false)
+ }
+ }
+ }
+}
+```
+
+### Authentication
+
+If the user is not authenticated, we can utilize the `login` method to authenticate the user. For the Wallet, we will add an Email Passwordless login. We'll create a helper function, `login` inside `MainViewModel`. The login method is pretty straightforward in Web3Auth and takes `LoginParams` as input. After successfully logging in, we'll generate and prepare the `Credentials`, important to interact with the blockchain. Along with that, we'll retrieve user info, and navigate them to `HomeScreen`.
+
+Learn more about [Web3Auth LoginParams](/docs/sdk/mobile/pnp/android/usage#parameters).
+
+```kotlin
+class MainViewModel(private val web3AuthHelper: Web3AuthHelper) : ViewModel() {
+ // Additional code
+
+ fun login(email: String) {
+ // focus-start
+ val loginParams = LoginParams(
+ loginProvider = Provider.EMAIL_PASSWORDLESS,
+ extraLoginOptions = ExtraLoginOptions(login_hint = email)
+ )
+ // focus-end
+ viewModelScope.launch {
+ try {
+ // focus-next-line
+ web3AuthHelper.login(loginParams = loginParams).await()
+ // Functions from Session Management code snippets
+ prepareCredentials()
+ prepareUserInfo()
+
+ // Emit true to navigate to HomeScreen
+ _isLoggedIn.emit(true)
+ } catch (error: Exception) {
+ _isLoggedIn.emit(false)
+ throw error
+ }
+ }
+ }
+}
+```
+
+## Set up Blockchain Providers
+
+Once we have successfully authenticated the user, the next step would be to fetch the user details, retrieve the wallet address, and prepare blockchain providers for interactions. For this guide, we are supporting only the Ethereum ecosystem, but the general idea can be used for any blockchain ecosystem.
+
+Given that the project follows MVVM architecture pattern, we'll want to create a UseCase to interact with the Blockchain. This UseCase will help us easily expand the blockchain support while isolating it from the rest of the application.
+
+For interacting with Ethereum chains, we'll use the [web3j](https://github.com/hyperledger/web3j) SDK.
+
+To install the web3j SDK, in your module-level `build.gradle` or `settings.gradle` file, add `web3j` in your app-level dependencies.
+
+```groovy
+dependencies {
+ // ...
+ // focus-next-line
+ implementation 'org.web3j:core:4.8.7-android'
+}
+```
+
+After successfully installing the SDK, it's time to set up our Ethereum UseCase. First, we'll create a new class, `EthereumUseCase` interface, which will used as a base class for `EthereumUseCaseImpl`. If you wish to support any additional ecosystem, you can create the chain-agnostic UseCase and implement the methods.
+
+If you want to learn, how you can integrate different blockchains with Web3Auth, you can check out our [Connect Blockchain resources](/docs/connect-blockchain/).
+
+```kotlin
+interface EthereumUseCase {
+ suspend fun getBalance(publicKey: String): String
+ suspend fun signMessage(message: String, sender: Credentials): String
+ suspend fun sendETH(amount: String, recipientAddress: String, sender: Credentials): String
+
+ suspend fun getBalanceOf(contractAddress: String, address: String, credentials: Credentials): String
+ suspend fun approve(contractAddress: String, spenderAddress: String, credentials: Credentials): String
+}
+```
+
+Generally, for any blockchain provider, you'll only require the `getBalance`, `sendTransaction`, and `signMessage`. The `getBalance` and `approve` can be used to interact with smart contracts. To interact with smart contracts, we'll be required to generate smart contract function wrappers in Java from Solidity ABI files.
+
+### Smart Contract Wrappers
+
+For generating the wrappers, we'll use the [web3j command line tools](https://docs.web3j.io/4.11.0/command_line_tools/).
+
+To install the web3j cli, you can use the below command. Read more about [web3j cli installation](https://docs.web3j.io/4.11.0/command_line_tools/#installation).
+
+```bash
+curl -L get.web3j.io | sh && source ~/.web3j/source.sh
+```
+
+Once, we have installed the cli, the next step is to create `Token.sol` file, which has the smart contract interface for the ERC-20 token. [Learn more about ERC-20 token standard](https://docs.web3j.io/4.11.0/getting_started/deploy_interact_smart_contracts/#eip-20-ethereum-token-standard-smart-contract).
+
+```sol
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+interface IERC20 {
+ function totalSupply() external view returns (uint256);
+ function balanceOf(address account) external view returns (uint256);
+ function transfer(address recipient, uint256 amount)
+ external
+ returns (bool);
+ function allowance(address owner, address spender)
+ external
+ view
+ returns (uint256);
+ function approve(address spender, uint256 amount) external returns (bool);
+ function transferFrom(address sender, address recipient, uint256 amount)
+ external
+ returns (bool);
+}
+```
+
+After creating the interface for the ERC-20 token, the next step is to compile the solidity file and generate the abi and bin files to generate the wrappers. To compile the solidity file, we'll use the [solc](https://docs.soliditylang.org/en/latest/installing-solidity.html).
+
+To install the solc we'll require the npm or yarn. If you have the npm already installed, you can use the below command to install the solc package globally.
+
+```bash
+npm install -g solc
+```
+
+Once, we have the solc package installed, we'll compile the smart contract. The bin and abi options will generate the abi and bin files. Feel free to choose the output directory of your choice.
+
+```bash
+solc Token.sol --bin --abi --optimize -o /
+```
+
+Once, we have compiled the smart contract, the next step is to use the web3j cli to generat the wrpapers.
+
+```bash
+web3j generate solidity -b /path/to/Tokne.bin -a /path/to/Token..abi -o /path/to/src/main/java -p com.your.organisation.name
+```
+
+Once you run the command, it'll create a wrapper `Token.java` which extends the `Contract`. You can use this class to interact with the smart contracts. Please make sure to compile and regenerate wrappers if you make any changes in the smart contract.
+
+### Ethereum UseCase Implementation
+
+Once we have generated `Token` wrapper, we'll create `EthereumUseCaseImpl` and implement the methods. To create the `Web3j` instance, you'll require the rpcTarget URL. If you are using public RPCs, you can face some network congestion. It's ideal to use paid RPCs for production.
+
+The `getBalance`, and `approve` methods are used to interact with smart contracts in the Ethereum ecosystem. The `getBalance` is used to read the balance from the ERC-20 smart contracts, whereas the `approve` is used to change the approval to zero for the ERC-20. For the `getBalance` and `approve` we'll be using the `Token` wrapper.
+
+```kotlin
+class EthereumUseCaseImpl(
+ private val web3: Web3j
+) : EthereumUseCase {
+ override suspend fun getBalance(publicKey: String): String = withContext(Dispatchers.IO) {
+ try {
+ val balanceResponse = web3.ethGetBalance(publicKey, DefaultBlockParameterName.LATEST).send()
+ val ethBalance = BigDecimal.valueOf(balanceResponse.balance.toDouble()).divide(BigDecimal.TEN.pow(18))
+ DecimalFormat("#,##0.00000").format(ethBalance)
+ } catch (e: Exception) {
+ throw e
+ }
+ }
+
+ override suspend fun signMessage(message: String, sender: Credentials): String {
+ try {
+ val signature = Sign.signPrefixedMessage(message.toByteArray(), sender.ecKeyPair)
+ val r = Numeric.toHexString(signature.r)
+ val s = Numeric.toHexString(signature.s).substring(2)
+ val v = Numeric.toHexString(signature.v).substring(2)
+
+ return StringBuilder(r).append(s).append(v).toString()
+ } catch (e: Exception) {
+ throw e
+ }
+ }
+
+ override suspend fun sendETH(amount: String, recipientAddress: String, sender: Credentials): String {
+ try {
+
+
+ val ethGetTransactionCount: EthGetTransactionCount =
+ web3.ethGetTransactionCount(sender.address, DefaultBlockParameterName.LATEST)
+ .sendAsync().get()
+ val nonce: BigInteger = ethGetTransactionCount.transactionCount
+ val value: BigInteger = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger()
+ val gasLimit: BigInteger = BigInteger.valueOf(21000)
+ val gasPrice = web3.ethGasPrice().sendAsync().get()
+
+
+ val rawTransaction: RawTransaction = RawTransaction.createEtherTransaction(
+ nonce,
+ gasPrice.gasPrice,
+ gasLimit,
+ recipientAddress,
+ value
+ )
+
+ val signedMessage: ByteArray = TransactionEncoder.signMessage(rawTransaction, sender)
+ val hexValue: String = Numeric.toHexString(signedMessage)
+ val ethSendTransaction: EthSendTransaction =
+ web3.ethSendRawTransaction(hexValue).sendAsync().get()
+
+ if (ethSendTransaction.error != null) {
+ throw Exception(ethSendTransaction.error.message)
+ } else {
+ return ethSendTransaction.transactionHash
+ }
+ } catch (e: Exception) {
+ throw e
+ }
+ }
+
+ override suspend fun getBalanceOf(contractAddress: String, address: String, credentials: Credentials): String = withContext(Dispatchers.IO) {
+ val token = Token.load(contractAddress, web3, credentials, DefaultGasProvider())
+ val balanceResponse = token.balanceOf(address).sendAsync().get()
+ BigDecimal.valueOf(balanceResponse.toDouble()).divide(BigDecimal.TEN.pow(18)).toString()
+ }
+
+ override suspend fun approve(
+ contractAddress: String,
+ spenderAddress: String,
+ credentials: Credentials
+ ): String = withContext(Dispatchers.IO) {
+ val token = Token.load(contractAddress, web3, credentials, DefaultGasProvider())
+ val hash = token.approve(spenderAddress, BigInteger.ZERO).sendAsync().get()
+ hash.transactionHash
+ }
+}
+```
+
+Once we have the created `EthereumUseCaseImpl`, next is to initialize the `EthereumUseCaseImpl` instance in the Koin module.
+
+```kotlin
+val appModule = module {
+ // Additional code
+
+ // focus-next-line
+ factory { EthereumUseCaseImpl(Web3j.build(HttpService(chainConfigList.first().rpcTarget))) }
+
+ // Additonal code
+```
+
+## Set up Supported Chains
+
+After having our blockchain UseCase in place, the next step on the list is to define the supported chains. To keep things simple, we'll simply create a new file `ChainConfigList` with an array of ChainConfig to define the supported chains.
+
+For the guide, we have added the support for Ethereum Sepolia, and Arbitrum Sepolia. If you wish to support more chains in your wallet, you can simply add the config with the required details in the list below. Along with that, you can also add the desired chain using the add custom chain feature in the app.
+
+```kotlin
+var chainConfigList = arrayOf(
+ ChainConfig(
+ chainNamespace = ChainNamespace.EIP155,
+ decimals = 18,
+ blockExplorerUrl = "https://sepolia.etherscan.io/",
+ chainId = "11155111",
+ displayName = "Ethereum Sepolia",
+ rpcTarget = "https://1rpc.io/sepolia",
+ ticker = "ETH",
+ tickerName = "Ethereum"
+ ),
+ ChainConfig(
+ chainNamespace = ChainNamespace.EIP155,
+ decimals = 18,
+ blockExplorerUrl = "https://sepolia.etherscan.io/",
+ chainId = "421614",
+ displayName = "Arbitrum Sepolia",
+ rpcTarget = "https://endpoints.omniatech.io/v1/arbitrum/sepolia/public",
+ ticker = "ETH",
+ tickerName = "Ethereum"
+ )
+)
+```
+
+## Wallet Implementation
+
+Once, we have set up the EthereumUseCase, and supported chains, it's time to integrate and plug them into the wallet. Since we have already created `MainViewModel` before, we'll add the other features inside it.
+
+This will help us to separate business logic from UI.
+
+### Set up MainViewModel
+
+Once we have set up supported chains, the next on the list is to add more functionality in `MinaViewModel` to help us manage the state & functionality of the wallet. It will help us manage the state of the currently selected chain, fetch balance, sign transactions, and access other functionalities of Web3Auth.
+
+```kotlin
+class MainViewModel(private val web3AuthHelper: Web3AuthHelper) : ViewModel() {
+ // _isLoggedIn can be used in the UI to know whether the user is logged.
+ private val _isLoggedIn: MutableStateFlow = MutableStateFlow(false)
+ val isLoggedIn: StateFlow = _isLoggedIn
+
+ // _isAccountLoaded can be used in the UI to know whether the user's account is loaded.
+ // If it's false, we'll show the loading indictor.
+ private val _isAccountLoaded: MutableStateFlow = MutableStateFlow(false)
+ val isAccountLoaded: StateFlow = _isAccountLoaded
+
+ // _balance holds the user's balance for the selected ChainConfig.
+ private val _balance: MutableStateFlow = MutableStateFlow("0.0")
+ val balance: StateFlow = _balance
+
+
+ // Currently selected ChainConfig by the user. By default, it would be the first ChainConfig
+ // in the list.
+ private val _selectedChain: MutableStateFlow = MutableStateFlow(chainConfigList[0])
+ val selectedChain: StateFlow = _selectedChain
+
+ // Credentials will be used to retrive user's EOA address, and sign the transactions.
+ lateinit var credentials: Credentials
+ lateinit var userInfo: UserInfo
+
+ // EthereumUseCaseImpl to interact with the selected Ethereum ChainConfig.
+ private var ethereumUseCase: EthereumUseCase = EthereumUseCaseImpl(
+ Web3j.build(
+ HttpService(
+ chainConfigList.first().rpcTarget
+ )
+ )
+ )
+
+ // User's Ethereum compatible private key.
+ private fun privateKey(): String {
+ return web3AuthHelper.getPrivateKey()
+ }
+
+ private fun prepareCredentials() {
+ credentials = Credentials.create(privateKey())
+ }
+
+ private fun prepareUserInfo() {
+ userInfo = web3AuthHelper.getUserInfo()
+ }
+
+ fun login(email: String) {
+ // Defined previously
+ }
+
+ fun initialise() {
+ // Defined previously
+ }
+
+ private fun isUserLoggedIn() {
+ // Defined previously
+ }
+
+ // Retrieves user's balance for the currently selected ChainConfig.
+ fun getBalance() {
+ viewModelScope.launch {
+ _isAccountLoaded.emit(false)
+ try {
+ Log.d("Address", credentials.address)
+ _balance.emit(ethereumUseCase.getBalance(credentials.address))
+ _isAccountLoaded.emit(true)
+ } catch (e: Exception) {
+ _isAccountLoaded.emit(false)
+ throw e
+ }
+ }
+ }
+
+ // Logouts out user, and deletes the currently active session.
+ fun logOut() {
+ viewModelScope.launch {
+ try {
+ web3AuthHelper.logOut().await()
+ _isLoggedIn.emit(true)
+ } catch (e: Exception) {
+ _isLoggedIn.emit(false)
+ }
+ }
+ }
+
+ // Signs and broadcast a trasnfer transaction.
+ fun sendTransaction(value: String, recipient: String, onSign: (hash: String?, error: String?) -> Unit) {
+ viewModelScope.launch {
+ try {
+ val hash = ethereumUseCase.sendETH(value, recipient, credentials)
+ onSign(hash, null)
+ } catch (e: Exception) {
+ e.localizedMessage?.let { onSign(null, it) }
+ }
+ }
+ }
+
+ // Signs a personal message.
+ fun signMessage(message: String, onSign: (hash: String?, error: String?) -> Unit) {
+ viewModelScope.launch {
+ try {
+ val signature = ethereumUseCase.signMessage(message, credentials)
+ Log.d("Signature", signature)
+ onSign(signature, null)
+ } catch (e: Exception) {
+ e.localizedMessage?.let { onSign(null, it) }
+ }
+ }
+ }
+
+ // Changes the currently selected ChainConfig.
+ fun changeChainConfig(config: ChainConfig) {
+ _selectedChain.value = config
+ ethereumUseCase = EthereumUseCaseImpl(
+ Web3j.build(
+ HttpService(
+ config.rpcTarget
+ )
+ )
+ )
+ getBalance()
+ }
+
+ // Retreives the ERC-20 token balance using the getBalanceOf method.
+ fun getTokenBalance(contractAddress: String, onSuccess: (balance: String?, error: String?) -> Unit) {
+ viewModelScope.launch {
+ try {
+ val balance = ethereumUseCase.getBalanceOf(contractAddress, credentials.address, credentials)
+ Log.d("Token Balance:",balance)
+ onSuccess(balance, null)
+ } catch (e: Exception) {
+ onSuccess(null, e.localizedMessage)
+ }
+ }
+ }
+
+ // Revokes the approval for the ERC-20 token using the approve function.
+ fun revokeApproval(contractAddress: String, spenderAddress: String, onRevoke: (hash: String?, error: String?) -> Unit) {
+ viewModelScope.launch {
+ try {
+ val hash = ethereumUseCase.approve(contractAddress, spenderAddress, credentials)
+ Log.d("Revoke Hash:", hash)
+ onRevoke(hash, null)
+ } catch (e: Exception) {
+ onRevoke(null, e.localizedMessage)
+ }
+ }
+ }
+
+ fun userInfo(onAvailable: (userInfo: UserInfo?, error: String?) -> Unit) {
+ try {
+ val info = web3AuthHelper.getUserInfo()
+ onAvailable(info, null)
+ } catch (e: Exception) {
+ e.localizedMessage?.let { onAvailable(null, it) }
+ }
+ }
+}
+```
+
+### Set up Home screen
+
+Once, we have our view model ready, we create a new `HomeScreen` to show user details as email address, wallet address, user's balance for selectedChain, and blockchain interaction methods.
+
+To get the user's balance, we'll use `getBalance` method from the `MainViewModel`. The method internally uses `EthereumUseCaseImpl` to retrieve the user's wallet address and fetch the wallet balance for the address. Check out `EthereumUseCaseImpl` implementation for more details.
+
+For the bottom navigation, we have created `TabBarView`, please check TabBarView.kt file for more details on UI implementation.
+
+```kotlin
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun HomeScreen(viewModel: MainViewModel) {
+ val homeTab = TabBarItem(
+ title = "Home",
+ selectedIcon = Icons.Filled.Home,
+ unselectedIcon = Icons.Outlined.Home
+ )
+ val alertsTab = TabBarItem(
+ title = "Sign & Send",
+ selectedIcon = Icons.Filled.Create,
+ unselectedIcon = Icons.Outlined.Create
+ )
+ val settingsTab = TabBarItem(
+ title = "Smart Contracts",
+ selectedIcon = Icons.Filled.Receipt,
+ unselectedIcon = Icons.Outlined.Receipt
+ )
+
+ val tabBarItems = listOf(homeTab, alertsTab, settingsTab)
+
+ val navController = rememberNavController()
+
+ // Show the UI if the account is loaded, otherwise show the
+ // progress indictor.
+ if (viewModel.isAccountLoaded.collectAsState().value) {
+ Scaffold(
+ topBar = {
+ TopAppBar(
+ title = {
+ Text(text = "Android Playground")
+ },
+
+ actions = {
+ Row {
+ // Logs out user
+ IconButton(onClick = { viewModel.logOut() }) {
+ Icon(Icons.Outlined.ExitToApp, contentDescription = "Logout")
+ }
+ }
+ }
+ )
+ },
+ bottomBar = {
+ TabView(tabBarItems = tabBarItems, navController = navController)
+ }
+ ) { innerPadding ->
+ // Different Views which will be shown upon user selection. By default, it'll be AccountView.
+ NavHost(navController = navController, startDestination = "Home", modifier = Modifier.padding(innerPadding)) {
+ composable(homeTab.title) {
+ AccountView(viewModel = viewModel)
+ }
+ composable(alertsTab.title) {
+ TransactionScreen(viewModel = viewModel)
+ }
+ composable(settingsTab.title) {
+ SmartContractsScreen(viewModel = viewModel)
+ }
+ }
+ }
+ } else {
+ // Shows CircularProgressIndicator
+ Box(modifier = Modifier
+ .fillMaxWidth()
+ .fillMaxHeight(), contentAlignment = Alignment.Center) {
+ CircularProgressIndicator()
+ }
+ }
+}
+
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
+@Composable
+fun AccountView(viewModel: MainViewModel) {
+ // Used for ExposedDropdownMenuBox state management
+ var expanded by remember { mutableStateOf(false) }
+
+ // Defines whether to showcase user info dialog. By default,
+ // it's false.
+ val openUserInfoDialog = remember {
+ mutableStateOf(false)
+ }
+
+ var balance = viewModel.balance.collectAsState().value
+ val clipboardManager: ClipboardManager = LocalClipboardManager.current
+ val refreshing by viewModel.isAccountLoaded.collectAsState()
+
+ val pullRefreshState = rememberPullRefreshState(!refreshing, { viewModel.getBalance() })
+
+ // Displays UserInfoDialog when openUserInfoDialog is true.
+ if(openUserInfoDialog.value) {
+ UserInfoDialog(onDismissRequest = {
+ openUserInfoDialog.value = false
+ }, userInfo = viewModel.userInfo.toString())
+ }
+
+ Box(Modifier.pullRefresh(pullRefreshState)) {
+ LazyColumn(
+ modifier = Modifier
+ .padding(PaddingValues(horizontal = 16.dp, vertical = 8.dp))
+ ) {
+ item {
+ // Additional UI
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ ) {
+ // Dropdown for chain selection
+ ExposedDropdownMenuBox(
+ expanded = expanded,
+ onExpandedChange = {
+ expanded = !expanded
+ }
+ ) {
+ OutlinedTextField(
+ value = viewModel.selectedChain.collectAsState().value.displayName!!,
+ onValueChange = {},
+ readOnly = true,
+ trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
+ modifier = Modifier
+ .menuAnchor()
+ .fillMaxWidth()
+ )
+
+ ExposedDropdownMenu(
+ expanded = expanded,
+ onDismissRequest = { expanded = false }
+ ) {
+ chainConfigList.forEach { item ->
+ DropdownMenuItem(
+ text = { Text(text = item.displayName!!) },
+ onClick = {
+ expanded = false
+ viewModel.changeChainConfig(item)
+ }
+ )
+ }
+ }
+ }
+ }
+ // Additonal UI code
+
+ // Display User info
+ Row {
+ Box(
+ modifier = Modifier
+ .height(120.dp)
+ .width(120.dp)
+ .background(color = MaterialTheme.colorScheme.primary),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(
+ text = viewModel.userInfo.name.first().uppercase(),
+ style = Typography.headlineLarge.copy(color = Color.White)
+ )
+ }
+
+ Box(modifier = Modifier.width(16.dp))
+ Column {
+ Text(text = viewModel.userInfo.name, style = Typography.titleLarge)
+ Box(modifier = Modifier.height(12.dp))
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ // Displays user's EOA address
+ Text(
+ text = viewModel.credentials.address.addressAbbreviation(),
+ style = Typography.titleMedium
+ )
+ IconButton(onClick = {
+ clipboardManager.setText(AnnotatedString(viewModel.credentials.address))
+ }) {
+ Icon(Icons.Outlined.ContentCopy, contentDescription = "Copy")
+ }
+ }
+ }
+ }
+ // Additional UI code
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceBetween
+ ) {
+ Column {
+ // Displays user's wallet balance for selected ChainConfig.
+ Text(text = "Wallet Balance", style = Typography.titleMedium)
+ Spacer(modifier = Modifier.height(8.dp))
+ Text(text = balance, style = Typography.headlineSmall)
+ }
+ Column(horizontalAlignment = Alignment.End) {
+ // Displays the chainId for selected ChainConfig
+ Text(text = "Chain id", style = Typography.titleMedium)
+ Spacer(modifier = Modifier.height(8.dp))
+ Text(text = viewModel.selectedChain.collectAsState().value.chainId, style = Typography.headlineSmall)
+ }
+ }
+ }
+ }
+
+ // Adds additional pull to refresh functionality
+ PullRefreshIndicator(!refreshing, pullRefreshState, Modifier.align(Alignment.TopCenter))
+ }
+}
+```
+
+### Chain Interactions
+
+Once we have set up `HomeScreen` and `AccountView`, the next step is to set up chain interactions for signing messages, signing transactions, reading from contracts, and writing on contracts. For signing messages and transaction, we'll create a new `TransactionScreen` widget and utilize `signMessage` and `sendTransaction` from `MainViewModel` for the respective functionality.
+
+```kotlin
+@OptIn(ExperimentalPagerApi::class)
+@Composable
+fun TransactionScreen(viewModel: MainViewModel) {
+ val pagerState = rememberPagerState( 0)
+ val tabItems = listOf(
+ "Sign Message",
+ "Send Transaction",
+ )
+
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
+ Spacer(modifier = Modifier.height(16.dp))
+ Text(
+ text = "Signing/Transaction", style = Typography.headlineLarge,
+ textAlign = TextAlign.Center
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ Tabs(pagerState = pagerState, tabItems)
+ Spacer(modifier = Modifier.height(16.dp))
+ TabsContent(pagerState = pagerState, viewModel)
+ }
+}
+
+@OptIn(ExperimentalPagerApi::class)
+@Composable
+fun TabsContent(pagerState: PagerState, viewModel: MainViewModel) {
+
+ HorizontalPager(state = pagerState, count = 2) {
+ page ->
+ when (page) {
+ 0 -> SigningView(viewModel = viewModel)
+ 1 -> TransactionView(viewModel = viewModel)
+ }
+ }
+}
+
+@Composable
+fun SigningView(viewModel: MainViewModel) {
+ // Default signing message
+ var messageText by remember { mutableStateOf("Welcome to Web3Auth") }
+ val openAlertDialog = remember { mutableStateOf(false) }
+ var dialogText by remember { mutableStateOf("") }
+
+ when {
+ openAlertDialog.value -> MinimalDialog(dialogText) {
+ openAlertDialog.value = false
+ }
+ }
+
+ Column(modifier = Modifier
+ .fillMaxSize()
+ .padding(horizontal = 16.dp)) {
+ // Additional UI code
+ Button(onClick = {
+ // focus-start
+ // Signs the message and show the signature
+ viewModel.signMessage(messageText, onSign = {
+ signature, error ->
+ if(signature != null) {
+ dialogText = "Signature:\n$signature"
+ openAlertDialog.value = true
+ } else {
+ dialogText = "Error:\n$error"
+ openAlertDialog.value = true
+
+ }
+ })
+ // focus-end
+ }, shape = RoundedCornerShape(4.dp), modifier = Modifier.fillMaxWidth()) {
+ Text("Sign Message")
+ }
+
+ }
+}
+
+
+@Composable
+fun TransactionView(viewModel: MainViewModel) {
+ var valueText by remember { mutableStateOf("") }
+ var addressText by remember { mutableStateOf("") }
+ val openAlertDialog = remember { mutableStateOf(false) }
+ var dialogText by remember { mutableStateOf("") }
+
+ when {
+ openAlertDialog.value -> MinimalDialog(dialogText) {
+ openAlertDialog.value = false
+ }
+ }
+
+ Column(modifier = Modifier
+ .fillMaxSize()
+ .padding(horizontal = 16.dp)) {
+ // Additional UI code
+ Button(onClick = {
+ // focus-start
+ // Performs transfer transaction and displays the hash for the transaction
+ viewModel.sendTransaction(valueText, addressText, onSign = {
+ hash, error ->
+ if(hash != null) {
+ dialogText = "Hash:\n$hash"
+ openAlertDialog.value = true
+ } else {
+ dialogText = "Error:\n$error"
+ openAlertDialog.value = true
+ }
+ })
+ // focus-end
+ }, shape = RoundedCornerShape(4.dp), modifier = Modifier.fillMaxWidth()) {
+ Text("Send transaction")
+ }
+ }
+}
+```
+
+Once we have set up `TransactionScreen`, the next is to create `SmartContractsScreen` for fetching ERC-20 token balance, and revoking approval. We'll utilize the `getTokenBalance` and `revokeApproval` methods from `MainViewModel` for the above functionality.
+
+```kotlin
+@OptIn(ExperimentalPagerApi::class)
+@Composable
+fun SmartContractsScreen(viewModel: MainViewModel) {
+ val pagerState = rememberPagerState( 0)
+ val tabItems = listOf(
+ "Read from Contract",
+ "Write from Contract",
+ )
+
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
+ Spacer(modifier = Modifier.height(16.dp))
+ Text(
+ text = "Smart Contract Interactions", style = Typography.headlineLarge,
+ textAlign = TextAlign.Center
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ Tabs(pagerState = pagerState, tabItems)
+ Spacer(modifier = Modifier.height(16.dp))
+ ContractTabsContent(pagerState = pagerState, viewModel)
+ }
+}
+
+
+@Composable
+@OptIn(ExperimentalPagerApi::class)
+fun ContractTabsContent(pagerState: PagerState, viewModel: MainViewModel) {
+ HorizontalPager(state = pagerState, count = 2) {
+ page ->
+ when (page) {
+ 0 -> ReadContractView(viewModel = viewModel)
+ 1 -> WriteContractView(viewModel = viewModel)
+ }
+ }
+}
+
+@Composable
+fun ReadContractView(viewModel: MainViewModel) {
+ var contractAddressText by remember { mutableStateOf("0x10279e6333f9d0EE103F4715b8aaEA75BE61464C") }
+ val openAlertDialog = remember { mutableStateOf(false) }
+ var dialogText by remember { mutableStateOf("") }
+
+ when {
+ openAlertDialog.value -> MinimalDialog(dialogText) {
+ openAlertDialog.value = false
+ }
+ }
+
+ Column(modifier = Modifier
+ .fillMaxSize()
+ .padding(horizontal = 16.dp)) {
+ // Additional code
+ Button(onClick = {
+ // focus-start
+ // Retrieves ERC-20 token balance for the user's EOA address
+ viewModel.getTokenBalance(contractAddressText, onSuccess = {
+ balance, error ->
+ if(balance != null) {
+ dialogText = "Balance:\n$balance"
+ openAlertDialog.value = true
+ } else {
+ dialogText = "Error:\n$error"
+ openAlertDialog.value = true
+ }
+ })
+ // focus-end
+ }, shape = RoundedCornerShape(4.dp), modifier = Modifier.fillMaxWidth()) {
+ Text("Fetch Balance")
+ }
+ }
+}
+
+@Composable
+fun WriteContractView(viewModel: MainViewModel) {
+ var contractAddressText by remember { mutableStateOf("0x10279e6333f9d0EE103F4715b8aaEA75BE61464C") }
+ var spenderAddressText by remember { mutableStateOf("") }
+ val openAlertDialog = remember { mutableStateOf(false) }
+ var dialogText by remember { mutableStateOf("") }
+
+ when {
+ openAlertDialog.value -> MinimalDialog(dialogText) {
+ openAlertDialog.value = false
+ }
+ }
+
+ Column(modifier = Modifier
+ .fillMaxSize()
+ .padding(horizontal = 16.dp)) {
+ // Additional code
+ Button(onClick = {
+ // focus-start
+ // Revokes the approval of ERC-20 token for respective spenderAddress.
+ viewModel.revokeApproval(contractAddressText, spenderAddressText, onRevoke = {
+ hash, error ->
+ if(hash != null) {
+ dialogText = "Hash:\n$hash"
+ openAlertDialog.value = true
+ } else {
+ dialogText = "Error:\n$error"
+ openAlertDialog.value = true
+ }
+ })
+ // focus-end
+ }, shape = RoundedCornerShape(4.dp), modifier = Modifier.fillMaxWidth()) {
+ Text("Revoke Approval")
+ }
+
+ }
+}
+```
+
+## Conclusion
+
+Voila, you have build a Ethereum Web3 wallet. This guide only gives you an overview of how to create your wallet with Ethereum ecosystem support. The general idea of the guide can be used for any of the blockchain ecosystem.
+
+If you are interested in learning more about Web3Auth, please checkout our [documentation for Android](/docs/sdk/mobile/pnp/android). You can find the code used for the guide on our [examples repo](https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-playground).
diff --git a/src/pages/guides/erc20-paymaster.mdx b/src/pages/guides/erc20-paymaster.mdx
new file mode 100644
index 00000000000..9c45ac1a35c
--- /dev/null
+++ b/src/pages/guides/erc20-paymaster.mdx
@@ -0,0 +1,231 @@
+---
+title: Send your first transaction with ERC-20 Paymaster
+image: 'img/guides/guides-banners/erc20-paymaster.png'
+description: Learn how to use ERC-20 paymaster with Web3Auth Native Account Abstraction.
+type: guide
+tags: [embedded wallets, account abstraction, web, paymaster, erc4337, web3auth]
+date: October 29, 2024
+author: Web3Auth Team
+---
+
+import SEO from '@site/src/components/SEO'
+import TabItem from '@theme/TabItem'
+import Tabs from '@theme/Tabs'
+
+
+
+A paymaster is a vital component in the ERC-4337 standard, responsible for covering transaction costs on behalf of the user. There are various types of paymasters, such as gasless paymasters, ERC-20 paymasters, and more.
+
+In this guide, we'll talk about how you can use the Pimlico's ERC-20 Paymaster with Web3Auth Account Abstraction Provider to allow your users to pay for their transactions using ERC-20 tokens.
+
+If you are looking to use sponsored paymaster, you can refer to the [sponsored paymaster guide](/docs/guides/sending-gasless-transaction).
+
+## Prerequisites
+
+- Pimlico Account: Since we'll be using the Pimlico paymaster, you'll need to have an API key from Pimlico. You can get a free API key from [Pimlico Dashboard](https://dashboard.pimlico.io/).
+- Web3Auth Dashboard: If you haven't already, sign up on the Web3Auth platform. It is free and gives you access to the Web3Auth's base plan. Head to Web3Auth's documentation page for detailed [instructions on setting up the Web3Auth Dashboard](/docs/dashboard).
+- Web3Auth PnP Web SDK: This guide assumes that you already know how to integrate the PnP Web SDK in your project. If not, you can learn how to [integrate Web3Auth in your Web app](/docs/sdk/web/react/).
+
+## Integrate AccountAbstractionProvider
+
+Once, you have set up the Web3Auth Dashboard, and created a new project, it's time to integrate Web3Auth Account Abstraction Provider in your Web application. For the implementation, we'll use the [@web3auth/account-abstraction-provider](https://www.npmjs.com/package/@web3auth/account-abstraction-provider). The provider simplifies the entire process by managing the complex logic behind configuring the account abstraction provider, bundler, and preparing user operations.
+
+If you are already using the Web3Auth Pnp SDK in your project, you just need to configure the AccountAbstractionProvider with the paymaster details, and pass it to the Web3Auth instance. No other changes are required.
+
+### Installation
+
+```bash
+npm install --save @web3auth/account-abstraction-provider
+```
+
+### Configure ERC-20 Paymaster
+
+The `AccountAbstractionProvider` requires specific configurations to function correctly. One key configuration is the paymaster. Web3Auth supports custom paymaster configurations, allowing you to deploy your own paymaster and integrate it with the provider.
+
+You can choose from a variety of paymaster services available in the ecosystem. In this guide, we'll be configuring the Pimlico's ERC-20 Paymaster. However, it's important to note that paymaster support is not limited to the Pimlico, giving you the flexibility to integrate any compatible paymaster service that suits your requirements.
+
+To configure the ERC-20 Paymaster, you need to pass the `token` in the `paymasterContext` which allows you to specify the ERC-20 token that will be used to pay for the transaction. For this guide, we'll use the USDC token. [Find the USDC token address for your desired network](https://developers.circle.com/stablecoins/usdc-on-test-networks).
+
+For the simplicity, we have only use `SafeSmartAccount`, but you choose your favorite smart account provider from the available ones. [Learn how to configure the smart account](/docs/sdk/web/react/advanced/smart-accounts).
+
+```ts
+// focus-start
+import {
+ AccountAbstractionProvider,
+ SafeSmartAccount,
+} from '@web3auth/account-abstraction-provider'
+// focus-end
+
+const chainConfig = {
+ chainNamespace: CHAIN_NAMESPACES.EIP155,
+ chainId: '0xaa36a7',
+ rpcTarget: 'https://rpc.sepolia.org',
+ displayName: 'Ethereum Sepolia Testnet',
+ blockExplorerUrl: 'https://sepolia.etherscan.io',
+ ticker: 'ETH',
+ tickerName: 'Ethereum',
+ logo: 'https://cryptologos.cc/logos/ethereum-eth-logo.png',
+}
+
+// focus-start
+const accountAbstractionProvider = new AccountAbstractionProvider({
+ config: {
+ chainConfig,
+ bundlerConfig: {
+ // Get the pimlico API Key from dashboard.pimlico.io
+ url: `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoAPIKey}`,
+ paymasterContext: {
+ // USDC address on Ethereum Sepolia
+ token: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
+ },
+ },
+ smartAccountInit: new SafeSmartAccount(),
+ paymasterConfig: {
+ // Get the pimlico API Key from dashboard.pimlico.io
+ url: `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoAPIKey}`,
+ },
+ },
+})
+// focus-end
+```
+
+## Configure Web3Auth
+
+Once you have configured your `AccountAbstractionProvider`, you can now plug it in your Web3Auth Modal/No Modal instance. If you are using the external wallets like MetaMask, Coinbase, etc, you can define whether you want to use the AccountAbstractionProvider, or EthereumPrivateKeyProvider by setting the `useAAWithExternalWallet` in `IWeb3AuthCoreOptions`.
+
+If you are setting `useAAWithExternalWallet` to `true`, it'll create a new Smart Account for your user, where the signer/creator of the Smart Account would be the external wallet.
+
+If you are setting `useAAWithExternalWallet` to `false`, it'll skip creating a new Smart Account, and directly use the external wallet to sign the transactions.
+
+
+
+
+
+```ts
+import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
+import { Web3Auth } from "@web3auth/modal";
+
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ // Use the chain config we declared earlier
+ config: { chainConfig },
+});
+
+const web3auth = new Web3Auth({
+ clientId: "YOUR_WEB3AUTH_CLIENT_ID",
+ web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
+ privateKeyProvider,
+ // Use the account abstraction provider we configured earlier
+ accountAbstractionProvider
+ // This will allow you to use EthereumPrivateKeyProvider for
+ // external wallets, while use the AccountAbstractionProvider
+ // for Web3Auth embedded wallets.
+ useAAWithExternalWallet: false,
+});
+```
+
+
+
+
+
+```ts
+import { Web3AuthNoModal } from "@web3auth/no-modal";
+import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
+import { AuthAdapter } from "@web3auth/auth-adapter";
+
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ config: { chainConfig },
+});
+
+const web3auth = new Web3AuthNoModal({
+ clientId: "YOUR_WEB3AUTH_CLIENT_ID",
+ web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
+ privateKeyProvider,
+ // Use the account abstraction provider we configured earlier
+ accountAbstractionProvider
+ // This will allow you to use EthereumPrivateKeyProvider for
+ // external wallets, while use the AccountAbstractionProvider
+ // for Web3Auth embedded wallets.
+ useAAWithExternalWallet: false,
+});
+
+const authadapter = new AuthAdapter();
+web3auth.configureAdapter(authadapter);
+```
+
+
+
+
+## Send a transaction
+
+To submit the transaction using ERC-20 paymaster, we'll require to first need to approve ERC-20 token to be used by the paymaster. Ideally, we should first check the token allowance, and only provide approve allowance to be used by the paymaster.
+
+To modify the token allowance, you'll need to perform a write operation on the ERC-20 contract. In the example below, we're using Pimlico, but be sure to update the paymaster and ERC-20 token addresses according to your specific case.
+
+Since, we want to perform the approval transaction, and send transaction in a single call, we'll use batch transaction feature of the `AccountAbstractionProvider`. Performing a batch transaction differs slightly from the normal flow.
+
+To execute a batch transaction, you'll need to use the `BundlerClient` generated by the `AccountAbstractionProvider`. The Web3Auth instance provider can't be used for this, as it's a proxy provider designed to ensure compatibility with your preferred signer package for basic operations.
+
+Please make sure you have enough USDC balance in the wallet to pay the transaction fees. [Request faucet for USDC tokens](https://faucet.circle.com/).
+
+```ts
+// Use the same accountAbstractionProvider we created earlier.
+const bundlerClient = accountAbstractionProvider.bundlerClient!
+const smartAccount = accountAbstractionProvider.smartAccount!
+
+// Pimlico's ERC-20 Paymaster address
+const pimlicoPaymasterAddress = '0x0000000000000039cd5e8aE05257CE51C473ddd1'
+
+// USDC address on Ethereum Sepolia
+const usdcAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'
+
+// 0.00001 ETH in WEI format
+const amount = 10000000000000n
+
+// 10 USDC in WEI format. Since USDC has 6 decimals, 10 * 10^6
+const approvalAmount = 10000000n
+
+const userOpHash = await bundlerClient.sendUserOperation({
+ account: smartAccount,
+ calls: [
+ // Approve USDC on Sepolia chain for Pimlico's ERC 20 Paymaster
+ {
+ to: usdcAddress,
+ abi: parseAbi(['function approve(address,uint)']),
+ functionName: 'approve',
+ args: [pimlicoPaymasterAddress, approvalAmount],
+ },
+ {
+ to: 'DESTINATION_ADDRESS',
+ value: amount,
+ data: '0x',
+ },
+ {
+ to: 'DESTINATION_ADDRESS',
+ value: amount,
+ data: '0x',
+ },
+ ],
+})
+
+// Retrieve user operation receipt
+const receipt = await bundlerClient.waitForUserOperationReceipt({
+ hash: userOpHash,
+})
+
+const transactionHash = receipt.receipt.transactionHash
+```
+
+## Conclusion
+
+Voila, you have successfully sent your first transaction using the Pimlico's ERC-20 paymaster with Web3Auth Account Abstraction Provider. To learn more about advance features of the Account Abstraction Provider like performing batch transactions, using sponsored paymaster you can refer to the [Account Abstraction Provider](/docs/sdk/web/react) documentation.
diff --git a/src/pages/guides/flutter-wallet.mdx b/src/pages/guides/flutter-wallet.mdx
new file mode 100644
index 00000000000..97a3bb4514d
--- /dev/null
+++ b/src/pages/guides/flutter-wallet.mdx
@@ -0,0 +1,925 @@
+---
+title: Create a Chain Agnostic Web3 wallet in Flutter
+image: 'img/guides/guides-banners/flutter-wallet.png'
+description: Empower your Flutter app with a Chain Agnostic Web3 wallet using the Web3Auth PnP SDK.
+type: guide
+tags: [embedded wallets, flutter, andriod, ios, evm, solana, web3auth]
+date: April 22, 2024
+author: Web3Auth Team
+---
+
+import SEO from '@site/src/components/SEO'
+import TabItem from '@theme/TabItem'
+import Tabs from '@theme/Tabs'
+import WalletPreview from '@site/static/img/guides/flutter-wallet-preview.png'
+
+
+
+In this guide, we'll talk about how we can use Web3Auth to build your chain-agnostic Web3 wallet in Flutter. The wallet will support the Ethereum and Solana ecosystem.
+
+As an overview, the app is quite simple, with functionality to log in, display user details, and perform blockchain interactions. The signing of the blockchain transactions is done through the Web3Auth embedded wallet. You can check out the infrastructure docs, ["Web3Auth Wallet Management Infrastructure"](/docs/infrastructure) for a high-level overview of the Web3Auth architecture and implementation. For those who want to skip straight to the code, you can find it on [GitHub](https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-playground).
+
+Here are few screenshots of the application.
+
+
+
+## How to set up Web3Auth Dashboard
+
+If you haven't already, sign up on the Web3Auth platform. It is free and gives you access to the Web3Auth's base plan. After the basic setup, explore other features and functionalities offered by the Web3Auth Dashboard. It includes custom verifiers, whitelabeling, analytics, and more. Head to [Web3Auth's documentation](/docs/dashboard) page for detailed instructions on setting up the Web3Auth Dashboard.
+
+## Integrating Web3Auth in Flutter
+
+Once, you have set up the Web3Auth Dashboard, and created a new project, it's time to integrate Web3Auth in your Flutter application. For the implementation, we'll use the "web3auth_flutter package". This package facilitates integration with Web3Auth. This way you can easily manage embedded wallet in your Flutter application.
+
+### Installation
+
+To install the web3auth_flutter package, you have two options. You can either manually add the package in the `pubspec.yaml` file, or you can use the `flutter pub add` command.
+
+
+
+
+Add `web3auth_flutter` using `flutter pub add` command.
+
+```sh
+flutter pub add web3auth_flutter
+```
+
+
+
+
+Add `web3auth_flutter` as a dependency to your `pubspec.yaml`.
+
+```yaml
+dependencies:
+ web3auth_flutter: ^6.1.2
+```
+
+
+
+
+### Initialization
+
+After successfully installing the package, the next step is to initialize Web3Auth in your Flutter app. This sets up the necessary configurations using Client Id and prepares Web3Auth. [Learn more about Web3Auth Initialization](/docs/sdk/mobile/pnp/flutter/initialize).
+
+```dart
+Future main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+
+ // Addditional code
+
+ final Uri redirectUrl;
+ if (Platform.isAndroid) {
+ redirectUrl =
+ Uri.parse('w3aexample://com.example.flutter_solana_example/auth');
+ } else {
+ redirectUrl = Uri.parse('com.web3auth.fluttersolanasample://auth');
+ }
+
+ await Web3AuthFlutter.init(
+ Web3AuthOptions(
+ clientId: "YOUR_WEB3AUTH_CLIENT_ID",
+ network: Network.sapphire_mainnet,
+ redirectUrl: redirectUrl,
+ ),
+ );
+
+ await Web3AuthFlutter.initialize();
+
+ runApp(const MainApp());
+}
+```
+
+### Session Management
+
+To check whether the user is authenticated, you can use the `getPrivateKey` or `getEd25519PrivKey` method. For a user already authenticated, the result would be a non-empty `String`. You can navigate to different views based on the result. If the user is already authenticated, we'll navigate them to `HomeScreen`. In case of no active session, we'll navigate to `LoginScreen` to authenticate again. [Learn more about Web3Auth session management](/docs/features/session-management).
+
+```dart
+class MainApp extends StatefulWidget {
+ const MainApp({super.key});
+
+ @override
+ State createState() => _MainAppState();
+}
+
+class _MainAppState extends State {
+ late final Future privateKeyFuture;
+ @override
+ void initState() {
+ super.initState();
+ privateKeyFuture = Web3AuthFlutter.getEd25519PrivKey();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ home: FutureBuilder(
+ future: privateKeyFuture,
+ builder: (context, snapshot) {
+ if (snapshot.connectionState == ConnectionState.done) {
+ if (snapshot.hasData) {
+ if (snapshot.data!.isNotEmpty) {
+ return const HomeScreen();
+ }
+ }
+ return const LoginScreen();
+ }
+ return const Center(
+ child: CircularProgressIndicator.adaptive(),
+ );
+ },
+ ),
+ );
+ }
+}
+```
+
+### Authentication
+
+If the user is not authenticated, you should utilize the `login` method. For the Wallet, we will add two login options, Google, and Email Passwordless login. In Web3Auth, you can choose between a Single Page Authentication flow or a Regular Web Application flow. For this guide, we'll be using a Single Page Authentication flow. We'll create a helper function, `_login` inside `LoginScreen`. The login method is pretty straightforward in Web3Auth and takes `LoginParams` as input. After successfully logging in, we'll navigate the user to `HomeScreen`.
+
+Learn more about [Web3Auth LoginParams](/docs/sdk/mobile/pnp/flutter/usage#arguments).
+
+```dart
+class _LoginScreenState extends State with WidgetsBindingObserver {
+ // Additional Code
+
+ @override
+ void didChangeAppLifecycleState(final AppLifecycleState state) {
+ // This is important to trigger the user cancellation on Android.
+ if (state == AppLifecycleState.resumed) {
+ Web3AuthFlutter.setCustomTabsClosed();
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ // Login View
+ }
+
+ Future _login(BuildContext context) async {
+ try {
+ // Validate the form, and TextField. In case of invalide
+ // form state, return back.
+ if (!formKey.currentState!.validate()) {
+ return;
+ }
+
+ // It can be used to set the OAuth login options for corresponding
+ // loginProvider. For instance, you'll need to pass user's email address as
+ // login_hint when the Provider is email_passwordless.
+ await Web3AuthFlutter.login(
+ LoginParams(
+ loginProvider: Provider.email_passwordless,
+ mfaLevel: MFALevel.DEFAULT,
+ extraLoginOptions: ExtraLoginOptions(
+ login_hint: emailController.text,
+ ),
+ ),
+ );
+
+ // If login is successful, navigate user to HomeScreen.
+ if (context.mounted) {
+ Navigator.of(context).pushReplacement(
+ MaterialPageRoute(builder: (context) {
+ return const HomeScreen();
+ }),
+ );
+ }
+ } catch (e, _) {
+ if (context.mounted) {
+ showInfoDialog(context, e.toString());
+ }
+ }
+ }
+}
+```
+
+## Set up Blockchain Providers
+
+Once we have successfully authenticated the user, the next step would be to fetch the user details, retrieve wallet address and prepare blockchain providers for interactions. For this guide, we are supporting only Ethereum and Solana ecosystem, but the general idea can be used for any blockchain ecosystem.
+
+Given that the project follows clean architecture and Test-Driven Development (TDD) principles, we'll want to create an abstract layer to interact with the Blockchain providers. This abstraction will help us easily expand the blockchain support while isolate it from the rest of the application.
+
+For interacting ethereum chains, we'll use the [web3dart](https://pub.dev/packages/web3dart) package. Similary for solana, we'll use the [solana](https://pub.dev/packages/solana) package. To install the packages, you have two options. You can either manually add the packages in the `pubspec.yaml` file, or you can use the `flutter pub add` command.
+
+
+
+
+Add `web3dart` and `solana` using `flutter pub add` command.
+
+```sh
+flutter pub add web3dart
+flutter pub add solana
+```
+
+
+
+
+Add `web3dart` and `solana` as a dependency to your `pubspec.yaml`.
+
+```yaml
+dependencies:
+ web3dart: ^2.7.3
+ solana: ^0.30.4
+```
+
+
+
+
+After successfully installing both packages, it's time to set up our Blockchain provider. First, we'll create a new class, `ChainProvider`, which will used as a base class for `EthereumProvider` and `SolanaProvider`. If you wish to support any additional ecosystem, you can extend the `ChainProvider` and implement the methods.
+
+If you want to learn, how you can integrate different blockchain with Web3Auth, you can checkout our [Connect Blockchain resources](/docs/connect-blockchain/).
+
+```dart
+abstract class ChainProvider {
+ Future getBalance(String address);
+ Future sendTransaction(String to, double amount);
+ Future signMessage(String messsage);
+ Future readContract(
+ String address,
+ String function,
+ List params,
+ );
+
+ Future writeContract(
+ String address,
+ String function,
+ List params,
+ );
+}
+```
+
+Generally, for any blockchain provider, you'll only require the `getBalance`, `sendTransaction`, and `signMessage`. The `readContract` and `writeContract` can be used to interact with SmartContract.
+
+### Ethereum Provider
+
+Once we have our base class, we'll create `EthereumProvider` and implement the methods. To create the `Web3Client` instance, you'll require the rpcTarget URL. If you are using public RPCs, you can face some network congestion. It's ideal to use paid RPCs for production.
+
+The `readContract`, and `writeContract` methods are used to interact with smart contracts on Ethereum ecosystem. The `readContract` is used to read the data from the smart contracts, where as the `writeContract` is used to write data on smart contract.
+
+```dart
+class EthereumProvider extends ChainProvider {
+ final Web3Client web3client;
+
+ EthereumProvider({required String rpcTarget})
+ : web3client = Web3Client(
+ rpcTarget,
+ Client(),
+ );
+
+ @override
+ Future getBalance(String address) async {
+ final balance = await web3client.getBalance(
+ EthereumAddress.fromHex(address),
+ );
+
+ // The result we from Web3Client is in wei, the smallest value. To convert
+ // the value to ether, you can divide it with 10^18, where 18 denotes the
+ // decimals for wei.
+ //
+ // For the sample, we'll use a helper function from web3dart package which
+ // has the same implementation.
+ return balance.getValueInUnit(EtherUnit.ether).toStringAsFixed(4);
+ }
+
+ @override
+ Future sendTransaction(String to, double amount) async {
+ final Credentials credentials = await _prepareCredentials();
+ final amountInWei = amount * pow(10, 18);
+ final Transaction transaction = Transaction(
+ to: EthereumAddress.fromHex(to),
+ value: EtherAmount.fromBigInt(
+ EtherUnit.wei,
+ BigInt.from(amountInWei),
+ ),
+ );
+
+ final hash = await web3client.sendTransaction(
+ credentials,
+ transaction,
+ chainId: null,
+ fetchChainIdFromNetworkId: true,
+ );
+ return hash;
+ }
+
+ @override
+ Future signMessage(String messsage) async {
+ final Credentials credentials = await _prepareCredentials();
+ final signBytes = credentials.signPersonalMessageToUint8List(
+ Uint8List.fromList(messsage.codeUnits),
+ );
+
+ return bytesToHex(signBytes);
+ }
+
+ // Prepares the Credentials used for signing the message,
+ // and transaction on EVM chains. EVM ecosystem uses the
+ // scep2561k curve. You can use the Web3AuthFlutter.getPrivKey
+ // to retrieve the scep2561K compatible private key.
+ Future _prepareCredentials() async {
+ final privateKey = await Web3AuthFlutter.getPrivKey();
+ final Credentials credentials = EthPrivateKey.fromHex(privateKey);
+ return credentials;
+ }
+
+ @override
+ Future readContract(
+ String address,
+ String function,
+ List params,
+ ) async {
+ // For this sample, we are using the ERC 20 Contract. The same can be
+ // used for any of the EVM smart contract.
+ final contract = DeployedContract(
+ ContractAbi.fromJson(erc20Abi, 'Contract'),
+ EthereumAddress.fromHex(address),
+ );
+
+ final readFunction = contract.function(function);
+ final result = await web3client.call(
+ contract: contract,
+ function: readFunction,
+ params: params,
+ );
+
+ return result;
+ }
+
+ @override
+ Future writeContract(String address, String function, List params) async {
+ // For this sample, we are using the ERC 20 Contract. The same can be
+ // used for any of the EVM smart contract.
+ final contract = DeployedContract(
+ ContractAbi.fromJson(erc20Abi, 'Contract'),
+ EthereumAddress.fromHex(address),
+ );
+
+ final writeFunction = contract.function(function);
+ final Credentials credentials = await _prepareCredentials();
+ final result = await web3client.sendTransaction(
+ credentials,
+ Transaction.callContract(
+ contract: contract,
+ function: writeFunction,
+ parameters: params,
+ ),
+ chainId: null,
+ fetchChainIdFromNetworkId: true,
+ );
+
+ return result;
+ }
+}
+```
+
+### Solana Provider
+
+After `EthereumProvider`, it's time to extend `ChainProvider` and create `SolanaProvider`. For `SolanaProvider`, we'll only implement the `getBalance`, `sendTransaction`, and `signMessage`. We'll also add `_generateKeyPair()`, a helper method to create `Ed25519HDKeyPair`. It's used to sign the transactions and messages on Solana ecosystem. Since, Solana uses `ed25519` curve, we can utilize the `Web3AuthFlutter.getEd25519PrivKey`.
+
+```dart
+class SolanaProvider extends ChainProvider {
+ final SolanaClient solanaClient;
+
+ SolanaProvider({required String rpcTarget, required String wss})
+ : solanaClient = SolanaClient(
+ rpcUrl: Uri.parse(rpcTarget),
+ websocketUrl: Uri.parse(wss),
+ );
+
+ @override
+ Future getBalance(String address) async {
+ final balanceResponse = await solanaClient.rpcClient.getBalance(
+ address,
+ );
+
+ /// We are dividing the balance by 10^9, because Solana's
+ /// token decimals is set to be 9;
+ return (balanceResponse.value / pow(10, 9)).toString();
+ }
+
+ @override
+ Future sendTransaction(String to, double amount) async {
+ final Ed25519HDKeyPair ed25519hdKeyPair = await _generateKeyPair();
+
+ /// Converting user input to the lamports, which are smallest value
+ /// in Solana.
+ final num lamports = amount * pow(10, 9);
+ final transactionHash = await solanaClient.transferLamports(
+ source: ed25519hdKeyPair,
+ destination: Ed25519HDPublicKey.fromBase58(to),
+ lamports: lamports.toInt(),
+ );
+
+ return transactionHash;
+ }
+
+ @override
+ Future signMessage(String messsage) async {
+ final Ed25519HDKeyPair ed25519hdKeyPair = await _generateKeyPair();
+
+ final signatrure = await ed25519hdKeyPair.sign(
+ ByteArray.fromString(messsage),
+ );
+ return signatrure.toBase58();
+ }
+
+ Future _generateKeyPair() async {
+ final privateKey = await Web3AuthFlutter.getEd25519PrivKey();
+ return await Ed25519HDKeyPair.fromPrivateKeyBytes(
+ privateKey: privateKey.hexToBytes.take(32).toList(),
+ );
+ }
+
+ @override
+ Future readContract(
+ String address,
+ String function,
+ List params,
+ ) {
+ // TODO: implement readContract
+ throw UnimplementedError();
+ }
+
+ @override
+ Future writeContract(String address, String function, List params) {
+ // TODO: implement writeContract
+ throw UnimplementedError();
+ }
+}
+```
+
+## Set up Supported Chains
+
+After having our blockchain proivders in place, the next step on the list to define the supported chains. To keep things simple, we'll simply a create a new file `chain_configs` with list of Map to define the supported chains.
+
+For the guide, we have added the support for Ethereum Sepolia, Ethereum Mainnet, Polygon Mainnet, Polygon Amoy, and Solana devnet. If you wish to support more chains in your wallet, you can simply add the config with the required details in the list below.
+
+```dart
+import 'package:web3auth_flutter/enums.dart';
+
+final chainConfigs = [
+ {
+ "chainNamespace": ChainNamespace.eip155.name,
+ "chainId": "0xaa36a7",
+ "displayName": "Ethereum Sepolia",
+ "ticker": "ETH",
+ "rpcTarget": "https://rpc.sepolia.org",
+ "blockExplorerUrl": "https://sepolia.etherscan.io",
+ "logo": "https://web3auth.io/images/web3authlog.png",
+ "wss": '',
+ },
+ {
+ "chainNamespace": ChainNamespace.eip155.name,
+ "chainId": "0x1",
+ "displayName": "Ethereum Mainnet",
+ "rpcTarget": "https://rpc.ethereum.org",
+ "blockExplorerUrl": "https://etherscan.io",
+ "ticker": "ETH",
+ "logo": "https://web3auth.io/images/web3authlog.png",
+ "wss": '',
+ },
+ {
+ "chainNamespace": ChainNamespace.eip155.name,
+ "chainId": "0x89",
+ "rpcTarget": "https://polygon-rpc.com",
+ "displayName": "Polygon Mainnet",
+ "blockExplorerUrl": "https://polygonscan.com",
+ "ticker": "POL",
+ "logo": "https://web3auth.io/images/web3authlog.png",
+ "wss": '',
+ },
+ {
+ "chainNamespace": ChainNamespace.eip155.name,
+ "chainId": "80002",
+ "rpcTarget": "https://rpc-amoy.polygon.technology",
+ "displayName": "Polygon Amoy Testnet",
+ "blockExplorerUrl": "https://www.oklink.com/amoy",
+ "ticker": "POL",
+ "logo": "https://web3auth.io/images/web3authlog.png",
+ "wss": '',
+ },
+ {
+ "chainNamespace": ChainNamespace.solana.name,
+ "chainId": "devnet",
+ "rpcTarget": "https://api.devnet.solana.com",
+ "displayName": "Solana Devnet",
+ "blockExplorerUrl": "https://explorer.solana.com/?cluster=devnet/",
+ "ticker": "SOL",
+ "logo": "https://web3auth.io/images/web3authlog.png",
+ "wss": "ws://api.devnet.solana.com"
+ },
+];
+```
+
+Once, we have defined the supported chains, create a new model `ChainConfig`, to represent the Dart object for the above chain config map. We'll use the `ChainConfig` model for UI purposes and chain interaction.
+
+In the `ChainConfig,` we'll also add a `isEVM` parameter to help us differentiate the selected chain ecosystem. If `isEVM` is true for the selected chain, we can use `EthereumProvider` for chain interactions, or else we can use the `SolanaProvider`.
+
+```dart
+import 'package:flutter_playground/features/home/domain/entities/chain_config.dart';
+import 'package:web3auth_flutter/enums.dart';
+
+class ChainConfigModel extends ChainConfig {
+ ChainConfigModel({
+ required super.chainNamespace,
+ required super.displayName,
+ required super.ticker,
+ required super.rpcTarget,
+ required super.logo,
+ required super.blockExplorerUrl,
+ required super.chainId,
+ required super.isEVMChain,
+ required super.wss,
+ });
+
+ factory ChainConfigModel.fromJson(Map json) {
+ final nameSpace = ChainNamespace.values.byName(json['chainNamespace']!);
+ final isEVM = nameSpace == ChainNamespace.eip155;
+ return ChainConfigModel(
+ isEVMChain: isEVM,
+ chainNamespace: nameSpace,
+ displayName: json['displayName']!,
+ ticker: json['ticker']!,
+ rpcTarget: json['rpcTarget']!,
+ logo: json['logo'],
+ blockExplorerUrl: json['blockExplorerUrl']!,
+ chainId: json['chainId']!,
+ wss: json['wss']!,
+ );
+ }
+}
+```
+
+## Wallet Implementation
+
+Once, we have set up the providers, and supported chains, it's time to integrate and plug them into the wallet. For this guide, we are using the `get_it` package for service locator abilities. It will help us with the dependency injection.
+
+### Service Locator
+
+Let's create a new `ServiceLocator` class, and set up the `ChainConfigDataSource` and `ChainConfigRepository`. The `ChainConfigRepository` is responsible for converting the list of chain configs map we defined earlier into a list of `ChainConfig` models and inject into UI. As said earlier, for simplicity we are maintaining the list of chain configs on the frontend, but using `ChainConfigRepository` you can get the list from the server as well.
+
+Checkout the implementation of `ChainConfigDataSource` and `ChainConfigRepository` for more details.
+
+```dart
+class ServiceLocator {
+ ServiceLocator._();
+
+ static GetIt get getIt => GetIt.instance;
+
+ static void setUp() {
+ getIt.registerLazySingleton(
+ () => ChainConfigDataSourceImpl(chainConfigs: chainConfigs),
+ );
+
+ getIt.registerLazySingleton(
+ () => ChainConfigRepositoryImp(getIt()),
+ );
+ }
+}
+```
+
+After successfully setting up the `ServiceLocator`, initialize it in the `main` function above `Web3AuthFlutter` initiliation.
+
+```dart
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+ ServiceLocator.setUp();
+
+ // Additional Web3AuthFlutter initiliation code.
+}
+```
+
+### Set up Home Provider
+
+Once we have set up service locator, the next on list is to create a `ChangeNotifier` to help us maange the state of the wallet. The notifier will help us manage the state of currently selected chain, and access the respective chain provider. For the state management, we will be using the `provider` package, so make sure to add `provider` as a dependency.
+
+```dart
+class HomeProvider with ChangeNotifier {
+ late ChainConfig _selectedChain;
+ late List _chains;
+ late String _chainAddress;
+
+ ChainConfig get selectedChain => _selectedChain;
+ List get chains => _chains;
+ String get chainAddress => _chainAddress;
+
+ HomeProvider(List chains) {
+ _selectedChain = chains.first;
+ _chains = List.from(chains);
+ }
+
+ /// Update the selected chain
+ void updateSelectedChain(ChainConfig chain) {
+ _selectedChain = chain;
+ notifyListeners();
+ }
+
+ /// Update the chain address for corresponding
+ /// selected chain.
+ void updateChainAddress(String address) {
+ _chainAddress = address;
+ }
+
+ /// Add a new custom EVM chain on runtime.
+ void addNewChain(ChainConfig newChain) {
+ _chains.add(newChain);
+ notifyListeners();
+ }
+}
+```
+
+To access the blockchain provider for currently selected chain, we will create a new extension on `ChainConfig`.
+
+```dart
+extension ChainConfigExtension on ChainConfig {
+ ChainProvider prepareChainProvider() {
+ if (isEVMChain) {
+ return EthereumProvider(rpcTarget: rpcTarget);
+ } else {
+ return SolanaProvider(rpcTarget: rpcTarget, wss: wss);
+ }
+ }
+}
+```
+
+### Setting up Home screen
+
+Once, we have our provider ready, we create a new `HomeScreen` widget to show user details as email address, wallet address, user's balance for selectedChain, and blockchain interaction methods. We'll retrieve the `ChainConfigRepository` using `ServiceLocator`, and initialize our `HomeProvider`.
+
+To get the user's balance, we'll use `prepareAccount` method from the `ChainConfigRepository`. The method internally uses `ChainProvider` to retrieve user's wallet address, and fetch the wallet balance for the address. Checkout `ChainConfigRepository` implementation for more details. The methods returns `Account` object which has the above details.
+
+Checkout `Account` data model below.
+
+```dart
+class Account {
+ final Ed25519HDKeyPair? solanaKeyPair;
+ final Credentials? ethereumKeyPair;
+ final String balance;
+ final String publicAddress;
+
+ Account({
+ this.solanaKeyPair,
+ this.ethereumKeyPair,
+ required this.balance,
+ required this.publicAddress,
+ });
+}
+```
+
+Once, we have retrieve the `ChainConfigRepository` in `init` method of `HomeScren`, we'll invoke the `prepareAccount`, and pass the `Account` instance to `StreamController` which is used for data flow in the application.
+
+```dart
+class HomeScreen extends StatefulWidget {
+ const HomeScreen({super.key});
+
+ @override
+ State createState() => _HomeScreenState();
+}
+
+class _HomeScreenState extends State {
+ late final ChainConfigRepository chainConfigRepository;
+ late final TorusUserInfo userInfo;
+
+ late final StreamController streamController;
+ late final HomeProvider homeProvider;
+
+ @override
+ void initState() {
+ super.initState();
+ chainConfigRepository = ServiceLocator.getIt();
+
+ streamController = StreamController();
+ homeProvider = Provider.of(
+ context,
+ listen: false,
+ );
+ loadAccount(false);
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ // loadAccount function is used to fetch the account
+ // details such as balance, user address, and private key
+ // for currently selected chain.
+ Future loadAccount(bool isReload) async {
+ if (!isReload) {
+ userInfo = await Web3AuthFlutter.getUserInfo();
+ }
+
+ final account = await chainConfigRepository.prepareAccount(
+ homeProvider.selectedChain,
+ );
+
+ homeProvider.updateChainAddress(account.publicAddress);
+ // We streamController to control data flow in the application.
+ streamController.add(account);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text(StringConstants.appBarTitle),
+ ),
+ drawer: const SideDrawer(),
+ body: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16),
+ child: StreamBuilder(
+ stream: streamController.stream,
+ builder: (context, snapShot) {
+ // Check if the AsyncSnapshot is in active connection,
+ // and if it's true, build the UI.
+ if (snapShot.connectionState == ConnectionState.active) {
+ return SingleChildScrollView(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const SizedBox(height: 24),
+ const HomeHeader(),
+ const SizedBox(height: 12),
+ // Helps users to switch chain in the wallet.
+ ChainSwitchTile(
+ onSelect: (chainConfig) {
+ homeProvider.updateSelectedChain(chainConfig);
+ loadAccount(true);
+ },
+ ),
+ const SizedBox(height: 16),
+ const Divider(),
+ const SizedBox(height: 16),
+ // Displays user details, such as email,
+ // user name, and logo.
+ AccountDetails(
+ userInfo: userInfo,
+ account: snapShot.requireData,
+ ),
+ const SizedBox(height: 24),
+ Consumer(builder: (
+ _,
+ homeProvider,
+ __,
+ ) {
+ final chain = homeProvider.selectedChain;
+ // Displays user balance.
+ return BalanceWidget(
+ balance: snapShot.data!.balance,
+ ticker: chain.ticker,
+ chainId: chain.chainId,
+ );
+ }),
+ const SizedBox(height: 16),
+ Consumer(builder: (_, __, ___) {
+ return Column(
+ children: [
+ CustomTextButton(
+ onTap: () {
+ _navigationToScreen(
+ context,
+ const TransactionsScreen(),
+ );
+ },
+ text: 'Transaction',
+ ),
+
+ // Disable the SmartContractInteractionScreen for
+ // non evm chains.
+ if (homeProvider.selectedChain.isEVMChain) ...[
+ const SizedBox(height: 16),
+ CustomTextButton(
+ onTap: () {
+ _navigationToScreen(
+ context,
+ const SmartContractInteractionScreen(),
+ );
+ },
+ text:
+ StringConstants.smartContractInteractionsText,
+ ),
+ ]
+ ],
+ );
+ }),
+ ],
+ ),
+ );
+ }
+ return const Center(child: CircularProgressIndicator.adaptive());
+ },
+ ),
+ ),
+ );
+ }
+
+ // Helper function to navigate to different screens.
+ void _navigationToScreen(BuildContext context, Widget screen) {
+ Navigator.of(context).push(MaterialPageRoute(builder: (_) {
+ return screen;
+ }));
+ }
+}
+```
+
+In `HomeScreen` we'll also give users an option to logout from the wallet in navigation drawer. To do so, we'll utilize the `Web3AuthFlutter.logout`. Upon success, we'll navigate users back to `LoginScreen`. Checkout `SideDrawer` widget for navigation drawer implementation.
+
+### Chain Interactions
+
+Once we have setup `HomeScreen`, the next step is to setup chain interactions for signing message, signing transaction, reading from contracts, and writing on contracts. For signing message and transaction, we'll create a new `TransactionsScreen` widget and utilize `signMessage` and `sendTransaction` from `ChainProvider` for respective functionality.
+
+To retrieve currently selected chain, and respective provider we'll use the `HomeProvider`.
+
+```dart
+class TransactionsScreen extends StatefulWidget {
+ const TransactionsScreen({super.key});
+
+ @override
+ State createState() => _TransactionsScreenState();
+}
+
+class _TransactionsScreenState extends State {
+ // Additional variable initiliation
+
+ @override
+ void initState() {
+ super.initState();
+ selectedChain = context.read().selectedChain;
+ chainProvider = selectedChain.prepareChainProvider();
+ // Additional code
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ // Additiona UI code.
+ // Checkout GitHub repo for full code.
+ }
+
+ Future _signMessage(BuildContext context) async {
+ try {
+ showLoader(context);
+ final signature = await chainProvider.signMessage(
+ signMessageTextController.text,
+ );
+ if (context.mounted) {
+ removeDialog(context);
+ showInfoDialog(context, signature);
+ }
+ } catch (e, _) {
+ log(e.toString(), stackTrace: _);
+ if (context.mounted) {
+ removeDialog(context);
+ showInfoDialog(context, e.toString());
+ }
+ }
+ }
+
+ Future _sendTransaction(BuildContext context) async {
+ try {
+ showLoader(context);
+ final amount = double.parse(amountTextController.text);
+ final hash = await chainProvider.sendTransaction(
+ destinationTextController.text,
+ amount,
+ );
+
+ if (context.mounted) {
+ removeDialog(context);
+ showInfoDialog(context, hash);
+ }
+ } catch (e, _) {
+ log(e.toString(), stackTrace: _);
+ if (context.mounted) {
+ removeDialog(context);
+ showInfoDialog(context, e.toString());
+ }
+ }
+ }
+}
+```
+
+## Conclusion
+
+Voila, you have build a chain agnostic Web3 wallet. This guide only gives you an overview of how to create your wallet with EVM and Solana ecosystem support. The general idea of the guide can be used for any of the blockchain ecosystem.
+
+If you are interested in learning more about Web3Auth, please checkout our [documentation for Flutter](/docs/sdk/mobile/pnp/flutter). You can find the code used for the guide on our [examples repo](https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-playground).
diff --git a/src/pages/guides/pnp-no-modal-multichain.mdx b/src/pages/guides/pnp-no-modal-multichain.mdx
new file mode 100644
index 00000000000..b0f250e4be7
--- /dev/null
+++ b/src/pages/guides/pnp-no-modal-multichain.mdx
@@ -0,0 +1,606 @@
+---
+title: Create a Chain Agnostic Web3 Wallet with Web3Auth
+image: 'img/guides/guides-banners/multi.png'
+description: Learn how to create a chain-agnostic Web3 wallet using Web3Auth.
+type: guide
+tags: [embedded wallets, web, multi chain, polkadot, evm, cosmos, web3auth]
+date: February 9, 2024
+author: Web3Auth Team
+communityPortalTopicId:
+---
+
+import SEO from '@site/src/components/SEO'
+import TabItem from '@theme/TabItem'
+import Tabs from '@theme/Tabs'
+
+
+
+This guide will cover the basics of how to integrate Web3Auth with different blockchains at the same time. In this demo, you will be able to authenticate with different social logins and get different addresses from each blockchain. Of course, you can interact and sign transactions with any of them.
+
+You will be able to make calls like get the user's `account`, fetch `balance`, `sign message`, `send transaction`, `read` from and `write` to smart contracts, etc.
+
+**Web3Auth is designed to support any blockchain that follows the `secp256k1` & `ed25519` curves**. This means it works seamlessly with all EVMs such as Ethereum, Polygon, Binance Smart Chain, and others. Additionally, it supports non-EVM blockchains like Aptos, Cosmos, Polkadot, Solana, Tezos, Bitcoin, among many others. Web3Auth is not limited to these examples and is capable of integrating with any blockchain that adheres to these cryptographic standards, offering a wide range of compatibility to suit various needs and preferences in the blockchain ecosystem.
+
+## Quick Start
+
+You can run the following command or you can check the [full example](https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/custom-authentication/multi-chain-example) in our Github.
+
+```bash
+npx degit Web3Auth/web3auth-pnp-examples/custom-authentication/multi-chain-example/ w3a-multi-chain-demo && cd w3a-multi-chain-demo && npm install && npm run dev
+```
+
+## Prerequisites
+
+- For Web Apps: A basic knowledge of JavaScript is required to use Web3Auth SDK.
+
+- For Mobile Apps: For the Web3Auth Mobile SDKs, you have a choice between iOS, Android, React Native & Flutter. Please refer to the [Web3Auth SDK Reference](/sdk) for more information.
+
+- Create a Web3Auth account on the [Web3Auth Dashboard](https://dashboard.web3auth.io)
+
+## How to set up Web3Auth Dashboard
+
+If you haven't already, sign up on the Web3Auth platform. It is free and gives you access to the Web3Auth's base plan. After the basic setup, explore other features and functionalities offered by the Web3Auth Dashboard. It includes custom verifiers, whitelabeling, analytics, and more. Head to [Web3Auth's documentation](/docs/dashboard) page for detailed instructions on setting up the Web3Auth Dashboard.
+
+## Using Web3Auth with Multiple Blockchains
+
+To use Web3Auth with multiple blockchains, you need to set up your React application with the Web3Auth SDK. This guide will walk you through the setup and implementation.
+
+#### Setting up your base project for using Web3 libraries:
+
+If you are starting from scratch, to set up this project locally, you will need to create a base Web application, where you can install the required dependencies. However, while working with Web3, there are a few base libraries, which need additional configuration. This is because certain packages are not available in the browser environment, and we need to polyfill them manually. You can follow [this documentation](/troubleshooting/webpack-issues) where we have mentioned the configuration changes for some popular frameworks for your reference.
+
+### Installation
+
+We need several dependencies to make this work with multiple blockchains:
+
+```bash npm2yarn
+npm install @web3auth/modal @solana/web3.js ethers @taquito/signer @taquito/taquito @taquito/utils @polkadot/api @polkadot/util-crypto tweetnacl
+```
+
+### Setting up Web3Auth Provider
+
+First, create a configuration file for Web3Auth (e.g., `web3authContext.tsx`):
+
+```tsx
+import { WEB3AUTH_NETWORK, type Web3AuthOptions } from '@web3auth/modal'
+
+// Get your client ID from https://dashboard.web3auth.io
+const clientId = import.meta.env.VITE_WEB3AUTH_CLIENT_ID || ''
+
+// Instantiate SDK
+const web3AuthOptions: Web3AuthOptions = {
+ clientId,
+ web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
+}
+
+const web3AuthContextConfig = {
+ web3AuthOptions,
+}
+
+export default web3AuthContextConfig
+```
+
+Then, set up the Web3Auth provider in your application entry point (`index.tsx` or similar):
+
+```tsx
+import ReactDOM from 'react-dom/client'
+// Setup Web3Auth Provider
+import { Web3AuthProvider } from '@web3auth/modal/react'
+import web3AuthContextConfig from './web3authContext'
+
+import App from './App'
+
+const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
+root.render(
+
+
+
+)
+```
+
+### Implementing the Multi-Chain Wallet
+
+Now, let's implement the main application with support for multiple blockchains. We'll create RPC modules for each blockchain and use them in our app.
+
+#### Setting up the Main App Component
+
+```tsx
+import './App.css'
+import {
+ useWeb3AuthConnect,
+ useWeb3AuthDisconnect,
+ useWeb3AuthUser,
+ useWeb3Auth,
+} from '@web3auth/modal/react'
+
+// Import RPC functions
+import {
+ getEthereumAccounts,
+ getEthereumBalance,
+ signEthereumMessage,
+ sendEthereumTransaction,
+} from './RPC/ethersRPC'
+import {
+ getSolanaAccount,
+ getSolanaBalance,
+ signSolanaMessage,
+ sendSolanaTransaction,
+} from './RPC/solanaRPC'
+import {
+ getTezosAccount,
+ getTezosBalance,
+ signTezosMessage,
+ signAndSendTezosTransaction,
+} from './RPC/tezosRPC'
+import {
+ getPolkadotAccounts,
+ getPolkadotBalance,
+ signAndSendPolkadotTransaction,
+} from './RPC/polkadotRPC'
+
+function App() {
+ const {
+ connect,
+ isConnected,
+ loading: connectLoading,
+ error: connectError,
+ } = useWeb3AuthConnect()
+ const { disconnect, loading: disconnectLoading, error: disconnectError } = useWeb3AuthDisconnect()
+ const { userInfo } = useWeb3AuthUser()
+ const { provider } = useWeb3Auth()
+
+ const getAllAccounts = async () => {
+ if (!provider) {
+ uiConsole('provider not initialized yet')
+ return
+ }
+ const eth_address = await getEthereumAccounts(provider)
+ const solana_address = await getSolanaAccount(provider)
+ const tezos_address = await getTezosAccount(provider)
+ const polkadot_address = await getPolkadotAccounts(provider)
+
+ uiConsole(
+ 'Ethereum Address: ' + eth_address,
+ 'Solana Address: ' + solana_address,
+ 'Tezos Address: ' + tezos_address,
+ 'Polkadot Address: ' + polkadot_address
+ )
+ }
+
+ const getAllBalances = async () => {
+ if (!provider) {
+ uiConsole('provider not initialized yet')
+ return
+ }
+
+ const eth_balance = await getEthereumBalance(provider)
+ const solana_balance = await getSolanaBalance(provider)
+ const tezos_balance = await getTezosBalance(provider)
+ const polkadot_balance = await getPolkadotBalance(provider)
+
+ uiConsole(
+ 'Ethereum Balance: ' + eth_balance,
+ 'Solana Balance: ' + solana_balance,
+ 'Tezos Balance: ' + tezos_balance,
+ 'Polkadot Balance: ' + polkadot_balance
+ )
+ }
+
+ function uiConsole(...args: any[]): void {
+ const el = document.querySelector('#console>p')
+ if (el) {
+ el.innerHTML = JSON.stringify(args || {}, null, 2)
+ }
+ }
+
+ const loggedInView = (
+
+
+
+
+
+
+
+ {disconnectLoading &&
Disconnecting...
}
+ {disconnectError &&
{disconnectError.message}
}
+
+
+
Account Operations
+
+
+
+
+
+
+
+ {/* Additional blockchain operations buttons */}
+
+
+
+ )
+
+ const unloggedInView = (
+
+
+ {connectLoading &&
Connecting...
}
+ {connectError &&
{connectError.message}
}
+
+ )
+
+ return (
+
+
+
+
{isConnected ? loggedInView : unloggedInView}
+
+
+
+ )
+}
+
+export default App
+```
+
+### Implementing Blockchain RPC Modules
+
+Let's implement the RPC modules for each blockchain. These modules will interact with the respective blockchain networks.
+
+## EVM (Ethereum)
+
+Here's how to implement the Ethereum RPC module:
+
+```tsx
+// ethersRPC.ts
+import type { IProvider } from '@web3auth/modal'
+import { ethers } from 'ethers'
+
+export async function getEthereumAccounts(provider: IProvider): Promise {
+ try {
+ const ethersProvider = new ethers.BrowserProvider(provider)
+ const signer = await ethersProvider.getSigner()
+ // Get user's Ethereum public address
+ const address = signer.getAddress()
+ return await address
+ } catch (error) {
+ return error
+ }
+}
+
+export async function getEthereumBalance(provider: IProvider): Promise {
+ try {
+ const ethersProvider = new ethers.BrowserProvider(provider)
+ const signer = await ethersProvider.getSigner()
+ // Get user's Ethereum public address
+ const address = signer.getAddress()
+ // Get user's balance in ether
+ const balance = ethers.formatEther(
+ await ethersProvider.getBalance(address) // Balance is in wei
+ )
+ return balance
+ } catch (error) {
+ return error as string
+ }
+}
+
+export async function signEthereumMessage(provider: IProvider): Promise {
+ try {
+ const ethersProvider = new ethers.BrowserProvider(provider)
+ const signer = await ethersProvider.getSigner()
+ const originalMessage = 'YOUR_MESSAGE'
+ // Sign the message
+ const signedMessage = await signer.signMessage(originalMessage)
+ return signedMessage
+ } catch (error) {
+ return error as string
+ }
+}
+
+export async function sendEthereumTransaction(provider: IProvider): Promise {
+ try {
+ const ethersProvider = new ethers.BrowserProvider(provider)
+ const signer = await ethersProvider.getSigner()
+ const destination = '0x40e1c367Eca34250cAF1bc8330E9EddfD403fC56'
+ // Convert 1 ether to wei
+ const amount = ethers.parseEther('0.001')
+ // Submit transaction to the blockchain
+ const tx = await signer.sendTransaction({
+ to: destination,
+ value: amount,
+ maxPriorityFeePerGas: '5000000000', // Max priority fee per gas
+ maxFeePerGas: '6000000000000', // Max fee per gas
+ })
+ // Wait for transaction to be mined
+ const receipt = await tx.wait()
+ return receipt
+ } catch (error) {
+ return error as string
+ }
+}
+```
+
+## Solana
+
+Here's how to implement the Solana RPC module:
+
+```tsx
+// solanaRPC.ts
+import { Keypair, Connection } from '@solana/web3.js'
+import { IProvider, getED25519Key } from '@web3auth/modal'
+import nacl from 'tweetnacl'
+
+export async function getSolanaAccount(ethProvider: IProvider): Promise {
+ const ethPrivateKey = await ethProvider.request({
+ method: 'private_key',
+ })
+
+ const privateKey = getED25519Key(ethPrivateKey as string).sk.toString('hex')
+ const secretKey = new Uint8Array(Buffer.from(privateKey, 'hex'))
+ const keypair = Keypair.fromSecretKey(secretKey)
+ return keypair.publicKey.toBase58()
+}
+
+export async function getSolanaBalance(ethProvider: IProvider): Promise {
+ const ethPrivateKey = await ethProvider.request({
+ method: 'private_key',
+ })
+ const privateKey = getED25519Key(ethPrivateKey as string).sk.toString('hex')
+ const secretKey = new Uint8Array(Buffer.from(privateKey, 'hex'))
+ const keypair = Keypair.fromSecretKey(secretKey)
+ const connection = new Connection('https://api.devnet.solana.com')
+ const balance = await connection.getBalance(keypair.publicKey)
+ return balance.toString()
+}
+
+export async function signSolanaMessage(ethProvider: IProvider): Promise {
+ try {
+ const ethPrivateKey = await ethProvider.request({
+ method: 'private_key',
+ })
+ const privateKey = getED25519Key(ethPrivateKey as string).sk.toString('hex')
+ const secretKey = new Uint8Array(Buffer.from(privateKey, 'hex'))
+ const keypair = Keypair.fromSecretKey(secretKey)
+
+ // Convert message to Uint8Array
+ const messageBytes = new TextEncoder().encode('Hello Solana')
+
+ // Sign the message
+ const signature = nacl.sign.detached(messageBytes, keypair.secretKey)
+
+ return Buffer.from(signature).toString('base64')
+ } catch (error) {
+ console.error('Error signing Solana message:', error)
+ throw error
+ }
+}
+
+export async function sendSolanaTransaction(ethProvider: IProvider): Promise {
+ try {
+ const ethPrivateKey = await ethProvider.request({
+ method: 'private_key',
+ })
+ const privateKey = getED25519Key(ethPrivateKey as string).sk.toString('hex')
+ const secretKey = new Uint8Array(Buffer.from(privateKey, 'hex'))
+ const keypair = Keypair.fromSecretKey(secretKey)
+
+ const connection = new Connection('https://api.devnet.solana.com')
+
+ // Import required modules for transaction
+ const { SystemProgram, Transaction, PublicKey, sendAndConfirmTransaction } = await import(
+ '@solana/web3.js'
+ )
+
+ // Create a test recipient address
+ const toAccount = new PublicKey('7C4jsPZpht1JHMWmwDF5ZEVfGSBViXCKbQEcm2GKHtKQ')
+
+ // Create a transfer instruction
+ const transferInstruction = SystemProgram.transfer({
+ fromPubkey: keypair.publicKey,
+ toPubkey: toAccount,
+ lamports: 100000, // 0.0001 SOL
+ })
+
+ // Create a transaction and add the instruction
+ const transaction = new Transaction().add(transferInstruction)
+
+ // Set a recent blockhash
+ transaction.recentBlockhash = (await connection.getRecentBlockhash()).blockhash
+ transaction.feePayer = keypair.publicKey
+
+ // Sign and send the transaction
+ const signature = await sendAndConfirmTransaction(connection, transaction, [keypair])
+
+ return signature
+ } catch (error) {
+ console.error('Error sending Solana transaction:', error)
+ throw error
+ }
+}
+```
+
+## Tezos
+
+Here's how to implement the Tezos RPC module:
+
+```tsx
+// tezosRPC.ts
+import { InMemorySigner } from '@taquito/signer'
+import { TezosToolkit } from '@taquito/taquito'
+import { hex2buf } from '@taquito/utils'
+// @ts-ignore
+import * as tezosCrypto from '@tezos-core-tools/crypto-utils'
+import type { IProvider } from '@web3auth/modal'
+
+const tezos = new TezosToolkit('https://rpc.tzbeta.net/')
+
+export async function getTezosKeyPair(provider: IProvider): Promise {
+ try {
+ const privateKey = (await provider.request({ method: 'private_key' })) as string
+ const keyPair = tezosCrypto.utils.seedToKeyPair(hex2buf(privateKey))
+ return keyPair
+ } catch (error) {
+ console.error(error)
+ return null
+ }
+}
+
+export async function setProvider(provider: IProvider): Promise {
+ const keyPair = await getTezosKeyPair(provider)
+ tezos.setSignerProvider(await InMemorySigner.fromSecretKey(keyPair?.sk as string))
+}
+
+export async function getTezosAccount(provider: IProvider): Promise {
+ try {
+ const keyPair = await getTezosKeyPair(provider)
+ return keyPair?.pkh
+ } catch (error) {
+ console.error('Error', error)
+ return error
+ }
+}
+
+export async function getTezosBalance(provider: IProvider): Promise {
+ try {
+ const keyPair = await getTezosKeyPair(provider)
+ const balance = await tezos.tz.getBalance(keyPair?.pkh as string)
+ return balance.toString()
+ } catch (error) {
+ console.error('Error', error)
+ return error
+ }
+}
+
+export async function signTezosMessage(provider: IProvider): Promise {
+ try {
+ const keyPair = await getTezosKeyPair(provider)
+ const signer = new InMemorySigner(keyPair.sk)
+ const message = '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad'
+ const signature = await signer.sign(message)
+ return signature
+ } catch (error) {
+ return error
+ }
+}
+
+export async function signAndSendTezosTransaction(provider: IProvider): Promise {
+ try {
+ await setProvider(provider)
+ // example address
+ const address = 'tz1dHzQTA4PGBk2igZ3kBrDsVXuvHdN8kvTQ'
+
+ const op = await tezos.wallet
+ .transfer({
+ to: address,
+ amount: 0.00005,
+ })
+ .send()
+
+ const txRes = await op.confirmation()
+ return txRes
+ } catch (error) {
+ return error
+ }
+}
+```
+
+## Polkadot
+
+Here's how to implement the Polkadot RPC module:
+
+```tsx
+// polkadotRPC.ts
+import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'
+import { cryptoWaitReady } from '@polkadot/util-crypto'
+import type { IProvider } from '@web3auth/modal'
+
+export async function makeClient(): Promise {
+ console.log('Establishing connection to Rococo Relay Chain RPC...')
+ const provider = new WsProvider('wss://rococo-rpc.polkadot.io') // roccoco testnet relay chain
+ const api = await ApiPromise.create({ provider })
+ const resp = await api.isReady
+ console.log('Polkadot RPC is ready', resp)
+ return api
+}
+
+export async function getPolkadotKeyPair(provider: IProvider): Promise {
+ await cryptoWaitReady()
+ const privateKey = (await provider.request({
+ method: 'private_key',
+ })) as string
+ const keyring = new Keyring({ ss58Format: 42, type: 'sr25519' })
+ const keyPair = keyring.addFromUri(`0x${privateKey}`)
+ return keyPair
+}
+
+export async function getPolkadotAccounts(provider: IProvider): Promise {
+ const keyPair = await getPolkadotKeyPair(provider)
+ return keyPair.address
+}
+
+export async function getPolkadotBalance(provider: IProvider): Promise {
+ const keyPair = await getPolkadotKeyPair(provider)
+ const api = await makeClient()
+ const data = await api.query.system.account(keyPair.address)
+ const accountData = data.toHuman()
+ return accountData.data.free
+}
+
+export async function signAndSendPolkadotTransaction(provider: IProvider): Promise {
+ try {
+ const keyPair = await getPolkadotKeyPair(provider)
+ const api = await makeClient()
+ const txHash = await api.tx.balances
+ .transferKeepAlive('5Gzhnn1MsDUjMi7S4cN41CfggEVzSyM58LkTYPFJY3wt7o3d', 12345)
+ .signAndSend(keyPair)
+ return txHash.toHuman()
+ } catch (err: any) {
+ return err.toString()
+ }
+}
+```
+
+## Conclusion
+
+This guide has shown you how to create a multi-chain wallet application using Web3Auth. With this setup, you can:
+
+1. Authenticate users with their social accounts
+2. Generate blockchain addresses for multiple chains (Ethereum, Solana, Tezos, Polkadot)
+3. Check balances across different blockchains
+4. Sign messages and send transactions on various networks
+
+The power of Web3Auth lies in its ability to derive keys for multiple blockchains from a single authentication session, providing users with a seamless experience across the web3 ecosystem.
+
+If you want to integrate with a specific blockchain and you're having trouble with the code, please contact us in our [community portal](https://web3auth.io/community/).
+
+## References
+
+- [Web3Auth Documentation](https://web3auth.io/docs/)
+- [Web3Auth Examples](https://github.com/Web3Auth/web3auth-pnp-examples/)
diff --git a/src/pages/guides/sending-gasless-transaction.mdx b/src/pages/guides/sending-gasless-transaction.mdx
new file mode 100644
index 00000000000..5567bc7f052
--- /dev/null
+++ b/src/pages/guides/sending-gasless-transaction.mdx
@@ -0,0 +1,294 @@
+---
+title: Send your first gasless transaction
+image: 'img/guides/guides-banners/gasless-transaction.png'
+description: Learn how to use gasless paymaster with Web3Auth Native Account Abstraction.
+type: guide
+tags: [embedded wallets, account abstraction, web, paymaster, erc4337, web3auth]
+date: October 22, 2024
+author: Web3Auth Team
+---
+
+import SEO from '@site/src/components/SEO'
+import TabItem from '@theme/TabItem'
+import Tabs from '@theme/Tabs'
+
+
+
+A paymaster is a vital component in the ERC-4337 standard, responsible for covering transaction costs on behalf of the user. There are various types of paymasters, such as gasless paymasters, ERC-20 paymasters, and more.
+
+In this guide, we'll talk about how you can use the Pimlico gasless Paymaster with Web3Auth Account Abstraction Provider to sponsor the transaction for your users without requiring the user to pay gas fees.
+
+For those who want to skip straight to the code, you can find it on [GitHub](https://github.com/Web3Auth/web3auth-examples/tree/main/other/smart-account-example).
+
+## Prerequisites
+
+- Pimlico Account: Since we'll be using the Pimlico paymaster, you'll need to have an API key from Pimlico. You can get a free API key from [Pimlico Dashboard](https://dashboard.pimlico.io/).
+- Web3Auth Dashboard: If you haven't already, sign up on the Web3Auth platform. It is free and gives you access to the Web3Auth's base plan. Head to Web3Auth's documentation page for detailed [instructions on setting up the Web3Auth Dashboard](/docs/dashboard).
+- Web3Auth PnP Web SDK: This guide assumes that you already know how to integrate the PnP Web SDK in your project. If not, you can learn how to [integrate Web3Auth in your Web app](/docs/sdk/web/react/).
+
+## Integrate AccountAbstractionProvider
+
+Once, you have set up the Web3Auth Dashboard, and created a new project, it's time to integrate Web3Auth Account Abstraction Provider in your Web application. For the implementation, we'll use the [@web3auth/account-abstraction-provider](https://www.npmjs.com/package/@web3auth/account-abstraction-provider). The provider simplifies the entire process by managing the complex logic behind configuring the account abstraction provider, bundler, and preparing user operations.
+
+If you are already using the Web3Auth Pnp SDK in your project, you just need to configure the AccountAbstractionProvider with the paymaster details, and pass it to the Web3Auth instance. No other changes are required.
+
+### Installation
+
+```bash
+npm install --save @web3auth/account-abstraction-provider
+```
+
+### Configure Paymaster
+
+The AccountAbstractionProvider requires specific configurations to function correctly. One key configuration is the paymaster. Web3Auth supports custom paymaster configurations, allowing you to deploy your own paymaster and integrate it with the provider.
+
+You can choose from a variety of paymaster services available in the ecosystem. In this guide, we'll be configuring the Pimlico's paymaster. However, it's important to note that paymaster support is not limited to the Pimlico, giving you the flexibility to integrate any compatible paymaster service that suits your requirements.
+
+For the simplicity, we have only use `SafeSmartAccount`, but you choose your favorite smart account provider from the available ones. [Learn how to configure the smart account](/docs/sdk/web/react/advanced/smart-accounts).
+
+```ts
+// focus-start
+import {
+ AccountAbstractionProvider,
+ SafeSmartAccount,
+} from '@web3auth/account-abstraction-provider'
+// focus-end
+
+const chainConfig = {
+ chainNamespace: CHAIN_NAMESPACES.EIP155,
+ chainId: '0xaa36a7',
+ rpcTarget: 'https://rpc.sepolia.org',
+ displayName: 'Ethereum Sepolia Testnet',
+ blockExplorerUrl: 'https://sepolia.etherscan.io',
+ ticker: 'ETH',
+ tickerName: 'Ethereum',
+ logo: 'https://cryptologos.cc/logos/ethereum-eth-logo.png',
+}
+
+// focus-start
+const accountAbstractionProvider = new AccountAbstractionProvider({
+ config: {
+ chainConfig,
+ bundlerConfig: {
+ // Get the pimlico API Key from dashboard.pimlico.io
+ url: `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoAPIKey}`,
+ },
+ smartAccountInit: new SafeSmartAccount(),
+ paymasterConfig: {
+ // Get the pimlico API Key from dashboard.pimlico.io
+ url: `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoAPIKey}`,
+ },
+ },
+})
+// focus-end
+```
+
+## Configure Web3Auth
+
+Once you have configured your `AccountAbstractionProvider`, you can now plug it in your Web3Auth Modal/No Modal instance. If you are using the external wallets like MetaMask, Coinbase, etc, you can define whether you want to use the AccountAbstractionProvider, or EthereumPrivateKeyProvider by setting the `useAAWithExternalWallet` in `IWeb3AuthCoreOptions`.
+
+If you are setting `useAAWithExternalWallet` to `true`, it'll create a new Smart Account for your user, where the signer/creator of the Smart Account would be the external wallet.
+
+If you are setting `useAAWithExternalWallet` to `false`, it'll skip creating a new Smart Account, and directly use the external wallet to sign the transactions.
+
+
+
+
+
+```ts
+import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
+import { Web3Auth } from "@web3auth/modal";
+
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ // Use the chain config we declared earlier
+ config: { chainConfig },
+});
+
+const web3auth = new Web3Auth({
+ clientId: "YOUR_WEB3AUTH_CLIENT_ID",
+ web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
+ privateKeyProvider,
+ // Use the account abstraction provider we configured earlier
+ accountAbstractionProvider
+ // This will allow you to use EthereumPrivateKeyProvider for
+ // external wallets, while use the AccountAbstractionProvider
+ // for Web3Auth embedded wallets.
+ useAAWithExternalWallet: false,
+});
+```
+
+
+
+
+
+```ts
+import { Web3AuthNoModal } from "@web3auth/no-modal";
+import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
+import { AuthAdapter } from "@web3auth/auth-adapter";
+
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ config: { chainConfig },
+});
+
+const web3auth = new Web3AuthNoModal({
+ clientId: "YOUR_WEB3AUTH_CLIENT_ID",
+ web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
+ privateKeyProvider,
+ // Use the account abstraction provider we configured earlier
+ accountAbstractionProvider
+ // This will allow you to use EthereumPrivateKeyProvider for
+ // external wallets, while use the AccountAbstractionProvider
+ // for Web3Auth embedded wallets.
+ useAAWithExternalWallet: false,
+});
+
+const authadapter = new AuthAdapter();
+web3auth.configureAdapter(authadapter);
+```
+
+
+
+
+## Configure Signer
+
+The Web3Auth Smart Account feature is compatible with popular signer SDKs, including wagmi, ethers, and viem. You can choose your preferred package to configure the signer.
+
+You can retreive the provider to configure the signer from Web3Auth instance.
+
+:::info Wagmi
+
+Wagmi does not require any special configuration to use the signer with smart accounts. Once you have set up your Web3Auth provider and connected your wallet, Wagmi's hooks (such as useSigner or useAccount) will automatically use the smart account as the signer. You can interact with smart accounts using Wagmi just like you would with a regular EOA (Externally Owned Account) signer—no additional setup is needed.
+
+:::
+
+
+
+
+
+```tsx
+import { createWalletClient } from 'viem'
+
+// Use your Web3Auth instance to retreive the provider.
+const provider = web3auth.provider
+
+const walletClient = createWalletClient({
+ transport: custom(provider),
+})
+```
+
+
+
+
+
+```tsx
+import { ethers } from 'ethers'
+
+// Use your Web3Auth instance to retreive the provider.
+const provider = web3auth.provider
+
+const ethersProvider = new ethers.providers.Web3Provider(provider)
+const signer = await ethersProvider.getSigner()
+```
+
+
+
+
+## Send a transaction
+
+Developers can use their preferred signer or Wagmi hooks to initiate on-chain transactions, while Web3Auth manages the creation and submission of the UserOperation. Only the `to`, `data`, and `value` fields need to be provided. Any additional parameters will be ignored and automatically overridden.
+
+To ensure reliable execution, the bundler client sets maxFeePerGas and maxPriorityFeePerGas values. If custom values are required, developers can use the [Viem's BundlerClient](https://viem.sh/account-abstraction/clients/bundler#bundler-client) to manually construct and send the user operation.
+
+Since Smart Accounts are deployed smart contracts, the user's first transaction also triggers the on-chain deployment of their wallet.
+
+
+
+
+
+```tsx
+import { useSendTransaction } from 'wagmi'
+
+const { data: hash, sendTransaction } = useSendTransaction()
+
+// Convert 1 ether to WEI format
+const value = web3.utils.toWei(1)
+
+sendTransaction({ to: 'DESTINATION_ADDRESS', value, data: '0x' })
+
+const {
+ data: receipt,
+ isLoading: isConfirming,
+ isSuccess: isConfirmed,
+} = useWaitForTransactionReceipt({
+ hash,
+})
+```
+
+
+
+
+```tsx
+// Convert 1 ether to WEI format
+const amount = ethers.parseEther('1.0')
+
+// Submits a user operation to the blockchain
+const transaction = await signer.sendTransaction({
+ to: 'DESTINATION_ADDRESS',
+ value: amount,
+ // This will perform the transfer of ETH
+ data: '0x',
+})
+
+// Wait for the transaction to be mined
+const receipt = await transaction.wait()
+```
+
+
+
+
+```tsx
+// Convert 1 ether to WEI format
+const amount = parseEther('1')
+
+// Submits a user operation to the blockchain
+const hash = await walletClient.sendTransaction({
+ to: 'DESTINATION_ADDRESS',
+ value: amount,
+ // This will perform the transfer of ETH
+ data: '0x',
+})
+
+// Wait for the transaction to be mined
+const receipt = await publicClient.waitForTransactionReceipt({ hash })
+```
+
+
+
+
+## Conclusion
+
+Voila, you have successfully sent your first gasless transaction using the Pimlico paymaster with Web3Auth Account Abstraction Provider. To learn more about advance features of the Account Abstraction Provider like performing batch transactions, using ERC-20 paymaster you can refer to the [Account Abstraction Provider](/docs/sdk/web/react) documentation.
diff --git a/src/pages/guides/telegram-miniapp-client.mdx b/src/pages/guides/telegram-miniapp-client.mdx
new file mode 100644
index 00000000000..17f99dc4fd7
--- /dev/null
+++ b/src/pages/guides/telegram-miniapp-client.mdx
@@ -0,0 +1,474 @@
+---
+title: 'Client-Side Setup for Telegram Mini App with Web3Auth'
+image: 'img/guides/guides-banners/telegram-miniapp-client.png'
+description: |
+ Learn how to set up the client-side of a Telegram Mini App using Web3Auth to authenticate users and retrieve wallet details. This guide is the second part of the Telegram Mini App series.
+type: guide
+tags: [embedded wallets, telegram, authentication, web3auth, ton]
+date: October 24, 2024
+author: Web3Auth Team
+---
+
+import SEO from '@site/src/components/SEO'
+import TelegramMiniAppDiagram from '@site/static/img/guides/telegram-mini-app-flow-diagram.png'
+
+
+
+:::tip Live Demo
+
+Before diving into development, experience Web3Auth in action! Check out our demo Telegram Mini App:
+
+👉 **[Launch Demo Mini App](https://t.me/w3a_tg_mini_app_bot)**
+
+:::
+
+:::info Source Code
+
+You can find the full working code for this client + server example here: [**Web3Auth Telegram Mini App Example**](https://github.com/Web3Auth/web3auth-core-kit-examples/tree/main/single-factor-auth-web/sfa-web-ton-telegram-example)
+
+:::
+
+### **Objectives**
+
+In this guide, we will focus on setting up the client-side of a Telegram Mini App using Web3Auth for authentication. By the end of this guide, you will:
+
+1. Implement Web3Auth in the **client-side app** to authenticate Telegram users using the JWT tokens generated in [Part 1](/guides/telegram-miniapp-server).
+2. Retrieve wallet details (e.g., TON blockchain addresses) via Web3Auth and display them in the app.
+
+:::tip
+
+**Prerequisite**: If you haven't completed [Part 1](/guides/telegram-miniapp-server), where we set up the backend server and handled Telegram authentication, it's recommended to start from there before proceeding with this guide.
+
+:::
+
+---
+
+### **Guide Breakdown**
+
+1. **Part 1**: Set up the server-side logic to validate Telegram login data and generate JWT tokens.
+2. **Part 2 (Current Guide)**: Focuses on integrating Web3Auth into the client-side app to authenticate users and retrieve their wallet details.
+
+---
+
+### Overview
+
+In this guide, we will implement the client-side part of the Telegram Mini App. The client will handle user interaction, manage the login flow using Web3Auth, and retrieve wallet details from the TON blockchain.
+
+We'll be using the JWT token generated in [Part 1](/guides/telegram-miniapp-server) of this guide to authenticate users on the client-side and establish a session with Web3Auth to retrieve decentralized wallet information.
+
+The flow is as follows:
+
+
+
+1. The user logs into the Telegram Mini App.
+2. The JWT token (generated from the backend) is passed to Web3Auth for authentication.
+3. Web3Auth authenticates the user and retrieves wallet details (e.g., the user's TON blockchain address).
+4. The client displays the wallet details to the user.
+
+---
+
+### **What You Will Learn:**
+
+1. Integrate Web3Auth into a client-side app to handle user authentication.
+2. Retrieve wallet details (TON blockchain) from Web3Auth.
+3. Mock Telegram environments for local development and testing.
+
+---
+
+[Follow these steps to set up your Custom Verifier with Web3Auth](/docs/authentication/custom-connections/custom-jwt#set-up-custom-jwt-connection).
+
+---
+
+### Step 1: Install Required Packages
+
+Before starting, install the required dependencies for the client-side app.
+
+```bash
+npm install @web3auth/single-factor-auth @telegram-apps/sdk-react dotenv @orbs-network/ton-access
+```
+
+#### **Brief Overview of Dependencies:**
+
+- **@web3auth/single-factor-auth**: This is the core package for using Web3Auth's Single Factor Authentication (SFA) flow, which will allow us to authenticate Telegram users and retrieve blockchain data.
+- **@telegram-apps/sdk-react**: This package is used to handle Telegram's launch parameters and mock Telegram environments for testing during development.
+- **dotenv**: Allows loading environment variables from a `.env` file, ensuring secure storage of sensitive data such as server URLs.
+- **@orbs-network/ton-access**: Provides access to the TON blockchain RPC endpoint for fetching account information and signing messages on the TON network.
+
+---
+
+### Step 2: Set Up Environment Variables
+
+Ensure that the `.env` file contains the following value:
+
+```env
+VITE_SERVER_URL=https://your-server-url.com
+```
+
+This value will be used to connect the client-side app to your backend server.
+
+---
+
+### Step 3: Import Necessary Packages and Set Up States
+
+In this step, we will import all the necessary packages for our client-side application and set up the states that will manage the login flow, user data, and TON blockchain interactions.
+
+#### Import and State Setup
+
+```tsx
+import { useEffect, useState } from "react";
+import { Web3Auth, decodeToken } from "@web3auth/single-factor-auth";
+import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK } from "@web3auth/base";
+import { CommonPrivateKeyProvider } from "@web3auth/base-provider";
+import { useLaunchParams } from "@telegram-apps/sdk-react";
+import { useTelegramMock } from "./hooks/useMockTelegramInitData";
+import { getHttpEndpoint } from "@orbs-network/ton-access";
+import "./App.css";
+
+const verifier = "w3a-telegram-demo";
+const clientId = "BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ";
+
+function App() {
+ const [isLoggingIn, setIsLoggingIn] = useState(false);
+ const [web3authSfa, setWeb3authSfa] = useState(null);
+ const [web3AuthInitialized, setWeb3AuthInitialized] = useState(false);
+ const [userData, setUserData] = useState(null);
+ const [tonAccountAddress, setTonAccountAddress] = useState(null);
+ const [signedMessage, setSignedMessage] = useState(null);
+ const [isLoggedIn, setIsLoggedIn] = useState(false);
+
+ const { initDataRaw, initData, themeParams } = useLaunchParams() || {};
+
+ useTelegramMock(); // Initialize the Telegram mock data
+```
+
+- **Explanation**: In this step, we import the necessary libraries and set up states like `isLoggingIn`, `web3authSfa`, `web3AuthInitialized`, `userData`, `tonAccountAddress`, and `signedMessage` that will manage our app's flow.
+
+---
+
+### Step 4: Initialize Web3Auth and Fetch the ID Token
+
+Now that the states are set up, let's move on to initializing **Web3Auth** and setting up the connection to our backend server to fetch the ID token generated in **[Part 1](/guides/telegram-miniapp-server)**.
+
+#### Web3Auth Initialization and Configuration
+
+```tsx
+useEffect(() => {
+ const initializeWeb3Auth = async () => {
+ try {
+ console.log('Fetching TON Testnet RPC endpoint...')
+ const testnetRpc = await getHttpEndpoint({
+ network: 'testnet',
+ protocol: 'json-rpc',
+ })
+
+ const chainConfig = {
+ chainNamespace: CHAIN_NAMESPACES.OTHER,
+ chainId: 'testnet',
+ rpcTarget: testnetRpc,
+ displayName: 'TON Testnet',
+ blockExplorerUrl: 'https://testnet.tonscan.org',
+ ticker: 'TON',
+ tickerName: 'Toncoin',
+ }
+
+ const privateKeyProvider = new CommonPrivateKeyProvider({
+ config: { chainConfig },
+ })
+
+ // Initialize Web3Auth
+ const web3authInstance = new Web3Auth({
+ clientId,
+ web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
+ usePnPKey: false,
+ privateKeyProvider,
+ })
+
+ setWeb3authSfa(web3authInstance)
+
+ console.log('Initializing Web3Auth...')
+ await web3authInstance.init()
+ console.log('Web3Auth initialized.')
+
+ setWeb3AuthInitialized(true)
+ } catch (error) {
+ console.error('Error fetching TON Testnet RPC endpoint: ', error)
+ }
+ }
+
+ initializeWeb3Auth()
+}, [])
+```
+
+- **Explanation**: This block initializes Web3Auth using the **Single Factor Authentication** method. We also fetch the TON blockchain's testnet RPC endpoint, which will allow us to connect to the network and retrieve blockchain data such as the wallet address.
+
+---
+
+### Step 5: Mocking Telegram Environments for Local Development
+
+Before we proceed with connecting to Web3Auth, we need to simulate the Telegram environment in local development. We achieve this by using the `useTelegramMock()` hook.
+
+#### Mocking Telegram Environment with `useTelegramMock.ts`
+
+```tsx
+/* eslint-disable camelcase */
+import { mockTelegramEnv, parseInitData, retrieveLaunchParams } from '@telegram-apps/sdk-react'
+
+/**
+ * Mocks
+
+ Telegram environment in development mode.
+ */
+export function useTelegramMock(): void {
+ if (process.env.NODE_ENV !== 'development') return
+
+ let shouldMock: boolean
+
+ try {
+ retrieveLaunchParams()
+ shouldMock = !!sessionStorage.getItem('____mocked')
+ } catch (e) {
+ shouldMock = true
+ }
+
+ if (shouldMock) {
+ const randomId = Math.floor(Math.random() * 1000000000)
+
+ const initDataRaw = new URLSearchParams([
+ [
+ 'user',
+ JSON.stringify({
+ id: randomId,
+ first_name: 'Andrew',
+ last_name: 'Rogue',
+ username: 'rogue',
+ language_code: 'en',
+ is_premium: true,
+ allows_write_to_pm: true,
+ }),
+ ],
+ ['hash', '89d6079ad6762351f38c6dbbc41bb53048019256a9443988af7a48bcad16ba31'],
+ ['auth_date', '1716922846'],
+ ['start_param', 'debug'],
+ ['chat_type', 'sender'],
+ ['chat_instance', '8428209589180549439'],
+ ]).toString()
+
+ mockTelegramEnv({
+ themeParams: {
+ accentTextColor: '#6ab2f2',
+ bgColor: '#17212b',
+ buttonColor: '#5288c1',
+ buttonTextColor: '#ffffff',
+ destructiveTextColor: '#ec3942',
+ headerBgColor: '#17212b',
+ hintColor: '#708499',
+ linkColor: '#6ab3f3',
+ secondaryBgColor: '#232e3c',
+ sectionBgColor: '#17212b',
+ sectionHeaderTextColor: '#6ab3f3',
+ subtitleTextColor: '#708499',
+ textColor: '#f5f5f5',
+ },
+ initData: parseInitData(initDataRaw),
+ initDataRaw,
+ version: '7.7',
+ platform: 'tdesktop',
+ })
+
+ sessionStorage.setItem('____mocked', '1')
+ }
+}
+```
+
+- **Explanation**: This hook mocks the Telegram environment by generating mock `initData` that mimics Telegram's launch parameters, ensuring that the app behaves as if it were running in an actual Telegram Mini App environment.
+
+:::tip **Why is Mocking Necessary?**
+
+Mocking the environment during local development ensures smooth testing. Without mocking, the Telegram SDK might throw errors or behave unexpectedly when not running within Telegram.
+
+:::
+
+---
+
+### Step 6: Connecting to Web3Auth and Fetching the ID Token
+
+Now, let's connect to Web3Auth and retrieve the ID token from our backend server, as configured in **[Part 1](/guides/telegram-miniapp-server)**.
+
+#### Connecting Web3Auth
+
+```tsx
+useEffect(() => {
+ const connectWeb3Auth = async () => {
+ if (web3authSfa && web3AuthInitialized && initDataRaw) {
+ setIsLoggingIn(true)
+ try {
+ if (web3authSfa.status === 'connected') {
+ await web3authSfa.logout()
+ }
+
+ const idToken = await getIdTokenFromServer(initDataRaw, initData.user.photoUrl) // Fetch ID token
+ const { payload } = decodeToken(idToken)
+
+ await web3authSfa.connect({
+ verifier,
+ verifierId: payload.sub,
+ idToken,
+ })
+
+ setUserData(payload)
+ setIsLoggedIn(true)
+
+ const tonRpc = new TonRPC(web3authSfa.provider)
+ const tonAddress = await tonRpc.getAccounts()
+ setTonAccountAddress(tonAddress)
+
+ const signedMsg = await tonRpc.signMessage('Hello, TON!')
+ setSignedMessage(signedMsg)
+ } catch (error) {
+ console.error('Error during Web3Auth connection:', error)
+ } finally {
+ setIsLoggingIn(false)
+ }
+ }
+ }
+
+ if (web3AuthInitialized && initDataRaw) {
+ connectWeb3Auth()
+ }
+}, [initDataRaw, web3authSfa, web3AuthInitialized])
+```
+
+- **Explanation**: This effect establishes a connection to Web3Auth using the ID token fetched from the backend. Once connected, we fetch the TON blockchain account details, including the account address and a signed message.
+
+---
+
+### Step 7: Display User and TON Account Information
+
+Finally, we display the user's Telegram profile details and their TON account address along with the signed message.
+
+```tsx
+const userInfoBox = (
+
+

+
+
+ ID: {userData?.telegram_id}
+
+
+ Username: {userData?.username}
+
+
+ Name: {userData?.name}
+
+
+
+)
+
+const tonAccountBox = (
+
+
+ TON Account: {tonAccountAddress}
+
+
+)
+
+const signedMessageBox = (
+
+
+ Signed Message: {signedMessage}
+
+
+)
+
+return (
+
+
Web3Auth TON Telegram MiniApp
+ {isLoggedIn ? (
+ <>
+ {userInfoBox}
+ {tonAccountBox}
+ {signedMessageBox}
+ >
+ ) : (
+
+ )}
+
+)
+```
+
+---
+
+### Step 8: Running and Testing the App
+
+To run the app locally:
+
+```bash
+npm run start
+```
+
+Ensure that the backend server from **[Part 1](/guides/telegram-miniapp-server)** is running and accessible via the `VITE_SERVER_URL`.
+
+For detailed steps on debugging your Telegram Mini App, refer to this [official guide](https://docs.ton.org/develop/dapps/telegram-apps/testing-apps).
+
+---
+
+### Step 9: Deploy Your App
+
+Deploy this app to GitHub Pages, Vercel, or any other hosting service. For Vercel:
+
+- Push your code to GitHub.
+- Sign in to [Vercel](https://vercel.com/).
+- Import your GitHub repository.
+- Deploy your project.
+
+After deployment, you will get a domain link. Use this link when setting up your Telegram bot.
+
+:::info
+
+Remember to whitelist the deployed client app's URL in the allowed origins array in the backend server CORS configuration that we set up in **[Part 1](/guides/telegram-miniapp-server)**.
+
+:::
+
+---
+
+### Step 10: Setting Up a Telegram Bot
+
+To connect your Mini App to Telegram, you need to **create a bot** and set up a Mini App for it.
+
+Follow these steps:
+
+1. **Start a Chat with BotFather**
+
+ - Open the Telegram app or web version.
+ - Search for `@BotFather` or follow the [link](https://t.me/BotFather).
+ - Start a chat with BotFather by clicking on the `START` button.
+
+2. **Create a New Bot**
+
+ - Send the `/newbot` command to BotFather.
+ - BotFather will ask you to choose a name for your bot (this is a display name and can contain spaces).
+ - Next, choose a unique username for your bot, which must end in "bot" (e.g., `sample_bot`).
+
+3. **Set Up Bot Mini App**
+
+ - Send the `/mybots` command to BotFather.
+ - Choose your bot from the list and select the "Bot Settings" option.
+ - Choose the "Menu Button" option.
+ - Choose "Edit Menu Button URL" and send the URL to your Telegram Mini App, for example, the link from GitHub Pages or Vercel deploy.
+
+4. **Accessing the Bot**
+ - You can now search for your bot using its username in Telegram's search bar.
+ - Press the button next to the attach picker to launch your Telegram Mini App in the messenger.
+
+---
+
+This completes the client-side setup for the Telegram Mini App. By following these steps, you can authenticate Telegram users, retrieve their TON blockchain account details, and allow them to interact with decentralized applications via Web3Auth.
diff --git a/src/pages/guides/telegram-miniapp-server.mdx b/src/pages/guides/telegram-miniapp-server.mdx
new file mode 100644
index 00000000000..e50a2df9289
--- /dev/null
+++ b/src/pages/guides/telegram-miniapp-server.mdx
@@ -0,0 +1,341 @@
+---
+title: 'Server-Side Setup for Telegram Mini App with Web3Auth'
+image: 'img/guides/guides-banners/telegram-miniapp-server.png'
+description: |
+ Learn how to set up a server for a Telegram Mini App using Web3Auth and validate Telegram login
+ data to generate JWT tokens. This guide is the first step in creating a Telegram Mini App with Web3Auth.
+type: guide
+tags: [embedded wallets, telegram, authentication, jwt, web3auth]
+date: October 24, 2024
+author: Web3Auth Team
+---
+
+import SEO from '@site/src/components/SEO'
+import TelegramMiniAppFlowDiagram from '@site/static/img/guides/telegram-mini-app-flow-diagram.png'
+
+
+
+:::tip Live Demo
+
+Before diving into development, experience Web3Auth in action! Check out our demo Telegram Mini App:
+
+👉 **[Launch Demo Mini App](https://t.me/w3a_tg_mini_app_bot)**
+
+:::
+
+:::info Source Code
+
+The backend example featured in this guide is part of a full working demo: [**Web3Auth Telegram Mini App Example**](https://github.com/Web3Auth/web3auth-core-kit-examples/tree/main/single-factor-auth-web/sfa-web-ton-telegram-example)
+
+:::
+
+### **Objectives**
+
+This guide is part of a two-part series aimed at helping you build a fully functioning Telegram Mini App that uses Web3Auth for decentralized authentication. By the end of this series, you will have:
+
+1. Set up a **backend server** that can handle Telegram authentication, validate the `initData`, and generate JWT tokens.
+2. Integrated the **Web3Auth** system into the **client-side app** to authenticate users and retrieve wallet details (e.g., TON blockchain addresses).
+
+By following these two guides, you will be able to securely authenticate Telegram users and allow them to interact with decentralized applications via their wallet on the TON blockchain.
+
+---
+
+### **Guide Breakdown**
+
+1. **Part 1 (Current Guide)**: Focuses on setting up the server-side logic to validate Telegram login data and generate JWT tokens.
+
+ - This will include setting up an Express server, handling Telegram login requests, validating `initData`, and generating JWT tokens for users.
+ - You will also see how to mock data during development for easy testing and debugging.
+
+2. **[Part 2](/guides/telegram-miniapp-client)**: Focuses on the client-side integration with Web3Auth, where you will use the JWT tokens generated in Part 1 to authenticate users and retrieve their wallet information from Web3Auth.
+
+ - You will implement the Web3Auth SDK and handle interactions between the Telegram Mini App and Web3Auth to access TON wallet details.
+
+---
+
+:::info Already completed this guide?
+
+You can continue to Part 2, where we implement the client-side app and integrate Web3Auth for authentication. [Go to Part 2](/guides/telegram-miniapp-client) to continue your journey in creating a working Telegram Mini App.
+
+:::
+
+---
+
+### Overview
+
+In this guide, we will set up a backend server for a Telegram Mini App using Telegram OAuth and Web3Auth for authentication. The server will validate the Telegram-provided `initData` and generate JWT tokens to securely authenticate users.
+
+
+
+Above is a visual flow diagram that shows how this process works from start to finish. You can visualize the interaction between the user, the Telegram client, the server, and Web3Auth.
+
+- The process starts when a user opens the Telegram Mini App.
+- Telegram provides `initData`, which includes user data and a signature.
+- The client forwards this data to the backend server for validation.
+- Once the server validates the `initData`, it generates a JWT token and returns it to the client.
+- Finally, the client uses the JWT token with Web3Auth to authenticate the user and obtain wallet details.
+
+By following this flow, you will enable users to authenticate seamlessly within the Telegram Mini App environment while allowing them access to their decentralized wallet information.
+
+---
+
+### **What You Will Learn:**
+
+1. Set up an Express server to handle Telegram Mini App authentication.
+2. Validate Telegram login data and generate JWT tokens.
+3. Use the `isMocked` parameter to bypass validation for local testing.
+
+---
+
+### Prerequisites
+
+- Basic knowledge of Node.js and Express.
+- A Telegram bot token (learn how to get one from the [Telegram Bot documentation](https://core.telegram.org/bots)).
+- Understanding of JWT authentication.
+
+---
+
+### Step 1: Install Required Packages
+
+```bash
+npm install express jsonwebtoken @telegram-apps/init-data-node dotenv cors
+```
+
+#### **Package Usage:**
+
+- **express**: Used to create and manage the server.
+- **jsonwebtoken**: Required for generating and verifying JWT tokens, which are essential for authenticating users.
+- **@telegram-apps/init-data-node**: Provides the utility to validate Telegram's `initData` to ensure data integrity and prevent tampering.
+- **dotenv**: Allows you to securely manage environment variables like your bot token and JWT secret.
+- **cors**: Used to configure Cross-Origin Resource Sharing (CORS), which ensures that your app can securely communicate with other domains like your front-end app.
+
+---
+
+### Step 2: Environment Variables Setup
+
+Create a `.env` file to store your sensitive data.
+
+```env
+NODE_ENV=development
+APP_URL="https://your-app-url.com"
+TELEGRAM_BOT_TOKEN=your_bot_token_here
+JWT_SECRET=your_secret_key
+JWT_KEY_ID=your_key_id
+```
+
+- The `NODE_ENV` is the environment in which the app is running.
+- The `APP_URL` is the URL of your deployed app.
+- The `JWT_SECRET` is the private key used to sign the JWT.
+- The `TELEGRAM_BOT_TOKEN` is the Telegram bot token.
+- The `JWT_KEY_ID` is a unique identifier in for the key used to sign the JWT. This ID helps Web3Auth locate the correct public key from your JWKS endpoint for token verification. It must match the `kid` value in your JWKS configuration.
+
+---
+
+### Step 3: Set Up the Express Server
+
+Let’s break down the code into smaller chunks to better understand each part:
+
+#### **Part 1: Basic Setup**
+
+```javascript
+const jwt = require('jsonwebtoken')
+const fs = require('fs')
+const express = require('express')
+const dotenv = require('dotenv')
+const path = require('path')
+const { validate } = require('@telegram-apps/init-data-node')
+
+dotenv.config()
+
+const app = express()
+app.use(express.json()) // Middleware to parse JSON requests
+const { TELEGRAM_BOT_TOKEN, JWT_KEY_ID, APP_URL } = process.env
+const privateKey = fs.readFileSync(path.resolve(__dirname, 'privateKey.pem'), 'utf8')
+```
+
+:::tip Where Do I Get the PEM File?
+
+The PEM file is a private key used for signing JSON Web Tokens (JWTs). If you're wondering how to generate or obtain this PEM file, follow the **BYO JWT guide** from Web3Auth. It explains how to create a custom JWT verifier and generate the necessary keys. You can find the guide here: [Custom JWT Providers](/docs/authentication/custom-connections/custom-jwt).
+
+This step is crucial if you're using your own custom login providers, as you'll need to register this verifier on the Web3Auth dashboard, which we will use in **[Part 2](/guides/telegram-miniapp-client)** when setting up the client-side app.
+
+:::
+
+This is the basic setup for your Express server. It reads your environment variables, sets up the required middleware for parsing JSON, and loads the private key that will be used for signing the JWT.
+
+---
+
+#### **Part 2: CORS Configuration**
+
+```javascript
+// Define allowed origins
+const allowedOrigins = [APP_URL]
+
+// CORS configuration
+app.use((req, res, next) => {
+ const origin = req.headers.origin
+ if (allowedOrigins.includes(origin)) {
+ res.setHeader('Access-Control-Allow-Origin', origin)
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
+ res.setHeader(
+ 'Access-Control-Allow-Headers',
+ 'Content-Type, Authorization, X-Requested-With, Accept'
+ )
+ res.setHeader('Access-Control-Allow-Credentials', 'true')
+ }
+
+ if (req.method === 'OPTIONS') {
+ res.setHeader(
+ 'Access-Control-Allow-Headers',
+ 'Content-Type, Authorization, X-Requested-With, Accept'
+ )
+ return res.sendStatus(204)
+ }
+ next()
+})
+```
+
+Here, we are configuring CORS (Cross-Origin Resource Sharing) to only allow requests from specific origins (your app’s URL). Be sure to add your app’s URL to the `allowedOrigins` array.
+
+:::tip
+
+After deploying your client-side app in **[Part 2](/guides/telegram-miniapp-client)**, don't forget to add its URL to the `allowedOrigins` array to ensure proper communication between the client and the server.
+
+:::
+
+---
+
+#### **Part 3: Rate Limiting**
+
+```javascript
+const RateLimit = require('express-rate-limit')
+
+const limiter = RateLimit({
+ windowMs: 15 * 60 * 1000, // 15 minutes
+ max: 100, // Max 100 requests per IP
+ message: 'Too many requests from this IP, please try again later.',
+})
+
+app.use(limiter)
+```
+
+This section sets up a rate limiter to prevent abuse by limiting the number of requests from the same IP address.
+
+:::tip Why Use a Rate Limiter and CORS Configuration?
+
+- **Rate Limiter**: Protects your server from being overwhelmed by too many requests in a short period, preventing abuse or DoS attacks. In this example, it limits each IP address to 100 requests every 15 minutes.
+
+- **CORS**: The Cross-Origin Resource Sharing (CORS) settings ensure only requests from your allowed origins (like your app's domain) can access the server. Don't forget to whitelist your app's origin by adding its address to the `allowedOrigins` array, ensuring the right domain is permitted.
+
+:::
+
+---
+
+#### **Part 4: Helper Function to Generate JWT Token**
+
+```javascript
+const generateJwtToken = userData => {
+ const payload = {
+ telegram_id: userData.id,
+ username: userData.username,
+ avatar_url: userData.photo_url || 'https://www.gravatar.com/avatar',
+ sub: userData.id.toString(),
+ name: userData.first_name,
+ iss: 'https://api.telegram.org',
+ iat: Math.floor(Date.now() / 1000),
+ exp: Math.floor(Date.now() / 1000) + 60 * 60, // Token valid for 1 hour
+ }
+ return jwt.sign(payload, privateKey, { algorithm: 'RS256', keyid: JWT_KEY_ID })
+}
+```
+
+This function creates a JWT using the `userData` and signs it with your private key. This JWT will be used for user authentication.
+
+---
+
+#### **Part 5: Routes**
+
+```javascript
+// Route 1: Test route to verify server is running
+app.get('/test', (req, res) => {
+ res.json({ message: 'Connection successful. Server is running!' })
+})
+```
+
+This route is just for testing whether the server is running successfully.
+
+```javascript
+// Route 2: Telegram authentication route
+app.post('/auth/telegram', async (req, res) => {
+ const { initDataRaw, isMocked, photoUrl } = req.body // Extract photoUrl from request body
+
+ if (!initDataRaw) {
+ return res.status(400).json({ error: 'initDataRaw is required' })
+ }
+
+ if (isMocked) {
+ // Handle mock data parsing
+ const data = new URLSearchParams(initDataRaw)
+ const user = JSON.parse(decodeURIComponent(data.get('user')))
+ const mockUser = {
+ id: user.id,
+ username: user.username,
+ photo_url: photoUrl || user.photo_url || 'https://www.gravatar.com/avatar',
+ first_name: user.first_name,
+ }
+ const JWTtoken = generateJwtToken(mockUser)
+ return res.json({ token: JWTtoken })
+ }
+
+ try {
+ // Validate the real initDataRaw using @telegram-apps/init-data-node
+ validate(initDataRaw, TELEGRAM_BOT_TOKEN)
+
+ // If validation is successful, parse the data
+ const data = new URLSearchParams(initDataRaw)
+ const user = JSON.parse(decodeURIComponent(data.get('user')))
+ const validatedUser = {
+ ...user,
+ photo_url: photoUrl || user.photo_url || 'https://www.gravatar.com/avatar',
+ }
+
+ // Generate the JWT token
+ const JWTtoken = generateJwtToken(validatedUser)
+ res.json({ token: JWTtoken })
+ } catch (error) {
+ console.error('Error validating Telegram data:', error)
+ res.status(400).json({ error: 'Invalid Telegram data' })
+ }
+})
+```
+
+This route handles the Telegram login process. If the data is mocked, it creates a mock user and generates a JWT. If not, it validates the `initData` using the `@telegram-apps/init-data-node` package.
+
+---
+
+### Step 4: Run the Server
+
+```bash
+node index.js
+```
+
+You can now run your server and verify its operation by sending requests to the `/test` or `/auth/telegram` routes.
+
+---
+
+Once you deploy your app (which you'll build in **[Part 2](/guides/telegram-miniapp-client)**), you can replace the `APP_URL` with your deployed app’s URL.
+
+For custom JWT login (getting the JWKS and more), follow the guide here: [Custom JWT Providers](https://web3auth.io/docs/authentication/custom-connections/custom-jwt). This will also help you create a verifier on the Web3Auth dashboard, which you'll use in **[Part 2](/guides/telegram-miniapp-client)**.
+
+---
+
+This guide sets up the server-side logic for validating Telegram logins and generating JWT tokens. To continue the journey, head over to [Part 2](/guides/telegram-miniapp-client), where we integrate Web3Auth into the client-side app for a complete solution.
diff --git a/src/pages/guides/telegram.mdx b/src/pages/guides/telegram.mdx
new file mode 100644
index 00000000000..787af9da4d2
--- /dev/null
+++ b/src/pages/guides/telegram.mdx
@@ -0,0 +1,496 @@
+---
+title: How to use Telegram OAuth with Web3Auth
+image: 'img/guides/guides-banners/telegram-oauth.png'
+description: Learn how to seamlessly integrate Telegram Login with Web3Auth to enhance your app's authentication capabilities.
+type: guide
+tags: [embedded wallets, telegram, oauth, telegram login widget, authentication, telegram login, telegram oauth, web3auth]
+date: August 15, 2024
+author: Web3Auth Team
+---
+
+import SEO from '@site/src/components/SEO'
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+
+
+This guide will explain the basic steps of integrating the [Telegram Login Widget](https://core.telegram.org/widgets/login) _aka_ Telegram OAuth with Web3Auth for authentication. In this guide, you will learn how to create a Telegram bot, generate a JWKS file, and establish a custom JWT verifier on Web3Auth. Finally, we will demonstrate how to implement the Telegram OAuth flow for user authentication and generate Ethereum/Solana keys using [Web3Auth Plug and Play](https://web3auth.io/docs/sdk/web/install) and [Single Factor Auth](https://web3auth.io/docs/sdk/sfa/sfa-js/install) SDKs.
+
+:::note TLDR;
+
+1. [Create a Telegram bot](https://core.telegram.org/bots/features#creating-a-new-bot) and [generate an API Token](https://core.telegram.org/bots/features#generating-an-authentication-token).
+2. [Create a JWKS file for your public key used for JWT signing](/docs/authentication/custom-connections/custom-jwt/#how-to-convert-pem-to-jwks) and host it on a public endpoint.
+3. [Set up a Telegram custom JWT verifier](/docs/authentication/social-logins/oauth) for Telegram on the Web3Auth Dashboard.
+4. Implement the Telegram OAuth flow for user authentication.
+5. Use user data from Telegram to generate the JWT token.
+6. Pass the JWT token to Web3Auth for generating Ethereum/Solana keys using the Web3Auth Plug and Play and Single Factor Auth Mobile SDKs.
+
+:::
+
+:::info Important Links
+
+- Telegram Login example with Web3Auth PnP SDK
+ - [GitHub Repository](https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/web-no-modal-sdk/custom-authentication/single-verifier-examples/telegram-no-modal-example)
+ - [Live Demo](https://telegram-no-modal-example.vercel.app)
+- Telegram Login example with Web3Auth SFA Node SDK
+ - [GitHub Repository](https://github.com/Web3Auth/web3auth-core-kit-examples/tree/main/single-factor-auth-node/sfa-telegram-oauth-server)
+- Telegram Login example with Web3Auth SFA JS SDK
+ - [GitHub Repository](https://github.com/Web3Auth/web3auth-core-kit-examples/tree/main/single-factor-auth-web/sfa-web-telegram-example)
+
+:::
+
+## How it works?
+
+When a user clicks on the Telegram Login Widget, it initiates the Telegram OAuth flow. The widget will prompt the user to log in to their Telegram account and grant permission for the application to access their Telegram data. Once the user logs in, the Telegram API will send the user data to the specified callback URL in the Telegram Login Widget. The callback URL, with the help of the backend server, will then create a JWT token using the user data and send it to the application's frontend. The frontend will then send the JWT token to the Web3Auth SDK, which will use it to generate Ethereum or Solana keys.
+
+## Prerequisites
+
+1. [Telegram bot](https://core.telegram.org/bots/features#creating-a-new-bot) with [an API Token](https://core.telegram.org/bots/features#generating-an-authentication-token).
+2. [Custom JWT verifier for Telegram](https://web3auth.io/docs/authentication/social-logins/oauth)
+
+## Express server for Telegram OAuth
+
+To set up an Express server to manage the Telegram OAuth flow, you will need to create three routes:
+
+1. `/` - This route will simply check if the server is running.
+
+2. `/login` - Use this route to display the login page with the Telegram Login Widget.
+
+3. `/callback` - This route will manage the Telegram OAuth callback and generate the JWT.
+
+In order to build the server, you will use the `express`, `jsonwebtoken`, and `@telegram-auth/server` packages. The `generateJwtToken` function will be used to create a JWT token based on the user data received from Telegram. The `/callback` route will validate the Telegram data using the `AuthDataValidator` class and generate the JWT token, which will then be sent to the frontend.
+
+**What each packages do**:
+
+- `express` - A Node.js web application framework that provides a robust set of features for web and mobile applications.
+
+- `jsonwebtoken` - An implementation of JSON Web Tokens (JWT) to generate and verify JWT tokens.
+
+- `@telegram-auth/server` - A package that provides a utility class to validate the Telegram data received from the Telegram Login Widget.
+
+The server will utilize the `login.html` file to display the Telegram Login Widget. This HTML file will dynamically create the Telegram Login Widget using the Telegram bot username and the callback URL.
+
+A few important points:
+
+- Ensure that the private key matches the one generated during the JWKS setup phase.
+
+- The `JWT_KEY_ID` should be identical to the one specified during the JWKS setup phase and should be present in the JWKS file.
+
+
+
+
+
+```js title="server.js"
+const express = require('express')
+const app = express()
+const { resolve } = require('path')
+const jwt = require('jsonwebtoken')
+const fs = require('fs')
+const { AuthDataValidator } = require('@telegram-auth/server')
+const { objectToAuthDataMap } = require('@telegram-auth/server/utils')
+
+// Read the private key for JWT signing (Ensure you specify the correct path to the private key file)
+const privateKey = fs.readFileSync('/path/to/privateKey.pem', 'utf8')
+
+const generateJwtToken = userData => {
+ const payload = {
+ telegram_id: userData.id,
+ username: userData.username,
+ avatar_url: userData.photo_url,
+ sub: userData.id.toString(),
+ name: userData.first_name,
+ iss: 'https://api.telegram.org', // Issuer
+ iat: Math.floor(Date.now() / 1000),
+ exp: Math.floor(Date.now() / 1000) + 60 * 60, // 1 hour expiration, can lower or increase as needed
+ }
+
+ return jwt.sign(payload, privateKey, { algorithm: 'RS256', keyid: 'JWT_KEY_ID' })
+}
+
+app.get('/', (req, res) => res.send('Express Server for Telegram Login to be used with Web3Auth'))
+
+app.get('/login', (req, res) => {
+ res.sendFile(resolve(__dirname, 'login.html'))
+})
+
+app.get('/callback', async (req, res) => {
+ const validator = new AuthDataValidator({ botToken: process.env.TELEGRAM_BOT_API_TOKEN }) // Use environment variable for bot token
+ const data = objectToAuthDataMap(req.query || {})
+
+ try {
+ const user = await validator.validate(data)
+ const JWTtoken = generateJwtToken(user)
+
+ const redirectUrl = `${process.env.FRONTEND_URL}?token=${JWTtoken}` // Use environment variable for frontend URL
+ res.redirect(redirectUrl)
+ } catch (error) {
+ console.error('Error validating Telegram data:', error)
+ res.status(400).send('Invalid Telegram data')
+ }
+})
+
+// Port 3000 or environment variable for port if deployed on a different service
+const PORT = process.env.PORT || 3000
+app.listen(PORT, () => console.log(`Server ready on port ${PORT}.`))
+
+module.exports = app
+```
+
+
+
+
+
+```html title="login.html"
+
+
+
+ Telegram OAuth App with Web3Auth
+
+
+
+
+
+
+
+```
+
+
+
+
+
+**_Please note that the Telegram OAuth flow will not work in localhost_**. To test the Telegram OAuth flow, you'll need to deploy the server to a public endpoint. Alternatively, you can use a service like [ngrok](https://ngrok.com/) to create a public URL for your localhost.
+
+For your convenience, we have deployed the server to [Vercel](https://vercel.com/guides/using-express-with-vercel). You can find the server code [here](https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/web-no-modal-sdk/custom-authentication/single-verifier-examples/telegram-no-modal-example/server) and the live demo [here](https://telegram-no-modal-server.vercel.app/login).
+
+## Edit Telegram Bot to set the domain
+
+To ensure that the Telegram Login Widget works correctly, you will need to set the domain of your server.
+
+Check this guide on editing the Telegram Bot at https://core.telegram.org/bots/features#edit-bots to set the domain.
+
+1. Simply select your Bot from the BotFather and click on the `Bot Settings` option.
+2. Then, click on the `Domain` option, and click on `Set Domain` to enter the domain of your server.
+3. You will see a message saying `Success! Domain updated.`
+
+ 
+
+## Using Telegram Login with Web3Auth
+
+The Telegram OAuth server mentioned above will authenticate users and generate a JWT token. This token can be utilized with Web3Auth's Plug and Play SDK or Single Factor Auth SDK. In the upcoming sections, we will illustrate how to use the Web3Auth SDKs with the JWT token.
+
+### Web3Auth Plug and Play SDK
+
+To use the Web3Auth Plug and Play SDK with the Telegram OAuth flow, you'll need to first configure Web3Auth based on your project and Telegram verifier. Then, initiate the login by redirecting the user to the `/login` route of your Express server. After the user logs in and is redirected back to the frontend, you can extract the JWT token from the URL and pass it to the Web3Auth SDK to initiate the login process with Web3Auth.
+
+#### Set up the Web3Auth PnP SDK
+
+[Install the PnP packages](https://web3auth.io/docs/sdk/web/install) and then import it and configure the Web3Auth PnP No Modal SDK with the Telegram verifier.
+
+```js
+import { Web3AuthNoModal } from '@web3auth/no-modal'
+import { EthereumPrivateKeyProvider } from '@web3auth/ethereum-provider'
+import {
+ WALLET_ADAPTERS,
+ CHAIN_NAMESPACES,
+ IProvider,
+ UX_MODE,
+ WEB3AUTH_NETWORK,
+} from '@web3auth/base'
+import { AuthAdapter } from '@web3auth/auth-adapter'
+
+const clientId =
+ 'BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ' // get from https://dashboard.web3auth.io
+
+const chainConfig = {
+ chainNamespace: CHAIN_NAMESPACES.EIP155,
+ chainId: '0x1', // Please use 0x1 for Mainnet
+ rpcTarget: 'https://rpc.ethereum.org',
+ displayName: 'Ethereum Mainnet',
+ blockExplorerUrl: 'https://etherscan.io/',
+ ticker: 'ETH',
+ tickerName: 'Ethereum',
+ logo: 'https://cryptologos.cc/logos/ethereum-eth-logo.png',
+}
+
+const privateKeyProvider = new EthereumPrivateKeyProvider({ config: { chainConfig } })
+
+const web3auth = new Web3AuthNoModal({
+ clientId,
+ web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
+ privateKeyProvider,
+})
+
+const authAdapter = new AuthAdapter({
+ adapterSettings: {
+ uxMode: UX_MODE.REDIRECT,
+ loginConfig: {
+ jwt: {
+ // focus-next-line
+ verifier: 'w3a-telegram-oauth-demo', // Replace with your verifier name
+ typeOfLogin: 'jwt',
+ clientId,
+ },
+ },
+ },
+})
+web3auth.configureAdapter(authAdapter)
+
+await web3auth?.init()
+```
+
+#### Initiate the Telegram OAuth flow
+
+Redirect the user to the `/login` route of your Express server to initiate the Telegram OAuth flow.
+
+```js
+const login = async () => {
+ window.location.href = `${SERVER_URL}/login`
+ // e.g https://w3a-telegram-server.vercel.app/login
+}
+```
+
+#### Extract the JWT token from the URL
+
+Extract the JWT token from the URL and pass it to the Web3Auth SDK to initiate the login process and then reset the URL state to remove the token.
+
+```js
+useEffect(() => {
+ const params = new URLSearchParams(window.location.search)
+ const jwtToken = params.get('token')
+ if (jwtToken) {
+ // focus-next-line
+ loginWithWeb3Auth(jwtToken)
+ window.history.replaceState({}, document.title, window.location.pathname)
+ }
+}, [])
+```
+
+#### Login with Web3Auth using the JWT token
+
+Use the JWT token in the `connectTo()` method to initiate the login process with Web3Auth with the verifierIdField set to `sub` or any other field based on the verifier's configuration.
+
+```js
+const loginWithWeb3Auth = async (token: string) => {
+ await web3auth?.init();
+ const web3authProvider = await web3auth?.connectTo(WALLET_ADAPTERS.AUTH, {
+ loginProvider: "jwt",
+ extraLoginOptions: {
+ // focus-next-line
+ id_token: token,
+ verifierIdField: "sub", // Based on the verifier's verifierIdField
+ },
+ });
+};
+```
+
+The above code snippets demonstrate how to use the Web3Auth Plug and Play SDK with the Telegram OAuth flow. You can find the complete example code in [this GitHub repository](https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/web-no-modal-sdk/custom-authentication/single-verifier-examples/telegram-no-modal-example).
+
+### Web3Auth Single Factor Auth SDK
+
+To use the Web3Auth Single Factor Auth SDK with the Telegram OAuth flow, there could be two ways to use it:
+
+1. Using the Web3Auth Single Factor Auth SDK in the Node environment.
+2. Using the Web3Auth Single Factor Auth SDK in the browser environment.
+
+#### Using the Web3Auth Single Factor Auth SDK in the Node environment
+
+To use the Web3Auth Single Factor Auth SDK in the Node environment, you'll need to first configure the SFA Node SDK with the Web3Auth project and Telegram verifier details. Then, initiate the login by calling the `connect` method with the verifier details along with the JWT token.
+
+#### Set up the Web3Auth SFA Node SDK
+
+[Install the SFA Node packages](https://web3auth.io/docs/sdk/sfa/sfa-js/install) and then import it and configure the Web3Auth SFA Node SDK with the Telegram verifier.
+
+Note: For this, you can continue to use the Express server setup from the previous section. Simply update with the below code snippet.
+
+```js
+const { Web3Auth } = require('@web3auth/node-sdk')
+const { EthereumPrivateKeyProvider } = require('@web3auth/ethereum-provider')
+
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ config: {
+ chainConfig: {
+ chainId: '0x1',
+ rpcTarget: 'https://rpc.ethereum.org',
+ displayName: 'Ethereum Mainnet',
+ blockExplorer: 'https://etherscan.io',
+ ticker: 'ETH',
+ tickerName: 'Ethereum',
+ },
+ },
+})
+
+const web3auth = new Web3Auth({
+ clientId:
+ 'BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ', // Get your Client ID from the Web3Auth Dashboard
+ web3AuthNetwork: 'sapphire_mainnet',
+ usePnPKey: false, // Setting this to true returns the same key as PnP Web SDK, By default, this SDK returns CoreKitKey.
+})
+web3auth.init({ provider: privateKeyProvider })
+```
+
+#### Initiate the Telegram OAuth flow
+
+The "/login" route will start the Telegram OAuth flow. The code snippet remains the same for this part. When handling the "/callback" route, update the function to utilize the "getPrivateKey()" function for generating the Ethereum private key. "getPrivateKey()" is a helper function that uses the JWT token and Telegram user ID to produce the Ethereum private key. This is necessary because we are working in a server environment and don't have access to web3 libraries at the server level. Therefore, we are using a provider to obtain the Ethereum private and public keys. For simplicity, we are logging the Ethereum private key and public address to the express server, but you can customize this according to your needs.
+
+Here's the updated code snippet:
+
+```js
+app.get('/login', (req, res) => {
+ res.sendFile(resolve(__dirname, 'login.html'))
+})
+
+app.get('/callback', async (req, res) => {
+ const validator = new AuthDataValidator({ botToken: process.env.TELEGRAM_BOT_API_TOKEN }) // Use environment variable for bot token
+ const data = objectToAuthDataMap(req.query || {})
+
+ try {
+ const user = await validator.validate(data)
+ const JWTtoken = generateJwtToken(user)
+ // getPriavteKey function is defined below
+ // focus-next-line
+ const ethData = await getPrivateKey(JWTtoken, user.id.toString())
+ // Use ethData as per your requirement
+ console.log('Ethereum Data:', ethData)
+ res.json('Ethereum Data is generated on your server.')
+ } catch (error) {
+ console.error('Error validating Telegram data:', error)
+ res.status(400).send('Invalid Telegram data')
+ }
+})
+```
+
+#### Generate Ethereum private key
+
+Use the provider to generate the Ethereum private key using the JWT token and the Telegram user ID.
+
+```js
+const getPrivateKey = async (idToken, verifierId) => {
+ const web3authNodeprovider = await web3auth.connect({
+ verifier: 'WEB3AUTH_VERIFIER_NAME', // Replace with your verifier name
+ verifierId,
+ idToken,
+ })
+
+ const ethPrivateKey = await web3authNodeprovider.request({ method: 'eth_private_key' })
+ const ethPublicAddress = await web3authNodeprovider.request({ method: 'eth_accounts' })
+ const ethData = {
+ ethPrivateKey,
+ ethPublicAddress,
+ }
+ return ethData
+}
+```
+
+The above code snippets demonstrate how to use the Web3Auth SFA Node SDK with the Telegram OAuth flow. You can find the complete example code in [this GitHub repository](https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/web-no-modal-sdk/custom-authentication/single-verifier-examples/telegram-no-modal-example).
+
+#### Using the Web3Auth Single Factor Auth SDK in the browser environment
+
+To use the Web3Auth Single Factor Auth SDK in the browser environment, you'll need to first configure the SFA JS SDK with the Web3Auth project and Telegram verifier details. Then, initiate the login by calling the `connect` method with the verifier details along with the JWT token.
+
+#### Set up the Web3Auth SFA JS SDK
+
+[Install the SFA JS packages](https://web3auth.io/docs/sdk/sfa/sfa-js/install) and then import it and configure the Web3Auth SFA JS SDK with the Telegram verifier in your React or any other frontend project.
+
+```js
+import { CHAIN_NAMESPACES, WEB3AUTH_NETWORK } from '@web3auth/base'
+import { Web3Auth, decodeToken } from '@web3auth/single-factor-auth'
+import { EthereumPrivateKeyProvider } from '@web3auth/ethereum-provider'
+
+const chainConfig = {
+ chainId: '0x1',
+ displayName: 'Ethereum Mainnet',
+ chainNamespace: CHAIN_NAMESPACES.EIP155,
+ tickerName: 'Ethereum',
+ ticker: 'ETH',
+ decimals: 18,
+ rpcTarget: 'https://rpc.ethereum.org',
+ blockExplorerUrl: 'https://etherscan.io',
+}
+
+const ethereumPrivateKeyProvider = new EthereumPrivateKeyProvider({
+ config: { chainConfig },
+})
+
+const web3auth = new Web3Auth({
+ clientId:
+ 'BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ', // Get your Client ID from the Web3Auth Dashboard
+ web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
+ usePnPKey: false, // Setting this to true returns the same key as PnP Web SDK, By default, this SDK returns CoreKitKey.
+ privateKeyProvider: ethereumPrivateKeyProvider,
+})
+
+await web3auth.init()
+```
+
+#### Initiate the Telegram OAuth flow
+
+The `/login` route will initiate the Telegram OAuth flow. The `/callback` will handle the Telegram OAuth callback and generate the JWT token. The code snippet remains the same for both routes from the [Express server setup section](#express-server-for-telegram-oauth).
+
+#### Extract the JWT token from the URL
+
+Extract the JWT token from the URL and pass it to the Web3Auth SDK to initiate the login process and then reset the URL state to remove the token.
+
+```js
+useEffect(() => {
+ const params = new URLSearchParams(window.location.search)
+ const jwtToken = params.get('token')
+ if (jwtToken) {
+ // focus-next-line
+ loginWithWeb3Auth(jwtToken)
+ window.history.replaceState({}, document.title, window.location.pathname)
+ }
+}, [])
+```
+
+#### Login with Web3Auth SFA JS using the JWT token
+
+Use the JWT token in the `connect()` method to initiate the login process with Web3Auth SFA JS SDK.
+
+```js
+const loginWithWeb3Auth = async (token: string) => {
+ const decodedToken = decodeToken(token);
+ const verifierId = decodedToken.sub;
+ // focus-next-line
+ const web3authProvider = await web3auth.connect({
+ verifier: "WEB3AUTH_VERIFIER_NAME", // Replace with your verifier name
+ verifierId,
+ idToken: token,
+ });
+};
+```
+
+The above code snippets demonstrate how to use the Web3Auth SFA JS SDK with the Telegram OAuth flow. You can find the complete example code in [this GitHub repository](https://github.com/Web3Auth/web3auth-pnp-examples/tree/main/web-no-modal-sdk/custom-authentication/single-verifier-examples/telegram-no-modal-example).
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 0570b0e8229..d66f3c0d184 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -15,73 +15,71 @@ export default function Home(): JSX.Element {
description="Build with the world's leading self-custodial crypto wallet."
button={{
label: 'Get Started',
- href: '/sdk',
+ href: '/quickstart',
icon: 'arrow-right',
}}
/>
-
+
+
+
+
+
-
-
diff --git a/src/pages/quickstart/MediaStep/MediaStep.module.css b/src/pages/quickstart/MediaStep/MediaStep.module.css
new file mode 100644
index 00000000000..0296fcfb47d
--- /dev/null
+++ b/src/pages/quickstart/MediaStep/MediaStep.module.css
@@ -0,0 +1,269 @@
+/* Media Step Container */
+.mediaContainer {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ background: var(--ifm-background-surface-color);
+ border-radius: 12px;
+ overflow: hidden;
+ position: relative;
+}
+
+/* Media Content */
+.mediaContent {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ position: relative;
+ transition: opacity 0.3s ease;
+}
+
+.mediaContent.hidden {
+ opacity: 0;
+ pointer-events: none;
+}
+
+/* YouTube Player */
+.youtubePlayer {
+ width: 100%;
+ height: 400px;
+ min-height: 300px;
+ border-radius: 8px;
+ border: none;
+ background: #000;
+ aspect-ratio: 16/9;
+}
+
+/* Video Player */
+.videoPlayer {
+ width: 100%;
+ height: auto;
+ max-height: 100%;
+ object-fit: contain;
+ background: #000;
+ border-radius: 8px;
+}
+
+/* Image Display */
+.imageDisplay {
+ width: 100%;
+ height: auto;
+ max-height: 100%;
+ object-fit: contain;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+/* Media Caption */
+.mediaCaption {
+ padding: 1rem;
+ background: var(--ifm-color-emphasis-50);
+ border-top: 1px solid var(--ifm-color-emphasis-200);
+ margin-top: auto;
+}
+
+.mediaCaption p {
+ margin: 0;
+ font-size: 14px;
+ line-height: 1.5;
+ color: var(--ifm-color-content-secondary);
+ text-align: center;
+}
+
+/* Placeholder State */
+.mediaPlaceholder {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 300px;
+ gap: 1rem;
+ color: var(--ifm-color-content-secondary);
+ border: 2px dashed var(--ifm-color-emphasis-300);
+ border-radius: 8px;
+ margin: 1rem;
+}
+
+.placeholderIcon {
+ font-size: 48px;
+}
+
+.loadButton {
+ padding: 0.75rem 1.5rem;
+ background: var(--ifm-color-primary);
+ color: white;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: 500;
+ transition: all 0.2s ease;
+}
+
+.loadButton:hover {
+ background: var(--ifm-color-primary-dark);
+ transform: translateY(-1px);
+}
+
+.mediaPlaceholder p {
+ margin: 0;
+ font-size: 16px;
+ color: var(--ifm-color-content-secondary);
+}
+
+/* Loading State */
+.mediaLoading {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 300px;
+ gap: 1rem;
+ color: var(--ifm-color-content-secondary);
+}
+
+.loadingSpinner {
+ width: 32px;
+ height: 32px;
+ border: 3px solid var(--ifm-color-emphasis-300);
+ border-top: 3px solid var(--ifm-color-primary);
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+.mediaLoading p {
+ margin: 0;
+ font-size: 14px;
+ color: var(--ifm-color-content-secondary);
+}
+
+/* Error State */
+.mediaError {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 300px;
+ gap: 1rem;
+ padding: 2rem;
+ text-align: center;
+ color: var(--ifm-color-content-secondary);
+}
+
+.errorIcon {
+ font-size: 48px;
+}
+
+.mediaError p {
+ margin: 0;
+ font-size: 16px;
+ color: var(--ifm-color-content-secondary);
+}
+
+.retryButton {
+ padding: 0.5rem 1rem;
+ background: var(--ifm-color-primary);
+ color: white;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ font-size: 14px;
+ transition: background-color 0.2s ease;
+}
+
+.retryButton:hover {
+ background: var(--ifm-color-primary-dark);
+}
+
+/* Play Status Indicator */
+.playStatus {
+ position: absolute;
+ top: 1rem;
+ right: 1rem;
+ opacity: 0;
+ transform: translateY(-10px);
+ transition: all 0.3s ease;
+ pointer-events: none;
+}
+
+.playStatus.visible {
+ opacity: 1;
+ transform: translateY(0);
+}
+
+.playIndicator {
+ background: rgba(0, 0, 0, 0.7);
+ color: white;
+ padding: 0.5rem 1rem;
+ border-radius: 20px;
+ font-size: 12px;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ backdrop-filter: blur(4px);
+}
+
+/* Playing state effects */
+.mediaContent.playing .videoPlayer {
+ box-shadow: 0 0 20px rgba(var(--ifm-color-primary-rgb), 0.3);
+}
+
+/* Responsive Design */
+@media (max-width: 768px) {
+ .mediaContainer {
+ border-radius: 8px;
+ }
+
+ .youtubePlayer {
+ height: 250px;
+ min-height: 200px;
+ }
+
+ .mediaCaption {
+ padding: 0.75rem;
+ }
+
+ .mediaCaption p {
+ font-size: 13px;
+ }
+
+ .mediaLoading,
+ .mediaError,
+ .mediaPlaceholder {
+ height: 200px;
+ padding: 1rem;
+ }
+
+ .errorIcon,
+ .placeholderIcon {
+ font-size: 36px;
+ }
+}
+
+/* Dark Mode Adjustments */
+[data-theme='dark'] .mediaCaption {
+ background: var(--ifm-color-emphasis-100);
+ border-top-color: var(--ifm-color-emphasis-300);
+}
+
+[data-theme='dark'] .loadingSpinner {
+ border-color: var(--ifm-color-emphasis-400);
+ border-top-color: var(--ifm-color-primary);
+}
+
+[data-theme='dark'] .playIndicator {
+ background: rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(8px);
+}
\ No newline at end of file
diff --git a/src/pages/quickstart/MediaStep/index.tsx b/src/pages/quickstart/MediaStep/index.tsx
new file mode 100644
index 00000000000..aabb67186b2
--- /dev/null
+++ b/src/pages/quickstart/MediaStep/index.tsx
@@ -0,0 +1,180 @@
+import React, { useState, useEffect, useRef, useCallback } from 'react';
+import classNames from 'classnames';
+import { IntegrationStep } from '../interfaces';
+import styles from './MediaStep.module.css';
+
+interface MediaStepProps {
+ step: IntegrationStep;
+ className?: string;
+ isVisible?: boolean; // Add visibility prop for lazy loading
+}
+
+const MediaStep: React.FC = ({ step, className, isVisible = true }) => {
+ const [isLoading, setIsLoading] = useState(true); // Start loading immediately
+ const [hasError, setHasError] = useState(false);
+ const [isPlaying, setIsPlaying] = useState(false);
+ const videoRef = useRef(null);
+ const imageRef = useRef(null);
+
+ if (!step.mediaContent) {
+ return (
+
+
+
No media content available
+
+
+ );
+ }
+
+ const { type, url, youtubeId, alt, caption, poster, autoplay = false, loop = false, muted = true } = step.mediaContent;
+
+ const handleLoad = useCallback(() => {
+ setIsLoading(false);
+ setHasError(false);
+ }, []);
+
+ const handleError = useCallback(() => {
+ setIsLoading(false);
+ setHasError(true);
+ }, []);
+
+ const handlePlay = useCallback(() => {
+ setIsPlaying(true);
+ }, []);
+
+ const handlePause = useCallback(() => {
+ setIsPlaying(false);
+ }, []);
+
+
+
+
+
+ // Reset when URL changes
+ useEffect(() => {
+ setIsLoading(true);
+ setHasError(false);
+ setIsPlaying(false);
+ }, [url]);
+
+ const renderMedia = () => {
+
+ if (type === 'youtube') {
+ const youtubeUrl = `https://www.youtube.com/embed/${youtubeId}?rel=0&modestbranding=1&showinfo=0${autoplay ? '&autoplay=1' : ''}${muted ? '&mute=1' : ''}`;
+
+ return (
+
+ );
+ }
+
+ if (type === 'video') {
+ return (
+
+ );
+ }
+
+ if (type === 'image') {
+ return (
+
+ );
+ }
+
+ return null;
+ };
+
+ return (
+
+
+
+ {/* Loading State */}
+ {isLoading && !hasError && (
+
+
+
Loading {type === 'youtube' ? 'YouTube video' : type}...
+
+ )}
+
+ {/* Error State */}
+ {hasError && (
+
+
⚠️
+
Failed to load {type === 'youtube' ? 'YouTube video' : type}
+
+
+ )}
+
+ {/* Media Content */}
+
+ {renderMedia()}
+
+ {/* Caption */}
+ {caption && !isLoading && !hasError && (
+
+ )}
+
+ {/* Video Play Status Indicator */}
+ {type === 'video' && !isLoading && !hasError && (
+
+ )}
+
+
+ );
+};
+
+// Memoize the component to prevent unnecessary re-renders
+export default React.memo(MediaStep);
\ No newline at end of file
diff --git a/src/pages/quickstart/NavigationOverlay/NavigationFlow.tsx b/src/pages/quickstart/NavigationOverlay/NavigationFlow.tsx
new file mode 100644
index 00000000000..bea9711fc8d
--- /dev/null
+++ b/src/pages/quickstart/NavigationOverlay/NavigationFlow.tsx
@@ -0,0 +1,153 @@
+import React, { useState } from 'react';
+import clsx from 'clsx';
+import Link from '@docusaurus/Link';
+import Heading from '@theme/Heading';
+import { useColorMode } from '@docusaurus/theme-common';
+import CutOffCorners from '@site/src/components/elements/cut-off-corners';
+import Button from '@site/src/components/elements/buttons/button';
+import SvgStar from '@site/static/img/icons/star.svg';
+import Shape from '@site/static/img/shapes/intro-cards/shape.svg';
+import styles from './NavigationOverlay.module.css';
+import {
+ METAMASK_SDK,
+ EMBEDDED_WALLETS
+} from '../builder/choices';
+
+interface NavigationOption {
+ id: string;
+ title: string;
+ description: string;
+ product?: string;
+ link?: string;
+}
+
+interface NavigationFlowProps {
+ onSelect: (product: string) => void;
+}
+
+const navigationOptions: NavigationOption[] = [
+ {
+ id: 'mm-sdk',
+ title: "I want to connect to users' MetaMask Wallet",
+ description: "MetaMask SDK",
+ product: METAMASK_SDK
+ },
+ {
+ id: 'embedded-wallets-1',
+ title: "I want to create wallets inside my dApp/ Mobile App",
+ description: "Embedded Wallets",
+ product: EMBEDDED_WALLETS
+ },
+ {
+ id: 'embedded-wallets-2',
+ title: "I want a Wallet Aggregator for my dApp",
+ description: "Embedded Wallets",
+ product: EMBEDDED_WALLETS
+ },
+ {
+ id: 'delegation-toolkit-1',
+ title: "I want to manage Gasless Transactions",
+ description: "Delegation Toolkit",
+ link: "/delegation-toolkit"
+ },
+ {
+ id: 'delegation-toolkit-2',
+ title: "I want to Delegate Permission for my users",
+ description: "Delegation Toolkit",
+ link: "/delegation-toolkit"
+ },
+ {
+ id: 'delegation-toolkit-3',
+ title: "I want to convert EOAs to Smart Wallets",
+ description: "Delegation Toolkit",
+ link: "/delegation-toolkit"
+ },
+ {
+ id: 'delegation-toolkit-4',
+ title: "I want to request Readable Permissions",
+ description: "Delegation Toolkit",
+ link: "/delegation-toolkit"
+ },
+];
+
+const NavigationFlow: React.FC = ({ onSelect }) => {
+ const { colorMode } = useColorMode();
+ const [hoveredCard, setHoveredCard] = useState(null);
+
+ const handleOptionSelect = (option: NavigationOption) => {
+ if (option.product) {
+ onSelect(option.product);
+ } else if (option.link) {
+ window.location.href = option.link;
+ }
+ };
+
+ return (
+
+
+
What would you like to do?
+
Choose the option that best describes your project goals:
+
+
+
+ {navigationOptions.map((option) => (
+
+
+
+ setHoveredCard(option.id)}
+ onMouseLeave={() => setHoveredCard(null)}
+ onClick={() => handleOptionSelect(option)}
+ >
+
+
+
+
+
+ {option.title}
+
+
+
+
+
+ {option.description}
+
+
+
+
+
+
+
+
+ ))}
+
+
+ {/*
+
Quick Links
+
+
+ 📖 MetaMask SDK Docs
+
+
+ 💳 Embedded Wallets Docs
+
+
+ ⚡ Delegation Toolkit Docs
+
+
+
*/}
+
+ );
+};
+
+export default NavigationFlow;
\ No newline at end of file
diff --git a/src/pages/quickstart/NavigationOverlay/NavigationOverlay.module.css b/src/pages/quickstart/NavigationOverlay/NavigationOverlay.module.css
new file mode 100644
index 00000000000..4838e41f7b6
--- /dev/null
+++ b/src/pages/quickstart/NavigationOverlay/NavigationOverlay.module.css
@@ -0,0 +1,548 @@
+/* Overlay Container - Full layover covering entire builder */
+.overlayContainer {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: var(--ifm-background-surface-color);
+ z-index: 100;
+ animation: fadeIn 0.3s ease-out;
+}
+
+/* Dark mode: Use darker background for better contrast with cards */
+html[data-theme='dark'] .overlayContainer {
+ background: var(--general-gray-dark);
+}
+
+.overlayContent {
+ height: 100%;
+ width: 100%;
+ padding: 1.6rem;
+ overflow-y: auto;
+ display: flex;
+ flex-direction: column;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .overlayContent {
+ padding: 1.6rem;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .overlayContent {
+ padding: 2.4rem;
+ }
+}
+
+/* Header */
+.header {
+ position: relative;
+ padding: 1.6rem 0 0.8rem 0;
+ margin-bottom: 0;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .header {
+ padding: 2.4rem 0 1.2rem 0;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .header {
+ padding: 4rem 0 1.6rem 0;
+ }
+}
+
+.title {
+ color: var(--ifm-heading-color);
+ font-family: var(--ifm-heading-font-family);
+ font-size: 2.4rem;
+ font-weight: 600;
+ line-height: 1.25;
+ margin: 0 0 0.8rem 0;
+}
+
+.subtitle {
+ color: var(--ifm-color-content-secondary);
+ font-family: var(--ifm-font-family-base);
+ font-size: 1.6rem;
+ line-height: 1.5;
+ margin: 0;
+ max-width: 600px;
+}
+
+.closeButton {
+ position: absolute;
+ top: 1.6rem;
+ right: 0;
+ background: var(--ifm-color-emphasis-100);
+ border: 1px solid var(--ifm-color-emphasis-300);
+ font-size: 1.4rem;
+ color: var(--ifm-color-content);
+ cursor: pointer;
+ padding: 0.6rem 1rem;
+ border-radius: 0.6rem;
+ font-family: var(--ifm-font-family-base);
+ transition: all 0.2s ease;
+ font-weight: 500;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .closeButton {
+ top: 2.4rem;
+ font-size: 1.5rem;
+ padding: 0.7rem 1.1rem;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .closeButton {
+ font-size: 1.6rem;
+ padding: 0.8rem 1.2rem;
+ }
+}
+
+.closeButton:hover {
+ background: var(--ifm-color-emphasis-200);
+ border-color: var(--ifm-color-emphasis-400);
+}
+
+/* Flow Container */
+.flowContainer {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+}
+
+.stepHeader {
+ margin-bottom: 0;
+ padding: 1.6rem 0 2rem 0;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .stepHeader {
+ padding: 2rem 0 3rem 0;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .stepHeader {
+ padding: 2rem 0 4rem 0;
+ }
+}
+
+.sectionTitle {
+ font-size: 2rem;
+ font-weight: 500;
+ margin: 0 0 1.6rem 0;
+ color: var(--color-text-heading);
+ line-height: 1.4;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .sectionTitle {
+ font-size: 2.2rem;
+ margin: 0 0 2rem 0;
+ line-height: 1.3;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .sectionTitle {
+ font-size: 2.4rem;
+ line-height: 1.2;
+ }
+}
+
+.sectionDescription {
+ font-size: 1.4rem;
+ font-weight: 400;
+ margin: 0;
+ color: var(--color-text-paragraph);
+ line-height: 1.5;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .sectionDescription {
+ font-size: 1.5rem;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .sectionDescription {
+ font-size: 1.6rem;
+ }
+}
+
+
+
+/* Cards Wrapper - mimics CardSection layout */
+.cardsWrapper {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 2rem;
+ margin-bottom: 2rem;
+ flex: 1;
+}
+
+@media (min-width: 997px) {
+ .cardsWrapper {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media (min-width: 1440px) {
+ .cardsWrapper {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+.cardColumn {
+ display: flex;
+}
+
+/* Card Items - mimics Card component */
+.cardItem {
+ margin-bottom: 1.6rem;
+ transition: filter calc(var(--motion) * var(--motion-speed)) ease;
+ flex: 1;
+}
+
+.cardItem>div {
+ background-color: var(--general-gray-light);
+ position: relative;
+ transition: background-color calc(var(--motion) * var(--motion-speed) * 0.5) ease;
+}
+
+.cardItem>div>div:not(.cardHolder) {
+ position: absolute;
+ top: 0.1rem;
+ left: 0.1rem;
+ width: calc(100% - 0.2rem);
+ height: calc(100% - 0.2rem);
+ background-color: var(--general-white);
+}
+
+.cardItem.cardActive {
+ filter: drop-shadow(0 0.8rem 2rem rgba(0, 0, 0, 0.1));
+}
+
+.cardItem.cardActive>div {
+ background-color: var(--general-white);
+}
+
+.cardHolder {
+ position: relative;
+ z-index: 1;
+ height: 100%;
+ cursor: pointer;
+}
+
+.cardInner {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ padding: 2rem;
+ gap: 0.5rem;
+ min-height: 16rem;
+ position: relative;
+ height: 100%;
+ color: var(--general-black);
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .cardInner {
+ padding: 2.4rem;
+ min-height: 18rem;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .cardInner {
+ padding: 3.2rem;
+ min-height: 20rem;
+ }
+}
+
+.cardInner::before {
+ position: absolute;
+ content: '';
+ top: 0;
+ left: 0;
+ width: 1rem;
+ height: 100%;
+ opacity: 0;
+ transition: opacity calc(var(--motion) * var(--motion-speed)) ease;
+ background-color: var(--color-palette, var(--general-gray-mid));
+}
+
+.cardHolder:hover .cardInner::before {
+ opacity: 1;
+}
+
+.cardShape {
+ position: absolute;
+ right: 0;
+ top: 0;
+ height: 100%;
+ width: 18.8rem;
+ color: var(--color-palette, var(--general-gray-mid));
+}
+
+@media (min-width: 997px) {
+ .cardShape {
+ width: 14.2rem;
+ }
+}
+
+@media (min-width: 1440px) {
+ .cardShape {
+ width: 13rem;
+ }
+}
+
+.cardHeader {
+ display: flex;
+ flex-direction: column;
+ gap: 1.6rem;
+ position: relative;
+}
+
+.cardFooter {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-end;
+ gap: 1.6rem;
+ position: relative;
+}
+
+@media (max-width: 996px) {
+ .cardFooter {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1.4rem;
+ }
+}
+
+.cardIcon {
+ flex: 0 0 auto;
+ width: 2.4rem;
+ height: 2.4rem;
+ color: var(--color-palette, var(--general-gray-mid));
+ transition: color calc(var(--motion) * var(--motion-speed)) ease;
+}
+
+.cardTitle {
+ color: var(--general-black);
+ font-size: 1.6rem;
+ font-weight: 600;
+ margin: 0;
+ line-height: 1.4;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .cardTitle {
+ font-size: 1.7rem;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .cardTitle {
+ font-size: 1.8rem;
+ }
+}
+
+.cardDescription {
+ color: var(--general-black);
+ font-size: 1.4rem;
+ line-height: 1.5;
+ margin: 0;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .cardDescription {
+ font-size: 1.5rem;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .cardDescription {
+ font-size: 1.7rem;
+ }
+}
+
+@media (min-width: 997px) {
+ .cardDescription {
+ max-width: 82%;
+ }
+}
+
+.cardButton {
+ flex: 0 0 auto;
+}
+
+/* Dark theme support */
+html[data-theme='dark'] .cardItem>div {
+ background-color: var(--general-black-light);
+}
+
+html[data-theme='dark'] .cardItem>div>div:not(.cardHolder) {
+ display: none;
+}
+
+html[data-theme='dark'] .cardItem.cardActive>div {
+ background-color: var(--general-black);
+}
+
+html[data-theme='dark'] .cardItem.cardActive .cardShape {
+ color: var(--color-palette, var(--general-gray-mid));
+}
+
+html[data-theme='dark'] .cardInner {
+ color: var(--general-white);
+}
+
+html[data-theme='dark'] .cardTitle {
+ color: var(--general-white);
+}
+
+html[data-theme='dark'] .cardDescription {
+ color: var(--general-white);
+}
+
+html[data-theme='dark'] .cardShape {
+ color: var(--general-black);
+ transition: color calc(var(--motion) * var(--motion-speed)) ease;
+}
+
+.quickLink:hover {
+ background: var(--ifm-color-emphasis-200);
+ color: var(--ifm-color-content);
+ text-decoration: none;
+ border-color: var(--ifm-color-emphasis-300);
+}
+
+/* Animations */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+/* Quick links responsive */
+.quickLinks {
+ border-top: 1px solid var(--ifm-color-emphasis-200);
+ padding-top: 1.6rem;
+ margin-top: auto;
+ margin-bottom: 1.6rem;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .quickLinks {
+ padding-top: 2rem;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .quickLinks {
+ padding-top: 2.4rem;
+ margin-bottom: 2rem;
+ }
+}
+
+.quickLinksTitle {
+ color: var(--color-text-heading);
+ font-size: 1.4rem;
+ font-weight: 600;
+ margin: 0 0 1.2rem 0;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .quickLinksTitle {
+ font-size: 1.5rem;
+ margin: 0 0 1.4rem 0;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .quickLinksTitle {
+ font-size: 1.6rem;
+ margin: 0 0 1.6rem 0;
+ }
+}
+
+.linkGrid {
+ display: flex;
+ flex-direction: column;
+ gap: 0.8rem;
+}
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ .linkGrid {
+ flex-direction: row;
+ flex-wrap: wrap;
+ gap: 1rem;
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .linkGrid {
+ gap: 1.2rem;
+ }
+}
+
+.quickLink {
+ background: var(--ifm-color-emphasis-100);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ color: var(--ifm-color-content);
+ text-decoration: none;
+ padding: 0.8rem 1.2rem;
+ border-radius: 0.6rem;
+ font-size: 1.3rem;
+ font-family: var(--ifm-font-family-base);
+ font-weight: 500;
+ transition: all 0.2s ease;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.8rem;
+}
+
+/* Desktop and up */
+@media (min-width: 997px) {
+ .quickLink {
+ padding: 1rem 1.6rem;
+ font-size: 1.4rem;
+ justify-content: flex-start;
+ }
+}
\ No newline at end of file
diff --git a/src/pages/quickstart/NavigationOverlay/index.tsx b/src/pages/quickstart/NavigationOverlay/index.tsx
new file mode 100644
index 00000000000..924fbdec71b
--- /dev/null
+++ b/src/pages/quickstart/NavigationOverlay/index.tsx
@@ -0,0 +1,30 @@
+import React, { useState } from 'react';
+import styles from './NavigationOverlay.module.css';
+import NavigationFlow from './NavigationFlow';
+
+interface NavigationOverlayProps {
+ onClose: () => void;
+ onSelect: (product: string, platform: string) => void;
+}
+
+const NavigationOverlay: React.FC = ({ onClose, onSelect }) => {
+ return (
+
+ );
+};
+
+export default NavigationOverlay;
\ No newline at end of file
diff --git a/src/pages/quickstart/builder/choices.ts b/src/pages/quickstart/builder/choices.ts
new file mode 100644
index 00000000000..9fb608d98e1
--- /dev/null
+++ b/src/pages/quickstart/builder/choices.ts
@@ -0,0 +1,48 @@
+import { DisplayChoice } from '../interfaces'
+
+//Product choices
+export const EMBEDDED_WALLETS = 'EMBEDDED_WALLETS'
+export const METAMASK_SDK = 'METAMASK_SDK'
+
+// Product choices
+export const PRODUCTS: DisplayChoice[] = [
+ { key: METAMASK_SDK, displayName: 'Metamask SDK' },
+ { key: EMBEDDED_WALLETS, displayName: 'Embedded Wallets' },
+]
+
+// Platform choices
+export const REACT = 'REACT'
+export const NEXTJS = 'NEXTJS'
+export const VUE = 'VUE'
+export const ANGULAR = 'ANGULAR'
+export const ANDROID = 'ANDROID'
+export const IOS = 'IOS'
+export const WEBGL = 'WEBGL'
+export const REACT_NATIVE = 'REACT_NATIVE'
+export const FLUTTER = 'FLUTTER'
+
+export const LANGS_EMBEDDED_WALLETS: DisplayChoice[] = [
+ { key: REACT, displayName: 'React' },
+ { key: NEXTJS, displayName: 'Next JS' },
+ { key: VUE, displayName: 'Vue' },
+ { key: ANGULAR, displayName: 'Angular' },
+ { key: ANDROID, displayName: 'Android' },
+ { key: IOS, displayName: 'iOS/Swift' },
+ { key: REACT_NATIVE, displayName: 'React Native' },
+ { key: FLUTTER, displayName: 'Flutter' },
+]
+
+export const LANGS_METAMASK_SDK: DisplayChoice[] = [
+ { key: REACT, displayName: 'React' },
+ { key: NEXTJS, displayName: 'Next JS' },
+]
+
+// Misc choices
+
+export const YES = 'YES'
+export const NO = 'NO'
+
+export const TOGGLE: DisplayChoice[] = [
+ { key: NO, displayName: 'No' },
+ { key: YES, displayName: 'Yes' },
+]
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/index.ts b/src/pages/quickstart/builder/embedded-wallets/android/index.ts
new file mode 100644
index 00000000000..328b8fd21f4
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/index.ts
@@ -0,0 +1,20 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT)
+ filenames.push(qsFileLinks.EW_PNP_ANDROID_ANDROIDMANIFEST_XML)
+ filenames.push(qsFileLinks.EW_PNP_ANDROID_BUILD_GRADLE)
+ filenames.push(qsFileLinks.EW_PNP_ANDROID_SETTINGS_GRADLE)
+ filenames.push(qsFileLinks.EW_PNP_ANDROID_STRINGS_XML)
+ filenames.push(qsFileLinks.EW_PNP_ANDROID_ACTIVITY_MAIN_XML)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/androidQuickStart.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/androidQuickStart.mdx
new file mode 100644
index 00000000000..097206d5242
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/androidQuickStart.mdx
@@ -0,0 +1,22 @@
+### Web3Auth PnP Android Quick Start
+
+This guide is designed to help you quickly integrate a basic instance of Web3Auth Plug and Play in your Android app.
+
+If you face any problem anytime, you can always find help in the [Web3Auth Community](https://web3auth.io/community/c/help-pnp/pnp-android/16).
+
+:::tip building locally
+
+- Clone the PnP Android Quick Start Application
+
+ ```shell npm2yarn
+ npx degit Web3Auth/web3auth-android-examples/android-quick-start w3a-android-quick-start
+ ```
+
+- Install & Run
+
+ ```shell npm2yarn
+ cd w3a-android-quick-start
+ ### run android project in Android Studio
+ ```
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/blockchainCalls.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/blockchainCalls.mdx
new file mode 100644
index 00000000000..b5bbee7f0c0
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/blockchainCalls.mdx
@@ -0,0 +1,9 @@
+### Making Blockchain Calls
+
+While using the Web3Auth Android SDK, you get the private key and sessionId within the user scope. This private key can interact with [Ethereum](https://ethereum.org/) to make any blockchain calls, like getting user's `account`, fetch `balance`, `sign transaction`, `send transaction`, `read` from and `write` to the smart contract, etc. We have added a basic EVM chain based example here for your reference.
+
+:::info Connect any Blockchain
+
+Refer to the [Blockchain Documentation](/connect-blockchain/) to know more about how to make calls on any blockchain.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/configureDeepLink.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/configureDeepLink.mdx
new file mode 100644
index 00000000000..54bb2b511b7
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/configureDeepLink.mdx
@@ -0,0 +1,29 @@
+### Configure Deep Link & Whitelist
+
+Open your app's `AndroidManifest.xml` file and add the following deep link intent filter to your sign-in activity:
+
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+:::info Whitelist your app
+
+In order to whitelist your App, you'll need to create a project in the [Developer Dashboard](https://dashboard.web3auth.io).
+
+- Go to [Developer Dashboard](https://dashboard.web3auth.io/), select your Web3Auth project.
+
+- Add `{YOUR_APP_PACKAGE_NAME}://auth` to **Whitelist URLs**.
+
+- Copy the `Client ID` and paste it inside `res/values/strings.xml` file.
+
+- It will be used as `R.string.web3auth_project_id` during initialization.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/enableInternetUsage.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/enableInternetUsage.mdx
new file mode 100644
index 00000000000..ccc6c2bb7dd
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/enableInternetUsage.mdx
@@ -0,0 +1,13 @@
+### Enable Internet usage
+
+Open your app's `AndroidManifest.xml` file and add the following permission:
+
+```xml
+
+```
+
+:::note
+
+The `` element must be a direct child of the `` root element.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/index.ts b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/index.ts
new file mode 100644
index 00000000000..08b12078fe8
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/index.ts
@@ -0,0 +1,32 @@
+import * as getUserInfo from '../../../../commonSteps/getUserInfo.mdx'
+import * as registerApp from '../../../../commonSteps/registerApp.mdx'
+import { toSteps } from '../../../../utils'
+import * as blockchainCalls from './blockchainCalls.mdx'
+import * as jitpack from './jitpack.mdx'
+import * as installation from './installation.mdx'
+import * as login from './login.mdx'
+import * as logout from './logout.mdx'
+import * as androidQuickStart from './androidQuickStart.mdx'
+import * as requirements from './requirements.mdx'
+import * as enableInternetUsage from './enableInternetUsage.mdx'
+import * as singleTop from './singleTop.mdx'
+import * as configureDeepLink from './configureDeepLink.mdx'
+import * as initialize from './initialize.mdx'
+
+const STEPS = toSteps({
+ androidQuickStart,
+ requirements,
+ installation,
+ jitpack,
+ enableInternetUsage,
+ singleTop,
+ configureDeepLink,
+ registerApp,
+ initialize,
+ login,
+ getUserInfo,
+ blockchainCalls,
+ logout,
+})
+
+export default STEPS
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/initialize.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/initialize.mdx
new file mode 100644
index 00000000000..cb45f8b2974
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/initialize.mdx
@@ -0,0 +1,13 @@
+### Create and initialize the Web3Auth instance
+
+Let's now create an instance of the `Web3Auth`.
+
+We need `clientId` and `network` to initialize the Web3Auth class. You can get your `clientId` from registering (above), whereas `network` signifies the type of network(`SAPPHIRE_MAINNET` or `SAPPHIRE_DEVNET`) you want to initialize web3auth with.
+
+Now, let's create an instance of the `Web3Auth` class. It can be initialized on-demand when the user interactions are input (like button click) or when the screen is initialized.
+
+:::info sdk reference
+
+Read more about [Android SDK](/sdk/mobile/pnp/android).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/installation.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/installation.mdx
new file mode 100644
index 00000000000..2db5535bfad
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/installation.mdx
@@ -0,0 +1,9 @@
+### Installation
+
+Add Web3Auth's Android SDK to the dependency list. In your app-level `build.gradle` dependencies section, add the latest `com.github.Web3Auth:web3auth-android-sdk`.
+
+:::warning Update to the Latest-SDK
+
+Please use the **[latest version](https://github.com/Web3Auth/web3auth-android-sdk/releases)** of Web3Auth's Android SDK.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/jitpack.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/jitpack.mdx
new file mode 100644
index 00000000000..2c73501dd35
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/jitpack.mdx
@@ -0,0 +1,14 @@
+### Add Jitpack Repository
+
+In your project-level `build.gradle` or `settings.gradle` file, add the JitPack repository.
+
+```groovy
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ maven { url "https://jitpack.io" } // <-- Add this line
+ }
+}
+```
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/login.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/login.mdx
new file mode 100644
index 00000000000..4a152fe3949
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/login.mdx
@@ -0,0 +1,11 @@
+### Logging in your User
+
+Use the `login` function in the Web3Auth Instance to log in user. Just create a button that triggers the `login` for the user of the login method of their choice.
+
+After a successful user login, Web3Auth will redirect back to your app, with a payload stored in the state of the Web3Auth Instance.
+
+:::info SDK Reference
+
+- [`login()` function](/sdk/mobile/pnp/android/usage#logging-in-a-user).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/logout.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/logout.mdx
new file mode 100644
index 00000000000..2a1bb0798e2
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/logout.mdx
@@ -0,0 +1,9 @@
+### Log the user out
+
+Use the `logout` function of the Web3Auth Instance to log the user out.
+
+:::info SDK Reference
+
+- [`logout()` function](/sdk/mobile/pnp/android/usage#logging-out-a-user).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/requirements.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/requirements.mdx
new file mode 100644
index 00000000000..e9f967edf24
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/requirements.mdx
@@ -0,0 +1,6 @@
+:::note Requirements
+
+- Android API version `24` or newer is required.
+- `targetSdk` & `compileSdk` should be `34` or newer.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/setURLResult.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/setURLResult.mdx
new file mode 100644
index 00000000000..dce1c844d7e
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/setURLResult.mdx
@@ -0,0 +1,11 @@
+### Set Result URL
+
+This handles sign-in for the app within an activity.
+
+```kotlin
+override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+
+ web3Auth.setResultUrl(intent?.data)
+}
+```
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/stepContent/singleTop.mdx b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/singleTop.mdx
new file mode 100644
index 00000000000..1ed40cc79b1
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/stepContent/singleTop.mdx
@@ -0,0 +1,17 @@
+### Enable singleTop launchMode activity
+
+Make sure your sign-in activity `launchMode` is set to **singleTop** in your `AndroidManifest.xml`
+
+```xml
+
+ // ...
+
+```
+
+:::tip
+
+Copy the `activity_main.xml` file from here to your project for easier integration.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/android/steps.ts b/src/pages/quickstart/builder/embedded-wallets/android/steps.ts
new file mode 100644
index 00000000000..0928c7a75db
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/android/steps.ts
@@ -0,0 +1,111 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.androidQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT,
+ files[qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.requirements,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_BUILD_GRADLE,
+ files[qsFileLinks.EW_PNP_ANDROID_BUILD_GRADLE],
+ 'Requirements'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_BUILD_GRADLE,
+ files[qsFileLinks.EW_PNP_ANDROID_BUILD_GRADLE],
+ 'Installation'
+ ),
+ },
+ {
+ ...STEPS.jitpack,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_SETTINGS_GRADLE,
+ files[qsFileLinks.EW_PNP_ANDROID_SETTINGS_GRADLE],
+ 'Add JitPack URL'
+ ),
+ },
+ {
+ ...STEPS.enableInternetUsage,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_ANDROIDMANIFEST_XML,
+ files[qsFileLinks.EW_PNP_ANDROID_ANDROIDMANIFEST_XML],
+ 'Enable Internet Usage'
+ ),
+ },
+ {
+ ...STEPS.singleTop,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_ANDROIDMANIFEST_XML,
+ files[qsFileLinks.EW_PNP_ANDROID_ANDROIDMANIFEST_XML],
+ 'Enable Single Top'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_STRINGS_XML,
+ files[qsFileLinks.EW_PNP_ANDROID_STRINGS_XML],
+ 'Get your Web3Auth Client ID from Dashboard'
+ ),
+ },
+ {
+ ...STEPS.configureDeepLink,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_ANDROIDMANIFEST_XML,
+ files[qsFileLinks.EW_PNP_ANDROID_ANDROIDMANIFEST_XML],
+ 'Configure Deep Link'
+ ),
+ },
+ {
+ ...STEPS.initialize,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT,
+ files[qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT],
+ 'Initialize Web3Auth'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT,
+ files[qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.getUserInfo,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT,
+ files[qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT],
+ 'Get User Info'
+ ),
+ },
+ {
+ ...STEPS.blockchainCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT,
+ files[qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT,
+ files[qsFileLinks.EW_PNP_ANDROID_MAINACTIVITY_KT],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/index.ts b/src/pages/quickstart/builder/embedded-wallets/angular/index.ts
new file mode 100644
index 00000000000..e376877c365
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/index.ts
@@ -0,0 +1,21 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS)
+ filenames.push(qsFileLinks.EW_ANGULAR_PACKAGE_JSON)
+ filenames.push(qsFileLinks.EW_ANGULAR_APP_COMPONENT_HTML)
+ filenames.push(qsFileLinks.EW_ANGULAR_POLYFILL_TS)
+ filenames.push(qsFileLinks.EW_ANGULAR_TSCONFIG_JSON)
+ filenames.push(qsFileLinks.EW_ANGULAR_ETHERSRPC_TS)
+ filenames.push(qsFileLinks.EW_ANGULAR_VIEMRPC_TS)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/angularBundlerIssues.mdx b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/angularBundlerIssues.mdx
new file mode 100644
index 00000000000..4647ade954a
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/angularBundlerIssues.mdx
@@ -0,0 +1,5 @@
+### Fixing Bundler Issues
+
+While using any web3 library in Angular, you may run into issues building. This issue occurs because some core packages like `eccrypto` have certain dependencies which are not present within the browser build environment.
+
+> To solve this, please have a look at our troubleshooting pages about [Webpack 5 Issues](/troubleshooting/webpack-issues)
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/angularQuickStart.mdx b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/angularQuickStart.mdx
new file mode 100644
index 00000000000..d007e7e92dc
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/angularQuickStart.mdx
@@ -0,0 +1,15 @@
+### Web3Auth Angular Quick Start
+
+Integrate secure and seamless Web3 authentication into your Angular app using Web3Auth.
+
+Clone the Angular Quick Start Application
+
+```shell
+npx degit Web3Auth/web3auth-examples/quick-starts/angular-quick-start w3a-quick-start
+```
+
+:::info
+
+If you face any problem anytime, you can always find help in the [**Web3Auth Community**](https://web3auth.io/community/c/help-pnp/pnp-web/7).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/blockchainCalls.mdx b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/blockchainCalls.mdx
new file mode 100644
index 00000000000..13c80e8e1fc
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/blockchainCalls.mdx
@@ -0,0 +1,9 @@
+### Making Blockchain Calls
+
+This example demonstrates the connection for an EVM Chain with Web3Auth. You can choose the library of your choice and configure it according the steps given in the respective RPC Files.
+
+:::tip Other Blockchains
+
+Web3Auth supports all blockchains. Have a look at our [Connect Blockchain](/connect-blockchain/) section of the documentation and choose your blockchain to get started.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/config.mdx b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/config.mdx
new file mode 100644
index 00000000000..813d9ab51ab
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/config.mdx
@@ -0,0 +1,9 @@
+### Configure Web3Auth
+
+Create a basic config for Web3Auth and pass the `clientId` & `web3AuthNetwork` from your Web3Auth Dashboard Project Settings.
+
+:::info
+
+This is where you can also configure any major settings of your integration as well. Visit our [**configuration section**](/sdk/web/js/config) of the sdk reference to learn more about the different options available.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/index.ts b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/index.ts
new file mode 100644
index 00000000000..10f0c79d6b4
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/index.ts
@@ -0,0 +1,24 @@
+import * as angularQuickStart from "./angularQuickStart.mdx";
+import * as angularBundlerIssues from "./angularBundlerIssues.mdx";
+import * as initialization from "./initialize.mdx";
+import * as login from "./login.mdx";
+import * as logout from "./logout.mdx";
+import * as blockchainCalls from "./blockchainCalls.mdx";
+import * as registerApp from "../../../../commonSteps/registerApp.mdx";
+import * as installation from "./installation.mdx";
+import * as config from "./config.mdx";
+import { toSteps } from "../../../../utils";
+
+const STEPS = toSteps({
+ angularQuickStart,
+ angularBundlerIssues,
+ installation,
+ initialization,
+ config,
+ registerApp,
+ blockchainCalls,
+ login,
+ logout,
+});
+
+export default STEPS;
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/initialize.mdx b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/initialize.mdx
new file mode 100644
index 00000000000..d2999166151
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/initialize.mdx
@@ -0,0 +1,3 @@
+### Initialize Web3Auth
+
+Web3Auth's Instance needs to be initialized as soon as your app loads up to enable the user to log in. Preferably done within a constructor.
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/installation.mdx b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/installation.mdx
new file mode 100644
index 00000000000..0fe526a1c53
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/installation.mdx
@@ -0,0 +1,11 @@
+### Install Web3Auth
+
+Install the Web3Auth package in your project.
+
+> Additionally, for blockchain calls, this example can run with `viem` or `ethers`, you can choose your preferred library.
+
+```bash npm2yarn
+npm install --save @web3auth/modal viem
+```
+
+[](https://www.npmjs.com/package/@web3auth/modal) [](https://www.jsdelivr.com/package/npm/@web3auth/modal)
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/login.mdx b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/login.mdx
new file mode 100644
index 00000000000..4cea1e4489e
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/login.mdx
@@ -0,0 +1,3 @@
+### Logging in your User
+
+Use the `connect` function in the Web3Auth Instance to display the modal. The modal will prompt the user to login with their wallet and handle the authentication for you.
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/logout.mdx b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/logout.mdx
new file mode 100644
index 00000000000..2a00c234dba
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/stepContent/logout.mdx
@@ -0,0 +1,9 @@
+### Log the user out
+
+Use the `useWeb3AuthDisconnect` composable to log the user out. This will also delete the session information from the local storage of the browser.
+
+:::info
+
+There are multiple other functions available in the Web3Auth SDK. Visit our [**functions section**](/sdk/web/js/functions) of the sdk reference to learn more about the different functions available.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/angular/steps.ts b/src/pages/quickstart/builder/embedded-wallets/angular/steps.ts
new file mode 100644
index 00000000000..57687222dfb
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/angular/steps.ts
@@ -0,0 +1,79 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.angularQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS,
+ files[qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_PACKAGE_JSON,
+ files[qsFileLinks.EW_ANGULAR_PACKAGE_JSON],
+ 'Web3Auth Installation'
+ ),
+ },
+ {
+ ...STEPS.angularBundlerIssues,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_POLYFILL_TS,
+ files[qsFileLinks.EW_ANGULAR_POLYFILL_TS],
+ 'Bundler Issues'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS,
+ files[qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS],
+ 'Dashboard Registration'
+ ),
+ },
+ {
+ ...STEPS.config,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS,
+ files[qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS],
+ 'Config'
+ ),
+ },
+ {
+ ...STEPS.initialization,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS,
+ files[qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS],
+ 'SDK Initialization'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS,
+ files[qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.blockchainCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS,
+ files[qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS,
+ files[qsFileLinks.EW_ANGULAR_APP_COMPONENT_TS],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/index.ts b/src/pages/quickstart/builder/embedded-wallets/flutter/index.ts
new file mode 100644
index 00000000000..890192ff288
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/index.ts
@@ -0,0 +1,18 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.EW_PNP_FLUTTER_MAIN_DART)
+ filenames.push(qsFileLinks.EW_PNP_FLUTTER_BUILD_GRADLE)
+ filenames.push(qsFileLinks.EW_PNP_FLUTTER_PODFILE)
+ filenames.push(qsFileLinks.EW_PNP_FLUTTER_PUBSPEC_YAML)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/blockchainCalls.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/blockchainCalls.mdx
new file mode 100644
index 00000000000..0853ae17885
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/blockchainCalls.mdx
@@ -0,0 +1,9 @@
+### Making Blockchain Calls
+
+While using the Web3Auth Flutter SDK, you get the private key within the user scope. This private key can interact with [Ethereum](https://ethereum.org/) to make any blockchain calls, like getting user's `account`, fetch `balance`, `sign transaction`, `send transaction`, `read` from and `write` to the smart contract, etc.
+
+:::info Connect any Blockchain
+
+Refer to the [Blockchain Documentation](/connect-blockchain/) to know more about how to make calls on any blockchain.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/flutterQuickStart.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/flutterQuickStart.mdx
new file mode 100644
index 00000000000..a26a9a551e0
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/flutterQuickStart.mdx
@@ -0,0 +1,22 @@
+### Web3Auth PnP Flutter Quick Start
+
+This guide is designed to help you quickly integrate a basic instance of Web3Auth Plug and Play in your Flutter app.
+
+If you face any problem anytime, you can always find help in the [Web3Auth Community](https://web3auth.io/community/c/help-pnp/pnp-flutter/18).
+
+:::tip building locally
+
+- Clone the PnP Flutter Quick Start Application
+
+ ```shell npm2yarn
+ npx degit Web3Auth/web3auth-flutter-examples/flutter-quick-start flutter-quick-start
+ ```
+
+- Install & Run
+
+ ```shell npm2yarn
+ cd flutter-quick-start
+ ### run project in Android Studio or in VSCode
+ ```
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/index.ts b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/index.ts
new file mode 100644
index 00000000000..5fae9dd12ea
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/index.ts
@@ -0,0 +1,28 @@
+import { toSteps } from '../../../../utils'
+import * as flutterQuickStart from './flutterQuickStart.mdx'
+import * as requirementsAndroid from './requirementsAndroid.mdx'
+import * as requirementsIOS from './requirementsIOS.mdx'
+import * as installation from './installation.mdx'
+import * as whitelist from './whitelist.mdx'
+import * as registerApp from '../../../../commonSteps/registerApp.mdx'
+import * as initialization from './initialize.mdx'
+import * as login from './login.mdx'
+import * as getUserInfo from '../../../../commonSteps/getUserInfo.mdx'
+import * as blockchainCalls from './blockchainCalls.mdx'
+import * as logout from './logout.mdx'
+
+const STEPS = toSteps({
+ flutterQuickStart,
+ requirementsAndroid,
+ requirementsIOS,
+ installation,
+ registerApp,
+ whitelist,
+ initialization,
+ login,
+ getUserInfo,
+ blockchainCalls,
+ logout,
+})
+
+export default STEPS
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/initialize.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/initialize.mdx
new file mode 100644
index 00000000000..3ce97e5d268
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/initialize.mdx
@@ -0,0 +1,11 @@
+### Create and initialize the Web3Auth instance
+
+Let's now create an instance of the `Web3AuthFlutter`.
+
+We need `clientId` and `network` to initialize Web3AuthFlutter class. You can get your `clientId` from registering (above), whereas `network` signifies the type of network(`sapphire_mainnet` or `sapphire_devnet`) you want to initialize web3auth with.
+
+:::info sdk reference
+
+Read more about [Flutter SDK](/sdk/mobile/pnp/flutter).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/installation.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/installation.mdx
new file mode 100644
index 00000000000..51aa8d64bb7
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/installation.mdx
@@ -0,0 +1,22 @@
+### Install Web3Auth
+
+For making hybrid iOS & Android applications using Flutter, we have the [web3auth-flutter-sdk](https://github.com/Web3Auth/web3auth-flutter-sdk) to integrate Web3Auth into your application.
+
+Add `web3auth_flutter` as a dependency to your `pubspec.yaml` file.
+
+```sh
+flutter pub add web3auth_flutter
+```
+
+or
+
+```yaml
+dependencies:
+ web3auth_flutter: ^3.1.1 ### or the latest version
+```
+
+:::warning Update to the Latest-SDK
+
+Please use the **[latest version](https://github.com/Web3Auth/web3auth-flutter-sdk/releases)** of Web3Auth's Flutter SDK.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/login.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/login.mdx
new file mode 100644
index 00000000000..0424fc7d531
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/login.mdx
@@ -0,0 +1,11 @@
+### Logging in your User
+
+Use the `login` function in the Web3Auth Instance to log in user. Just create a button that triggers the `login` for the user of the login method of their choice.
+
+After a successful user login, Web3Auth will redirect back to your app, with a payload stored in the state of the Web3Auth Instance.
+
+:::info SDK Reference
+
+- [`login()` function](/sdk/mobile/pnp/flutter/usage#logging-in-a-user).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/logout.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/logout.mdx
new file mode 100644
index 00000000000..320bd19b5ff
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/logout.mdx
@@ -0,0 +1,9 @@
+### Log the user out
+
+Use the `logout` function of the Web3Auth Instance to log the user out.
+
+:::info SDK Reference
+
+- [`logout()` function](/sdk/mobile/pnp/flutter/usage#logging-out-a-user).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/requirementsAndroid.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/requirementsAndroid.mdx
new file mode 100644
index 00000000000..51b99f5ca98
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/requirementsAndroid.mdx
@@ -0,0 +1,7 @@
+:::note Requirements Android
+
+- Android API version `24` or newer is required.
+- `compileSdk` should be `34` or newer.
+- Check `android/app/build.gradle` in your Flutter project to change it.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/requirementsIOS.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/requirementsIOS.mdx
new file mode 100644
index 00000000000..6d16aecb344
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/requirementsIOS.mdx
@@ -0,0 +1,9 @@
+:::note Requirements iOS
+
+- iOS 14+
+- Xcode 11.4+ / 12.x
+- Swift 4.x / 5.x
+- `platform :ios` needs to be `14.0`.
+- Check `ios/Podfile` in your Flutter project to change it.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/whitelist.mdx b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/whitelist.mdx
new file mode 100644
index 00000000000..e482869710c
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/stepContent/whitelist.mdx
@@ -0,0 +1,10 @@
+### Whitelist Package & Bundle ID
+
+To whitelist, you'll need to create a project or use an existing one in the [Developer Dashboard](https://dashboard.web3auth.io).
+
+- Create or Select a Web3Auth project.
+
+- To **Whitelist URLs** section:
+
+ - Add `{SCHEME}://{YOUR_APP_PACKAGE_NAME}` for `Android`,
+ - and, `{bundleId}://auth` for `iOS` to
diff --git a/src/pages/quickstart/builder/embedded-wallets/flutter/steps.ts b/src/pages/quickstart/builder/embedded-wallets/flutter/steps.ts
new file mode 100644
index 00000000000..3c5503d26cc
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/flutter/steps.ts
@@ -0,0 +1,95 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.flutterQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_MAIN_DART,
+ files[qsFileLinks.EW_PNP_FLUTTER_MAIN_DART],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.requirementsAndroid,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_BUILD_GRADLE,
+ files[qsFileLinks.EW_PNP_FLUTTER_BUILD_GRADLE],
+ 'Requirements Android'
+ ),
+ },
+ {
+ ...STEPS.requirementsIOS,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_PODFILE,
+ files[qsFileLinks.EW_PNP_FLUTTER_PODFILE],
+ 'Requirements iOS'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_PUBSPEC_YAML,
+ files[qsFileLinks.EW_PNP_FLUTTER_PUBSPEC_YAML],
+ 'Installation'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_MAIN_DART,
+ files[qsFileLinks.EW_PNP_FLUTTER_MAIN_DART],
+ 'Get your Web3Auth Client ID from Dashboard'
+ ),
+ },
+ {
+ ...STEPS.whitelist,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_BUILD_GRADLE,
+ files[qsFileLinks.EW_PNP_FLUTTER_BUILD_GRADLE],
+ 'Whitelist bundle ID'
+ ),
+ },
+ {
+ ...STEPS.initialization,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_MAIN_DART,
+ files[qsFileLinks.EW_PNP_FLUTTER_MAIN_DART],
+ 'Initialize Web3Auth'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_MAIN_DART,
+ files[qsFileLinks.EW_PNP_FLUTTER_MAIN_DART],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.getUserInfo,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_MAIN_DART,
+ files[qsFileLinks.EW_PNP_FLUTTER_MAIN_DART],
+ 'Get User Info'
+ ),
+ },
+ {
+ ...STEPS.blockchainCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_MAIN_DART,
+ files[qsFileLinks.EW_PNP_FLUTTER_MAIN_DART],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_FLUTTER_MAIN_DART,
+ files[qsFileLinks.EW_PNP_FLUTTER_MAIN_DART],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/index.ts b/src/pages/quickstart/builder/embedded-wallets/ios/index.ts
new file mode 100644
index 00000000000..aef4243c776
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/index.ts
@@ -0,0 +1,19 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT)
+ filenames.push(qsFileLinks.EW_PNP_IOS_CONTENTVIEW_SWIFT)
+ filenames.push(qsFileLinks.EW_PNP_IOS_LOGINVIEW_SWIFT)
+ filenames.push(qsFileLinks.EW_PNP_IOS_WEB3RPC_SWIFT)
+ filenames.push(qsFileLinks.EW_PNP_IOS_USERDETAILVIEW_SWIFT)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/blockchainCalls.mdx b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/blockchainCalls.mdx
new file mode 100644
index 00000000000..05b6e1bcbe6
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/blockchainCalls.mdx
@@ -0,0 +1,9 @@
+### Making Blockchain Calls
+
+While using the Web3Auth Swift/iOS SDK, you get the private key within the user scope. This means that you can use it with any blockchain with their corresponding library within the Swift/iOS environment.
+
+:::info Connect any Blockchain
+
+Refer to the [Blockchain Documentation](/connect-blockchain/) to know more about how to make calls on any blockchain.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/iOSQuickStart.mdx b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/iOSQuickStart.mdx
new file mode 100644
index 00000000000..3e35f2879ed
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/iOSQuickStart.mdx
@@ -0,0 +1,28 @@
+### Web3Auth PnP Swift/iOS Quick Start
+
+This guide is designed to help you quickly integrate a basic instance of Web3Auth Plug and Play in your Swift/iOS app.
+
+If you face any problem anytime, you can always find help in the [Web3Auth Community](https://web3auth.io/community/c/help-pnp/pnp-ios/17).
+
+:::tip building locally
+
+- Clone the PnP Swift/iOS Quick Start Application
+
+ ```shell npm2yarn
+ npx degit Web3Auth/web3auth-ios-examples/ios-quick-start w3a-ios-quick-start
+ ```
+
+- Install & Run
+
+ ```shell npm2yarn
+ cd w3a-ios-quick-start
+ ### run project in Xcode
+ ```
+
+:::
+
+:::note Requirements
+
+- iOS 14+, Xcode 11.4+ / 12.x & Swift 4.x / 5.x
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/index.ts b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/index.ts
new file mode 100644
index 00000000000..b8ee0758dc8
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/index.ts
@@ -0,0 +1,24 @@
+import * as getUserInfo from '../../../../commonSteps/getUserInfo.mdx'
+import * as registerApp from '../../../../commonSteps/registerApp.mdx'
+import * as whitelist from './whitelist.mdx'
+import { toSteps } from '../../../../utils'
+import * as blockchainCalls from './blockchainCalls.mdx'
+import * as initialization from './initialize.mdx'
+import * as installation from './installation.mdx'
+import * as login from './login.mdx'
+import * as logout from './logout.mdx'
+import * as iOSQuickStart from './iOSQuickStart.mdx'
+
+const STEPS = toSteps({
+ iOSQuickStart,
+ installation,
+ registerApp,
+ whitelist,
+ initialization,
+ login,
+ getUserInfo,
+ blockchainCalls,
+ logout,
+})
+
+export default STEPS
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/initialize.mdx b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/initialize.mdx
new file mode 100644
index 00000000000..a96fdb65ec3
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/initialize.mdx
@@ -0,0 +1,13 @@
+### Create and initialize the Web3Auth instance
+
+Let's now create an instance of the `Web3Auth`.
+
+We need `clientId` and `network` to initialize the web3auth class. You can get your `clientId` from registering (above), whereas `network` signifies the type of network(`SAPPHIRE_MAINNET` or `SAPPHIRE_DEVNET` ) you want to initialize web3auth with.
+
+Now, let's create an instance of the `Web3Auth` class. It can be initialized on-demand when the user interactions are input (like button click) or when the screen is initialized.
+
+:::info sdk reference
+
+Read more about [iOS SDK](/sdk/mobile/pnp/ios).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/installation.mdx b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/installation.mdx
new file mode 100644
index 00000000000..a356639d8a0
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/installation.mdx
@@ -0,0 +1,21 @@
+### Install Web3Auth
+
+Add the Web3Auth PnP iOS SDK to your project
+
+1. In Xcode, with your app project open, navigate to **File > Add Packages**.
+
+1. When prompted, add the SFA iOS SDK repository:
+
+ ```bash
+ https://github.com/Web3Auth/web3auth-swift-sdk
+ ```
+
+ From the `Dependency Rule` dropdown, select `Exact Version` and enter the [latest version](https://github.com/Web3Auth/web3auth-swift-sdk/releases).
+
+1. When finished, Xcode will automatically begin resolving and downloading your dependencies in the background.
+
+:::tip SDK Reference
+
+- [Installing Web3Auth](/sdk/mobile/pnp/ios/install).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/login.mdx b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/login.mdx
new file mode 100644
index 00000000000..42df8f296bb
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/login.mdx
@@ -0,0 +1,11 @@
+### Logging in your User
+
+Use the `login` function in the Web3Auth Instance to log in the user. Just create a button that triggers the `login` for the user of the login method of their choice.
+
+After a successful user login, Web3Auth will redirect back to your app, with a payload stored in the state of the Web3Auth Instance.
+
+:::info SDK Reference
+
+- [`login()` function](/sdk/mobile/pnp/react-native/usage#logging-in-a-user).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/logout.mdx b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/logout.mdx
new file mode 100644
index 00000000000..825e5a41549
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/logout.mdx
@@ -0,0 +1,9 @@
+### Log the user out
+
+Use the `logout` function of the Web3Auth Instance to log the user out.
+
+:::info SDK Reference
+
+- [`logout()` function](/sdk/mobile/pnp/react-native/usage#logging-out-a-user).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/whitelist.mdx b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/whitelist.mdx
new file mode 100644
index 00000000000..4551f92fe1a
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/stepContent/whitelist.mdx
@@ -0,0 +1,7 @@
+### Whitelist Bundle ID
+
+To whitelist, you'll need to
+
+- Select your Web3Auth project in the [Developer Dashboard](https://dashboard.web3auth.io).
+
+- Add `(bundleId)://auth` to **Whitelist URLs** section.
diff --git a/src/pages/quickstart/builder/embedded-wallets/ios/steps.ts b/src/pages/quickstart/builder/embedded-wallets/ios/steps.ts
new file mode 100644
index 00000000000..a1b4d4dbb19
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/ios/steps.ts
@@ -0,0 +1,79 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.iOSQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_CONTENTVIEW_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_CONTENTVIEW_SWIFT],
+ 'Installation'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT],
+ 'Get your Web3Auth Client ID from Dashboard'
+ ),
+ },
+ {
+ ...STEPS.whitelist,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT],
+ 'Whitelist bundle ID'
+ ),
+ },
+ {
+ ...STEPS.initialization,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT],
+ 'Initialize Web3Auth'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.getUserInfo,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_VIEWMODEL_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_USERDETAILVIEW_SWIFT],
+ 'Get User Info'
+ ),
+ },
+ {
+ ...STEPS.blockchainCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_WEB3RPC_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_WEB3RPC_SWIFT],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_IOS_USERDETAILVIEW_SWIFT,
+ files[qsFileLinks.EW_PNP_IOS_USERDETAILVIEW_SWIFT],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/embedded-wallets/nextjs/index.ts b/src/pages/quickstart/builder/embedded-wallets/nextjs/index.ts
new file mode 100644
index 00000000000..83e90bb7974
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/nextjs/index.ts
@@ -0,0 +1,22 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.EW_NEXTJS_LAYOUT_TSX)
+ filenames.push(qsFileLinks.EW_NEXTJS_PAGE_TSX)
+ filenames.push(qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX)
+ filenames.push(qsFileLinks.EW_NEXTJS_COMPONENTS_APP_TSX)
+ filenames.push(qsFileLinks.EW_NEXTJS_PACKAGE_JSON)
+ filenames.push(qsFileLinks.EW_NEXTJS_GET_BALANCE_TSX)
+ filenames.push(qsFileLinks.EW_NEXTJS_SEND_TRANSACTION_TSX)
+ filenames.push(qsFileLinks.EW_NEXTJS_SWITCH_NETWORK_TSX)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/embedded-wallets/nextjs/stepContent/index.ts b/src/pages/quickstart/builder/embedded-wallets/nextjs/stepContent/index.ts
new file mode 100644
index 00000000000..e9265e1cad6
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/nextjs/stepContent/index.ts
@@ -0,0 +1,24 @@
+import * as nextjsQuickStart from "./nextjsQuickStart.mdx";
+import * as login from "../../react/stepContent/login.mdx";
+import * as logout from "../../react/stepContent/logout.mdx";
+import * as setupWeb3AuthProvider from "../../react/stepContent/setupWeb3AuthProvider.mdx";
+import * as wagmiCalls from "../../react/stepContent/wagmiCalls.mdx";
+import * as registerApp from "../../../../commonSteps/registerApp.mdx";
+import * as installation from "../../react/stepContent/installation.mdx";
+import * as config from "../../react/stepContent/config.mdx";
+import * as setupWagmiProvider from "../../react/stepContent/setupWagmiProvider.mdx";
+import { toSteps } from "../../../../utils";
+
+const STEPS = toSteps({
+ nextjsQuickStart,
+ installation,
+ config,
+ setupWagmiProvider,
+ registerApp,
+ wagmiCalls,
+ login,
+ logout,
+ setupWeb3AuthProvider,
+});
+
+export default STEPS;
diff --git a/src/pages/quickstart/builder/embedded-wallets/nextjs/stepContent/nextjsQuickStart.mdx b/src/pages/quickstart/builder/embedded-wallets/nextjs/stepContent/nextjsQuickStart.mdx
new file mode 100644
index 00000000000..1391ee6bac1
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/nextjs/stepContent/nextjsQuickStart.mdx
@@ -0,0 +1,15 @@
+### Web3Auth NextJS Quick Start
+
+Integrate secure and seamless Web3 authentication into your NextJS app using Web3Auth.
+
+Clone the NextJS Quick Start Application
+
+```shell
+npx degit Web3Auth/web3auth-examples/quick-starts/nextjs-quick-start w3a-quick-start
+```
+
+:::info
+
+If you face any problem anytime, you can always find help in the [**Web3Auth Community**](https://web3auth.io/community/c/help-pnp/pnp-web/7).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/nextjs/steps.ts b/src/pages/quickstart/builder/embedded-wallets/nextjs/steps.ts
new file mode 100644
index 00000000000..b397aa4012b
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/nextjs/steps.ts
@@ -0,0 +1,79 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.nextjsQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_LAYOUT_TSX,
+ files[qsFileLinks.EW_NEXTJS_LAYOUT_TSX],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_PACKAGE_JSON,
+ files[qsFileLinks.EW_NEXTJS_PACKAGE_JSON],
+ 'Web3Auth Installation'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX,
+ files[qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX],
+ 'Dashboard Registration'
+ ),
+ },
+ {
+ ...STEPS.config,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX,
+ files[qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX],
+ 'Config'
+ ),
+ },
+ {
+ ...STEPS.setupWeb3AuthProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX,
+ files[qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX],
+ 'Setup Web3Auth Provider'
+ ),
+ },
+ {
+ ...STEPS.setupWagmiProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX,
+ files[qsFileLinks.EW_NEXTJS_COMPONENTS_PROVIDER_TSX],
+ 'Setup Wagmi Provider'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_COMPONENTS_APP_TSX,
+ files[qsFileLinks.EW_NEXTJS_COMPONENTS_APP_TSX],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.wagmiCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_COMPONENTS_APP_TSX,
+ files[qsFileLinks.EW_NEXTJS_COMPONENTS_APP_TSX],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_NEXTJS_COMPONENTS_APP_TSX,
+ files[qsFileLinks.EW_NEXTJS_COMPONENTS_APP_TSX],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/index.ts b/src/pages/quickstart/builder/embedded-wallets/react/index.ts
new file mode 100644
index 00000000000..e3299032b41
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/index.ts
@@ -0,0 +1,22 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.EW_REACT_WEB3AUTHCONTEXT_TSX)
+ filenames.push(qsFileLinks.EW_REACT_MAIN_TSX)
+ filenames.push(qsFileLinks.EW_REACT_APP_TSX)
+ filenames.push(qsFileLinks.EW_REACT_PACKAGE_JSON)
+ filenames.push(qsFileLinks.EW_REACT_INDEX_HTML)
+ filenames.push(qsFileLinks.EW_REACT_GET_BALANCE_TSX)
+ filenames.push(qsFileLinks.EW_REACT_SEND_TRANSACTION_TSX)
+ filenames.push(qsFileLinks.EW_REACT_SWITCH_NETWORK_TSX)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/config.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/config.mdx
new file mode 100644
index 00000000000..81a7fb94c38
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/config.mdx
@@ -0,0 +1,9 @@
+### Configure Web3Auth
+
+Create a basic config for Web3Auth and pass the `clientId` & `web3AuthNetwork` from your Web3Auth Dashboard Project Settings.
+
+:::info
+
+This is where you can also configure any major settings of your integration as well. Visit our [**configuration section**](/sdk/web/react) of the sdk reference to learn more about the different options available.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/index.ts b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/index.ts
new file mode 100644
index 00000000000..bfd5f3829d2
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/index.ts
@@ -0,0 +1,26 @@
+import * as reactQuickStart from "./reactQuickStart.mdx";
+import * as reactBundlerIssues from "./reactBundlerIssues.mdx";
+import * as login from "./login.mdx";
+import * as logout from "./logout.mdx";
+import * as setupWeb3AuthProvider from "./setupWeb3AuthProvider.mdx";
+import * as wagmiCalls from "./wagmiCalls.mdx";
+import * as registerApp from "../../../../commonSteps/registerApp.mdx";
+import * as installation from "./installation.mdx";
+import * as config from "./config.mdx";
+import * as setupWagmiProvider from "./setupWagmiProvider.mdx";
+import { toSteps } from "../../../../utils";
+
+const STEPS = toSteps({
+ reactQuickStart,
+ reactBundlerIssues,
+ installation,
+ config,
+ setupWagmiProvider,
+ registerApp,
+ wagmiCalls,
+ login,
+ logout,
+ setupWeb3AuthProvider,
+});
+
+export default STEPS;
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/installation.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/installation.mdx
new file mode 100644
index 00000000000..b8d730e99e5
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/installation.mdx
@@ -0,0 +1,11 @@
+### Install Web3Auth
+
+Install the Web3Auth package in your project.
+
+Additionally, for blockchain calls, we're using `wagmi` for this example.
+
+```bash npm2yarn
+npm install --save @web3auth/modal wagmi @tanstack/react-query
+```
+
+[](https://www.npmjs.com/package/@web3auth/modal) [](https://www.jsdelivr.com/package/npm/@web3auth/modal)
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/login.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/login.mdx
new file mode 100644
index 00000000000..2dba8fda7d6
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/login.mdx
@@ -0,0 +1,3 @@
+### Logging in your User
+
+Use the `useWeb3AuthConnect` hook to get access to the login functionality. The modal will prompt the user to login with their wallet and handle the authentication for you.
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/logout.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/logout.mdx
new file mode 100644
index 00000000000..32297f5eb87
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/logout.mdx
@@ -0,0 +1,9 @@
+### Log the user out
+
+Use the `useWeb3AuthDisconnect` hook to log the user out. This will also delete the session information from the local storage of the browser.
+
+:::info
+
+There are multiple other hooks available in the Web3Auth React SDK. Visit our [**hooks section**](/sdk/web/react/hooks) of the sdk reference to learn more about the different hooks available.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/reactBundlerIssues.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/reactBundlerIssues.mdx
new file mode 100644
index 00000000000..e5399e4e8a1
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/reactBundlerIssues.mdx
@@ -0,0 +1,11 @@
+### Troubleshooting
+
+While using any web3 library in React, you may run into issues building. This issue occurs because some core packages like `eccrypto` have certain dependencies which are not present within the browser build environment.
+
+> To solve this, please have a look at our troubleshooting pages about [Vite Issues](/troubleshooting/vite-issues)
+
+:::info
+
+If you face any problem anytime, you can always find help in the [**Web3Auth Community**](https://web3auth.io/community/c/help-pnp/pnp-web/7).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/reactQuickStart.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/reactQuickStart.mdx
new file mode 100644
index 00000000000..d7e8dccce0f
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/reactQuickStart.mdx
@@ -0,0 +1,9 @@
+### Web3Auth Embedded Wallets Quick Start
+
+Add social login and wallet connection functionality to your React app.
+
+Clone the Quick Start in your terminal.
+
+```bash
+npx degit Web3Auth/web3auth-examples/quick-starts/react-quick-start w3a-quick-start
+```
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/setupWagmiProvider.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/setupWagmiProvider.mdx
new file mode 100644
index 00000000000..be32f571f2b
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/setupWagmiProvider.mdx
@@ -0,0 +1,9 @@
+### Setup Wagmi Provider
+
+Since we're using `wagmi` for this example, we need to setup the `WagmiProvider` component. Please use the `WagmiProvider` component from `@web3auth/modal/react/wagmi` to wrap your application.
+
+```tsx
+import { WagmiProvider } from '@web3auth/modal/react/wagmi'
+```
+
+> Apart from that, the standard wagmi setup is being used. You do not need to create any wagmi config, since the Web3Auth config is being used directly. Refer to the [wagmi docs](https://wagmi.sh/react/getting-started) for more information.
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/setupWeb3AuthProvider.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/setupWeb3AuthProvider.mdx
new file mode 100644
index 00000000000..d9b3e256748
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/setupWeb3AuthProvider.mdx
@@ -0,0 +1,3 @@
+### Setup Web3Auth Provider
+
+To enable the hooks across your application, you need to wrap your application with the `Web3AuthProvider` component. This involves using the configuration created in the previous step.
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/stepContent/wagmiCalls.mdx b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/wagmiCalls.mdx
new file mode 100644
index 00000000000..15ba70c76fb
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/stepContent/wagmiCalls.mdx
@@ -0,0 +1,15 @@
+### Making Blockchain Calls
+
+Since Wagmi is configured in this application, you can directly use the wagmi hooks to make blockchain calls. We have demonstrated some commonly used hooks like `useBalance`, `useAccount`, `useSignMessage`, `useSendTransaction` and `useSwitchChain`.
+
+:::info
+
+You can refer to the [**wagmi docs**](https://wagmi.sh/react/api/hooks) for more information on the hooks.
+
+:::
+
+:::tip Other Blockchains
+
+Web3Auth supports all blockchains. Have a look at our [Connect Blockchain](/connect-blockchain/) section of the documentation and choose your blockchain to get started.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react/steps.ts b/src/pages/quickstart/builder/embedded-wallets/react/steps.ts
new file mode 100644
index 00000000000..2e4f77134cd
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react/steps.ts
@@ -0,0 +1,87 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.reactQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.EW_REACT_WEB3AUTHCONTEXT_TSX],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_PACKAGE_JSON,
+ files[qsFileLinks.EW_REACT_PACKAGE_JSON],
+ 'Web3Auth Installation'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.EW_REACT_WEB3AUTHCONTEXT_TSX],
+ 'Dashboard Registration'
+ ),
+ },
+ {
+ ...STEPS.config,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.EW_REACT_WEB3AUTHCONTEXT_TSX],
+ 'Config'
+ ),
+ },
+ {
+ ...STEPS.setupWeb3AuthProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_MAIN_TSX,
+ files[qsFileLinks.EW_REACT_MAIN_TSX],
+ 'Setup Web3Auth Provider'
+ ),
+ },
+ {
+ ...STEPS.setupWagmiProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_MAIN_TSX,
+ files[qsFileLinks.EW_REACT_MAIN_TSX],
+ 'Setup Wagmi Provider'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_APP_TSX,
+ files[qsFileLinks.EW_REACT_APP_TSX],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.wagmiCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_APP_TSX,
+ files[qsFileLinks.EW_REACT_APP_TSX],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_APP_TSX,
+ files[qsFileLinks.EW_REACT_APP_TSX],
+ 'Logout'
+ ),
+ },
+ {
+ ...STEPS.reactBundlerIssues,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_REACT_INDEX_HTML,
+ files[qsFileLinks.EW_REACT_INDEX_HTML],
+ 'Bundler Issues'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/index.ts b/src/pages/quickstart/builder/embedded-wallets/react_native/index.ts
new file mode 100644
index 00000000000..1ca60c52d7e
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/index.ts
@@ -0,0 +1,21 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX)
+ filenames.push(qsFileLinks.EW_PNP_REACT_NATIVE_PACKAGE_JSON)
+ filenames.push(qsFileLinks.EW_PNP_REACT_NATIVE_METRO_CONFIG_JS)
+ filenames.push(qsFileLinks.EW_PNP_REACT_NATIVE_GLOBALS_JS)
+ filenames.push(qsFileLinks.EW_PNP_REACT_NATIVE_INDEX_JS)
+ filenames.push(qsFileLinks.EW_PNP_REACT_NATIVE_BUILD_GRADLE)
+ filenames.push(qsFileLinks.EW_PNP_REACT_NATIVE_PODFILE)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/blockchainCallsReactNative.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/blockchainCallsReactNative.mdx
new file mode 100644
index 00000000000..0bf9ff63631
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/blockchainCallsReactNative.mdx
@@ -0,0 +1,11 @@
+### Making Blockchain Calls
+
+While using the Web3Auth React Native SDK, you get the private key within the user scope. This means that you can use it with any blockchain with their corresponding library within the React Native environment.
+
+:::tip Reference
+
+Have a look at our [Connect Blockchain](/connect-blockchain/) section of the documentation and choose your blockchain to get started.
+
+In this example, we are using the [Ethers](https://docs.ethers.org/v5/cookbook/react-native/) library to make calls to the Ethereum blockchain. You can check out our [Ethereum in React Native](/connect-blockchain/evm/ethereum/react-native) guide of the documentation to get started.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/index.ts b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/index.ts
new file mode 100644
index 00000000000..ed350feb8f7
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/index.ts
@@ -0,0 +1,30 @@
+import * as getUserInfo from '../../../../commonSteps/getUserInfo.mdx'
+import * as reactNativeBundlerIssues from './reactNativeBundlerIssues.mdx'
+import * as registerApp from '../../../../commonSteps/registerApp.mdx'
+import { toSteps } from '../../../../utils'
+import * as blockchainCalls from './blockchainCallsReactNative.mdx'
+import * as initialization from './initializeReactNative.mdx'
+import * as installation from './installationReactNative.mdx'
+import * as login from './login.mdx'
+import * as logout from './logout.mdx'
+import * as rnQuickStart from './rnQuickStart.mdx'
+import * as requirementsAndroid from './requirementsAndroid.mdx'
+import * as requirementsIOS from './requirementsIOS.mdx'
+import * as whitelist from './whitelist.mdx'
+
+const STEPS = toSteps({
+ rnQuickStart,
+ reactNativeBundlerIssues,
+ requirementsAndroid,
+ requirementsIOS,
+ whitelist,
+ installation,
+ registerApp,
+ initialization,
+ login,
+ getUserInfo,
+ blockchainCalls,
+ logout,
+})
+
+export default STEPS
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/initializeReactNative.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/initializeReactNative.mdx
new file mode 100644
index 00000000000..598c59b0e06
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/initializeReactNative.mdx
@@ -0,0 +1,12 @@
+### Initialize Web3Auth
+
+Web3Auth needs to be initialized as soon as your app loads up to enable the user to log in. Preferably done within a constructor, initialization is the step where you can pass on all the configurations for Web3Auth you want.
+
+For initializing Web3Auth React Native SDK, you need to provide your Client ID, the Web3Auth Network of your project and the `redirectUrl` for your application. Make sure to set up Deep Linking so that the Web3Auth SDK can redirect the user back to your application after authentication.
+
+:::tip SDK Reference
+
+- [Initializing Web3Auth React Native SDK](/sdk/mobile/pnp/react-native/initialize).
+- [DeepLinking In React Native](/sdk/mobile/pnp/react-native/install#configuration).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/installationReactNative.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/installationReactNative.mdx
new file mode 100644
index 00000000000..6acab040b67
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/installationReactNative.mdx
@@ -0,0 +1,15 @@
+### Install Web3Auth
+
+Install the Web3Auth package in your React Native project.
+
+```bash npm2yarn
+npm install --save @web3auth/react-native-sdk @web3auth/base @web3auth/ethereum-provider
+```
+
+[](https://www.npmjs.com/package/@web3auth/react-native-sdk) [](https://www.jsdelivr.com/package/npm/@web3auth/react-native-sdk)
+
+:::tip SDK Reference
+
+- [Installing Web3Auth](/sdk/mobile/pnp/react-native/install).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/login.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/login.mdx
new file mode 100644
index 00000000000..42df8f296bb
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/login.mdx
@@ -0,0 +1,11 @@
+### Logging in your User
+
+Use the `login` function in the Web3Auth Instance to log in the user. Just create a button that triggers the `login` for the user of the login method of their choice.
+
+After a successful user login, Web3Auth will redirect back to your app, with a payload stored in the state of the Web3Auth Instance.
+
+:::info SDK Reference
+
+- [`login()` function](/sdk/mobile/pnp/react-native/usage#logging-in-a-user).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/logout.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/logout.mdx
new file mode 100644
index 00000000000..825e5a41549
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/logout.mdx
@@ -0,0 +1,9 @@
+### Log the user out
+
+Use the `logout` function of the Web3Auth Instance to log the user out.
+
+:::info SDK Reference
+
+- [`logout()` function](/sdk/mobile/pnp/react-native/usage#logging-out-a-user).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/reactNativeBundlerIssues.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/reactNativeBundlerIssues.mdx
new file mode 100644
index 00000000000..6380e061d4b
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/reactNativeBundlerIssues.mdx
@@ -0,0 +1,11 @@
+### Fixing Bundler Issues
+
+While using Web3Auth in React Native, you may run into issues building. This issue occurs because some core packages like `eccrypto` have certain dependencies which are not present within the Metro build environment.
+
+:::tip Troubleshooting
+
+To solve this, please have a look at our troubleshooting page:
+
+- [React Native Metro Bundler Issues](/troubleshooting/metro-issues)
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/requirementsAndroid.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/requirementsAndroid.mdx
new file mode 100644
index 00000000000..d1c02844b30
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/requirementsAndroid.mdx
@@ -0,0 +1,7 @@
+:::note Requirements Android
+
+- Android API version `23` or newer is required.
+- `compileSdk` should be `34` or newer.
+- Check `android/app/build.gradle` in your React Native project to change it.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/requirementsIOS.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/requirementsIOS.mdx
new file mode 100644
index 00000000000..e75f4e02416
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/requirementsIOS.mdx
@@ -0,0 +1,9 @@
+:::note Requirements iOS
+
+- iOS 14+
+- Xcode 11.4+ / 12.x
+- Swift 4.x / 5.x
+- `platform :ios` needs to be `14.0`.
+- Check `ios/Podfile` in your React Native project to change it.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/rnQuickStart.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/rnQuickStart.mdx
new file mode 100644
index 00000000000..6dac1afb3eb
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/rnQuickStart.mdx
@@ -0,0 +1,29 @@
+### Web3Auth PnP React Native Quick Start
+
+This guide is designed to help you quickly integrate a basic instance of Web3Auth Plug and Play in your React Native app.
+
+If you face any problem anytime, you can always find help in the [Web3Auth Community](https://web3auth.io/community/c/help-pnp/pnp-rn/19).
+
+:::tip building locally
+
+- Clone the PnP React Native Quick Start Application
+
+ ```shell npm2yarn
+ npx degit Web3Auth/web3auth-react-native-examples/rn-bare-quick-start w3a-quick-start
+ ```
+
+- Install & Run
+
+ ```shell npm2yarn
+ cd w3a-quick-start
+ npm install
+ npm run ios ### or npm run android
+ ```
+
+:::
+
+:::caution
+
+The Web3Auth React Native PnP SDK is not compatible with "Expo Go" app. It is compatible only with Custom Dev Client and EAS builds. Please refer to the [troubleshooting section](/troubleshooting/metro-issues#update-your-metroconfigjs) for more on this.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/whitelist.mdx b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/whitelist.mdx
new file mode 100644
index 00000000000..e482869710c
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/stepContent/whitelist.mdx
@@ -0,0 +1,10 @@
+### Whitelist Package & Bundle ID
+
+To whitelist, you'll need to create a project or use an existing one in the [Developer Dashboard](https://dashboard.web3auth.io).
+
+- Create or Select a Web3Auth project.
+
+- To **Whitelist URLs** section:
+
+ - Add `{SCHEME}://{YOUR_APP_PACKAGE_NAME}` for `Android`,
+ - and, `{bundleId}://auth` for `iOS` to
diff --git a/src/pages/quickstart/builder/embedded-wallets/react_native/steps.ts b/src/pages/quickstart/builder/embedded-wallets/react_native/steps.ts
new file mode 100644
index 00000000000..838dffc4644
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/react_native/steps.ts
@@ -0,0 +1,95 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.rnQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.requirementsAndroid,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_BUILD_GRADLE,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_BUILD_GRADLE],
+ 'Requirements Android'
+ ),
+ },
+ {
+ ...STEPS.requirementsIOS,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_PODFILE,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_PODFILE],
+ 'Requirements iOS'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_PACKAGE_JSON,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_PACKAGE_JSON],
+ 'Web3Auth Installation'
+ ),
+ },
+ {
+ ...STEPS.reactNativeBundlerIssues,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_METRO_CONFIG_JS,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_METRO_CONFIG_JS],
+ 'Bundler Issues'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX],
+ 'Dashboard Registration'
+ ),
+ },
+ {
+ ...STEPS.whitelist,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX],
+ 'Whitelist bundle ID'
+ ),
+ },
+ {
+ ...STEPS.initialization,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX],
+ 'SDK Initialization'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.blockchainCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX,
+ files[qsFileLinks.EW_PNP_REACT_NATIVE_APP_TSX],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/index.ts b/src/pages/quickstart/builder/embedded-wallets/vue/index.ts
new file mode 100644
index 00000000000..c80cc466216
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/index.ts
@@ -0,0 +1,18 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.EW_VUE_WEB3AUTHCONTEXT_TSX)
+ filenames.push(qsFileLinks.EW_VUE_HOME_VUE)
+ filenames.push(qsFileLinks.EW_VUE_APP_VUE)
+ filenames.push(qsFileLinks.EW_VUE_CONFIG_JS)
+ filenames.push(qsFileLinks.EW_VUE_PACKAGE_JSON)
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/config.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/config.mdx
new file mode 100644
index 00000000000..134ce1ee994
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/config.mdx
@@ -0,0 +1,9 @@
+### Configure Web3Auth
+
+Create a basic config for Web3Auth and pass the `clientId` & `web3AuthNetwork` from your Web3Auth Dashboard Project Settings.
+
+:::info
+
+This is where you can also configure any major settings of your integration as well. Visit our [**configuration section**](/sdk/web/vue/config) of the sdk reference to learn more about the different options available.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/index.ts b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/index.ts
new file mode 100644
index 00000000000..cda2f30750e
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/index.ts
@@ -0,0 +1,26 @@
+import * as vueQuickStart from "./vueQuickStart.mdx";
+import * as vueBundlerIssues from "./vueBundlerIssues.mdx";
+import * as login from "./login.mdx";
+import * as logout from "./logout.mdx";
+import * as setupWeb3AuthProvider from "./setupWeb3AuthProvider.mdx";
+import * as wagmiCalls from "./wagmiCalls.mdx";
+import * as registerApp from "../../../../commonSteps/registerApp.mdx";
+import * as installation from "./installation.mdx";
+import * as config from "./config.mdx";
+import * as setupWagmiProvider from "./setupWagmiProvider.mdx";
+import { toSteps } from "../../../../utils";
+
+const STEPS = toSteps({
+ vueQuickStart,
+ vueBundlerIssues,
+ installation,
+ config,
+ setupWagmiProvider,
+ registerApp,
+ wagmiCalls,
+ login,
+ logout,
+ setupWeb3AuthProvider,
+});
+
+export default STEPS;
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/installation.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/installation.mdx
new file mode 100644
index 00000000000..f68fc98929a
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/installation.mdx
@@ -0,0 +1,11 @@
+### Install Web3Auth
+
+Install the Web3Auth package in your project.
+
+> Additionally, for blockchain calls, we're using `@wagmi/vue` and its dependency, `@tanstack/vue-query` for this example.
+
+```bash npm2yarn
+npm install --save @web3auth/modal @wagmi/vue @tanstack/vue-query
+```
+
+[](https://www.npmjs.com/package/@web3auth/modal) [](https://www.jsdelivr.com/package/npm/@web3auth/modal)
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/login.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/login.mdx
new file mode 100644
index 00000000000..935ebf17c79
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/login.mdx
@@ -0,0 +1,3 @@
+### Logging in your User
+
+Use the `useWeb3AuthConnect` composable to get access to the login functionality. The modal will prompt the user to login with their wallet and handle the authentication for you.
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/logout.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/logout.mdx
new file mode 100644
index 00000000000..cd230e718fc
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/logout.mdx
@@ -0,0 +1,9 @@
+### Log the user out
+
+Use the `useWeb3AuthDisconnect` composable to log the user out. This will also delete the session information from the local storage of the browser.
+
+:::info
+
+There are multiple other composables available in the Web3Auth Vue SDK. Visit our [**composables section**](/sdk/web/vue/composables) of the sdk reference to learn more about the different composables available.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/setupWagmiProvider.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/setupWagmiProvider.mdx
new file mode 100644
index 00000000000..e4f91dd280a
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/setupWagmiProvider.mdx
@@ -0,0 +1,9 @@
+### Setup Wagmi Provider
+
+Since we're using `@wagmi/vue` for this example, we need to setup the `WagmiProvider` component. Please use the `WagmiProvider` component from `@web3auth/modal/vue/wagmi` to wrap your application.
+
+```tsx
+import { WagmiProvider } from '@web3auth/modal/vue/wagmi'
+```
+
+> Apart from that, the standard wagmi setup is being used. You do not need to create any wagmi config, since the Web3Auth config is being used directly. Refer to the [wagmi docs](https://wagmi.sh/vue/getting-started) for more information.
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/setupWeb3AuthProvider.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/setupWeb3AuthProvider.mdx
new file mode 100644
index 00000000000..85ce39a3bd3
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/setupWeb3AuthProvider.mdx
@@ -0,0 +1,3 @@
+### Setup Web3Auth Provider
+
+To enable the composables across your application, you need to wrap your application with the `Web3AuthProvider` component. This involves using the configuration created in the previous step.
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/vueBundlerIssues.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/vueBundlerIssues.mdx
new file mode 100644
index 00000000000..c9ca434728a
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/vueBundlerIssues.mdx
@@ -0,0 +1,5 @@
+### Fixing Bundler Issues
+
+While using Web3Auth in Vue, you may run into issues building. This issue occurs because some core packages like `eccrypto` have certain dependencies which are not present within the browser build environment.
+
+> To solve this, please have a look at our troubleshooting pages for [Vite Issues](/troubleshooting/vite-issues)
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/vueQuickStart.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/vueQuickStart.mdx
new file mode 100644
index 00000000000..3591033213d
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/vueQuickStart.mdx
@@ -0,0 +1,15 @@
+### Web3Auth Vue Quick Start
+
+Integrate secure and seamless Web3 authentication into your Vue app using Web3Auth.
+
+Clone the Vue Quick Start Application
+
+```shell
+npx degit Web3Auth/web3auth-examples/quick-starts/vue-quick-start w3a-quick-start
+```
+
+:::info
+
+If you face any problem anytime, you can always find help in the [**Web3Auth Community**](https://web3auth.io/community/c/help-pnp/pnp-web/7).
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/wagmiCalls.mdx b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/wagmiCalls.mdx
new file mode 100644
index 00000000000..ffb17d9bee9
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/stepContent/wagmiCalls.mdx
@@ -0,0 +1,15 @@
+### Making Blockchain Calls
+
+Since Wagmi is configured in this application, you can directly use the wagmi composables to make blockchain calls. We have demonstrated some commonly used composables like `useBalance`, `useAccount`, `useSignMessage`, `useSendTransaction` and `useSwitchChain`.
+
+:::info
+
+You can refer to the [**wagmi docs**](https://wagmi.sh/vue/api/composables) for more information on the composables.
+
+:::
+
+:::tip Other Blockchains
+
+Web3Auth supports all blockchains. Have a look at our [Connect Blockchain](/connect-blockchain/) section of the documentation and choose your blockchain to get started.
+
+:::
diff --git a/src/pages/quickstart/builder/embedded-wallets/vue/steps.ts b/src/pages/quickstart/builder/embedded-wallets/vue/steps.ts
new file mode 100644
index 00000000000..66b7299fd9f
--- /dev/null
+++ b/src/pages/quickstart/builder/embedded-wallets/vue/steps.ts
@@ -0,0 +1,87 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.vueQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.EW_VUE_WEB3AUTHCONTEXT_TSX],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_PACKAGE_JSON,
+ files[qsFileLinks.EW_VUE_PACKAGE_JSON],
+ 'Web3Auth Installation'
+ ),
+ },
+ {
+ ...STEPS.vueBundlerIssues,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_CONFIG_JS,
+ files[qsFileLinks.EW_VUE_CONFIG_JS],
+ 'Bundler Issues'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.EW_VUE_WEB3AUTHCONTEXT_TSX],
+ 'Dashboard Registration'
+ ),
+ },
+ {
+ ...STEPS.config,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.EW_VUE_WEB3AUTHCONTEXT_TSX],
+ 'Config'
+ ),
+ },
+ {
+ ...STEPS.setupWeb3AuthProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_APP_VUE,
+ files[qsFileLinks.EW_VUE_APP_VUE],
+ 'Setup Web3Auth Provider'
+ ),
+ },
+ {
+ ...STEPS.setupWagmiProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_APP_VUE,
+ files[qsFileLinks.EW_VUE_APP_VUE],
+ 'Setup Wagmi Provider'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_HOME_VUE,
+ files[qsFileLinks.EW_VUE_HOME_VUE],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.wagmiCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_HOME_VUE,
+ files[qsFileLinks.EW_VUE_HOME_VUE],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.EW_VUE_HOME_VUE,
+ files[qsFileLinks.EW_VUE_HOME_VUE],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/highlight.ts b/src/pages/quickstart/builder/highlight.ts
new file mode 100644
index 00000000000..1decb70a64a
--- /dev/null
+++ b/src/pages/quickstart/builder/highlight.ts
@@ -0,0 +1,87 @@
+/* eslint-disable no-plusplus */
+function highlightStart(fileContent: string, variableName: string): string {
+ // Add defensive check for undefined fileContent
+ if (!fileContent) {
+ console.warn(`File content is undefined in highlightStart for variable: ${variableName}`)
+ return ''
+ }
+
+ const contentByLine = fileContent.split(`\n`)
+ for (let i = 0; i < contentByLine.length; i += 1) {
+ if (contentByLine[i].includes(`IMP START - ${variableName}`)) {
+ contentByLine[i] = `//highlight-start \n// focus-start`
+ }
+ }
+ return contentByLine.join('\n')
+}
+
+function highlightEnd(fileContent: string, variableName: string): string {
+ // Add defensive check for undefined fileContent
+ if (!fileContent) {
+ console.warn(`File content is undefined in highlightEnd for variable: ${variableName}`)
+ return ''
+ }
+
+ const contentByLine = fileContent.split(`\n`)
+ for (let i = 0; i < contentByLine.length; i += 1) {
+ if (contentByLine[i].includes(`IMP END - ${variableName}`)) {
+ contentByLine[i] = `//highlight-end \n// focus-end`
+ }
+ }
+ return contentByLine.join('\n')
+}
+
+function removeHighlightCode(fileContent: string): string {
+ // Add defensive check for undefined fileContent
+ if (!fileContent) {
+ console.warn(`File content is undefined in removeHighlightCode`)
+ return ''
+ }
+
+ // 2. line that this occurs on
+ const contentByLine = fileContent.split(`\n`)
+ for (let i = 0; i < contentByLine.length; i += 1) {
+ if (contentByLine[i].includes('IMP')) {
+ contentByLine.splice(i, 1)
+ }
+ }
+ return contentByLine.join('\n')
+}
+
+function highlightSection(fileContent: string, variableName: string): string {
+ // Add defensive check for undefined fileContent
+ if (!fileContent) {
+ console.warn(`File content is undefined in highlightSection for variable: ${variableName}`)
+ return ''
+ }
+
+ const highlightStartFile = highlightStart(fileContent, variableName)
+ const highlightedFile = highlightEnd(highlightStartFile, variableName)
+ return removeHighlightCode(highlightedFile)
+}
+
+function highlight(stepIndex, filenames, files, steps) {
+ // Add defensive checks for undefined parameters
+ if (!steps || !steps[stepIndex] || !steps[stepIndex].pointer) {
+ console.warn(`Invalid step data at index ${stepIndex}`)
+ return files || {}
+ }
+
+ const { pointer } = steps[stepIndex]
+ const newFiles = files || {}
+
+ for (let i = 0; i < filenames.length; i++) {
+ if (filenames[i] === pointer.filename) {
+ newFiles[filenames[i]] = highlightSection(
+ pointer.fileContent || files[filenames[i]],
+ pointer.variableName
+ )
+ } else {
+ newFiles[filenames[i]] = removeHighlightCode(files[filenames[i]])
+ }
+ }
+
+ return newFiles
+}
+
+export default highlight
diff --git a/src/pages/quickstart/builder/index.ts b/src/pages/quickstart/builder/index.ts
new file mode 100644
index 00000000000..b146e136445
--- /dev/null
+++ b/src/pages/quickstart/builder/index.ts
@@ -0,0 +1,142 @@
+/* eslint-disable camelcase */
+import { IntegrationBuilder, IntegrationStep } from '../interfaces'
+import {
+ EWQuickStartHostedLinks,
+ EWQuickStartSourceCode,
+ MMSDKQuickStartSourceCode,
+ MMSDKQuickStartHostedLinks,
+} from '../../../utils/qs-map'
+import { PRODUCTS, LANGS_EMBEDDED_WALLETS, LANGS_METAMASK_SDK, EMBEDDED_WALLETS } from './choices'
+
+import highlight from './highlight'
+import EWAndroid from './embedded-wallets/android'
+import EWFlutter from './embedded-wallets/flutter'
+import EWIos from './embedded-wallets/ios'
+import EWReactNative from './embedded-wallets/react_native'
+import EWAngular from './embedded-wallets/angular'
+import EWNextjs from './embedded-wallets/nextjs'
+import EWReact from './embedded-wallets/react'
+import EWVue from './embedded-wallets/vue'
+import MMReact from './metamask-sdk/react'
+import MMNextjs from './metamask-sdk/nextjs'
+
+const frameworks = {
+ EW_ANGULAR: EWAngular,
+ EW_NEXTJS: EWNextjs,
+ EW_REACT: EWReact,
+ EW_VUE: EWVue,
+ EW_ANDROID: EWAndroid,
+ EW_IOS: EWIos,
+ EW_REACT_NATIVE: EWReactNative,
+ EW_FLUTTER: EWFlutter,
+ MMSDK_REACT: MMReact,
+ MMSDK_NEXTJS: MMNextjs,
+}
+
+// Helper function to map framework choice to framework key based on product
+const getFrameworkKey = (product: string, framework: string): string => {
+ if (product === EMBEDDED_WALLETS) {
+ return `EW_${framework}`
+ } else {
+ return `MMSDK_${framework}`
+ }
+}
+
+const builder: IntegrationBuilder = {
+ // Name of the integration builder
+ displayName: 'Web3Auth',
+ // Options that will be displayed in the UI for selection
+ options: {
+ product: {
+ displayName: 'Product',
+ default: PRODUCTS[0].key,
+ type: 'product_selection',
+ choices: PRODUCTS,
+ },
+ framework: {
+ displayName: 'Platform/ Framework',
+ default: LANGS_METAMASK_SDK[0].key,
+ type: 'dropdown',
+ choices: LANGS_METAMASK_SDK,
+ },
+ },
+
+ // Build integrations based on input values
+ build(values: Record, files: Record, stepIndex: number) {
+ const finalValues = values
+
+ const filenames: string[] = []
+ const newFiles = JSON.parse(JSON.stringify(files))
+ const steps: IntegrationStep[] = []
+
+ let frameworkChoices, frameworkDefault
+
+ if (finalValues.product === EMBEDDED_WALLETS) {
+ frameworkChoices = LANGS_EMBEDDED_WALLETS
+ frameworkDefault = LANGS_EMBEDDED_WALLETS[0].key
+ } else {
+ frameworkChoices = LANGS_METAMASK_SDK
+ frameworkDefault = LANGS_METAMASK_SDK[0].key
+ }
+
+ if (!frameworkChoices.map(item => item.key).includes(finalValues.framework)) {
+ finalValues.framework = frameworkDefault
+ }
+
+ this.options = {
+ product: {
+ displayName: 'Product',
+ default: PRODUCTS[0].key,
+ type: 'product_selection',
+ choices: PRODUCTS,
+ },
+ framework: {
+ displayName: 'Platform/ Framework',
+ default: frameworkDefault,
+ type: 'dropdown',
+ choices: frameworkChoices,
+ },
+ }
+
+ let sourceCodeLink, embedLink
+
+ if (finalValues.product === EMBEDDED_WALLETS) {
+ sourceCodeLink = EWQuickStartSourceCode[finalValues.framework]
+ embedLink = EWQuickStartHostedLinks[finalValues.framework]
+ } else {
+ sourceCodeLink = MMSDKQuickStartSourceCode[finalValues.framework]
+ embedLink = MMSDKQuickStartHostedLinks[finalValues.framework]
+ }
+
+ // Get the correct framework key by mapping the choice to the framework object key
+ const frameworkKey = getFrameworkKey(finalValues.product, finalValues.framework)
+
+ // Check if the framework exists before calling build
+ if (!frameworks[frameworkKey]) {
+ throw new Error(`Framework not found: ${frameworkKey}`)
+ }
+
+ frameworks[frameworkKey].build({ ...finalValues, filenames, files: newFiles, steps })
+
+ if (stepIndex >= steps.length) {
+ // eslint-disable-next-line no-param-reassign
+ stepIndex = steps.length - 1
+ }
+
+ const highlightedFiles = highlight(stepIndex, filenames, newFiles, steps)
+
+ return {
+ filenames: filenames.map(it => `${it}`),
+ files: highlightedFiles,
+ steps: steps.map(it => ({
+ ...it,
+ pointer: it.pointer ? { ...it.pointer, filename: `${it.pointer.filename}` } : undefined,
+ })),
+ stepIndex,
+ embedLink,
+ sourceCodeLink,
+ }
+ },
+}
+
+export default builder
diff --git a/src/pages/quickstart/builder/metamask-sdk/nextjs/index.ts b/src/pages/quickstart/builder/metamask-sdk/nextjs/index.ts
new file mode 100644
index 00000000000..b411a124218
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/nextjs/index.ts
@@ -0,0 +1,22 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.MMSDK_NEXTJS_LAYOUT_TSX)
+ filenames.push(qsFileLinks.MMSDK_NEXTJS_PAGE_TSX)
+ filenames.push(qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX)
+ filenames.push(qsFileLinks.MMSDK_NEXTJS_COMPONENTS_APP_TSX)
+ filenames.push(qsFileLinks.MMSDK_NEXTJS_PACKAGE_JSON)
+ filenames.push(qsFileLinks.MMSDK_NEXTJS_GET_BALANCE_TSX)
+ filenames.push(qsFileLinks.MMSDK_NEXTJS_SEND_TRANSACTION_TSX)
+ filenames.push(qsFileLinks.MMSDK_NEXTJS_SWITCH_NETWORK_TSX)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/metamask-sdk/nextjs/stepContent/index.ts b/src/pages/quickstart/builder/metamask-sdk/nextjs/stepContent/index.ts
new file mode 100644
index 00000000000..e9265e1cad6
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/nextjs/stepContent/index.ts
@@ -0,0 +1,24 @@
+import * as nextjsQuickStart from "./nextjsQuickStart.mdx";
+import * as login from "../../react/stepContent/login.mdx";
+import * as logout from "../../react/stepContent/logout.mdx";
+import * as setupWeb3AuthProvider from "../../react/stepContent/setupWeb3AuthProvider.mdx";
+import * as wagmiCalls from "../../react/stepContent/wagmiCalls.mdx";
+import * as registerApp from "../../../../commonSteps/registerApp.mdx";
+import * as installation from "../../react/stepContent/installation.mdx";
+import * as config from "../../react/stepContent/config.mdx";
+import * as setupWagmiProvider from "../../react/stepContent/setupWagmiProvider.mdx";
+import { toSteps } from "../../../../utils";
+
+const STEPS = toSteps({
+ nextjsQuickStart,
+ installation,
+ config,
+ setupWagmiProvider,
+ registerApp,
+ wagmiCalls,
+ login,
+ logout,
+ setupWeb3AuthProvider,
+});
+
+export default STEPS;
diff --git a/src/pages/quickstart/builder/metamask-sdk/nextjs/stepContent/nextjsQuickStart.mdx b/src/pages/quickstart/builder/metamask-sdk/nextjs/stepContent/nextjsQuickStart.mdx
new file mode 100644
index 00000000000..d5132f4fd35
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/nextjs/stepContent/nextjsQuickStart.mdx
@@ -0,0 +1,15 @@
+### MetaMask SDK NextJS Quick Start
+
+Integrate secure and seamless Web3 authentication into your NextJS app using Web3Auth.
+
+Clone the NextJS Quick Start Application
+
+```shell
+npx degit Web3Auth/web3auth-examples/quick-starts/nextjs-quick-start w3a-quick-start
+```
+
+:::info
+
+If you face any problem anytime, you can always find help in the [**Web3Auth Community**](https://web3auth.io/community/c/help-pnp/pnp-web/7).
+
+:::
diff --git a/src/pages/quickstart/builder/metamask-sdk/nextjs/steps.ts b/src/pages/quickstart/builder/metamask-sdk/nextjs/steps.ts
new file mode 100644
index 00000000000..d448779d7e5
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/nextjs/steps.ts
@@ -0,0 +1,79 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.nextjsQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_LAYOUT_TSX,
+ files[qsFileLinks.MMSDK_NEXTJS_LAYOUT_TSX],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_PACKAGE_JSON,
+ files[qsFileLinks.MMSDK_NEXTJS_PACKAGE_JSON],
+ 'Web3Auth Installation'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX,
+ files[qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX],
+ 'Dashboard Registration'
+ ),
+ },
+ {
+ ...STEPS.config,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX,
+ files[qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX],
+ 'Config'
+ ),
+ },
+ {
+ ...STEPS.setupWeb3AuthProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX,
+ files[qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX],
+ 'Setup Web3Auth Provider'
+ ),
+ },
+ {
+ ...STEPS.setupWagmiProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX,
+ files[qsFileLinks.MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX],
+ 'Setup Wagmi Provider'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_COMPONENTS_APP_TSX,
+ files[qsFileLinks.MMSDK_NEXTJS_COMPONENTS_APP_TSX],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.wagmiCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_COMPONENTS_APP_TSX,
+ files[qsFileLinks.MMSDK_NEXTJS_COMPONENTS_APP_TSX],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_NEXTJS_COMPONENTS_APP_TSX,
+ files[qsFileLinks.MMSDK_NEXTJS_COMPONENTS_APP_TSX],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/index.ts b/src/pages/quickstart/builder/metamask-sdk/react/index.ts
new file mode 100644
index 00000000000..d14c27f9fe0
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/index.ts
@@ -0,0 +1,22 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import { ReplaceFileAggregator } from '../../../utils'
+import getSteps from './steps'
+
+const framework = {
+ build({ filenames, files, steps }) {
+ const replacementAggregator = new ReplaceFileAggregator()
+ getSteps(steps, files, replacementAggregator)
+ filenames.push(qsFileLinks.MMSDK_REACT_WEB3AUTHCONTEXT_TSX)
+ filenames.push(qsFileLinks.MMSDK_REACT_MAIN_TSX)
+ filenames.push(qsFileLinks.MMSDK_REACT_APP_TSX)
+ filenames.push(qsFileLinks.MMSDK_REACT_PACKAGE_JSON)
+ filenames.push(qsFileLinks.MMSDK_REACT_INDEX_HTML)
+ filenames.push(qsFileLinks.MMSDK_REACT_GET_BALANCE_TSX)
+ filenames.push(qsFileLinks.MMSDK_REACT_SEND_TRANSACTION_TSX)
+ filenames.push(qsFileLinks.MMSDK_REACT_SWITCH_NETWORK_TSX)
+
+ return { filenames, files, steps }
+ },
+}
+
+export default framework
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/config.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/config.mdx
new file mode 100644
index 00000000000..81a7fb94c38
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/config.mdx
@@ -0,0 +1,9 @@
+### Configure Web3Auth
+
+Create a basic config for Web3Auth and pass the `clientId` & `web3AuthNetwork` from your Web3Auth Dashboard Project Settings.
+
+:::info
+
+This is where you can also configure any major settings of your integration as well. Visit our [**configuration section**](/sdk/web/react) of the sdk reference to learn more about the different options available.
+
+:::
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/index.ts b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/index.ts
new file mode 100644
index 00000000000..a9ec30f1b22
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/index.ts
@@ -0,0 +1,28 @@
+import * as reactQuickStart from './reactQuickStart.mdx'
+import * as reactBundlerIssues from './reactBundlerIssues.mdx'
+import * as login from './login.mdx'
+import * as logout from './logout.mdx'
+import * as setupWeb3AuthProvider from './setupWeb3AuthProvider.mdx'
+import * as wagmiCalls from './wagmiCalls.mdx'
+import * as registerApp from '../../../../commonSteps/registerApp.mdx'
+import * as installation from './installation.mdx'
+import * as config from './config.mdx'
+import * as setupWagmiProvider from './setupWagmiProvider.mdx'
+import * as videoDemo from './videoDemo.mdx'
+import { toSteps } from '../../../../utils'
+
+const STEPS = toSteps({
+ reactQuickStart,
+ reactBundlerIssues,
+ installation,
+ config,
+ setupWagmiProvider,
+ registerApp,
+ wagmiCalls,
+ login,
+ logout,
+ setupWeb3AuthProvider,
+ videoDemo,
+})
+
+export default STEPS
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/installation.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/installation.mdx
new file mode 100644
index 00000000000..b13e77060c8
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/installation.mdx
@@ -0,0 +1,11 @@
+### Install Web3Auth
+
+Install the Web3Auth package in your project.
+
+> Additionally, for blockchain calls, we're using `wagmi` and its dependency, `@tanstack/react-query` for this example.
+
+```bash npm2yarn
+npm install --save @web3auth/modal wagmi @tanstack/react-query
+```
+
+[](https://www.npmjs.com/package/@web3auth/modal) [](https://www.jsdelivr.com/package/npm/@web3auth/modal)
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/login.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/login.mdx
new file mode 100644
index 00000000000..2dba8fda7d6
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/login.mdx
@@ -0,0 +1,3 @@
+### Logging in your User
+
+Use the `useWeb3AuthConnect` hook to get access to the login functionality. The modal will prompt the user to login with their wallet and handle the authentication for you.
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/logout.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/logout.mdx
new file mode 100644
index 00000000000..32297f5eb87
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/logout.mdx
@@ -0,0 +1,9 @@
+### Log the user out
+
+Use the `useWeb3AuthDisconnect` hook to log the user out. This will also delete the session information from the local storage of the browser.
+
+:::info
+
+There are multiple other hooks available in the Web3Auth React SDK. Visit our [**hooks section**](/sdk/web/react/hooks) of the sdk reference to learn more about the different hooks available.
+
+:::
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/reactBundlerIssues.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/reactBundlerIssues.mdx
new file mode 100644
index 00000000000..eb037459599
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/reactBundlerIssues.mdx
@@ -0,0 +1,5 @@
+### Fixing Bundler Issues
+
+While using any web3 library in React, you may run into issues building. This issue occurs because some core packages like `eccrypto` have certain dependencies which are not present within the browser build environment.
+
+> To solve this, please have a look at our troubleshooting pages about [Vite Issues](/troubleshooting/vite-issues)
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/reactQuickStart.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/reactQuickStart.mdx
new file mode 100644
index 00000000000..3766bee2b06
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/reactQuickStart.mdx
@@ -0,0 +1,15 @@
+### MetaMask SDK React Quick Start
+
+Integrate secure and seamless Web3 authentication into your React app using Web3Auth.
+
+Clone the React Quick Start Application
+
+```shell
+npx degit Web3Auth/web3auth-examples/quick-starts/react-quick-start w3a-quick-start
+```
+
+:::info
+
+If you face any problem anytime, you can always find help in the [**Web3Auth Community**](https://web3auth.io/community/c/help-pnp/pnp-web/7).
+
+:::
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/setupWagmiProvider.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/setupWagmiProvider.mdx
new file mode 100644
index 00000000000..be32f571f2b
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/setupWagmiProvider.mdx
@@ -0,0 +1,9 @@
+### Setup Wagmi Provider
+
+Since we're using `wagmi` for this example, we need to setup the `WagmiProvider` component. Please use the `WagmiProvider` component from `@web3auth/modal/react/wagmi` to wrap your application.
+
+```tsx
+import { WagmiProvider } from '@web3auth/modal/react/wagmi'
+```
+
+> Apart from that, the standard wagmi setup is being used. You do not need to create any wagmi config, since the Web3Auth config is being used directly. Refer to the [wagmi docs](https://wagmi.sh/react/getting-started) for more information.
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/setupWeb3AuthProvider.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/setupWeb3AuthProvider.mdx
new file mode 100644
index 00000000000..d9b3e256748
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/setupWeb3AuthProvider.mdx
@@ -0,0 +1,3 @@
+### Setup Web3Auth Provider
+
+To enable the hooks across your application, you need to wrap your application with the `Web3AuthProvider` component. This involves using the configuration created in the previous step.
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/videoDemo.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/videoDemo.mdx
new file mode 100644
index 00000000000..27fb53e07d8
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/videoDemo.mdx
@@ -0,0 +1,19 @@
+---
+contentType: 'media'
+mediaContent:
+ type: 'youtube'
+ youtubeId: 'ga9OH7zzFoE'
+ caption: 'Watch how MetaMask SDK enables seamless Web3 connections - official MetaMask demonstration'
+ autoplay: false
+ muted: false
+---
+
+### See MetaMask SDK in Action
+
+This lightweight video demonstrates how the MetaMask SDK connects with the browser extension. The video shows the key integration points you've just implemented in your React application.
+
+**What you'll see:**
+
+- MetaMask connection flow
+- User wallet interaction
+- Seamless integration experience
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/stepContent/wagmiCalls.mdx b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/wagmiCalls.mdx
new file mode 100644
index 00000000000..15ba70c76fb
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/stepContent/wagmiCalls.mdx
@@ -0,0 +1,15 @@
+### Making Blockchain Calls
+
+Since Wagmi is configured in this application, you can directly use the wagmi hooks to make blockchain calls. We have demonstrated some commonly used hooks like `useBalance`, `useAccount`, `useSignMessage`, `useSendTransaction` and `useSwitchChain`.
+
+:::info
+
+You can refer to the [**wagmi docs**](https://wagmi.sh/react/api/hooks) for more information on the hooks.
+
+:::
+
+:::tip Other Blockchains
+
+Web3Auth supports all blockchains. Have a look at our [Connect Blockchain](/connect-blockchain/) section of the documentation and choose your blockchain to get started.
+
+:::
diff --git a/src/pages/quickstart/builder/metamask-sdk/react/steps.ts b/src/pages/quickstart/builder/metamask-sdk/react/steps.ts
new file mode 100644
index 00000000000..78920f05d77
--- /dev/null
+++ b/src/pages/quickstart/builder/metamask-sdk/react/steps.ts
@@ -0,0 +1,91 @@
+import qsFileLinks from '../../../../../utils/qs-file-links.json'
+import STEPS from './stepContent'
+
+export default function getSteps(steps, files, replacementAggregator) {
+ steps.push(
+ {
+ ...STEPS.videoDemo,
+ // No pointer needed for media content
+ },
+ {
+ ...STEPS.reactQuickStart,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.MMSDK_REACT_WEB3AUTHCONTEXT_TSX],
+ 'Quick Start'
+ ),
+ },
+ {
+ ...STEPS.installation,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_PACKAGE_JSON,
+ files[qsFileLinks.MMSDK_REACT_PACKAGE_JSON],
+ 'Web3Auth Installation'
+ ),
+ },
+ {
+ ...STEPS.reactBundlerIssues,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_INDEX_HTML,
+ files[qsFileLinks.MMSDK_REACT_INDEX_HTML],
+ 'Bundler Issues'
+ ),
+ },
+ {
+ ...STEPS.registerApp,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.MMSDK_REACT_WEB3AUTHCONTEXT_TSX],
+ 'Dashboard Registration'
+ ),
+ },
+ {
+ ...STEPS.config,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_WEB3AUTHCONTEXT_TSX,
+ files[qsFileLinks.MMSDK_REACT_WEB3AUTHCONTEXT_TSX],
+ 'Config'
+ ),
+ },
+ {
+ ...STEPS.setupWeb3AuthProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_MAIN_TSX,
+ files[qsFileLinks.MMSDK_REACT_MAIN_TSX],
+ 'Setup Web3Auth Provider'
+ ),
+ },
+ {
+ ...STEPS.setupWagmiProvider,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_MAIN_TSX,
+ files[qsFileLinks.MMSDK_REACT_MAIN_TSX],
+ 'Setup Wagmi Provider'
+ ),
+ },
+ {
+ ...STEPS.login,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_APP_TSX,
+ files[qsFileLinks.MMSDK_REACT_APP_TSX],
+ 'Login'
+ ),
+ },
+ {
+ ...STEPS.wagmiCalls,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_APP_TSX,
+ files[qsFileLinks.MMSDK_REACT_APP_TSX],
+ 'Blockchain Calls'
+ ),
+ },
+ {
+ ...STEPS.logout,
+ pointer: replacementAggregator.highlightRange(
+ qsFileLinks.MMSDK_REACT_APP_TSX,
+ files[qsFileLinks.MMSDK_REACT_APP_TSX],
+ 'Logout'
+ ),
+ }
+ )
+}
diff --git a/src/pages/quickstart/commonSteps/blockchainCalls.mdx b/src/pages/quickstart/commonSteps/blockchainCalls.mdx
new file mode 100644
index 00000000000..e398d88f4d7
--- /dev/null
+++ b/src/pages/quickstart/commonSteps/blockchainCalls.mdx
@@ -0,0 +1,16 @@
+### Making Blockchain Calls
+
+Web3Auth is chain agnostic. This means that you can use it with any blockchain with the provider exposed by Web3Auth. For EVM and Solana Blockchains Web3Auth exposes special providers for native integrations.
+
+This example demonstrates the connection for an EVM Chain with Web3Auth. You can choose the library of your choice and configure it according the steps given in the respective RPC Files.
+
+:::tip Reference
+
+Have a look at our [Connect Blockchain](/connect-blockchain/) section of the documentation and choose your blockchain to get started.
+
+- [EVM Based Chains](/connect-blockchain/evm/ethereum/web)
+- [Solana](/connect-blockchain/solana)
+- [XRPL](/connect-blockchain/xrpl)
+- [Other Blockchains](/connect-blockchain/)
+
+:::
diff --git a/src/pages/quickstart/commonSteps/getUserInfo.mdx b/src/pages/quickstart/commonSteps/getUserInfo.mdx
new file mode 100644
index 00000000000..d8722c13dd0
--- /dev/null
+++ b/src/pages/quickstart/commonSteps/getUserInfo.mdx
@@ -0,0 +1,5 @@
+### Get User Info
+
+Once logged in, Web3Auth state exposes some information about your logged in user. This is fetched directly from the JWT token and Web3Auth doesn't store this info anywhere.
+
+This information can help you identify your users and provide a more personalized experience.
diff --git a/src/pages/quickstart/commonSteps/registerApp.mdx b/src/pages/quickstart/commonSteps/registerApp.mdx
new file mode 100644
index 00000000000..50a1ce665b9
--- /dev/null
+++ b/src/pages/quickstart/commonSteps/registerApp.mdx
@@ -0,0 +1,18 @@
+---
+contentType: 'hybrid'
+mediaContent:
+ type: 'image'
+ url: '/img/web3auth-dashboard/web3auth-client-id.png'
+---
+
+### Get your Client ID from the Web3Auth Dashboard
+
+Visit the Web3Auth Dashboard and create a new project. Use the Client ID of the project to start your integration.
+
+
+ Go to the Developer Dashboard
+
diff --git a/src/pages/quickstart/index.tsx b/src/pages/quickstart/index.tsx
new file mode 100644
index 00000000000..e37730ff9a3
--- /dev/null
+++ b/src/pages/quickstart/index.tsx
@@ -0,0 +1,864 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+/* eslint-disable react-hooks/exhaustive-deps */
+import { MDXProvider } from "@mdx-js/react";
+import Layout from "@theme/Layout";
+import MDXComponents from "@theme/MDXComponents";
+import classNames from "classnames";
+import copyToClipboard from "copy-to-clipboard";
+import { UIEvent, useEffect, useMemo, useState, useRef, useCallback } from "react";
+import MoonLoader from "react-spinners/BeatLoader";
+import React from "react";
+
+import SEO from "../../components/SEO";
+import IntegrationBuilderCodeView from "../../theme/IntegrationBuilderCodeView";
+import builder from "./builder";
+import styles from "./styles.module.css";
+import { getWindowLocation } from "../../theme/URLParams";
+import { METAMASK_SDK, EMBEDDED_WALLETS } from "./builder/choices";
+import NavigationOverlay from "./NavigationOverlay";
+import MediaStep from "./MediaStep";
+
+const hasRelevantURLParams = () => {
+ const url = new URL(getWindowLocation());
+ const relevantParams = ['product', 'framework'];
+ return relevantParams.some(param => url.searchParams.has(param));
+};
+
+const getDefaultBuilderOptions = () => {
+ const defaultOpts = Object.fromEntries(
+ Object.entries(builder.options).map(([key, option]) => [key, option.default]),
+ );
+ const url = new URL(getWindowLocation());
+
+ const urlOpts = {};
+ url.searchParams.forEach((value, key) => {
+ urlOpts[key] = value;
+ });
+
+ return { ...defaultOpts, ...urlOpts };
+};
+const getURLFromBuilderOptions = (opts: Record, stepIndex): string => {
+ const url = new URL(getWindowLocation());
+ // Clear all existing parameters
+ url.search = "";
+ // Add all builder options except stepIndex (if it somehow exists in opts)
+ for (const [key, value] of Object.entries(opts)) {
+ if (key !== "stepIndex") {
+ url.searchParams.append(key, value);
+ }
+ }
+ // Add stepIndex separately to ensure only one exists
+ url.searchParams.append("stepIndex", stepIndex.toString());
+ return url.toString();
+};
+
+interface NavigationFlowProps {
+ onSelect: (product: string) => void;
+}
+
+// Add new component for step navigation menu
+const StepNavigationMenu: React.FC<{
+ steps: any[];
+ currentStepIndex: number;
+ onStepChange: (index: number) => void;
+ scrollToStep: (stepElementId: string) => void;
+}> = ({ steps, currentStepIndex, onStepChange, scrollToStep }) => {
+ return (
+
+
+ {steps.map((step, index) => (
+
onStepChange(index)}
+ >
+
+ {index < currentStepIndex ? '✓' : index + 1}
+
+
+ ))}
+
+
+ );
+};
+
+
+
+export default function IntegrationBuilderPage(props: any) {
+ // Try different ways to access files
+ const files = props.files || (props.route?.modules?.files ? JSON.parse(props.route.modules.files) : {});
+
+ // Always check URL params dynamically instead of caching at init
+ const [showNavigationOverlay, setShowNavigationOverlay] = useState(false);
+ const [builderOptions, setBuilderOptions] = useState>({});
+ const [isLinkCopied, setLinkCopied] = useState(false);
+ const [IBCountdown, setIBCountdown] = useState(10);
+ const [builderView, setBuilderView] = useState(true);
+ const [abortCountdown, setAbortCountdown] = useState(false);
+ const [showPreviewModal, setShowPreviewModal] = useState(false);
+ const url = new URL(getWindowLocation());
+ const [stepIndex, setStepIndex] = useState(
+ // Always start at step 0 when showing navigation overlay
+ hasRelevantURLParams() ? parseInt(url.searchParams.get("stepIndex") || "0", 10) : 0,
+ );
+ const [loading, setLoading] = useState(false);
+ const [initialLoadComplete, setInitialLoadComplete] = useState(false);
+ const [isManualNavigation, setIsManualNavigation] = useState(false);
+
+ // Check URL params and set initial state
+ useEffect(() => {
+ const hasParams = hasRelevantURLParams();
+
+ if (!hasParams) {
+ setShowNavigationOverlay(true);
+ setBuilderOptions({});
+ setStepIndex(0);
+
+ // Clean URL by removing any step-related params
+ const currentUrl = new URL(getWindowLocation());
+ if (currentUrl.searchParams.has('stepIndex')) {
+ currentUrl.searchParams.delete('stepIndex');
+ // eslint-disable-next-line no-restricted-globals
+ history.replaceState({}, "", currentUrl.toString());
+ }
+ } else {
+ setShowNavigationOverlay(false);
+ setBuilderOptions(getDefaultBuilderOptions());
+ }
+ }, []); // Run once on mount
+
+ // Monitor URL changes and reset to overlay if params are removed
+ useEffect(() => {
+ const checkURLAndResetIfNeeded = () => {
+ const hasParams = hasRelevantURLParams();
+
+ if (!hasParams) {
+ setShowNavigationOverlay(true);
+ setBuilderOptions({});
+ setStepIndex(0);
+ }
+ };
+
+ // Check on popstate (back/forward navigation)
+ const handlePopState = () => {
+ checkURLAndResetIfNeeded();
+ };
+
+ // Check on pushstate/replacestate (programmatic navigation)
+ const originalPushState = history.pushState;
+ const originalReplaceState = history.replaceState;
+
+ history.pushState = function (...args) {
+ originalPushState.apply(history, args);
+ setTimeout(checkURLAndResetIfNeeded, 0);
+ };
+
+ history.replaceState = function (...args) {
+ originalReplaceState.apply(history, args);
+ setTimeout(checkURLAndResetIfNeeded, 0);
+ };
+
+ window.addEventListener('popstate', handlePopState);
+
+ return () => {
+ window.removeEventListener('popstate', handlePopState);
+ history.pushState = originalPushState;
+ history.replaceState = originalReplaceState;
+ };
+ }, []);
+
+ // Simplified URL change detection - only when actually needed
+ useEffect(() => {
+ // Only check if we're showing builder (not overlay) and detect if params disappear
+ if (!showNavigationOverlay) {
+ const hasParams = hasRelevantURLParams();
+ if (!hasParams) {
+ setShowNavigationOverlay(true);
+ setBuilderOptions({});
+ setStepIndex(0);
+ }
+ }
+ }, [showNavigationOverlay]); // Only when overlay state changes
+
+ // Handle navigation overlay selection
+ const handleNavigationSelect = (product: string) => {
+ const newBuilderOptions = {
+ product: product,
+ };
+ setBuilderOptions(newBuilderOptions);
+ setShowNavigationOverlay(false);
+ setStepIndex(0); // Always start at step 0 when selecting from overlay
+
+ // Update URL with selected options and reset to step 0
+ // eslint-disable-next-line no-restricted-globals
+ history.pushState({}, "", getURLFromBuilderOptions(newBuilderOptions, 0));
+ };
+
+ const handleCloseOverlay = () => {
+ // User chose to manually explore - set default options
+ const defaultOptions = getDefaultBuilderOptions();
+ setBuilderOptions(defaultOptions);
+ setShowNavigationOverlay(false);
+ setStepIndex(0); // Always start at step 0 when closing overlay
+
+ // Update URL with default options and reset to step 0
+ // eslint-disable-next-line no-restricted-globals
+ history.pushState({}, "", getURLFromBuilderOptions(defaultOptions, 0));
+ };
+
+ const integration = useMemo(() => {
+ // Don't build integration if overlay is showing
+ if (showNavigationOverlay || Object.keys(builderOptions).length === 0) {
+ return {
+ filenames: [],
+ files: {},
+ steps: [],
+ stepIndex: 0,
+ embedLink: '',
+ sourceCodeLink: ''
+ };
+ }
+ const result = builder.build(builderOptions, files || {}, stepIndex);
+ return result;
+ }, [builderOptions, files, stepIndex, showNavigationOverlay]);
+ const [selectedFilename, setSelectedFilename] = useState(integration.filenames[0] || "");
+ const [activeTab, setActiveTab] = useState<'media' | 'code'>('media');
+
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
+ const ref = useRef(null);
+
+ const onClickCopyLink = async () => {
+ if (isLinkCopied) return;
+
+ copyToClipboard(getWindowLocation());
+ setLinkCopied(true);
+ await delay(500);
+ setLinkCopied(false);
+ };
+
+ const { steps } = integration;
+
+ // Reset to media tab when step changes for hybrid content
+ useEffect(() => {
+ if (steps[stepIndex]?.contentType === 'hybrid') {
+ setActiveTab('media');
+ }
+ }, [stepIndex, steps]);
+
+ // Navigation handlers with smooth scrolling to exact top
+ const scrollToStep = useCallback((stepElementId: string) => {
+ const stepsContainer = document.getElementById('steps-container');
+ const targetStepElement = document.getElementById(stepElementId);
+
+ if (stepsContainer && targetStepElement) {
+ const containerRect = stepsContainer.getBoundingClientRect();
+ const stepRect = targetStepElement.getBoundingClientRect();
+ const scrollOffset = stepRect.top - containerRect.top + stepsContainer.scrollTop;
+
+ // Use same custom easing for manual navigation
+ const startPosition = stepsContainer.scrollTop;
+ const distance = scrollOffset - startPosition;
+ const duration = Math.min(400, Math.abs(distance) * 0.5); // Quick, responsive timing
+ const startTime = performance.now();
+
+ const easeOutCubic = (t: number): number => {
+ return 1 - Math.pow(1 - t, 3);
+ };
+
+ const animateScroll = (currentTime: number) => {
+ const elapsed = currentTime - startTime;
+ const progress = Math.min(elapsed / duration, 1);
+ const easedProgress = easeOutCubic(progress);
+
+ stepsContainer.scrollTop = startPosition + (distance * easedProgress);
+
+ if (progress < 1) {
+ requestAnimationFrame(animateScroll);
+ }
+ };
+
+ requestAnimationFrame(animateScroll);
+ }
+ }, []);
+
+ const onChangeStep = useCallback((index: number) => {
+ if (index >= steps.length) {
+ // eslint-disable-next-line no-param-reassign
+ index = steps.length - 1;
+ }
+ if (index < 0) {
+ // eslint-disable-next-line no-param-reassign
+ index = 0;
+ }
+ if (steps[index] && steps[index].pointer && steps[index].pointer.filename) {
+ setSelectedFilename(steps[index].pointer.filename);
+ }
+ setStepIndex(index);
+ setIsManualNavigation(true);
+
+ // Update URL with new step index
+ const url = new URL(getWindowLocation());
+ url.searchParams.set('stepIndex', index.toString());
+ // eslint-disable-next-line no-restricted-globals
+ history.pushState({}, "", url.toString());
+
+ // Scroll to the step to ensure it's visible
+ setTimeout(() => {
+ scrollToStep(`step-${index}`);
+ // Reset manual navigation flag very quickly to not interfere with user scrolling
+ setTimeout(() => {
+ setIsManualNavigation(false);
+ }, 50); // Very short delay to only block during initial animation
+ }, 10); // Minimal delay to ensure state update is complete
+ }, [steps, scrollToStep]);
+
+ const handlePreviousStep = useCallback(() => {
+ if (stepIndex > 0) {
+ scrollToStep(`step-${stepIndex - 1}`);
+ }
+ }, [stepIndex, scrollToStep]);
+
+ const handleNextStep = useCallback(() => {
+ if (stepIndex < steps.length - 1) {
+ scrollToStep(`step-${stepIndex + 1}`);
+ }
+ }, [stepIndex, steps.length, scrollToStep]);
+
+ // Natural scroll-spy navigation with gentle snapping
+ useEffect(() => {
+ const stepsContainer = document.getElementById('steps-container');
+ if (!stepsContainer || steps.length === 0) return;
+
+ const handleScroll = () => {
+ if (isManualNavigation) return;
+
+ // Check if scrolled to bottom first
+ const isAtBottom = stepsContainer.scrollTop + stepsContainer.clientHeight >= stepsContainer.scrollHeight - 10;
+
+ if (isAtBottom) {
+ // Force last step when at bottom
+ const lastStepIndex = steps.length - 1;
+ if (stepIndex !== lastStepIndex) {
+ setStepIndex(lastStepIndex);
+ }
+ return;
+ }
+
+ // Simple scroll-spy: find which step is most visible
+ const containerRect = stepsContainer.getBoundingClientRect();
+ const containerTop = containerRect.top;
+ const containerBottom = containerRect.bottom;
+
+ let bestStepIndex = stepIndex;
+ let maxVisibleArea = 0;
+
+ steps.forEach((_, index) => {
+ const stepElement = document.getElementById(`step-${index}`);
+ if (stepElement) {
+ const stepRect = stepElement.getBoundingClientRect();
+
+ // Calculate visible area of this step
+ const visibleTop = Math.max(stepRect.top, containerTop);
+ const visibleBottom = Math.min(stepRect.bottom, containerBottom);
+ const visibleArea = Math.max(0, visibleBottom - visibleTop);
+
+ if (visibleArea > maxVisibleArea) {
+ maxVisibleArea = visibleArea;
+ bestStepIndex = index;
+ }
+ }
+ });
+
+ // Update step if it changed
+ if (bestStepIndex !== stepIndex) {
+ setStepIndex(bestStepIndex);
+ }
+ };
+
+ const handleKeyDown = (event: KeyboardEvent) => {
+ // Only handle keyboard navigation when not in an input field
+ if (
+ event.target instanceof HTMLInputElement ||
+ event.target instanceof HTMLTextAreaElement ||
+ event.target instanceof HTMLSelectElement
+ ) {
+ return;
+ }
+
+ switch (event.key) {
+ case 'ArrowLeft':
+ event.preventDefault();
+ handlePreviousStep();
+ break;
+ case 'ArrowRight':
+ event.preventDefault();
+ handleNextStep();
+ break;
+ case 'ArrowUp':
+ event.preventDefault();
+ handlePreviousStep();
+ break;
+ case 'ArrowDown':
+ event.preventDefault();
+ handleNextStep();
+ break;
+ default:
+ break;
+ }
+ };
+
+ stepsContainer.addEventListener('scroll', handleScroll, { passive: true });
+ document.addEventListener('keydown', handleKeyDown);
+
+ return () => {
+ stepsContainer.removeEventListener('scroll', handleScroll);
+ document.removeEventListener('keydown', handleKeyDown);
+ };
+ }, [stepIndex, steps.length, onChangeStep, handlePreviousStep, handleNextStep]);
+
+ const onScrollLeft = (e: UIEvent) => {
+ if (!initialLoadComplete) return;
+
+ const el = e.target as HTMLDivElement;
+ const stepEls = el.getElementsByClassName(styles.stepContainer);
+ const containerHeight = el.clientHeight;
+ const scrollTop = el.scrollTop;
+ const scrollHeight = el.scrollHeight;
+ const viewportCenter = scrollTop + containerHeight / 2;
+
+ // Check if we're at the bottom of the scroll container
+ const isAtBottom = scrollTop + containerHeight >= scrollHeight - 5; // 5px tolerance
+
+ let closestIndex = 0;
+ let closestDistance = Infinity;
+
+ // If we're at the bottom, automatically select the last element
+ if (isAtBottom && stepEls.length > 0) {
+ closestIndex = stepEls.length - 1;
+ } else {
+ // Otherwise, find the element closest to center
+ for (let i = 0; i < stepEls.length; i += 1) {
+ const stepEl = stepEls.item(i) as HTMLDivElement;
+ const elementCenter = stepEl.offsetTop + stepEl.offsetHeight / 2;
+ const distance = Math.abs(viewportCenter - elementCenter);
+
+ if (distance < closestDistance) {
+ closestDistance = distance;
+ closestIndex = i;
+ }
+ }
+ }
+
+ // Only update if the closest step is different from current
+ if (closestIndex !== stepIndex) {
+ onChangeStep(closestIndex);
+ }
+ };
+
+ // const onChangeOptionValue = (optionKey: string, event: ChangeEvent) => {
+ // const el = event.target as HTMLInputElement;
+ // const finalOptionValue = el.checked ? YES : NO;
+
+ // setBuilderOptions({
+ // ...builderOptions,
+ // [optionKey]: finalOptionValue,
+ // });
+ // };
+
+ const onChangeDropdown = (optionKey: string, optionValue: string) => {
+ setBuilderOptions({
+ ...builderOptions,
+ [optionKey]: optionValue,
+ });
+ setAbortCountdown(true);
+ };
+
+ const toggleBuilderView = async () => {
+ if (builderView) {
+ setBuilderView(false);
+ const element = ref.current as HTMLElement | null;
+ if (element) {
+ element.scrollIntoView({ behavior: "smooth" });
+ }
+ } else {
+ setBuilderView(true);
+ }
+ };
+
+ const togglePreviewModal = (link?: string) => {
+ if (showPreviewModal) {
+ setShowPreviewModal(false);
+ } else {
+ setLoading(true);
+ setShowPreviewModal(true);
+ }
+ };
+
+ useEffect(() => {
+ // Don't update anything if overlay is showing
+ if (showNavigationOverlay) return;
+
+ setStepIndex(integration.stepIndex);
+ // Update selected file when either integration changed
+ if (integration.steps && integration.steps[integration.stepIndex] && integration.steps[integration.stepIndex].pointer) {
+ setSelectedFilename(integration.steps[integration.stepIndex].pointer.filename);
+ } else if (integration.filenames && integration.filenames.length > 0) {
+ setSelectedFilename(integration.filenames[0]);
+ }
+
+ for (const optionKey in builderOptions) {
+ if (builder.options[optionKey]) {
+ const check = builder.options[optionKey].choices.flatMap((choice) => choice.key);
+ if (!check.includes(builderOptions[optionKey])) {
+ const option = Object.fromEntries(
+ Object.entries(builder.options).map(([key, optioning]) => [key, optioning.default]),
+ );
+ onChangeDropdown(optionKey, option[optionKey]);
+ }
+ }
+ }
+ // Update query params only if we have valid options
+ if (Object.keys(builderOptions).length > 0) {
+ // eslint-disable-next-line no-restricted-globals
+ history.pushState({}, "", getURLFromBuilderOptions(builderOptions, stepIndex));
+ }
+ }, [builderOptions, integration, stepIndex, isLinkCopied, showNavigationOverlay]);
+
+ // Update the useEffect for initial navigation
+ useEffect(() => {
+ // Initialize to the step index from URL
+ if (stepIndex > 0 && steps && steps[stepIndex]) {
+ const stepElements = document.getElementsByClassName(styles.stepContainer);
+ if (stepElements && stepElements.length > stepIndex) {
+ const element = stepElements[stepIndex] as HTMLElement;
+ if (element) {
+ element.scrollIntoView({ behavior: "smooth" });
+
+ // Set initialLoadComplete after a delay to allow scrolling to complete
+ setTimeout(() => {
+ setInitialLoadComplete(true);
+ }, 1000);
+ }
+ }
+ } else {
+ setInitialLoadComplete(true);
+ }
+ }, []);
+
+ useEffect(() => {
+ if (IBCountdown > 0) {
+ setTimeout(() => setIBCountdown(IBCountdown - 1), 1000);
+ }
+ if (IBCountdown === 0 && builderView && !abortCountdown) {
+ toggleBuilderView();
+ }
+ }, [IBCountdown]);
+
+ const optionRender = (key, option) => {
+ switch (option.type) {
+ case "dropdown":
+ return (
+
+
+
+ );
+
+ case "product_selection":
+ return (
+
+
+ {option.choices.map((value) => (
+
+ {value.key === METAMASK_SDK && (
+ onChangeDropdown(key, value.key)}
+ >
+
+ {value.displayName}
+
+
+ )}
+ {value.key === EMBEDDED_WALLETS && (
+ onChangeDropdown(key, value.key)}
+ >
+
+ {value.displayName}
+
+
+ )}
+
+ ))}
+
+
+ );
+
+ default:
+ return ;
+ }
+ };
+
+ const handleModalClick = (event) => {
+ event.stopPropagation(); // Prevents the click from propagating to the background
+ };
+
+ return (
+
+
+ {showNavigationOverlay && (
+
+ )}
+
+
+ {/* Top Control Pane */}
+
+
+ {/* Product Selection */}
+ {Object.entries(builder.options).map(([key, option]) =>
+ option.type === 'product_selection' ? optionRender(key, option) : null
+ )}
+
+ {/* Dropdown and Actions */}
+
+ {Object.entries(builder.options).map(([key, option]) =>
+ option.type === 'dropdown' ? optionRender(key, option) : null
+ )}
+
+
+ {integration.embedLink && (
+
+ )}
+
+
+
+
+ {showPreviewModal && (
+
togglePreviewModal()}>
+
+
+
Preview
+
+
+
+ {loading && (
+
+ {" "}
+
+
+ )}
+
+
+
+ )}
+
+
+
+
+
+ {steps && steps.length > 0 ? (
+
+ {steps.map((step, index) => (
+
stepIndex,
+ [styles.nextStep]: index === stepIndex + 1,
+ })}
+ id={`step-${index}`}
+ data-step-index={index}
+ onClick={() => {
+ if (index !== stepIndex) {
+ onChangeStep(index);
+ }
+ }}
+ style={{
+ cursor: index !== stepIndex ? 'pointer' : 'default'
+ }}
+ >
+
+
+ Step {index + 1} of {steps.length}
+
+
{step.title}
+
{step.content}
+
+
+ {/* Simple separator between steps */}
+ {index < steps.length - 1 && (
+
+ )}
+
+ ))}
+
+ ) : (
+
+
Loading...
+
Please wait while we load the integration steps.
+
+ )}
+
+
+
+ {/* Conditionally render media or code based on step content type */}
+ {steps[stepIndex]?.contentType === 'media' ? (
+
+ ) : steps[stepIndex]?.contentType === 'hybrid' ? (
+
+ {/* Tab Navigation */}
+
+
+
+
+
+ {/* Tab Content */}
+
+ {activeTab === 'media' ? (
+
+ ) : (
+
+ setSelectedFilename(filename)}
+ />
+
+ )}
+
+
+ ) : (
+ // Default: show code view for 'text' content type or undefined
+
setSelectedFilename(filename)}
+ />
+ )}
+
+
+ {/* Step Navigation Menu */}
+ {steps && steps.length > 0 && (
+
+ )}
+
+
+
+ );
+}
diff --git a/src/pages/quickstart/interfaces.ts b/src/pages/quickstart/interfaces.ts
new file mode 100644
index 00000000000..7dcc0e689fa
--- /dev/null
+++ b/src/pages/quickstart/interfaces.ts
@@ -0,0 +1,53 @@
+import { ReactNode } from 'react'
+
+export interface IntegrationStep {
+ title?: string // Optional title for the step
+ content?: ReactNode // Make optional for media-only steps
+ contentType?: 'text' | 'media' | 'hybrid' // Default: 'text'
+ mediaContent?: {
+ type: 'image' | 'video' | 'youtube'
+ url?: string // For images or regular videos
+ youtubeId?: string // For YouTube videos (just the video ID)
+ alt?: string
+ caption?: string
+ poster?: string // For videos
+ autoplay?: boolean
+ loop?: boolean
+ muted?: boolean
+ }
+ pointer?: {
+ filename: string
+ variableName: string
+ fileContent: string
+ range: string
+ }
+}
+
+export interface Integration {
+ filenames: string[]
+ files: Record
+ steps: IntegrationStep[]
+ stepIndex: number
+ embedLink: string
+ sourceCodeLink: string
+}
+
+export interface DisplayChoice {
+ key: string
+ displayName: string
+}
+
+export interface IntegrationBuilder {
+ displayName: string
+ options: Record<
+ string,
+ {
+ displayName: string
+ default: string
+ type: 'dropdown' | 'product_selection'
+ choices: DisplayChoice[]
+ }
+ >
+
+ build(values: Record, files: Record, stepIndex: number): Integration
+}
diff --git a/src/pages/quickstart/styles.module.css b/src/pages/quickstart/styles.module.css
new file mode 100644
index 00000000000..0ca6aa263db
--- /dev/null
+++ b/src/pages/quickstart/styles.module.css
@@ -0,0 +1,1358 @@
+.container {
+ width: 100%;
+ height: 100%;
+}
+
+.loadingContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ color: var(--ifm-color-content);
+ background-color: var(--ifm-background-surface-color);
+ font-size: large;
+}
+
+.iframeContainer {
+ width: 100%;
+ height: 90%;
+ overflow: scroll;
+ border-radius: 16px;
+ background: var(--ifm-color-white);
+}
+
+.previewModalContainer {
+ position: fixed;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 100%;
+ width: 100%;
+ background: rgba(0, 0, 0, 0.5);
+ z-index: 1000;
+}
+
+.previewModal {
+ display: block;
+ background: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ box-shadow: 0px 1px 2px var(--ifm-color-emphasis-200);
+ border-radius: 16px;
+ padding: 24px;
+ margin: 5%;
+ height: 90%;
+ width: 90%;
+ overflow: hidden;
+}
+
+.optionsPane {
+ padding: 16px;
+ border-radius: 16px;
+ max-height: max-content;
+ overflow: hidden;
+ background: var(--ifm-color-second-narbar);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2),
+ 0 6px 12px rgba(0, 0, 0, 0.1),
+ 0 10px 20px #00000026;
+ position: fixed;
+ bottom: 1%;
+ right: 10px;
+ /* transition: max-height 0.3s ease-in-out, width 0.3s ease-in-out, padding 0.3s ease-in-out; */
+ width: max-content;
+ z-index: 1000;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
+
+.optionsHeader {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.optionsHeaderText {
+ font-weight: 700;
+ font-size: 18px;
+ line-height: 30px;
+ color: var(--ifm-color-content);
+ margin: 0;
+}
+
+.optionsHeaderButtonsContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-evenly;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.optionsContainer {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-end;
+ flex-wrap: wrap;
+}
+
+.builderContainer {
+ display: flex;
+ flex-direction: col;
+ justify-content: flex-start;
+ align-items: center;
+ flex-wrap: wrap;
+}
+
+.utilityButtonsContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 8px;
+ flex-wrap: wrap;
+}
+
+.productSelectionRow {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ width: 100%;
+ margin-bottom: 12px;
+}
+
+.controlsRow {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 8px;
+ flex-wrap: wrap;
+}
+
+/* Top Control Pane */
+.topControlPane {
+ width: 100%;
+ background: var(--ifm-background-surface-color);
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+ padding: 8px 16px;
+ top: 0;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.topControlContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ margin: 0;
+ gap: 20px;
+}
+
+.controlActions {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 8px;
+ flex-shrink: 0;
+}
+
+.cols {
+ width: 100%;
+ display: block;
+ flex-direction: row;
+}
+
+.leftCol {
+ overflow-x: hidden;
+ overflow-y: scroll;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+.stepContainer {
+ padding: 0.25rem var(--ifm-navbar-padding-horizontal);
+ border-left: 6px solid transparent;
+ cursor: pointer;
+ background: var(--ifm-color-emphasis-100);
+}
+
+.stepContainer:hover {
+ border-color: var(--ifm-color-primary-darkest);
+}
+
+.stepContainer.stepSelected {
+ /* background-color: var(--ifm-background-surface-color); */
+ background: var(--ifm-color-emphasis-200);
+
+ border-color: var(--ifm-color-primary);
+}
+
+/* .stepContainer p {
+ margin-bottom: 0;
+} */
+
+.stepContainer .stepHeader {
+ font-family: var(--ifm-font-family-base);
+ font-weight: 600;
+ margin-bottom: 12px;
+ font-size: 20px;
+}
+
+.rightCol {
+ width: 100%;
+}
+
+/* Switch */
+.switch {
+ position: relative;
+ display: inline-block;
+ width: 40px;
+ height: 24px;
+}
+
+.switch input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: var(--ifm-color-emphasis-200);
+ -webkit-transition: 0.4s;
+ transition: 0.4s;
+ border-radius: 34px;
+}
+
+.slider:before {
+ position: absolute;
+ content: "";
+ height: 16px;
+ width: 16px;
+ left: 4px;
+ bottom: 4px;
+ background-color: var(--ifm-color-gray-400);
+ -webkit-transition: 0.4s;
+ transition: 0.4s;
+ border-radius: 50%;
+}
+
+.switch input:checked+.slider {
+ background-color: var(--ifm-color-primary-light);
+}
+
+/* Dark mode: Better visibility for checked switches */
+[data-theme='dark'] .switch input:checked+.slider {
+ background-color: var(--ifm-color-primary);
+}
+
+.switch input:checked+.slider:before {
+ background-color: var(--ifm-color-white);
+}
+
+.switch input:focus+.slider {
+ box-shadow: 0 0 1px var(--ifm-color-primary-light);
+}
+
+input:checked+.slider:before {
+ -webkit-transform: translateX(16px);
+ -ms-transform: translateX(16px);
+ transform: translateX(16px);
+}
+
+/* Drowpdown */
+.w3DropdownLink {
+ cursor: pointer;
+ margin-right: 0.5rem;
+}
+
+.w3DropdownLink:after {
+ border: none;
+ content: "";
+ display: inline-block;
+ margin-right: 10px;
+ box-sizing: border-box;
+ position: absolute;
+ width: 7px;
+ height: 7px;
+ border-bottom: 2px solid;
+ border-right: 2px solid;
+ transform: rotate(45deg);
+ right: -18px;
+ top: 9px;
+}
+
+.w3DropdownMenu {
+ padding: 4px 0;
+ margin-top: -5px;
+}
+
+.w3DropdownMenu li {
+ padding: 4px 12px;
+ cursor: pointer;
+}
+
+.w3DropdownMenu li:hover {
+ background-color: var(--ifm-color-emphasis-100);
+}
+
+
+
+.heading {
+ color: var(--ifm-color-content);
+ margin-top: 30px;
+ margin-bottom: 20px;
+ font-weight: 600;
+ font-size: 24px;
+ line-height: 150%;
+}
+
+.productSelection {
+ display: block;
+ width: 100%;
+}
+
+.productSelection h3 {
+ font-weight: 600 !important;
+ font-size: 18px;
+ line-height: 150%;
+ color: var(--ifm-color-content);
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 0;
+}
+
+.cardContainer {
+ display: flex;
+ flex-direction: row;
+ gap: 6px;
+ flex-wrap: wrap;
+ min-width: 300px;
+}
+
+.card,
+.selectedCard {
+ padding: 8px 16px;
+ background: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: 6px;
+ min-width: 90px;
+ text-decoration: none;
+ color: var(--ifm-color-content);
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.card:hover {
+ border-color: var(--ifm-color-primary-light);
+}
+
+.selectedCard {
+ border: 1px solid var(--ifm-color-primary);
+}
+
+.cardTitle {
+ font-size: 13px;
+ line-height: 18px;
+ color: var(--ifm-color-content);
+ font-weight: 500 !important;
+ margin: 0;
+ text-align: center;
+}
+
+.list {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+.list h3 {
+ font-weight: 600 !important;
+ font-size: 14px;
+ line-height: 21px;
+ color: var(--ifm-color-content);
+ padding: 0;
+ margin: 0;
+ margin-bottom: 8px;
+ margin-top: 16px;
+}
+
+.list select {
+ padding: 8px 16px;
+ font-weight: 500 !important;
+ font-size: 14px;
+ line-height: 20px;
+ color: var(--ifm-color-content);
+ border-radius: 6px;
+ outline: none;
+ cursor: pointer;
+ min-width: 140px;
+ background: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ background-image: url("data:image/svg+xml;utf8,");
+ background-repeat: no-repeat;
+ background-position: center right 12px;
+ transition: all 0.2s ease;
+}
+
+.list select:hover {
+ border-color: var(--ifm-color-primary-light);
+}
+
+.list select::-ms-expand {
+ display: none;
+}
+
+.list :disabled {
+ color: var(--ifm-color-emphasis-600);
+}
+
+.copyButton,
+.previewButton,
+.copyButton2,
+.previewButton2 {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
+ padding: 8px 16px;
+ border-radius: 6px;
+ background: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ cursor: pointer;
+ font-size: 14px;
+ line-height: 20px;
+ font-weight: 600 !important;
+ min-width: 100px;
+ transition: all 0.2s ease;
+ text-decoration: none;
+ color: var(--ifm-color-content);
+}
+
+.copyButton:hover,
+.copyButton2:hover {
+ border-color: var(--ifm-color-primary-light);
+ box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.15);
+ transform: translateY(-1px);
+}
+
+.previewButton,
+.previewButton2 {
+ background: var(--ifm-color-primary);
+ border: 1px solid var(--ifm-color-primary);
+ box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.15);
+ color: var(--ifm-background-surface-color);
+}
+
+/* Dark mode: Better contrast for preview buttons */
+[data-theme='dark'] .previewButton,
+[data-theme='dark'] .previewButton2 {
+ background: var(--ifm-color-primary-dark);
+ border: 1px solid var(--ifm-color-primary-dark);
+ color: white;
+}
+
+.previewButton:hover,
+.previewButton2:hover {
+ background: var(--ifm-color-primary-light);
+ border-color: var(--ifm-color-primary-light);
+ box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
+ transform: translateY(-1px);
+}
+
+/* Dark mode: Better contrast for preview button hover */
+[data-theme='dark'] .previewButton:hover,
+[data-theme='dark'] .previewButton2:hover {
+ background: var(--ifm-color-primary);
+ border-color: var(--ifm-color-primary);
+ color: white;
+}
+
+.hideButton {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ font-size: 14px;
+ font-weight: 500 !important;
+ cursor: pointer;
+ line-height: 21px;
+ gap: 8px;
+ border-radius: 8px;
+ background: none;
+ border: none;
+ color: var(--ifm-color-content);
+}
+
+.closeButton {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ font-size: 14px;
+ font-weight: 500 !important;
+ cursor: pointer;
+ line-height: 21px;
+ gap: 8px;
+ background: none;
+ border: none;
+}
+
+@media (max-width: 768px) {
+ .topControlPane {
+ padding: 6px 12px;
+ }
+
+ .topControlContainer {
+ flex-direction: column;
+ align-items: stretch;
+ gap: 12px;
+ }
+
+ .cardContainer {
+ justify-content: center;
+ min-width: auto;
+ }
+
+ .controlActions {
+ justify-content: center;
+ flex-wrap: wrap;
+ gap: 8px;
+ }
+
+ .copyButton2,
+ .previewButton2 {
+ min-width: 80px;
+ padding: 8px 12px;
+ font-size: 13px;
+ }
+
+ .list select {
+ min-width: 120px;
+ }
+}
+
+@media (min-width: 960px) {
+ .cols {
+ display: flex;
+ height: calc(100vh - 86px - 45px);
+ position: relative;
+ }
+
+ .leftCol {
+ width: 50%;
+ overflow-x: hidden;
+ overflow-y: scroll;
+ margin-left: 0;
+ margin-right: 0;
+ display: flex;
+ flex-direction: column;
+ scroll-behavior: smooth;
+ scrollbar-width: thin;
+ scroll-padding-top: 0;
+ }
+
+ .rightCol {
+ width: 50%;
+ }
+}
+
+/* Step Navigation Menu */
+.stepNavigationMenu {
+ background: var(--ifm-background-surface-color);
+ border-left: 1px solid var(--ifm-color-emphasis-300);
+ padding: 1rem 0;
+ overflow-y: auto;
+ position: sticky;
+ top: 0;
+ height: calc(100vh - 86px - 45px);
+}
+
+.stepMenuHeader {
+ padding: 0 1rem 0.5rem 1rem;
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+ margin-bottom: 0.5rem;
+}
+
+.stepMenuHeader h4 {
+ margin: 0;
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--ifm-color-emphasis-600);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.stepMenuList {
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+}
+
+.stepMenuItem {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0.5rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ border-left: 3px solid transparent;
+}
+
+.stepMenuItem:hover {
+ background: var(--ifm-color-emphasis-100);
+}
+
+.stepMenuItemActive {
+ background: var(--ifm-color-emphasis-200);
+ border-left-color: var(--ifm-color-primary);
+}
+
+.stepMenuItemCompleted {
+ color: var(--ifm-color-success);
+}
+
+.stepMenuNumber {
+ width: 24px;
+ height: 24px;
+ border-radius: 50%;
+ background: var(--ifm-color-emphasis-200);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 12px;
+ font-weight: 600;
+ flex-shrink: 0;
+}
+
+.stepMenuItemActive .stepMenuNumber {
+ background: var(--ifm-color-primary);
+ color: white;
+}
+
+/* Dark mode: Ensure good contrast for active step numbers */
+[data-theme='dark'] .stepMenuItemActive .stepMenuNumber {
+ background: var(--ifm-color-primary-dark);
+ color: white;
+}
+
+.stepMenuItemCompleted .stepMenuNumber {
+ background: var(--ifm-color-success);
+ color: black;
+}
+
+/* Dark mode: Use darker success color for better visibility with black text */
+[data-theme='dark'] .stepMenuItemCompleted .stepMenuNumber {
+ background: var(--consumer-green-dark);
+ color: white;
+}
+
+/* Steps Scroll Container */
+.stepsScrollContainer {
+ display: flex;
+ flex-direction: column;
+ min-height: 100%;
+ padding-bottom: 100vh;
+ /* Enough space for last step to reach top */
+}
+
+/* Step Section - Fixed height containers for consistent scrolling */
+.stepSection {
+ transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
+ height: 85vh;
+ /* Fixed height for ALL steps */
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ position: relative;
+ padding: 1rem 0;
+ /* Consistent padding */
+ box-sizing: border-box;
+ /* Remove margin-bottom for consistent spacing */
+}
+
+/* First step uses same height as others */
+.stepSection:first-child {
+ height: 85vh;
+ /* Same as all other steps */
+ padding: 1rem 0;
+ /* Same padding as others */
+}
+
+/* Active Step */
+.activeStep {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ z-index: 2;
+}
+
+.activeStep .stepContainer {
+ border-left: none;
+ cursor: default;
+ background: var(--ifm-background-surface-color);
+ padding: 1.5rem;
+ margin-top: 0;
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08);
+ border-radius: 12px;
+ border: 1px solid var(--ifm-color-emphasis-200);
+ transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
+ flex: 1;
+ overflow-y: auto;
+ max-height: calc(85vh - 4rem);
+ /* Adjusted for new container height */
+}
+
+/* Previous Steps */
+.previousStep {
+ opacity: 0.65;
+ transform: translateY(-3px) scale(0.98);
+ z-index: 1;
+}
+
+.previousStep .stepContainer {
+ border-left: none;
+ background: var(--ifm-color-emphasis-50);
+ padding: 1.5rem;
+ border-radius: 10px;
+ transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ flex: 1;
+ overflow-y: auto;
+ max-height: calc(85vh - 4rem);
+ /* Adjusted for new container height */
+}
+
+.previousStep .stepProgressIndicator {
+ background: var(--ifm-color-success);
+ color: black;
+}
+
+/* Dark mode: Use darker success color for better contrast with white text */
+[data-theme='dark'] .previousStep .stepProgressIndicator {
+ background: var(--consumer-green-dark);
+ color: white;
+}
+
+/* Upcoming Steps */
+.upcomingStep {
+ opacity: 0.5;
+ transform: translateY(3px) scale(0.97);
+ z-index: 0;
+ transition: all 0.3s ease;
+}
+
+.upcomingStep .stepContainer {
+ border-left: none;
+ background: var(--ifm-color-emphasis-25);
+ padding: 1.5rem;
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: 10px;
+ transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
+ flex: 1;
+ overflow-y: auto;
+ max-height: calc(85vh - 4rem);
+ /* Adjusted for new container height */
+}
+
+.upcomingStep:hover {
+ opacity: 0.8;
+ transform: translateY(0px) scale(0.99);
+}
+
+.upcomingStep[style*="pointer"] {
+ cursor: pointer !important;
+}
+
+.upcomingStep[style*="pointer"]:hover {
+ opacity: 0.85;
+ transform: translateY(-1px) scale(1);
+}
+
+.upcomingStep .stepProgressIndicator {
+ background: var(--ifm-color-emphasis-400);
+ color: var(--ifm-color-emphasis-700);
+}
+
+/* Make the immediate next step much more visible */
+.nextStep {
+ opacity: 0.9;
+ transform: translateY(1px) scale(0.99);
+ transition: all 0.3s ease;
+}
+
+.nextStep .stepContainer {
+ background: var(--ifm-color-emphasis-75);
+ border: 1px solid var(--ifm-color-emphasis-400);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+ flex: 1;
+ overflow-y: auto;
+ max-height: calc(85vh - 4rem);
+ /* Adjusted for new container height */
+}
+
+.nextStep .stepHeader {
+ color: var(--ifm-color-content);
+ opacity: 1;
+ font-weight: 600;
+}
+
+/* Ensure upcoming step titles are readable */
+.upcomingStep .stepHeader {
+ color: var(--ifm-color-content);
+ opacity: 0.9;
+}
+
+.nextStep:hover {
+ opacity: 0.98;
+ transform: translateY(-1px) scale(1);
+}
+
+.nextStep[style*="pointer"]:hover {
+ opacity: 1;
+ transform: translateY(-2px) scale(1.01);
+}
+
+/* Step Progress Indicator */
+.stepProgressIndicator {
+ background: var(--ifm-color-primary-light);
+ color: white;
+ padding: 0.25rem 0.75rem;
+ border-radius: 12px;
+ font-size: 12px;
+ font-weight: 600;
+ display: inline-block;
+ margin-bottom: 1rem;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+/* Dark mode: Use darker background for better contrast with white text */
+[data-theme='dark'] .stepProgressIndicator {
+ background: var(--ifm-color-primary-dark);
+ color: white;
+}
+
+
+
+/* Step Separator */
+.stepSeparator {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin: 4rem 0;
+ opacity: 0.3;
+}
+
+.separatorLine {
+ width: 100%;
+ height: 1px;
+ background: linear-gradient(to right,
+ transparent 0%,
+ var(--ifm-color-emphasis-300) 50%,
+ transparent 100%);
+}
+
+
+
+/* Completion Indicator */
+.completionIndicator {
+ text-align: center;
+ padding: 2rem;
+ margin: 4rem 1.5rem 2rem 1.5rem;
+ background: linear-gradient(135deg, var(--ifm-color-success-light) 0%, var(--ifm-color-success) 100%);
+ color: white;
+ border-radius: 12px;
+ font-size: 18px;
+ font-weight: 600;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+/* Dark mode: Better contrast for completion indicator */
+[data-theme='dark'] .completionIndicator {
+ background: linear-gradient(135deg, var(--consumer-green-dark) 0%, var(--institution-green-dark) 100%);
+ color: white;
+}
+
+/* Smooth transition animations */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes fadeInUp {
+ from {
+ opacity: 0;
+ transform: translateY(20px) scale(0.98);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+/* Mobile responsive adjustments */
+@media (max-width: 960px) {
+ .stepNavigationMenu {
+ display: none;
+ }
+
+ .leftCol {
+ width: 100% !important;
+ max-height: 70vh;
+ overflow-y: auto;
+ }
+
+ .rightCol {
+ width: 100% !important;
+ margin-top: 1rem;
+ }
+
+ .cols {
+ flex-direction: column;
+ height: auto;
+ }
+
+ .stepSection {
+ height: 75vh;
+ /* Fixed height for mobile */
+ padding: 0.5rem 0;
+ /* Consistent padding */
+ }
+
+ .stepSection:first-child {
+ height: 75vh;
+ /* Same as all other steps on mobile */
+ padding: 0.5rem 0;
+ /* Same padding as others */
+ }
+
+ .stepSection .stepContainer {
+ max-height: calc(75vh - 3rem);
+ /* Adjusted for new mobile container height */
+ }
+
+ .stepSeparator {
+ margin: 3rem 0;
+ }
+
+ .stepsScrollContainer {
+ padding-bottom: 80vh;
+ /* Enough space for last step on mobile */
+ }
+
+ .stepProgressIndicator {
+ font-size: 10px;
+ padding: 0.2rem 0.5rem;
+ }
+
+ .completionIndicator {
+ font-size: 16px;
+ padding: 1.5rem;
+ }
+}
+
+/* Media Step Styles */
+.mediaStepContainer {
+ height: 100%;
+ width: 100%;
+ background: var(--ifm-background-surface-color);
+ border-radius: 12px;
+ border: 1px solid var(--ifm-color-emphasis-200);
+ overflow: hidden;
+}
+
+/* Hybrid Layout Styles */
+.hybridContainer {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ gap: 1rem;
+}
+
+.hybridMediaSection {
+ flex: 0 0 40%;
+ min-height: 200px;
+ max-height: 400px;
+}
+
+.hybridCodeSection {
+ flex: 1;
+ min-height: 300px;
+ overflow: hidden;
+}
+
+.hybridMediaStep {
+ height: 100%;
+ border-radius: 8px;
+ border: 1px solid var(--ifm-color-emphasis-200);
+}
+
+/* Responsive Design for Media Components */
+@media (max-width: 996px) {
+ .hybridContainer {
+ flex-direction: column;
+ }
+
+ .hybridMediaSection {
+ flex: 0 0 250px;
+ max-height: 250px;
+ }
+
+ .hybridCodeSection {
+ flex: 1;
+ min-height: 200px;
+ }
+}
+
+@media (max-width: 768px) {
+ .mediaStepContainer {
+ border-radius: 8px;
+ }
+
+ .hybridMediaSection {
+ flex: 0 0 200px;
+ max-height: 200px;
+ }
+
+ .hybridMediaStep {
+ border-radius: 6px;
+ }
+}
+
+/* Hybrid Tab Layout Styles */
+.hybridTabContainer {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ background: var(--ifm-background-surface-color);
+ border-radius: 12px;
+ border: 1px solid var(--ifm-color-emphasis-200);
+ overflow: hidden;
+}
+
+.tabNavigation {
+ display: flex;
+ background: var(--ifm-background-surface-color);
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+ padding: 0;
+ margin: 0;
+ box-shadow: 0 1px 0 0 var(--ifm-color-emphasis-200);
+}
+
+.tabButton {
+ flex: 1;
+ padding: 14px 20px;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--ifm-color-content-secondary);
+ transition: all 0.15s ease-in-out;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-transform: none;
+ letter-spacing: 0.02em;
+}
+
+.tabButton:hover {
+ background: var(--ifm-hover-overlay);
+ color: var(--ifm-color-content);
+}
+
+.tabButtonActive {
+ background: transparent;
+ color: var(--ifm-color-primary);
+ position: relative;
+}
+
+.tabButtonActive::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 3px;
+ background: var(--ifm-color-primary);
+ border-radius: 3px 3px 0 0;
+}
+
+.tabButtonActive:hover {
+ background: var(--ifm-hover-overlay);
+ color: var(--ifm-color-primary);
+}
+
+.tabContent {
+ flex: 1;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ box-sizing: border-box;
+}
+
+/* Ensure both tab contents have identical sizing */
+.tabContent>* {
+ width: 100% !important;
+ height: 100% !important;
+ flex: 1 1 auto;
+ box-sizing: border-box;
+ min-width: 0;
+ min-height: 0;
+ max-width: none !important;
+ max-height: none !important;
+ position: relative;
+ overflow: hidden;
+}
+
+.tabContent .hybridMediaStep {
+ width: 100% !important;
+ height: 100% !important;
+ border-radius: 0;
+ border: none;
+ flex: 1;
+ max-width: none !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ min-width: 0 !important;
+ overflow: hidden;
+}
+
+.tabContent .hybridCodeView {
+ width: 100% !important;
+ height: 100% !important;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ max-width: none !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ min-width: 0 !important;
+ overflow: hidden;
+}
+
+.tabContent .hybridCodeView>* {
+ width: 100% !important;
+ height: 100%;
+ flex: 1;
+ max-width: none !important;
+}
+
+/* Force light background for code blocks in hybrid tabs */
+.tabContent .hybridCodeView .prism-code {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+.tabContent .hybridCodeView pre {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+.tabContent .hybridCodeView code {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+/* Override any dark theme code styling in hybrid tabs */
+.tabContent .hybridCodeView [class*="language-"] {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+.tabContent .hybridCodeView [class*="language-"] pre {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+.tabContent .hybridCodeView [class*="language-"] code {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+/* Override the IntegrationBuilderCodeView container background */
+.tabContent .hybridCodeView .container {
+ background: var(--ifm-background-surface-color) !important;
+}
+
+.tabContent .hybridCodeView .body {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+/* Ensure code text has proper contrast on light background */
+.tabContent .hybridCodeView .token {
+ color: var(--ifm-color-content) !important;
+}
+
+/* Override any CSS variables that might affect code block styling */
+.tabContent .hybridCodeView {
+ --prism-background-color: var(--ifm-color-emphasis-100) !important;
+ --ifm-pre-background: var(--ifm-color-emphasis-100) !important;
+ --w3a-ib-code-tab-background-color: var(--ifm-color-emphasis-100) !important;
+}
+
+/* Override header styling to match light theme */
+.tabContent .hybridCodeView .header {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+/* Target specific scrollbar backgrounds */
+.tabContent .hybridCodeView ::-webkit-scrollbar {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+/* Keep tab items styling intact */
+.tabContent .hybridCodeView .tabs__item {
+ background: transparent !important;
+}
+
+.tabContent .hybridCodeView .tabs__item--active {
+ background: var(--ifm-color-emphasis-300) !important;
+}
+
+/* Additional CodeBlock overrides */
+.tabContent .hybridCodeView [class*="codeBlockContainer"] {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+.tabContent .hybridCodeView [class*="codeBlock"] {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+/* Comprehensive override for all possible code-related backgrounds */
+.tabContent .hybridCodeView div[class*="code"],
+.tabContent .hybridCodeView div[class*="prism"],
+.tabContent .hybridCodeView div[class*="theme"] {
+ background: var(--ifm-color-emphasis-100) !important;
+}
+
+/* Override any MediaStep internal constraints in hybrid tabs */
+.tabContent .hybridMediaStep .mediaContainer {
+ width: 100% !important;
+ max-width: none !important;
+ margin: 0 !important;
+ border-radius: 0 !important;
+ border: none !important;
+ display: flex !important;
+ flex-direction: column !important;
+ height: 100% !important;
+}
+
+.tabContent .hybridMediaStep .mediaContent {
+ width: 100% !important;
+ max-width: none !important;
+ display: flex !important;
+ flex-direction: column !important;
+ height: 100% !important;
+ flex: 1 !important;
+ align-items: center !important;
+ justify-content: center !important;
+ padding: 2rem !important;
+ background: var(--ifm-background-surface-color) !important;
+}
+
+/* Force exact same layout for both tab types */
+.hybridTabContainer .tabContent>div {
+ width: 100% !important;
+ height: 100% !important;
+ display: flex !important;
+ flex-direction: column !important;
+ flex: 1 !important;
+ min-width: 0 !important;
+ min-height: 0 !important;
+ box-sizing: border-box !important;
+}
+
+/* Override media element constraints in hybrid tabs */
+.tabContent .hybridMediaStep .youtubePlayer,
+.tabContent .hybridMediaStep .videoPlayer {
+ width: 100% !important;
+ max-width: none !important;
+ margin: 0 !important;
+ border-radius: 0 !important;
+ aspect-ratio: unset !important;
+ height: 100% !important;
+ min-height: unset !important;
+ max-height: 100% !important;
+}
+
+/* Special styling for images in hybrid tabs */
+.tabContent .hybridMediaStep .imageDisplay {
+ width: auto !important;
+ max-width: 90% !important;
+ height: auto !important;
+ max-height: 80% !important;
+ margin: auto !important;
+ border-radius: 12px !important;
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12) !important;
+ object-fit: contain !important;
+ display: block !important;
+}
+
+/* Caption styling for hybrid tabs */
+.tabContent .hybridMediaStep .mediaCaption {
+ margin-top: 1rem !important;
+ padding: 0.75rem 1rem !important;
+ background: var(--ifm-color-emphasis-100) !important;
+ border-radius: 8px !important;
+ max-width: 90% !important;
+ text-align: center !important;
+ margin-left: auto !important;
+ margin-right: auto !important;
+}
+
+.tabContent .hybridMediaStep .mediaCaption p {
+ margin: 0 !important;
+ font-size: 14px !important;
+ color: var(--ifm-color-content-secondary) !important;
+ line-height: 1.4 !important;
+}
+
+/* Responsive styles for tabs */
+@media (max-width: 768px) {
+ .tabButton {
+ padding: 12px 16px;
+ font-size: 14px;
+ font-weight: 600;
+ }
+
+ .hybridTabContainer {
+ border-radius: 8px;
+ }
+
+ .tabButtonActive::after {
+ height: 2px;
+ }
+
+ /* Mobile image adjustments */
+ .tabContent .hybridMediaStep .mediaContent {
+ padding: 1rem !important;
+ }
+
+ .tabContent .hybridMediaStep .imageDisplay {
+ max-width: 95% !important;
+ max-height: 85% !important;
+ border-radius: 8px !important;
+ }
+}
\ No newline at end of file
diff --git a/src/pages/quickstart/utils.tsx b/src/pages/quickstart/utils.tsx
new file mode 100644
index 00000000000..a0163af0522
--- /dev/null
+++ b/src/pages/quickstart/utils.tsx
@@ -0,0 +1,110 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import React from "react";
+
+import { IntegrationStep } from "./interfaces";
+
+interface Module {
+ default: React.FC;
+ frontMatter?: Record;
+}
+
+export function toStep(mod: Module): IntegrationStep {
+ const Component = mod.default;
+ const step: IntegrationStep = {
+ content: , // Always include the MDX content
+ };
+
+ // Add contentType if specified
+ if (mod.frontMatter?.contentType) {
+ step.contentType = mod.frontMatter.contentType;
+ }
+
+ // Add mediaContent if specified
+ if (mod.frontMatter?.mediaContent) {
+ step.mediaContent = mod.frontMatter.mediaContent;
+ }
+
+ return step;
+}
+
+export function toSteps(mods: T) {
+ return Object.fromEntries(Object.entries(mods).map(([key, mod]) => [key, toStep(mod as Module)])) as { [key in keyof T]: IntegrationStep };
+}
+
+export class ReplaceFileAggregator {
+ replacementOutcomes = [];
+
+ replaceFileVariable(fileContent: string, filename: string, variableName: string, replacement: string): string {
+ // Add defensive check for undefined/null fileContent
+ if (!fileContent || typeof fileContent !== 'string') {
+ console.warn(`Warning: fileContent is ${fileContent} for file ${filename}. Using empty string.`);
+ return '';
+ }
+
+ // 1. number of new lines to derive OFFSET
+ const replacementLineCount = replacement.split(`\n`).length - 3;
+ // 2. line that this occurs on
+ const contentByLine = fileContent.split(`\n`);
+ let variableLine;
+ for (let i = 0; i < contentByLine.length; i += 1) {
+ if (contentByLine[i].includes(variableName)) {
+ variableLine = i;
+ }
+ }
+ variableLine += 1;
+ const exp = `\n *// REPLACE-${variableName}-\n *`;
+ const re = new RegExp(exp, "gm");
+
+ this.replacementOutcomes.push({ filename, replacementLineCount, variableLine });
+ return fileContent.replace(re, replacement);
+ }
+
+ highlightRange(
+ filename: string,
+ fileContent: string,
+ variableName: string,
+ ): { range: string; filename: string; fileContent: string; variableName: string } {
+ // Add defensive check for undefined/null fileContent
+ if (!fileContent || typeof fileContent !== 'string') {
+ console.warn(`Warning: fileContent is ${fileContent} for file ${filename} in highlightRange. Using empty string.`);
+ return { range: "1-1", filename, fileContent: "", variableName };
+ }
+
+ const contentByLine = fileContent.split(`\n`);
+ const startLine = [];
+ const endLine = [];
+ for (let i = 0; i < contentByLine.length; i += 1) {
+ if (contentByLine[i].includes(`IMP START - ${variableName}`)) {
+ startLine.push(i);
+ }
+ if (contentByLine[i].includes(`IMP END - ${variableName}`)) {
+ endLine.push(i);
+ }
+ }
+
+ return { range: `${startLine[0]}-${endLine[0]}`, filename, fileContent, variableName };
+ }
+
+ rangeOffsetEditor(pointer: { range: string; filename: string }) {
+ const numbersInRange = pointer.range.split("-");
+ for (let x = 0; x < numbersInRange.length; x += 1) {
+ let actualNum = parseInt(numbersInRange[x], 10);
+ let offset = 0;
+ for (let i = 0; i < this.replacementOutcomes.length; i += 1) {
+ const mutatedActualNum = actualNum + offset;
+ if (mutatedActualNum > this.replacementOutcomes[i].variableLine && this.replacementOutcomes[i].filename === pointer.filename) {
+ offset += this.replacementOutcomes[i].replacementLineCount;
+ }
+ }
+ actualNum += offset;
+ numbersInRange[x] = actualNum.toString();
+ }
+ return { range: numbersInRange.join("-"), filename: pointer.filename };
+ }
+}
+
+export function replaceFileVariable(fileContent: string, variableName: string, replacement: string) {
+ const exp = `\n *// REPLACE-${variableName}-\n *`;
+ const re = new RegExp(exp, "gm");
+ return fileContent.replace(re, replacement);
+}
diff --git a/src/plugins/docusaurus-plugin-guides/index.js b/src/plugins/docusaurus-plugin-guides/index.js
new file mode 100644
index 00000000000..7f70379d597
--- /dev/null
+++ b/src/plugins/docusaurus-plugin-guides/index.js
@@ -0,0 +1,43 @@
+const path = require("path");
+const fs = require("fs");
+const util = require("util");
+const glob = require("glob");
+const matter = require("gray-matter");
+
+const globAsync = util.promisify(glob);
+const readFileAsync = util.promisify(fs.readFile);
+
+module.exports = (context, options) => ({
+ name: "docusaurus-plugin-guides",
+ getPathsToWatch() {
+ const dir = path.resolve(context.siteDir, "src", "pages", "guides");
+ return [`${dir}/**/*.{md,mdx}`];
+ },
+ async loadContent() {
+ const dir = path.resolve(context.siteDir, "src", "pages", "guides");
+
+ const filenames = await globAsync("**/*.{md,mdx}", { cwd: dir, nodir: true });
+ const frontMatters = {};
+
+ for (const filename of filenames) {
+ const src = await readFileAsync(path.join(dir, filename), "utf-8");
+ const { data } = matter(src);
+ const splits = filename.split(".");
+ splits.pop();
+ const name = splits.join("."); // Trim .md
+ frontMatters[name] = data;
+ }
+
+ return frontMatters;
+ },
+ async contentLoaded({ content, actions }) {
+ const { createData, addRoute } = actions;
+ const contentHub = await createData("guides.json", JSON.stringify(content));
+ addRoute({
+ path: "/guides",
+ exact: true,
+ component: "@site/src/components/GuidesPage",
+ modules: { content: contentHub },
+ });
+ },
+});
diff --git a/src/plugins/docusaurus-plugin-virtual-files/index.js b/src/plugins/docusaurus-plugin-virtual-files/index.js
new file mode 100644
index 00000000000..57dba514aae
--- /dev/null
+++ b/src/plugins/docusaurus-plugin-virtual-files/index.js
@@ -0,0 +1,100 @@
+const axios = require("axios");
+const util = require("util");
+const fs = require("fs");
+const path = require("path");
+const joi = require("joi");
+const readFileAsync = util.promisify(fs.readFile);
+const writeFileAsync = util.promisify(fs.writeFile);
+
+const environment = process.env.IB_ENV || "development";
+
+async function fetchHostedFile(filename) {
+ try {
+ const response = await axios.get("https://raw.githubusercontent.com/" + filename);
+ var fileContent = response.data;
+ if (typeof fileContent !== "string") {
+ fileContent = JSON.stringify(fileContent, null, 2);
+ }
+ return fileContent;
+ } catch (e) {
+ return ""; // Return empty string as fallback
+ }
+}
+
+const qsFileLinks = require("../../utils/qs-file-links.json");
+module.exports = (context, options) => ({
+ name: "docusaurus-plugin-virtual-files",
+ async loadContent() {
+ console.log('🔄 Virtual files plugin: loadContent called');
+ const dir = path.resolve(context.siteDir, options.rootDir);
+ const filenames = Object.values(qsFileLinks);
+ const fileContents = {};
+ if (!fs.existsSync(dir)) {
+ fs.mkdirSync(dir, { recursive: true });
+ }
+
+ if (environment === "development") {
+ var data = "";
+ for (const filename of filenames) {
+ const filePath = path.join(dir, filename.replaceAll("/", "-"));
+ try {
+ data = await readFileAsync(filePath, "utf8");
+ } catch (e) {
+ data = await fetchHostedFile(filename);
+
+ try {
+ await writeFileAsync(filePath, data);
+ } catch (error) {
+ console.log(`Error saving ${filename} to cache: ${error.message}`);
+ }
+ }
+ fileContents[filename] = data;
+ }
+ } else {
+ for (const filename of filenames) {
+ fileContents[filename] = await fetchHostedFile(filename);
+ }
+ }
+
+ const emptyFiles = Object.entries(fileContents).filter(([key, value]) => !value || value.length === 0);
+ if (emptyFiles.length > 0) {
+ console.log(`Warning: ${emptyFiles.length} files are empty:`, emptyFiles.map(([key]) => key));
+ }
+
+ console.log(`✅ Virtual files plugin: Loaded ${Object.keys(fileContents).length} files`);
+ return fileContents;
+ },
+ async contentLoaded({ content, actions }) {
+ const { createData, addRoute } = actions;
+
+ console.log('🔄 Virtual files plugin: contentLoaded called');
+ console.log(`📁 Content has ${Object.keys(content).length} files`);
+
+ // Create JSON data file like web3auth-docs
+ const files = await createData("files.json", JSON.stringify(content));
+ console.log('📄 Created files.json data:', files);
+
+ const routePath = "/quickstart";
+ console.log(`🛣️ Adding route at path: ${routePath}`);
+ console.log(`📍 Component path: @site/src/pages/quickstart`);
+
+ addRoute({
+ path: routePath,
+ exact: true,
+ component: "@site/src/pages/quickstart",
+ modules: {
+ files,
+ },
+ });
+
+ console.log('✅ Virtual files plugin: Route added successfully');
+ },
+});
+
+module.exports.validateOptions = ({ options, validate }) =>
+ validate(
+ joi.object({
+ rootDir: joi.string().required(),
+ }),
+ options,
+ );
diff --git a/src/scss/custom.scss b/src/scss/custom.scss
index 881a76eb81c..601882d107c 100644
--- a/src/scss/custom.scss
+++ b/src/scss/custom.scss
@@ -652,6 +652,43 @@ ol {
}
}
+/* Code Focus & Blur Effects */
+%blur-transition {
+ filter: blur(0.5px);
+ opacity: 0.3;
+ transition:
+ filter 0.2s ease,
+ opacity 0.2s ease;
+ will-change: filter, opacity;
+}
+
+%clear-blur {
+ filter: none;
+ opacity: 1;
+}
+
+.code-unfocus {
+ @extend %blur-transition;
+}
+
+.blurred-code {
+ .token-line:not(.code-focus) {
+ @extend %blur-transition;
+ }
+
+ .code-focus {
+ @extend %clear-blur;
+ }
+
+ &:hover .token-line:not(.code-focus) {
+ @extend %clear-blur;
+ }
+}
+
+code:hover .code-unfocus {
+ @extend %clear-blur;
+}
+
.git-diff-remove {
background-color: #ff000020;
display: block;
@@ -731,7 +768,7 @@ ol {
align-items: flex-start;
justify-content: center;
padding: 5px;
- background-color: var(--w3a-color-icon-background);
+ background-color: var(--ifm-code-background);
border-radius: 8px;
svg {
@@ -739,13 +776,13 @@ ol {
vertical-align: top;
width: 26px;
height: 24px;
- color: var(--w3a-color-icon-gray);
+ color: var(--ifm-menu-color);
transition: color 0.2s ease;
}
}
&:hover span {
- background-color: var(--w3a-color-icon-active-background);
+ background-color: var(--ifm-color-primary-light);
svg {
color: var(--ifm-color-primary);
@@ -754,17 +791,20 @@ ol {
h2 {
@extend .dropdown__link;
+ font-family: var(--ifm-font-family-base);
font-size: 1.6rem !important;
+ font-weight: 500;
text-decoration: none !important;
margin: 0 0 4px 0;
color: inherit;
}
p {
+ font-family: var(--ifm-font-family-base);
font-size: 1.4rem;
line-height: 1.8rem;
font-weight: 400 !important;
- color: var(--w3a-color-icon-gray);
+ color: var(--ifm-menu-color);
text-decoration: none !important;
margin: 0;
}
@@ -846,4 +886,357 @@ div[class^='theme-announcement-bar'] {
/* Add scroll padding to account for sticky product banner */
html {
scroll-padding-top: 10rem;
-}
\ No newline at end of file
+}
+
+.sdk-menu {
+ display: flex;
+ flex-direction: row;
+ border-radius: 8px;
+ padding: 0;
+}
+
+.sdk-menu h2 {
+ font-family: var(--ifm-font-family-base);
+ font-size: 1.6rem;
+ font-weight: 500 !important;
+ margin: 0 0 4px 0;
+}
+
+.sdk-menu h3 {
+ font-family: var(--ifm-font-family-base);
+ text-transform: uppercase;
+ font-size: 1.2rem;
+ line-height: 1.5;
+ font-weight: 500 !important;
+ color: var(--ifm-menu-color);
+ padding-left: 14px;
+ margin: 0;
+ margin-top: 14px;
+ opacity: 0.8;
+}
+
+.sdk-menu p {
+ font-family: var(--ifm-font-family-base);
+ font-size: 1.4rem;
+ line-height: 1.8rem;
+ font-weight: 400 !important;
+ margin: 0;
+ color: var(--ifm-menu-color);
+}
+
+.product-selection-menu {
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ justify-content: space-between;
+ padding: 16px;
+ gap: var(--ifm-spacing-horizontal);
+ border-radius: 8px;
+ background-color: var(--ifm-background-surface-color);
+ margin: 0;
+}
+
+.product-selection-menu ul {
+ display: flex;
+ padding-left: 0;
+ color: var(--ifm-navbar-link-color);
+ list-style-type: none;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.product-selection-menu a {
+ display: flex;
+ padding-left: 14px;
+ color: var(--ifm-navbar-link-color);
+ flex-direction: row;
+ justify-content: space-between;
+ width: 190px;
+ align-items: center;
+ border-radius: 8px;
+ margin: 0;
+ border: 0;
+ background-color: var(--ifm-background-surface-color);
+ transition:
+ background-color 0.2s ease,
+ color 0.2s ease;
+ text-decoration: none !important;
+
+ &:hover,
+ &:focus {
+ background-color: var(--ifm-hover-overlay);
+ color: var(--ifm-navbar-link-hover-color);
+ outline: none;
+ }
+}
+
+.product-selection-menu .selected {
+ background-color: var(--ifm-color-primary);
+ color: var(--general-white);
+
+ &:hover {
+ background-color: var(--ifm-color-primary);
+ color: var(--general-white);
+ }
+}
+
+/* Dark mode: Use dark text on primary color for better contrast */
+[data-theme='dark'] .product-selection-menu .selected {
+ color: var(--general-black);
+
+ &:hover {
+ color: var(--general-black);
+ }
+}
+
+.product-selection-menu a div {
+ font-family: var(--ifm-font-family-base);
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: center;
+ text-align: left;
+ margin: 0;
+}
+
+.product-selection-menu a h2 {
+ font-family: var(--ifm-font-family-base);
+ font-size: 1.6rem !important;
+ font-weight: 500;
+ text-decoration: none !important;
+ margin: 0 0 4px 0;
+ color: inherit;
+}
+
+.product-selection-menu a p {
+ font-family: var(--ifm-font-family-base);
+ font-size: 1.4rem;
+ line-height: 1.8rem;
+ font-weight: 400 !important;
+ color: var(--ifm-menu-color);
+ text-decoration: none !important;
+ margin: 0;
+}
+
+.sdk-selection-menu {
+ display: none;
+ flex-direction: row;
+ align-items: flex-start;
+ justify-content: space-between;
+ padding: 16px;
+ gap: var(--ifm-spacing-horizontal);
+ border-radius: 8px;
+}
+
+.selected-menu {
+ display: flex !important;
+}
+
+.sdk-selection-menu ul {
+ display: flex;
+ padding-left: 0;
+ color: var(--ifm-navbar-link-color);
+ list-style-type: none;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.sdk-selection-menu a {
+ position: relative;
+ display: flex;
+ padding-left: 14px;
+ color: var(--ifm-navbar-link-color);
+ flex-direction: row;
+ justify-content: flex-start;
+ width: 240px;
+ align-items: center;
+ border-radius: 8px;
+ margin: 0;
+ text-decoration: none !important;
+ transition:
+ background-color 0.2s ease,
+ color 0.2s ease;
+
+ &::before {
+ content: '';
+ position: absolute;
+ left: -2px;
+ top: 0;
+ bottom: 0;
+ width: 3px;
+ background-color: var(--ifm-color-primary);
+ opacity: 0;
+ transition: opacity 0.2s ease;
+ border-radius: 1px;
+ }
+
+ &:hover,
+ &:focus {
+ background-color: var(--ifm-hover-overlay);
+ color: var(--ifm-navbar-link-hover-color);
+ outline: none;
+
+ &::before {
+ opacity: 1;
+ }
+
+ span {
+ background-color: var(--ifm-color-primary-light);
+
+ svg {
+ color: var(--ifm-color-primary);
+ }
+ }
+ }
+}
+
+/* Dark mode: Better contrast for SDK selection menu hover/focus */
+[data-theme='dark'] .sdk-selection-menu a:hover,
+[data-theme='dark'] .sdk-selection-menu a:focus {
+ span {
+ background-color: var(--ifm-color-primary);
+
+ svg {
+ color: var(--general-black);
+ }
+ }
+}
+
+.sdk-selection-menu a div {
+ font-family: var(--ifm-font-family-base);
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: center;
+ text-align: left;
+ margin: 0;
+}
+
+.sdk-selection-menu a h2 {
+ font-family: var(--ifm-font-family-base);
+ font-size: 1.6rem !important;
+ font-weight: 500;
+ text-decoration: none !important;
+ margin: 0 0 4px 0;
+ color: inherit;
+ transition: color 0.2s ease;
+}
+
+.sdk-selection-menu a p {
+ font-family: var(--ifm-font-family-base);
+ font-size: 1.4rem;
+ line-height: 1.8rem;
+ font-weight: 400 !important;
+ color: var(--ifm-menu-color);
+ text-decoration: none !important;
+ margin: 0;
+}
+
+.sdk-selection-menu a span {
+ display: flex;
+ background-color: var(--ifm-code-background);
+ border-radius: 8px;
+ margin: 0;
+ text-align: center;
+ align-items: center;
+ justify-content: center;
+ padding: 5px;
+}
+
+.sdk-selection-menu a:has(p) {
+ align-items: flex-start;
+}
+
+.sdk-selection-menu a:has(p) span {
+ margin-top: 10px;
+}
+
+.sdk-selection-menu a span svg {
+ height: 24px;
+ width: 24px;
+ color: var(--ifm-menu-color);
+ display: block;
+ position: relative;
+ left: 50%;
+ -webkit-transform: translateX(-50%);
+ -ms-transform: translateX(-50%);
+ transform: translateX(-50%);
+}
+
+@media screen and (max-width: 996px) {
+ .sdk-selection-menu {
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-start;
+ padding: 0;
+ gap: 0;
+ }
+
+ .sdk-selection-menu ul {
+ gap: 0;
+ }
+
+ .sdk-selection-menu a {
+ width: 100%;
+ justify-content: flex-start;
+ }
+}
+
+@media screen and (max-width: 996px) {
+ .sdk-menu {
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-start;
+ padding: 0;
+ gap: 0;
+ margin: 0;
+ width: 100%;
+ }
+
+ .product-selection-menu {
+ display: none;
+ }
+
+ .sdk-selection-menu {
+ display: flex;
+ }
+
+ #pnp-menu h3::before {
+ content: 'Plug and Play - ';
+ }
+
+ #core-kit-sfa-menu h3::before {
+ content: 'Core Kit SFA - ';
+ }
+
+ #core-kit-mfa-menu h3::before {
+ content: 'Core Kit MFA - ';
+ }
+
+ #wallet-ecosystems-menu h3::before {
+ content: 'Wallet Ecosystems - ';
+ }
+
+ #helper-sdks-menu h3::before {
+ content: 'Helper SDKs - ';
+ }
+
+ .sdk-selection-menu {
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-start;
+ padding: 0;
+ gap: 0;
+ }
+
+ .sdk-selection-menu ul {
+ gap: 0;
+ }
+
+ .sdk-selection-menu a {
+ width: 100%;
+ justify-content: flex-start;
+ }
+}
diff --git a/src/theme/Footer/index.js b/src/theme/Footer/index.js
index b760056a5bb..a1f6c1265ee 100644
--- a/src/theme/Footer/index.js
+++ b/src/theme/Footer/index.js
@@ -1,9 +1,11 @@
-import React, { useEffect } from "react";
+import React, { useEffect, useState } from "react";
import Footer from "@theme-original/Footer";
import { Intercom } from "@intercom/messenger-js-sdk";
import useIsBrowser from "@docusaurus/useIsBrowser";
export default function FooterWrapper(props) {
+ const [canShowFooter, setCanShowFooter] = useState(true);
+
useEffect(() => {
const handleManageCookie = () => {
window.Osano.cm.showDrawer("osano-cm-dom-info-dialog-open");
@@ -17,6 +19,17 @@ export default function FooterWrapper(props) {
};
}, []);
+ useEffect(() => {
+ if (typeof window !== "undefined") {
+ // check if footer can be shown
+ const path = window.location.pathname;
+ if (path.includes("quickstart")) {
+ setCanShowFooter(false);
+ }
+ }
+ }, []);
+
+
const isBrowser = useIsBrowser();
const isProd = process.env.NODE_ENV === "production";
if (isBrowser && isProd) {
@@ -25,6 +38,8 @@ export default function FooterWrapper(props) {
});
}
+ if (!canShowFooter) return null;
+
return (
<>
diff --git a/src/theme/IntegrationBuilderCodeView/index.tsx b/src/theme/IntegrationBuilderCodeView/index.tsx
new file mode 100644
index 00000000000..71b50adcffb
--- /dev/null
+++ b/src/theme/IntegrationBuilderCodeView/index.tsx
@@ -0,0 +1,93 @@
+import CodeBlock from "@theme/CodeBlock";
+import classNames from "classnames";
+import rangeParser from "parse-numeric-range";
+import path from "path";
+import { FiFile } from "react-icons/fi";
+import { animated, useSpring } from "react-spring";
+import { useEffect, useState } from "react";
+
+import styles from "./styles.module.css";
+
+interface Props {
+ filenames: string[];
+ fileContents: Record;
+ highlight?: string;
+ selectedFilename: string;
+ onClickFilename: (filename: string) => void;
+ scroll?: number;
+}
+
+const getDisplayName = (filename: string): string => {
+ return path.basename(filename);
+};
+
+const getLanguage = (filename: string): string => {
+ const ext = path.extname(filename).substr(1);
+
+ if (
+ ["jsx", "java", "swift", "ts", "tsx", "html", "css", "xml", "dart", "json", "cs"].includes(ext)
+ )
+ return `language-${ext}`;
+ if (ext === "js") return "language-jsx";
+ if (ext === "vue") return "language-ts";
+ if (ext === "gradle") return "language-groovy";
+ if (ext === "kt") return "language-kotlin";
+ if (ext === "plist") return "language-xml";
+ if (ext === "yaml") return "language-yaml";
+ if (ext === "") return "language-shell";
+ return undefined;
+};
+
+export default function IntegrationBuilderCodeView({
+ selectedFilename,
+ filenames,
+ fileContents,
+ highlight,
+ onClickFilename,
+}: Props) {
+ const highlightLines = rangeParser(highlight || "0");
+ const [viewportHeight, setViewportHeight] = useState(800);
+
+ useEffect(() => {
+ setViewportHeight(window.innerHeight);
+
+ const handleResize = () => setViewportHeight(window.innerHeight);
+ window.addEventListener("resize", handleResize);
+ return () => window.removeEventListener("resize", handleResize);
+ }, []);
+
+ const props = useSpring({
+ scroll: Math.max(highlightLines[0] * 15 - viewportHeight / 3, 0),
+ }); // 15 is line height, position at roughly 1/3 of the viewport
+ return (
+
+
+
+ {filenames.map((filename) => (
+ -
+
+ {getDisplayName(filename.replace("-", "-\u2060"))}
+
+ ))}
+
+
+
+
+ {fileContents[selectedFilename]}
+
+
+
+ );
+}
diff --git a/src/theme/IntegrationBuilderCodeView/styles.module.css b/src/theme/IntegrationBuilderCodeView/styles.module.css
new file mode 100644
index 00000000000..4d3c07519e6
--- /dev/null
+++ b/src/theme/IntegrationBuilderCodeView/styles.module.css
@@ -0,0 +1,103 @@
+.container {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+.header {
+ height: 56px;
+ padding: 0 12px;
+ background: var(--w3a-ib-code-tab-background-color);
+ display: flex;
+ justify-content: start;
+ align-items: center;
+}
+
+.container :global ::-webkit-scrollbar {
+ background: var(--w3a-ib-code-tab-background-color);
+ width: 4px;
+ height: 4px;
+}
+
+.container :global ::-webkit-scrollbar {
+ -ms-overflow-style: none;
+ /* IE and Edge */
+ scrollbar-width: none;
+ /* Firefox */
+}
+
+.container ::-webkit-scrollbar-thumb {
+ background: var(--ifm-color-gray-400);
+ border-radius: 8px;
+}
+
+.container ::-webkit-scrollbar-thumb:hover {
+ background: var(--ifm-color-white);
+}
+
+.body {
+ height: 100%;
+ overflow: scroll;
+}
+
+.body>div {
+ margin-bottom: 0;
+}
+
+.body :global .prism-code>div {
+ min-height: 80vh;
+}
+
+.container :global .prism-code {
+ counter-reset: line-number;
+ border-radius: 0;
+}
+
+.container :global .prism-code>div {
+ padding-top: 10px;
+}
+
+.container :global .prism-code[class*="language-"] .token-line::before {
+ counter-increment: line-number;
+ display: inline-block;
+ content: counter(line-number);
+ min-width: 1.625em;
+ text-align: right;
+ margin-right: calc(var(--ifm-pre-padding) * 1.25);
+ opacity: 0.25;
+}
+
+.codeTabs :global .tabs__item {
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ color: var(--ifm-color-gray-400);
+ font-size: 16px;
+ font-weight: 500;
+ padding: 4px 10px 3px 10px;
+ margin: 6px;
+ margin-bottom: 20px;
+ border-radius: 9999px;
+ border: none;
+ user-select: none;
+ transition: all var(--ifm-transition-fast) var(--ifm-transition-timing-default);
+}
+
+.codeTabs :global .tabs__item>svg {
+ margin-right: 4px;
+ margin-bottom: 2px;
+}
+
+.codeTabs :global .tabs__item:last-child {
+ margin-right: 0;
+}
+
+.codeTabs :global .tabs__item:hover {
+ color: var(--ifm-color-white);
+}
+
+.codeTabs :global .tabs__item.tabs__item--active {
+ color: var(--ifm-color-content);
+ background: var(--ifm-color-emphasis-300);
+}
\ No newline at end of file
diff --git a/src/theme/MDXPage/index.tsx b/src/theme/MDXPage/index.tsx
new file mode 100644
index 00000000000..e4d7925edbf
--- /dev/null
+++ b/src/theme/MDXPage/index.tsx
@@ -0,0 +1,183 @@
+import * as React from "react";
+import BrowserOnly from "@docusaurus/BrowserOnly";
+import Link from "@docusaurus/Link";
+import { MDXProvider } from "@mdx-js/react";
+import Layout from "@theme/Layout";
+import MDXComponents from "@theme/MDXComponents";
+import TOC from "@theme/TOC";
+import OriginalMDXPage from "@theme-original/MDXPage";
+import { ComponentProps, useState } from "react";
+import Bookmark from "react-bookmark";
+
+import DiscourseComment from "../../components/DiscourseComment";
+import styles from "./styles.module.css";
+
+export default function MDXPage(props: ComponentProps) {
+ const [copyButtonText, setCopyButtonText] = useState("Copy");
+
+ const { content: MDXPageContent } = props;
+ const { frontMatter, metadata } = MDXPageContent;
+ const { permalink } = metadata;
+
+ if (!permalink.includes(`/guides/`)) {
+ return ;
+ }
+
+ // if (!permalink.includes(`/blog/`)) {
+ // return ;
+ // }
+
+ const {
+ title,
+ image,
+ description,
+ type,
+ tags,
+ author,
+ date,
+ wrapperClassName,
+ communityPortalTopicId,
+ } = frontMatter;
+ const url = `https://web3auth.io${permalink}`;
+ const facebookLink = `https://www.facebook.com/sharer/sharer.php?${url}`;
+ const twitterLink = `http://twitter.com/share?text=Checkout ${title} published by @Web3Auth&url=${url}`;
+
+ const handleClick = () => {
+ navigator.clipboard.writeText(url);
+ setCopyButtonText("Copied!");
+
+ setTimeout(() => {
+ setCopyButtonText("Copy");
+ }, 500);
+ };
+
+ return (
+
+
+
+
+
+
+
+ {/*

*/}
+
+
{title}
+
+
+ {tags &&
+ tags.map((item) => {
+ return (
+
+ {item}
+
+ );
+ })}
+
+
+ {author} | {date}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {() => (
+
+
+
+ )}
+
+
+
+
+ {MDXPageContent.toc && (
+
+
+
+ )}
+
+
+
+
+
+ );
+}
diff --git a/src/theme/MDXPage/styles.module.css b/src/theme/MDXPage/styles.module.css
new file mode 100644
index 00000000000..cf5f5599ba8
--- /dev/null
+++ b/src/theme/MDXPage/styles.module.css
@@ -0,0 +1,219 @@
+.titleContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ overflow: hidden;
+ width: 95%;
+ margin-bottom: 16px;
+ gap: 10px;
+}
+
+.tagsContainer {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ width: 100%;
+ gap: 5px;
+}
+
+.tag {
+ font-weight: 500;
+ font-size: 12px;
+ line-height: 150%;
+ padding: 2px 10px;
+ height: 22px;
+ background-color: var(--ifm-color-emphasis-200);
+ color: var(--ifm-color-emphasis-600);
+ border-radius: 30px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: visible;
+ white-space: nowrap;
+ cursor: pointer;
+}
+
+.title {
+ font-family: var(--ifm-heading-font-family);
+ font-size: 30px;
+ font-weight: 500;
+ text-align: center;
+}
+
+.date {
+ color: #676767;
+ font-size: 14px;
+}
+
+.cover {
+ width: 100%;
+ text-align: center;
+ border-radius: 20px;
+}
+
+.pillContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ /* white */
+ background: var(--w3a-color-indigo-background);
+ border-radius: 8px;
+ text-decoration: none;
+ padding: 0;
+ margin: 0;
+ margin-bottom: 7px;
+ width: max-content;
+ overflow: hidden;
+ flex-wrap: wrap;
+}
+
+.pill {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ text-align: center;
+ align-items: center;
+ width: max-content;
+ padding-top: 2px;
+ padding-bottom: 2px;
+ padding-left: 15px;
+ padding-right: 15px;
+ margin: 0;
+ font-weight: 500 !important;
+ font-size: 15px;
+ text-transform: uppercase;
+ line-height: 150%;
+ color: var(--w3a-color-indigo);
+ flex-wrap: wrap;
+}
+
+.socialButtonContainer {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 8px;
+}
+
+.socialButton {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 8px 24px 8px 24px;
+ font-style: normal;
+ font-weight: 500;
+ font-size: 12px;
+ line-height: 150%;
+ border: 1px solid var(--w3a-border-light-color);
+ background-color: var(--ifm-background-surface-color);
+ border-radius: 8px;
+ cursor: pointer;
+ gap: 8px;
+}
+
+.socialButton:hover {
+ background-color: var(--w3a-border-light-color);
+}
+
+.socialButton:active {
+ border: 1px solid var(--w3a-menu-heading-color);
+ background-color: var(--w3a-menu-heading-color);
+}
+
+.bookmarkButton {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 8px 24px 8px 24px;
+ font-style: normal;
+ font-weight: 500;
+ font-size: 12px;
+ line-height: 150%;
+ border: none;
+ background-color: var(--ifm-background-color);
+ border-radius: 8px;
+ gap: 8px;
+}
+
+.bottomMenu {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+ padding: 20px;
+ padding-left: 0;
+ padding-right: 0;
+ border-top: 1px solid var(--w3a-border-light-color);
+ border-bottom: 1px solid var(--w3a-border-light-color);
+ margin-top: 20px;
+ margin-bottom: 20px;
+ gap: 10px;
+}
+
+.topMenu {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+ padding: 20px;
+ padding-left: 0;
+ padding-right: 0;
+ border-top: 1px solid var(--w3a-border-light-color);
+ border-bottom: 1px solid var(--w3a-border-light-color);
+ gap: 10px;
+}
+
+.authorName {
+ gap: 10px;
+ text-align: left;
+ align-self: center;
+ font-style: normal;
+ font-weight: 400;
+ font-size: 16px;
+ line-height: 150%;
+}
+
+@media only screen and (min-width: 481px) {
+ .title {
+ font-size: 40px;
+ }
+
+ .cover {
+ width: 90%;
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .title {
+ font-size: 48px;
+ }
+
+ .cover {
+ width: 80%;
+ }
+
+ .topMenu {
+ flex-direction: column;
+ }
+
+ .bottomMenu {
+ flex-direction: column;
+ }
+}
+
+@media only screen and (min-width: 1216px) {
+ .title {
+ font-size: 52px;
+ }
+
+ .cover {
+ width: 80%;
+ }
+}
\ No newline at end of file
diff --git a/src/theme/URLParams/index.tsx b/src/theme/URLParams/index.tsx
new file mode 100644
index 00000000000..cd248c25eb0
--- /dev/null
+++ b/src/theme/URLParams/index.tsx
@@ -0,0 +1,22 @@
+export const getWindowLocation = () => {
+ if (typeof window !== "undefined") return window.location.href;
+ return "http://localhost";
+};
+
+export const getURLOptions = () => {
+ const url = new URL(getWindowLocation());
+
+ const urlOpts = new Map();
+ url.searchParams.forEach((value, key) => {
+ urlOpts.set(key, value);
+ });
+
+ return Object.fromEntries(urlOpts);
+};
+
+export const getURLFromFilterOptions = (opts: Record): string => {
+ const url = new URL(getWindowLocation());
+ url.search = "";
+ for (const [key, value] of Object.entries(opts)) url.searchParams.append(key, value);
+ return url.toString();
+};
diff --git a/src/utils/example-map.tsx b/src/utils/example-map.tsx
new file mode 100644
index 00000000000..f5f26c7f390
--- /dev/null
+++ b/src/utils/example-map.tsx
@@ -0,0 +1,1286 @@
+export interface ExamplesInterface {
+ id: string;
+ title: string;
+ description: string;
+ image: string;
+ type: string;
+ tags: string[];
+ link: string;
+ githubLink: string;
+ qsLink?: string;
+}
+
+export const tags = {
+ pnp: "plug and play",
+ mpcCoreKit: "mpc core kit",
+ sfa: "single factor auth",
+ sfaJS: "@web3auth/single-factor-auth",
+ mpcCoreKitJS: "@web3auth/mpc-core-kit",
+ web: "web",
+ android: "android",
+ ios: "ios",
+ wagmi: "wagmi",
+ reactNative: "react native",
+ flutter: "flutter",
+ node: "node",
+ unity: "unity",
+ unreal: "unreal engine",
+ evm: "evm",
+ solana: "solana",
+ multiChain: "multi chain",
+ xrpl: "xrpl",
+ algorand: "algorand",
+ aptos: "aptos",
+ bitcoin: "bitcoin",
+ cosmos: "cosmos",
+ immutablex: "immutablex",
+ near: "near",
+ polkadot: "polkadot",
+ polymesh: "polymesh",
+ starkex: "starkex",
+ starknet: "starknet",
+ sui: "sui",
+ tezos: "tezos",
+ tron: "tron",
+ ton: "ton",
+ customAuthentication: "custom authentication",
+ accountAbstraction: "account abstraction",
+ onRamp: "on ramp",
+ mfa: "mfa",
+};
+
+export const PLAYGROUND = "PLAYGROUND";
+export const QUICK_START = "QUICK START";
+export const SAMPLE_APP = "SAMPLE APP";
+
+export const webExamples: ExamplesInterface[] = [
+ // Quick Starts
+ {
+ title: "React Quick Start",
+ description: "A quick integration of Web3Auth SDK in React",
+ image: "banners/react.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-quick-start",
+ id: "react-quick-start",
+ qsLink: "/quick-start?framework=REACT&stepIndex=0",
+ },
+ {
+ title: "React Solana Quick Start",
+ description: "A quick integration of Web3Auth SDK in React with Solana blockchain",
+ image: "banners/solana.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.web, tags.solana, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-solana-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-solana-quick-start",
+ id: "react-solana-quick-start",
+ qsLink: "/quick-start?framework=REACT_SOLANA&stepIndex=0",
+ },
+ {
+ title: "Angular Quick Start",
+ description: "A quick integration of Web3Auth SDK in Angular",
+ image: "banners/angular.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.web, tags.evm, "angular"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/angular-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/angular-quick-start",
+ id: "angular-quick-start",
+ qsLink: "/quick-start?framework=ANGULAR&stepIndex=0",
+ },
+ {
+ title: "Vue Quick Start",
+ description: "A quick integration of Web3Auth SDK in Vue",
+ image: "banners/vue.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "vue"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vue-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vue-quick-start",
+ id: "vue-quick-start",
+ qsLink: "/quick-start?framework=VUE&stepIndex=0",
+ },
+ {
+ title: "Vue Solana Quick Start",
+ description: "A quick integration of Web3Auth SDK in Vue with Solana blockchain",
+ image: "banners/solana.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.web, tags.solana, "vue"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vue-solana-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vue-solana-quick-start",
+ id: "vue-solana-quick-start",
+ qsLink: "/quick-start?framework=VUE_SOLANA&stepIndex=0",
+ },
+ {
+ title: "NextJS Quick Start",
+ description: "A quick integration of Web3Auth SDK in NextJS",
+ image: "banners/next.js.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "nextjs"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/nextjs-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/nextjs-quick-start",
+ id: "nextjs-quick-start",
+ qsLink: "/quick-start?framework=NEXTJS&stepIndex=0",
+ },
+ {
+ title: "Vanilla JS Quick Start",
+ description: "A quick integration of Web3Auth SDK in Vanilla JavaScript",
+ image: "banners/htmljs.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.web, tags.evm],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vanillajs-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vanillajs-quick-start",
+ id: "vanillajs-quick-start",
+ qsLink: "/quick-start?framework=HTML&stepIndex=0",
+ },
+
+ // React Playground
+ {
+ title: "React Playground",
+ description: "A playground to test all the features of Web3Auth SDKs in React",
+ image: "banners/react.png",
+ type: PLAYGROUND,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "hooks"],
+ link: "https://web3auth-playground.vercel.app/",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/react-playground",
+ id: "react-playground",
+ },
+
+ // Custom Authentication Examples - Single Connection
+ {
+ title: "Auth0 Implicit Example",
+ description: "Implementing Auth0 implicit flow authentication with Web3Auth",
+ image: "banners/auth0.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "auth0", "implicit"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/auth0-implicit-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/auth0-implicit-example",
+ id: "auth0-implicit-example",
+ },
+ {
+ title: "Auth0 JWT Example",
+ description: "Implementing Auth0 JWT authentication with Web3Auth",
+ image: "banners/auth0.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "auth0", "jwt"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/auth0-jwt-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/auth0-jwt-example",
+ id: "auth0-jwt-example",
+ },
+ {
+ title: "Cognito Implicit Example",
+ description: "Implementing AWS Cognito implicit flow authentication with Web3Auth",
+ image: "banners/cognito.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "cognito", "implicit"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/cognito-implicit-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/cognito-implicit-example",
+ id: "cognito-implicit-example",
+ },
+ {
+ title: "Custom JWT Example",
+ description: "Implementing custom JWT authentication with Web3Auth",
+ image: "banners/jwt.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "jwt", "custom"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/custom-jwt-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/custom-jwt-example",
+ id: "custom-jwt-example",
+ },
+ {
+ title: "Discord Implicit Example",
+ description: "Implementing Discord implicit flow authentication with Web3Auth",
+ image: "banners/discord.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "discord", "implicit"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/discord-implicit-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/discord-implicit-example",
+ id: "discord-implicit-example",
+ },
+ {
+ title: "Facebook Implicit Example",
+ description: "Implementing Facebook implicit flow authentication with Web3Auth",
+ image: "banners/facebook.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "facebook", "implicit"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/facebook-implicit-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/facebook-implicit-example",
+ id: "facebook-implicit-example",
+ },
+ {
+ title: "Firebase JWT Example",
+ description: "Implementing Firebase JWT authentication with Web3Auth",
+ image: "banners/firebase.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "firebase", "jwt"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/firebase-jwt-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/firebase-jwt-example",
+ id: "firebase-jwt-example",
+ },
+ {
+ title: "Google Implicit Example",
+ description: "Implementing Google implicit flow authentication with Web3Auth",
+ image: "banners/google.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "google", "implicit"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/google-implicit-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/google-implicit-example",
+ id: "google-implicit-example",
+ },
+ {
+ title: "Google One Tap Example",
+ description: "Implementing Google One Tap authentication with Web3Auth",
+ image: "banners/google.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "google", "one-tap"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/google-one-tap-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/google-one-tap-example",
+ id: "google-one-tap-example",
+ },
+ {
+ title: "Modal Example",
+ description: "Implementing Web3Auth Modal for authentication",
+ image: "banners/react.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "modal"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/modal-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/modal-example",
+ id: "modal-example",
+ },
+ {
+ title: "Twitch Implicit Example",
+ description: "Implementing Twitch implicit flow authentication with Web3Auth",
+ image: "banners/twitch.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "twitch", "implicit"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/twitch-implicit-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/twitch-implicit-example",
+ id: "twitch-implicit-example",
+ },
+ {
+ title: "Worldcoin Implicit Example",
+ description: "Implementing Worldcoin implicit flow authentication with Web3Auth",
+ image: "banners/worldcoin.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "worldcoin", "implicit"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/worldcoin-implicit-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/single-connection/worldcoin-implicit-example",
+ id: "worldcoin-implicit-example",
+ },
+
+ // Custom Authentication Examples - Grouped Connection
+ {
+ title: "Auth0 Google Implicit Grouped Example",
+ description: "Implementing Auth0 and Google grouped authentication with implicit flow",
+ image: "banners/auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.web,
+ tags.evm,
+ tags.wagmi,
+ "react",
+ "auth0",
+ "google",
+ "implicit",
+ "grouped",
+ ],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/grouped-connection/auth0-google-implicit-grouped-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/grouped-connection/auth0-google-implicit-grouped-example",
+ id: "auth0-google-implicit-grouped-example",
+ },
+ {
+ title: "Auth0 Google JWT Grouped Example",
+ description: "Implementing Auth0 and Google grouped authentication with JWT",
+ image: "banners/auth0.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "auth0", "google", "jwt", "grouped"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/grouped-connection/auth0-google-jwt-grouped-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/grouped-connection/auth0-google-jwt-grouped-example",
+ id: "auth0-google-jwt-grouped-example",
+ },
+ {
+ title: "Firebase Google JWT Grouped Example",
+ description: "Implementing Firebase and Google grouped authentication with JWT",
+ image: "banners/firebase.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.web,
+ tags.evm,
+ tags.wagmi,
+ "react",
+ "firebase",
+ "google",
+ "jwt",
+ "grouped",
+ ],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/grouped-connection/firebase-google-jwt-grouped-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/grouped-connection/firebase-google-jwt-grouped-example",
+ id: "firebase-google-jwt-grouped-example",
+ },
+ {
+ title: "Modal Google Email Passwordless Grouped Example",
+ description: "Implementing Web3Auth Modal with Google and Email Passwordless authentication",
+ image: "banners/google.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.web,
+ tags.evm,
+ tags.wagmi,
+ "react",
+ "modal",
+ "google",
+ "email",
+ "passwordless",
+ "grouped",
+ ],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/grouped-connection/modal-google-email-passwordless-grouped-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/custom-authentication/grouped-connection/modal-google-email-passwordless-grouped-example",
+ id: "modal-google-email-passwordless-grouped-example",
+ },
+
+ // Other Blockchain Examples
+ {
+ title: "Algorand Example",
+ description: "Implementing Web3Auth with Algorand blockchain",
+ image: "banners/algorand.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.algorand, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/algorand-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/algorand-example",
+ id: "algorand-example",
+ },
+ {
+ title: "Aptos Example",
+ description: "Implementing Web3Auth with Aptos blockchain",
+ image: "banners/aptos.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.aptos, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/aptos-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/aptos-example",
+ id: "aptos-example",
+ },
+ {
+ title: "Bitcoin Example",
+ description: "Implementing Web3Auth with Bitcoin blockchain",
+ image: "banners/react.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.bitcoin, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/bitcoin-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/bitcoin-example",
+ id: "bitcoin-example",
+ },
+ {
+ title: "Cosmos Example",
+ description: "Implementing Web3Auth with Cosmos blockchain",
+ image: "banners/cosmos.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.cosmos, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/cosmos-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/cosmos-example",
+ id: "cosmos-example",
+ },
+ {
+ title: "Multi Chain Example",
+ description: "Implementing Web3Auth with multiple blockchain networks",
+ image: "banners/multichain.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.multiChain, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/multi-chain-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/multi-chain-example",
+ id: "multi-chain-example",
+ },
+ {
+ title: "Polkadot Example",
+ description: "Implementing Web3Auth with Polkadot blockchain",
+ image: "banners/polkadot.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.polkadot, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/polkadot-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/polkadot-example",
+ id: "polkadot-example",
+ },
+ {
+ title: "Polymesh Example",
+ description: "Implementing Web3Auth with Polymesh blockchain",
+ image: "banners/polymesh.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.polymesh, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/polymesh-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/polymesh-example",
+ id: "polymesh-example",
+ },
+ {
+ title: "Server Side Verification Example",
+ description: "Implementing server-side verification with Web3Auth",
+ image: "banners/ssv.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "nextjs", "server-side"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/server-side-verification-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/other/server-side-verification-example",
+ id: "server-side-verification-example",
+ },
+ {
+ title: "Sign Protocol Example",
+ description: "Implementing signing protocols with Web3Auth",
+ image: "banners/sign-protocol.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "signing"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/sign-protocol-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/other/sign-protocol-example",
+ id: "sign-protocol-example",
+ },
+ {
+ title: "Smart Account Example",
+ description: "Implementing smart accounts with Web3Auth for account abstraction",
+ image: "banners/react.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", tags.accountAbstraction],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/smart-account-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/other/smart-account-example",
+ id: "smart-account-example",
+ },
+ {
+ title: "Sui Example",
+ description: "Implementing Web3Auth with Sui blockchain",
+ image: "banners/sui.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.sui, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/sui-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/sui-example",
+ id: "sui-example",
+ },
+ {
+ title: "Tezos Example",
+ description: "Implementing Web3Auth with Tezos blockchain",
+ image: "banners/tezos.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.tezos, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/tezos-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/tezos-example",
+ id: "tezos-example",
+ },
+ {
+ title: "TON Example",
+ description: "Implementing Web3Auth with TON blockchain",
+ image: "banners/ton.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.ton, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/ton-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/ton-example",
+ id: "ton-example",
+ },
+ {
+ title: "TRON Example",
+ description: "Implementing Web3Auth with TRON blockchain",
+ image: "banners/tron.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.tron, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/tron-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/tron-example",
+ id: "tron-example",
+ },
+ {
+ title: "XMTP Example",
+ description: "Implementing Web3Auth with XMTP messaging protocol",
+ image: "banners/xmtp.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.evm, tags.wagmi, "react", "xmtp", "messaging"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/xmtp-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/xmtp-example",
+ id: "xmtp-example",
+ },
+ {
+ title: "XRPL Example",
+ description: "Implementing Web3Auth with XRP Ledger",
+ image: "banners/xrpl.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.web, tags.xrpl, "react"],
+ link: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/xrpl-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-examples/tree/main/other/xrpl-example",
+ id: "xrpl-example",
+ },
+];
+export const pnpiOSExamples: ExamplesInterface[] = [
+ {
+ title: "Web3Auth PnP iOS SDK Quick Start",
+ description: "A quick integration of Web3Auth Plug and Play iOS SDK",
+ image: "banners/ios-swift.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.ios, tags.evm, "swift"],
+ link: EWQuickStartHostedLinks.IOS,
+ id: "ios-quick-start",
+ githubLink: EWQuickStartSourceCode.IOS,
+ qsLink: "/quick-start?framework=IOS&stepIndex=0",
+ },
+ {
+ title: "Integrate Web3Auth PnP iOS SDK with Solana Blockchain",
+ description: "Use Solana Blockchain with Plug and Play iOS SDK",
+ image: "banners/ios-solana.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.ios, "swift", tags.solana, "ed25519"],
+ link: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-solana-example",
+ id: "ios-solana-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-solana-example",
+ },
+ {
+ title: "PnP iOS SDK Playground",
+ description: "A playground to test all the features of Plug and Play iOS SDK",
+ image: "banners/ios-swift.png",
+ type: PLAYGROUND,
+ tags: [tags.pnp, tags.ios, "swift", tags.solana, tags.evm, "secp256k1"],
+ link: "https://w3a.link/pnp-ios-playground",
+ githubLink: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-playground",
+ id: "pnp-ios-playground",
+ },
+ {
+ title: "Integrate Firebase based Login in PnP iOS SDK",
+ description: "Use your own Firebase ID Token based Login with Plug and Play iOS SDK",
+ image: "banners/ios-firebase.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.ios, "swift", "firebase", tags.evm, "id token login"],
+ link: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-firebase-example",
+ id: "ios-firebase-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-firebase-example",
+ },
+ // {
+ // title: "Integrate Auth0 SPA in PnP iOS SDK",
+ // description: "Use Auth0 Single Page App (Implicit Mode) with Plug and Play iOS SDK",
+ // image: "banners/ios-auth0.png",
+ // type: SAMPLE_APP,
+ // tags: [tags.pnp, tags.ios, "swift", "auth0", "email passwordless", tags.evm, "implicit mode"],
+ // link: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-auth0-example",
+ // id: "ios-auth0-example",
+ // githubLink: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-auth0-example",
+ //
+ // },
+ {
+ title: "Using Aggregate Verifiers in Web3Auth PnP iOS SDK",
+ description:
+ "Combine multiple logins (Google, Facebook and GitHub) using Aggregate Verifiers in Web3Auth Plug and Play iOS SDK",
+ image: "banners/ios-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.ios,
+ "swift",
+ "aggregate verifier",
+ "implicit mode",
+ "auth0",
+ "google",
+ "github",
+ "facebook",
+ tags.evm,
+ ],
+ link: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-aggregate-verifier-example",
+ id: "ios-aggregate-verifier-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-aggregate-verifier-example",
+ },
+];
+export const pnpAndroidExamples: ExamplesInterface[] = [
+ {
+ title: "Web3Auth PnP Android SDK Quick Start",
+ description: "A quick integration of Web3Auth Plug and Play Android SDK",
+ image: "banners/android.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.android, tags.evm, "kotlin"],
+ link: EWQuickStartHostedLinks.ANDROID,
+ githubLink: EWQuickStartSourceCode.ANDROID,
+ id: "android-quick-start",
+ qsLink: "/quick-start?framework=ANDROID&stepIndex=0",
+ },
+ {
+ title: "Integrate Web3Auth PnP Android SDK with Solana Blockchain",
+ description: "Use Solana Blockchain with Plug and Play Android SDK",
+ image: "banners/android-solana.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.android, "kotlin", tags.solana, "ed25519"],
+ link: "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-solana-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-solana-example",
+ id: "android-solana-example",
+ },
+ {
+ title: "PnP Android SDK Playground",
+ description: "A playground to test all the features of Plug and Play Android SDK",
+ image: "banners/android.png",
+ type: PLAYGROUND,
+ tags: [tags.pnp, tags.android, "kotlin", tags.solana, tags.evm, "secp256k1"],
+ link: "https://w3a.link/pnp-android-playground",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-playground",
+ id: "android-playground",
+ },
+ {
+ title: "Integrate Firebase based Login in PnP Android SDK",
+ description: "Use your own Firebase ID Token based Login with Plug and Play Android SDK",
+ image: "banners/android-firebase.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.android, "kotlin", "firebase", tags.evm, "id token login"],
+ link: "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-firebase-example",
+ id: "android-firebase-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-firebase-example",
+ },
+ {
+ title: "Integrate Auth0 SPA in PnP Android SDK",
+ description: "Use Auth0 Single Page App (Implicit Mode) with Plug and Play Android SDK",
+ image: "banners/android-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.android,
+ tags.evm,
+ "kotlin",
+ "auth0",
+ "email passwordless",
+ "implicit mode",
+ ],
+ link: "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-auth0-example",
+ id: "android-auth0-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-auth0-example",
+ },
+ {
+ title: "Using Aggregate Verifiers in Web3Auth PnP Android SDK",
+ description:
+ "Combine multiple logins (Google, Facebook and GitHub) using Aggregate Verifiers in Web3Auth Plug and Play Android SDK",
+ image: "banners/android-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.android,
+ tags.evm,
+ "kotlin",
+ "aggregate verifier",
+ "implicit mode",
+ "auth0",
+ "google",
+ "github",
+ "facebook",
+ ],
+ link: "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-aggregate-verifier-example",
+ id: "android-aggregate-verifier-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-aggregate-verifier-example",
+ },
+];
+export const pnpReactNativeExamples: ExamplesInterface[] = [
+ {
+ title: "Web3Auth PnP React Native SDK Quick Start",
+ description:
+ "A quick integration of Web3Auth Plug and Play React Native SDK in Android and iOS",
+ image: "banners/react-native.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.android, tags.ios, tags.evm, tags.reactNative],
+ link: EWQuickStartHostedLinks.REACT_NATIVE,
+ githubLink: EWQuickStartSourceCode.REACT_NATIVE,
+ id: "rn-bare-quick-start",
+ qsLink: "/quick-start?framework=REACT_NATIVE&stepIndex=0",
+ },
+ {
+ title: "Using Auth0 with Web3Auth PnP React Native SDK",
+ description:
+ "Using Auth0 Single Page App (Implicit Mode) in Web3Auth Plug and Play React Native SDK in Android and iOS",
+ image: "banners/react-native-auth0.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.android, tags.ios, tags.reactNative, tags.evm, "auth0", "implicit mode"],
+ link: "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-auth0-example",
+ id: "rn-bare-auth0-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-auth0-example",
+ },
+ {
+ title: "Using Aggregate Verifiers in Web3Auth PnP React Native SDK",
+ description:
+ "Combine multiple logins (Google, Facebook and GitHub) using Aggregate Verifiers in Web3Auth Plug and Play React Native SDK for Android and iOS",
+ image: "banners/react-native-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+
+ tags.android,
+ tags.ios,
+ tags.evm,
+ tags.reactNative,
+ "aggregate verifier",
+ "implicit mode",
+ "auth0",
+ "google",
+ "github",
+ "facebook",
+ ],
+ link: "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-aggregate-verifier-example",
+ id: "rn-bare-aggregate-verifier-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-aggregate-verifier-example",
+ },
+ {
+ title: "Using Web3Auth PnP React Native SDK in Expo",
+ description: "Using Web3Auth Plug and Play React Native SDK in an Expo App",
+ image: "banners/expo.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.android, tags.ios, tags.evm, tags.reactNative, "expo"],
+ link: "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-expo-example",
+ id: "rn-expo-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-expo-example",
+ },
+];
+export const pnpFlutterExamples: ExamplesInterface[] = [
+ {
+ title: "Web3Auth PnP Flutter SDK Quick Start",
+ description: "A quick integration of Web3Auth Plug and Play Flutter SDK for Android and iOS",
+ image: "banners/flutter.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.flutter, tags.ios, tags.android, tags.evm, "dart"],
+ link: "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-quick-start",
+ id: "flutter-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-quick-start",
+ },
+ {
+ title: "Integrate Web3Auth PnP Flutter SDK with Solana Blockchain",
+ description: "Use Solana Blockchain with Plug and Play Flutter SDK for Android and iOS",
+ image: "banners/flutter-solana.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.flutter, tags.ios, tags.android, "dart", tags.solana, "ed25519"],
+ link: "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-solana-example",
+ id: "flutter-solana-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-solana-example",
+ },
+ {
+ title: "PnP Flutter SDK Playground",
+ description:
+ "A playground to test all the features of Plug and Play Flutter SDK for Android and iOS",
+ image: "banners/flutter.png",
+ type: PLAYGROUND,
+ tags: [
+ tags.pnp,
+ tags.flutter,
+ tags.ios,
+ tags.android,
+ "dart",
+ tags.solana,
+ tags.evm,
+ "secp256k1",
+ ],
+ link: "https://w3a.link/pnp-flutter-ios-playground",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-playground",
+ id: "flutter-playground",
+ },
+ {
+ title: "Integrate Firebase based Login in PnP Flutter SDK",
+ description:
+ "Use your own Firebase ID Token based Login with Plug and Play Flutter SDK for Android and iOS",
+ image: "banners/flutter-firebase.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.flutter,
+ tags.ios,
+ tags.android,
+ tags.evm,
+ "dart",
+ "firebase",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-firebase-example",
+ id: "flutter-firebase-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-firebase-example",
+ },
+ {
+ title: "Integrate Auth0 SPA in PnP Flutter SDK",
+ description:
+ "Use Auth0 Single Page App (Implicit Mode) with Plug and Play Flutter SDK for Android and iOS",
+ image: "banners/flutter-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.flutter,
+ tags.ios,
+ tags.android,
+ "dart",
+ "auth0",
+ "email passwordless",
+ "implicit mode",
+ tags.evm,
+ ],
+ link: "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-auth0-example",
+ id: "flutter-auth0-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-auth0-example",
+ },
+ {
+ title: "Using Aggregate Verifiers in Web3Auth PnP Flutter SDK",
+ description:
+ "Combine multiple logins (Google, Facebook and GitHub) using Aggregate Verifiers in Web3Auth Plug and Play Flutter SDK for Android and iOS",
+ image: "banners/flutter-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.flutter,
+ tags.ios,
+ tags.android,
+ "dart",
+ "aggregate verifier",
+ "implicit mode",
+ "auth0",
+ "google",
+ "github",
+ "facebook",
+ tags.evm,
+ ],
+ link: "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-aggregate-verifier-example",
+ id: "flutter-aggregate-verifier-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-aggregate-verifier-example",
+ },
+];
+export const pnpUnityExamples: ExamplesInterface[] = [
+ {
+ title: "Web3Auth PnP Unity SDK Quick Start",
+ description:
+ "A quick integration of Web3Auth Plug and Play Unity SDK in Android, iOS and WebGL",
+ image: "banners/unity.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.unity, "csharp", tags.android, tags.ios, tags.evm, "webgl"],
+ link: EWQuickStartSourceCode.UNITY,
+ id: "unity-quick-start",
+ githubLink: EWQuickStartSourceCode.UNITY,
+ },
+ {
+ title: "Using Auth0 with Web3Auth PnP Unity SDK",
+ description:
+ "Using Auth0 Single Page App (Implicit Mode) in Web3Auth Plug and Play Unity SDK in Android, iOS and WebGL",
+ image: "banners/unity-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.unity,
+ "csharp",
+ tags.android,
+ tags.ios,
+ "webgl",
+ "auth0",
+ "implicit mode",
+ tags.evm,
+ ],
+ link: "https://github.com/Web3Auth/web3auth-unity-examples/tree/main/unity-auth0-example",
+ id: "unity-auth0-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-unity-examples/tree/main/unity-auth0-example",
+ },
+ {
+ title: "Using Aggregate Verifiers in Web3Auth PnP Unity SDK",
+ description:
+ "Combine multiple logins (Google, Facebook and GitHub) using Aggregate Verifiers in Web3Auth Plug and Play Unity SDK for Android, iOS and WebGL",
+ image: "banners/unity-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.unity,
+ "csharp",
+ tags.android,
+ tags.ios,
+ "webgl",
+ "aggregate verifier",
+ "implicit mode",
+ "auth0",
+ "google",
+ "github",
+ "facebook",
+ tags.evm,
+ ],
+ link: "https://github.com/Web3Auth/web3auth-unity-examples/tree/main/unity-aggregate-verifier-example",
+ id: "unity-aggregate-verifier-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-unity-examples/tree/main/unity-aggregate-verifier-example",
+ },
+];
+export const pnpUnrealExamples: ExamplesInterface[] = [
+ {
+ title: "Web3Auth PnP Unreal Engine SDK Quick Start",
+ description: "A quick integration of Web3Auth Plug and Play Unreal Engine SDK in Android & iOS",
+ image: "banners/unreal.png",
+ type: QUICK_START,
+ tags: [tags.pnp, tags.unreal, "csharp", tags.android, tags.evm, tags.ios],
+ link: "https://github.com/Web3Auth/web3auth-unreal-example/tree/master",
+ id: "unreal-quick-start",
+ githubLink: EWQuickStartSourceCode.UNREAL,
+ },
+ {
+ id: "unreal-auth0-example",
+ title: "Using Auth0 with Web3Auth PnP Unreal Engine SDK",
+ description:
+ "Using Auth0 Single Page App (Implicit Mode) in Web3Auth Plug and Play Unreal Engine SDK in Android & iOS",
+ image: "banners/unreal-auth0.png",
+ type: SAMPLE_APP,
+ tags: [tags.pnp, tags.unreal, tags.android, tags.ios, "auth0", tags.evm, "implicit mode"],
+ link: "https://github.com/Web3Auth/web3auth-unreal-example/tree/auth0-example",
+ githubLink: "https://github.com/Web3Auth/web3auth-unreal-example/tree/auth0-example",
+ },
+ {
+ id: "unreal-google-example",
+ title: "Using Google in Web3Auth PnP Unreal Engine SDK",
+ description:
+ "Using Google Custom Authentication in Web3Auth Plug and Play Unreal Engine SDK for Android & iOS",
+ image: "banners/unreal-google.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.pnp,
+ tags.unreal,
+ tags.android,
+ tags.ios,
+ tags.evm,
+ "aggregate verifier",
+ "implicit mode",
+ "auth0",
+ "google",
+ "github",
+ "facebook",
+ ],
+ link: "https://github.com/Web3Auth/web3auth-unreal-example/tree/custom-google",
+ githubLink: "https://github.com/Web3Auth/web3auth-unreal-example/tree/custom-google",
+ },
+];
+
+export const coreKitSfaiOSExamples: ExamplesInterface[] = [
+ {
+ title: "Web3Auth Single Factor Auth iOS SDK Quick Start",
+ description: "A quick integration of Single Factor Auth iOS SDK",
+ image: "banners/ios-swift.png",
+ type: QUICK_START,
+ tags: [tags.sfa, "sfa", tags.ios, tags.evm, "swift"],
+ link: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/sfa-ios-quick-start",
+ id: "sfa-ios-quick-start",
+ githubLink: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/sfa-ios-quick-start",
+ },
+];
+export const coreKitSfaAndroidExamples: ExamplesInterface[] = [
+ {
+ title: "Web3Auth Single Factor Auth Android SDK Quick Start",
+ description: "A quick integration of Web3Auth Single Factor Auth Android SDK",
+ image: "banners/android.png",
+ type: QUICK_START,
+ tags: [tags.sfa, "sfa", tags.android, tags.evm, "kotlin"],
+ link: "https://github.com/Web3Auth/web3auth-android-examples/tree/main/sfa-android-quick-start",
+ id: "sfa-ios-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-android-examples/tree/main/sfa-android-quick-start",
+ },
+];
+export const coreKitSfaReactNativeExamples: ExamplesInterface[] = [
+ {
+ id: "sfa-rn-bare-quick-start",
+ title: "Web3Auth Single Factor Auth React Native SDK Quick Start",
+ description:
+ "A quick integration of Web3Auth Single Factor Auth React Native SDK in Android and iOS",
+ image: "banners/react-native.png",
+ type: QUICK_START,
+ tags: [tags.sfa, "sfa", tags.android, tags.ios, tags.evm, tags.reactNative],
+ link: "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/sfa-rn-bare-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/sfa-rn-bare-quick-start",
+ },
+ {
+ id: "sfa-rn-expo-auth0-example",
+ title: "Using Web3Auth Single Factor Auth React Native SDK in Expo",
+ description: "Using Web3Auth Single Factor Auth React Native SDK in an Expo App",
+ image: "banners/expo.png",
+ type: SAMPLE_APP,
+ tags: [tags.sfa, "sfa", tags.android, tags.ios, tags.reactNative, "expo"],
+ link: "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/sfa-rn-expo-auth0-example",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/sfa-rn-expo-auth0-example",
+ },
+];
+export const coreKitSfaFlutterExamples: ExamplesInterface[] = [
+ {
+ id: "sfa_flutter_quick_start",
+ title: "Web3Auth Single Factor Auth Flutter SDK Quick Start",
+ description:
+ "A quick integration of Web3Auth Single Factor Auth Flutter SDK for Android and iOS",
+ image: "banners/flutter.png",
+ type: QUICK_START,
+ tags: [tags.sfa, "sfa", tags.flutter, tags.ios, tags.android, tags.evm, "dart"],
+ link: "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/sfa_flutter_quick_start",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/sfa_flutter_quick_start",
+ },
+ {
+ id: "sfa_flutter_solana",
+ title: "Integrate Web3Auth Single Factor Auth Flutter SDK with Solana Blockchain",
+ description: "Use Solana Blockchain with Single Factor Auth Flutter SDK for Android and iOS",
+ image: "banners/flutter-solana.png",
+ type: SAMPLE_APP,
+ tags: [tags.sfa, "sfa", tags.flutter, tags.ios, tags.android, "dart", tags.solana, "ed25519"],
+ link: "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/sfa_flutter_solana",
+ githubLink:
+ "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/sfa_flutter_solana",
+ },
+];
+
+export const coreKitMPCWebExamples: ExamplesInterface[] = [
+ {
+ title: "MPC Core Kit React Quick Start",
+ description: "A quick integration of Multi Party Computation Core Kit SDK in React",
+ image: "banners/react.png",
+ type: QUICK_START,
+ tags: [
+ tags.mpcCoreKit,
+ "mpc",
+ tags.web,
+ tags.mpcCoreKitJS,
+ tags.evm,
+
+ "react",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/quick-starts/mpc-core-kit-react-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/quick-starts/mpc-core-kit-react-quick-start",
+ id: "mpc-core-kit-react-quick-start",
+ },
+ {
+ title: "MPC Core Kit Angular Quick Start",
+ description: "A quick integration of Multi Party Computation Core Kit SDK in angular",
+ image: "banners/angular.png",
+ type: QUICK_START,
+ tags: [
+ tags.mpcCoreKit,
+ "mpc",
+ tags.web,
+ tags.mpcCoreKitJS,
+ tags.evm,
+
+ "angular",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/quick-starts/mpc-core-kit-angular-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/quick-starts/mpc-core-kit-angular-quick-start",
+ id: "mpc-core-kit-angular-quick-start",
+ },
+ {
+ title: "MPC Core Kit Vue Quick Start",
+ description: "A quick integration of Multi Party Computation Core Kit SDK in Vue",
+ image: "banners/vue.png",
+ type: QUICK_START,
+ tags: [tags.mpcCoreKit, "mpc", tags.web, tags.mpcCoreKitJS, tags.evm, "vue", "id token login"],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/quick-starts/mpc-core-kit-vue-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/quick-starts/mpc-core-kit-vue-quick-start",
+ id: "mpc-core-kit-vue-quick-start",
+ },
+ {
+ title: "MPC Core Kit NextJS Quick Start",
+ description: "A quick integration of Multi Party Computation Core Kit SDK in NextJS",
+ image: "banners/next.js.png",
+ type: QUICK_START,
+ tags: [
+ tags.mpcCoreKit,
+ "mpc",
+ tags.web,
+ tags.mpcCoreKitJS,
+ tags.evm,
+
+ "nextjs",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/quick-starts/mpc-core-kit-nextjs-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/quick-starts/mpc-core-kit-nextjs-quick-start",
+ id: "mpc-core-kit-nextjs-quick-start",
+ },
+ {
+ title: "Use Aggregate Verifiers in MPC Core Kit SDK",
+ description:
+ "Aggregate Google, Auth0 GitHub & Email Passwordless in Multi Party Computation Core Kit SDK",
+ image: "banners/auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.mpcCoreKit,
+ "mpc",
+ tags.web,
+ tags.mpcCoreKitJS,
+ tags.evm,
+
+ "aggregate verifier",
+ "google",
+ "github",
+ "email passwordless",
+ "auth0",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/blob/main/mpc-core-kit-web/mpc-core-kit-aggregate-verifier-example/",
+ id: "mpc-core-kit-aggregate-verifier-example",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/blob/main/mpc-core-kit-web/mpc-core-kit-aggregate-verifier-example/",
+ },
+ {
+ title: "Integrate Farcaster Login in MPC Core Kit SDK",
+ description: "Use Farcaster with Multi Party Computation Core Kit SDK",
+ image: "banners/farcaster.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.mpcCoreKit,
+ "mpc",
+ tags.web,
+ tags.mpcCoreKitJS,
+ tags.evm,
+
+ "farcaster",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/mpc-core-kit-farcaster",
+ id: "mpc-core-kit-farcaster",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/mpc-core-kit-farcaster",
+ },
+ {
+ title: "Integrate MPC Core Kit SDK with Solana Blockchain",
+ description: "Use Solana with MPC Core Kit SDK",
+ image: "banners/solana.png",
+ type: SAMPLE_APP,
+ tags: [tags.mpcCoreKit, tags.web, tags.mpcCoreKitJS, tags.evm, tags.solana, "ed25519"],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/mpc-core-kit-solana",
+ id: "mpc-core-kit-solana",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-web/mpc-core-kit-solana",
+ },
+];
+export const coreKitMPCReactNativeExamples: ExamplesInterface[] = [
+ {
+ id: "mpc-core-kit-rn-quick-start",
+ title: "Web3Auth MPC Core Kit React Native Quick Start",
+ description:
+ "A quick integration of Web3Auth Multi Party Computation Core Kit in React Native for Android and iOS",
+ image: "banners/react-native.png",
+ type: QUICK_START,
+ tags: [tags.mpcCoreKit, "mpc", tags.android, tags.evm, tags.ios, tags.reactNative],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-react-native/mpc-core-kit-rn-quick-start",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-react-native/mpc-core-kit-rn-quick-start",
+ },
+ {
+ id: "mpc-core-kit-rn-auth0",
+ title: "Using Auth0 with MPC Core Kit React Native",
+ description:
+ "Integrate Auth0 with Web3Auth Multi Party Computation Core Kit in React Native for Android and iOS",
+ image: "banners/react-native-auth0.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.mpcCoreKit,
+ "mpc",
+
+ tags.android,
+ tags.ios,
+ tags.reactNative,
+ tags.evm,
+ "auth0",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-react-native/mpc-core-kit-rn-auth0",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-react-native/mpc-core-kit-rn-auth0",
+ },
+ {
+ id: "mpc-core-kit-rn-solana",
+ title: "Using Solana MPC Core Kit SDK React Native",
+ description: "Integrate Solana with Web3Auth MPC Core Kit in React Native for Android and iOS",
+ image: "banners/solana.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.mpcCoreKit,
+ "mpc",
+
+ tags.android,
+ tags.ios,
+ tags.reactNative,
+ tags.evm,
+ "auth0",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-react-native/mpc-core-kit-rn-solana",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-react-native/mpc-core-kit-rn-solana",
+ },
+ {
+ id: "mpc-core-kit-rn-expo-auth0",
+ title: "Using MPC Core Kit SDK in Expo",
+ description:
+ "Integrate Auth0 with Web3Auth MPC Core Kit in React Native Expo for Android and iOS",
+ image: "banners/expo.png",
+ type: SAMPLE_APP,
+ tags: [
+ tags.mpcCoreKit,
+ "mpc",
+
+ tags.android,
+ tags.ios,
+ tags.reactNative,
+ tags.evm,
+ "auth0",
+ "id token login",
+ ],
+ link: "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-react-native/mpc-core-kit-rn-expo-auth0",
+ githubLink:
+ "https://github.com/Web3Auth/mpc-core-kit-examples/tree/main/mpc-core-kit-react-native/mpc-core-kit-rn-expo-auth0",
+ },
+];
+
+export const exampleMap: ExamplesInterface[] = [
+ ...webExamples,
+ ...pnpiOSExamples,
+ ...pnpAndroidExamples,
+ ...pnpReactNativeExamples,
+ ...pnpFlutterExamples,
+ ...pnpUnityExamples,
+ ...pnpUnrealExamples,
+ ...coreKitSfaiOSExamples,
+ ...coreKitSfaAndroidExamples,
+ ...coreKitSfaReactNativeExamples,
+ ...coreKitSfaFlutterExamples,
+ ...coreKitMPCWebExamples,
+ ...coreKitMPCReactNativeExamples,
+];
+
+function arrayToObjectById(array) {
+ return array.reduce((acc, obj) => {
+ acc[obj.id] = obj;
+ return acc;
+ }, {});
+}
+
+export const examples = arrayToObjectById(exampleMap);
diff --git a/src/utils/guides-map.tsx b/src/utils/guides-map.tsx
new file mode 100644
index 00000000000..356a6fe0e61
--- /dev/null
+++ b/src/utils/guides-map.tsx
@@ -0,0 +1,104 @@
+export const tags = {
+ web3Auth: "web3auth",
+ embeddedWallet: "embedded wallets",
+ metamaskSdk: "metamask sdk",
+ delegationToolkit: "delegation toolkit",
+ infura: "infura",
+ snaps: "snaps",
+ web: "web",
+ android: "android",
+ ios: "ios",
+ wagmi: "wagmi",
+ reactNative: "react native",
+ flutter: "flutter",
+ node: "node",
+ unity: "unity",
+ unreal: "unreal engine",
+ evm: "evm",
+ solana: "solana",
+ multiChain: "multi chain",
+ xrpl: "xrpl",
+ algorand: "algorand",
+ aptos: "aptos",
+ bitcoin: "bitcoin",
+ cosmos: "cosmos",
+ immutablex: "immutablex",
+ near: "near",
+ polkadot: "polkadot",
+ polymesh: "polymesh",
+ starkex: "starkex",
+ starknet: "starknet",
+ sui: "sui",
+ tezos: "tezos",
+ tron: "tron",
+ ton: "ton",
+ accountAbstraction: "account abstraction",
+ onRamp: "on ramp",
+};
+
+export interface GuidesInterface {
+ content: Record<
+ string,
+ {
+ title: string;
+ image: string;
+ description: string;
+ type: string;
+ tags: string[];
+ date: string;
+ author: string;
+ communityPortalTopicId: string;
+ pinned: string;
+ }
+ >;
+}
+
+export const platformMap = [
+ {
+ label: "Web",
+ value: tags.web,
+ },
+ {
+ label: "Android",
+ value: tags.android,
+ },
+ {
+ label: "iOS/ Swift",
+ value: tags.ios,
+ },
+ {
+ label: "React Native",
+ value: tags.reactNative,
+ },
+ {
+ label: "Flutter",
+ value: tags.flutter,
+ },
+ {
+ label: "Unity",
+ value: tags.unity,
+ },
+ {
+ label: "Unreal Engine",
+ value: tags.unreal,
+ },
+ {
+ label: "Node.js",
+ value: tags.node,
+ },
+];
+
+export const productMap = [
+ {
+ label: "Metamask SDK",
+ value: tags.metamaskSdk,
+ },
+ {
+ label: "Embedded Wallets",
+ value: tags.embeddedWallet,
+ },
+ {
+ label: "Delegation Toolkit",
+ value: tags.delegationToolkit,
+ },
+];
\ No newline at end of file
diff --git a/src/utils/qs-file-links.json b/src/utils/qs-file-links.json
new file mode 100644
index 00000000000..3cf455ec594
--- /dev/null
+++ b/src/utils/qs-file-links.json
@@ -0,0 +1,90 @@
+{
+ "EW_REACT_APP_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/App.tsx",
+ "EW_REACT_MAIN_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/main.tsx",
+ "EW_REACT_WEB3AUTHCONTEXT_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/web3authContext.tsx",
+ "EW_REACT_PACKAGE_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/package.json",
+ "EW_REACT_INDEX_HTML": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/index.html",
+ "EW_REACT_GET_BALANCE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/getBalance.tsx",
+ "EW_REACT_SEND_TRANSACTION_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/sendTransaction.tsx",
+ "EW_REACT_SWITCH_NETWORK_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/switchNetwork.tsx",
+ "EW_NEXTJS_LAYOUT_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/app/layout.tsx",
+ "EW_NEXTJS_PAGE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/app/page.tsx",
+ "EW_NEXTJS_COMPONENTS_APP_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/App.tsx",
+ "EW_NEXTJS_COMPONENTS_PROVIDER_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/provider.tsx",
+ "EW_NEXTJS_PACKAGE_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/package.json",
+ "EW_NEXTJS_GET_BALANCE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/getBalance.tsx",
+ "EW_NEXTJS_SEND_TRANSACTION_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/sendTransaction.tsx",
+ "EW_NEXTJS_SWITCH_NETWORK_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/switchNetwork.tsx",
+ "MMSDK_REACT_APP_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/App.tsx",
+ "MMSDK_REACT_MAIN_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/main.tsx",
+ "MMSDK_REACT_WEB3AUTHCONTEXT_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/web3authContext.tsx",
+ "MMSDK_REACT_PACKAGE_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/package.json",
+ "MMSDK_REACT_INDEX_HTML": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/index.html",
+ "MMSDK_REACT_GET_BALANCE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/getBalance.tsx",
+ "MMSDK_REACT_SEND_TRANSACTION_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/sendTransaction.tsx",
+ "MMSDK_REACT_SWITCH_NETWORK_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/switchNetwork.tsx",
+ "MMSDK_NEXTJS_LAYOUT_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/app/layout.tsx",
+ "MMSDK_NEXTJS_PAGE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/app/page.tsx",
+ "MMSDK_NEXTJS_COMPONENTS_APP_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/App.tsx",
+ "MMSDK_NEXTJS_COMPONENTS_PROVIDER_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/provider.tsx",
+ "MMSDK_NEXTJS_PACKAGE_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/package.json",
+ "MMSDK_NEXTJS_GET_BALANCE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/getBalance.tsx",
+ "MMSDK_NEXTJS_SEND_TRANSACTION_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/sendTransaction.tsx",
+ "MMSDK_NEXTJS_SWITCH_NETWORK_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/switchNetwork.tsx",
+ "DTK_REACT_APP_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/App.tsx",
+ "DTK_REACT_MAIN_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/main.tsx",
+ "DTK_REACT_WEB3AUTHCONTEXT_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/web3authContext.tsx",
+ "DTK_REACT_PACKAGE_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/package.json",
+ "DTK_REACT_INDEX_HTML": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/index.html",
+ "DTK_REACT_GET_BALANCE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/getBalance.tsx",
+ "DTK_REACT_SEND_TRANSACTION_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/sendTransaction.tsx",
+ "DTK_REACT_SWITCH_NETWORK_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/react-quick-start/src/components/switchNetwork.tsx",
+ "DTK_NEXTJS_LAYOUT_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/app/layout.tsx",
+ "DTK_NEXTJS_PAGE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/app/page.tsx",
+ "DTK_NEXTJS_COMPONENTS_APP_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/App.tsx",
+ "DTK_NEXTJS_COMPONENTS_PROVIDER_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/provider.tsx",
+ "DTK_NEXTJS_PACKAGE_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/package.json",
+ "DTK_NEXTJS_GET_BALANCE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/getBalance.tsx",
+ "DTK_NEXTJS_SEND_TRANSACTION_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/sendTransaction.tsx",
+ "DTK_NEXTJS_SWITCH_NETWORK_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/nextjs-quick-start/components/wagmi/switchNetwork.tsx",
+ "EW_ANGULAR_APP_COMPONENT_TS": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/angular-quick-start/src/app/app.component.ts",
+ "EW_ANGULAR_APP_COMPONENT_HTML": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/angular-quick-start/src/app/app.component.html",
+ "EW_ANGULAR_POLYFILL_TS": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/angular-quick-start/src/polyfills.ts",
+ "EW_ANGULAR_PACKAGE_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/angular-quick-start/package.json",
+ "EW_ANGULAR_TSCONFIG_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/angular-quick-start/tsconfig.json",
+ "EW_ANGULAR_ETHERSRPC_TS": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/angular-quick-start/src/app/ethersRPC.ts",
+ "EW_ANGULAR_VIEMRPC_TS": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/angular-quick-start/src/app/viemRPC.ts",
+ "EW_VUE_CONFIG_JS": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/vue-quick-start/vue.config.js",
+ "EW_VUE_PACKAGE_JSON": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/vue-quick-start/package.json",
+ "EW_VUE_HOME_VUE": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/vue-quick-start/src/Home.vue",
+ "EW_VUE_APP_VUE": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/vue-quick-start/src/App.vue",
+ "EW_VUE_WEB3AUTHCONTEXT_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/vue-quick-start/src/web3authContext.tsx",
+ "EW_VUE_GET_BALANCE_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/vue-quick-start/src/components/Balance.vue",
+ "EW_VUE_SEND_TRANSACTION_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/vue-quick-start/src/components/SendTransaction.vue",
+ "EW_VUE_SWITCH_NETWORK_TSX": "Web3Auth/web3auth-examples/refs/heads/main/quick-starts/vue-quick-start/src/components/SwitchNetwork.vue",
+ "EW_PNP_UNITY_WEB3AUTHSCRIPT_CS": "Web3Auth/web3auth-unity-examples/refs/heads/main/unity-quick-start/Assets/Web3AuthScript.cs",
+ "EW_PNP_UNITY_ANDROID_MANIFEST": "Web3Auth/web3auth-unity-examples/refs/heads/main/unity-quick-start/Assets/Plugins/Android/AndroidManifest.xml",
+ "EW_PNP_UNITY_MANIFEST_JSON": "Web3Auth/web3auth-unity-examples/refs/heads/main/unity-quick-start/Packages/manifest.json",
+ "EW_PNP_REACT_NATIVE_APP_TSX": "Web3Auth/web3auth-react-native-examples/main/rn-bare-quick-start/App.tsx",
+ "EW_PNP_REACT_NATIVE_PACKAGE_JSON": "Web3Auth/web3auth-react-native-examples/main/rn-bare-quick-start/package.json",
+ "EW_PNP_REACT_NATIVE_METRO_CONFIG_JS": "Web3Auth/web3auth-react-native-examples/main/rn-bare-quick-start/metro.config.js",
+ "EW_PNP_REACT_NATIVE_GLOBALS_JS": "Web3Auth/web3auth-react-native-examples/main/rn-bare-quick-start/globals.js",
+ "EW_PNP_REACT_NATIVE_INDEX_JS": "Web3Auth/web3auth-react-native-examples/main/rn-bare-quick-start/index.js",
+ "EW_PNP_REACT_NATIVE_PODFILE": "Web3Auth/web3auth-react-native-examples/main/rn-bare-quick-start/ios/Podfile",
+ "EW_PNP_REACT_NATIVE_BUILD_GRADLE": "Web3Auth/web3auth-react-native-examples/main/rn-bare-quick-start/android/build.gradle",
+ "EW_PNP_IOS_CONTENTVIEW_SWIFT": "Web3Auth/web3auth-ios-examples/main/ios-quick-start/ios-example/ContentView.swift",
+ "EW_PNP_IOS_LOGINVIEW_SWIFT": "Web3Auth/web3auth-ios-examples/main/ios-quick-start/ios-example/LoginView.swift",
+ "EW_PNP_IOS_USERDETAILVIEW_SWIFT": "Web3Auth/web3auth-ios-examples/main/ios-quick-start/ios-example/UserDetailView.swift",
+ "EW_PNP_IOS_VIEWMODEL_SWIFT": "Web3Auth/web3auth-ios-examples/main/ios-quick-start/ios-example/ViewModel.swift",
+ "EW_PNP_IOS_WEB3RPC_SWIFT": "Web3Auth/web3auth-ios-examples/main/ios-quick-start/ios-example/web3RPC.swift",
+ "EW_PNP_FLUTTER_MAIN_DART": "Web3Auth/web3auth-flutter-examples/main/flutter-quick-start/lib/main.dart",
+ "EW_PNP_FLUTTER_BUILD_GRADLE": "Web3Auth/web3auth-flutter-examples/main/flutter-quick-start/android/app/build.gradle",
+ "EW_PNP_FLUTTER_PODFILE": "Web3Auth/web3auth-flutter-examples/main/flutter-quick-start/ios/Podfile",
+ "EW_PNP_FLUTTER_PUBSPEC_YAML": "Web3Auth/web3auth-flutter-examples/main/flutter-quick-start/pubspec.yaml",
+ "EW_PNP_ANDROID_MAINACTIVITY_KT": "Web3Auth/web3auth-android-examples/main/android-quick-start/app/src/main/java/com/sbz/web3authdemoapp/MainActivity.kt",
+ "EW_PNP_ANDROID_ANDROIDMANIFEST_XML": "Web3Auth/web3auth-android-examples/main/android-quick-start/app/src/main/AndroidManifest.xml",
+ "EW_PNP_ANDROID_BUILD_GRADLE": "Web3Auth/web3auth-android-examples/main/android-quick-start/app/build.gradle",
+ "EW_PNP_ANDROID_SETTINGS_GRADLE": "Web3Auth/web3auth-android-examples/main/android-quick-start/settings.gradle",
+ "EW_PNP_ANDROID_STRINGS_XML": "Web3Auth/web3auth-android-examples/main/android-quick-start/app/src/main/res/values/strings.xml",
+ "EW_PNP_ANDROID_ACTIVITY_MAIN_XML": "Web3Auth/web3auth-android-examples/main/android-quick-start/app/src/main/res/layout/activity_main.xml"
+}
\ No newline at end of file
diff --git a/src/utils/qs-map.tsx b/src/utils/qs-map.tsx
new file mode 100644
index 00000000000..b939f3904d4
--- /dev/null
+++ b/src/utils/qs-map.tsx
@@ -0,0 +1,56 @@
+export const EWQuickStartHostedLinks = {
+ // PNP Modal SDK
+ ANGULAR: "https://web3auth-angular-quick-start.vercel.app/",
+ HTML: "https://web3auth-vanillajs-quick-start.vercel.app/",
+ NEXTJS: "https://web3auth-nextjs-quick-start.vercel.app/",
+ REACT: "https://web3auth-react-quick-start-tau.vercel.app/",
+ REACT_SOLANA: "https://web3auth-react-solana-quick-start.vercel.app/",
+ VUE: "https://web3auth-vue-quick-start.vercel.app/",
+ VUE_SOLANA: "https://web3auth-vue-solana-quick-start.vercel.app/",
+ ANDROID: "https://w3a.link/pnp-android-quick-start",
+ IOS: "https://w3a.link/pnp-ios-quick-start", // https://w3a.link/pnp-ios-quick-start",
+ REACT_NATIVE: "https://w3a.link/pnp-react-native-android-quick-start",
+ FLUTTER: "https://w3a.link/pnp-flutter-android-quick-start",
+ UNITY: "https://w3a.link/pnp-unity-android-quick-start",
+};
+
+export const DTKQuickStartHostedLinks = {
+ REACT: "https://web3auth-react-quick-start-tau.vercel.app/",
+ NEXTJS: "https://web3auth-nextjs-quick-start.vercel.app/",
+};
+
+export const MMSDKQuickStartHostedLinks = {
+ REACT: "https://web3auth-react-quick-start-tau.vercel.app/",
+ NEXTJS: "https://web3auth-nextjs-quick-start.vercel.app/",
+};
+
+export const EWQuickStartSourceCode = {
+ REACT: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-quick-start",
+ REACT_SOLANA:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-solana-quick-start",
+ ANGULAR:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/angular-quick-start",
+ VUE: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vue-quick-start",
+ VUE_SOLANA:
+ "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vue-solana-quick-start",
+ NEXTJS: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/nextjs-quick-start",
+ HTML: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/vanillajs-quick-start",
+ ANDROID: "https://github.com/Web3Auth/web3auth-android-examples/tree/main/android-quick-start",
+ IOS: "https://github.com/Web3Auth/web3auth-ios-examples/tree/main/ios-quick-start",
+ REACT_NATIVE:
+ "https://github.com/Web3Auth/web3auth-react-native-examples/tree/main/rn-bare-quick-start",
+ FLUTTER: "https://github.com/Web3Auth/web3auth-flutter-examples/tree/main/flutter-quick-start",
+ UNITY: "https://github.com/Web3Auth/web3auth-unity-examples/tree/main/unity-quick-start",
+ UNREAL: "https://github.com/Web3Auth/web3auth-unreal-example/tree/master",
+};
+
+export const DTKQuickStartSourceCode = {
+ REACT: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-quick-start",
+ NEXTJS: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/nextjs-quick-start",
+};
+
+export const MMSDKQuickStartSourceCode = {
+ REACT: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/react-quick-start",
+ NEXTJS: "https://github.com/Web3Auth/web3auth-examples/tree/main/quick-starts/nextjs-quick-start",
+};
+
diff --git a/static/img/guides/android-wallet-preview.png b/static/img/guides/android-wallet-preview.png
new file mode 100644
index 00000000000..6363e17513a
Binary files /dev/null and b/static/img/guides/android-wallet-preview.png differ
diff --git a/static/img/guides/flutter-wallet-preview.png b/static/img/guides/flutter-wallet-preview.png
new file mode 100644
index 00000000000..93b4331780d
Binary files /dev/null and b/static/img/guides/flutter-wallet-preview.png differ
diff --git a/static/img/guides/graph-6-final.png b/static/img/guides/graph-6-final.png
new file mode 100644
index 00000000000..a2d46371e94
Binary files /dev/null and b/static/img/guides/graph-6-final.png differ
diff --git a/static/img/guides/guides-banners/android-wallet.png b/static/img/guides/guides-banners/android-wallet.png
new file mode 100644
index 00000000000..49b0921f9b1
Binary files /dev/null and b/static/img/guides/guides-banners/android-wallet.png differ
diff --git a/static/img/guides/guides-banners/erc20-paymaster.png b/static/img/guides/guides-banners/erc20-paymaster.png
new file mode 100644
index 00000000000..a0a5596d4d2
Binary files /dev/null and b/static/img/guides/guides-banners/erc20-paymaster.png differ
diff --git a/static/img/guides/guides-banners/flutter-wallet.png b/static/img/guides/guides-banners/flutter-wallet.png
new file mode 100644
index 00000000000..58aa31effa2
Binary files /dev/null and b/static/img/guides/guides-banners/flutter-wallet.png differ
diff --git a/static/img/guides/guides-banners/gasless-transaction.png b/static/img/guides/guides-banners/gasless-transaction.png
new file mode 100644
index 00000000000..70a189fcd85
Binary files /dev/null and b/static/img/guides/guides-banners/gasless-transaction.png differ
diff --git a/static/img/guides/guides-banners/multi.png b/static/img/guides/guides-banners/multi.png
new file mode 100644
index 00000000000..81a805b6b78
Binary files /dev/null and b/static/img/guides/guides-banners/multi.png differ
diff --git a/static/img/guides/guides-banners/telegram-miniapp-client.png b/static/img/guides/guides-banners/telegram-miniapp-client.png
new file mode 100644
index 00000000000..328b0098bce
Binary files /dev/null and b/static/img/guides/guides-banners/telegram-miniapp-client.png differ
diff --git a/static/img/guides/guides-banners/telegram-miniapp-server.png b/static/img/guides/guides-banners/telegram-miniapp-server.png
new file mode 100644
index 00000000000..5bd1165fffb
Binary files /dev/null and b/static/img/guides/guides-banners/telegram-miniapp-server.png differ
diff --git a/static/img/guides/guides-banners/telegram-oauth.png b/static/img/guides/guides-banners/telegram-oauth.png
new file mode 100644
index 00000000000..c12a4444740
Binary files /dev/null and b/static/img/guides/guides-banners/telegram-oauth.png differ
diff --git a/static/img/guides/login-key-assignments.png b/static/img/guides/login-key-assignments.png
new file mode 100644
index 00000000000..300332daf08
Binary files /dev/null and b/static/img/guides/login-key-assignments.png differ
diff --git a/static/img/guides/telegram-mini-app-flow-diagram.png b/static/img/guides/telegram-mini-app-flow-diagram.png
new file mode 100644
index 00000000000..c3eca4ec4b1
Binary files /dev/null and b/static/img/guides/telegram-mini-app-flow-diagram.png differ
diff --git a/static/img/guides/web3auth-pnp-working.png b/static/img/guides/web3auth-pnp-working.png
new file mode 100644
index 00000000000..3e176b9997c
Binary files /dev/null and b/static/img/guides/web3auth-pnp-working.png differ
diff --git a/static/img/guides/whitelabel-web3auth-openlogin-dark.png b/static/img/guides/whitelabel-web3auth-openlogin-dark.png
new file mode 100644
index 00000000000..a40560a1f8b
Binary files /dev/null and b/static/img/guides/whitelabel-web3auth-openlogin-dark.png differ
diff --git a/static/img/guides/whitelabel-web3auth-openlogin-language.png b/static/img/guides/whitelabel-web3auth-openlogin-language.png
new file mode 100644
index 00000000000..426fc0de5db
Binary files /dev/null and b/static/img/guides/whitelabel-web3auth-openlogin-language.png differ
diff --git a/static/img/guides/whitelabel-web3auth-openlogin-light.png b/static/img/guides/whitelabel-web3auth-openlogin-light.png
new file mode 100644
index 00000000000..392248a469e
Binary files /dev/null and b/static/img/guides/whitelabel-web3auth-openlogin-light.png differ
diff --git a/static/img/guides/whitelabel-web3auth-openlogin-logo-dark.png b/static/img/guides/whitelabel-web3auth-openlogin-logo-dark.png
new file mode 100644
index 00000000000..0d49346cf9d
Binary files /dev/null and b/static/img/guides/whitelabel-web3auth-openlogin-logo-dark.png differ
diff --git a/static/img/guides/whitelabel-web3auth-openlogin-logo-light.png b/static/img/guides/whitelabel-web3auth-openlogin-logo-light.png
new file mode 100644
index 00000000000..ddbc74e7d5f
Binary files /dev/null and b/static/img/guides/whitelabel-web3auth-openlogin-logo-light.png differ
diff --git a/static/img/guides/whitelabel-web3auth-openlogin-theme1.png b/static/img/guides/whitelabel-web3auth-openlogin-theme1.png
new file mode 100644
index 00000000000..dfe46479560
Binary files /dev/null and b/static/img/guides/whitelabel-web3auth-openlogin-theme1.png differ
diff --git a/static/img/guides/whitelabel-web3auth-openlogin-theme2.png b/static/img/guides/whitelabel-web3auth-openlogin-theme2.png
new file mode 100644
index 00000000000..6ef3e7f32eb
Binary files /dev/null and b/static/img/guides/whitelabel-web3auth-openlogin-theme2.png differ
diff --git a/static/img/web3auth-dashboard/auth0-connection.png b/static/img/web3auth-dashboard/auth0-connection.png
new file mode 100644
index 00000000000..fb58419aa51
Binary files /dev/null and b/static/img/web3auth-dashboard/auth0-connection.png differ
diff --git a/static/img/web3auth-dashboard/authentication-custom-connections.png b/static/img/web3auth-dashboard/authentication-custom-connections.png
new file mode 100644
index 00000000000..e2f86617810
Binary files /dev/null and b/static/img/web3auth-dashboard/authentication-custom-connections.png differ
diff --git a/static/img/web3auth-dashboard/authentication-group-connections-confirm.png b/static/img/web3auth-dashboard/authentication-group-connections-confirm.png
new file mode 100644
index 00000000000..7236237642f
Binary files /dev/null and b/static/img/web3auth-dashboard/authentication-group-connections-confirm.png differ
diff --git a/static/img/web3auth-dashboard/authentication-group-connections-create.png b/static/img/web3auth-dashboard/authentication-group-connections-create.png
new file mode 100644
index 00000000000..21cd3926e8c
Binary files /dev/null and b/static/img/web3auth-dashboard/authentication-group-connections-create.png differ
diff --git a/static/img/web3auth-dashboard/authentication-group-connections-select.png b/static/img/web3auth-dashboard/authentication-group-connections-select.png
new file mode 100644
index 00000000000..11c641e8517
Binary files /dev/null and b/static/img/web3auth-dashboard/authentication-group-connections-select.png differ
diff --git a/static/img/web3auth-dashboard/authentication-social-connections.png b/static/img/web3auth-dashboard/authentication-social-connections.png
new file mode 100644
index 00000000000..84223b16280
Binary files /dev/null and b/static/img/web3auth-dashboard/authentication-social-connections.png differ
diff --git a/static/img/web3auth-dashboard/aws-cognito-connection.png b/static/img/web3auth-dashboard/aws-cognito-connection.png
new file mode 100644
index 00000000000..128b7b9f6d4
Binary files /dev/null and b/static/img/web3auth-dashboard/aws-cognito-connection.png differ
diff --git a/static/img/web3auth-dashboard/chains-and-networks.png b/static/img/web3auth-dashboard/chains-and-networks.png
new file mode 100644
index 00000000000..2cbf5d19729
Binary files /dev/null and b/static/img/web3auth-dashboard/chains-and-networks.png differ
diff --git a/static/img/web3auth-dashboard/create-verifier.gif b/static/img/web3auth-dashboard/create-verifier.gif
new file mode 100644
index 00000000000..d1e1fc8f12a
Binary files /dev/null and b/static/img/web3auth-dashboard/create-verifier.gif differ
diff --git a/static/img/web3auth-dashboard/create-verifier.png b/static/img/web3auth-dashboard/create-verifier.png
new file mode 100644
index 00000000000..e2cc9ee1525
Binary files /dev/null and b/static/img/web3auth-dashboard/create-verifier.png differ
diff --git a/static/img/web3auth-dashboard/custom-connection.png b/static/img/web3auth-dashboard/custom-connection.png
new file mode 100644
index 00000000000..a590f395651
Binary files /dev/null and b/static/img/web3auth-dashboard/custom-connection.png differ
diff --git a/static/img/web3auth-dashboard/customization-branding.png b/static/img/web3auth-dashboard/customization-branding.png
new file mode 100644
index 00000000000..acd5dca69c7
Binary files /dev/null and b/static/img/web3auth-dashboard/customization-branding.png differ
diff --git a/static/img/web3auth-dashboard/customization-login-modal.png b/static/img/web3auth-dashboard/customization-login-modal.png
new file mode 100644
index 00000000000..314de196db8
Binary files /dev/null and b/static/img/web3auth-dashboard/customization-login-modal.png differ
diff --git a/static/img/web3auth-dashboard/dashboard-analytics.png b/static/img/web3auth-dashboard/dashboard-analytics.png
new file mode 100644
index 00000000000..71442474324
Binary files /dev/null and b/static/img/web3auth-dashboard/dashboard-analytics.png differ
diff --git a/static/img/web3auth-dashboard/dashboard-private-key-export.png b/static/img/web3auth-dashboard/dashboard-private-key-export.png
new file mode 100644
index 00000000000..837d8dc3403
Binary files /dev/null and b/static/img/web3auth-dashboard/dashboard-private-key-export.png differ
diff --git a/static/img/web3auth-dashboard/dashboard-signup.gif b/static/img/web3auth-dashboard/dashboard-signup.gif
new file mode 100644
index 00000000000..88d1978692e
Binary files /dev/null and b/static/img/web3auth-dashboard/dashboard-signup.gif differ
diff --git a/static/img/web3auth-dashboard/discord-connection.png b/static/img/web3auth-dashboard/discord-connection.png
new file mode 100644
index 00000000000..5e008e009f0
Binary files /dev/null and b/static/img/web3auth-dashboard/discord-connection.png differ
diff --git a/static/img/web3auth-dashboard/email-passwordless-add-connection.png b/static/img/web3auth-dashboard/email-passwordless-add-connection.png
new file mode 100644
index 00000000000..4b9c1f880c2
Binary files /dev/null and b/static/img/web3auth-dashboard/email-passwordless-add-connection.png differ
diff --git a/static/img/web3auth-dashboard/email-passwordless-onboarding.gif b/static/img/web3auth-dashboard/email-passwordless-onboarding.gif
new file mode 100644
index 00000000000..03b6955cf09
Binary files /dev/null and b/static/img/web3auth-dashboard/email-passwordless-onboarding.gif differ
diff --git a/static/img/web3auth-dashboard/email-passwordless-toggle.png b/static/img/web3auth-dashboard/email-passwordless-toggle.png
new file mode 100644
index 00000000000..a38db191a0f
Binary files /dev/null and b/static/img/web3auth-dashboard/email-passwordless-toggle.png differ
diff --git a/static/img/web3auth-dashboard/external-wallets-select-wallets.png b/static/img/web3auth-dashboard/external-wallets-select-wallets.png
new file mode 100644
index 00000000000..50d6e50148e
Binary files /dev/null and b/static/img/web3auth-dashboard/external-wallets-select-wallets.png differ
diff --git a/static/img/web3auth-dashboard/external-wallets-toggle.png b/static/img/web3auth-dashboard/external-wallets-toggle.png
new file mode 100644
index 00000000000..aa8e892d847
Binary files /dev/null and b/static/img/web3auth-dashboard/external-wallets-toggle.png differ
diff --git a/static/img/web3auth-dashboard/facebook-connection.png b/static/img/web3auth-dashboard/facebook-connection.png
new file mode 100644
index 00000000000..b75f9c843a1
Binary files /dev/null and b/static/img/web3auth-dashboard/facebook-connection.png differ
diff --git a/static/img/web3auth-dashboard/firebase-connection.png b/static/img/web3auth-dashboard/firebase-connection.png
new file mode 100644
index 00000000000..084800f1ead
Binary files /dev/null and b/static/img/web3auth-dashboard/firebase-connection.png differ
diff --git a/static/img/web3auth-dashboard/google-connection.png b/static/img/web3auth-dashboard/google-connection.png
new file mode 100644
index 00000000000..456e64027c9
Binary files /dev/null and b/static/img/web3auth-dashboard/google-connection.png differ
diff --git a/static/img/web3auth-dashboard/project-details.png b/static/img/web3auth-dashboard/project-details.png
new file mode 100644
index 00000000000..ac840ed063d
Binary files /dev/null and b/static/img/web3auth-dashboard/project-details.png differ
diff --git a/static/img/web3auth-dashboard/project-settings-advanced.png b/static/img/web3auth-dashboard/project-settings-advanced.png
new file mode 100644
index 00000000000..a38269bdbe9
Binary files /dev/null and b/static/img/web3auth-dashboard/project-settings-advanced.png differ
diff --git a/static/img/web3auth-dashboard/project-settings-domain.png b/static/img/web3auth-dashboard/project-settings-domain.png
new file mode 100644
index 00000000000..493b424d470
Binary files /dev/null and b/static/img/web3auth-dashboard/project-settings-domain.png differ
diff --git a/static/img/web3auth-dashboard/project-settings-general.png b/static/img/web3auth-dashboard/project-settings-general.png
new file mode 100644
index 00000000000..ab75e211a84
Binary files /dev/null and b/static/img/web3auth-dashboard/project-settings-general.png differ
diff --git a/static/img/web3auth-dashboard/smart-account/configure-paymaster.png b/static/img/web3auth-dashboard/smart-account/configure-paymaster.png
new file mode 100644
index 00000000000..71f54349a72
Binary files /dev/null and b/static/img/web3auth-dashboard/smart-account/configure-paymaster.png differ
diff --git a/static/img/web3auth-dashboard/smart-account/enable-smart-account.png b/static/img/web3auth-dashboard/smart-account/enable-smart-account.png
new file mode 100644
index 00000000000..9b8e773df17
Binary files /dev/null and b/static/img/web3auth-dashboard/smart-account/enable-smart-account.png differ
diff --git a/static/img/web3auth-dashboard/sms-otp-add-connection.png b/static/img/web3auth-dashboard/sms-otp-add-connection.png
new file mode 100644
index 00000000000..7beda3697b0
Binary files /dev/null and b/static/img/web3auth-dashboard/sms-otp-add-connection.png differ
diff --git a/static/img/web3auth-dashboard/sms-otp-toggle.png b/static/img/web3auth-dashboard/sms-otp-toggle.png
new file mode 100644
index 00000000000..f69d3f1a27d
Binary files /dev/null and b/static/img/web3auth-dashboard/sms-otp-toggle.png differ
diff --git a/static/img/web3auth-dashboard/twitch-connection.png b/static/img/web3auth-dashboard/twitch-connection.png
new file mode 100644
index 00000000000..7be46daf049
Binary files /dev/null and b/static/img/web3auth-dashboard/twitch-connection.png differ
diff --git a/static/img/web3auth-dashboard/wallet-configuration.png b/static/img/web3auth-dashboard/wallet-configuration.png
new file mode 100644
index 00000000000..c801bc86c36
Binary files /dev/null and b/static/img/web3auth-dashboard/wallet-configuration.png differ
diff --git a/static/img/web3auth-dashboard/web3auth-client-id.png b/static/img/web3auth-dashboard/web3auth-client-id.png
new file mode 100644
index 00000000000..ac0e1f85857
Binary files /dev/null and b/static/img/web3auth-dashboard/web3auth-client-id.png differ
diff --git a/static/js/code-focus.js b/static/js/code-focus.js
new file mode 100644
index 00000000000..eac41a49acd
--- /dev/null
+++ b/static/js/code-focus.js
@@ -0,0 +1,18 @@
+document.addEventListener("DOMContentLoaded", function () {
+ const observer = new MutationObserver(function (mutations) {
+ mutations.forEach(function (mutation) {
+ const codeBlocks = document.querySelectorAll("code");
+
+ codeBlocks.forEach(function (codeBlock) {
+ const hasCodeFocus = codeBlock.querySelector(".code-focus") !== null;
+
+ if (hasCodeFocus) {
+ codeBlock.classList.add("blurred-code");
+ }
+ });
+ });
+ });
+
+ // Start observing the document for additions to the DOM
+ observer.observe(document.body, { childList: true, subtree: true });
+});
diff --git a/static/js/fix-trailing-slash.js b/static/js/fix-trailing-slash.js
new file mode 100644
index 00000000000..61592bf70db
--- /dev/null
+++ b/static/js/fix-trailing-slash.js
@@ -0,0 +1,3 @@
+if (window && window.location && window.location.pathname.endsWith('/') && window.location.pathname !== '/') {
+ window.history.replaceState('', '', window.location.pathname.substr(0, window.location.pathname.length - 1))
+}
diff --git a/wallet/reference/json-rpc-methods/index.md b/wallet/reference/json-rpc-methods/index.md
index 4078eb1808a..b95141a37ee 100644
--- a/wallet/reference/json-rpc-methods/index.md
+++ b/wallet/reference/json-rpc-methods/index.md
@@ -1,5 +1,5 @@
---
-sidebar_class_name: "hidden"
+sidebar_class_name: 'hidden'
description: See the MetaMask JSON-RPC API reference.
---
@@ -17,4 +17,4 @@ Each method may have one or more of the following labels:
- **Ethereum API** - These are standard Ethereum JSON-RPC API methods. See the [Ethereum wiki](https://ethereum.org/en/#json-rpc-methods) for more information about these methods.
- **Multichain API** - These methods are compatible with the [Multichain API](../multichain-api.md).
- **Experimental** - These methods are experimental and may be changed in the future.
-- **Deprecated** - These methods are deprecated and may be removed in the future.
\ No newline at end of file
+- **Deprecated** - These methods are deprecated and may be removed in the future.
diff --git a/web3auth-sidebar.ts b/web3auth-sidebar.ts
new file mode 100644
index 00000000000..3abaf4d4b3e
--- /dev/null
+++ b/web3auth-sidebar.ts
@@ -0,0 +1,1323 @@
+import type { SidebarsConfig } from "@docusaurus/plugin-content-docs";
+
+import {
+ reactJS,
+ vue,
+ android,
+ ios,
+ reactnative,
+ flutter,
+ unity,
+ unreal,
+ js,
+} from "./src/common/SDKOptions";
+
+import {
+ getPnPVersion,
+ getSFAVersion,
+ getMPCCoreKitVersion,
+ pnpWebVersion,
+} from "./src/common/versions";
+
+function webTopNavButton(selectedSDK: string): string {
+ const baseUrl = process.env.REACT_APP_BASE_URL || "/docs/";
+
+ var webSDKs = {
+ [reactJS]: `${baseUrl}sdk/web/react`,
+ [vue]: `${baseUrl}sdk/web/vue`,
+ [js]: `${baseUrl}sdk/web/js`,
+ };
+ if (webSDKs.hasOwnProperty(selectedSDK)) {
+ delete webSDKs[selectedSDK];
+ }
+ var sdkNames = Object.keys(webSDKs);
+ var sdkLinks = Object.values(webSDKs);
+ var sdkVersion = pnpWebVersion;
+
+ return `
+ `;
+}
+
+function gamingTopNavButton(selectedSDK: string): string {
+ const baseUrl = process.env.REACT_APP_BASE_URL || "/docs/";
+
+ var gamingSDKs = {
+ [unity]: `${baseUrl}sdk/gaming/unity`,
+ [unreal]: `${baseUrl}sdk/gaming/unreal`,
+ };
+ if (gamingSDKs.hasOwnProperty(selectedSDK)) {
+ delete gamingSDKs[selectedSDK];
+ }
+ var sdkNames = Object.keys(gamingSDKs);
+ var sdkLinks = Object.values(gamingSDKs);
+ var sdkVersion = getPnPVersion(selectedSDK);
+
+ return `
+ `;
+}
+
+function pnpMobileTopNavButton(selectedSDK: string): string {
+ const baseUrl = process.env.REACT_APP_BASE_URL || "/docs/";
+
+ var pnpMobileSDKs = {
+ [android]: `${baseUrl}sdk/mobile/pnp/android`,
+ [ios]: `${baseUrl}sdk/mobile/pnp/ios`,
+ [reactnative]: `${baseUrl}sdk/mobile/pnp/react-native`,
+ [flutter]: `${baseUrl}sdk/mobile/pnp/flutter`,
+ };
+ if (pnpMobileSDKs.hasOwnProperty(selectedSDK)) {
+ delete pnpMobileSDKs[selectedSDK];
+ }
+ var sdkNames = Object.keys(pnpMobileSDKs);
+ var sdkLinks = Object.values(pnpMobileSDKs);
+ var sdkVersion = getPnPVersion(selectedSDK);
+
+ return `
+ `;
+}
+
+function sfaMobileTopNavButton(selectedSDK: string): string {
+ const baseUrl = process.env.REACT_APP_BASE_URL || "/docs/";
+
+ var sfaMobileSDKs = {
+ [android]: `${baseUrl}sdk/mobile/sfa/android`,
+ [ios]: `${baseUrl}sdk/mobile/sfa/ios`,
+ [reactnative]: `${baseUrl}sdk/mobile/sfa/react-native`,
+ [flutter]: `${baseUrl}sdk/mobile/sfa/flutter`,
+ };
+ if (sfaMobileSDKs.hasOwnProperty(selectedSDK)) {
+ delete sfaMobileSDKs[selectedSDK];
+ }
+ var sdkNames = Object.keys(sfaMobileSDKs);
+ var sdkLinks = Object.values(sfaMobileSDKs);
+ var sdkVersion = getSFAVersion(selectedSDK);
+
+ return `
+ `;
+}
+
+function mpcckTopNavButton(selectedSDK: string): string {
+ const baseUrl = process.env.REACT_APP_BASE_URL || "/docs/";
+
+ var mpcCoreKitSDKs = {
+ [js]: `${baseUrl}sdk/mpc-core-kit/mpc-core-kit-js`,
+ [reactnative]: `${baseUrl}sdk/mpc-core-kit/mpc-core-kit-react-native`,
+ };
+ if (mpcCoreKitSDKs.hasOwnProperty(selectedSDK)) {
+ delete mpcCoreKitSDKs[selectedSDK];
+ }
+ var sdkNames = Object.keys(mpcCoreKitSDKs);
+ var sdkLinks = Object.values(mpcCoreKitSDKs);
+ var sdkVersion = getMPCCoreKitVersion(selectedSDK);
+
+ return `
+ `;
+}
+
+const sdkQuickLinks: any = [
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ {
+ type: "link",
+ label: "Quick Start",
+ href: "/quick-start",
+ },
+ {
+ type: "link",
+ label: "Examples",
+ href: "/examples",
+ },
+ {
+ type: "link",
+ label: "Authentication",
+ href: "/authentication",
+ },
+ {
+ type: "link",
+ label: "Connect Blockchain",
+ href: "/connect-blockchain",
+ },
+ {
+ type: "link",
+ label: "Troubleshooting",
+ href: "/troubleshooting",
+ },
+ {
+ type: "link",
+ label: "Dashboard",
+ href: "/dashboard",
+ },
+];
+
+const sidebars: SidebarsConfig = {
+ docs: [
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ {
+ type: "doc",
+ id: "README",
+ },
+ "what-is-web3auth",
+ "how-web3auth-works",
+ {
+ type: "category",
+ label: "Product Stack",
+ items: [
+ {
+ type: "doc",
+ id: "product/product",
+ },
+ "product/pnp",
+ "product/sfa",
+ "product/mpc-core-kit",
+ "product/wallet-services",
+ ],
+ },
+ "product-fit",
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ { type: "autogenerated", dirName: "features" },
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ {
+ type: "link",
+ label: "Troubleshooting",
+ href: "/troubleshooting",
+ },
+ "change-of-ownership",
+ ],
+ resources: [
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: ``,
+ defaultStyle: true,
+ },
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ "resources",
+ {
+ type: "category",
+ label: "Authentication",
+ items: [
+ "authentication/authentication",
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ {
+ type: "category",
+ label: "Basic Logins",
+ collapsible: true,
+ collapsed: false,
+ items: [
+ "authentication/basic-logins/email-passwordless",
+ "authentication/basic-logins/sms-otp",
+ "authentication/basic-logins/external-wallets",
+ ],
+ collapsible: true,
+ collapsed: false,
+ },
+ {
+ type: "category",
+ label: "Social Logins",
+ collapsible: true,
+ collapsed: false,
+ items: [
+ "authentication/social-logins/google",
+ "authentication/social-logins/facebook",
+ "authentication/social-logins/twitch",
+ "authentication/social-logins/discord",
+ "authentication/social-logins/oauth",
+ ],
+ },
+ {
+ type: "category",
+ label: "Custom Connections",
+ collapsible: true,
+ collapsed: false,
+ items: [
+ "authentication/custom-connections/auth0",
+ "authentication/custom-connections/aws-cognito",
+ "authentication/custom-connections/firebase",
+ "authentication/custom-connections/custom-jwt",
+ ],
+ },
+ "authentication/group-connections",
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ "authentication/id-token",
+ ],
+ },
+ {
+ type: "category",
+ label: "Connect Blockchain",
+ items: [
+ "connect-blockchain/connect-blockchain",
+ {
+ type: "category",
+ label: "EVM Based Chains",
+ items: [
+ "connect-blockchain/evm/evm",
+ { type: "autogenerated", dirName: "connect-blockchain/evm" },
+ ],
+ },
+ {
+ type: "category",
+ label: "Solana",
+ items: [{ type: "autogenerated", dirName: "connect-blockchain/solana" }],
+ },
+ {
+ type: "category",
+ label: "Near",
+ items: [{ type: "autogenerated", dirName: "connect-blockchain/near" }],
+ },
+ {
+ type: "category",
+ label: "Other Chains",
+ items: [
+ "connect-blockchain/other/other",
+ "connect-blockchain/xrpl",
+ { type: "autogenerated", dirName: "connect-blockchain/other" },
+ ],
+ collapsible: true,
+ collapsed: false,
+ },
+ {
+ type: "html",
+ value: "",
+ defaultStyle: true,
+ },
+ "connect-blockchain/custom-chains",
+ "connect-blockchain/rpc-headers",
+ ],
+ },
+ {
+ type: "category",
+ label: "Dashboard",
+ items: [
+ "dashboard/dashboard",
+ "dashboard/create-new-project",
+ "dashboard/configure-connections",
+ ],
+ },
+ "examples",
+ "resources/checklist",
+ {
+ type: "category",
+ label: "Web3Auth Infrastructure",
+ items: [
+ "infrastructure/infrastructure",
+ "infrastructure/mpc-architecture",
+ "infrastructure/sss-architecture",
+ "infrastructure/nodes-and-dkg",
+ "infrastructure/glossary",
+ {
+ type: "link",
+ label: "Compliance, Audits and Trust",
+ href: "https://trust.web3auth.io",
+ },
+ ],
+ },
+ {
+ type: "category",
+ label: "Troubleshooting",
+ items: [
+ "troubleshooting/troubleshooting",
+ { type: "autogenerated", dirName: "troubleshooting" },
+ ],
+ },
+ ],
+ sdk_pnp_react: [
+ {
+ type: "html",
+ value: webTopNavButton(reactJS),
+ defaultStyle: true,
+ },
+ "sdk/web/react/react",
+ {
+ type: "category",
+ label: "Advanced Configuration",
+ items: [{ type: "autogenerated", dirName: "sdk/web/react/advanced" }],
+ },
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Web3Auth Hooks",
+ items: [{ type: "autogenerated", dirName: "sdk/web/react/hooks" }],
+ },
+ "sdk/web/react/ethereum-hooks",
+ {
+ type: "category",
+ label: "Solana Hooks",
+ items: [{ type: "autogenerated", dirName: "sdk/web/react/solana-hooks" }],
+ },
+ "sdk/web/react/examples",
+ {
+ type: "link",
+ label: "Playground",
+ href: "https://web3auth-playground.vercel.app/",
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-web/7",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-web/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ {
+ type: "category",
+ label: "Plug and Play Modal SDK",
+ items: [
+ "migration-guides/modal-v9-to-v10",
+ "migration-guides/modal-v8-to-v9",
+ "migration-guides/modal-v7-to-v8",
+ "migration-guides/modal-v6-to-v7",
+ "migration-guides/modal-v5-to-v6",
+ ],
+ },
+ {
+ type: "category",
+ label: "Plug and Play No Modal SDK",
+ items: [
+ "migration-guides/modal-v9-to-v10",
+ "migration-guides/no-modal-v8-to-v9",
+ "migration-guides/no-modal-v7-to-v8",
+ "migration-guides/no-modal-v6-to-v7",
+ "migration-guides/no-modal-v5-to-v6",
+ ],
+ },
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_pnp_vue: [
+ {
+ type: "html",
+ value: webTopNavButton(vue),
+ defaultStyle: true,
+ },
+ "sdk/web/vue/vue",
+ {
+ type: "category",
+ label: "Advanced Configuration",
+ items: [{ type: "autogenerated", dirName: "sdk/web/vue/advanced" }],
+ },
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Web3Auth Composables",
+ items: [{ type: "autogenerated", dirName: "sdk/web/vue/composables" }],
+ },
+ "sdk/web/vue/ethereum-composables",
+ {
+ type: "category",
+ label: "Solana Composables",
+ items: [{ type: "autogenerated", dirName: "sdk/web/vue/solana-composables" }],
+ },
+ "sdk/web/vue/examples",
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-web/7",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-web/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ {
+ type: "category",
+ label: "Plug and Play Modal SDK",
+ items: [
+ "migration-guides/modal-v8-to-v9",
+ "migration-guides/modal-v7-to-v8",
+ "migration-guides/modal-v6-to-v7",
+ "migration-guides/modal-v5-to-v6",
+ ],
+ },
+ {
+ type: "category",
+ label: "Plug and Play No Modal SDK",
+ items: [
+ "migration-guides/no-modal-v8-to-v9",
+ "migration-guides/no-modal-v7-to-v8",
+ "migration-guides/no-modal-v6-to-v7",
+ "migration-guides/no-modal-v5-to-v6",
+ ],
+ },
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_pnp_js: [
+ {
+ type: "html",
+ value: webTopNavButton(js),
+ defaultStyle: true,
+ },
+ "sdk/web/js/js",
+ {
+ type: "category",
+ label: "Advanced Settings",
+ items: [{ type: "autogenerated", dirName: "sdk/web/js/advanced" }],
+ },
+ "sdk/web/js/events",
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Functions",
+ items: [
+ "sdk/web/js/functions/functions",
+ "sdk/web/js/functions/connect",
+ "sdk/web/js/functions/enableMFA",
+ "sdk/web/js/functions/getIdentityToken",
+ "sdk/web/js/functions/getUserInfo",
+ "sdk/web/js/functions/logout",
+ "sdk/web/js/functions/manageMFA",
+ "sdk/web/js/functions/showCheckout",
+ "sdk/web/js/functions/showSwap",
+ "sdk/web/js/functions/showWalletConnectScanner",
+ "sdk/web/js/functions/showWalletUI",
+ "sdk/web/js/functions/switchChain",
+ ],
+ },
+ "sdk/web/js/ethereum-integration",
+ "sdk/web/js/examples",
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-web/7",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-web/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ {
+ type: "category",
+ label: "Plug and Play Modal SDK",
+ items: [
+ "migration-guides/modal-v8-to-v9",
+ "migration-guides/modal-v7-to-v8",
+ "migration-guides/modal-v6-to-v7",
+ "migration-guides/modal-v5-to-v6",
+ ],
+ },
+ {
+ type: "category",
+ label: "Plug and Play No Modal SDK",
+ items: [
+ "migration-guides/no-modal-v8-to-v9",
+ "migration-guides/no-modal-v7-to-v8",
+ "migration-guides/no-modal-v6-to-v7",
+ "migration-guides/no-modal-v5-to-v6",
+ ],
+ },
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_pnp_android: [
+ {
+ type: "html",
+ value: pnpMobileTopNavButton(android),
+ defaultStyle: true,
+ },
+ "sdk/mobile/pnp/android/android",
+ "sdk/mobile/pnp/android/install",
+ "sdk/mobile/pnp/android/initialize",
+ "sdk/mobile/pnp/android/usage",
+ "sdk/mobile/pnp/android/examples",
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Additional Settings",
+ items: [
+ "sdk/mobile/pnp/android/whitelabel",
+ "sdk/mobile/pnp/android/custom-authentication",
+ "sdk/mobile/pnp/android/mfa",
+ "sdk/mobile/pnp/android/dapp-share",
+ ],
+ },
+ {
+ type: "link",
+ label: "Playground",
+ href: "https://w3a.link/pnp-android-playground",
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-android/16",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-android-sdk/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ "migration-guides/android-v8-to-v9",
+ "migration-guides/android-v7.2-to-v7.3",
+ "migration-guides/android-v7.1.2-to-v7.2",
+ "migration-guides/android-v7.1.1-to-v7.1.2",
+ "migration-guides/android-v6-to-v6.1",
+ "migration-guides/android-v5-to-v6",
+ "migration-guides/android-v4-to-v5",
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_pnp_ios: [
+ {
+ type: "html",
+ value: pnpMobileTopNavButton(ios),
+ defaultStyle: true,
+ },
+ "sdk/mobile/pnp/ios/ios",
+ "sdk/mobile/pnp/ios/install",
+ "sdk/mobile/pnp/ios/initialize",
+ "sdk/mobile/pnp/ios/usage",
+ "sdk/mobile/pnp/ios/examples",
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Additional Settings",
+ items: [
+ "sdk/mobile/pnp/ios/whitelabel",
+ "sdk/mobile/pnp/ios/custom-authentication",
+ "sdk/mobile/pnp/ios/mfa",
+ "sdk/mobile/pnp/ios/dapp-share",
+ ],
+ },
+ {
+ type: "link",
+ label: "Playground",
+ href: "https://w3a.link/pnp-ios-playground",
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-ios/17",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-swift-sdk/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ "migration-guides/ios-v9-to-v10",
+ "migration-guides/ios-v8.2-to-v8.3",
+ "migration-guides/ios-v8.1-to-v8.2",
+ "migration-guides/ios-v8-to-v8.1",
+ "migration-guides/ios-v7-to-v8",
+ "migration-guides/ios-v6-to-v7",
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_pnp_react_native: [
+ {
+ type: "html",
+ value: pnpMobileTopNavButton(reactnative),
+ defaultStyle: true,
+ },
+ "sdk/mobile/pnp/react-native/react-native",
+ "sdk/mobile/pnp/react-native/install",
+ "sdk/mobile/pnp/react-native/initialize",
+ "sdk/mobile/pnp/react-native/usage",
+ "sdk/mobile/pnp/react-native/examples",
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Additional Settings",
+ items: [
+ "sdk/mobile/pnp/react-native/account-abstraction",
+ "sdk/mobile/pnp/react-native/whitelabel",
+ "sdk/mobile/pnp/react-native/custom-authentication",
+ "sdk/mobile/pnp/react-native/mfa",
+ "sdk/mobile/pnp/react-native/dapp-share",
+ ],
+ },
+ {
+ type: "category",
+ label: "Providers",
+ items: [
+ "sdk/mobile/pnp/react-native/providers/providers",
+ "sdk/mobile/pnp/react-native/providers/evm",
+ "sdk/mobile/pnp/react-native/providers/aa-provider",
+ "sdk/mobile/pnp/react-native/providers/solana",
+ "sdk/mobile/pnp/react-native/providers/xrpl",
+ "sdk/mobile/pnp/react-native/providers/common",
+ ],
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-rn/19",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-react-native-sdk/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ "migration-guides/rn-v7-to-v8",
+ "migration-guides/rn-v5-to-v6",
+ "migration-guides/rn-v4-to-v5",
+ "migration-guides/rn-v3-to-v4",
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_pnp_flutter: [
+ {
+ type: "html",
+ value: pnpMobileTopNavButton(flutter),
+ defaultStyle: true,
+ },
+ "sdk/mobile/pnp/flutter/flutter",
+ "sdk/mobile/pnp/flutter/install",
+ "sdk/mobile/pnp/flutter/initialize",
+ "sdk/mobile/pnp/flutter/usage",
+ "sdk/mobile/pnp/flutter/examples",
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Additional Settings",
+ items: [
+ "sdk/mobile/pnp/flutter/whitelabel",
+ "sdk/mobile/pnp/flutter/custom-authentication",
+ "sdk/mobile/pnp/flutter/mfa",
+ "sdk/mobile/pnp/flutter/dapp-share",
+ ],
+ },
+ {
+ type: "link",
+ label: "Playground Android",
+ href: "https://w3a.link/pnp-flutter-android-playground",
+ },
+ {
+ type: "link",
+ label: "Playground iOS",
+ href: "https://w3a.link/pnp-flutter-ios-playground",
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-flutter/18",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-flutter-sdk/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: ["migration-guides/flutter-v5-to-v6", "migration-guides/flutter-v3-to-v4"],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_pnp_unity: [
+ {
+ type: "html",
+ value: gamingTopNavButton(unity),
+ defaultStyle: true,
+ },
+ "sdk/gaming/unity/unity",
+ "sdk/gaming/unity/install",
+ "sdk/gaming/unity/initialize",
+ "sdk/gaming/unity/usage",
+ "sdk/gaming/unity/examples",
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Additional Settings",
+ items: [
+ "sdk/gaming/unity/whitelabel",
+ "sdk/gaming/unity/custom-authentication",
+ "sdk/gaming/unity/mfa",
+ "sdk/gaming/unity/dapp-share",
+ ],
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-unity/20",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-unity-sdk/releases",
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_pnp_unreal: [
+ {
+ type: "html",
+ value: gamingTopNavButton(unreal),
+ defaultStyle: true,
+ },
+ "sdk/gaming/unreal/unreal",
+ "sdk/gaming/unreal/install",
+ "sdk/gaming/unreal/initialize",
+ "sdk/gaming/unreal/usage",
+ "sdk/gaming/unreal/examples",
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Additional Settings",
+ items: [
+ "sdk/gaming/unreal/whitelabel",
+ "sdk/gaming/unreal/custom-authentication",
+ "sdk/gaming/unreal/mfa",
+ ],
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-unreal/21",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-unreal-sdk/releases",
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_core_kit_sfa_react_native: [
+ {
+ type: "html",
+ value: sfaMobileTopNavButton(reactnative),
+ defaultStyle: true,
+ },
+ "sdk/mobile/sfa/react-native/react-native",
+ "sdk/mobile/sfa/react-native/install",
+ "sdk/mobile/sfa/react-native/initialize",
+ "sdk/mobile/sfa/react-native/authentication",
+ "sdk/mobile/sfa/react-native/usage",
+ "sdk/mobile/sfa/react-native/examples",
+ {
+ type: "category",
+ collapsible: true,
+ collapsed: false,
+ label: "Additional Settings",
+ items: [
+ "sdk/mobile/sfa/react-native/account-abstraction",
+ "sdk/mobile/sfa/react-native/initiate-topup",
+ "sdk/mobile/sfa/react-native/show-wallet-connect",
+ ],
+ },
+ {
+ type: "category",
+ label: "Providers",
+ items: [
+ "sdk/mobile/sfa/react-native/providers/providers",
+ "sdk/mobile/sfa/react-native/providers/evm",
+ "sdk/mobile/sfa/react-native/providers/aa-provider",
+ "sdk/mobile/sfa/react-native/providers/solana",
+ "sdk/mobile/sfa/react-native/providers/xrpl",
+ "sdk/mobile/sfa/react-native/providers/common",
+ ],
+ },
+ {
+ type: "category",
+ label: "Wallet Services Plugin",
+ items: [
+ "sdk/mobile/sfa/react-native/wallet-services/wallet-services",
+ "sdk/mobile/sfa/react-native/wallet-services/usage",
+ "sdk/mobile/sfa/react-native/wallet-services/wallet-services-hooks",
+ ],
+ },
+ {
+ type: "link",
+ label: "Playground",
+ href: "https://demo-sfa.web3auth.io",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: ["migration-guides/sfa-rn-to-sfa-js", "migration-guides/sfa-node-to-sfa-js"],
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-core-kit/core-kit-sfa/22",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/web3auth/single-factor-auth-web/releases",
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_sfa_android: [
+ {
+ type: "html",
+ value: sfaMobileTopNavButton(android),
+ defaultStyle: true,
+ },
+ "sdk/mobile/sfa/android/android",
+ "sdk/mobile/sfa/android/install",
+ "sdk/mobile/sfa/android/initialize",
+ "sdk/mobile/sfa/android/authentication",
+ "sdk/mobile/sfa/android/usage",
+ "sdk/mobile/sfa/android/examples",
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-core-kit/core-kit-sfa-android/26",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/web3auth/single-factor-auth-android/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ "migration-guides/sfa-android-v2-to-v3",
+ "migration-guides/sfa-android-v1.2.0-to-v2.0.0",
+ "migration-guides/sfa-android-v0.4.0-to-v1",
+ "migration-guides/sfa-android-v0.1.0-to-v0.3.0",
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_sfa_ios: [
+ {
+ type: "html",
+ value: sfaMobileTopNavButton(ios),
+ defaultStyle: true,
+ },
+ "sdk/mobile/sfa/ios/ios",
+ "sdk/mobile/sfa/ios/install",
+ "sdk/mobile/sfa/ios/initialize",
+ "sdk/mobile/sfa/ios/authentication",
+ "sdk/mobile/sfa/ios/usage",
+ "sdk/mobile/sfa/ios/examples",
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-core-kit/sfa-swift-sdk/30",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/web3auth/single-factor-auth-swift/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ "migration-guides/sfa-ios-v8-to-v9",
+ "migration-guides/sfa-ios-v7-to-v8",
+ "migration-guides/sfa-ios-v2-to-v4",
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_sfa_flutter: [
+ {
+ type: "html",
+ value: sfaMobileTopNavButton(flutter),
+ defaultStyle: true,
+ },
+ "sdk/mobile/sfa/flutter/flutter",
+ "sdk/mobile/sfa/flutter/install",
+ "sdk/mobile/sfa/flutter/initialize",
+ "sdk/mobile/sfa/flutter/authentication",
+ "sdk/mobile/sfa/flutter/usage",
+ "sdk/mobile/sfa/flutter/examples",
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-core-kit/sfa-flutter-sdk/31",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/web3auth/single-factor-auth-flutter/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: [
+ "migration-guides/sfa-flutter-v5-to-v6",
+ "migration-guides/sfa-flutter-v4-to-v5",
+ "migration-guides/sfa-flutter-v2-to-v4",
+ "migration-guides/sfa-flutter-v1-to-v2",
+ ],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_mpc_core_kit_js: [
+ {
+ type: "html",
+ value: mpcckTopNavButton(js),
+ defaultStyle: true,
+ },
+ "sdk/mpc-core-kit/mpc-core-kit-js/mpc-core-kit-js",
+ "sdk/mpc-core-kit/mpc-core-kit-js/install",
+ "sdk/mpc-core-kit/mpc-core-kit-js/initialize",
+ {
+ type: "category",
+ label: "Authentication",
+ items: [
+ "sdk/mpc-core-kit/mpc-core-kit-js/authentication/authentication",
+ "sdk/mpc-core-kit/mpc-core-kit-js/authentication/login-jwt",
+ "sdk/mpc-core-kit/mpc-core-kit-js/authentication/login-oauth",
+ ],
+ },
+ "sdk/mpc-core-kit/mpc-core-kit-js/signing",
+ "sdk/mpc-core-kit/mpc-core-kit-js/usage",
+ "sdk/mpc-core-kit/mpc-core-kit-js/examples",
+ {
+ type: "category",
+ label: "Providers",
+ items: [
+ "sdk/mpc-core-kit/mpc-core-kit-js/providers/providers",
+ "sdk/mpc-core-kit/mpc-core-kit-js/providers/evm",
+ ],
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-core-kit/mpc-core-kit/33",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/mpc-core-kit/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: ["migration-guides/mpc-core-kit-web-v2-to-v3"],
+ },
+ ...sdkQuickLinks,
+ ],
+ sdk_mpc_core_kit_react_native: [
+ {
+ type: "html",
+ value: mpcckTopNavButton(reactnative),
+ defaultStyle: true,
+ },
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/mpc-core-kit-react-native",
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/install",
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/initialize",
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/authentication",
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/signing",
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/usage",
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/examples",
+ {
+ type: "category",
+ label: "Providers",
+ items: [
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/providers/providers",
+ "sdk/mpc-core-kit/mpc-core-kit-react-native/providers/evm",
+ ],
+ },
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-core-kit/mpc-core-kit/33",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/react-nativempc-core-kit/releases",
+ },
+ {
+ type: "category",
+ label: "Migration Guides",
+ items: ["migration-guides/mpc-core-kit-react-native-migration"],
+ },
+ ...sdkQuickLinks,
+ ],
+};
+
+export default sidebars;