diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml
index ef0b139..1954521 100644
--- a/.github/workflows/deploy-dev.yml
+++ b/.github/workflows/deploy-dev.yml
@@ -28,5 +28,5 @@ jobs:
dist_path: .
enable_notify_comment: true
enable_notify_slack: true
- slack_channel: public-darwinia-websites-apps
+ slack_channel: public-ringdao-apps
slack_webhook: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }}
diff --git a/.github/workflows/deploy-prd.yml b/.github/workflows/deploy-prd.yml
index 422ee36..c4b9969 100644
--- a/.github/workflows/deploy-prd.yml
+++ b/.github/workflows/deploy-prd.yml
@@ -29,6 +29,6 @@ jobs:
script_run: false
dist_path: .
enable_notify_slack: true
- slack_channel: public-darwinia-websites-apps
+ slack_channel: public-ringdao-apps
slack_webhook: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }}
diff --git a/.github/workflows/deploy-stg.yml b/.github/workflows/deploy-stg.yml
index e6e0464..c69b21e 100644
--- a/.github/workflows/deploy-stg.yml
+++ b/.github/workflows/deploy-stg.yml
@@ -29,5 +29,5 @@ jobs:
dist_path: .
enable_notify_comment: true
enable_notify_slack: true
- slack_channel: public-darwinia-websites-apps
+ slack_channel: public-ringdao-apps
slack_webhook: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }}
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..f8acd65
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,9 @@
+
+FROM node:21-alpine
+
+COPY . /app
+
+RUN yarn install && yarn build
+
+
+
diff --git a/next.config.js b/next.config.js
index f469222..fcf9515 100644
--- a/next.config.js
+++ b/next.config.js
@@ -3,7 +3,7 @@ const nextConfig = {
webpack: (config) => {
config.externals.push("lokijs", "encoding", "pino-pretty");
return config;
- },
+ }
};
module.exports = nextConfig;
diff --git a/package-lock.json b/package-lock.json
index 79ec955..7a70a14 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"@polkadot/api": "^12.3.1",
"@polkadot/react-identicon": "^3.6.3",
"@rainbow-me/rainbowkit": "^1.1.3",
+ "@react-spring/web": "^9.5.0",
"@talismn/connect-wallets": "^1.2.3",
"next": "13.5.4",
"react": "^18",
@@ -3937,6 +3938,73 @@
"wagmi": "~1.0.1 || ~1.1.0 || ~1.2.0 || ~1.3.0 || ~1.4.0"
}
},
+ "node_modules/@react-spring/animated": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.5.5.tgz",
+ "integrity": "sha512-glzViz7syQ3CE6BQOwAyr75cgh0qsihm5lkaf24I0DfU63cMm/3+br299UEYkuaHNmfDfM414uktiPlZCNJbQA==",
+ "dependencies": {
+ "@react-spring/shared": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/core": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.5.5.tgz",
+ "integrity": "sha512-shaJYb3iX18Au6gkk8ahaF0qx0LpS0Yd+ajb4asBaAQf6WPGuEdJsbsNSgei1/O13JyEATsJl20lkjeslJPMYA==",
+ "dependencies": {
+ "@react-spring/animated": "~9.5.5",
+ "@react-spring/rafz": "~9.5.5",
+ "@react-spring/shared": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-spring/donate"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/rafz": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.5.5.tgz",
+ "integrity": "sha512-F/CLwB0d10jL6My5vgzRQxCNY2RNyDJZedRBK7FsngdCmzoq3V4OqqNc/9voJb9qRC2wd55oGXUeXv2eIaFmsw=="
+ },
+ "node_modules/@react-spring/shared": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.5.5.tgz",
+ "integrity": "sha512-YwW70Pa/YXPOwTutExHZmMQSHcNC90kJOnNR4G4mCDNV99hE98jWkIPDOsgqbYx3amIglcFPiYKMaQuGdr8dyQ==",
+ "dependencies": {
+ "@react-spring/rafz": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/types": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.5.5.tgz",
+ "integrity": "sha512-7I/qY8H7Enwasxr4jU6WmtNK+RZ4Z/XvSlDvjXFVe7ii1x0MoSlkw6pD7xuac8qrHQRm9BTcbZNyeeKApYsvCg=="
+ },
+ "node_modules/@react-spring/web": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.5.0.tgz",
+ "integrity": "sha512-fq33Og23zCLxH7HELdOyAk0pWtwbSsk8MzPenN2JZMYI1dElB208r4CedM78TPY99YWIY2XRJ45VxbikxVeWLQ==",
+ "dependencies": {
+ "@react-spring/animated": "~9.5.0",
+ "@react-spring/core": "~9.5.0",
+ "@react-spring/shared": "~9.5.0",
+ "@react-spring/types": "~9.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || >=17.0.0 || >=18.0.0",
+ "react-dom": "^16.8.0 || >=17.0.0 || >=18.0.0"
+ }
+ },
"node_modules/@rushstack/eslint-patch": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz",
@@ -14552,6 +14620,56 @@
"react-remove-scroll": "2.5.4"
}
},
+ "@react-spring/animated": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.5.5.tgz",
+ "integrity": "sha512-glzViz7syQ3CE6BQOwAyr75cgh0qsihm5lkaf24I0DfU63cMm/3+br299UEYkuaHNmfDfM414uktiPlZCNJbQA==",
+ "requires": {
+ "@react-spring/shared": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ }
+ },
+ "@react-spring/core": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.5.5.tgz",
+ "integrity": "sha512-shaJYb3iX18Au6gkk8ahaF0qx0LpS0Yd+ajb4asBaAQf6WPGuEdJsbsNSgei1/O13JyEATsJl20lkjeslJPMYA==",
+ "requires": {
+ "@react-spring/animated": "~9.5.5",
+ "@react-spring/rafz": "~9.5.5",
+ "@react-spring/shared": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ }
+ },
+ "@react-spring/rafz": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.5.5.tgz",
+ "integrity": "sha512-F/CLwB0d10jL6My5vgzRQxCNY2RNyDJZedRBK7FsngdCmzoq3V4OqqNc/9voJb9qRC2wd55oGXUeXv2eIaFmsw=="
+ },
+ "@react-spring/shared": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.5.5.tgz",
+ "integrity": "sha512-YwW70Pa/YXPOwTutExHZmMQSHcNC90kJOnNR4G4mCDNV99hE98jWkIPDOsgqbYx3amIglcFPiYKMaQuGdr8dyQ==",
+ "requires": {
+ "@react-spring/rafz": "~9.5.5",
+ "@react-spring/types": "~9.5.5"
+ }
+ },
+ "@react-spring/types": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.5.5.tgz",
+ "integrity": "sha512-7I/qY8H7Enwasxr4jU6WmtNK+RZ4Z/XvSlDvjXFVe7ii1x0MoSlkw6pD7xuac8qrHQRm9BTcbZNyeeKApYsvCg=="
+ },
+ "@react-spring/web": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.5.0.tgz",
+ "integrity": "sha512-fq33Og23zCLxH7HELdOyAk0pWtwbSsk8MzPenN2JZMYI1dElB208r4CedM78TPY99YWIY2XRJ45VxbikxVeWLQ==",
+ "requires": {
+ "@react-spring/animated": "~9.5.0",
+ "@react-spring/core": "~9.5.0",
+ "@react-spring/shared": "~9.5.0",
+ "@react-spring/types": "~9.5.0"
+ }
+ },
"@rushstack/eslint-patch": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz",
diff --git a/package.json b/package.json
index 396df1a..b0f9970 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"@polkadot/api": "^12.3.1",
"@polkadot/react-identicon": "^3.6.3",
"@rainbow-me/rainbowkit": "^1.1.3",
+ "@react-spring/web": "^9.5.0",
"@talismn/connect-wallets": "^1.2.3",
"next": "13.5.4",
"react": "^18",
diff --git a/public/fonts/EuclidCircularA/Euclid Circular A Bold Italic.ttf b/public/fonts/EuclidCircularA/Euclid Circular A Bold Italic.ttf
new file mode 100644
index 0000000..3f4e417
Binary files /dev/null and b/public/fonts/EuclidCircularA/Euclid Circular A Bold Italic.ttf differ
diff --git a/public/fonts/EuclidCircularA/Euclid Circular A Italic.ttf b/public/fonts/EuclidCircularA/Euclid Circular A Italic.ttf
new file mode 100644
index 0000000..a445215
Binary files /dev/null and b/public/fonts/EuclidCircularA/Euclid Circular A Italic.ttf differ
diff --git a/public/fonts/EuclidCircularA/Euclid Circular A Light Italic.ttf b/public/fonts/EuclidCircularA/Euclid Circular A Light Italic.ttf
new file mode 100644
index 0000000..9b617da
Binary files /dev/null and b/public/fonts/EuclidCircularA/Euclid Circular A Light Italic.ttf differ
diff --git a/public/fonts/EuclidCircularA/Euclid Circular A Medium Italic.ttf b/public/fonts/EuclidCircularA/Euclid Circular A Medium Italic.ttf
new file mode 100644
index 0000000..68732af
Binary files /dev/null and b/public/fonts/EuclidCircularA/Euclid Circular A Medium Italic.ttf differ
diff --git a/public/fonts/EuclidCircularA/Euclid Circular A SemiBold Italic.ttf b/public/fonts/EuclidCircularA/Euclid Circular A SemiBold Italic.ttf
new file mode 100644
index 0000000..a95e6c4
Binary files /dev/null and b/public/fonts/EuclidCircularA/Euclid Circular A SemiBold Italic.ttf differ
diff --git a/public/fonts/EuclidCircularA/Euclid Circular A SemiBold.ttf b/public/fonts/EuclidCircularA/Euclid Circular A SemiBold.ttf
new file mode 100644
index 0000000..36616c4
Binary files /dev/null and b/public/fonts/EuclidCircularA/Euclid Circular A SemiBold.ttf differ
diff --git a/public/fonts/EuclidCircularA/EuclidCircularABold.ttf b/public/fonts/EuclidCircularA/EuclidCircularABold.ttf
new file mode 100644
index 0000000..1a5c3bf
Binary files /dev/null and b/public/fonts/EuclidCircularA/EuclidCircularABold.ttf differ
diff --git a/public/fonts/EuclidCircularA/EuclidCircularALight.ttf b/public/fonts/EuclidCircularA/EuclidCircularALight.ttf
new file mode 100644
index 0000000..6a60f9b
Binary files /dev/null and b/public/fonts/EuclidCircularA/EuclidCircularALight.ttf differ
diff --git a/public/fonts/EuclidCircularA/EuclidCircularAMedium.ttf b/public/fonts/EuclidCircularA/EuclidCircularAMedium.ttf
new file mode 100644
index 0000000..3661986
Binary files /dev/null and b/public/fonts/EuclidCircularA/EuclidCircularAMedium.ttf differ
diff --git a/public/fonts/EuclidCircularA/EuclidCircularARegular.ttf b/public/fonts/EuclidCircularA/EuclidCircularARegular.ttf
new file mode 100644
index 0000000..b78b394
Binary files /dev/null and b/public/fonts/EuclidCircularA/EuclidCircularARegular.ttf differ
diff --git a/public/images/asset/dot.svg b/public/images/asset/dot.svg
new file mode 100644
index 0000000..9d5bad6
--- /dev/null
+++ b/public/images/asset/dot.svg
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/images/icons/assethub-icon.svg b/public/images/icons/assethub-icon.svg
new file mode 100644
index 0000000..4d2e150
--- /dev/null
+++ b/public/images/icons/assethub-icon.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/public/images/icons/copy-icon.svg b/public/images/icons/copy-icon.svg
new file mode 100644
index 0000000..ef9105d
--- /dev/null
+++ b/public/images/icons/copy-icon.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/public/images/icons/darwinia-icon.svg b/public/images/icons/darwinia-icon.svg
new file mode 100644
index 0000000..1821ac2
--- /dev/null
+++ b/public/images/icons/darwinia-icon.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/public/images/icons/disconnect-icon.svg b/public/images/icons/disconnect-icon.svg
new file mode 100644
index 0000000..192d50d
--- /dev/null
+++ b/public/images/icons/disconnect-icon.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/images/icons/downarrow-icon.svg b/public/images/icons/downarrow-icon.svg
new file mode 100644
index 0000000..e5cd8fd
--- /dev/null
+++ b/public/images/icons/downarrow-icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/images/icons/email-icon.svg b/public/images/icons/email-icon.svg
new file mode 100644
index 0000000..999a8cd
--- /dev/null
+++ b/public/images/icons/email-icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/images/icons/github-icon.svg b/public/images/icons/github-icon.svg
new file mode 100644
index 0000000..efe173b
--- /dev/null
+++ b/public/images/icons/github-icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/images/icons/hydration-icon.svg b/public/images/icons/hydration-icon.svg
new file mode 100644
index 0000000..baf4a3b
--- /dev/null
+++ b/public/images/icons/hydration-icon.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/public/images/icons/pending-icon.svg b/public/images/icons/pending-icon.svg
new file mode 100644
index 0000000..544d048
--- /dev/null
+++ b/public/images/icons/pending-icon.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/images/icons/pink-icon.png b/public/images/icons/pink-icon.png
new file mode 100644
index 0000000..282f059
Binary files /dev/null and b/public/images/icons/pink-icon.png differ
diff --git a/public/images/icons/ring-icon.svg b/public/images/icons/ring-icon.svg
new file mode 100644
index 0000000..e85b8de
--- /dev/null
+++ b/public/images/icons/ring-icon.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/public/images/icons/success-icon.svg b/public/images/icons/success-icon.svg
new file mode 100644
index 0000000..98acdd4
--- /dev/null
+++ b/public/images/icons/success-icon.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/images/icons/telegram-icon.svg b/public/images/icons/telegram-icon.svg
new file mode 100644
index 0000000..f190ba3
--- /dev/null
+++ b/public/images/icons/telegram-icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/images/icons/usdt-icon.svg b/public/images/icons/usdt-icon.svg
new file mode 100644
index 0000000..c1fa5f1
--- /dev/null
+++ b/public/images/icons/usdt-icon.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/public/images/icons/wallet-icon.svg b/public/images/icons/wallet-icon.svg
new file mode 100644
index 0000000..09a027b
--- /dev/null
+++ b/public/images/icons/wallet-icon.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/images/icons/x-icon.svg b/public/images/icons/x-icon.svg
new file mode 100644
index 0000000..926b865
--- /dev/null
+++ b/public/images/icons/x-icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/images/network/astar.svg b/public/images/network/astar.svg
new file mode 100644
index 0000000..21c2bea
--- /dev/null
+++ b/public/images/network/astar.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/public/images/network/bifrost.svg b/public/images/network/bifrost.svg
new file mode 100644
index 0000000..6b39290
--- /dev/null
+++ b/public/images/network/bifrost.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/public/images/network/centrufuge.svg b/public/images/network/centrufuge.svg
new file mode 100644
index 0000000..02956ea
--- /dev/null
+++ b/public/images/network/centrufuge.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/public/images/paralink-logo.svg b/public/images/paralink-logo.svg
new file mode 100644
index 0000000..08a45b9
--- /dev/null
+++ b/public/images/paralink-logo.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/images/wallet/coinbase.svg b/public/images/wallet/coinbase.svg
new file mode 100644
index 0000000..c47fdf9
--- /dev/null
+++ b/public/images/wallet/coinbase.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/public/images/wallet/metamask.png b/public/images/wallet/metamask.png
new file mode 100644
index 0000000..8f89676
Binary files /dev/null and b/public/images/wallet/metamask.png differ
diff --git a/public/images/wallet/nova.svg b/public/images/wallet/nova.svg
new file mode 100644
index 0000000..722da83
--- /dev/null
+++ b/public/images/wallet/nova.svg
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/images/wallet/polkadot.png b/public/images/wallet/polkadot.png
new file mode 100644
index 0000000..5bbdbfb
Binary files /dev/null and b/public/images/wallet/polkadot.png differ
diff --git a/public/images/wallet/ronin.svg b/public/images/wallet/ronin.svg
new file mode 100644
index 0000000..131f651
--- /dev/null
+++ b/public/images/wallet/ronin.svg
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/images/wallet/sub-wallet.png b/public/images/wallet/sub-wallet.png
new file mode 100644
index 0000000..01bd377
Binary files /dev/null and b/public/images/wallet/sub-wallet.png differ
diff --git a/public/images/wallet/wallet-connect.svg b/public/images/wallet/wallet-connect.svg
new file mode 100644
index 0000000..d90457a
--- /dev/null
+++ b/public/images/wallet/wallet-connect.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/app/globals.css b/src/app/globals.css
index e77b20f..6254e50 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -26,6 +26,36 @@ body {
rgb(var(--background-start-rgb));
} */
+@font-face {
+ font-family: JetBrainsMono;
+ src: url("/fonts/EuclidCircularA/EuclidCircularALight.ttf") format("woff2");
+ font-wheit: 100;
+}
+@font-face {
+ font-family: EuclidCircularA;
+ src: url("/fonts/EuclidCircularA/EuclidCircularALight.ttf") format("woff2");
+ font-wheit: 300;
+}
+@font-face {
+ font-family: EuclidCircularA;
+ src: url("/fonts/EuclidCircularA/EuclidCircularARegular.ttf") format("woff2");
+ font-wheit: 400;
+}
+@font-face {
+ font-family: EuclidCircularA;
+ src: url("/fonts/EuclidCircularA/EuclidCircularAMedium.ttf") format("woff2");
+ font-wheit: 500;
+}
+@font-face {
+ font-family: EuclidCircularA;
+ src: url("/fonts/EuclidCircularA/EuclidCircularABold.ttf") format("woff2");
+ font-wheit: 700;
+}
+
+html {
+ font-family: EuclidCircularA;
+}
+
@layer components {
.border-radius {
@apply rounded-2xl;
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 958df21..d65ef54 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -2,10 +2,10 @@ import RainbowProvider from "@/providers/rainbow-provider";
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
-import Header from "@/components/header";
-import Footer from "@/components/footer";
import TalismanProvider from "@/providers/talisman-provider";
import TransferProvider from "@/providers/transfer-provider";
+import Header from "@/components/header";
+import Footer from "@/components/footer";
const inter = Inter({ subsets: ["latin"] });
@@ -17,8 +17,10 @@ export const metadata: Metadata = {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
-
-
+
+
diff --git a/src/app/oladPage.tsx b/src/app/oladPage.tsx
new file mode 100644
index 0000000..85e0125
--- /dev/null
+++ b/src/app/oladPage.tsx
@@ -0,0 +1,10 @@
+import Transfer from "@/old_components/transfer";
+import PageWrap from "@/old_components/page-wrap";
+
+export default function Home() {
+ return (
+
+
+
+ );
+}
diff --git a/src/app/oldLayout.tsx b/src/app/oldLayout.tsx
new file mode 100644
index 0000000..a35e376
--- /dev/null
+++ b/src/app/oldLayout.tsx
@@ -0,0 +1,34 @@
+import RainbowProvider from "@/providers/rainbow-provider";
+import "./globals.css";
+import type { Metadata } from "next";
+import { Inter } from "next/font/google";
+import Header from "@/old_components/header";
+import Footer from "@/old_components/footer";
+import TalismanProvider from "@/providers/talisman-provider";
+import TransferProvider from "@/providers/transfer-provider";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export const metadata: Metadata = {
+ title: "Darwinia Paralink",
+ description: "A user-friendly UI for XCM token transfers across various parachains.",
+ manifest: "/manifest.json",
+};
+
+export default function RootLayout({ children }: { children: React.ReactNode }) {
+ return (
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 0a12179..6bc2cd5 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,10 +1,9 @@
-import Transfer from "@/components/transfer";
-import PageWrap from "@/components/page-wrap";
+import AppBox from "@/components/appBox";
export default function Home() {
return (
-
-
-
+
);
}
diff --git a/src/components/accountButton.tsx b/src/components/accountButton.tsx
new file mode 100644
index 0000000..9ee2820
--- /dev/null
+++ b/src/components/accountButton.tsx
@@ -0,0 +1,144 @@
+import DisconnectButton from "./disconnetButton";
+import data from "../data/data.json";
+import Image from "next/image";
+import { MouseEventHandler, useCallback, useEffect, useMemo, useState } from "react";
+import { useAccount, useDisconnect, useNetwork, useSwitchNetwork } from "wagmi";
+import { useTalisman, useTransfer } from "@/hooks";
+import { isValidAddress, parseCross, toShortAdrress, formatBalance, getAssetIconSrc } from "@/utils";
+import { WalletID } from "@/types";
+
+export default function AccountButton({ setSwitchWallet }: { setSwitchWallet: (x: boolean) => void }) {
+ const { talismanAccounts } = useTalisman();
+ const { disconnect } = useDisconnect();
+
+ const { address } = useAccount();
+ const { chain } = useNetwork();
+ const { chains, error, isLoading, pendingChainId, switchNetworkAsync } = useSwitchNetwork();
+
+ const { defaultSourceAssetOptions } = parseCross();
+ const {
+ sender,
+ sourceChain,
+ targetChain,
+ activeSenderWallet,
+ activeRecipientWallet,
+ setSender,
+ activeSenderAccount,
+ sourceAssetBalance,
+ setActiveSenderAccount,
+ setActiveRecipientAccount,
+ setActiveSenderWallet,
+ setActiveRecipientWallet,
+ } = useTransfer();
+
+ const [sourceAssetOptions, setSourceAssetOptions] = useState(defaultSourceAssetOptions);
+ const [subMenu, setSubMenu] = useState(false);
+ const [copied, setCopied] = useState(false);
+ const handleToggleSubMenu = useCallback(() => {
+ setSubMenu((prev) => !prev);
+ }, []);
+
+ useEffect(() => {
+ if (copied) {
+ setTimeout(() => {
+ setCopied(false);
+ }, 2000);
+ }
+ }, [copied]);
+ const needSwitchNetwork = useMemo(
+ () => activeSenderWallet === WalletID.EVM && chain && chain.id !== sourceChain.id,
+ [chain, sourceChain, activeSenderWallet],
+ );
+
+ const connectedAddress =
+ activeSenderWallet === WalletID.TALISMAN
+ ? talismanAccounts[0]?.address
+ : activeSenderWallet === WalletID.EVM
+ ? address
+ : undefined;
+
+ const walletIcon = activeSenderWallet === WalletID.EVM ? "evm.png" : "talisman-red.svg";
+
+ const handleDisconnect = useCallback(() => {
+ setSender(undefined);
+ setActiveSenderWallet(undefined);
+ setActiveSenderAccount(undefined);
+ disconnect();
+ }, [setSender, setActiveSenderWallet, setActiveSenderAccount]);
+
+ useEffect(() => {
+ if (needSwitchNetwork) {
+ switchNetworkAsync?.(sourceChain.id)
+ .then((res) => {
+ console.log(res);
+ })
+ .catch((err) => {
+ console.log("switch chain", err);
+ handleDisconnect();
+ setSwitchWallet(true);
+ });
+ }
+ }, [sourceChain, chain, switchNetworkAsync]);
+
+ useEffect(() => {
+ window.addEventListener("click", () => {
+ setSubMenu(false);
+ });
+ }, []);
+
+ return (
+
+
{
+ e.stopPropagation();
+ handleToggleSubMenu();
+ }}
+ className="relative flex h-[36px] w-fit cursor-pointer items-center justify-center gap-[5px] rounded-[10px] bg-white px-[10px] duration-300 hover:shadow-lg"
+ >
+
+
+
{connectedAddress && toShortAdrress(connectedAddress.toString())}
+
+
+ {subMenu && (
+
+
+
+
+ {connectedAddress && toShortAdrress(connectedAddress.toString())}
+
+ {connectedAddress && (
+ <>
+
{
+ e.stopPropagation();
+ navigator.clipboard.writeText(connectedAddress.toString());
+ setCopied(true);
+ }}
+ className="block h-[18px] w-[18px] flex-shrink-0 bg-[url('/images/icons/copy-icon.svg')] bg-contain bg-center bg-no-repeat"
+ />
+
+ Copied!
+
+ >
+ )}
+
+
+
+ {sourceAssetOptions.map((token) => (
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/src/components/appBox.tsx b/src/components/appBox.tsx
new file mode 100644
index 0000000..3904c5b
--- /dev/null
+++ b/src/components/appBox.tsx
@@ -0,0 +1,525 @@
+"use client";
+
+import { ChangeEventHandler, useCallback, useEffect, useMemo, useRef, useState } from "react";
+import data from "../data/data.json";
+import Image from "next/image";
+import ChainSelectInput, { chainType } from "./chainSelectInput";
+import SuccessModal from "./successModal";
+import PendingModal from "./pendingModal";
+import { formatBalance, getAssetIconSrc, isExceedingCrossChainLimit, isValidAddress, parseCross } from "@/utils";
+import { useTransfer } from "@/hooks";
+import { BN, BN_ZERO, bnToBn } from "@polkadot/util";
+import { formatUnits, parseUnits } from "viem";
+import { WalletID } from "@/types";
+import { useAccount, useNetwork, useSwitchNetwork } from "wagmi";
+import notification from "@/ui/notification";
+import { supportedTokenList } from "@/config/tokens";
+import { useTrail, animated, useSpring } from "@react-spring/web";
+import WalletSelectionModal from "./walletSelectionModal";
+
+export default function AppBox() {
+ const [connectModal, setConnectModal] = useState(false);
+
+ const { defaultSourceChainOptions, defaultSourceAssetOptions } = parseCross();
+ const [selectedAsset, setSelectedAsset] = useState(supportedTokenList[0]);
+ const [allowedChain, setAllowedChain] = useState([]);
+ // const [sourceAssetOptions, setSourceAssetOptions] = useState(defaultSourceAssetOptions);
+ const [successModal, setSuccessModal] = useState(false);
+
+ const {
+ sender,
+ setSender,
+ recipient,
+ setRecipient,
+ sourceAssetBalance,
+ sourceAsset,
+ setTargetAsset,
+ setTransferAmount,
+ transferAmount,
+ setSourceAsset,
+ bridgeInstance,
+ assetLimitOnTargetChain,
+ targetAssetSupply,
+ existentialDepositOnTargetChain,
+ sourceChain,
+ setSourceChain,
+ targetChain,
+ setTargetChain,
+ transfer,
+ activeSenderWallet,
+ updateSourceAssetBalance,
+ updateTargetAssetBalance,
+ updateTargetAssetSupply,
+ updateSourceNativeBalance,
+ updateTargetNativeBalance,
+ targetNativeBalance,
+ updateFeeBalanceOnSourceChain,
+ activeSenderAccount,
+ feeBalanceOnSourceChain,
+ sourceNativeBalance,
+ } = useTransfer();
+ const handleCloseSuccessModal = useCallback(() => {
+ setSuccessModal(false);
+ setTransferAmount({ valid: true, input: "", amount: BN_ZERO });
+ updateSourceAssetBalance();
+ updateTargetAssetBalance();
+ updateTargetAssetSupply();
+ updateSourceNativeBalance();
+ updateTargetNativeBalance();
+ updateFeeBalanceOnSourceChain();
+ }, []);
+
+ const sourceChainRef = useRef(sourceChain);
+ const targetChainRef = useRef(targetChain);
+
+ const cross = bridgeInstance?.getCrossInfo();
+ const assetLimit = assetLimitOnTargetChain?.amount;
+ const assetSupply = targetAssetSupply?.amount;
+
+ const min = useMemo(() => {
+ if (cross && cross.fee.asset.local.id === sourceAsset.id) {
+ return cross.fee.amount;
+ }
+ return undefined;
+ }, [cross, sourceAsset.id]);
+
+ const insufficient =
+ sourceAssetBalance?.amount && transferAmount?.input && sourceAssetBalance.amount.lt(transferAmount?.amount)
+ ? true
+ : false;
+ const requireMin = min && transferAmount?.input && transferAmount.amount.lt(min) ? true : false;
+ const requireLimit = isExcess(assetLimitOnTargetChain?.amount, targetAssetSupply?.amount, transferAmount?.amount);
+
+ const handleInputChange = useCallback>(
+ (e) => {
+ if (e.target.value) {
+ if (!Number.isNaN(Number(e.target.value)) && sourceAsset) {
+ setTransferAmount(
+ parseValue(e.target.value, sourceAsset.decimals, min, sourceAssetBalance?.amount, assetLimit, assetSupply),
+ );
+ }
+ } else {
+ setTransferAmount({ valid: true, input: e.target.value, amount: BN_ZERO });
+ }
+ },
+ [sourceAsset, min, sourceAssetBalance, assetLimit, assetSupply, setTransferAmount],
+ );
+
+ const senderAddressType = useMemo(() => sourceChain.addressType, [sourceChain]);
+
+ const handleSenderAddressChange = useCallback>(
+ (e) => {
+ const address = e.target.value;
+ const valid = address ? isValidAddress(address, senderAddressType) : true;
+ setSender({ valid, address });
+ },
+ [senderAddressType, setSender],
+ );
+
+ const recipientAddressType = useMemo(() => targetChain.addressType, [targetChain]);
+
+ const handleRecipientAddressChange = useCallback>(
+ (e) => {
+ const address = e.target.value;
+ const valid = address ? isValidAddress(address, recipientAddressType) : true;
+ setRecipient({ valid, address });
+ },
+ [recipientAddressType, setRecipient],
+ );
+
+ const { chain } = useNetwork();
+ const { switchNetwork } = useSwitchNetwork();
+ const { address } = useAccount();
+
+ const needSwitchNetwork = useMemo(
+ () => activeSenderWallet === WalletID.EVM && chain && chain.id !== sourceChain.id,
+ [chain, sourceChain, activeSenderWallet],
+ );
+
+ const [busy, setBusy] = useState(false);
+
+ const feeAlert = useMemo(() => {
+ const fee = bridgeInstance?.getCrossInfo()?.fee;
+ if (fee && feeBalanceOnSourceChain && fee.amount.gt(feeBalanceOnSourceChain.amount)) {
+ return (
+
+
+ {`You need at least ${formatBalance(
+ fee.amount,
+ feeBalanceOnSourceChain.currency.decimals,
+ )} ${feeBalanceOnSourceChain.currency.symbol} in your Sender on ${
+ sourceChainRef.current.name
+ } to cover cross-chain fees.`}
+
+ );
+ }
+ return null;
+ }, [bridgeInstance, feeBalanceOnSourceChain]);
+
+ // console.log("fee alert", feeAlert);
+
+ const existentialAlertOnSourceChain = useMemo(() => {
+ if (
+ sourceChain.existential &&
+ sourceNativeBalance &&
+ sourceNativeBalance.amount.lt(sourceChain.existential.minBalance)
+ ) {
+ return (
+
+
+ {`You need at least ${formatBalance(
+ sourceChain.existential.minBalance,
+ sourceChain.nativeCurrency.decimals,
+ )} ${sourceChain.nativeCurrency.symbol} in your Sender on ${
+ sourceChain.name
+ } to keep an account alive.`}
+
+ );
+ }
+ return null;
+ }, [
+ sourceChain.existential,
+ sourceChain.name,
+ sourceChain.nativeCurrency.decimals,
+ sourceChain.nativeCurrency.symbol,
+ sourceNativeBalance,
+ ]);
+
+ const existentialAlertOnTargetChain = useMemo(() => {
+ if (
+ targetNativeBalance &&
+ existentialDepositOnTargetChain &&
+ targetNativeBalance.amount.lt(existentialDepositOnTargetChain.amount)
+ ) {
+ return (
+
+
+ {`You need at least ${formatBalance(
+ existentialDepositOnTargetChain.amount,
+ existentialDepositOnTargetChain.currency.decimals,
+ )} ${existentialDepositOnTargetChain.currency.symbol} in your Recipient on ${
+ targetChainRef.current.name
+ } to keep an account open.`}
+
+ );
+ }
+ return null;
+ }, [targetNativeBalance, existentialDepositOnTargetChain]);
+
+ const disabledSend =
+ !sender?.address ||
+ !sender.valid ||
+ !recipient?.address ||
+ !recipient?.valid ||
+ !transferAmount.input ||
+ !transferAmount.valid ||
+ !!feeAlert ||
+ !!existentialAlertOnSourceChain ||
+ !!existentialAlertOnTargetChain;
+
+ // console.log(
+ // "check this now",
+ // sender?.address,
+ // sender?.valid,
+ // recipient?.address,
+ // recipient?.valid,
+ // transferAmount.input,
+ // transferAmount.valid,
+ // feeAlert,
+ // existentialAlertOnSourceChain,
+ // existentialAlertOnTargetChain,
+ // );
+
+ const handleSend = useCallback(async () => {
+ if (needSwitchNetwork) {
+ switchNetwork?.(sourceChain.id);
+ } else if (bridgeInstance && recipient) {
+ const callback = {
+ successCb: () => {
+ setBusy(false);
+ setSuccessModal(true);
+ },
+ failedCb: () => {
+ setBusy(false);
+ },
+ };
+ const sender_ = activeSenderAccount ?? (address && sender?.address === address ? address : undefined);
+ setBusy(true);
+ if (await isExceedingCrossChainLimit(bridgeInstance, transferAmount.input)) {
+ notification.error({ title: "Transaction failed", description: "Exceeding the cross-chain limit." });
+ updateTargetAssetSupply();
+ setBusy(false);
+ } else if (sender_) {
+ await transfer(bridgeInstance, sender_, recipient.address, transferAmount.amount, callback);
+ }
+ } else {
+ notification.warn({ title: "Oops!", description: "Failed to construct bridge." });
+ }
+ }, [
+ activeSenderAccount,
+ address,
+ bridgeInstance,
+ needSwitchNetwork,
+ recipient,
+ sender?.address,
+ setTransferAmount,
+ sourceChain.id,
+ switchNetwork,
+ transfer,
+ transferAmount.amount,
+ transferAmount.input,
+ updateFeeBalanceOnSourceChain,
+ updateSourceAssetBalance,
+ updateTargetAssetBalance,
+ updateTargetAssetSupply,
+ updateSourceNativeBalance,
+ updateTargetNativeBalance,
+ ]);
+
+ useEffect(() => {
+ console.log("defaultSourceAssetOptions", sourceChain.assets);
+ let sourceChainOptions: any = [];
+ for (const item of selectedAsset.allowedSource) {
+ for (const chain of defaultSourceChainOptions) {
+ if (chain.name === item) {
+ sourceChainOptions.push(chain);
+ }
+ }
+ }
+ let selectedSourceAsset;
+ for (const item of sourceChainOptions[0].assets) {
+ if (selectedAsset.icon === item.icon) {
+ selectedSourceAsset = item;
+ }
+ }
+ setAllowedChain([...sourceChainOptions]);
+ setSourceChain(sourceChainOptions[0]);
+ setSourceAsset(selectedSourceAsset);
+ setTargetChain(sourceChainOptions[1]);
+ }, [selectedAsset]);
+
+ useEffect(() => {
+ console.log(allowedChain);
+ if (allowedChain.length > 0) {
+ if (sourceChain.name === allowedChain[0].name && targetChain.name === allowedChain[0].name) {
+ setTargetChain(allowedChain[1]);
+ } else if (sourceChain.name === allowedChain[1].name && targetChain.name === allowedChain[1].name) {
+ setTargetChain(allowedChain[0]);
+ }
+ }
+ for (const asset of sourceChain.assets) {
+ if (selectedAsset.name === asset.name) setSourceAsset(asset);
+ }
+ }, [sourceChain]);
+
+ useEffect(() => {
+ if (allowedChain.length > 0) {
+ if (targetChain.name === allowedChain[0].name && sourceChain.name == allowedChain[0].name) {
+ setSourceChain(allowedChain[1]);
+ } else if (targetChain.name === allowedChain[1].name && sourceChain.name === allowedChain[1].name) {
+ setSourceChain(allowedChain[0]);
+ }
+ }
+ for (const asset of targetChain.assets) {
+ if (selectedAsset.name === asset.name) setTargetAsset(asset);
+ }
+ }, [targetChain]);
+
+ const trails = useTrail(5, {
+ from: { transform: "translateX(-100%)", opacity: 0 },
+ to: { opacity: 1, transform: "translateX(0)" },
+ });
+
+ const style = useSpring({
+ from: { opacity: 0, transform: "translateY(-100%)" },
+ to: { opacity: 1, transform: "translateY(0)" },
+ });
+
+ // console.log("check this.................", sender, needSwitchNetwork, disabledSend);
+
+ return (
+ <>
+
+
+
+
+ {supportedTokenList.map((item: any) => (
+
{
+ setSelectedAsset(item);
+ }}
+ >
+
+
{item.name}
+
+ ))}
+
+
+
+
+ {sender ? (
+
+ ) : (
+ {
+ setConnectModal(true);
+ }}
+ className="mt-auto h-[24px] w-fit text-[14px] font-bold text-[#FF0083]"
+ >
+ Connect Wallet
+
+ )}
+
+
+
+
+
+
+
+
+
+
+ {
+ if (sourceAssetBalance?.amount && assetSupply) {
+ if (assetLimit && assetSupply.gte(assetLimit)) {
+ setTransferAmount({ valid: !(min && min.gt(BN_ZERO)), input: "0", amount: BN_ZERO });
+ } else if (assetLimit) {
+ const remaining = assetLimit.sub(assetSupply);
+ const amount = remaining.lte(sourceAssetBalance?.amount) ? remaining : sourceAssetBalance?.amount;
+ const input = formatUnits(BigInt(amount.toString()), sourceAsset.decimals);
+ setTransferAmount({ valid: !(min && min.gt(amount)), input, amount });
+ } else {
+ setTransferAmount({
+ amount: sourceAssetBalance?.amount,
+ valid: !(min && min.gt(sourceAssetBalance?.amount)),
+ input: formatUnits(BigInt(sourceAssetBalance?.amount.toString()), sourceAsset.decimals),
+ });
+ }
+ } else {
+ setTransferAmount({ valid: !(min && min.gt(BN_ZERO)), input: "0", amount: BN_ZERO });
+ }
+ }}
+ className="duration-300s h-[26px] w-fit flex-shrink-0 rounded-[5px] bg-[#FF00831A] px-[15px] text-[12px] font-bold text-[#FF0083] hover:shadow-lg"
+ >
+ Max
+
+
+
+ {sourceAssetBalance && (
+
+ Balance: {formatBalance(sourceAssetBalance.amount, sourceAsset.decimals)} {sourceAsset.name}
+
+ )}
+ {requireLimit ? (
+
+ {`* Limit: ${formatBalance(assetLimit ?? BN_ZERO, sourceAsset?.decimals ?? 0)}, supply: ${formatBalance(
+ (assetSupply ?? BN_ZERO).add(transferAmount?.amount ?? BN_ZERO),
+ sourceAsset?.decimals ?? 0,
+ )}.`}
+
+ ) : requireMin ? (
+
+ {`* At least ${formatBalance(min ?? BN_ZERO, sourceAsset?.decimals ?? 0)} ${
+ sourceAsset.symbol
+ } for tx fee.`}
+
+ ) : insufficient ? (
+ * Insufficient.
+ ) : null}
+
+ {feeAlert}
+ {existentialAlertOnSourceChain}
+ {existentialAlertOnTargetChain}
+
+
+ Send
+
+
+
+
+
+
+ {
+ setConnectModal(false);
+ }}
+ />
+ >
+ );
+}
+
+function parseValue(origin: string, decimals: number, min?: BN, max?: BN, limit?: BN, supply?: BN) {
+ let input = "";
+ let amount = BN_ZERO;
+ const [i, d] = origin.split(".").concat("-1");
+ if (i) {
+ input = d === "-1" ? i : d ? `${i}.${d.slice(0, decimals)}` : `${i}.`;
+ amount = bnToBn(parseUnits(input, decimals));
+ }
+ const valid =
+ min && amount.lt(min) ? false : max && amount.gt(max) ? false : isExcess(limit, supply, amount) ? false : true;
+ return { input, amount, valid };
+}
+
+function isExcess(limit?: BN, supply?: BN, amount = BN_ZERO) {
+ return limit && supply && supply.add(amount).gt(limit) ? true : false;
+}
diff --git a/src/components/chainButton.tsx b/src/components/chainButton.tsx
new file mode 100644
index 0000000..086c421
--- /dev/null
+++ b/src/components/chainButton.tsx
@@ -0,0 +1,80 @@
+import { useCallback, useEffect, useRef, useState } from "react";
+import Image from "next/image";
+import { useTransfer } from "@/hooks";
+import { getChainLogoSrc, parseCross } from "@/utils";
+import { Asset, ChainConfig, WalletID } from "@/types";
+import data from "../data/data.json";
+
+export default function ChainButton() {
+ const { sourceChain, setSourceChain } = useTransfer();
+ const { defaultSourceChainOptions } = parseCross();
+ const [sourceChainOptions, _setSourceChainOptions] = useState([
+ ...defaultSourceChainOptions,
+ ...data.otherChains,
+ ]);
+
+ const sourceChainRef = useRef(sourceChain);
+
+ const _setSourceChain = useCallback(
+ (chain: ChainConfig | undefined) => {
+ setSourceChain((prev) => chain ?? prev);
+ sourceChainRef.current = chain ?? sourceChainRef.current;
+ },
+ [setSourceChain],
+ );
+
+ const [subMenu, setSubMenu] = useState(false);
+ const handleToggleSubMenu = useCallback(() => {
+ setSubMenu(!subMenu);
+ }, [subMenu]);
+
+ useEffect(() => {
+ window.addEventListener("click", () => {
+ console.log("hi");
+ setSubMenu(false);
+ });
+ }, []);
+
+ return (
+
+
{
+ e.stopPropagation();
+ handleToggleSubMenu();
+ }}
+ >
+
+
+ {sourceChain.name.includes("Polkadot") ? sourceChain.name.replace(" AssetHub", "") : sourceChain.name}
+
+
+
+
+
+ {sourceChainOptions.map((chain) => (
+
{
+ if (chain.id !== undefined) {
+ _setSourceChain(chain);
+ setSubMenu(false);
+ }
+ }}
+ >
+
+
+ {chain.name.includes("Polkadot") ? chain.name.replace(" AssetHub", "") : chain.name}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/src/components/chainSelectInput.tsx b/src/components/chainSelectInput.tsx
new file mode 100644
index 0000000..1482b3a
--- /dev/null
+++ b/src/components/chainSelectInput.tsx
@@ -0,0 +1,116 @@
+"use clients";
+
+import Image from "next/image";
+import data from "../data/data.json";
+import { useCallback, useEffect, useRef, useState } from "react";
+import { useTransfer } from "@/hooks";
+import { getChainLogoSrc, parseCross } from "@/utils";
+import { Asset, ChainConfig } from "@/types";
+
+export interface chainType {
+ name: string;
+ logo: string;
+}
+
+export default function ChainSelectInput({ who, options }: { who: string; options: [any] }) {
+ const { sourceChain, setSourceChain, sourceAsset, setTargetChain, setSourceAsset, targetChain } = useTransfer();
+ const {
+ defaultSourceChainOptions,
+ defaultTargetChainOptions,
+ availableTargetChainOptions,
+ availableSourceAssetOptions,
+ defaultSourceAssetOptions,
+ } = parseCross();
+ const [sourceChainOptions, _setSourceChainOptions] = useState(defaultSourceChainOptions);
+ const [sourceAssetOptions, setSourceAssetOptions] = useState(defaultSourceAssetOptions);
+ const [targetChainOptions, setTargetChainOptions] = useState(defaultTargetChainOptions);
+
+ const targetChainRef = useRef(targetChain);
+ const sourceAssetRef = useRef(sourceAsset);
+ const sourceChainRef = useRef(sourceChain);
+
+ const _setTargetChain = useCallback(
+ (chain: ChainConfig | undefined) => {
+ setTargetChain((prev) => chain ?? prev);
+ targetChainRef.current = chain ?? targetChainRef.current;
+ },
+ [setTargetChain],
+ );
+
+ // useEffect(() => {
+ // const options = availableTargetChainOptions[sourceChain.network]?.[sourceAsset.symbol] || [];
+ // setTargetChainOptions(options);
+ // _setTargetChain(options.at(0));
+ // }, [sourceChain, sourceAsset, _setTargetChain]);
+
+ const _setSourceChain = useCallback(
+ (chain: ChainConfig | undefined) => {
+ setSourceChain((prev) => chain ?? prev);
+ sourceChainRef.current = chain ?? sourceChainRef.current;
+ },
+ [setSourceChain],
+ );
+
+ // const _setSourceAsset = useCallback(
+ // (asset: Asset | undefined) => {
+ // setSourceAsset((prev) => asset ?? prev);
+ // sourceAssetRef.current = asset ?? sourceAssetRef.current;
+ // },
+ // [setSourceAsset],
+ // );
+
+ // useEffect(() => {
+ // const options = availableSourceAssetOptions[sourceChain.network] || [];
+ // setSourceAssetOptions(options);
+ // _setSourceAsset(options.at(0));
+ // }, [sourceChain, _setSourceAsset]);
+ const [open, setOpen] = useState(false);
+
+ const name = "Polkadot AssetHub";
+ return (
+ {
+ setOpen(!open);
+ }}
+ >
+
+
+
+ {who === "sender"
+ ? sourceChain.name.includes("Polkadot")
+ ? sourceChain.name.replace(" AssetHub", "")
+ : sourceChain.name
+ : targetChain.name.includes("Polkadot")
+ ? targetChain.name.replace(" AssetHub", "")
+ : targetChain.name}
+
+
+
+
+
+ {options.map((item) => (
+
_setSourceChain(item) : () => _setTargetChain(item)}
+ >
+
+
+ {item.name.includes("Polkadot") ? item.name.replace(" AssetHub", "") : item.name}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/src/components/disconnetButton.tsx b/src/components/disconnetButton.tsx
new file mode 100644
index 0000000..c4267c2
--- /dev/null
+++ b/src/components/disconnetButton.tsx
@@ -0,0 +1,14 @@
+export default function DisconnectButton({ handleDisconnect }: { handleDisconnect: () => void }) {
+ return (
+ {
+ e.stopPropagation();
+ handleDisconnect();
+ }}
+ className="flex h-[28px] w-full items-center justify-center gap-[10px] rounded-[10px] bg-[#FF00831A] duration-200 hover:shadow-lg"
+ >
+
+ Disconnect
+
+ );
+}
diff --git a/src/components/footer.tsx b/src/components/footer.tsx
index 7685d08..d06b3e1 100644
--- a/src/components/footer.tsx
+++ b/src/components/footer.tsx
@@ -1,39 +1,22 @@
-import Image from "next/image";
-import { PropsWithChildren } from "react";
+import Link from "next/link";
+import data from "../data/data.json";
export default function Footer() {
return (
-
-
-
{`© ${new Date().getFullYear()} Darwinia Network`}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ @ 2024 Paralink powerd by Darwinia Network
+
+
+ {data.social.map((item: any) => (
+
+
+
+ ))}
-
- );
-}
-
-function SocialLink({ children, href }: PropsWithChildren<{ href: string }>) {
- return (
-
- {children}
-
+
);
}
diff --git a/src/components/header.tsx b/src/components/header.tsx
index 6a45158..3caf248 100644
--- a/src/components/header.tsx
+++ b/src/components/header.tsx
@@ -1,14 +1,134 @@
+"use client";
+
import Image from "next/image";
import Link from "next/link";
+import { useCallback, useEffect, useState } from "react";
+import data from "../data/data.json";
+import WalletButton from "./walletButton";
+import AccountButton from "./accountButton";
+import ChainButton from "./chainButton";
+import { useAccount, useChainId } from "wagmi";
+import { useTalisman, useTransfer } from "@/hooks";
+import { isValidAddress, parseCross } from "@/utils";
+import WalletSelectionModal from "./walletSelectionModal";
+import { WalletID } from "@/types";
export default function Header() {
+ const [connectModal, setConnectModal] = useState(false);
+ const [connected, setConnected] = useState(false);
+ const { address: activeAddress } = useAccount();
+ const { talismanAccounts, connectTalisman } = useTalisman();
+ const { activeSenderWallet, setSender, sourceChain, sender } = useTransfer();
+ const [switchWallet, setSwitchWallet] = useState
(false);
+
+ console.log(talismanAccounts);
+
+ const handleClose = useCallback(() => {
+ setConnectModal(false);
+ setSwitchWallet(false);
+ }, []);
+
+ const [showMenu, setShowMenu] = useState(false);
+
+ const handleOpenMenu = useCallback(() => {
+ setShowMenu(true);
+ }, []);
+
+ const handleCloseMenu = useCallback(() => {
+ setShowMenu(false);
+ }, []);
+
+ const senderOptions =
+ activeSenderWallet === WalletID.EVM && activeAddress
+ ? [{ address: activeAddress }]
+ : activeSenderWallet === WalletID.TALISMAN
+ ? talismanAccounts
+ : [];
+
+ useEffect(() => {
+ if ((activeAddress || talismanAccounts.length > 0) && activeSenderWallet) {
+ setConnected(true);
+ if (senderOptions.length > 0) {
+ const address = senderOptions[0].address;
+ const valid = address ? isValidAddress(address, sourceChain.addressType) : true;
+ setSender({ valid, address });
+ }
+ } else {
+ setConnected(false);
+ setSender(undefined);
+ }
+ }, [activeAddress, talismanAccounts.length, activeSenderWallet]);
+
return (
-
-
+
+ {!connected ? (
+
+ setConnectModal(true)} />
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {!sender ? (
+
{
+ handleCloseMenu();
+ setConnectModal(true);
+ }}
+ />
+ ) : (
+
+ )}
+
+
+ {data.social.map((item: any) => (
+
+
+
+ ))}
+
+
+
+
+
);
}
diff --git a/src/components/pendingModal.tsx b/src/components/pendingModal.tsx
new file mode 100644
index 0000000..2aab8fd
--- /dev/null
+++ b/src/components/pendingModal.tsx
@@ -0,0 +1,33 @@
+import { useTrail, animated } from "@react-spring/web";
+import Image from "next/image";
+
+export default function PendingModal({ visible }: { visible: boolean }) {
+ const trails = useTrail(2, {
+ from: { transform: "translateX(-100%)", opacity: 0 },
+ to: { opacity: visible ? 1 : 0, transform: visible ? "translateX(0)" : "translateX(-100%)" },
+ });
+ return (
+ <>
+ {visible && (
+
+
+
+
+
+
+
+ Transaction is being Processed
+
+
+
+
+ )}
+ >
+ );
+}
diff --git a/src/components/successModal.tsx b/src/components/successModal.tsx
new file mode 100644
index 0000000..f77c0ae
--- /dev/null
+++ b/src/components/successModal.tsx
@@ -0,0 +1,45 @@
+import { useTransfer } from "@/hooks";
+import { formatBalance } from "@/utils";
+import Image from "next/image";
+import { useTrail, animated } from "@react-spring/web";
+
+export default function SuccessModal({ visible, onClose }: { visible: boolean; onClose: () => void }) {
+ const { sourceAsset, transferAmount } = useTransfer();
+
+ const trails = useTrail(3, {
+ from: { transform: "translateX(-100%)", opacity: 0 },
+ to: { opacity: visible ? 1 : 0, transform: visible ? "translateX(0)" : "translateX(-100%)" },
+ });
+ return (
+ <>
+ {visible && (
+
+
+
+
+
+
+
+ Success !
+
+ You send {formatBalance(transferAmount.amount, sourceAsset.decimals)} {sourceAsset.name}
+
+
+
+
+ OK
+
+
+ Detail
+
+
+
+
+
+ )}
+ >
+ );
+}
diff --git a/src/components/walletButton.tsx b/src/components/walletButton.tsx
new file mode 100644
index 0000000..5d98a5f
--- /dev/null
+++ b/src/components/walletButton.tsx
@@ -0,0 +1,135 @@
+import { useCallback, useEffect, useRef, useState } from "react";
+import WalletSelectionModal from "./walletSelectionModal";
+import { useTransfer } from "@/hooks";
+import { getChainLogoSrc, parseCross } from "@/utils";
+import { ChainConfig } from "@/types";
+import Image from "next/image";
+import data from "../data/data.json";
+
+export default function WalletButton({ openModal }: { openModal: () => void }) {
+ const [subMenu, setSubMenu] = useState
(false);
+ const [tab, setTab] = useState("evm");
+ const { sourceChain, setSourceChain } = useTransfer();
+ const { defaultSourceChainOptions } = parseCross();
+ const [sourceChainOptions, _setSourceChainOptions] = useState([...defaultSourceChainOptions]);
+
+ const sourceChainRef = useRef(sourceChain);
+
+ const _setSourceChain = useCallback(
+ (chain: ChainConfig | undefined) => {
+ setSourceChain((prev) => chain ?? prev);
+ sourceChainRef.current = chain ?? sourceChainRef.current;
+ },
+ [setSourceChain],
+ );
+
+ const handleToggleSubMenu = useCallback(() => {
+ setSubMenu(!subMenu);
+ }, [subMenu]);
+
+ useEffect(() => {
+ window.addEventListener("click", () => {
+ console.log("hi");
+ setSubMenu(false);
+ });
+ }, []);
+
+ console.log(subMenu);
+ return (
+
+
{
+ e.stopPropagation();
+ handleToggleSubMenu();
+ }}
+ className="flex h-[36px] w-[190px] cursor-pointer items-center gap-[5px] rounded-[10px] bg-white px-[10px] hover:shadow-lg lg:w-fit lg:justify-center"
+ >
+
+
Connect Wallet
+
+
{
+ e.stopPropagation();
+ }}
+ style={{ maxHeight: subMenu ? "100vh" : "0" }}
+ className="absolute right-0 top-[calc(100%+20px)] z-50 flex h-fit w-[500px] flex-col gap-[40px] overflow-hidden rounded-[10px] bg-white duration-700"
+ >
+
+ {sourceChainOptions.map((chain) => (
+
{
+ if (chain.id !== undefined) {
+ _setSourceChain(chain);
+ setSubMenu(false);
+ }
+ }}
+ >
+
+
+ {chain.name.includes("Polkadot") ? chain.name.replace(" AssetHub", "") : chain.name}
+
+
+ ))}
+
+
+
+
{
+ setTab("evm");
+ }}
+ className="-mb-[1px] w-[150px] cursor-pointer rounded-[10px_10px_0_0] p-[10px] text-center"
+ style={{
+ borderTop: tab === "evm" ? "1px solid #FF0083" : "none",
+ borderRight: tab === "evm" ? "1px solid #FF0083" : "none",
+ borderLeft: tab === "evm" ? "1px solid #FF0083" : "none",
+ borderBottom: "none",
+ backgroundColor: tab === "evm" ? "white" : "transparent",
+ }}
+ >
+ EVM wallet
+
+
{
+ setTab("substrate");
+ }}
+ className="-mb-[1px] w-[150px] cursor-pointer rounded-[10px_10px_0_0] p-[10px] text-center"
+ style={{
+ borderBottom: "none",
+ borderTop: tab === "substrate" ? "1px solid #FF0083" : "none",
+ borderRight: tab === "substrate" ? "1px solid #FF0083" : "none",
+ borderLeft: tab === "substrate" ? "1px solid #FF0083" : "none",
+ backgroundColor: tab === "substrate" ? "#fff" : "transparent",
+ }}
+ >
+ Substrate wallet
+
+
+
+ {data.wallets[tab === "evm" ? "evm" : "substrate"].map((item: any) => (
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/src/components/walletSelectionModal.tsx b/src/components/walletSelectionModal.tsx
new file mode 100644
index 0000000..d544d68
--- /dev/null
+++ b/src/components/walletSelectionModal.tsx
@@ -0,0 +1,121 @@
+"use client";
+
+import { useTalisman, useTransfer } from "@/hooks";
+import { WalletID } from "@/types";
+import { isValidAddress } from "@/utils";
+import { useConnectModal } from "@rainbow-me/rainbowkit";
+import Image from "next/image";
+import { useEffect, useMemo } from "react";
+import { useAccount } from "wagmi";
+
+export default function WalletSelectionModal({
+ visible,
+ onClose,
+ switchWallet,
+}: {
+ visible: boolean;
+ onClose: () => void;
+ switchWallet?: boolean;
+}) {
+ const { talismanAccounts, connectTalisman } = useTalisman();
+ const { openConnectModal } = useConnectModal();
+
+ const {
+ sender,
+ sourceChain,
+ targetChain,
+ activeSenderWallet,
+ activeRecipientWallet,
+ setSender,
+ setActiveSenderAccount,
+ setActiveRecipientAccount,
+ setActiveSenderWallet,
+ setActiveRecipientWallet,
+ } = useTransfer();
+
+ const { address } = useAccount();
+
+ const [supportedWalletEvm, supportedWalletTalisman] = useMemo(() => {
+ return [
+ sourceChain.wallets.some((id) => id === WalletID.EVM),
+ sourceChain.wallets.some((id) => id === WalletID.TALISMAN),
+ ];
+ }, [sourceChain.wallets]);
+
+ const senderOptions =
+ activeSenderWallet === WalletID.EVM && address
+ ? [{ address }]
+ : activeSenderWallet === WalletID.TALISMAN
+ ? talismanAccounts
+ : [];
+
+ // useEffect(() => {
+ // if (activeSenderWallet) {
+ // const address = senderOptions[0].address;
+ // const valid = address ? isValidAddress(address, sourceChain.addressType) : true;
+ // setSender({ valid, address });
+ // }
+ // }, [activeSenderWallet]);
+ return (
+ <>
+ {visible && (
+
+
+
+
+ {switchWallet
+ ? "The selected source chain is not supported by current wallet, please change you wallet"
+ : "Select a wallet Type"}
+
+
+ {
+ setActiveSenderWallet(WalletID.TALISMAN);
+ connectTalisman();
+ onClose();
+ }}
+ >
+
+ Talisman
+
+ {
+ setActiveSenderWallet(WalletID.EVM);
+ openConnectModal?.();
+ onClose();
+ }}
+ >
+
+ EVM wallets
+
+
+
+
+ Cancel
+
+
+
+
+ )}
+ >
+ );
+}
diff --git a/src/config/chains/assethub-polkadot-chain.ts b/src/config/chains/assethub-polkadot-chain.ts
index 12cf260..933be1f 100644
--- a/src/config/chains/assethub-polkadot-chain.ts
+++ b/src/config/chains/assethub-polkadot-chain.ts
@@ -95,6 +95,36 @@ export const assethubPolkadotChain: ChainConfig = {
},
],
},
+ {
+ icon: "dot.svg",
+ id: 23,
+ name: "DOT",
+ symbol: "DOT",
+ decimals: 10,
+ origin: {
+ parachainId: ParachainID.ASSETHUB_POLKADOT,
+ palletInstance: 50,
+ id: 23,
+ },
+ cross: [
+ {
+ target: { network: "darwinia", symbol: "DOT" },
+ fee: {
+ amount: bnToBn(20000),
+ asset: {
+ local: { id: 1984 },
+ origin: {
+ parachainId: ParachainID.ASSETHUB_POLKADOT,
+ palletInstance: 50,
+ id: 1984,
+ },
+ },
+ },
+ section: "polkadotXcm",
+ method: "limitedReserveTransferAssets",
+ },
+ ],
+ },
],
wallets: [WalletID.TALISMAN],
addressType: "substrate",
diff --git a/src/config/chains/darwinia-chain.ts b/src/config/chains/darwinia-chain.ts
index 0c4aa21..ff6e933 100644
--- a/src/config/chains/darwinia-chain.ts
+++ b/src/config/chains/darwinia-chain.ts
@@ -125,6 +125,36 @@ export const darwiniaChain: ChainConfig = {
},
],
},
+ {
+ icon: "dot.svg",
+ id: 1028,
+ name: "DOT",
+ symbol: "DOT",
+ decimals: 10,
+ origin: {
+ parachainId: ParachainID.ASSETHUB_POLKADOT,
+ palletInstance: 50,
+ id: 23,
+ },
+ cross: [
+ {
+ target: { network: "assethub-polkadot", symbol: "PINK" },
+ fee: {
+ amount: bnToBn(700000),
+ asset: {
+ local: { id: 1027 },
+ origin: {
+ parachainId: ParachainID.ASSETHUB_POLKADOT,
+ palletInstance: 50,
+ id: 1984,
+ },
+ },
+ },
+ section: "xTokens",
+ method: "transferMultiassets",
+ },
+ ],
+ },
],
wallets: [WalletID.EVM, WalletID.TALISMAN],
addressType: "evm",
diff --git a/src/config/tokens/index.ts b/src/config/tokens/index.ts
new file mode 100644
index 0000000..a417e7b
--- /dev/null
+++ b/src/config/tokens/index.ts
@@ -0,0 +1,22 @@
+export const supportedTokenList = [
+ {
+ name: "USDT",
+ icon: "usdt.svg",
+ allowedSource: ["Darwinia", "Polkadot AssetHub"],
+ },
+ {
+ name: "RING",
+ icon: "ring.png",
+ allowedSource: ["Darwinia", "Hydration"],
+ },
+ {
+ name: "PINK",
+ icon: "pink.jpg",
+ allowedSource: ["Darwinia", "Polkadot AssetHub"],
+ },
+ {
+ name: "DOT",
+ icon: "dot.svg",
+ allowedSource: ["Darwinia", "Polkadot AssetHub"],
+ },
+];
diff --git a/src/data/data.json b/src/data/data.json
new file mode 100644
index 0000000..feca8cc
--- /dev/null
+++ b/src/data/data.json
@@ -0,0 +1,111 @@
+{
+ "tokens": [
+ {
+ "name": "USDT",
+ "icon": "/images/icons/usdt-icon.svg",
+ "balance": "449.385"
+ },
+ {
+ "name": "RING",
+ "icon": "/images/icons/ring-icon.svg",
+ "balance": "449.371"
+ },
+ {
+ "name": "PINK",
+ "icon": "/images/icons/pink-icon.png",
+ "balance": "449.371"
+ }
+ ],
+ "chains": [
+ {
+ "name": "AssetHub",
+ "logo": "/images/icons/assethub-icon.svg"
+ },
+ {
+ "name": "Darwinia",
+ "logo": "/images/icons/darwinia-icon.svg"
+ },
+ {
+ "name": "Hydration",
+ "logo": "/images/icons/hydration-icon.svg"
+ }
+ ],
+ "social": [
+ {
+ "name": "x",
+ "url": "https://twitter.com/DarwiniaNetwork",
+ "icon": "/images/icons/x-icon.svg"
+ },
+ {
+ "name": "telegram",
+ "url": "https://t.me/DarwiniaNetwork",
+ "icon": "/images/icons/telegram-icon.svg"
+ },
+ {
+ "name": "github",
+ "url": "https://github.com/darwinia-network",
+ "icon": "/images/icons/github-icon.svg"
+ },
+ {
+ "name": "email",
+ "url": "mailto:hello@darwinia.network",
+ "icon": "/images/icons/email-icon.svg"
+ }
+ ],
+ "otherChains": [
+ {
+ "name": "Astar",
+ "logo": "astar.svg"
+ },
+ {
+ "name": "Bifrost",
+ "logo": "bifrost.svg"
+ },
+ {
+ "name": "Centrufuge",
+ "logo": "centrufuge.svg"
+ }
+ ],
+ "wallets": {
+ "evm": [
+ {
+ "name": "MetaMask",
+ "logo": "metamask.png"
+ },
+ {
+ "name": "Coinbase Wallet",
+ "logo": "coinbase.svg"
+ },
+ {
+ "name": "WalletConnect",
+ "logo": "wallet-connect.svg"
+ },
+ {
+ "name": "NovaWallet",
+ "logo": "nova.svg"
+ },
+ {
+ "name": "Talisman",
+ "logo": "talisman-red.svg"
+ },
+ {
+ "name": "Ronin Wallet",
+ "logo": "ronin.svg"
+ }
+ ],
+ "substrate": [
+ {
+ "name": "Polkadot",
+ "logo": "polkadot.png"
+ },
+ {
+ "name": "SubWallet",
+ "logo": "sub-wallet.png"
+ },
+ {
+ "name": "Talisman",
+ "logo": "talisman-red.svg"
+ }
+ ]
+ }
+}
diff --git a/src/components/address-identicon.tsx b/src/old_components/address-identicon.tsx
similarity index 100%
rename from src/components/address-identicon.tsx
rename to src/old_components/address-identicon.tsx
diff --git a/src/components/address-input.tsx b/src/old_components/address-input.tsx
similarity index 100%
rename from src/components/address-input.tsx
rename to src/old_components/address-input.tsx
diff --git a/src/components/asset-select.tsx b/src/old_components/asset-select.tsx
similarity index 100%
rename from src/components/asset-select.tsx
rename to src/old_components/asset-select.tsx
diff --git a/src/components/balance-input.tsx b/src/old_components/balance-input.tsx
similarity index 100%
rename from src/components/balance-input.tsx
rename to src/old_components/balance-input.tsx
diff --git a/src/components/chain-select.tsx b/src/old_components/chain-select.tsx
similarity index 100%
rename from src/components/chain-select.tsx
rename to src/old_components/chain-select.tsx
diff --git a/src/components/confirm-send-modal.tsx b/src/old_components/confirm-send-modal.tsx
similarity index 100%
rename from src/components/confirm-send-modal.tsx
rename to src/old_components/confirm-send-modal.tsx
diff --git a/src/components/connect-wallet.tsx b/src/old_components/connect-wallet.tsx
similarity index 100%
rename from src/components/connect-wallet.tsx
rename to src/old_components/connect-wallet.tsx
diff --git a/src/components/evm-identicon.tsx b/src/old_components/evm-identicon.tsx
similarity index 100%
rename from src/components/evm-identicon.tsx
rename to src/old_components/evm-identicon.tsx
diff --git a/src/old_components/footer.tsx b/src/old_components/footer.tsx
new file mode 100644
index 0000000..7685d08
--- /dev/null
+++ b/src/old_components/footer.tsx
@@ -0,0 +1,39 @@
+import Image from "next/image";
+import { PropsWithChildren } from "react";
+
+export default function Footer() {
+ return (
+
+
+
{`© ${new Date().getFullYear()} Darwinia Network`}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function SocialLink({ children, href }: PropsWithChildren<{ href: string }>) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/old_components/header.tsx b/src/old_components/header.tsx
new file mode 100644
index 0000000..6a45158
--- /dev/null
+++ b/src/old_components/header.tsx
@@ -0,0 +1,14 @@
+import Image from "next/image";
+import Link from "next/link";
+
+export default function Header() {
+ return (
+
+ );
+}
diff --git a/src/components/input-alert.tsx b/src/old_components/input-alert.tsx
similarity index 100%
rename from src/components/input-alert.tsx
rename to src/old_components/input-alert.tsx
diff --git a/src/components/label.tsx b/src/old_components/label.tsx
similarity index 100%
rename from src/components/label.tsx
rename to src/old_components/label.tsx
diff --git a/src/components/page-wrap.tsx b/src/old_components/page-wrap.tsx
similarity index 100%
rename from src/components/page-wrap.tsx
rename to src/old_components/page-wrap.tsx
diff --git a/src/components/switch-cross.tsx b/src/old_components/switch-cross.tsx
similarity index 100%
rename from src/components/switch-cross.tsx
rename to src/old_components/switch-cross.tsx
diff --git a/src/components/transfer-section.tsx b/src/old_components/transfer-section.tsx
similarity index 100%
rename from src/components/transfer-section.tsx
rename to src/old_components/transfer-section.tsx
diff --git a/src/components/transfer.tsx b/src/old_components/transfer.tsx
similarity index 98%
rename from src/components/transfer.tsx
rename to src/old_components/transfer.tsx
index c4e4c73..34e24fa 100644
--- a/src/components/transfer.tsx
+++ b/src/old_components/transfer.tsx
@@ -253,11 +253,11 @@ export default function Transfer() {
updateTargetNativeBalance,
]);
- useEffect(() => {
- const options = availableSourceAssetOptions[sourceChain.network] || [];
- setSourceAssetOptions(options);
- _setSourceAsset(options.at(0));
- }, [sourceChain, _setSourceAsset]);
+ // useEffect(() => {
+ // const options = availableSourceAssetOptions[sourceChain.network] || [];
+ // setSourceAssetOptions(options);
+ // _setSourceAsset(options.at(0));
+ // }, [sourceChain, _setSourceAsset]);
useEffect(() => {
const options = availableTargetChainOptions[sourceChain.network]?.[sourceAsset.symbol] || [];
diff --git a/src/ui/input-select.tsx b/src/ui/input-select.tsx
index 9792748..a81348d 100644
--- a/src/ui/input-select.tsx
+++ b/src/ui/input-select.tsx
@@ -14,7 +14,7 @@ import {
import Image from "next/image";
import { ChangeEventHandler, PropsWithChildren, ReactElement, useEffect, useRef } from "react";
import Input from "./input";
-import { InputAlert } from "@/components/input-alert";
+import { InputAlert } from "@/old_components/input-alert";
interface Props {
alert?: string;
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 1b93872..c6c9529 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -58,6 +58,17 @@ const config: Config = {
height: "16px",
},
},
+ bouncing: {
+ "0%": {
+ transform: "scale(1)",
+ },
+ "50%": {
+ transform: "scale(1.2)",
+ },
+ "100%": {
+ transform: "scale(1)",
+ },
+ },
},
animation: {
"notification-enter": "rightenter 400ms ease-out",
@@ -65,6 +76,7 @@ const config: Config = {
"notification-fadeout": "notificationfadeout 200ms ease-out forwards",
"count-loading-small": "countloadingsmall 1200ms cubic-bezier(0, 0.5, 0.5, 1) infinite",
"count-loading-large": "countloadinglarge 1200ms cubic-bezier(0, 0.5, 0.5, 1) infinite",
+ "pending-bounce": "bouncing 1.5s ease-in-out infinite",
},
},
},