From db67531b334bdc275771a48c638a2cec5256741f Mon Sep 17 00:00:00 2001 From: brentstone Date: Thu, 11 Dec 2025 19:41:53 -0800 Subject: [PATCH 1/4] remove duplicate imports --- package-lock.json | 514 +++++++++++++++++++++++++--------------------- package.json | 2 +- src/main.ts | 4 +- 3 files changed, 281 insertions(+), 239 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2bbb315..5e9d16c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "devDependencies": { "prettier": "^3.6.2", "typescript": "^5.9.2", - "vite": "^5.4.3" + "vite": "^7.2.7" } }, "node_modules/@adraffy/ens-normalize": { @@ -30,7 +30,6 @@ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -331,9 +330,9 @@ "license": "Apache-2.0" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", "cpu": [ "ppc64" ], @@ -344,13 +343,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", "cpu": [ "arm" ], @@ -361,13 +360,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", "cpu": [ "arm64" ], @@ -378,13 +377,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", "cpu": [ "x64" ], @@ -395,13 +394,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", "cpu": [ "arm64" ], @@ -412,13 +411,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", "cpu": [ "x64" ], @@ -429,13 +428,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", "cpu": [ "arm64" ], @@ -446,13 +445,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", "cpu": [ "x64" ], @@ -463,13 +462,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", "cpu": [ "arm" ], @@ -480,13 +479,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", "cpu": [ "arm64" ], @@ -497,13 +496,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", "cpu": [ "ia32" ], @@ -514,13 +513,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", "cpu": [ "loong64" ], @@ -531,13 +530,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", "cpu": [ "mips64el" ], @@ -548,13 +547,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", "cpu": [ "ppc64" ], @@ -565,13 +564,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", "cpu": [ "riscv64" ], @@ -582,13 +581,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", "cpu": [ "s390x" ], @@ -599,13 +598,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", "cpu": [ "x64" ], @@ -616,13 +615,30 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", "cpu": [ "x64" ], @@ -633,13 +649,30 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", "cpu": [ "x64" ], @@ -650,13 +683,30 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", "cpu": [ "x64" ], @@ -667,13 +717,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" ], @@ -684,13 +734,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", "cpu": [ "ia32" ], @@ -701,13 +751,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], @@ -718,7 +768,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@keplr-wallet/types": { @@ -1132,7 +1182,6 @@ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz", "integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://paulmillr.com/funding/" } @@ -1187,7 +1236,6 @@ "resolved": "https://registry.npmjs.org/@scure/starknet/-/starknet-1.1.0.tgz", "integrity": "sha512-83g3M6Ix2qRsPN4wqLDqiRZ2GBNbjVWfboJE/9UjfG+MHr6oDSu/CWgy8hsBSJejr09DkkL+l0Ze4KVrlCIdtQ==", "license": "MIT", - "peer": true, "dependencies": { "@noble/curves": "~1.7.0", "@noble/hashes": "~1.6.0" @@ -1201,7 +1249,6 @@ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", "license": "MIT", - "peer": true, "dependencies": { "@noble/hashes": "1.6.0" }, @@ -1217,7 +1264,6 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", "license": "MIT", - "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -1230,7 +1276,6 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", "license": "MIT", - "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -1410,7 +1455,6 @@ "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", "license": "MIT", - "peer": true, "dependencies": { "buffer": "~6.0.3" }, @@ -1423,7 +1467,6 @@ "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz", "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==", "license": "MIT", - "peer": true, "dependencies": { "@solana/errors": "2.3.0" }, @@ -1439,7 +1482,6 @@ "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz", "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==", "license": "MIT", - "peer": true, "dependencies": { "@solana/codecs-core": "2.3.0", "@solana/errors": "2.3.0" @@ -1456,7 +1498,6 @@ "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz", "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==", "license": "MIT", - "peer": true, "dependencies": { "chalk": "^5.4.1", "commander": "^14.0.0" @@ -1531,23 +1572,20 @@ "version": "0.7.10", "resolved": "https://registry.npmjs.org/@starknet-io/types-js/-/types-js-0.7.10.tgz", "integrity": "sha512-1VtCqX4AHWJlRRSYGSn+4X1mqolI1Tdq62IwzoU2vUuEE72S1OlEeGhpvd6XsdqXcfHmVzYfj8k1XtKBQqwo9w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@starknet-io/starknet-types-08": { "name": "@starknet-io/types-js", "version": "0.8.4", "resolved": "https://registry.npmjs.org/@starknet-io/types-js/-/types-js-0.8.4.tgz", "integrity": "sha512-0RZ3TZHcLsUTQaq1JhDSCM8chnzO4/XNsSCozwDET64JK5bjFDIf2ZUkta+tl5Nlbf4usoU7uZiDI/Q57kt2SQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@swc/helpers": { "version": "0.5.17", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.8.0" } @@ -1557,7 +1595,6 @@ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*" } @@ -1588,15 +1625,13 @@ "version": "8.3.4", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/ws": { "version": "7.4.7", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*" } @@ -1627,7 +1662,6 @@ "resolved": "https://registry.npmjs.org/abi-wan-kanabi/-/abi-wan-kanabi-2.2.4.tgz", "integrity": "sha512-0aA81FScmJCPX+8UvkXLki3X1+yPQuWxEkqXBVKltgPAK79J+NB+Lp5DouMXa7L6f+zcRlIA/6XO7BN/q9fnvg==", "license": "ISC", - "peer": true, "dependencies": { "ansicolors": "^0.3.2", "cardinal": "^2.1.1", @@ -1664,7 +1698,6 @@ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "license": "MIT", - "peer": true, "dependencies": { "humanize-ms": "^1.2.1" }, @@ -1677,7 +1710,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -1687,7 +1719,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -1702,8 +1733,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", @@ -1712,9 +1742,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -1727,7 +1757,6 @@ "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", "license": "MIT", - "peer": true, "dependencies": { "safe-buffer": "^5.0.1" } @@ -1778,7 +1807,6 @@ "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "bn.js": "^5.2.0", "bs58": "^4.0.0", @@ -1796,7 +1824,6 @@ "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", "license": "MIT", - "peer": true, "dependencies": { "base-x": "^3.0.2" } @@ -1820,7 +1847,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -1844,7 +1870,6 @@ "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", "license": "MIT", - "peer": true, "dependencies": { "ansicolors": "~0.3.2", "redeyed": "~2.1.0" @@ -1858,7 +1883,6 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "license": "MIT", - "peer": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -1871,7 +1895,6 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "license": "ISC", - "peer": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -1886,7 +1909,6 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", - "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -1898,8 +1920,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", @@ -1918,7 +1939,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", "license": "MIT", - "peer": true, "engines": { "node": ">=20" } @@ -1968,7 +1988,6 @@ "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -2024,8 +2043,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/es-define-property": { "version": "1.0.1", @@ -2076,23 +2094,21 @@ "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", "license": "MIT", - "peer": true, "dependencies": { "es6-promise": "^4.0.3" } }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2100,32 +2116,35 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, "node_modules/escalade": { @@ -2133,7 +2152,6 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -2143,7 +2161,6 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "license": "BSD-2-Clause", - "peer": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -2162,7 +2179,6 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", - "peer": true, "engines": { "node": "> 0.1.90" } @@ -2171,8 +2187,25 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, "license": "MIT", - "peer": true + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } }, "node_modules/follow-redirects": { "version": "1.15.11", @@ -2215,7 +2248,6 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -2254,7 +2286,6 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "license": "ISC", - "peer": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -2328,8 +2359,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/has-property-descriptors": { "version": "1.0.2", @@ -2408,7 +2438,6 @@ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.0.0" } @@ -2431,8 +2460,7 @@ "url": "https://feross.org/support" } ], - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/inherits": { "version": "2.0.4", @@ -2445,7 +2473,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -2479,7 +2506,6 @@ "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.2.0.tgz", "integrity": "sha512-VfJ9t1YLwacIubLhONk0KFeosUBwstRWQ0IRT1KDjEjnVnSOVHC3uwugyV7L0c7R9lpVyrUGT2XWiBA1UTtpyg==", "license": "MIT", - "peer": true, "dependencies": { "@types/connect": "^3.4.33", "@types/node": "^12.12.54", @@ -2505,22 +2531,19 @@ "version": "12.20.55", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jayson/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jayson/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "license": "MIT", - "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -2529,15 +2552,13 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/jsonfile": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "license": "MIT", - "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -2585,8 +2606,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-4.1.1.tgz", "integrity": "sha512-HusN80C0ohtT9kOHQH7EuUaqzRQsnekpa+2ot8OzvW0iC08dq/YtM/7uKwwajldQsCrHyC8q9fz3t3L+TmDltA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/math-intrinsics": { "version": "1.1.0", @@ -2634,8 +2654,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.11", @@ -2667,7 +2686,6 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", - "peer": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -2746,6 +2764,20 @@ "dev": true, "license": "ISC" }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -2848,7 +2880,6 @@ "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", "license": "MIT", - "peer": true, "dependencies": { "esprima": "~4.0.0" } @@ -2858,7 +2889,6 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -2908,7 +2938,6 @@ "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.1.3.tgz", "integrity": "sha512-I+kNjW0udB4Fetr3vvtRuYZJS0PcSPyyvBcH5sDdoV8DFs5E4W2pTr7aiMlKfPxANTClP9RlqCPolj9dd5MsEA==", "license": "LGPL-3.0-only", - "peer": true, "dependencies": { "@swc/helpers": "^0.5.11", "@types/uuid": "^8.3.4", @@ -2932,7 +2961,6 @@ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*" } @@ -2942,7 +2970,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "license": "MIT", - "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -2952,7 +2979,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -3004,7 +3030,6 @@ "resolved": "https://registry.npmjs.org/starknet/-/starknet-7.6.4.tgz", "integrity": "sha512-FB20IaLCDbh/XomkB+19f5jmNxG+RzNdRO7QUhm7nfH81UPIt2C/MyWAlHCYkbv2wznSEb73wpxbp9tytokTgQ==", "license": "MIT", - "peer": true, "dependencies": { "@noble/curves": "1.7.0", "@noble/hashes": "1.6.0", @@ -3026,7 +3051,6 @@ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", "license": "MIT", - "peer": true, "dependencies": { "@noble/hashes": "1.6.0" }, @@ -3042,7 +3066,6 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", "license": "MIT", - "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -3054,15 +3077,13 @@ "version": "2.2.5", "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/stream-json": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "stream-chain": "^2.2.5" } @@ -3081,7 +3102,6 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3096,7 +3116,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3109,7 +3128,6 @@ "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==", "license": "MIT", - "peer": true, "engines": { "node": ">=14.0.0" } @@ -3126,35 +3144,49 @@ "node_modules/text-encoding-utf-8": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", - "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==", - "peer": true + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/ts-mixer": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/typescript": { "version": "5.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3174,7 +3206,6 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "license": "MIT", - "peer": true, "engines": { "node": ">= 10.0.0" } @@ -3218,6 +3249,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@noble/curves": "1.9.6", "@noble/hashes": "1.8.0", @@ -3274,21 +3306,24 @@ } }, "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", + "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -3297,19 +3332,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -3330,6 +3371,12 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, @@ -3337,15 +3384,13 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", - "peer": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -3356,7 +3401,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3374,6 +3418,7 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=8.3.0" }, @@ -3405,7 +3450,6 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "license": "ISC", - "peer": true, "engines": { "node": ">=10" } @@ -3415,7 +3459,6 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "license": "MIT", - "peer": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -3434,7 +3477,6 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } diff --git a/package.json b/package.json index 58bf468..247f232 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,6 @@ "devDependencies": { "prettier": "^3.6.2", "typescript": "^5.9.2", - "vite": "^5.4.3" + "vite": "^7.2.7" } } diff --git a/src/main.ts b/src/main.ts index f0a11a7..8acc045 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,5 @@ -import { createWalletClient, route } from "@skip-go/client"; -import { createWalletClient, custom, parseUnits } from "viem"; +import { route } from "@skip-go/client"; +import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; declare global { From a524fdd4960e446542db26cb005564f2a11104f5 Mon Sep 17 00:00:00 2001 From: brentstone Date: Thu, 11 Dec 2025 19:49:08 -0800 Subject: [PATCH 2/4] use nam mainnet --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 8acc045..89cc568 100644 --- a/src/main.ts +++ b/src/main.ts @@ -23,7 +23,7 @@ const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"; const COSMOS_CHAIN_ID = "cosmoshub-4"; const COSMOS_ETHEREUM_CLIENT = "cosmoshub-0"; const COSMOS_PORT = "transfer"; -const COSMOS_TO_NAMADA_CHANNEL = "channel-1485"; +const COSMOS_TO_NAMADA_CHANNEL = "channel-1317"; const COSMOS_IBC_WETH = "ibc/C0B53D3D23827AE38058BED0BDCD554229278AF530A8D265FCF6DFF7C4B2ADFF"; From 207374186160878512f198b19ca6ef2f63af2dd2 Mon Sep 17 00:00:00 2001 From: brentstone Date: Thu, 11 Dec 2025 20:59:18 -0800 Subject: [PATCH 3/4] init commit --- index.html | 418 ++++++++++++++++++++++++++++++++- src/main.ts | 664 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 981 insertions(+), 101 deletions(-) diff --git a/index.html b/index.html index a967303..e34c869 100644 --- a/index.html +++ b/index.html @@ -1,24 +1,418 @@ - + - WETH → Cosmos Hub → Namada (PoC) + WETH → Cosmos Hub → Namada + -

WETH → Cosmos Hub → Namada (PoC)

-
-
- +
+

WETH → Namada Transfer

+

Cross-chain transfer via Cosmos Hub using IBC Eureka

+ +
+ 🔷 Ethereum + + ⚛️ Cosmos Hub + + 🟣 Namada +
+ +
+ How it works: This app initiates a single Ethereum transaction that + automatically routes WETH through Cosmos Hub to your Namada address using IBC packet + forwarding. The Skip relayer handles the cross-chain messaging (~20 min). +
+ + +
+
+ Wallet +
+ Not connected +
+
+ +
+ + +
+
+ Transfer Details +
+ +
+ + +
⚠️ Skip relay fees are ~$0.20. Small amounts may be rejected if fees exceed ~50% of value.
+
+ +
+ + +
+ +
+ + +
-
-
- + + +
+
+ + + + + +
+
Transaction Log
+

     
-
-
-

+
     
   
 
diff --git a/src/main.ts b/src/main.ts
index 89cc568..7618867 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,23 +1,34 @@
 import { route } from "@skip-go/client";
-import { createWalletClient, custom } from "viem";
+import { createWalletClient, custom, formatUnits } from "viem";
 import { mainnet } from "viem/chains";
 
 declare global {
   interface Window {
     ethereum?: any;
-    keplr?: any;
   }
 }
 
+// ============================================================================
+// DOM Elements
+// ============================================================================
+
 const logEl = document.getElementById("log")!;
-const btn1 = document.getElementById("transfer")!;
+const statusEl = document.getElementById("status")!;
+const errorEl = document.getElementById("error")!;
+const connectBtn = document.getElementById("connect-wallet")!;
+const walletStatusEl = document.getElementById("wallet-status")!;
+const transferBtn = document.getElementById("transfer")!;
 const amountInput = document.getElementById("amount") as HTMLInputElement;
 const tnamInput = document.getElementById("tnam") as HTMLInputElement;
+const cosmosInput = document.getElementById("cosmos") as HTMLInputElement;
+
+// ============================================================================
+// Constants
+// ============================================================================
 
 const ETHEREUM_CHAIN_ID = "1";
+const ETHEREUM_CHAIN_ID_HEX = "0x1";
 const ETHEREUM_PROXY_ADDR = "0xfc2d0487a0ae42ae7329a80dc269916a9184cf7c";
-const ETHEREUM_ICS20_CONTRACT_ADDR =
-  "0xa348CfE719B63151F228e3C30EB424BA5a983012";
 const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
 
 const COSMOS_CHAIN_ID = "cosmoshub-4";
@@ -27,8 +38,100 @@ const COSMOS_TO_NAMADA_CHANNEL = "channel-1317";
 const COSMOS_IBC_WETH =
   "ibc/C0B53D3D23827AE38058BED0BDCD554229278AF530A8D265FCF6DFF7C4B2ADFF";
 
+// ============================================================================
+// State
+// ============================================================================
+
+let connectedAccount: string | null = null;
+
+// ============================================================================
+// Logging & Status Utilities
+// ============================================================================
+
 function log(...args: any[]) {
-  logEl.textContent += args.join(" ") + "\n";
+  const timestamp = new Date().toLocaleTimeString();
+  logEl.textContent += `[${timestamp}] ${args.join(" ")}\n`;
+  logEl.scrollTop = logEl.scrollHeight;
+}
+
+function setStatus(message: string, type: "info" | "success" | "warning" = "info") {
+  statusEl.textContent = message;
+  statusEl.className = `status status-${type}`;
+}
+
+function clearStatus() {
+  statusEl.textContent = "";
+  statusEl.className = "status";
+}
+
+function showError(message: string) {
+  errorEl.textContent = message;
+  errorEl.style.display = "block";
+}
+
+function clearError() {
+  errorEl.textContent = "";
+  errorEl.style.display = "none";
+}
+
+// ============================================================================
+// Validation Utilities
+// ============================================================================
+
+function validateNamadaAddress(address: string): { valid: boolean; error?: string } {
+  if (!address) {
+    return { valid: false, error: "Namada address is required" };
+  }
+  if (!address.startsWith("tnam")) {
+    return { 
+      valid: false, 
+      error: "Invalid Namada address: must start with 'tnam' (transparent address). Shielded addresses (znam) are not supported for direct deposits." 
+    };
+  }
+  if (address.length < 40) {
+    return { valid: false, error: "Invalid Namada address: address appears too short" };
+  }
+  return { valid: true };
+}
+
+function validateCosmosAddress(address: string): { valid: boolean; error?: string } {
+  if (!address) {
+    return { valid: false, error: "Cosmos Hub address is required for recovery/refund purposes" };
+  }
+  if (!address.startsWith("cosmos1")) {
+    return { 
+      valid: false, 
+      error: "Invalid Cosmos Hub address: must start with 'cosmos1'" 
+    };
+  }
+  if (address.length !== 45) {
+    return { valid: false, error: `Invalid Cosmos Hub address: expected 45 characters, got ${address.length}` };
+  }
+  return { valid: true };
+}
+
+function validateAmount(amountStr: string): { valid: boolean; error?: string; weiStr?: string } {
+  if (!amountStr || amountStr.trim() === "") {
+    return { valid: false, error: "Amount is required" };
+  }
+  
+  const amount = parseFloat(amountStr);
+  if (isNaN(amount)) {
+    return { valid: false, error: "Invalid amount: must be a valid number" };
+  }
+  if (amount <= 0) {
+    return { valid: false, error: "Invalid amount: must be greater than 0" };
+  }
+  if (amount > 1000) {
+    return { valid: false, error: "Invalid amount: maximum 1000 WETH per transfer (safety limit)" };
+  }
+  
+  const weiStr = toWeiStr(amountStr);
+  if (weiStr === "0") {
+    return { valid: false, error: "Invalid amount: too small (rounds to 0 wei)" };
+  }
+  
+  return { valid: true, weiStr };
 }
 
 function toWeiStr(amountStr: string): string {
@@ -38,29 +141,198 @@ function toWeiStr(amountStr: string): string {
   return (int + frac).replace(/^0+/, "") || "0";
 }
 
-async function getKeplrEvmProvider() {
-  if (!window.keplr?.ethereum)
-    throw new Error("EVM provider of Keplr not found");
-  const eth = window.keplr.ethereum;
-  await eth.enable();
-  return eth;
+// ============================================================================
+// MetaMask Wallet Connection
+// ============================================================================
+
+/**
+ * Tests if a provider actually supports standard Ethereum JSON-RPC methods.
+ * Some extensions claim isMetaMask but don't implement the full API.
+ */
+async function testProvider(provider: any): Promise {
+  try {
+    // Try a simple read-only method that all Ethereum providers should support
+    const chainId = await provider.request({ method: "eth_chainId" });
+    return typeof chainId === "string" && chainId.startsWith("0x");
+  } catch {
+    return false;
+  }
 }
 
-// Ethereum (EVM)
-async function getEthereumAccount() {
-  const ethProvider = await getKeplrEvmProvider();
-  const accounts = await ethProvider.request({ method: "eth_requestAccounts" });
-  return accounts[0];
+/**
+ * Gets the MetaMask provider specifically, even when multiple wallet extensions are installed.
+ * This handles the case where other extensions may override window.ethereum.
+ * Returns a list of candidate providers to try.
+ */
+function getCandidateProviders(): any[] {
+  const candidates: any[] = [];
+
+  if (typeof window.ethereum === "undefined") {
+    return candidates;
+  }
+
+  // If there are multiple providers (EIP-5749), collect all MetaMask-like ones
+  if (window.ethereum.providers?.length) {
+    for (const provider of window.ethereum.providers) {
+      if (provider.isMetaMask) {
+        candidates.push(provider);
+      }
+    }
+  }
+
+  // Also try the main window.ethereum if it claims to be MetaMask
+  if (window.ethereum.isMetaMask && !candidates.includes(window.ethereum)) {
+    candidates.push(window.ethereum);
+  }
+
+  // If no MetaMask found but window.ethereum exists, try it anyway as fallback
+  if (candidates.length === 0 && window.ethereum) {
+    candidates.push(window.ethereum);
+  }
+
+  return candidates;
+}
+
+let cachedProvider: any = null;
+
+async function findWorkingProvider(): Promise {
+  if (cachedProvider) return cachedProvider;
+
+  const candidates = getCandidateProviders();
+  log(`Found ${candidates.length} candidate provider(s)`);
+
+  for (let i = 0; i < candidates.length; i++) {
+    const provider = candidates[i];
+    log(`Testing provider ${i + 1}/${candidates.length}...`);
+    
+    if (await testProvider(provider)) {
+      log(`Provider ${i + 1} works!`);
+      cachedProvider = provider;
+      return provider;
+    } else {
+      log(`Provider ${i + 1} failed basic test, trying next...`);
+    }
+  }
+
+  return null;
+}
+
+function getProvider(): any {
+  return cachedProvider;
+}
+
+async function checkCorrectNetwork(): Promise {
+  const provider = getProvider();
+  if (!provider) return false;
+
+  try {
+    const chainId = await provider.request({ method: "eth_chainId" });
+    return chainId === ETHEREUM_CHAIN_ID_HEX;
+  } catch (error) {
+    log(`Network check error: ${error}`);
+    return false;
+  }
+}
+
+async function switchToMainnet(): Promise {
+  const provider = getProvider();
+  if (!provider) throw new Error("MetaMask not available");
+
+  try {
+    await provider.request({
+      method: "wallet_switchEthereumChain",
+      params: [{ chainId: ETHEREUM_CHAIN_ID_HEX }],
+    });
+  } catch (error: any) {
+    if (error.code === 4902) {
+      throw new Error("Ethereum Mainnet not configured in MetaMask. Please add it manually.");
+    }
+    throw new Error(`Failed to switch network: ${error.message || "Unknown error"}`);
+  }
+}
+
+async function connectMetaMask(): Promise {
+  log("Detecting wallet providers...");
+
+  // Find a working provider
+  const provider = await findWorkingProvider();
+  
+  if (!provider) {
+    throw new Error(
+      "No working Ethereum wallet found. Please ensure MetaMask is installed and enabled. " +
+      "You have multiple browser extensions installed that may be conflicting. " +
+      "Try these steps:\n" +
+      "1. Open MetaMask and make sure it's unlocked\n" +
+      "2. Disable other wallet extensions temporarily (Namada, Polkadot.js, Keplr, etc.)\n" +
+      "3. Refresh this page and try again"
+    );
+  }
+
+  log("Working provider found");
+
+  // Check and switch to correct network
+  log("Checking network...");
+  const isCorrectNetwork = await checkCorrectNetwork();
+  
+  if (!isCorrectNetwork) {
+    log("Not on Ethereum Mainnet, attempting to switch...");
+    try {
+      await switchToMainnet();
+      log("Switched to Ethereum Mainnet");
+    } catch (error: any) {
+      throw new Error(
+        `Please manually switch to Ethereum Mainnet in your wallet. ` +
+        `(${error.message})`
+      );
+    }
+  } else {
+    log("Already on Ethereum Mainnet");
+  }
+
+  // Request account access
+  log("Requesting account access...");
+  try {
+    const accounts = await provider.request({
+      method: "eth_requestAccounts",
+    });
+
+    if (!accounts || accounts.length === 0) {
+      throw new Error("No accounts returned. Please unlock your wallet and try again.");
+    }
+
+    return accounts[0];
+  } catch (error: any) {
+    if (error.code === 4001) {
+      throw new Error("Connection rejected: You declined the wallet connection request.");
+    }
+    if (error.code === -32002) {
+      throw new Error("Connection pending: Please check your wallet for a pending connection request.");
+    }
+    throw new Error(`Failed to connect wallet: ${error.message || "Unknown error"}`);
+  }
 }
 
-// Cosmos Hub
-async function getCosmosAccount() {
-  await (window as any).keplr.enable(COSMOS_CHAIN_ID);
-  const key = await (window as any).keplr.getKey(COSMOS_CHAIN_ID);
-  return key.bech32Address;
+function updateWalletUI(account: string | null) {
+  if (account) {
+    const shortAddr = `${account.slice(0, 6)}...${account.slice(-4)}`;
+    walletStatusEl.textContent = `Connected: ${shortAddr}`;
+    walletStatusEl.className = "wallet-connected";
+    connectBtn.textContent = "Wallet Connected";
+    (connectBtn as HTMLButtonElement).disabled = true;
+    (transferBtn as HTMLButtonElement).disabled = false;
+  } else {
+    walletStatusEl.textContent = "Not connected";
+    walletStatusEl.className = "wallet-disconnected";
+    connectBtn.textContent = "Connect MetaMask";
+    (connectBtn as HTMLButtonElement).disabled = false;
+    (transferBtn as HTMLButtonElement).disabled = true;
+  }
 }
 
-// ERC20 ABI (approve)
+// ============================================================================
+// Contract ABIs
+// ============================================================================
+
 const ERC20_ABI = [
   {
     type: "function",
@@ -71,9 +343,14 @@ const ERC20_ABI = [
     ],
     outputs: [{ type: "bool" }],
   },
-];
+  {
+    type: "function",
+    name: "balanceOf",
+    inputs: [{ name: "account", type: "address" }],
+    outputs: [{ type: "uint256" }],
+  },
+] as const;
 
-// Eureka transfer
 const PROXY_ABI = [
   {
     type: "function",
@@ -106,33 +383,86 @@ const PROXY_ABI = [
   },
 ] as const;
 
-async function sendEurekaWithPFM(namadaReceiver: string, amountWei: BigInt) {
-  const ethProvider = await getKeplrEvmProvider();
-  const account = await getEthereumAccount();
-  const cosmosAddr = await getCosmosAccount();
+// ============================================================================
+// Main Transfer Function
+// ============================================================================
+
+async function sendEurekaWithPFM(
+  namadaReceiver: string,
+  cosmosRecoveryAddr: string,
+  amountWei: bigint
+) {
+  if (!connectedAccount) {
+    throw new Error("Wallet not connected. Please connect MetaMask first.");
+  }
+
+  const provider = getProvider();
+  if (!provider) {
+    throw new Error("MetaMask not available");
+  }
+
+  // Verify still on correct network
+  if (!(await checkCorrectNetwork())) {
+    throw new Error("Wrong network detected. Please switch to Ethereum Mainnet in MetaMask.");
+  }
 
   const client = createWalletClient({
-    account,
+    account: connectedAccount as `0x${string}`,
     chain: mainnet,
-    transport: custom(ethProvider),
+    transport: custom(provider),
   });
 
-  // 0. get Cosmos info and the relay fee
-  const r = await route({
-    sourceAssetChainId: ETHEREUM_CHAIN_ID,
-    sourceAssetDenom: WETH,
-    destAssetChainId: COSMOS_CHAIN_ID,
-    destAssetDenom: COSMOS_IBC_WETH,
-    amountIn: String(amountWei),
-    smartRelay: true,
-    experimentalFeatures: ["eureka"],
-  });
-  const eurekaTransfer = r.operations?.[0].eurekaTransfer;
+  // Step 0: Get relay fee quote from Skip
+  setStatus("Fetching relay fee quote from Skip...", "info");
+  log("Requesting route from Skip API...");
+
+  let routeResponse;
+  try {
+    routeResponse = await route({
+      sourceAssetChainId: ETHEREUM_CHAIN_ID,
+      sourceAssetDenom: WETH,
+      destAssetChainId: COSMOS_CHAIN_ID,
+      destAssetDenom: COSMOS_IBC_WETH,
+      amountIn: String(amountWei),
+      smartRelay: true,
+      experimentalFeatures: ["eureka"],
+    });
+  } catch (error: any) {
+    const errorMsg = error.message || "Unknown error";
+    
+    // Check for the specific USD value difference error
+    if (errorMsg.includes("USD value") || errorMsg.includes("too large")) {
+      throw new Error(
+        `Transfer amount too small: The relay fee would consume too much of your transfer. ` +
+        `Skip requires that fees don't exceed ~50% of the transfer value. ` +
+        `Please increase the amount to at least 0.005 WETH (~$15+).`
+      );
+    }
+    
+    throw new Error(
+      `Failed to get route from Skip API: ${errorMsg}. ` +
+      `This could be due to network issues or the Skip service being unavailable.`
+    );
+  }
+
+  const eurekaTransfer = routeResponse.operations?.[0]?.eurekaTransfer;
+  if (!eurekaTransfer) {
+    throw new Error(
+      "Invalid response from Skip API: missing eurekaTransfer data. " +
+      "The API response structure may have changed or the route is not supported."
+    );
+  }
 
   const feeInfo = eurekaTransfer.smartRelayFeeQuote;
+  if (!feeInfo) {
+    throw new Error(
+      "Invalid response from Skip API: missing relay fee quote. " +
+      "Smart relay may not be available for this route."
+    );
+  }
+
   const relayFee = BigInt(feeInfo.feeAmount);
   const relayFeeRecipient = feeInfo.feePaymentAddress;
-
   const expirationStr = feeInfo.expiration;
   const expirationSec = Math.floor(Date.parse(expirationStr) / 1000);
   const quoteExpiry = BigInt(expirationSec);
@@ -140,23 +470,58 @@ async function sendEurekaWithPFM(namadaReceiver: string, amountWei: BigInt) {
   const callbackAddress = eurekaTransfer.toChainCallbackContractAddress;
   const entryContract = eurekaTransfer.toChainEntryContractAddress;
 
+  if (!callbackAddress || !entryContract) {
+    throw new Error(
+      "Invalid response from Skip API: missing callback or entry contract addresses."
+    );
+  }
+
+  log(`Relay fee: ${formatUnits(relayFee, 18)} WETH`);
+  log(`Callback contract: ${callbackAddress}`);
+  log(`Entry contract: ${entryContract}`);
+
+  // Calculate received amount
   const receivedAmount = amountWei - relayFee;
-  log("Amount to be received:", receivedAmount);
-
-  // 1. approve
-  await client.writeContract({
-    address: WETH as `0x${string}`,
-    abi: ERC20_ABI,
-    functionName: "approve",
-    args: [ETHEREUM_PROXY_ADDR, amountWei],
-    account,
-  });
+  if (receivedAmount <= 0n) {
+    throw new Error(
+      `Transfer amount (${formatUnits(amountWei, 18)} WETH) is less than or equal to the relay fee ` +
+      `(${formatUnits(relayFee, 18)} WETH). Please increase the transfer amount.`
+    );
+  }
+
+  log(`Amount after relay fee: ${formatUnits(receivedAmount, 18)} WETH`);
+
+  // Step 1: Approve WETH spending
+  setStatus("Step 1/2: Approving WETH spending... (check MetaMask)", "info");
+  log("Requesting WETH approval in MetaMask...");
+
+  try {
+    const approveHash = await client.writeContract({
+      address: WETH as `0x${string}`,
+      abi: ERC20_ABI,
+      functionName: "approve",
+      args: [ETHEREUM_PROXY_ADDR as `0x${string}`, amountWei],
+      account: connectedAccount as `0x${string}`,
+    });
+    log(`Approval tx submitted: ${approveHash}`);
+    log("Waiting for approval confirmation...");
+  } catch (error: any) {
+    if (error.message?.includes("User rejected") || error.code === 4001) {
+      throw new Error("Transaction rejected: You declined the WETH approval in MetaMask.");
+    }
+    throw new Error(`WETH approval failed: ${error.message || "Unknown error"}`);
+  }
+
+  // Step 2: Prepare and send the transfer
+  setStatus("Step 2/2: Sending transfer... (check MetaMask)", "info");
 
   const nowSec = Math.floor(Date.now() / 1000);
-  // IMPORTANT: 12 hours timeout because the Skip relayer will ignore the packet with less than 10 hours timeout
+  // IMPORTANT: 12 hours timeout because Skip relayer ignores packets with <10 hours timeout
   const timeout = BigInt(nowSec + 43200);
+  const timeoutDate = new Date((nowSec + 43200) * 1000).toLocaleString();
+  log(`Timeout set to: ${timeoutDate} (12 hours from now)`);
 
-  // 2. Forward memo with CosmWasm contract (Cosmos to Namada)
+  // Construct the forwarding memo
   const memo = JSON.stringify({
     dest_callback: {
       address: callbackAddress,
@@ -168,9 +533,9 @@ async function sendEurekaWithPFM(namadaReceiver: string, amountWei: BigInt) {
           action: {
             ibc_transfer: {
               ibc_info: {
-                memo: "", // should be empty
+                memo: "", // Must be empty - forwarding reuses this field
                 receiver: namadaReceiver,
-                recover_address: cosmosAddr,
+                recover_address: cosmosRecoveryAddr,
                 source_channel: COSMOS_TO_NAMADA_CHANNEL,
               },
             },
@@ -182,43 +547,164 @@ async function sendEurekaWithPFM(namadaReceiver: string, amountWei: BigInt) {
     },
   });
 
-  // 3. transfer
-  const txHash = await client.writeContract({
-    address: ETHEREUM_PROXY_ADDR,
-    abi: PROXY_ABI,
-    functionName: "transfer",
-    args: [
-      receivedAmount,
-      {
-        token: WETH,
-        // Need to sent tokens to the callback address
-        recipient: callbackAddress,
-        sourceClient: COSMOS_ETHEREUM_CLIENT,
-        destPort: COSMOS_PORT,
-        timeoutTimestamp: timeout,
-        memo,
-      },
-      {
-        relayFee,
-        relayFeeRecipient,
-        quoteExpiry,
-      },
-    ],
-    account,
-  });
+  log("Submitting transfer transaction...");
 
-  log("EVM tx sent:", txHash);
+  try {
+    const txHash = await client.writeContract({
+      address: ETHEREUM_PROXY_ADDR as `0x${string}`,
+      abi: PROXY_ABI,
+      functionName: "transfer",
+      args: [
+        receivedAmount,
+        {
+          token: WETH as `0x${string}`,
+          recipient: callbackAddress,
+          sourceClient: COSMOS_ETHEREUM_CLIENT,
+          destPort: COSMOS_PORT,
+          timeoutTimestamp: timeout,
+          memo,
+        },
+        {
+          relayFee,
+          relayFeeRecipient: relayFeeRecipient as `0x${string}`,
+          quoteExpiry,
+        },
+      ],
+      account: connectedAccount as `0x${string}`,
+    });
+
+    log(`✓ Transfer tx submitted: ${txHash}`);
+    log(`View on Etherscan: https://etherscan.io/tx/${txHash}`);
+    log("");
+    log("Transfer initiated successfully!");
+    log("The Skip relayer will now pick up this transaction and relay it to Cosmos Hub,");
+    log("then the CosmWasm contract will forward it to Namada.");
+    log("This typically takes ~20 minutes. Monitor the transaction on Etherscan.");
+    
+    setStatus("Transfer submitted! Relaying takes ~20 minutes.", "success");
+    
+    return txHash;
+  } catch (error: any) {
+    if (error.message?.includes("User rejected") || error.code === 4001) {
+      throw new Error("Transaction rejected: You declined the transfer in MetaMask.");
+    }
+    if (error.message?.includes("insufficient funds")) {
+      throw new Error(
+        "Insufficient funds: You don't have enough ETH to pay for gas, " +
+        "or not enough WETH for the transfer amount."
+      );
+    }
+    throw new Error(`Transfer failed: ${error.message || "Unknown error"}`);
+  }
 }
 
-btn1.addEventListener("click", async () => {
+// ============================================================================
+// Event Handlers
+// ============================================================================
+
+connectBtn.addEventListener("click", async () => {
+  clearError();
+  setStatus("Connecting to MetaMask...", "info");
+
   try {
-    log("Transferring WETH from Ethereum");
+    const account = await connectMetaMask();
+    connectedAccount = account;
+    updateWalletUI(account);
+    log(`Wallet connected: ${account}`);
+    setStatus("Wallet connected successfully!", "success");
+    setTimeout(clearStatus, 3000);
+  } catch (error: any) {
+    showError(error.message);
+    setStatus("Connection failed", "warning");
+    log(`Connection error: ${error.message}`);
+  }
+});
 
-    const amountWei = toWeiStr(amountInput.value.trim());
-    const toNamada = tnamInput.value.trim();
+transferBtn.addEventListener("click", async () => {
+  clearError();
 
-    await sendEurekaWithPFM(toNamada, BigInt(amountWei));
-  } catch (e: any) {
-    log("Transfer error", e.message);
+  // Validate all inputs
+  const amountStr = amountInput.value.trim();
+  const namadaAddr = tnamInput.value.trim();
+  const cosmosAddr = cosmosInput.value.trim();
+
+  // Validate amount
+  const amountValidation = validateAmount(amountStr);
+  if (!amountValidation.valid) {
+    showError(amountValidation.error!);
+    return;
+  }
+
+  // Validate Namada address
+  const namadaValidation = validateNamadaAddress(namadaAddr);
+  if (!namadaValidation.valid) {
+    showError(namadaValidation.error!);
+    return;
+  }
+
+  // Validate Cosmos address
+  const cosmosValidation = validateCosmosAddress(cosmosAddr);
+  if (!cosmosValidation.valid) {
+    showError(cosmosValidation.error!);
+    return;
+  }
+
+  // Disable button during transfer
+  (transferBtn as HTMLButtonElement).disabled = true;
+
+  try {
+    log("─".repeat(50));
+    log(`Initiating transfer of ${amountStr} WETH`);
+    log(`To Namada: ${namadaAddr}`);
+    log(`Recovery address: ${cosmosAddr}`);
+    log("─".repeat(50));
+
+    await sendEurekaWithPFM(namadaAddr, cosmosAddr, BigInt(amountValidation.weiStr!));
+  } catch (error: any) {
+    showError(error.message);
+    setStatus("Transfer failed", "warning");
+    log(`ERROR: ${error.message}`);
+  } finally {
+    // Re-enable button if wallet is still connected
+    if (connectedAccount) {
+      (transferBtn as HTMLButtonElement).disabled = false;
+    }
   }
 });
+
+// Listen for account changes - set up after a short delay to ensure provider is detected
+function setupProviderListeners() {
+  const provider = getProvider();
+  if (provider) {
+    provider.on("accountsChanged", (accounts: string[]) => {
+      if (accounts.length === 0) {
+        connectedAccount = null;
+        updateWalletUI(null);
+        log("Wallet disconnected");
+      } else if (accounts[0] !== connectedAccount) {
+        connectedAccount = accounts[0];
+        updateWalletUI(accounts[0]);
+        log(`Account changed to: ${accounts[0]}`);
+      }
+    });
+
+    provider.on("chainChanged", (chainId: string) => {
+      if (chainId !== ETHEREUM_CHAIN_ID_HEX) {
+        showError("Wrong network! Please switch to Ethereum Mainnet in MetaMask.");
+        log(`Network changed to chain ID ${chainId} - please switch back to Mainnet`);
+      } else {
+        clearError();
+        log("Network: Ethereum Mainnet");
+      }
+    });
+
+    log("MetaMask event listeners registered");
+  }
+}
+
+// Defer listener setup to allow provider detection
+setTimeout(setupProviderListeners, 100);
+
+// Initial UI state
+updateWalletUI(null);
+log("Application loaded. Connect your MetaMask wallet to begin.");

From b9ec1ab44c040d5f6db9ae419d491e42765c57ab Mon Sep 17 00:00:00 2001
From: brentstone 
Date: Thu, 11 Dec 2025 22:59:37 -0800
Subject: [PATCH 4/4] add .gitignore

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 .gitignore

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules