initial checkin
334
.gitignore
vendored
Normal file
@@ -0,0 +1,334 @@
|
||||
/.idea/
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
### Solidity template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### Node template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### NextJS template
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
2
empty-module.js
Normal file
@@ -0,0 +1,2 @@
|
||||
// Empty module to replace problematic dependencies
|
||||
module.exports = {};
|
||||
42
next.config.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
output: 'export',
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
trailingSlash: true,
|
||||
webpack: (config) => {
|
||||
config.resolve.fallback = {
|
||||
...config.resolve.fallback,
|
||||
fs: false,
|
||||
net: false,
|
||||
tls: false,
|
||||
crypto: false,
|
||||
stream: false,
|
||||
http: false,
|
||||
https: false,
|
||||
zlib: false,
|
||||
path: false,
|
||||
os: false,
|
||||
'pino-pretty': false,
|
||||
'@react-native-async-storage/async-storage': false,
|
||||
'react-native': false,
|
||||
};
|
||||
|
||||
config.externals.push(
|
||||
'pino-pretty',
|
||||
'lokijs',
|
||||
'encoding'
|
||||
);
|
||||
|
||||
// Ignore specific warnings
|
||||
config.ignoreWarnings = [
|
||||
/Failed to parse source map/,
|
||||
/Critical dependency: the request of a dependency is an expression/,
|
||||
];
|
||||
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
8425
package-lock.json
generated
Normal file
40
package.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "liquidity-party-web",
|
||||
"version": "0.1.0",
|
||||
"description": "Web interface for interacting with the Liquidity Party DEX",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"@radix-ui/react-tabs": "^1.1.1",
|
||||
"@rainbow-me/rainbowkit": "2.2.8",
|
||||
"@tanstack/react-query": "5.90.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"i18next": "^23.15.0",
|
||||
"lucide-react": "^0.460.0",
|
||||
"next": "^15.1.3",
|
||||
"next-themes": "^0.4.4",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-i18next": "^15.1.0",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"viem": "2.38.0",
|
||||
"wagmi": "2.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.4.49",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
9
postcss.config.mjs
Normal file
@@ -0,0 +1,9 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
142
public/logo-dark.svg
Normal file
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
viewBox="0 0 540.71997 77.792397"
|
||||
id="svg421"
|
||||
sodipodi:docname="logo-dark.svg"
|
||||
width="540.71997"
|
||||
height="77.792397"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs425" />
|
||||
<sodipodi:namedview
|
||||
id="namedview423"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.3596491"
|
||||
inkscape:cx="281.82156"
|
||||
inkscape:cy="41.319703"
|
||||
inkscape:window-width="1864"
|
||||
inkscape:window-height="1131"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg421" />
|
||||
<!-- Liquidity -->
|
||||
<g
|
||||
id="SvgjsG7443"
|
||||
featurekey="J3GnXt-0"
|
||||
transform="matrix(3,0,0,3,-3,-1.6038)"
|
||||
fill="#dddddd">
|
||||
<path
|
||||
d="m 7.22,19.02 c 0.96,0.46 1.88,0.62 2.64,0.62 0.74,0 1.36,-0.16 1.76,-0.28 v 2.14 c -0.5,0.12 -1.12,0.22 -1.82,0.22 -0.94,0 -2,-0.16 -3.16,-0.66 C 5.02,20.36 3.44,20.2 2.38,20.2 1.54,20.2 1,20.3 1,20.3 V 6.28 H 3.16 V 18.2 c 1.3,0 2.88,0.26 4.06,0.82 z m 4.4,-1.6 H 9.46 V 6.28 h 2.16 z m 14.14,-0.06 c 2.54,1.84 4.68,3 7.9,3 1.08,0 2.16,-0.14 3.16,-0.42 v 2.04 c -1.02,0.22 -2.1,0.34 -3.16,0.34 -3.86,0 -6.22,-1.38 -9.3,-3.52 -1.1,0.82 -2.54,1.3 -4.22,1.3 -4.32,0 -6.92,-3.14 -6.92,-7 0,-3.86 2.6,-7 6.92,-7 4.3,0 6.9,3.14 6.9,7 0,1.6 -0.44,3.08 -1.28,4.26 z M 36.82,6.28 h 2.14 v 6.46 c 0,2.88 -1.6,4.86 -4.92,4.86 -3.3,0 -4.92,-1.98 -4.92,-4.86 V 6.28 h 2.16 v 5.74 c 0,1.44 -0.1,3.6 2.76,3.6 2.88,0 2.78,-2.16 2.78,-3.6 z m -12.8,9.9 c 0.52,-0.84 0.78,-1.9 0.78,-3.08 0,-2.86 -1.56,-5.02 -4.66,-5.02 -3.12,0 -4.68,2.16 -4.68,5.02 0,1.14 0.24,2.16 0.74,2.98 0.5,-0.36 1.8,-1.1 3.74,-1.1 1.54,0 2.84,0.48 4.08,1.2 z m -3.88,1.96 c 0.92,0 1.7,-0.2 2.34,-0.54 -0.76,-0.38 -1.6,-0.64 -2.54,-0.64 -1.08,0 -1.86,0.3 -2.32,0.56 0.68,0.4 1.52,0.62 2.52,0.62 z m 22.8,1.78 H 40.78 V 6.28 h 2.16 z m 2,-13.64 h 5.14 c 4.3,0 6.9,2.96 6.9,6.82 0,3.76 -2.44,6.66 -6.54,6.82 h -5.5 z m 5.14,11.68 c 3.12,0 4.66,-1.98 4.66,-4.86 0,-2.86 -1.54,-4.84 -4.66,-4.84 H 47.1 v 9.7 z m 10.68,1.96 H 58.6 V 6.28 h 2.16 z m 1.4,-13.64 h 10.96 v 1.98 h -4.4 V 19.92 H 66.56 V 8.26 h -4.4 z m 22.26,0 h 2.54 l -5.6,8.26 v 5.38 h -2.14 v -5.36 l -5.6,-8.28 h 2.54 l 4.14,6.1 z"
|
||||
id="path374" />
|
||||
</g>
|
||||
<!-- Flower -->
|
||||
<g
|
||||
transform="matrix(0.9,0,0,0.9,267,-1.6038)"
|
||||
fill="#000000"
|
||||
id="g413">
|
||||
<g
|
||||
id="g411">
|
||||
<!-- <circle fill="#000000" cx="45" cy="44.999" r="5.277"></circle>-->
|
||||
<g
|
||||
id="g409">
|
||||
<g
|
||||
id="g379">
|
||||
<path
|
||||
fill="#0d47a1"
|
||||
class="blue1"
|
||||
d="m 45.214,33.672 c 24.117,-31.271 0.369,-31.89 0.369,-31.89 0,0 -23.756,0.069 -0.369,31.89 z"
|
||||
id="path377" />
|
||||
</g>
|
||||
<g
|
||||
id="g383">
|
||||
<path
|
||||
fill="#1976d2"
|
||||
class="blue2"
|
||||
d="M 37.141,36.837 C 32.082,-2.327 14.853,14.027 14.853,14.027 c 0,0 -16.749,16.847 22.288,22.81 z"
|
||||
id="path381" />
|
||||
</g>
|
||||
<g
|
||||
id="g387">
|
||||
<path
|
||||
fill="#2196f3"
|
||||
class="blue3"
|
||||
d="M 33.67,44.786 C 2.401,20.667 1.782,44.416 1.782,44.416 c 0,0 0.069,23.757 31.888,0.37 z"
|
||||
id="path385" />
|
||||
</g>
|
||||
<g
|
||||
id="g391">
|
||||
<path
|
||||
fill="#00bcd4"
|
||||
class="blue4"
|
||||
d="m 36.837,52.859 c -39.166,5.059 -22.81,22.288 -22.81,22.288 0,0 16.847,16.752 22.81,-22.288 z"
|
||||
id="path389" />
|
||||
</g>
|
||||
<g
|
||||
id="g395">
|
||||
<path
|
||||
fill="#4fc3f7"
|
||||
class="blue5"
|
||||
d="m 44.785,56.33 c -24.118,31.271 -0.369,31.888 -0.369,31.888 0,0 23.755,-0.069 0.369,-31.888 z"
|
||||
id="path393" />
|
||||
</g>
|
||||
<g
|
||||
id="g399">
|
||||
<path
|
||||
fill="#3f51b5"
|
||||
class="blue6"
|
||||
d="m 52.859,53.164 c 5.057,39.164 22.287,22.81 22.287,22.81 0,0 16.75,-16.847 -22.287,-22.81 z"
|
||||
id="path397" />
|
||||
</g>
|
||||
<g
|
||||
id="g403">
|
||||
<path
|
||||
fill="#039be5"
|
||||
class="blue7"
|
||||
d="m 56.33,45.216 c 31.271,24.117 31.888,0.369 31.888,0.369 0,0 -0.07,-23.756 -31.888,-0.369 z"
|
||||
id="path401" />
|
||||
</g>
|
||||
<g
|
||||
id="g407">
|
||||
<path
|
||||
fill="#64b5f6"
|
||||
class="blue8"
|
||||
d="m 53.162,37.142 c 39.166,-5.061 22.811,-22.289 22.811,-22.289 0,0 -16.847,-16.749 -22.811,22.289 z"
|
||||
id="path405" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<!-- Party - P -->
|
||||
<g
|
||||
id="SvgjsG7444-P"
|
||||
featurekey="J3GnXt-1"
|
||||
transform="matrix(3,0,0,3,359,-1.6038)"
|
||||
fill="#dddddd">
|
||||
<path
|
||||
d="m 6.12,6.28 c 2.32,0 5.14,0.56 5.14,4.16 0,2.78 -1.88,4.1 -4.98,4.1 -1.32,0 -3.12,0.6 -3.12,2.5 v 2.88 H 1 V 6.28 Z m -0.1,6.28 C 8.54,12.56 9,11.7 9,10.44 9,9.04 8.38,8.26 6,8.26 H 3.16 v 5.2 c 0.62,-0.52 1.5,-0.9 2.86,-0.9 z"
|
||||
id="path415" />
|
||||
</g>
|
||||
<!-- Party - ARTY -->
|
||||
<g
|
||||
id="SvgjsG7444-ARTY"
|
||||
featurekey="J3GnXt-1"
|
||||
transform="matrix(3,0,0,3,354,-1.6038)"
|
||||
fill="#dddddd">
|
||||
<path
|
||||
d="m 19.64,6.28 5.64,13.64 H 23.02 L 21.46,16.1 h -1.38 c -1.3,0 -2.7,0.24 -3.6,0.86 -0.8,0.54 -1.68,1.4 -2.2,2.58 l -0.16,0.38 H 11.86 L 17.5,6.28 Z m 0.42,7.9 h 0.62 L 18.56,8.98 16,15.3 c 1.04,-0.66 2,-1.12 4.06,-1.12 z m 14.66,1.52 c 1.54,2.26 2.12,2.26 2.52,2.26 v 1.96 h -0.32 c -1.42,0 -2.4,-0.98 -3.28,-2.32 -0.88,-1.32 -1.88,-3.06 -4.1,-3.06 h -0.98 v 5.38 H 26.4 V 6.28 h 4.92 c 2.92,0.02 5.14,0.74 5.14,4 0,2.38 -1.36,3.36 -3.2,3.72 0.56,0.42 1,1 1.46,1.7 z m -4.26,-3.14 c 1.98,0.02 3.76,0.06 3.76,-2.16 0,-1.9 -1.24,-2.14 -2.8,-2.14 h -2.86 v 4.3 z M 37.44,6.28 H 48.4 V 8.26 H 44 V 19.92 H 41.84 V 8.26 h -4.4 z m 22.26,0 h 2.54 l -5.6,8.26 v 5.38 H 54.5 V 14.56 L 48.9,6.28 h 2.54 l 4.14,6.1 z"
|
||||
id="path418" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
117
public/logo-flower.svg
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
viewBox="0 0 86.435997 86.435997"
|
||||
id="svg585"
|
||||
sodipodi:docname="logo-flower.svg"
|
||||
width="86.435997"
|
||||
height="86.435997"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs589" />
|
||||
<sodipodi:namedview
|
||||
id="namedview587"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.36"
|
||||
inkscape:cx="218.22034"
|
||||
inkscape:cy="48.516949"
|
||||
inkscape:window-width="1864"
|
||||
inkscape:window-height="1131"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg585" />
|
||||
<!-- Flower -->
|
||||
<g
|
||||
fill="#000000"
|
||||
id="g583"
|
||||
transform="translate(-1.782,-1.782)">
|
||||
<g
|
||||
id="g581">
|
||||
<circle
|
||||
fill="#000000"
|
||||
cx="45"
|
||||
cy="44.999001"
|
||||
r="5.277"
|
||||
id="circle545" />
|
||||
<g
|
||||
id="g579">
|
||||
<g
|
||||
id="g549">
|
||||
<path
|
||||
fill="#0d47a1"
|
||||
class="blue1"
|
||||
d="m 45.214,33.672 c 24.117,-31.271 0.369,-31.89 0.369,-31.89 0,0 -23.756,0.069 -0.369,31.89 z"
|
||||
id="path547" />
|
||||
</g>
|
||||
<g
|
||||
id="g553">
|
||||
<path
|
||||
fill="#1976d2"
|
||||
class="blue2"
|
||||
d="M 37.141,36.837 C 32.082,-2.327 14.853,14.027 14.853,14.027 c 0,0 -16.749,16.847 22.288,22.81 z"
|
||||
id="path551" />
|
||||
</g>
|
||||
<g
|
||||
id="g557">
|
||||
<path
|
||||
fill="#2196f3"
|
||||
class="blue3"
|
||||
d="M 33.67,44.786 C 2.401,20.667 1.782,44.416 1.782,44.416 c 0,0 0.069,23.757 31.888,0.37 z"
|
||||
id="path555" />
|
||||
</g>
|
||||
<g
|
||||
id="g561">
|
||||
<path
|
||||
fill="#00bcd4"
|
||||
class="blue4"
|
||||
d="m 36.837,52.859 c -39.166,5.059 -22.81,22.288 -22.81,22.288 0,0 16.847,16.752 22.81,-22.288 z"
|
||||
id="path559" />
|
||||
</g>
|
||||
<g
|
||||
id="g565">
|
||||
<path
|
||||
fill="#4fc3f7"
|
||||
class="blue5"
|
||||
d="m 44.785,56.33 c -24.118,31.271 -0.369,31.888 -0.369,31.888 0,0 23.755,-0.069 0.369,-31.888 z"
|
||||
id="path563" />
|
||||
</g>
|
||||
<g
|
||||
id="g569">
|
||||
<path
|
||||
fill="#3f51b5"
|
||||
class="blue6"
|
||||
d="m 52.859,53.164 c 5.057,39.164 22.287,22.81 22.287,22.81 0,0 16.75,-16.847 -22.287,-22.81 z"
|
||||
id="path567" />
|
||||
</g>
|
||||
<g
|
||||
id="g573">
|
||||
<path
|
||||
fill="#039be5"
|
||||
class="blue7"
|
||||
d="m 56.33,45.216 c 31.271,24.117 31.888,0.369 31.888,0.369 0,0 -0.07,-23.756 -31.888,-0.369 z"
|
||||
id="path571" />
|
||||
</g>
|
||||
<g
|
||||
id="g577">
|
||||
<path
|
||||
fill="#64b5f6"
|
||||
class="blue8"
|
||||
d="m 53.162,37.142 c 39.166,-5.061 22.811,-22.289 22.811,-22.289 0,0 -16.847,-16.749 -22.811,22.289 z"
|
||||
id="path575" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
141
public/logo-light.svg
Normal file
@@ -0,0 +1,141 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
viewBox="0 0 540.71997 77.792397"
|
||||
id="svg141"
|
||||
sodipodi:docname="logo-light.svg"
|
||||
width="540.71997"
|
||||
height="77.792397"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs145" />
|
||||
<sodipodi:namedview
|
||||
id="namedview143"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.6631579"
|
||||
inkscape:cx="281.99605"
|
||||
inkscape:cy="41.116601"
|
||||
inkscape:window-width="1864"
|
||||
inkscape:window-height="1131"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg141" />
|
||||
<!-- Liquidity -->
|
||||
<g
|
||||
id="SvgjsG7443"
|
||||
featurekey="J3GnXt-0"
|
||||
transform="matrix(3,0,0,3,-3,-1.6038)"
|
||||
fill="#000000">
|
||||
<path
|
||||
d="m 7.22,19.02 c 0.96,0.46 1.88,0.62 2.64,0.62 0.74,0 1.36,-0.16 1.76,-0.28 v 2.14 c -0.5,0.12 -1.12,0.22 -1.82,0.22 -0.94,0 -2,-0.16 -3.16,-0.66 C 5.02,20.36 3.44,20.2 2.38,20.2 1.54,20.2 1,20.3 1,20.3 V 6.28 H 3.16 V 18.2 c 1.3,0 2.88,0.26 4.06,0.82 z m 4.4,-1.6 H 9.46 V 6.28 h 2.16 z m 14.14,-0.06 c 2.54,1.84 4.68,3 7.9,3 1.08,0 2.16,-0.14 3.16,-0.42 v 2.04 c -1.02,0.22 -2.1,0.34 -3.16,0.34 -3.86,0 -6.22,-1.38 -9.3,-3.52 -1.1,0.82 -2.54,1.3 -4.22,1.3 -4.32,0 -6.92,-3.14 -6.92,-7 0,-3.86 2.6,-7 6.92,-7 4.3,0 6.9,3.14 6.9,7 0,1.6 -0.44,3.08 -1.28,4.26 z M 36.82,6.28 h 2.14 v 6.46 c 0,2.88 -1.6,4.86 -4.92,4.86 -3.3,0 -4.92,-1.98 -4.92,-4.86 V 6.28 h 2.16 v 5.74 c 0,1.44 -0.1,3.6 2.76,3.6 2.88,0 2.78,-2.16 2.78,-3.6 z m -12.8,9.9 c 0.52,-0.84 0.78,-1.9 0.78,-3.08 0,-2.86 -1.56,-5.02 -4.66,-5.02 -3.12,0 -4.68,2.16 -4.68,5.02 0,1.14 0.24,2.16 0.74,2.98 0.5,-0.36 1.8,-1.1 3.74,-1.1 1.54,0 2.84,0.48 4.08,1.2 z m -3.88,1.96 c 0.92,0 1.7,-0.2 2.34,-0.54 -0.76,-0.38 -1.6,-0.64 -2.54,-0.64 -1.08,0 -1.86,0.3 -2.32,0.56 0.68,0.4 1.52,0.62 2.52,0.62 z m 22.8,1.78 H 40.78 V 6.28 h 2.16 z m 2,-13.64 h 5.14 c 4.3,0 6.9,2.96 6.9,6.82 0,3.76 -2.44,6.66 -6.54,6.82 h -5.5 z m 5.14,11.68 c 3.12,0 4.66,-1.98 4.66,-4.86 0,-2.86 -1.54,-4.84 -4.66,-4.84 H 47.1 v 9.7 z m 10.68,1.96 H 58.6 V 6.28 h 2.16 z m 1.4,-13.64 h 10.96 v 1.98 h -4.4 V 19.92 H 66.56 V 8.26 h -4.4 z m 22.26,0 h 2.54 l -5.6,8.26 v 5.38 h -2.14 v -5.36 l -5.6,-8.28 h 2.54 l 4.14,6.1 z"
|
||||
id="path94" />
|
||||
</g>
|
||||
<!-- Flower -->
|
||||
<g
|
||||
transform="matrix(0.9,0,0,0.9,267,-1.6038)"
|
||||
fill="#000000"
|
||||
id="g133">
|
||||
<g
|
||||
id="g131">
|
||||
<g
|
||||
id="g129">
|
||||
<g
|
||||
id="g99">
|
||||
<path
|
||||
fill="#0d47a1"
|
||||
class="blue1"
|
||||
d="m 45.214,33.672 c 24.117,-31.271 0.369,-31.89 0.369,-31.89 0,0 -23.756,0.069 -0.369,31.89 z"
|
||||
id="path97" />
|
||||
</g>
|
||||
<g
|
||||
id="g103">
|
||||
<path
|
||||
fill="#1976d2"
|
||||
class="blue2"
|
||||
d="M 37.141,36.837 C 32.082,-2.327 14.853,14.027 14.853,14.027 c 0,0 -16.749,16.847 22.288,22.81 z"
|
||||
id="path101" />
|
||||
</g>
|
||||
<g
|
||||
id="g107">
|
||||
<path
|
||||
fill="#2196f3"
|
||||
class="blue3"
|
||||
d="M 33.67,44.786 C 2.401,20.667 1.782,44.416 1.782,44.416 c 0,0 0.069,23.757 31.888,0.37 z"
|
||||
id="path105" />
|
||||
</g>
|
||||
<g
|
||||
id="g111">
|
||||
<path
|
||||
fill="#00bcd4"
|
||||
class="blue4"
|
||||
d="m 36.837,52.859 c -39.166,5.059 -22.81,22.288 -22.81,22.288 0,0 16.847,16.752 22.81,-22.288 z"
|
||||
id="path109" />
|
||||
</g>
|
||||
<g
|
||||
id="g115">
|
||||
<path
|
||||
fill="#4fc3f7"
|
||||
class="blue5"
|
||||
d="m 44.785,56.33 c -24.118,31.271 -0.369,31.888 -0.369,31.888 0,0 23.755,-0.069 0.369,-31.888 z"
|
||||
id="path113" />
|
||||
</g>
|
||||
<g
|
||||
id="g119">
|
||||
<path
|
||||
fill="#3f51b5"
|
||||
class="blue6"
|
||||
d="m 52.859,53.164 c 5.057,39.164 22.287,22.81 22.287,22.81 0,0 16.75,-16.847 -22.287,-22.81 z"
|
||||
id="path117" />
|
||||
</g>
|
||||
<g
|
||||
id="g123">
|
||||
<path
|
||||
fill="#039be5"
|
||||
class="blue7"
|
||||
d="m 56.33,45.216 c 31.271,24.117 31.888,0.369 31.888,0.369 0,0 -0.07,-23.756 -31.888,-0.369 z"
|
||||
id="path121" />
|
||||
</g>
|
||||
<g
|
||||
id="g127">
|
||||
<path
|
||||
fill="#64b5f6"
|
||||
class="blue8"
|
||||
d="m 53.162,37.142 c 39.166,-5.061 22.811,-22.289 22.811,-22.289 0,0 -16.847,-16.749 -22.811,22.289 z"
|
||||
id="path125" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<!-- Party - P -->
|
||||
<g
|
||||
id="SvgjsG7444-P"
|
||||
featurekey="J3GnXt-1"
|
||||
transform="matrix(3,0,0,3,359,-1.6038)"
|
||||
fill="#000000">
|
||||
<path
|
||||
d="m 6.12,6.28 c 2.32,0 5.14,0.56 5.14,4.16 0,2.78 -1.88,4.1 -4.98,4.1 -1.32,0 -3.12,0.6 -3.12,2.5 v 2.88 H 1 V 6.28 Z m -0.1,6.28 C 8.54,12.56 9,11.7 9,10.44 9,9.04 8.38,8.26 6,8.26 H 3.16 v 5.2 c 0.62,-0.52 1.5,-0.9 2.86,-0.9 z"
|
||||
id="path135" />
|
||||
</g>
|
||||
<!-- Party - ARTY -->
|
||||
<g
|
||||
id="SvgjsG7444-ARTY"
|
||||
featurekey="J3GnXt-1"
|
||||
transform="matrix(3,0,0,3,354,-1.6038)"
|
||||
fill="#000000">
|
||||
<path
|
||||
d="m 19.64,6.28 5.64,13.64 H 23.02 L 21.46,16.1 h -1.38 c -1.3,0 -2.7,0.24 -3.6,0.86 -0.8,0.54 -1.68,1.4 -2.2,2.58 l -0.16,0.38 H 11.86 L 17.5,6.28 Z m 0.42,7.9 h 0.62 L 18.56,8.98 16,15.3 c 1.04,-0.66 2,-1.12 4.06,-1.12 z m 14.66,1.52 c 1.54,2.26 2.12,2.26 2.52,2.26 v 1.96 h -0.32 c -1.42,0 -2.4,-0.98 -3.28,-2.32 -0.88,-1.32 -1.88,-3.06 -4.1,-3.06 h -0.98 v 5.38 H 26.4 V 6.28 h 4.92 c 2.92,0.02 5.14,0.74 5.14,4 0,2.38 -1.36,3.36 -3.2,3.72 0.56,0.42 1,1 1.46,1.7 z m -4.26,-3.14 c 1.98,0.02 3.76,0.06 3.76,-2.16 0,-1.9 -1.24,-2.14 -2.8,-2.14 h -2.86 v 4.3 z M 37.44,6.28 H 48.4 V 8.26 H 44 V 19.92 H 41.84 V 8.26 h -4.4 z m 22.26,0 h 2.54 l -5.6,8.26 v 5.38 H 54.5 V 14.56 L 48.9,6.28 h 2.54 l 4.14,6.1 z"
|
||||
id="path138" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
138
public/logo-stacked-dark.svg
Normal file
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="2579.8655"
|
||||
height="2999.6877"
|
||||
viewBox="0 0 2579.8655 2999.6877"
|
||||
id="svg927"
|
||||
sodipodi:docname="logo-stacked-dark.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs931" />
|
||||
<sodipodi:namedview
|
||||
id="namedview929"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.074982027"
|
||||
inkscape:cx="1280.3068"
|
||||
inkscape:cy="1500.3595"
|
||||
inkscape:window-width="1864"
|
||||
inkscape:window-height="1131"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg927" />
|
||||
<g
|
||||
transform="matrix(7.3710444,0,0,7.3710444,1.0362297e-5,-4.583192e-5)"
|
||||
id="g925">
|
||||
<defs
|
||||
id="SvgjsDefs7691" />
|
||||
<!-- Colorful Flower -->
|
||||
<g
|
||||
id="SvgjsG7692"
|
||||
featureKey="HKaMnE-0"
|
||||
transform="matrix(2.6994924,0,0,2.6994924,54.189511,-4.8104891)"
|
||||
fill="#000000">
|
||||
<g
|
||||
id="g916">
|
||||
<g
|
||||
id="g914">
|
||||
<g
|
||||
id="g884">
|
||||
<path
|
||||
fill="#0d47a1"
|
||||
class="blue1"
|
||||
d="m 45.214,33.672 c 24.117,-31.271 0.369,-31.89 0.369,-31.89 0,0 -23.756,0.069 -0.369,31.89 z"
|
||||
id="path882" />
|
||||
</g>
|
||||
<g
|
||||
id="g888">
|
||||
<path
|
||||
fill="#1976d2"
|
||||
class="blue2"
|
||||
d="M 37.141,36.837 C 32.082,-2.327 14.853,14.027 14.853,14.027 c 0,0 -16.749,16.847 22.288,22.81 z"
|
||||
id="path886" />
|
||||
</g>
|
||||
<g
|
||||
id="g892">
|
||||
<path
|
||||
fill="#2196f3"
|
||||
class="blue3"
|
||||
d="M 33.67,44.786 C 2.401,20.667 1.782,44.416 1.782,44.416 c 0,0 0.069,23.757 31.888,0.37 z"
|
||||
id="path890" />
|
||||
</g>
|
||||
<g
|
||||
id="g896">
|
||||
<path
|
||||
fill="#00bcd4"
|
||||
class="blue4"
|
||||
d="m 36.837,52.859 c -39.166,5.059 -22.81,22.288 -22.81,22.288 0,0 16.847,16.752 22.81,-22.288 z"
|
||||
id="path894" />
|
||||
</g>
|
||||
<g
|
||||
id="g900">
|
||||
<path
|
||||
fill="#4fc3f7"
|
||||
class="blue5"
|
||||
d="m 44.785,56.33 c -24.118,31.271 -0.369,31.888 -0.369,31.888 0,0 23.755,-0.069 0.369,-31.888 z"
|
||||
id="path898" />
|
||||
</g>
|
||||
<g
|
||||
id="g904">
|
||||
<path
|
||||
fill="#3f51b5"
|
||||
class="blue6"
|
||||
d="m 52.859,53.164 c 5.057,39.164 22.287,22.81 22.287,22.81 0,0 16.75,-16.847 -22.287,-22.81 z"
|
||||
id="path902" />
|
||||
</g>
|
||||
<g
|
||||
id="g908">
|
||||
<path
|
||||
fill="#039be5"
|
||||
class="blue7"
|
||||
d="m 56.33,45.216 c 31.271,24.117 31.888,0.369 31.888,0.369 0,0 -0.07,-23.756 -31.888,-0.369 z"
|
||||
id="path906" />
|
||||
</g>
|
||||
<g
|
||||
id="g912">
|
||||
<path
|
||||
fill="#64b5f6"
|
||||
class="blue8"
|
||||
d="m 53.162,37.142 c 39.166,-5.061 22.811,-22.289 22.811,-22.289 0,0 -16.847,-16.749 -22.811,22.289 z"
|
||||
id="path910" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<!-- LIQUIDITY text -->
|
||||
<g
|
||||
id="SvgjsG7693"
|
||||
featureKey="J3GnXt-0"
|
||||
transform="matrix(4.0716613,0,0,4.0716613,-4.0716618,228.16287)"
|
||||
fill="#dddddd">
|
||||
<path
|
||||
d="m 7.22,19.02 c 0.96,0.46 1.88,0.62 2.64,0.62 0.74,0 1.36,-0.16 1.76,-0.28 v 2.14 c -0.5,0.12 -1.12,0.22 -1.82,0.22 -0.94,0 -2,-0.16 -3.16,-0.66 C 5.02,20.36 3.44,20.2 2.38,20.2 1.54,20.2 1,20.3 1,20.3 V 6.28 H 3.16 V 18.2 c 1.3,0 2.88,0.26 4.06,0.82 z m 4.4,-1.6 H 9.46 V 6.28 h 2.16 z m 14.14,-0.06 c 2.54,1.84 4.68,3 7.9,3 1.08,0 2.16,-0.14 3.16,-0.42 v 2.04 c -1.02,0.22 -2.1,0.34 -3.16,0.34 -3.86,0 -6.22,-1.38 -9.3,-3.52 -1.1,0.82 -2.54,1.3 -4.22,1.3 -4.32,0 -6.92,-3.14 -6.92,-7 0,-3.86 2.6,-7 6.92,-7 4.3,0 6.9,3.14 6.9,7 0,1.6 -0.44,3.08 -1.28,4.26 z M 36.82,6.28 h 2.14 v 6.46 c 0,2.88 -1.6,4.86 -4.92,4.86 -3.3,0 -4.92,-1.98 -4.92,-4.86 V 6.28 h 2.16 v 5.74 c 0,1.44 -0.1,3.6 2.76,3.6 2.88,0 2.78,-2.16 2.78,-3.6 z m -12.8,9.9 c 0.52,-0.84 0.78,-1.9 0.78,-3.08 0,-2.86 -1.56,-5.02 -4.66,-5.02 -3.12,0 -4.68,2.16 -4.68,5.02 0,1.14 0.24,2.16 0.74,2.98 0.5,-0.36 1.8,-1.1 3.74,-1.1 1.54,0 2.84,0.48 4.08,1.2 z m -3.88,1.96 c 0.92,0 1.7,-0.2 2.34,-0.54 -0.76,-0.38 -1.6,-0.64 -2.54,-0.64 -1.08,0 -1.86,0.3 -2.32,0.56 0.68,0.4 1.52,0.62 2.52,0.62 z m 22.8,1.78 H 40.78 V 6.28 h 2.16 z m 2,-13.64 h 5.14 c 4.3,0 6.9,2.96 6.9,6.82 0,3.76 -2.44,6.66 -6.54,6.82 h -5.5 z m 5.14,11.68 c 3.12,0 4.66,-1.98 4.66,-4.86 0,-2.86 -1.54,-4.84 -4.66,-4.84 H 47.1 v 9.7 z m 10.68,1.96 H 58.6 V 6.28 h 2.16 z m 1.4,-13.64 h 10.96 v 1.98 h -4.4 V 19.92 H 66.56 V 8.26 h -4.4 z m 22.26,0 h 2.54 l -5.6,8.26 v 5.38 h -2.14 v -5.36 l -5.6,-8.28 h 2.54 l 4.14,6.1 z"
|
||||
id="path919" />
|
||||
</g>
|
||||
<!-- PARTY text -->
|
||||
<g
|
||||
id="SvgjsG7694"
|
||||
featureKey="J3GnXt-1"
|
||||
transform="matrix(5.7152187,0,0,5.7152187,-5.71522,293.10844)"
|
||||
fill="#dddddd">
|
||||
<path
|
||||
d="m 6.12,6.28 c 2.32,0 5.14,0.56 5.14,4.16 0,2.78 -1.88,4.1 -4.98,4.1 -1.32,0 -3.12,0.6 -3.12,2.5 v 2.88 H 1 V 6.28 Z m -0.1,6.28 C 8.54,12.56 9,11.7 9,10.44 9,9.04 8.38,8.26 6,8.26 H 3.16 v 5.2 c 0.62,-0.52 1.5,-0.9 2.86,-0.9 z M 19.64,6.28 25.28,19.92 H 23.02 L 21.46,16.1 h -1.38 c -1.3,0 -2.7,0.24 -3.6,0.86 -0.8,0.54 -1.68,1.4 -2.2,2.58 l -0.16,0.38 H 11.86 L 17.5,6.28 Z m 0.42,7.9 h 0.62 L 18.56,8.98 16,15.3 c 1.04,-0.66 2,-1.12 4.06,-1.12 z m 14.66,1.52 c 1.54,2.26 2.12,2.26 2.52,2.26 v 1.96 h -0.32 c -1.42,0 -2.4,-0.98 -3.28,-2.32 -0.88,-1.32 -1.88,-3.06 -4.1,-3.06 h -0.98 v 5.38 H 26.4 V 6.28 h 4.92 c 2.92,0.02 5.14,0.74 5.14,4 0,2.38 -1.36,3.36 -3.2,3.72 0.56,0.42 1,1 1.46,1.7 z m -4.26,-3.14 c 1.98,0.02 3.76,0.06 3.76,-2.16 0,-1.9 -1.24,-2.14 -2.8,-2.14 h -2.86 v 4.3 z M 37.44,6.28 H 48.4 V 8.26 H 44 V 19.92 H 41.84 V 8.26 h -4.4 z m 22.26,0 h 2.54 l -5.6,8.26 v 5.38 H 54.5 V 14.56 L 48.9,6.28 h 2.54 l 4.14,6.1 z"
|
||||
id="path922" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.4 KiB |
138
public/logo-stacked-light.svg
Normal file
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="2579.8655"
|
||||
height="2999.6877"
|
||||
viewBox="0 0 2579.8655 2999.6877"
|
||||
id="svg751"
|
||||
sodipodi:docname="logo-stacked-light.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs755" />
|
||||
<sodipodi:namedview
|
||||
id="namedview753"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.074982027"
|
||||
inkscape:cx="1280.3068"
|
||||
inkscape:cy="1500.3595"
|
||||
inkscape:window-width="1864"
|
||||
inkscape:window-height="1131"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg751" />
|
||||
<g
|
||||
transform="matrix(7.3710444,0,0,7.3710444,1.0362297e-5,-4.583192e-5)"
|
||||
id="g749">
|
||||
<defs
|
||||
id="SvgjsDefs7691" />
|
||||
<!-- Colorful Flower -->
|
||||
<g
|
||||
id="SvgjsG7692"
|
||||
featureKey="HKaMnE-0"
|
||||
transform="matrix(2.6994924,0,0,2.6994924,54.189511,-4.8104891)"
|
||||
fill="#000000">
|
||||
<g
|
||||
id="g740">
|
||||
<g
|
||||
id="g738">
|
||||
<g
|
||||
id="g708">
|
||||
<path
|
||||
fill="#0d47a1"
|
||||
class="blue1"
|
||||
d="m 45.214,33.672 c 24.117,-31.271 0.369,-31.89 0.369,-31.89 0,0 -23.756,0.069 -0.369,31.89 z"
|
||||
id="path706" />
|
||||
</g>
|
||||
<g
|
||||
id="g712">
|
||||
<path
|
||||
fill="#1976d2"
|
||||
class="blue2"
|
||||
d="M 37.141,36.837 C 32.082,-2.327 14.853,14.027 14.853,14.027 c 0,0 -16.749,16.847 22.288,22.81 z"
|
||||
id="path710" />
|
||||
</g>
|
||||
<g
|
||||
id="g716">
|
||||
<path
|
||||
fill="#2196f3"
|
||||
class="blue3"
|
||||
d="M 33.67,44.786 C 2.401,20.667 1.782,44.416 1.782,44.416 c 0,0 0.069,23.757 31.888,0.37 z"
|
||||
id="path714" />
|
||||
</g>
|
||||
<g
|
||||
id="g720">
|
||||
<path
|
||||
fill="#00bcd4"
|
||||
class="blue4"
|
||||
d="m 36.837,52.859 c -39.166,5.059 -22.81,22.288 -22.81,22.288 0,0 16.847,16.752 22.81,-22.288 z"
|
||||
id="path718" />
|
||||
</g>
|
||||
<g
|
||||
id="g724">
|
||||
<path
|
||||
fill="#4fc3f7"
|
||||
class="blue5"
|
||||
d="m 44.785,56.33 c -24.118,31.271 -0.369,31.888 -0.369,31.888 0,0 23.755,-0.069 0.369,-31.888 z"
|
||||
id="path722" />
|
||||
</g>
|
||||
<g
|
||||
id="g728">
|
||||
<path
|
||||
fill="#3f51b5"
|
||||
class="blue6"
|
||||
d="m 52.859,53.164 c 5.057,39.164 22.287,22.81 22.287,22.81 0,0 16.75,-16.847 -22.287,-22.81 z"
|
||||
id="path726" />
|
||||
</g>
|
||||
<g
|
||||
id="g732">
|
||||
<path
|
||||
fill="#039be5"
|
||||
class="blue7"
|
||||
d="m 56.33,45.216 c 31.271,24.117 31.888,0.369 31.888,0.369 0,0 -0.07,-23.756 -31.888,-0.369 z"
|
||||
id="path730" />
|
||||
</g>
|
||||
<g
|
||||
id="g736">
|
||||
<path
|
||||
fill="#64b5f6"
|
||||
class="blue8"
|
||||
d="m 53.162,37.142 c 39.166,-5.061 22.811,-22.289 22.811,-22.289 0,0 -16.847,-16.749 -22.811,22.289 z"
|
||||
id="path734" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<!-- LIQUIDITY text -->
|
||||
<g
|
||||
id="SvgjsG7693"
|
||||
featureKey="J3GnXt-0"
|
||||
transform="matrix(4.0716613,0,0,4.0716613,-4.0716618,228.16287)"
|
||||
fill="#000000">
|
||||
<path
|
||||
d="m 7.22,19.02 c 0.96,0.46 1.88,0.62 2.64,0.62 0.74,0 1.36,-0.16 1.76,-0.28 v 2.14 c -0.5,0.12 -1.12,0.22 -1.82,0.22 -0.94,0 -2,-0.16 -3.16,-0.66 C 5.02,20.36 3.44,20.2 2.38,20.2 1.54,20.2 1,20.3 1,20.3 V 6.28 H 3.16 V 18.2 c 1.3,0 2.88,0.26 4.06,0.82 z m 4.4,-1.6 H 9.46 V 6.28 h 2.16 z m 14.14,-0.06 c 2.54,1.84 4.68,3 7.9,3 1.08,0 2.16,-0.14 3.16,-0.42 v 2.04 c -1.02,0.22 -2.1,0.34 -3.16,0.34 -3.86,0 -6.22,-1.38 -9.3,-3.52 -1.1,0.82 -2.54,1.3 -4.22,1.3 -4.32,0 -6.92,-3.14 -6.92,-7 0,-3.86 2.6,-7 6.92,-7 4.3,0 6.9,3.14 6.9,7 0,1.6 -0.44,3.08 -1.28,4.26 z M 36.82,6.28 h 2.14 v 6.46 c 0,2.88 -1.6,4.86 -4.92,4.86 -3.3,0 -4.92,-1.98 -4.92,-4.86 V 6.28 h 2.16 v 5.74 c 0,1.44 -0.1,3.6 2.76,3.6 2.88,0 2.78,-2.16 2.78,-3.6 z m -12.8,9.9 c 0.52,-0.84 0.78,-1.9 0.78,-3.08 0,-2.86 -1.56,-5.02 -4.66,-5.02 -3.12,0 -4.68,2.16 -4.68,5.02 0,1.14 0.24,2.16 0.74,2.98 0.5,-0.36 1.8,-1.1 3.74,-1.1 1.54,0 2.84,0.48 4.08,1.2 z m -3.88,1.96 c 0.92,0 1.7,-0.2 2.34,-0.54 -0.76,-0.38 -1.6,-0.64 -2.54,-0.64 -1.08,0 -1.86,0.3 -2.32,0.56 0.68,0.4 1.52,0.62 2.52,0.62 z m 22.8,1.78 H 40.78 V 6.28 h 2.16 z m 2,-13.64 h 5.14 c 4.3,0 6.9,2.96 6.9,6.82 0,3.76 -2.44,6.66 -6.54,6.82 h -5.5 z m 5.14,11.68 c 3.12,0 4.66,-1.98 4.66,-4.86 0,-2.86 -1.54,-4.84 -4.66,-4.84 H 47.1 v 9.7 z m 10.68,1.96 H 58.6 V 6.28 h 2.16 z m 1.4,-13.64 h 10.96 v 1.98 h -4.4 V 19.92 H 66.56 V 8.26 h -4.4 z m 22.26,0 h 2.54 l -5.6,8.26 v 5.38 h -2.14 v -5.36 l -5.6,-8.28 h 2.54 l 4.14,6.1 z"
|
||||
id="path743" />
|
||||
</g>
|
||||
<!-- PARTY text -->
|
||||
<g
|
||||
id="SvgjsG7694"
|
||||
featureKey="J3GnXt-1"
|
||||
transform="matrix(5.7152187,0,0,5.7152187,-5.71522,293.10844)"
|
||||
fill="#000000">
|
||||
<path
|
||||
d="m 6.12,6.28 c 2.32,0 5.14,0.56 5.14,4.16 0,2.78 -1.88,4.1 -4.98,4.1 -1.32,0 -3.12,0.6 -3.12,2.5 v 2.88 H 1 V 6.28 Z m -0.1,6.28 C 8.54,12.56 9,11.7 9,10.44 9,9.04 8.38,8.26 6,8.26 H 3.16 v 5.2 c 0.62,-0.52 1.5,-0.9 2.86,-0.9 z M 19.64,6.28 25.28,19.92 H 23.02 L 21.46,16.1 h -1.38 c -1.3,0 -2.7,0.24 -3.6,0.86 -0.8,0.54 -1.68,1.4 -2.2,2.58 l -0.16,0.38 H 11.86 L 17.5,6.28 Z m 0.42,7.9 h 0.62 L 18.56,8.98 16,15.3 c 1.04,-0.66 2,-1.12 4.06,-1.12 z m 14.66,1.52 c 1.54,2.26 2.12,2.26 2.52,2.26 v 1.96 h -0.32 c -1.42,0 -2.4,-0.98 -3.28,-2.32 -0.88,-1.32 -1.88,-3.06 -4.1,-3.06 h -0.98 v 5.38 H 26.4 V 6.28 h 4.92 c 2.92,0.02 5.14,0.74 5.14,4 0,2.38 -1.36,3.36 -3.2,3.72 0.56,0.42 1,1 1.46,1.7 z m -4.26,-3.14 c 1.98,0.02 3.76,0.06 3.76,-2.16 0,-1.9 -1.24,-2.14 -2.8,-2.14 h -2.86 v 4.3 z M 37.44,6.28 H 48.4 V 8.26 H 44 V 19.92 H 41.84 V 8.26 h -4.4 z m 22.26,0 h 2.54 l -5.6,8.26 v 5.38 H 54.5 V 14.56 L 48.9,6.28 h 2.54 l 4.14,6.1 z"
|
||||
id="path746" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.4 KiB |
BIN
public/web-app-manifest-192x192.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
public/web-app-manifest-512x512.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
25
requirements.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Introduction
|
||||
We wish to build a standalone Single-Page App (SPA) to interact with our new EVM-based DEX called Liquidity Party, which has a standard structure where each contract address represents an AMM pool that is an ERC20 LP token as well as a swap interface. Our pool is multi-asset and can quote any pair combination. Minting and redeeming are done most efficiently with a correctly-proportioned basket, but we also offer swap-mint and burn-swap operations that mint or burn from/to a single asset instead of a basket, by integrating a swap operation as well as the mint/burn liquidity operation.
|
||||
|
||||
The app should be client-side only, deployable on a CDN using no server. It will interact only with the blockchain via the user's Web3 wallet, in order to discover pools, prices, and provide swap / mint functionality.
|
||||
|
||||
It should be minimal and familiar, using popular UI frameworks and packages wherever possible (e.g. RainbowKit)
|
||||
|
||||
* mobile-first design
|
||||
* Typescript
|
||||
* next.js with static export (CDN / IPFS deployment target)
|
||||
* Localization using next-intl and subpath routing
|
||||
* shadcn/ui + Tailwind
|
||||
* RainbowKit
|
||||
* wagmi + viem
|
||||
* no linting
|
||||
* light/dark mode
|
||||
* no cookies, embedded analytics, or any tracking or server interactions.
|
||||
|
||||
* Landing page is swap form
|
||||
* Tabs available to Swap or Stake
|
||||
* Chain selector and wallet connector (RainbowKit)
|
||||
* Token search combobox
|
||||
* Mint tab (empty for now)
|
||||
* Swap form (main tab)
|
||||
*
|
||||
BIN
src/app/apple-icon.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
src/app/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
60
src/app/globals.css
Normal file
@@ -0,0 +1,60 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
--primary: 217 91% 60%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 217 91% 60%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 224 71% 4%;
|
||||
--foreground: 213 31% 91%;
|
||||
--card: 224 71% 6%;
|
||||
--card-foreground: 213 31% 91%;
|
||||
--popover: 224 71% 6%;
|
||||
--popover-foreground: 213 31% 91%;
|
||||
--primary: 217 91% 60%;
|
||||
--primary-foreground: 213 31% 91%;
|
||||
--secondary: 222 47% 11%;
|
||||
--secondary-foreground: 213 31% 91%;
|
||||
--muted: 223 47% 11%;
|
||||
--muted-foreground: 215.4 16.3% 56.9%;
|
||||
--accent: 216 34% 17%;
|
||||
--accent-foreground: 213 31% 91%;
|
||||
--destructive: 0 63% 31%;
|
||||
--destructive-foreground: 213 31% 91%;
|
||||
--border: 216 34% 17%;
|
||||
--input: 216 34% 17%;
|
||||
--ring: 217 91% 60%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
font-feature-settings: "rlig" 1, "calt" 1;
|
||||
}
|
||||
}
|
||||
36
src/app/icon0.svg
Normal file
@@ -0,0 +1,36 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000"><g clip-path="url(#SvgjsClipPath1209)"><rect width="1000" height="1000" fill="#ffffff"></rect><g transform="matrix(9.25540316264299,0,0,9.25540316264299,100,100)"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="86.435997" height="86.435997"><svg version="1.1" viewBox="0 0 86.435997 86.435997" id="svg188" sodipodi:docname="logo-flower.svg" inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs id="defs192"><clipPath id="SvgjsClipPath1209"><rect width="1000" height="1000" x="0" y="0" rx="500" ry="500"></rect></clipPath></defs>
|
||||
<sodipodi:namedview id="namedview190" pagecolor="#ffffff" bordercolor="#000000" borderopacity="0.25" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" showgrid="false" inkscape:zoom="5.6893399" inkscape:cx="83.489475" inkscape:cy="69.515973" inkscape:window-width="1864" inkscape:window-height="1131" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg188"></sodipodi:namedview>
|
||||
<!-- Flower -->
|
||||
<g fill="#000000" id="g186" transform="translate(-1.782,-1.782)">
|
||||
<g id="g184">
|
||||
<circle fill="#000000" cx="45" cy="44.999001" r="5.277" id="circle148"></circle>
|
||||
<g id="g182">
|
||||
<g id="g152">
|
||||
<path fill="#0d47a1" class="blue1" d="m 45.214,33.672 c 24.117,-31.271 0.369,-31.89 0.369,-31.89 0,0 -23.756,0.069 -0.369,31.89 z" id="path150"></path>
|
||||
</g>
|
||||
<g id="g156">
|
||||
<path fill="#1976d2" class="blue2" d="M 37.141,36.837 C 32.082,-2.327 14.853,14.027 14.853,14.027 c 0,0 -16.749,16.847 22.288,22.81 z" id="path154"></path>
|
||||
</g>
|
||||
<g id="g160">
|
||||
<path fill="#2196f3" class="blue3" d="M 33.67,44.786 C 2.401,20.667 1.782,44.416 1.782,44.416 c 0,0 0.069,23.757 31.888,0.37 z" id="path158"></path>
|
||||
</g>
|
||||
<g id="g164">
|
||||
<path fill="#00bcd4" class="blue4" d="m 36.837,52.859 c -39.166,5.059 -22.81,22.288 -22.81,22.288 0,0 16.847,16.752 22.81,-22.288 z" id="path162"></path>
|
||||
</g>
|
||||
<g id="g168">
|
||||
<path fill="#4fc3f7" class="blue5" d="m 44.785,56.33 c -24.118,31.271 -0.369,31.888 -0.369,31.888 0,0 23.755,-0.069 0.369,-31.888 z" id="path166"></path>
|
||||
</g>
|
||||
<g id="g172">
|
||||
<path fill="#3f51b5" class="blue6" d="m 52.859,53.164 c 5.057,39.164 22.287,22.81 22.287,22.81 0,0 16.75,-16.847 -22.287,-22.81 z" id="path170"></path>
|
||||
</g>
|
||||
<g id="g176">
|
||||
<path fill="#039be5" class="blue7" d="m 56.33,45.216 c 31.271,24.117 31.888,0.369 31.888,0.369 0,0 -0.07,-23.756 -31.888,-0.369 z" id="path174"></path>
|
||||
</g>
|
||||
<g id="g180">
|
||||
<path fill="#64b5f6" class="blue8" d="m 53.162,37.142 c 39.166,-5.061 22.811,-22.289 22.811,-22.289 0,0 -16.847,-16.749 -22.811,22.289 z" id="path178"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg></svg></g></g></svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/app/icon1.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
21
src/app/layout.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import '@rainbow-me/rainbowkit/styles.css';
|
||||
import '@/app/globals.css';
|
||||
import { Providers } from '@/components/providers';
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<head>
|
||||
<title>Liquidity Party</title>
|
||||
<meta name="description" content="Decentralized Exchange for Multi-Asset AMM Pools" />
|
||||
</head>
|
||||
<body className="min-h-screen">
|
||||
<Providers>{children}</Providers>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
21
src/app/manifest.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "Liquidity Party",
|
||||
"short_name": "Liquidity Party",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/web-app-manifest-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/web-app-manifest-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
31
src/app/page.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
'use client';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { SwapForm } from '@/components/swap-form';
|
||||
|
||||
export default function HomePage() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<Tabs defaultValue="swap" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-2 mb-8">
|
||||
<TabsTrigger value="swap">{t('nav.swap')}</TabsTrigger>
|
||||
<TabsTrigger value="stake">{t('nav.stake')}</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="swap">
|
||||
<SwapForm />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="stake">
|
||||
<div className="text-center py-12 text-muted-foreground">
|
||||
<h2 className="text-2xl font-semibold mb-2">{t('stake.title')}</h2>
|
||||
<p>{t('stake.comingSoon')}</p>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
56
src/components/header.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
'use client';
|
||||
import { ConnectButton } from '@rainbow-me/rainbowkit';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { LanguageSelector } from '@/components/language-selector';
|
||||
import { Moon, Sun } from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export function Header() {
|
||||
const { theme, setTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
const toggleTheme = () => {
|
||||
console.log('Toggle clicked, current theme:', theme);
|
||||
const newTheme = theme === 'dark' ? 'light' : 'dark';
|
||||
console.log('Setting theme to:', newTheme);
|
||||
setTheme(newTheme);
|
||||
};
|
||||
|
||||
const logoSrc = !mounted ? '/logo-dark.svg' : theme === 'dark' ? '/logo-dark.svg' : '/logo-light.svg';
|
||||
|
||||
return (
|
||||
<header className="border-b">
|
||||
<div className="container mx-auto px-4 py-4 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<img
|
||||
src={logoSrc}
|
||||
alt="Liquidity Party"
|
||||
className="h-8 w-auto"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Language Selector */}
|
||||
<LanguageSelector />
|
||||
|
||||
{/* Theme Toggle */}
|
||||
<Button variant="ghost" size="icon" onClick={toggleTheme} type="button">
|
||||
<Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
|
||||
{/* Wallet Connect */}
|
||||
<ConnectButton />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
54
src/components/language-selector.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
'use client';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { languages, type Language } from '@/lib/i18n';
|
||||
import { Globe } from 'lucide-react';
|
||||
|
||||
export function LanguageSelector() {
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
const changeLanguage = (lng: Language) => {
|
||||
i18n.changeLanguage(lng);
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('language', lng);
|
||||
}
|
||||
};
|
||||
|
||||
const currentLanguage = (i18n.language as Language) || 'en';
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="relative" type="button">
|
||||
<Globe className="h-5 w-5" />
|
||||
<span className="absolute -bottom-1 -right-1 text-xs">
|
||||
{languages[currentLanguage]?.flag || '🇬🇧'}
|
||||
</span>
|
||||
<span className="sr-only">Change language</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="min-w-[160px]">
|
||||
{Object.entries(languages).map(([code, { name, flag }]) => (
|
||||
<DropdownMenuItem
|
||||
key={code}
|
||||
onClick={() => changeLanguage(code as Language)}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<span className="mr-2 text-lg">{flag}</span>
|
||||
<span>{name}</span>
|
||||
{currentLanguage === code && (
|
||||
<span className="ml-auto text-primary">✓</span>
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
72
src/components/providers.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
'use client';
|
||||
|
||||
import { getDefaultConfig, RainbowKitProvider, darkTheme, lightTheme } from '@rainbow-me/rainbowkit';
|
||||
import { WagmiProvider } from 'wagmi';
|
||||
import { mainnet, polygon, optimism, arbitrum, base } from 'wagmi/chains';
|
||||
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
||||
import { ThemeProvider, useTheme } from 'next-themes';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { TranslationsProvider } from '@/providers/translations-provider';
|
||||
import { Header } from '@/components/header';
|
||||
|
||||
const config = getDefaultConfig({
|
||||
appName: 'Liquidity Party',
|
||||
projectId: 'YOUR_PROJECT_ID', // Get this from https://cloud.walletconnect.com
|
||||
chains: [mainnet, polygon, optimism, arbitrum, base],
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
function Web3Provider({ children }: { children: React.ReactNode }) {
|
||||
const { theme } = useTheme();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
// Use dark theme by default until mounted, then follow the actual theme
|
||||
const rainbowKitTheme = !mounted || theme === 'dark'
|
||||
? darkTheme({
|
||||
accentColor: '#a855f7', // Purple to match your primary color
|
||||
accentColorForeground: 'white',
|
||||
})
|
||||
: lightTheme({
|
||||
accentColor: '#a855f7',
|
||||
accentColorForeground: 'white',
|
||||
});
|
||||
|
||||
return (
|
||||
<WagmiProvider config={config}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RainbowKitProvider theme={rainbowKitTheme}>
|
||||
{children}
|
||||
</RainbowKitProvider>
|
||||
</QueryClientProvider>
|
||||
</WagmiProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export function Providers({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<TranslationsProvider>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="dark"
|
||||
enableSystem={false}
|
||||
storageKey="liquidity-party-theme"
|
||||
>
|
||||
<Web3Provider>
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<Header />
|
||||
<main className="flex-1 container mx-auto px-4 py-8">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
</Web3Provider>
|
||||
</ThemeProvider>
|
||||
</TranslationsProvider>
|
||||
);
|
||||
}
|
||||
97
src/components/swap-form.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ArrowDownUp } from 'lucide-react';
|
||||
import { useAccount } from 'wagmi';
|
||||
|
||||
export function SwapForm() {
|
||||
const { t } = useTranslation();
|
||||
const { isConnected } = useAccount();
|
||||
const [fromAmount, setFromAmount] = useState('');
|
||||
const [toAmount, setToAmount] = useState('');
|
||||
|
||||
const handleSwap = () => {
|
||||
// Swap logic will be implemented later
|
||||
console.log('Swap clicked');
|
||||
};
|
||||
|
||||
const switchTokens = () => {
|
||||
// Switch tokens logic
|
||||
setFromAmount(toAmount);
|
||||
setToAmount(fromAmount);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="w-full max-w-md mx-auto">
|
||||
<CardHeader>
|
||||
<CardTitle>{t('swap.title')}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* From Token */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between text-sm">
|
||||
<label className="text-muted-foreground">{t('swap.youPay')}</label>
|
||||
<span className="text-muted-foreground">{t('swap.balance')}: 0.00</span>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="0.0"
|
||||
value={fromAmount}
|
||||
onChange={(e) => setFromAmount(e.target.value)}
|
||||
className="text-2xl h-16"
|
||||
/>
|
||||
<Button variant="secondary" className="min-w-[120px]">
|
||||
{t('swap.selectToken')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Switch Button */}
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={switchTokens}
|
||||
className="rounded-full"
|
||||
>
|
||||
<ArrowDownUp className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* To Token */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between text-sm">
|
||||
<label className="text-muted-foreground">{t('swap.youReceive')}</label>
|
||||
<span className="text-muted-foreground">{t('swap.balance')}: 0.00</span>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="0.0"
|
||||
value={toAmount}
|
||||
onChange={(e) => setToAmount(e.target.value)}
|
||||
className="text-2xl h-16"
|
||||
/>
|
||||
<Button variant="secondary" className="min-w-[120px]">
|
||||
{t('swap.selectToken')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Swap Button */}
|
||||
<Button
|
||||
className="w-full h-14 text-lg"
|
||||
onClick={handleSwap}
|
||||
disabled={!isConnected || !fromAmount || !toAmount}
|
||||
>
|
||||
{!isConnected ? t('swap.connectWalletToSwap') : t('swap.swapButton')}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
55
src/components/ui/button.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline:
|
||||
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-4 py-2",
|
||||
sm: "h-9 rounded-md px-3",
|
||||
lg: "h-11 rounded-md px-8",
|
||||
icon: "h-10 w-10",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
|
||||
export { Button, buttonVariants }
|
||||
78
src/components/ui/card.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import * as React from "react"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Card.displayName = "Card"
|
||||
|
||||
const CardHeader = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardHeader.displayName = "CardHeader"
|
||||
|
||||
const CardTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLHeadingElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<h3
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-2xl font-semibold leading-none tracking-tight",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardTitle.displayName = "CardTitle"
|
||||
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
|
||||
const CardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||
))
|
||||
CardContent.displayName = "CardContent"
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex items-center p-6 pt-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = "CardFooter"
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
||||
182
src/components/ui/dropdown-menu.tsx
Normal file
@@ -0,0 +1,182 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const DropdownMenu = DropdownMenuPrimitive.Root
|
||||
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
||||
const DropdownMenuGroup = DropdownMenuPrimitive.Group
|
||||
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
|
||||
const DropdownMenuSub = DropdownMenuPrimitive.Sub
|
||||
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
||||
|
||||
const DropdownMenuSubTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean
|
||||
}
|
||||
>(({ className, inset, children, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
))
|
||||
DropdownMenuSubTrigger.displayName =
|
||||
DropdownMenuPrimitive.SubTrigger.displayName
|
||||
|
||||
const DropdownMenuSubContent = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuSubContent.displayName =
|
||||
DropdownMenuPrimitive.SubContent.displayName
|
||||
|
||||
const DropdownMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
||||
>(({ className, sideOffset = 4, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Portal>
|
||||
<DropdownMenuPrimitive.Content
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
))
|
||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
||||
|
||||
const DropdownMenuItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
||||
inset?: boolean
|
||||
}
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
||||
|
||||
const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
||||
>(({ className, children, checked, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.CheckboxItem>
|
||||
))
|
||||
DropdownMenuCheckboxItem.displayName =
|
||||
DropdownMenuPrimitive.CheckboxItem.displayName
|
||||
|
||||
const DropdownMenuRadioItem = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.RadioItem>
|
||||
))
|
||||
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
||||
|
||||
const DropdownMenuLabel = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
||||
inset?: boolean
|
||||
}
|
||||
>(({ className, inset, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Label
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"px-2 py-1.5 text-sm font-semibold",
|
||||
inset && "pl-8",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
||||
|
||||
const DropdownMenuSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
||||
|
||||
const DropdownMenuShortcut = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
|
||||
|
||||
export {
|
||||
DropdownMenu,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuRadioGroup,
|
||||
}
|
||||
24
src/components/ui/input.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import * as React from "react"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, ...props }, ref) => {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Input.displayName = "Input"
|
||||
|
||||
export { Input }
|
||||
54
src/components/ui/tabs.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Tabs = TabsPrimitive.Root
|
||||
|
||||
const TabsList = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.List>,
|
||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<TabsPrimitive.List
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsList.displayName = TabsPrimitive.List.displayName
|
||||
|
||||
const TabsTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<TabsPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
||||
|
||||
const TabsContent = React.forwardRef<
|
||||
React.ElementRef<typeof TabsPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<TabsPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
TabsContent.displayName = TabsPrimitive.Content.displayName
|
||||
|
||||
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
||||
46
src/lib/i18n.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
import enTranslations from '@/locales/en.json';
|
||||
import esTranslations from '@/locales/es.json';
|
||||
import frTranslations from '@/locales/fr.json';
|
||||
import deTranslations from '@/locales/de.json';
|
||||
import zhTranslations from '@/locales/zh.json';
|
||||
import jaTranslations from '@/locales/ja.json';
|
||||
|
||||
export const languages = {
|
||||
en: { name: 'English', flag: '🇬🇧' },
|
||||
es: { name: 'Español', flag: '🇪🇸' },
|
||||
fr: { name: 'Français', flag: '🇫🇷' },
|
||||
de: { name: 'Deutsch', flag: '🇩🇪' },
|
||||
zh: { name: '中文', flag: '🇨🇳' },
|
||||
ja: { name: '日本語', flag: '🇯🇵' },
|
||||
} as const;
|
||||
|
||||
export type Language = keyof typeof languages;
|
||||
|
||||
const resources = {
|
||||
en: { translation: enTranslations },
|
||||
es: { translation: esTranslations },
|
||||
fr: { translation: frTranslations },
|
||||
de: { translation: deTranslations },
|
||||
zh: { translation: zhTranslations },
|
||||
ja: { translation: jaTranslations },
|
||||
};
|
||||
|
||||
// Initialize i18next
|
||||
i18n
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources,
|
||||
lng: typeof window !== 'undefined' ? localStorage.getItem('language') || 'en' : 'en',
|
||||
fallbackLng: 'en',
|
||||
interpolation: {
|
||||
escapeValue: false, // React already escapes values
|
||||
},
|
||||
react: {
|
||||
useSuspense: false, // Disable suspense for client-side only
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
6
src/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
25
src/locales/de.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"common": {
|
||||
"liquidityParty": "Liquidity Party",
|
||||
"connectWallet": "Wallet Verbinden"
|
||||
},
|
||||
"nav": {
|
||||
"swap": "Tauschen",
|
||||
"stake": "Staken"
|
||||
},
|
||||
"swap": {
|
||||
"title": "Tauschen",
|
||||
"from": "Von",
|
||||
"to": "Zu",
|
||||
"youPay": "Sie zahlen",
|
||||
"youReceive": "Sie erhalten",
|
||||
"balance": "Guthaben",
|
||||
"selectToken": "Token auswählen",
|
||||
"swapButton": "Tauschen",
|
||||
"connectWalletToSwap": "Wallet verbinden zum Tauschen"
|
||||
},
|
||||
"stake": {
|
||||
"title": "Staken",
|
||||
"comingSoon": "Demnächst verfügbar..."
|
||||
}
|
||||
}
|
||||
25
src/locales/en.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"common": {
|
||||
"liquidityParty": "Liquidity Party",
|
||||
"connectWallet": "Connect Wallet"
|
||||
},
|
||||
"nav": {
|
||||
"swap": "Swap",
|
||||
"stake": "Stake"
|
||||
},
|
||||
"swap": {
|
||||
"title": "Swap",
|
||||
"from": "From",
|
||||
"to": "To",
|
||||
"youPay": "You pay",
|
||||
"youReceive": "You receive",
|
||||
"balance": "Balance",
|
||||
"selectToken": "Select token",
|
||||
"swapButton": "Swap",
|
||||
"connectWalletToSwap": "Connect wallet to swap"
|
||||
},
|
||||
"stake": {
|
||||
"title": "Stake",
|
||||
"comingSoon": "Coming soon..."
|
||||
}
|
||||
}
|
||||
25
src/locales/es.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"common": {
|
||||
"liquidityParty": "Liquidity Party",
|
||||
"connectWallet": "Conectar Billetera"
|
||||
},
|
||||
"nav": {
|
||||
"swap": "Intercambiar",
|
||||
"stake": "Apostar"
|
||||
},
|
||||
"swap": {
|
||||
"title": "Intercambiar",
|
||||
"from": "Desde",
|
||||
"to": "Hasta",
|
||||
"youPay": "Pagas",
|
||||
"youReceive": "Recibes",
|
||||
"balance": "Saldo",
|
||||
"selectToken": "Seleccionar token",
|
||||
"swapButton": "Intercambiar",
|
||||
"connectWalletToSwap": "Conecta tu billetera para intercambiar"
|
||||
},
|
||||
"stake": {
|
||||
"title": "Apostar",
|
||||
"comingSoon": "Próximamente..."
|
||||
}
|
||||
}
|
||||
25
src/locales/fr.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"common": {
|
||||
"liquidityParty": "Liquidity Party",
|
||||
"connectWallet": "Connecter le Portefeuille"
|
||||
},
|
||||
"nav": {
|
||||
"swap": "Échanger",
|
||||
"stake": "Staker"
|
||||
},
|
||||
"swap": {
|
||||
"title": "Échanger",
|
||||
"from": "De",
|
||||
"to": "À",
|
||||
"youPay": "Vous payez",
|
||||
"youReceive": "Vous recevez",
|
||||
"balance": "Solde",
|
||||
"selectToken": "Sélectionner un token",
|
||||
"swapButton": "Échanger",
|
||||
"connectWalletToSwap": "Connectez votre portefeuille pour échanger"
|
||||
},
|
||||
"stake": {
|
||||
"title": "Staker",
|
||||
"comingSoon": "Bientôt disponible..."
|
||||
}
|
||||
}
|
||||
25
src/locales/ja.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"common": {
|
||||
"liquidityParty": "Liquidity Party",
|
||||
"connectWallet": "ウォレット接続"
|
||||
},
|
||||
"nav": {
|
||||
"swap": "スワップ",
|
||||
"stake": "ステーキング"
|
||||
},
|
||||
"swap": {
|
||||
"title": "スワップ",
|
||||
"from": "から",
|
||||
"to": "へ",
|
||||
"youPay": "支払い",
|
||||
"youReceive": "受取り",
|
||||
"balance": "残高",
|
||||
"selectToken": "トークンを選択",
|
||||
"swapButton": "スワップ",
|
||||
"connectWalletToSwap": "スワップするにはウォレットを接続してください"
|
||||
},
|
||||
"stake": {
|
||||
"title": "ステーキング",
|
||||
"comingSoon": "近日公開..."
|
||||
}
|
||||
}
|
||||
25
src/locales/zh.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"common": {
|
||||
"liquidityParty": "Liquidity Party",
|
||||
"connectWallet": "连接钱包"
|
||||
},
|
||||
"nav": {
|
||||
"swap": "兑换",
|
||||
"stake": "质押"
|
||||
},
|
||||
"swap": {
|
||||
"title": "兑换",
|
||||
"from": "从",
|
||||
"to": "到",
|
||||
"youPay": "您支付",
|
||||
"youReceive": "您收到",
|
||||
"balance": "余额",
|
||||
"selectToken": "选择代币",
|
||||
"swapButton": "兑换",
|
||||
"connectWalletToSwap": "连接钱包以进行兑换"
|
||||
},
|
||||
"stake": {
|
||||
"title": "质押",
|
||||
"comingSoon": "即将推出..."
|
||||
}
|
||||
}
|
||||
9
src/providers/theme-provider.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import { ThemeProvider as NextThemesProvider } from 'next-themes';
|
||||
import { type ThemeProviderProps } from 'next-themes/dist/types';
|
||||
|
||||
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
|
||||
}
|
||||
26
src/providers/translations-provider.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
'use client';
|
||||
|
||||
import { ReactNode, useEffect, useState } from 'react';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import i18n from '@/lib/i18n';
|
||||
|
||||
export function TranslationsProvider({ children }: { children: ReactNode }) {
|
||||
const [isInitialized, setIsInitialized] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Ensure i18n is initialized on the client side
|
||||
if (!isInitialized) {
|
||||
setIsInitialized(true);
|
||||
}
|
||||
}, [isInitialized]);
|
||||
|
||||
if (!isInitialized) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
{children}
|
||||
</I18nextProvider>
|
||||
);
|
||||
}
|
||||
26
src/providers/web3-provider.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
'use client';
|
||||
|
||||
import '@rainbow-me/rainbowkit/styles.css';
|
||||
import { getDefaultConfig, RainbowKitProvider } from '@rainbow-me/rainbowkit';
|
||||
import { WagmiProvider } from 'wagmi';
|
||||
import { mainnet, polygon, optimism, arbitrum, base } from 'wagmi/chains';
|
||||
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
||||
|
||||
const config = getDefaultConfig({
|
||||
appName: 'Liquidity Party',
|
||||
projectId: 'YOUR_PROJECT_ID', // Get this from https://cloud.walletconnect.com
|
||||
chains: [mainnet, polygon, optimism, arbitrum, base],
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
export function Web3Provider({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<WagmiProvider config={config}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RainbowKitProvider>{children}</RainbowKitProvider>
|
||||
</QueryClientProvider>
|
||||
</WagmiProvider>
|
||||
);
|
||||
}
|
||||
57
tailwind.config.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { Config } from "tailwindcss";
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: "hsl(var(--secondary))",
|
||||
foreground: "hsl(var(--secondary-foreground))",
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: "hsl(var(--destructive))",
|
||||
foreground: "hsl(var(--destructive-foreground))",
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: "hsl(var(--muted))",
|
||||
foreground: "hsl(var(--muted-foreground))",
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: "hsl(var(--accent))",
|
||||
foreground: "hsl(var(--accent-foreground))",
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: "hsl(var(--popover))",
|
||||
foreground: "hsl(var(--popover-foreground))",
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card))",
|
||||
foreground: "hsl(var(--card-foreground))",
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
lg: "var(--radius)",
|
||||
md: "calc(var(--radius) - 2px)",
|
||||
sm: "calc(var(--radius) - 4px)",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
};
|
||||
|
||||
export default config;
|
||||
27
tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||