diff --git a/bun.lock b/bun.lock index 530420dd3..99647422f 100644 --- a/bun.lock +++ b/bun.lock @@ -31,7 +31,6 @@ "@swapkit/toolboxes": "workspace:*", "@swapkit/wallets": "workspace:*", "astro": "5.3.0", - "expressive-code-twoslash": "0.4.0", "sharp": "0.33.5", "starlight-typedoc": "0.19.0", "typedoc": "0.27.7", @@ -404,7 +403,7 @@ "@chainflip/bitcoin": ["@chainflip/bitcoin@1.1.1", "", { "dependencies": { "@chainflip/utils": "^0.4.0", "bitcoinjs-lib": "^7.0.0-rc.0" } }, "sha512-Jr6X/0QTSFYpTp23ZPhyioL6wL9x3Xpj6OGjadQKZyhobRN4BZkhLogv20HDYTJcRzVphzrTJArbEaNie04XVA=="], - "@chainflip/rpc": ["@chainflip/rpc@1.8.5", "", { "dependencies": { "@chainflip/utils": "0.4.0", "zod": "^3.24.2" } }, "sha512-5s1jsadc1wzOu/eoExxk3u7bsyKviBsqJaikANDJbuytaURgS9NtPuB3Ks0qjvxjqLyWlhfU28Rf/NWEUsGyNg=="], + "@chainflip/rpc": ["@chainflip/rpc@1.8.6", "", { "dependencies": { "@chainflip/utils": "0.4.0", "zod": "^3.24.2" } }, "sha512-aufMeb0ltGuudujH/H20EHPKsvt+qaYSB7weSy5Vw0ZfhUuQzDvFegXIpDLKajeUVpzaniKIlE2rKk4574nKDA=="], "@chainflip/sdk": ["@chainflip/sdk@1.7.0", "", { "dependencies": { "@chainflip/bitcoin": "^1.1.1", "@chainflip/rpc": "^1.6.11", "@chainflip/solana": "^1.0.2", "@chainflip/utils": "^0.4.0", "@trpc/client": "^10.45.2", "axios": "^1.7.7", "bignumber.js": "^9.1.2", "ethers": "^6.13.3", "superjson": "^1.13.3", "zod": "^3.23.8" } }, "sha512-teJ0XS/uMQQkJ544h56gajFiGnojUxqzKujC55HCUFWlVbeFDTKti5yAK8AJiS4jLvy2arHBwEE/IDvQgQNz6w=="], @@ -2016,7 +2015,7 @@ "eip55": ["eip55@2.1.1", "", { "dependencies": { "keccak": "^3.0.3" } }, "sha512-WcagVAmNu2Ww2cDUfzuWVntYwFxbvZ5MvIyLZpMjTTkjD6sCvkGOiS86jTppzu9/gWsc8isLHAeMBWK02OnZmA=="], - "electron-to-chromium": ["electron-to-chromium@1.5.102", "", {}, "sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q=="], + "electron-to-chromium": ["electron-to-chromium@1.5.103", "", {}, "sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA=="], "elliptic": ["elliptic@6.6.1", "", { "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", "hash.js": "^1.0.0", "hmac-drbg": "^1.0.1", "inherits": "^2.0.4", "minimalistic-assert": "^1.0.1", "minimalistic-crypto-utils": "^1.0.1" } }, "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g=="], @@ -2112,8 +2111,6 @@ "expressive-code": ["expressive-code@0.40.2", "", { "dependencies": { "@expressive-code/core": "^0.40.2", "@expressive-code/plugin-frames": "^0.40.2", "@expressive-code/plugin-shiki": "^0.40.2", "@expressive-code/plugin-text-markers": "^0.40.2" } }, "sha512-1zIda2rB0qiDZACawzw2rbdBQiWHBT56uBctS+ezFe5XMAaFaHLnnSYND/Kd+dVzO9HfCXRDpzH3d+3fvOWRcw=="], - "expressive-code-twoslash": ["expressive-code-twoslash@0.4.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.2", "mdast-util-gfm": "^3.1.0", "mdast-util-to-hast": "^13.2.0", "twoslash": "^0.2.12" }, "peerDependencies": { "@expressive-code/core": "^0.40.0", "expressive-code": "^0.40.0", "typescript": "^5.7" } }, "sha512-7HffO04pYLNHX0P8/8xX+pdgWYpFWdP9/gYi7dAH1nSAxO1W7pQHW4Ly6OXD3fs4SChkGP/PWkE4oLo6CeXTfg=="], - "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], "extendable-error": ["extendable-error@0.1.7", "", {}, "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg=="], @@ -2424,8 +2421,6 @@ "jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="], - "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], - "jotai": ["jotai@2.12.1", "", { "peerDependencies": { "@types/react": ">=17.0.0", "react": ">=17.0.0" }, "optionalPeers": ["@types/react", "react"] }, "sha512-VUW0nMPYIru5g89tdxwr9ftiVdc/nGV9jvHISN8Ucx+m1vI9dBeHemfqYzEuw5XSkmYjD/MEyApN9k6yrATsZQ=="], "js-sha3": ["js-sha3@0.8.0", "", {}, "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="], @@ -2550,7 +2545,7 @@ "markdown-it": ["markdown-it@14.1.0", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg=="], - "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + "markdown-table": ["markdown-table@1.1.3", "", {}, "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q=="], "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], @@ -2716,7 +2711,7 @@ "multiformats": ["multiformats@9.9.0", "", {}, "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg=="], - "nan": ["nan@2.22.0", "", {}, "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw=="], + "nan": ["nan@2.22.1", "", {}, "sha512-pfRR4ZcNTSm2ZFHaztuvbICf+hyiG6ecA06SfAxoPmuHjvMu0KUIae7Y8GyVkbBqeEIidsmXeYooWIX9+qjfRQ=="], "nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], @@ -2726,7 +2721,7 @@ "neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="], - "neverthrow": ["neverthrow@8.1.1", "", { "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "^4.24.0" } }, "sha512-DpbZ/UDI0B+TxJB1JysXSfi1++3YK2xLBqQLTlRN0b4zxlZ2MoiB+dKKV8dMRzt1fAFjRKDknXOVJgpl+a4Amw=="], + "neverthrow": ["neverthrow@8.2.0", "", { "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "^4.24.0" } }, "sha512-kOCT/1MCPAxY5iUV3wytNFUMUolzuwd/VF/1KCx7kf6CutrOsTie+84zTGTpgQycjvfLdBBdvBvFLqFD2c0wkQ=="], "next": ["next@15.1.7", "", { "dependencies": { "@next/env": "15.1.7", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.1.7", "@next/swc-darwin-x64": "15.1.7", "@next/swc-linux-arm64-gnu": "15.1.7", "@next/swc-linux-arm64-musl": "15.1.7", "@next/swc-linux-x64-gnu": "15.1.7", "@next/swc-linux-x64-musl": "15.1.7", "@next/swc-win32-arm64-msvc": "15.1.7", "@next/swc-win32-x64-msvc": "15.1.7", "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-GNeINPGS9c6OZKCvKypbL8GTsT5GhWPp4DM0fzkXJuXMilOO2EeFxuAY6JZbtk6XIl6Ws10ag3xRINDjSO5+wg=="], @@ -3280,7 +3275,7 @@ "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], - "tinyglobby": ["tinyglobby@0.2.11", "", { "dependencies": { "fdir": "^6.4.3", "picomatch": "^4.0.2" } }, "sha512-32TmKeeKUahv0Go8WmQgiEp9Y21NuxjwjqiRC1nrUB51YacfSwuB44xgXD+HdIppmMRgjQNPdrHyA6vIybYZ+g=="], + "tinyglobby": ["tinyglobby@0.2.12", "", { "dependencies": { "fdir": "^6.4.3", "picomatch": "^4.0.2" } }, "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww=="], "tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="], @@ -3392,7 +3387,7 @@ "unplugin": ["unplugin@2.1.0", "", { "dependencies": { "acorn": "^8.14.0", "webpack-virtual-modules": "^0.6.2" } }, "sha512-us4j03/499KhbGP8BU7Hrzrgseo+KdfJYWcbcajCOqsAyb8Gk0Yn2kiUIcZISYCb1JFaZfIuG3b42HmguVOKCQ=="], - "unstorage": ["unstorage@1.14.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^3.6.0", "destr": "^2.0.3", "h3": "^1.13.0", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.4", "ofetch": "^1.4.1", "ufo": "^1.5.4" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.5.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3", "@deno/kv": ">=0.8.4", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.1" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-1SYeamwuYeQJtJ/USE1x4l17LkmQBzg7deBJ+U9qOBoHo15d1cDxG4jM31zKRgF7pG0kirZy4wVMX6WL6Zoscg=="], + "unstorage": ["unstorage@1.15.0", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^4.0.3", "destr": "^2.0.3", "h3": "^1.15.0", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.6", "ofetch": "^1.4.1", "ufo": "^1.5.4" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-m40eHdGY/gA6xAPqo8eaxqXgBuzQTlAKfmB1iF7oCKXE1HfwHwzDJBywK+qQGn52dta+bPlZluPF7++yR3p/bg=="], "update-browserslist-db": ["update-browserslist-db@1.1.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg=="], @@ -3400,7 +3395,7 @@ "url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="], - "usb": ["usb@2.14.0", "", { "dependencies": { "@types/w3c-web-usb": "^1.0.6", "node-addon-api": "^8.0.0", "node-gyp-build": "^4.5.0" } }, "sha512-I3lzVOH21BsO6qPYvx1C7Ji08lbuM0qmsEtNGAphqlhNME5cz/vExY+jIXZl+HQIRybI/sTxdyLab5tALsL69w=="], + "usb": ["usb@2.15.0", "", { "dependencies": { "@types/w3c-web-usb": "^1.0.6", "node-addon-api": "^8.0.0", "node-gyp-build": "^4.5.0" } }, "sha512-BA9r7PFxyYp99wps1N70lIqdPb2Utcl2KkWohDtWUmhDBeM5hDH1Zl/L/CZvWxd5W3RUCNm1g+b+DEKZ6cHzqg=="], "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], @@ -3558,8 +3553,6 @@ "@coinbase/wallet-sdk/clsx": ["clsx@1.2.1", "", {}, "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="], - "@cosmjs/crypto/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], - "@cosmjs/socket/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], @@ -3708,7 +3701,7 @@ "@polkadot/x-ws/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "@polkadot/x-ws/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "@polkadot/x-ws/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], "@psf/bitcoincashjs-lib/bs58check": ["bs58check@2.1.2", "", { "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", "safe-buffer": "^5.1.2" } }, "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA=="], @@ -3796,7 +3789,7 @@ "@solana/rpc-subscriptions-channel-websocket/@solana/errors": ["@solana/errors@2.0.0", "", { "dependencies": { "chalk": "^5.3.0", "commander": "^12.1.0" }, "peerDependencies": { "typescript": ">=5" }, "bin": { "errors": "bin/cli.mjs" } }, "sha512-IHlaPFSy4lvYco1oHJ3X8DbchWwAwJaL/4wZKnF1ugwZ0g0re8wbABrqNOe/jyZ84VU9Z14PYM8W9oDAebdJbw=="], - "@solana/rpc-subscriptions-channel-websocket/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "@solana/rpc-subscriptions-channel-websocket/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], "@solana/rpc-subscriptions-spec/@solana/errors": ["@solana/errors@2.0.0", "", { "dependencies": { "chalk": "^5.3.0", "commander": "^12.1.0" }, "peerDependencies": { "typescript": ">=5" }, "bin": { "errors": "bin/cli.mjs" } }, "sha512-IHlaPFSy4lvYco1oHJ3X8DbchWwAwJaL/4wZKnF1ugwZ0g0re8wbABrqNOe/jyZ84VU9Z14PYM8W9oDAebdJbw=="], @@ -3854,7 +3847,7 @@ "@trezor/blockchain-link/@solana/web3.js": ["@solana/web3.js@2.0.0", "", { "dependencies": { "@solana/accounts": "2.0.0", "@solana/addresses": "2.0.0", "@solana/codecs": "2.0.0", "@solana/errors": "2.0.0", "@solana/functional": "2.0.0", "@solana/instructions": "2.0.0", "@solana/keys": "2.0.0", "@solana/programs": "2.0.0", "@solana/rpc": "2.0.0", "@solana/rpc-parsed-types": "2.0.0", "@solana/rpc-spec-types": "2.0.0", "@solana/rpc-subscriptions": "2.0.0", "@solana/rpc-types": "2.0.0", "@solana/signers": "2.0.0", "@solana/sysvars": "2.0.0", "@solana/transaction-confirmation": "2.0.0", "@solana/transaction-messages": "2.0.0", "@solana/transactions": "2.0.0" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-x+ZRB2/r5tVK/xw8QRbAfgPcX51G9f2ifEyAQ/J5npOO+6+MPeeCjtr5UxHNDAYs9Ypo0PN+YJATCO4vhzQJGg=="], - "@trezor/blockchain-link/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "@trezor/blockchain-link/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], "@trezor/blockchain-link-types/@solana/web3.js": ["@solana/web3.js@2.0.0", "", { "dependencies": { "@solana/accounts": "2.0.0", "@solana/addresses": "2.0.0", "@solana/codecs": "2.0.0", "@solana/errors": "2.0.0", "@solana/functional": "2.0.0", "@solana/instructions": "2.0.0", "@solana/keys": "2.0.0", "@solana/programs": "2.0.0", "@solana/rpc": "2.0.0", "@solana/rpc-parsed-types": "2.0.0", "@solana/rpc-spec-types": "2.0.0", "@solana/rpc-subscriptions": "2.0.0", "@solana/rpc-types": "2.0.0", "@solana/signers": "2.0.0", "@solana/sysvars": "2.0.0", "@solana/transaction-confirmation": "2.0.0", "@solana/transaction-messages": "2.0.0", "@solana/transactions": "2.0.0" }, "peerDependencies": { "typescript": ">=5" } }, "sha512-x+ZRB2/r5tVK/xw8QRbAfgPcX51G9f2ifEyAQ/J5npOO+6+MPeeCjtr5UxHNDAYs9Ypo0PN+YJATCO4vhzQJGg=="], @@ -3992,8 +3985,6 @@ "eth-gas-reporter/ethers": ["ethers@5.7.2", "", { "dependencies": { "@ethersproject/abi": "5.7.0", "@ethersproject/abstract-provider": "5.7.0", "@ethersproject/abstract-signer": "5.7.0", "@ethersproject/address": "5.7.0", "@ethersproject/base64": "5.7.0", "@ethersproject/basex": "5.7.0", "@ethersproject/bignumber": "5.7.0", "@ethersproject/bytes": "5.7.0", "@ethersproject/constants": "5.7.0", "@ethersproject/contracts": "5.7.0", "@ethersproject/hash": "5.7.0", "@ethersproject/hdnode": "5.7.0", "@ethersproject/json-wallets": "5.7.0", "@ethersproject/keccak256": "5.7.0", "@ethersproject/logger": "5.7.0", "@ethersproject/networks": "5.7.1", "@ethersproject/pbkdf2": "5.7.0", "@ethersproject/properties": "5.7.0", "@ethersproject/providers": "5.7.2", "@ethersproject/random": "5.7.0", "@ethersproject/rlp": "5.7.0", "@ethersproject/sha2": "5.7.0", "@ethersproject/signing-key": "5.7.0", "@ethersproject/solidity": "5.7.0", "@ethersproject/strings": "5.7.0", "@ethersproject/transactions": "5.7.0", "@ethersproject/units": "5.7.0", "@ethersproject/wallet": "5.7.0", "@ethersproject/web": "5.7.1", "@ethersproject/wordlists": "5.7.0" } }, "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg=="], - "eth-gas-reporter/markdown-table": ["markdown-table@1.1.3", "", {}, "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q=="], - "ethereum-bloom-filters/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], "ethereum-cryptography/@noble/hashes": ["@noble/hashes@1.2.0", "", {}, "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ=="], @@ -4054,6 +4045,8 @@ "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + "mdast-util-gfm-table/markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + "micro-key-producer/@noble/curves": ["@noble/curves@1.8.1", "", { "dependencies": { "@noble/hashes": "1.7.1" } }, "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ=="], "micro-key-producer/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], @@ -4132,7 +4125,7 @@ "rpc-websockets/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - "rpc-websockets/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "rpc-websockets/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], "rxjs/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -4150,8 +4143,6 @@ "secp256k1/node-addon-api": ["node-addon-api@5.1.0", "", {}, "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="], - "shelljs/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "shiki/@shikijs/core": ["@shikijs/core@1.29.2", "", { "dependencies": { "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ=="], "shiki/@shikijs/types": ["@shikijs/types@1.29.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw=="], @@ -4162,7 +4153,7 @@ "slice-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "smoldot/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "smoldot/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], "socks-proxy-agent/agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="], @@ -4210,16 +4201,12 @@ "tsx/esbuild": ["esbuild@0.25.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.0", "@esbuild/android-arm": "0.25.0", "@esbuild/android-arm64": "0.25.0", "@esbuild/android-x64": "0.25.0", "@esbuild/darwin-arm64": "0.25.0", "@esbuild/darwin-x64": "0.25.0", "@esbuild/freebsd-arm64": "0.25.0", "@esbuild/freebsd-x64": "0.25.0", "@esbuild/linux-arm": "0.25.0", "@esbuild/linux-arm64": "0.25.0", "@esbuild/linux-ia32": "0.25.0", "@esbuild/linux-loong64": "0.25.0", "@esbuild/linux-mips64el": "0.25.0", "@esbuild/linux-ppc64": "0.25.0", "@esbuild/linux-riscv64": "0.25.0", "@esbuild/linux-s390x": "0.25.0", "@esbuild/linux-x64": "0.25.0", "@esbuild/netbsd-arm64": "0.25.0", "@esbuild/netbsd-x64": "0.25.0", "@esbuild/openbsd-arm64": "0.25.0", "@esbuild/openbsd-x64": "0.25.0", "@esbuild/sunos-x64": "0.25.0", "@esbuild/win32-arm64": "0.25.0", "@esbuild/win32-ia32": "0.25.0", "@esbuild/win32-x64": "0.25.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw=="], - "unstorage/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], - - "usb/node-addon-api": ["node-addon-api@8.3.0", "", {}, "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg=="], + "usb/node-addon-api": ["node-addon-api@8.3.1", "", {}, "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA=="], "use-callback-ref/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "use-sidecar/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "vite/postcss": ["postcss@8.5.2", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA=="], - "web3-utils/ethereum-cryptography": ["ethereum-cryptography@2.2.1", "", { "dependencies": { "@noble/curves": "1.4.2", "@noble/hashes": "1.4.0", "@scure/bip32": "1.4.0", "@scure/bip39": "1.3.0" } }, "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg=="], "whatwg-encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], @@ -4518,16 +4505,12 @@ "sc-istanbul/supports-color/has-flag": ["has-flag@1.0.0", "", {}, "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA=="], - "shelljs/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "solidity-coverage/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], "solidity-coverage/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], "solidity-coverage/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], - "solidity-coverage/globby/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], "table/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -4586,8 +4569,6 @@ "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ=="], - "unstorage/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - "web3-utils/ethereum-cryptography/@noble/curves": ["@noble/curves@1.4.2", "", { "dependencies": { "@noble/hashes": "1.4.0" } }, "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw=="], "web3-utils/ethereum-cryptography/@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="], @@ -4704,16 +4685,10 @@ "sc-istanbul/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], - "shelljs/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], - "solidity-coverage/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], "solidity-coverage/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], - "solidity-coverage/globby/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - - "unstorage/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "web3-utils/ethereum-cryptography/@scure/bip32/@scure/base": ["@scure/base@1.1.9", "", {}, "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg=="], "web3-utils/ethereum-cryptography/@scure/bip39/@scure/base": ["@scure/base@1.1.9", "", {}, "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg=="], @@ -4735,7 +4710,5 @@ "qrcode/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], "solidity-coverage/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], - - "solidity-coverage/globby/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], } } diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 421bc4397..c9d29f36e 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -31,9 +31,9 @@ function createTypeDoc(docs, nest = "") { } function createDocs() { - /** - * I recommend commenting out unnecessary entries in development as re-generating the docs is a bit slow. - */ + if (!process.env.REFERENCES) { + return { plugins: [], items: [] }; + } const base = createTypeDoc([ { label: "/core", entrypoint: "core/src/index.ts" }, @@ -119,11 +119,15 @@ export default defineConfig({ sidebar: [ { label: "Guides", autogenerate: { directory: "guides" } }, { label: "Others", autogenerate: { directory: "others" } }, - { - label: "References", - collapsed: true, - items: [{ label: "@swapkit", items: docsSidebarItems }], - }, + ...(process.env.REFERENCES + ? [ + { + label: "References", + collapsed: true, + items: [{ label: "@swapkit", items: docsSidebarItems }], + }, + ] + : []), ], }), ], diff --git a/docs/package.json b/docs/package.json index ba2088a8a..2cd13b98b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,10 +4,7 @@ "version": "0.0.0", "scripts": { "dev": "astro dev", - "start": "astro dev", - "build": "astro build", - "preview": "astro preview", - "astro": "astro" + "deploy": "REFERENCES=true astro build" }, "dependencies": { "@astrojs/react": "4.2.0", @@ -20,7 +17,6 @@ "@swapkit/toolboxes": "workspace:*", "@swapkit/wallets": "workspace:*", "astro": "5.3.0", - "expressive-code-twoslash": "0.4.0", "sharp": "0.33.5", "starlight-typedoc": "0.19.0", "typedoc": "0.27.7", diff --git a/docs/src/content/docs/others/migrate_to_v4.mdx b/docs/src/content/docs/others/migrate_to_v4.mdx index 13b6c4ec9..3896be7e3 100644 --- a/docs/src/content/docs/others/migrate_to_v4.mdx +++ b/docs/src/content/docs/others/migrate_to_v4.mdx @@ -4,9 +4,50 @@ description: A guide to migrate to v4 and update your codebase. --- ```ts twoslash -import { EVMToolbox } from "@swapkit/toolboxes/evm" +import { BTCToolbox } from "@swapkit/toolboxes/utxo" +import { AVAXToolbox, ETHToolbox, getProvider } from "@swapkit/toolboxes/evm" +import { Chain, createSwapKit, DerivationPath } from "@swapkit/sdk" + +const btc = BTCToolbox() +const eth = ETHToolbox({ provider: getProvider(Chain.Ethereum) }) +const avax = AVAXToolbox({ provider: getProvider(Chain.Avalanche) }) + +const ethNetwork = eth.getNetworkParams() +const avaxNetwork = avax.getNetworkParams() + +const btcKeys = await btc.createKeysForPath({ + phrase: "...", + derivationPath: `${DerivationPath.BTC}/0`, +}) + +const publicKey = btcKeys.getPublicKey?.(); + +const skClient = createSwapKit() + +skClient.swap +// ^| + + + + + + + + + + + + + + + + + + + + + -const evm = EVMToolbox @@ -20,6 +61,7 @@ const evm = EVMToolbox ``` +# MIGRATE FROM CORE v3 to v4 > [!IMPORTANT]Read before continue > We migrated to combined functionality packages to simplify developer experience. You will have to change imports to use the new version of the packages. diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts index 0766b0d64..430ab64b0 100644 --- a/packages/core/src/client.ts +++ b/packages/core/src/client.ts @@ -310,7 +310,7 @@ export function SwapKit< const wallet = getWallet(chain); if (type === "transfer") { const txObject = await wallet.createTransferTx(params); - return wallet.estimateTransactionFee(txObject, feeOptionKey); + return wallet.estimateTransactionFee({ ...txObject, chain, feeOption: feeOptionKey }); } if (type === "approve" && !assetValue.isGasAsset) { @@ -321,7 +321,7 @@ export function SwapKit< from: wallet.address, }); - return wallet.estimateTransactionFee(approvalTx, feeOptionKey); + return wallet.estimateTransactionFee({ ...approvalTx, chain, feeOption: feeOptionKey }); } if (type === "swap") { @@ -333,7 +333,7 @@ export function SwapKit< assetValue, }); - return wallet.estimateTransactionFee(txObject, feeOptionKey); + return wallet.estimateTransactionFee({ ...txObject, chain, feeOption: feeOptionKey }); } const { tx } = params.route; @@ -341,10 +341,12 @@ export function SwapKit< return undefined; } - return wallet.estimateTransactionFee( - { ...(tx as EVMTransaction), value: BigInt((tx as EVMTransaction).value) }, - feeOptionKey, - ); + return wallet.estimateTransactionFee({ + ...(tx as EVMTransaction), + value: BigInt((tx as EVMTransaction).value), + feeOption: feeOptionKey, + chain, + }); } return AssetValue.from({ chain }); diff --git a/packages/helpers/src/types/chains.ts b/packages/helpers/src/types/chains.ts index 979e60aff..f8cbc84b1 100644 --- a/packages/helpers/src/types/chains.ts +++ b/packages/helpers/src/types/chains.ts @@ -212,7 +212,7 @@ export const MAYASupportedChains = [ export const RPC_URLS: Record = { [Chain.Arbitrum]: "https://arb1.arbitrum.io/rpc", - [Chain.Avalanche]: "https://avalanche-c-chain-rpc.publicnode.com", + [Chain.Avalanche]: "https://api.avax.network/ext/bc/C/rpc", [Chain.Base]: "https://base-rpc.publicnode.com", [Chain.BinanceSmartChain]: "https://bsc-dataseed.binance.org", [Chain.BitcoinCash]: "https://node-router.thorswap.net/bitcoin-cash", diff --git a/packages/helpers/src/utils/wallets.ts b/packages/helpers/src/utils/wallets.ts index 7d5a15606..41d63633e 100644 --- a/packages/helpers/src/utils/wallets.ts +++ b/packages/helpers/src/utils/wallets.ts @@ -1,4 +1,5 @@ -import type { BrowserProvider } from "ethers"; +import type { getToolboxByChain } from "@swapkit/toolboxes/evm"; +import type { BrowserProvider, JsonRpcPayload, Provider } from "ethers"; import { SwapKitError } from "../modules/swapKitError"; import { type AddChainType, @@ -116,12 +117,16 @@ export function wrapMethodWithNetworkSwitch any>( }) as unknown as T; } -export function prepareNetworkSwitch any }>({ +export function prepareNetworkSwitch< + T extends ReturnType>, + P extends BrowserProvider | Provider | JsonRpcPayload | undefined, + M extends keyof T, +>({ toolbox, chain, provider = window.ethereum, methodNames = [], -}: { toolbox: T; chain: Chain; provider?: BrowserProvider; methodNames?: string[] }) { +}: { toolbox: T; chain: Chain; provider?: P; methodNames?: M[] }) { const methodsToWrap = [ ...methodNames, "approve", @@ -138,18 +143,19 @@ export function prepareNetworkSwitch { if (!toolbox[methodName]) return object; + const method = toolbox[methodName]; if (typeof method !== "function") return object; - return { - // biome-ignore lint/performance/noAccumulatingSpread: This is a valid use case - ...object, - [methodName]: wrapMethodWithNetworkSwitch(method, provider, chain), - }; + // @ts-expect-error + const wrappedMethod = wrapMethodWithNetworkSwitch(method, provider, chain); + + // biome-ignore lint/performance/noAccumulatingSpread: valid use case + return { ...object, [methodName]: wrappedMethod }; }, {}); return { ...toolbox, ...wrappedMethods }; diff --git a/packages/plugins/src/evm/index.ts b/packages/plugins/src/evm/index.ts index 628d7458b..d4466bab9 100644 --- a/packages/plugins/src/evm/index.ts +++ b/packages/plugins/src/evm/index.ts @@ -76,7 +76,7 @@ export const EVMPlugin = createPlugin({ } const { from, to, data, value } = tx as EVMTransaction; - return wallet.sendTransaction({ from, to, data, value: BigInt(value) }, feeOptionKey); + return wallet.sendTransaction({ from, to, data, value: BigInt(value), feeOptionKey }); }, }), }); diff --git a/packages/toolboxes/src/evm/__tests__/ethereum.test.ts b/packages/toolboxes/src/evm/__tests__/ethereum.test.ts index 006a8953f..2b674d6c9 100644 --- a/packages/toolboxes/src/evm/__tests__/ethereum.test.ts +++ b/packages/toolboxes/src/evm/__tests__/ethereum.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, test } from "bun:test"; import type ethers from "@nomicfoundation/hardhat-ethers"; -import { AssetValue, Chain, FeeOption } from "@swapkit/helpers"; +import { AssetValue, Chain } from "@swapkit/helpers"; import { erc20ABI } from "@swapkit/helpers/contracts"; import type { JsonRpcProvider } from "ethers"; // import hre from "hardhat"; @@ -74,7 +74,7 @@ describe("Ethereum toolkit", () => { test.todo( "Send Token", async () => { - const USDC = await context.toolbox.createContract(USDCAddress, erc20ABI, context.provider); + const USDC = await context.toolbox.createContract(USDCAddress, erc20ABI); const balance = await USDC.balanceOf?.(emptyRecipient); expect(balance.toString()).toBe("0"); await context.toolbox.transfer({ @@ -124,7 +124,7 @@ describe("Ethereum toolkit", () => { test.todo( "Create contract tx object and sendTransaction", async () => { - const USDC = context.toolbox.createContract(USDCAddress, erc20ABI, context.provider); + const USDC = context.toolbox.createContract(USDCAddress, erc20ABI); const balance = await USDC.balanceOf?.(emptyRecipient); expect(balance.toString()).toBe("0"); @@ -138,7 +138,7 @@ describe("Ethereum toolkit", () => { }, }); - await context.toolbox.sendTransaction(txObject, FeeOption.Average); + await context.toolbox.sendTransaction(txObject); // biome-ignore lint/correctness/noUnsafeOptionalChaining: expect((await USDC?.balanceOf?.(emptyRecipient)).toString()).toBe("2222222"); }, diff --git a/packages/toolboxes/src/evm/helpers.ts b/packages/toolboxes/src/evm/helpers.ts index b2a9a251b..f789fdbdd 100644 --- a/packages/toolboxes/src/evm/helpers.ts +++ b/packages/toolboxes/src/evm/helpers.ts @@ -11,7 +11,8 @@ import { import type { BrowserProvider, JsonRpcProvider, Provider } from "ethers"; import { getEvmApi } from "./api"; -import { type EIP1559TxParams, type EVMMaxSendableAmountsParams, estimateGasPrices } from "./index"; +import { getEstimateGasPrices } from "./toolbox/baseEVMToolbox"; +import type { EIP1559TxParams, EVMMaxSendableAmountsParams } from "./types"; export const estimateMaxSendableAmount = async ({ toolbox, @@ -72,7 +73,9 @@ export const estimateMaxSendableAmount = async ({ return AssetValue.from({ chain: balance.chain, value: maxSendableAmount.getValue("string") }); }; -export const toHexString = (value: bigint) => (value > 0n ? `0x${value.toString(16)}` : "0x0"); +export function toHexString(value: bigint) { + return value > 0n ? `0x${value.toString(16)}` : "0x0"; +} export const getBalance = async ({ provider, @@ -114,32 +117,32 @@ export const getBalance = async ({ ); }; -export const estimateTransactionFee = async ( - txObject: EIP1559TxParams, - // biome-ignore lint/style/useDefaultParameterLast: Should only be used through wrapped toolboxes - feeOption: FeeOption = FeeOption.Fast, - chain: EVMChain, - provider: Provider | BrowserProvider, +export function getEstimateTransactionFee({ + provider, isEIP1559Compatible = true, -) => { - const gasPrices = (await estimateGasPrices(provider, isEIP1559Compatible))[feeOption]; - const gasLimit = await provider.estimateGas(txObject); - const assetValue = AssetValue.from({ chain }); - - if (!isEIP1559Compatible && gasPrices.gasPrice) { - return assetValue.set( - SwapKitNumber.fromBigInt(gasPrices.gasPrice * gasLimit, assetValue.decimal), - ); - } - - if (gasPrices.maxFeePerGas && gasPrices.maxPriorityFeePerGas) { - return assetValue.set( - SwapKitNumber.fromBigInt( - (gasPrices.maxFeePerGas + gasPrices.maxPriorityFeePerGas) * gasLimit, - assetValue.decimal, - ), - ); - } - - throw new Error("No gas price found"); -}; +}: { provider: Provider | BrowserProvider; isEIP1559Compatible?: boolean }) { + return async function estimateTransactionFee({ + feeOption = FeeOption.Fast, + chain, + ...txObject + }: EIP1559TxParams & { feeOption: FeeOption; chain: EVMChain }) { + const estimateGasPrices = getEstimateGasPrices({ provider, isEIP1559Compatible }); + const gasPrices = await estimateGasPrices(); + const gasLimit = await provider.estimateGas(txObject); + + const assetValue = AssetValue.from({ chain }); + const { gasPrice, maxFeePerGas, maxPriorityFeePerGas } = gasPrices[feeOption]; + + if (!isEIP1559Compatible && gasPrice) { + return assetValue.set(SwapKitNumber.fromBigInt(gasPrice * gasLimit, assetValue.decimal)); + } + + if (maxFeePerGas && maxPriorityFeePerGas) { + const fee = (maxFeePerGas + maxPriorityFeePerGas) * gasLimit; + + return assetValue.set(SwapKitNumber.fromBigInt(fee, assetValue.decimal)); + } + + throw new Error("No gas price found"); + }; +} diff --git a/packages/toolboxes/src/evm/index.ts b/packages/toolboxes/src/evm/index.ts index 58cf8ffe2..f4fa5d57a 100644 --- a/packages/toolboxes/src/evm/index.ts +++ b/packages/toolboxes/src/evm/index.ts @@ -4,17 +4,13 @@ export * from "./api"; export * from "./helpers"; export * from "./provider"; -export * from "./toolbox/EVMToolbox"; +export * from "./toolbox/baseEVMToolbox"; export * from "./types"; /** * Toolboxes */ -export * from "./toolbox/arb"; -export * from "./toolbox/avax"; -export * from "./toolbox/bsc"; -export * from "./toolbox/eth"; +export * from "./toolbox/baseEVMToolbox"; export * from "./toolbox/getToolboxByChain"; -export * from "./toolbox/matic"; export * from "./toolbox/op"; -export * from "./toolbox/base"; +export * from "./toolbox/evm"; diff --git a/packages/toolboxes/src/evm/toolbox/EVMToolbox.ts b/packages/toolboxes/src/evm/toolbox/EVMToolbox.ts deleted file mode 100644 index 1e6cbb78b..000000000 --- a/packages/toolboxes/src/evm/toolbox/EVMToolbox.ts +++ /dev/null @@ -1,662 +0,0 @@ -import { - type Asset, - type AssetValue, - Chain, - ContractAddress, - type EVMChain, - FeeOption, - SwapKitError, - SwapKitNumber, - type WalletTxParams, - isGasAsset, -} from "@swapkit/helpers"; -import { erc20ABI } from "@swapkit/helpers/contracts"; -import { - BrowserProvider, - Contract, - type ContractTransaction, - type Fragment, - type HDNodeWallet, - Interface, - type JsonFragment, - type JsonRpcSigner, - MaxInt256, - type Provider, - type Signer, - getAddress, - hexlify, - toUtf8Bytes, -} from "ethers"; - -import { - type ARBToolbox, - type AVAXToolbox, - type BASEToolbox, - type BSCToolbox, - type ETHToolbox, - type MATICToolbox, - type OPToolbox, - toHexString, -} from "../index"; -import type { - ApproveParams, - ApprovedParams, - CallParams, - EIP1559TxParams, - EVMTxParams, - EstimateCallParams, - IsApprovedParams, - LegacyEVMTxParams, - TransferParams, -} from "../types"; - -export const MAX_APPROVAL = MaxInt256; - -const baseAssetAddress: Record = { - [Chain.Arbitrum]: ContractAddress.ARB, - [Chain.Avalanche]: ContractAddress.AVAX, - [Chain.Base]: ContractAddress.BASE, - [Chain.BinanceSmartChain]: ContractAddress.BSC, - [Chain.Ethereum]: ContractAddress.ETH, - [Chain.Optimism]: ContractAddress.OP, - [Chain.Polygon]: ContractAddress.MATIC, -}; - -const stateMutable = ["payable", "nonpayable"]; -// const nonStateMutable = ['view', 'pure']; - -const isEIP1559Transaction = (tx: EVMTxParams) => - (tx as EIP1559TxParams).type === 2 || - !!(tx as EIP1559TxParams).maxFeePerGas || - !!(tx as EIP1559TxParams).maxPriorityFeePerGas; - -export const isBrowserProvider = (provider: any) => provider instanceof BrowserProvider; -export const createContract = ( - address: string, - abi: readonly (JsonFragment | Fragment)[], - provider: Provider, -) => { - return new Contract(address, Interface.from(abi), provider); -}; - -const validateAddress = (address: string) => { - try { - getAddress(address); - return true; - } catch (_error) { - return false; - } -}; - -export const isStateChangingCall = (abi: readonly JsonFragment[], functionName: string) => { - const abiFragment = abi.find((fragment: any) => fragment.name === functionName) as any; - if (!abiFragment) throw new SwapKitError("toolbox_evm_no_abi_fragment", { functionName }); - return abiFragment.stateMutability && stateMutable.includes(abiFragment.stateMutability); -}; - -export type WithSigner = T & { signer?: Signer }; - -/** - * @info call contract function - * When using this method to make a non state changing call to the blockchain, like a isApproved call, - * the signer needs to be set to undefined - */ -const call = async ( - provider: Provider, - isEIP1559Compatible: boolean, - { - callProvider, - signer, - contractAddress, - abi, - funcName, - funcParams = [], - txOverrides = {}, - feeOption = FeeOption.Fast, - }: WithSigner, -): Promise => { - const contractProvider = callProvider || provider; - if (!contractAddress) throw new Error("contractAddress must be provided"); - - const isStateChanging = isStateChangingCall(abi, funcName); - const overridesParams = { - ...txOverrides, - from: txOverrides?.from || (await signer?.getAddress()), - }; - - if (isStateChanging && isBrowserProvider(contractProvider) && signer) { - const txObject = await createContractTxObject(contractProvider, { - contractAddress, - abi, - funcName, - funcParams, - txOverrides: overridesParams, - }); - - return EIP1193SendTransaction(contractProvider, txObject) as Promise; - } - const contract = createContract(contractAddress, abi, contractProvider); - - // only use signer if the contract function is state changing - if (isStateChanging) { - if (!signer) throw new SwapKitError("toolbox_evm_no_signer"); - - const address = txOverrides?.from || (await signer.getAddress()); - - if (!address) throw new SwapKitError("toolbox_evm_no_signer_address"); - - const connectedContract = contract.connect(signer); - const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = ( - await estimateGasPrices(provider, isEIP1559Compatible) - )[feeOption]; - - const gasLimit = await contract.getFunction(funcName).estimateGas(...funcParams, txOverrides); - - // @ts-expect-error - const result = await connectedContract[funcName](...funcParams, { - ...txOverrides, - gasLimit, - maxFeePerGas, - maxPriorityFeePerGas, - gasPrice, - /** - * nonce must be set due to a possible bug with ethers.js, - * expecting a synchronous nonce while the JsonRpcProvider delivers Promise - */ - nonce: txOverrides?.nonce || (await contractProvider.getTransactionCount(address)), - }); - - return typeof result?.hash === "string" ? result?.hash : result; - } - - const result = await contract[funcName]?.(...funcParams); - - return typeof result?.hash === "string" ? result?.hash : result; -}; - -export const createContractTxObject = async ( - provider: Provider, - { contractAddress, abi, funcName, funcParams = [], txOverrides }: CallParams, -) => - createContract(contractAddress, abi, provider) - .getFunction(funcName) - .populateTransaction(...funcParams.concat(txOverrides).filter((p) => typeof p !== "undefined")); - -const approvedAmount = async ( - provider: Provider, - { assetAddress, spenderAddress, from }: IsApprovedParams, -) => - await call(provider, true, { - contractAddress: assetAddress, - abi: erc20ABI as any, - funcName: "allowance", - funcParams: [from, spenderAddress], - }); - -const isApproved = async ( - provider: Provider, - { assetAddress, spenderAddress, from, amount = MAX_APPROVAL }: IsApprovedParams, -) => { - return SwapKitNumber.fromBigInt( - await approvedAmount(provider, { assetAddress, spenderAddress, from }), - ).gte(SwapKitNumber.fromBigInt(BigInt(amount))); -}; - -const approve = async ( - provider: Provider, - { - assetAddress, - spenderAddress, - feeOptionKey = FeeOption.Fast, - amount, - gasLimitFallback, - from, - nonce, - }: ApproveParams, - signer?: Signer, - isEIP1559Compatible = true, -) => { - const funcParams = [spenderAddress, BigInt(amount || MAX_APPROVAL)]; - const txOverrides = { from }; - - const functionCallParams = { - contractAddress: assetAddress, - abi: erc20ABI, - funcName: "approve", - funcParams, - signer, - txOverrides, - }; - - if (isBrowserProvider(provider)) { - return EIP1193SendTransaction( - provider, - await createContractTxObject(provider, functionCallParams), - ); - } - - return call(provider, isEIP1559Compatible, { - ...functionCallParams, - funcParams, - txOverrides: { - from, - nonce, - gasLimit: gasLimitFallback ? BigInt(gasLimitFallback.toString()) : undefined, - }, - feeOption: feeOptionKey, - }); -}; - -const transfer = async ( - provider: Provider | BrowserProvider, - { - assetValue, - memo, - recipient, - feeOptionKey = FeeOption.Fast, - data, - from: fromOverride, - maxFeePerGas, - maxPriorityFeePerGas, - gasPrice, - ...tx - }: TransferParams, - signer?: Signer, - isEIP1559Compatible = true, -) => { - const txAmount = assetValue.getBaseValue("bigint"); - const chain = assetValue.chain as EVMChain; - - const from = fromOverride || (await signer?.getAddress()); - - if (!from) throw new SwapKitError("toolbox_evm_no_from_address"); - - if (!assetValue.isGasAsset) { - const contractAddress = getTokenAddress(assetValue, chain); - if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address"); - - // Transfer ERC20 - return call(provider, isEIP1559Compatible, { - signer, - contractAddress, - abi: erc20ABI, - funcName: "transfer", - funcParams: [recipient, txAmount], - txOverrides: { from, maxFeePerGas, maxPriorityFeePerGas, gasPrice }, - feeOption: feeOptionKey, - }); - } - // Transfer ETH - const txObject = { - ...tx, - from, - to: recipient, - value: txAmount, - data: data || hexlify(toUtf8Bytes(memo || "")), - }; - - return sendTransaction(provider, txObject, feeOptionKey, signer, isEIP1559Compatible); -}; - -export const estimateGasPrices = async (provider: Provider, isEIP1559Compatible = true) => { - try { - const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = await provider.getFeeData(); - - if (isEIP1559Compatible) { - if (maxFeePerGas === null || maxPriorityFeePerGas === null) - throw new SwapKitError("toolbox_evm_no_fee_data"); - - return { - [FeeOption.Average]: { maxFeePerGas, maxPriorityFeePerGas }, - [FeeOption.Fast]: { - maxFeePerGas: (maxFeePerGas * 15n) / 10n, - maxPriorityFeePerGas: (maxPriorityFeePerGas * 15n) / 10n, - }, - [FeeOption.Fastest]: { - maxFeePerGas: maxFeePerGas * 2n, - maxPriorityFeePerGas: maxPriorityFeePerGas * 2n, - }, - }; - } - if (!gasPrice) throw new SwapKitError("toolbox_evm_no_gas_price"); - - return { - [FeeOption.Average]: { gasPrice }, - [FeeOption.Fast]: { gasPrice: (gasPrice * 15n) / 10n }, - [FeeOption.Fastest]: { gasPrice: gasPrice * 2n }, - }; - } catch (error) { - throw new Error( - `Failed to estimate gas price: ${(error as any).msg ?? (error as any).toString()}`, - ); - } -}; - -const estimateCall = ( - provider: Provider, - { - signer, - contractAddress, - abi, - funcName, - funcParams = [], - txOverrides, - }: WithSigner, -) => { - if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address"); - - const contract = createContract(contractAddress, abi, provider); - return signer - ? contract - .connect(signer) - .getFunction(funcName) - .estimateGas(...funcParams, txOverrides) - : contract.getFunction(funcName).estimateGas(...funcParams, txOverrides); -}; - -const estimateGasLimit = ( - provider: Provider, - { - assetValue, - recipient, - memo, - from, - funcName, - funcParams, - txOverrides, - signer, - }: WalletTxParams & { - assetValue: AssetValue; - funcName?: string; - funcParams?: unknown[]; - signer?: Signer; - txOverrides?: EVMTxParams; - }, -) => { - // const value = assetValue.getBaseValue("bigint"); - const value = assetValue.bigIntValue; - - const assetAddress = assetValue.isGasAsset - ? null - : getTokenAddress(assetValue, assetValue.chain as EVMChain); - - if (assetAddress && funcName) { - // ERC20 gas estimate - return estimateCall(provider, { - contractAddress: assetAddress, - abi: erc20ABI, - funcName, - funcParams, - txOverrides, - signer, - }); - } - - return provider.estimateGas({ - from, - to: recipient, - value, - data: memo ? hexlify(toUtf8Bytes(memo)) : undefined, - }); -}; - -const sendTransaction = async ( - provider: Provider | BrowserProvider, - tx: EVMTxParams, - feeOptionKey: FeeOption = FeeOption.Fast, - signer?: Signer, - isEIP1559Compatible = true, - // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: refactor -) => { - if (!signer) throw new SwapKitError("toolbox_evm_no_signer"); - const { from, to, data, value, ...transaction } = tx; - if (!to) throw new SwapKitError("toolbox_evm_no_to_address"); - - const parsedTxObject = { - ...transaction, - data: data || "0x", - to, - from, - value: BigInt(value || 0), - }; - - // early return to skip gas estimation if provider is EIP-1193 - if (isBrowserProvider(provider)) { - return EIP1193SendTransaction(provider, parsedTxObject); - } - - const address = from || (await signer.getAddress()); - const nonce = tx.nonce || (await provider.getTransactionCount(address)); - const chainId = (await provider.getNetwork()).chainId; - - const isEIP1559 = isEIP1559Transaction(parsedTxObject) || isEIP1559Compatible; - - const feeData = - (isEIP1559 && - !( - (parsedTxObject as EIP1559TxParams).maxFeePerGas && - (parsedTxObject as EIP1559TxParams).maxPriorityFeePerGas - )) || - !(parsedTxObject as LegacyEVMTxParams).gasPrice - ? Object.entries( - (await estimateGasPrices(provider, isEIP1559Compatible))[feeOptionKey], - ).reduce( - // biome-ignore lint/performance/noAccumulatingSpread: this is a small object - (acc, [k, v]) => ({ ...acc, [k]: toHexString(BigInt(v)) }), - {} as { - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - gasPrice?: string; - }, - ) - : {}; - let gasLimit: string; - try { - gasLimit = toHexString( - parsedTxObject.gasLimit || ((await provider.estimateGas(parsedTxObject)) * 11n) / 10n, - ); - } catch (error) { - throw new SwapKitError("toolbox_evm_error_estimating_gas_limit", { error }); - } - - try { - const txObject = { - ...parsedTxObject, - chainId, - type: isEIP1559 ? 2 : 0, - gasLimit, - nonce, - ...feeData, - }; - - try { - const response = await signer.sendTransaction(txObject); - return response.hash; - } catch (_error) { - const txHex = await signer.signTransaction({ - ...txObject, - from: address, - }); - const response = await provider.broadcastTransaction(txHex); - return response.hash; - } - } catch (error) { - throw new SwapKitError("toolbox_evm_error_sending_transaction", { error }); - } -}; - -/** - * Exported helper functions - */ -export const toChecksumAddress = (address: string) => getAddress(address); - -export const EIP1193SendTransaction = ( - provider: Provider | BrowserProvider, - { from, to, data, value }: EVMTxParams | ContractTransaction, -): Promise => { - if (!isBrowserProvider(provider)) - throw new SwapKitError("toolbox_evm_provider_not_eip1193_compatible"); - return (provider as BrowserProvider).send("eth_sendTransaction", [ - { value: toHexString(BigInt(value || 0)), from, to, data } as any, - ]); -}; - -export const getChecksumAddressFromAsset = (asset: Asset, chain: EVMChain) => { - const assetAddress = getTokenAddress(asset, chain); - - if (assetAddress) { - return getAddress(assetAddress.toLowerCase()); - } - - throw new SwapKitError("toolbox_evm_invalid_gas_asset_address"); -}; - -export const getTokenAddress = ({ chain, symbol, ticker }: Asset, baseAssetChain: EVMChain) => { - try { - const isBSCBNB = chain === Chain.BinanceSmartChain && symbol === "BNB" && ticker === "BNB"; - const isBaseAsset = - chain === baseAssetChain && symbol === baseAssetChain && ticker === baseAssetChain; - const isEVMAsset = - [Chain.Arbitrum, Chain.Base].includes(chain) && symbol === "ETH" && ticker === "ETH"; - - if (isBaseAsset || isBSCBNB || isEVMAsset) { - return baseAssetAddress[baseAssetChain]; - } - - // strip 0X only - 0x is still valid - return getAddress(symbol.slice(ticker.length + 1).replace(/^0X/, "")); - } catch (_error) { - return null; - } -}; - -const createTransferTx = async ( - provider: Provider | BrowserProvider, - { - assetValue, - memo, - recipient, - feeOptionKey = FeeOption.Fast, - data, - from: fromOverride, - maxFeePerGas, - maxPriorityFeePerGas, - gasPrice, - ...tx - }: TransferParams, - signer?: Signer, -) => { - const txAmount = assetValue.getBaseValue("bigint"); - const chain = assetValue.chain as EVMChain; - - const from = fromOverride || (await signer?.getAddress()); - - if (!from) throw new SwapKitError("toolbox_evm_no_from_address"); - - if (!isGasAsset(assetValue)) { - const contractAddress = getTokenAddress(assetValue, chain); - if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address"); - - // Transfer ERC20 - return createContractTxObject(provider, { - contractAddress, - abi: erc20ABI, - funcName: "transfer", - funcParams: [recipient, txAmount], - txOverrides: { from, maxFeePerGas, maxPriorityFeePerGas, gasPrice }, - }); - } - // Transfer ETH - const txObject = { - ...tx, - from, - to: recipient, - value: txAmount, - data: data || hexlify(toUtf8Bytes(memo || "")), - }; - - return txObject; -}; - -const createApprovalTx = async ( - provider: Provider, - { assetAddress, spenderAddress, amount, from }: ApproveParams, - signer?: Signer, -) => { - const funcParams = [spenderAddress, BigInt(amount || MAX_APPROVAL)]; - const txOverrides = { from }; - - const functionCallParams = { - contractAddress: assetAddress, - abi: erc20ABI, - funcName: "approve", - funcParams, - signer, - txOverrides, - }; - - const txObject = await createContractTxObject(provider, functionCallParams); - - return txObject; -}; - -function signMessage(signer?: Signer | JsonRpcSigner | HDNodeWallet) { - if (!signer) throw new SwapKitError("toolbox_evm_no_signer"); - - return signer.signMessage; -} - -export const EVMToolbox = ({ - provider, - signer, - isEIP1559Compatible = true, -}: { - signer?: Signer | JsonRpcSigner | HDNodeWallet; - provider: Provider | BrowserProvider; - isEIP1559Compatible?: boolean; -}) => ({ - approve: (params: ApproveParams) => approve(provider, params, signer, isEIP1559Compatible), - approvedAmount: (params: ApprovedParams) => approvedAmount(provider, params), - broadcastTransaction: provider.broadcastTransaction, - call: (params: CallParams) => call(provider, isEIP1559Compatible, { ...params, signer }), - createContract: ( - address: string, - abi: (JsonFragment | Fragment)[], - contractProvider?: Provider, - ) => createContract(address, abi, contractProvider || provider), - createContractTxObject: (params: CallParams) => createContractTxObject(provider, params), - EIP1193SendTransaction: (tx: EIP1559TxParams) => EIP1193SendTransaction(provider, tx), - estimateCall: (params: EstimateCallParams) => estimateCall(provider, { ...params, signer }), - estimateGasLimit: ({ - assetValue, - recipient, - memo, - }: WalletTxParams & { assetValue: AssetValue }) => - estimateGasLimit(provider, { assetValue, recipient, memo, signer }), - estimateGasPrices: () => estimateGasPrices(provider, isEIP1559Compatible), - isApproved: (params: IsApprovedParams) => isApproved(provider, params), - sendTransaction: (params: EIP1559TxParams, feeOption?: FeeOption) => - sendTransaction(provider, params, feeOption, signer, isEIP1559Compatible), - transfer: (params: TransferParams) => transfer(provider, params, signer, isEIP1559Compatible), - validateAddress, - createTransferTx: (params: TransferParams) => createTransferTx(provider, params, signer), - createApprovalTx: (params: ApproveParams) => createApprovalTx(provider, params, signer), - signMessage: signMessage(signer), -}); - -export const evmValidateAddress = ({ address }: { address: string }) => validateAddress(address); - -export type EVMWallet = ReturnType; -export type EVMWalletType = { - [Chain.Arbitrum]: ReturnType; - [Chain.Avalanche]: ReturnType; - [Chain.Base]: ReturnType; - [Chain.BinanceSmartChain]: ReturnType; - [Chain.Ethereum]: ReturnType; - [Chain.Optimism]: ReturnType; - [Chain.Polygon]: ReturnType; -}; - -export type EVMWallets = { - [chain in EVMChain]: EVMWallet & EVMWalletType[chain]; -}; diff --git a/packages/toolboxes/src/evm/toolbox/arb.ts b/packages/toolboxes/src/evm/toolbox/arb.ts deleted file mode 100644 index 14b6f727c..000000000 --- a/packages/toolboxes/src/evm/toolbox/arb.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { - BaseDecimal, - Chain, - ChainId, - ChainToExplorerUrl, - FeeOption, - SKConfig, -} from "@swapkit/helpers"; -import type { BrowserProvider, JsonRpcProvider, Provider, Signer } from "ethers"; - -import { type EVMTxBaseParams, estimateTransactionFee, getBalance } from "../index"; - -import { EVMToolbox } from "./EVMToolbox"; - -const getNetworkParams = () => ({ - chainId: ChainId.ArbitrumHex, - chainName: "Arbitrum One", - nativeCurrency: { name: "Ethereum", symbol: Chain.Ethereum, decimals: BaseDecimal.ETH }, - rpcUrls: [SKConfig.get("rpcUrls")[Chain.Arbitrum]], - blockExplorerUrls: [ChainToExplorerUrl[Chain.Arbitrum]], -}); - -const estimateGasPrices = async (provider: Provider) => { - try { - const { gasPrice } = await provider.getFeeData(); - - if (!gasPrice) throw new Error("No fee data available"); - - return { - [FeeOption.Average]: { gasPrice }, - [FeeOption.Fast]: { gasPrice }, - [FeeOption.Fastest]: { gasPrice }, - }; - } catch (error) { - throw new Error( - `Failed to estimate gas price: ${(error as any).msg ?? (error as any).toString()}`, - ); - } -}; - -export const ARBToolbox = ({ - provider, - signer, -}: { signer?: Signer; provider: JsonRpcProvider | BrowserProvider }) => { - const evmToolbox = EVMToolbox({ provider, signer, isEIP1559Compatible: false }); - const chain = Chain.Arbitrum; - - return { - ...evmToolbox, - getNetworkParams, - estimateGasPrices: () => estimateGasPrices(provider), - estimateTransactionFee: (txObject: EVMTxBaseParams) => - estimateTransactionFee(txObject, FeeOption.Average, chain, provider, false), - getBalance: ( - address: string, - potentialScamFilter = true, - overwriteProvider?: JsonRpcProvider | BrowserProvider, - ) => - getBalance({ provider: overwriteProvider || provider, address, chain, potentialScamFilter }), - }; -}; diff --git a/packages/toolboxes/src/evm/toolbox/avax.ts b/packages/toolboxes/src/evm/toolbox/avax.ts deleted file mode 100644 index 2c557423b..000000000 --- a/packages/toolboxes/src/evm/toolbox/avax.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { BaseDecimal, Chain, ChainId, ChainToExplorerUrl, type FeeOption } from "@swapkit/helpers"; -import type { BrowserProvider, JsonRpcProvider, Signer } from "ethers"; - -import { type EVMTxBaseParams, estimateTransactionFee, getBalance } from "../index"; - -import { EVMToolbox } from "./EVMToolbox"; - -const getNetworkParams = () => ({ - chainId: ChainId.AvalancheHex, - chainName: "Avalanche Network", - nativeCurrency: { name: "Avalanche", symbol: Chain.Avalanche, decimals: BaseDecimal.AVAX }, - // Use external rpc URL so wallets don't throw warning to user - rpcUrls: ["https://api.avax.network/ext/bc/C/rpc"], - blockExplorerUrls: [ChainToExplorerUrl[Chain.Avalanche]], -}); - -export const AVAXToolbox = ({ - provider, - signer, -}: { signer?: Signer; provider: JsonRpcProvider | BrowserProvider }) => { - const evmToolbox = EVMToolbox({ provider, signer }); - const chain = Chain.Avalanche; - - return { - ...evmToolbox, - getNetworkParams, - estimateTransactionFee: (txObject: EVMTxBaseParams, feeOptionKey: FeeOption) => - estimateTransactionFee(txObject, feeOptionKey, chain, provider), - getBalance: ( - address: string, - potentialScamFilter = true, - overwriteProvider?: JsonRpcProvider | BrowserProvider, - ) => - getBalance({ provider: overwriteProvider || provider, address, chain, potentialScamFilter }), - }; -}; diff --git a/packages/toolboxes/src/evm/toolbox/base.ts b/packages/toolboxes/src/evm/toolbox/base.ts deleted file mode 100644 index 66f1bc98e..000000000 --- a/packages/toolboxes/src/evm/toolbox/base.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - BaseDecimal, - Chain, - ChainId, - ChainToExplorerUrl, - type FeeOption, - SKConfig, -} from "@swapkit/helpers"; -import type { BrowserProvider, JsonRpcProvider, Signer } from "ethers"; - -import { type EVMTxBaseParams, estimateTransactionFee, getBalance } from "../index"; - -import { EVMToolbox } from "./EVMToolbox"; - -const getNetworkParams = () => ({ - chainId: ChainId.BaseHex, - chainName: "Base Mainnet", - nativeCurrency: { name: "Ethereum", symbol: Chain.Ethereum, decimals: BaseDecimal.ETH }, - rpcUrls: [SKConfig.get("rpcUrls")[Chain.Base]], - blockExplorerUrls: [ChainToExplorerUrl[Chain.Base]], -}); - -export const BASEToolbox = ({ - provider, - signer, -}: { signer?: Signer; provider: JsonRpcProvider | BrowserProvider }) => { - const evmToolbox = EVMToolbox({ provider, signer }); - const chain = Chain.Base; - - return { - ...evmToolbox, - getNetworkParams, - estimateTransactionFee: (txObject: EVMTxBaseParams, feeOptionKey: FeeOption) => - estimateTransactionFee(txObject, feeOptionKey, chain, provider), - getBalance: async ( - address: string, - potentialScamFilter = true, - overwriteProvider?: JsonRpcProvider | BrowserProvider, - ) => - getBalance({ provider: overwriteProvider || provider, address, chain, potentialScamFilter }), - }; -}; diff --git a/packages/toolboxes/src/evm/toolbox/baseEVMToolbox.ts b/packages/toolboxes/src/evm/toolbox/baseEVMToolbox.ts new file mode 100644 index 000000000..9cd275566 --- /dev/null +++ b/packages/toolboxes/src/evm/toolbox/baseEVMToolbox.ts @@ -0,0 +1,667 @@ +import { + type Asset, + type AssetValue, + Chain, + ContractAddress, + type EVMChain, + FeeOption, + SwapKitError, + SwapKitNumber, + type WalletTxParams, + isGasAsset, +} from "@swapkit/helpers"; +import { erc20ABI } from "@swapkit/helpers/contracts"; +import { + BrowserProvider, + Contract, + type ContractTransaction, + type Fragment, + type HDNodeWallet, + Interface, + type JsonFragment, + type JsonRpcSigner, + type Provider, + type Signer, + getAddress, + hexlify, + toUtf8Bytes, +} from "ethers"; + +import { + type ARBToolbox, + type AVAXToolbox, + type BASEToolbox, + type BSCToolbox, + type ETHToolbox, + type MATICToolbox, + type OPToolbox, + toHexString, +} from "../index"; +import type { + ApproveParams, + CallParams, + EIP1559TxParams, + EVMTxParams, + EstimateCallParams, + IsApprovedParams, + LegacyEVMTxParams, + TransferParams, +} from "../types"; + +export const MAX_APPROVAL = BigInt( + "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", +); + +export function BaseEVMToolbox< + P extends Provider | BrowserProvider, + S extends Signer | JsonRpcSigner | HDNodeWallet | undefined, +>({ + provider, + signer, + isEIP1559Compatible = true, +}: { signer: S; provider: P; isEIP1559Compatible?: boolean }) { + return { + call: getCall({ provider, signer, isEIP1559Compatible }), + estimateCall: getEstimateCall({ provider, signer }), + EIP1193SendTransaction: getEIP1193SendTransaction(provider), + approve: getApprove({ provider, signer, isEIP1559Compatible }), + approvedAmount: getApprovedAmount({ provider }), + broadcastTransaction: provider.broadcastTransaction, + createApprovalTx: getCreateApprovalTx(provider), + createContract: getCreateContract({ provider }), + createContractTxObject: getCreateContractTxObject(provider), + createTransferTx: getCreateTransferTx({ provider, signer }), + estimateGasLimit: getEstimateGasLimit({ provider, signer }), + estimateGasPrices: getEstimateGasPrices({ provider, isEIP1559Compatible }), + isApproved: getIsApproved({ provider }), + sendTransaction: getSendTransaction({ provider, signer, isEIP1559Compatible }), + signMessage: signer?.signMessage, + transfer: getTransfer({ provider, signer, isEIP1559Compatible }), + validateAddress: (address: string) => evmValidateAddress({ address }), + }; +} + +export function evmValidateAddress({ address }: { address: string }) { + try { + getAddress(address); + return true; + } catch (_error) { + return false; + } +} + +export type EVMWallet = ReturnType; +export type EVMWalletType = { + [Chain.Arbitrum]: ReturnType; + [Chain.Avalanche]: ReturnType; + [Chain.Base]: ReturnType; + [Chain.BinanceSmartChain]: ReturnType; + [Chain.Ethereum]: ReturnType; + [Chain.Optimism]: ReturnType; + [Chain.Polygon]: ReturnType; +}; + +export type EVMWallets = { + [chain in EVMChain]: EVMWallet & EVMWalletType[chain]; +}; + +const baseAssetAddress: Record = { + [Chain.Arbitrum]: ContractAddress.ARB, + [Chain.Avalanche]: ContractAddress.AVAX, + [Chain.Base]: ContractAddress.BASE, + [Chain.BinanceSmartChain]: ContractAddress.BSC, + [Chain.Ethereum]: ContractAddress.ETH, + [Chain.Optimism]: ContractAddress.OP, + [Chain.Polygon]: ContractAddress.MATIC, +}; + +const stateMutable = ["payable", "nonpayable"]; +// const nonStateMutable = ['view', 'pure']; + +const isEIP1559Transaction = (tx: EVMTxParams) => + (tx as EIP1559TxParams).type === 2 || + !!(tx as EIP1559TxParams).maxFeePerGas || + !!(tx as EIP1559TxParams).maxPriorityFeePerGas; + +type ToolboxWrapParams

= T & { + isEIP1559Compatible?: boolean; + provider: P; + signer?: Signer; +}; + +export function isBrowserProvider(provider: any) { + return provider instanceof BrowserProvider; +} + +export function createContract( + address: string, + abi: readonly (JsonFragment | Fragment)[], + provider: Provider, +) { + return new Contract(address, Interface.from(abi), provider); +} + +export function getCreateContract({ provider }: ToolboxWrapParams) { + return function createContract(address: string, abi: readonly (JsonFragment | Fragment)[]) { + return new Contract(address, Interface.from(abi), provider); + }; +} + +export function isStateChangingCall({ + abi, + funcName, +}: { abi: readonly JsonFragment[]; funcName: string }) { + const abiFragment = abi.find((fragment: any) => fragment.name === funcName) as any; + if (!abiFragment) throw new SwapKitError("toolbox_evm_no_abi_fragment", { funcName }); + return abiFragment.stateMutability && stateMutable.includes(abiFragment.stateMutability); +} + +function getCall({ provider, isEIP1559Compatible, signer }: ToolboxWrapParams) { + /** + * @info call contract function + * When using this method to make a non state changing call to the blockchain, like a isApproved call, + * the signer needs to be set to undefined + */ + return async function call({ + callProvider, + contractAddress, + abi, + funcName, + funcParams = [], + txOverrides = {}, + feeOption = FeeOption.Fast, + }: CallParams): Promise { + const contractProvider = callProvider || provider; + if (!contractAddress) throw new Error("contractAddress must be provided"); + + const isStateChanging = isStateChangingCall({ abi, funcName }); + + if (isStateChanging && isBrowserProvider(contractProvider) && signer) { + const createTx = getCreateContractTxObject({ provider: contractProvider }); + const from = txOverrides?.from || (await signer?.getAddress()); + const txObject = await createTx({ + contractAddress, + abi, + funcName, + funcParams, + txOverrides: { ...txOverrides, from }, + }); + const sendTx = getEIP1193SendTransaction(contractProvider); + + return sendTx(txObject) as Promise; + } + const contract = createContract(contractAddress, abi, contractProvider); + + // only use signer if the contract function is state changing + if (isStateChanging) { + if (!signer) throw new SwapKitError("toolbox_evm_no_signer"); + + const from = txOverrides?.from || (await signer.getAddress()); + if (!from) throw new SwapKitError("toolbox_evm_no_signer_address"); + + const connectedContract = contract.connect(signer); + const estimateGasPrices = getEstimateGasPrices({ provider, isEIP1559Compatible }); + const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = (await estimateGasPrices())[ + feeOption + ]; + + const gasLimit = await contract.getFunction(funcName).estimateGas(...funcParams, txOverrides); + + // @ts-expect-error + const result = await connectedContract[funcName](...funcParams, { + ...txOverrides, + gasLimit, + maxFeePerGas, + maxPriorityFeePerGas, + gasPrice, + /** + * nonce must be set due to a possible bug with ethers.js, + * expecting a synchronous nonce while the JsonRpcProvider delivers Promise + */ + nonce: txOverrides?.nonce || (await contractProvider.getTransactionCount(from)), + }); + + return typeof result?.hash === "string" ? result?.hash : result; + } + + const result = await contract[funcName]?.(...funcParams); + + return typeof result?.hash === "string" ? result?.hash : result; + }; +} + +export function getCreateContractTxObject({ provider }: ToolboxWrapParams) { + return async ({ contractAddress, abi, funcName, funcParams = [], txOverrides }: CallParams) => + createContract(contractAddress, abi, provider) + .getFunction(funcName) + .populateTransaction( + ...funcParams.concat(txOverrides).filter((p) => typeof p !== "undefined"), + ); +} + +function getApprovedAmount({ provider }: ToolboxWrapParams) { + return function approveAmount({ assetAddress, spenderAddress, from }: IsApprovedParams) { + const call = getCall({ provider, isEIP1559Compatible: true }); + + return call({ + contractAddress: assetAddress, + abi: erc20ABI, + funcName: "allowance", + funcParams: [from, spenderAddress], + }); + }; +} + +function getIsApproved({ provider }: ToolboxWrapParams) { + return async function isApproved({ + assetAddress, + spenderAddress, + from, + amount = MAX_APPROVAL, + }: IsApprovedParams) { + const approvedAmount = await getApprovedAmount({ provider })({ + assetAddress, + spenderAddress, + from, + }); + + return SwapKitNumber.fromBigInt(approvedAmount).gte(SwapKitNumber.fromBigInt(BigInt(amount))); + }; +} + +function getApprove({ signer, isEIP1559Compatible = true, provider }: ToolboxWrapParams) { + return async function approve({ + assetAddress, + spenderAddress, + feeOptionKey = FeeOption.Fast, + amount, + gasLimitFallback, + from, + nonce, + }: ApproveParams) { + const funcParams = [spenderAddress, BigInt(amount || MAX_APPROVAL)]; + + const functionCallParams = { + contractAddress: assetAddress, + abi: erc20ABI, + funcName: "approve", + funcParams, + signer, + txOverrides: { from }, + }; + + if (isBrowserProvider(provider)) { + const createTx = getCreateContractTxObject(provider); + const sendTx = getEIP1193SendTransaction(provider); + const txObject = await createTx(functionCallParams); + + return sendTx(txObject); + } + + const call = getCall({ provider, isEIP1559Compatible }); + + return call({ + ...functionCallParams, + funcParams, + txOverrides: { + from, + nonce, + gasLimit: gasLimitFallback ? BigInt(gasLimitFallback.toString()) : undefined, + }, + feeOption: feeOptionKey, + }); + }; +} + +function getTransfer({ signer, isEIP1559Compatible = true, provider }: ToolboxWrapParams) { + return async function transfer({ + assetValue, + memo, + recipient, + feeOptionKey = FeeOption.Fast, + data, + from: fromOverride, + maxFeePerGas, + maxPriorityFeePerGas, + gasPrice, + ...tx + }: TransferParams) { + const txAmount = assetValue.getBaseValue("bigint"); + const chain = assetValue.chain as EVMChain; + const from = fromOverride || (await signer?.getAddress()); + + if (!from) throw new SwapKitError("toolbox_evm_no_from_address"); + + if (assetValue.isGasAsset) { + const sendTx = getSendTransaction({ provider, signer, isEIP1559Compatible }); + const txObject = { + ...tx, + from, + to: recipient, + value: txAmount, + data: data || hexlify(toUtf8Bytes(memo || "")), + feeOptionKey, + }; + + return sendTx(txObject); + } + + const call = getCall({ signer, provider, isEIP1559Compatible }); + const contractAddress = getTokenAddress(assetValue, chain); + if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address"); + + return call({ + contractAddress, + abi: erc20ABI, + funcName: "transfer", + funcParams: [recipient, txAmount], + txOverrides: { from, maxFeePerGas, maxPriorityFeePerGas, gasPrice }, + feeOption: feeOptionKey, + }); + }; +} + +export function getEstimateGasPrices({ + provider, + isEIP1559Compatible = true, +}: { provider: Provider; isEIP1559Compatible?: boolean }) { + return async function estimateGasPrices() { + try { + const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = await provider.getFeeData(); + + if (isEIP1559Compatible) { + if (maxFeePerGas === null || maxPriorityFeePerGas === null) + throw new SwapKitError("toolbox_evm_no_fee_data"); + + return { + [FeeOption.Average]: { maxFeePerGas, maxPriorityFeePerGas }, + [FeeOption.Fast]: { + maxFeePerGas: (maxFeePerGas * 15n) / 10n, + maxPriorityFeePerGas: (maxPriorityFeePerGas * 15n) / 10n, + }, + [FeeOption.Fastest]: { + maxFeePerGas: maxFeePerGas * 2n, + maxPriorityFeePerGas: maxPriorityFeePerGas * 2n, + }, + }; + } + if (!gasPrice) throw new SwapKitError("toolbox_evm_no_gas_price"); + + return { + [FeeOption.Average]: { gasPrice }, + [FeeOption.Fast]: { gasPrice: (gasPrice * 15n) / 10n }, + [FeeOption.Fastest]: { gasPrice: gasPrice * 2n }, + }; + } catch (error) { + throw new Error( + `Failed to estimate gas price: ${(error as any).msg ?? (error as any).toString()}`, + ); + } + }; +} + +function getEstimateCall({ provider, signer }: { signer?: Signer; provider: Provider }) { + return function estimateCall({ + contractAddress, + abi, + funcName, + funcParams = [], + txOverrides, + }: EstimateCallParams) { + if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address"); + + const contract = createContract(contractAddress, abi, provider); + return signer + ? contract + .connect(signer) + .getFunction(funcName) + .estimateGas(...funcParams, txOverrides) + : contract.getFunction(funcName).estimateGas(...funcParams, txOverrides); + }; +} + +function getEstimateGasLimit({ provider, signer }: ToolboxWrapParams) { + return function estimateGasLimit({ + assetValue, + recipient, + memo, + from, + funcName, + funcParams, + txOverrides, + }: WalletTxParams & { + assetValue: AssetValue; + funcName?: string; + funcParams?: unknown[]; + txOverrides?: EVMTxParams; + }) { + // const value = assetValue.getBaseValue("bigint"); + const value = assetValue.bigIntValue; + + const assetAddress = assetValue.isGasAsset + ? null + : getTokenAddress(assetValue, assetValue.chain as EVMChain); + + if (assetAddress && funcName) { + const estimateCall = getEstimateCall({ provider, signer }); + // ERC20 gas estimate + return estimateCall({ + contractAddress: assetAddress, + abi: erc20ABI, + funcName, + funcParams, + txOverrides, + }); + } + + return provider.estimateGas({ + from, + to: recipient, + value, + data: memo ? hexlify(toUtf8Bytes(memo)) : undefined, + }); + }; +} + +function getSendTransaction({ provider, signer, isEIP1559Compatible = true }: ToolboxWrapParams) { + return async function sendTransaction({ + feeOptionKey = FeeOption.Fast, + ...tx + }: EVMTxParams & { feeOptionKey?: FeeOption }) { + const { from, to, data, value, ...transaction } = tx; + + if (!signer) throw new SwapKitError("toolbox_evm_no_signer"); + if (!to) throw new SwapKitError("toolbox_evm_no_to_address"); + + const parsedTxObject = { + ...transaction, + data: data || "0x", + to, + from, + value: BigInt(value || 0), + }; + + // early return to skip gas estimation if provider is EIP-1193 + if (isBrowserProvider(provider)) { + const sendTx = getEIP1193SendTransaction(provider); + return sendTx(parsedTxObject); + } + + const address = from || (await signer.getAddress()); + const nonce = tx.nonce || (await provider.getTransactionCount(address)); + const chainId = (await provider.getNetwork()).chainId; + + const isEIP1559 = isEIP1559Transaction(parsedTxObject) || isEIP1559Compatible; + const estimateGasPrices = getEstimateGasPrices({ provider, isEIP1559Compatible }); + + const feeData = + (isEIP1559 && + !( + (parsedTxObject as EIP1559TxParams).maxFeePerGas && + (parsedTxObject as EIP1559TxParams).maxPriorityFeePerGas + )) || + !(parsedTxObject as LegacyEVMTxParams).gasPrice + ? Object.entries((await estimateGasPrices())[feeOptionKey]).reduce( + // biome-ignore lint/performance/noAccumulatingSpread: this is a small object + (acc, [k, v]) => ({ ...acc, [k]: toHexString(BigInt(v)) }), + {} as { + maxFeePerGas?: string; + maxPriorityFeePerGas?: string; + gasPrice?: string; + }, + ) + : {}; + let gasLimit: string; + try { + gasLimit = toHexString( + parsedTxObject.gasLimit || ((await provider.estimateGas(parsedTxObject)) * 11n) / 10n, + ); + } catch (error) { + throw new SwapKitError("toolbox_evm_error_estimating_gas_limit", { error }); + } + + try { + const txObject = { + ...parsedTxObject, + chainId, + type: isEIP1559 ? 2 : 0, + gasLimit, + nonce, + ...feeData, + }; + + try { + const response = await signer.sendTransaction(txObject); + return response.hash; + } catch (_error) { + const txHex = await signer.signTransaction({ + ...txObject, + from: address, + }); + const response = await provider.broadcastTransaction(txHex); + return response.hash; + } + } catch (error) { + throw new SwapKitError("toolbox_evm_error_sending_transaction", { error }); + } + }; +} + +/** + * Exported helper functions + */ +export function toChecksumAddress(address: string) { + return getAddress(address); +} + +export function getEIP1193SendTransaction(provider: Provider | BrowserProvider) { + return function EIP1193SendTransaction({ + value, + ...params + }: EVMTxParams | ContractTransaction): Promise { + if (!isBrowserProvider(provider)) { + throw new SwapKitError("toolbox_evm_provider_not_eip1193_compatible"); + } + + return (provider as BrowserProvider).send("eth_sendTransaction", [ + { value: toHexString(BigInt(value || 0)), ...params } as any, + ]); + }; +} + +export function getChecksumAddressFromAsset(asset: Asset, chain: EVMChain) { + const assetAddress = getTokenAddress(asset, chain); + + if (assetAddress) { + return getAddress(assetAddress.toLowerCase()); + } + + throw new SwapKitError("toolbox_evm_invalid_gas_asset_address"); +} + +export function getTokenAddress({ chain, symbol, ticker }: Asset, baseAssetChain: EVMChain) { + try { + const isBSCBNB = chain === Chain.BinanceSmartChain && symbol === "BNB" && ticker === "BNB"; + const isBaseAsset = + chain === baseAssetChain && symbol === baseAssetChain && ticker === baseAssetChain; + const isEVMAsset = + [Chain.Arbitrum, Chain.Base].includes(chain) && symbol === "ETH" && ticker === "ETH"; + + if (isBaseAsset || isBSCBNB || isEVMAsset) { + return baseAssetAddress[baseAssetChain]; + } + + // strip 0X only - 0x is still valid + return getAddress(symbol.slice(ticker.length + 1).replace(/^0X/, "")); + } catch (_error) { + return null; + } +} + +function getCreateTransferTx({ + provider, + signer, +}: { provider: Provider | BrowserProvider; signer?: Signer }) { + return async function createTransferTx({ + assetValue, + memo, + recipient, + feeOptionKey = FeeOption.Fast, + data, + from: fromOverride, + maxFeePerGas, + maxPriorityFeePerGas, + gasPrice, + ...tx + }: TransferParams) { + const txAmount = assetValue.getBaseValue("bigint"); + const chain = assetValue.chain as EVMChain; + const from = fromOverride || (await signer?.getAddress()); + + if (!from) throw new SwapKitError("toolbox_evm_no_from_address"); + + if (isGasAsset(assetValue)) { + return { + ...tx, + from, + to: recipient, + value: txAmount, + data: data || hexlify(toUtf8Bytes(memo || "")), + }; + } + + const contractAddress = getTokenAddress(assetValue, chain); + if (!contractAddress) throw new SwapKitError("toolbox_evm_no_contract_address"); + const createTx = getCreateContractTxObject(provider); + + return createTx({ + contractAddress, + abi: erc20ABI, + funcName: "transfer", + funcParams: [recipient, txAmount], + txOverrides: { from, maxFeePerGas, maxPriorityFeePerGas, gasPrice }, + }); + }; +} + +function getCreateApprovalTx(provider: Provider) { + return async function createApprovalTx({ + assetAddress, + spenderAddress, + amount, + from, + }: ApproveParams) { + const createTx = getCreateContractTxObject(provider); + const funcParams = [spenderAddress, BigInt(amount || MAX_APPROVAL)]; + + const txObject = await createTx({ + contractAddress: assetAddress, + abi: erc20ABI, + funcName: "approve", + funcParams, + txOverrides: { from }, + }); + + return txObject; + }; +} diff --git a/packages/toolboxes/src/evm/toolbox/bsc.ts b/packages/toolboxes/src/evm/toolbox/bsc.ts deleted file mode 100644 index 1b2d5dadf..000000000 --- a/packages/toolboxes/src/evm/toolbox/bsc.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { BaseDecimal, Chain, ChainId, ChainToExplorerUrl, type FeeOption } from "@swapkit/helpers"; -import type { BrowserProvider, JsonRpcProvider, Signer } from "ethers"; - -import { type EVMTxBaseParams, estimateTransactionFee, getBalance } from "../index"; -import { EVMToolbox } from "./EVMToolbox"; - -const getNetworkParams = () => ({ - chainId: ChainId.BinanceSmartChainHex, - chainName: "BNB Chain", - nativeCurrency: { name: "Binance Coin", symbol: "BNB", decimals: BaseDecimal.BSC }, - rpcUrls: ["https://bsc-dataseed.binance.org"], - blockExplorerUrls: [ChainToExplorerUrl[Chain.BinanceSmartChain]], -}); - -export const BSCToolbox = ({ - provider, - signer, -}: { signer?: Signer; provider: JsonRpcProvider | BrowserProvider }) => { - const evmToolbox = EVMToolbox({ provider, signer, isEIP1559Compatible: false }); - const chain = Chain.BinanceSmartChain; - - return { - ...evmToolbox, - getNetworkParams, - estimateTransactionFee: (txObject: EVMTxBaseParams, feeOptionKey: FeeOption) => - estimateTransactionFee(txObject, feeOptionKey, chain, provider, false), - getBalance: ( - address: string, - potentialScamFilter = true, - overwriteProvider?: JsonRpcProvider | BrowserProvider, - ) => - getBalance({ provider: overwriteProvider || provider, address, chain, potentialScamFilter }), - }; -}; diff --git a/packages/toolboxes/src/evm/toolbox/eth.ts b/packages/toolboxes/src/evm/toolbox/eth.ts deleted file mode 100644 index 708eb4581..000000000 --- a/packages/toolboxes/src/evm/toolbox/eth.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Chain, FeeOption } from "@swapkit/helpers"; -import type { BrowserProvider, JsonRpcProvider, JsonRpcSigner, Signer } from "ethers"; - -import { type EVMTxBaseParams, estimateTransactionFee, getBalance } from "../index"; - -import { multicallAbi } from "../contracts/eth/multicall"; -import { EVMToolbox } from "./EVMToolbox"; - -export const ETHToolbox = ({ - signer, - provider, -}: { signer?: Signer | JsonRpcSigner; provider: JsonRpcProvider | BrowserProvider }) => { - const evmToolbox = EVMToolbox({ provider, signer }); - const chain = Chain.Ethereum; - - async function multicall( - callTuples: { address: string; data: string }[], - multicallAddress = "0x5ba1e12693dc8f9c48aad8770482f4739beed696", - funcName = "aggregate", - feeOptionKey: FeeOption = FeeOption.Fast, - ) { - const txObject = await evmToolbox.createContractTxObject({ - contractAddress: multicallAddress, - abi: multicallAbi, - funcName, - funcParams: [callTuples], - }); - - return evmToolbox.sendTransaction(txObject, feeOptionKey); - } - - return { - ...evmToolbox, - multicall, - estimateTransactionFee: (txObject: EVMTxBaseParams, feeOptionKey?: FeeOption) => - estimateTransactionFee(txObject, feeOptionKey, chain, provider), - getBalance: ( - address: string, - potentialScamFilter = true, - overwriteProvider?: JsonRpcProvider | BrowserProvider, - ) => - getBalance({ provider: overwriteProvider || provider, address, chain, potentialScamFilter }), - }; -}; diff --git a/packages/toolboxes/src/evm/toolbox/evm.ts b/packages/toolboxes/src/evm/toolbox/evm.ts new file mode 100644 index 000000000..8d3573312 --- /dev/null +++ b/packages/toolboxes/src/evm/toolbox/evm.ts @@ -0,0 +1,155 @@ +import { + BaseDecimal, + Chain, + ChainToExplorerUrl, + ChainToHexChainId, + type EVMChain, + FeeOption, + type NetworkParams, + SKConfig, +} from "@swapkit/helpers"; +import type { BrowserProvider, JsonRpcProvider, Signer } from "ethers"; +import { multicallAbi } from "../contracts/eth/multicall"; +import { getBalance, getEstimateTransactionFee } from "../helpers"; +import { BaseEVMToolbox } from "./baseEVMToolbox"; + +export function ETHToolbox

({ + provider, + signer, +}: { signer?: S; provider: P }) { + const evmToolbox = createEvmToolbox(Chain.Ethereum)({ + provider, + signer, + }); + async function multicall( + callTuples: { address: string; data: string }[], + multicallAddress = "0x5ba1e12693dc8f9c48aad8770482f4739beed696", + funcName = "aggregate", + feeOptionKey: FeeOption = FeeOption.Fast, + ) { + const txObject = await evmToolbox.createContractTxObject({ + contractAddress: multicallAddress, + abi: multicallAbi, + funcName, + funcParams: [callTuples], + }); + + return evmToolbox.sendTransaction({ ...txObject, feeOptionKey }); + } + + return { ...evmToolbox, multicall }; +} + +export function ARBToolbox

({ + provider, + signer, +}: { signer?: S; provider: P }) { + const { estimateGasPrices: _, ...evmToolbox } = createEvmToolbox(Chain.Arbitrum)({ + provider, + signer, + }); + + async function estimateGasPrices() { + try { + const { gasPrice } = await provider.getFeeData(); + + if (!gasPrice) throw new Error("No fee data available"); + + return { + [FeeOption.Average]: { gasPrice }, + [FeeOption.Fast]: { gasPrice }, + [FeeOption.Fastest]: { gasPrice }, + }; + } catch (error) { + throw new Error( + `Failed to estimate gas price: ${(error as any).msg ?? (error as any).toString()}`, + ); + } + } + + return { ...evmToolbox, estimateGasPrices }; +} + +export const AVAXToolbox = createEvmToolbox(Chain.Avalanche); +export const BASEToolbox = createEvmToolbox(Chain.Base); +export const BSCToolbox = createEvmToolbox(Chain.BinanceSmartChain); +export const MATICToolbox = createEvmToolbox(Chain.Polygon); + +function createEvmToolbox(chain: C) { + return function createEvmToolbox

({ + provider, + signer, + }: { provider: P; signer?: S }) { + const isEIP1559Compatible = getIsEIP1559Compatible(chain); + const evmToolbox = BaseEVMToolbox({ provider, signer, isEIP1559Compatible }); + + return { + ...evmToolbox, + estimateTransactionFee: getEstimateTransactionFee({ provider, isEIP1559Compatible }), + getNetworkParams: getNetworkParams(chain), + getBalance: ( + address: string, + potentialScamFilter = true, + overwriteProvider?: JsonRpcProvider | BrowserProvider, + ) => + getBalance({ + provider: overwriteProvider || provider, + address, + chain, + potentialScamFilter, + }), + }; + }; +} + +function getNetworkParams(chain: C) { + return () => + (Chain.Ethereum === chain + ? undefined + : { + ...getNetworkInfo({ chain }), + chainId: ChainToHexChainId[chain], + rpcUrls: [SKConfig.get("rpcUrls")[chain]], + blockExplorerUrls: [ChainToExplorerUrl[chain]], + }) as C extends Chain.Ethereum ? undefined : NetworkParams; +} + +function getIsEIP1559Compatible(chain: C) { + const notCompatible = [Chain.Arbitrum, Chain.BinanceSmartChain]; + + return !notCompatible.includes(chain); +} + +function getNetworkInfo({ chain }: { chain: C }) { + const decimals = BaseDecimal[chain]; + + switch (chain) { + case Chain.Arbitrum: + return { + chainName: "Arbitrum One", + nativeCurrency: { name: "Ethereum", symbol: Chain.Ethereum, decimals }, + }; + case Chain.Avalanche: + return { + chainName: "Avalanche Network", + nativeCurrency: { name: "Avalanche", symbol: chain, decimals }, + }; + case Chain.Base: + return { + chainName: "Base Mainnet", + nativeCurrency: { name: "Ethereum", symbol: Chain.Ethereum, decimals }, + }; + case Chain.BinanceSmartChain: + return { + chainName: "BNB Chain", + nativeCurrency: { name: "Binance Coin", symbol: "BNB", decimals }, + }; + case Chain.Polygon: + return { + chainName: "Polygon Mainnet", + nativeCurrency: { name: "Polygon", symbol: Chain.Polygon, decimals }, + }; + default: + throw new Error(`Chain ${chain} is not supported`); + } +} diff --git a/packages/toolboxes/src/evm/toolbox/getToolboxByChain.ts b/packages/toolboxes/src/evm/toolbox/getToolboxByChain.ts index e545e4324..c7b1fcbf3 100644 --- a/packages/toolboxes/src/evm/toolbox/getToolboxByChain.ts +++ b/packages/toolboxes/src/evm/toolbox/getToolboxByChain.ts @@ -1,11 +1,6 @@ import { Chain } from "@swapkit/helpers"; -import { ARBToolbox } from "./arb"; -import { AVAXToolbox } from "./avax"; -import { BASEToolbox } from "./base"; -import { BSCToolbox } from "./bsc"; -import { ETHToolbox } from "./eth"; -import { MATICToolbox } from "./matic"; +import { ARBToolbox, AVAXToolbox, BASEToolbox, BSCToolbox, ETHToolbox, MATICToolbox } from "./evm"; import { OPToolbox } from "./op"; type ToolboxType = { @@ -39,4 +34,4 @@ export const getToolboxByChain = (chain: T): Toolbo } }; -export { evmValidateAddress } from "./EVMToolbox"; +export { evmValidateAddress } from "./baseEVMToolbox"; diff --git a/packages/toolboxes/src/evm/toolbox/matic.ts b/packages/toolboxes/src/evm/toolbox/matic.ts deleted file mode 100644 index f393aecfc..000000000 --- a/packages/toolboxes/src/evm/toolbox/matic.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - BaseDecimal, - Chain, - ChainId, - ChainToExplorerUrl, - type FeeOption, - SKConfig, -} from "@swapkit/helpers"; -import type { BrowserProvider, JsonRpcProvider, Signer } from "ethers"; - -import { type EVMTxBaseParams, estimateTransactionFee, getBalance } from "../index"; - -import { EVMToolbox } from "./EVMToolbox"; - -const getNetworkParams = () => ({ - chainId: ChainId.PolygonHex, - chainName: "Polygon Mainnet", - nativeCurrency: { name: "Polygon", symbol: Chain.Polygon, decimals: BaseDecimal.MATIC }, - rpcUrls: [SKConfig.get("rpcUrls")[Chain.Polygon]], - blockExplorerUrls: [ChainToExplorerUrl[Chain.Polygon]], -}); - -export const MATICToolbox = ({ - provider, - signer, -}: { signer?: Signer; provider: JsonRpcProvider | BrowserProvider }) => { - const evmToolbox = EVMToolbox({ provider, signer }); - const chain = Chain.Polygon; - - return { - ...evmToolbox, - getNetworkParams, - estimateTransactionFee: (txObject: EVMTxBaseParams, feeOptionKey: FeeOption) => - estimateTransactionFee(txObject, feeOptionKey, chain, provider), - getBalance: ( - address: string, - potentialScamFilter = true, - overwriteProvider?: JsonRpcProvider | BrowserProvider, - ) => - getBalance({ provider: overwriteProvider || provider, address, chain, potentialScamFilter }), - }; -}; diff --git a/packages/toolboxes/src/evm/toolbox/op.ts b/packages/toolboxes/src/evm/toolbox/op.ts index 5d57913f9..ffaf7de5d 100644 --- a/packages/toolboxes/src/evm/toolbox/op.ts +++ b/packages/toolboxes/src/evm/toolbox/op.ts @@ -10,83 +10,77 @@ import type { BrowserProvider, JsonRpcProvider, Signer, TransactionRequest } fro import { Contract, Transaction } from "ethers"; import { gasOracleAbi } from "../contracts/op/gasOracle"; -import { getBalance } from "../index"; - -import { EVMToolbox } from "./EVMToolbox"; +import { getBalance } from "../helpers"; +import { BaseEVMToolbox } from "./baseEVMToolbox"; const GAS_PRICE_ORACLE_ADDRESS = "0x420000000000000000000000000000000000000f"; -export const connectGasPriceOracle = (provider: JsonRpcProvider | BrowserProvider) => { +function connectGasPriceOracle

(provider: P) { return new Contract(GAS_PRICE_ORACLE_ADDRESS, gasOracleAbi, provider); -}; - -export const getL1GasPrice = (provider: JsonRpcProvider | BrowserProvider) => { - const gasPriceOracle = connectGasPriceOracle(provider); - - if (gasPriceOracle && "l1BaseFee" in gasPriceOracle) { - return gasPriceOracle?.l1BaseFee() as unknown as bigint; - } - - return undefined; -}; - -const _serializeTx = async ( - provider: JsonRpcProvider | BrowserProvider, - { data, from, to, gasPrice, type, gasLimit, nonce }: TransactionRequest, -) => { - if (!to) throw new Error("Missing to address"); - - return Transaction.from({ - data, - to: to as string, - gasPrice, - type, - gasLimit, - nonce: nonce ? nonce : from ? await provider.getTransactionCount(from) : 0, - }).serialized; -}; - -export const estimateL1GasCost = async ( - provider: JsonRpcProvider | BrowserProvider, - tx: TransactionRequest, -) => { - const gasPriceOracle = await connectGasPriceOracle(provider); - const serializedTx = await _serializeTx(provider, tx); - - if (gasPriceOracle && "getL1Fee" in gasPriceOracle) { - return gasPriceOracle.getL1Fee(serializedTx); - } -}; - -export const estimateL2GasCost = async ( - provider: JsonRpcProvider | BrowserProvider, - tx: TransactionRequest, -) => { - const l2GasPrice = await provider.send("eth_gasPrice", []); - const l2GasCost = await provider.estimateGas(tx); - return l2GasPrice.mul(l2GasCost); -}; - -export const estimateTotalGasCost = async ( - provider: JsonRpcProvider | BrowserProvider, - tx: TransactionRequest, -) => { - const l1GasCost = await estimateL1GasCost(provider, tx); - const l2GasCost = await estimateL2GasCost(provider, tx); - return l1GasCost.add(l2GasCost); -}; - -export const estimateL1Gas = async ( - provider: JsonRpcProvider | BrowserProvider, - tx: TransactionRequest, -) => { - const gasPriceOracle = connectGasPriceOracle(provider); - const serializedTx = await _serializeTx(provider, tx); - - if (gasPriceOracle && "getL1GasUsed" in gasPriceOracle) { - return gasPriceOracle.getL1GasUsed(serializedTx); - } -}; +} + +function getL1GasPriceFetcher

(provider: P) { + return function getL1GasPrice() { + const gasPriceOracle = connectGasPriceOracle(provider); + + if (gasPriceOracle && "l1BaseFee" in gasPriceOracle) { + return gasPriceOracle?.l1BaseFee() as unknown as bigint; + } + + return undefined; + }; +} + +function serializeTx

(provider: P) { + return async function serializeTx({ from, to, nonce, ...tx }: TransactionRequest) { + if (!to) throw new Error("Missing to address"); + const txParams = { + ...tx, + to: to as string, + nonce: nonce ? nonce : from ? await provider.getTransactionCount(from) : 0, + }; + + return Transaction.from(txParams).serialized; + }; +} + +function estimateL1GasCost

(provider: P) { + return async function estimateL1GasCost(tx: TransactionRequest) { + const gasPriceOracle = connectGasPriceOracle(provider); + const serializedTx = await serializeTx(provider)(tx); + + if (gasPriceOracle && "getL1Fee" in gasPriceOracle) { + return gasPriceOracle.getL1Fee(serializedTx); + } + }; +} + +function estimateL2GasCost

(provider: P) { + return async function estimateL2GasCost(tx: TransactionRequest) { + const l2GasPrice = await provider.send("eth_gasPrice", []); + const l2GasCost = await provider.estimateGas(tx); + return l2GasPrice.mul(l2GasCost); + }; +} + +function estimateTotalGasCost

(provider: P) { + return async function estimateTotalGasCost(tx: TransactionRequest) { + const l1GasCost = await estimateL1GasCost(provider)(tx); + const l2GasCost = await estimateL2GasCost(provider)(tx); + return l1GasCost.add(l2GasCost); + }; +} + +export function estimateL1Gas

(provider: P) { + return async function estimateL1Gas(tx: TransactionRequest) { + const gasPriceOracle = connectGasPriceOracle(provider); + const serializedTx = await serializeTx(provider)(tx); + + if (gasPriceOracle && "getL1GasUsed" in gasPriceOracle) { + return gasPriceOracle.getL1GasUsed(serializedTx); + } + }; +} const getNetworkParams = () => ({ chainId: ChainId.OptimismHex, @@ -96,58 +90,61 @@ const getNetworkParams = () => ({ blockExplorerUrls: [ChainToExplorerUrl[Chain.Optimism]], }); -const estimateGasPrices = async (provider: JsonRpcProvider | BrowserProvider) => { - try { - const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = await provider.getFeeData(); - const l1GasPrice = await getL1GasPrice(provider); - const price = gasPrice as bigint; - - if (!(maxFeePerGas && maxPriorityFeePerGas)) { - throw new Error("No fee data available"); +function estimateGasPrices

(provider: P) { + return async function estimateGasPrices() { + try { + const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = await provider.getFeeData(); + const l1GasPrice = getL1GasPriceFetcher(provider)(); + const price = gasPrice as bigint; + + if (!(maxFeePerGas && maxPriorityFeePerGas)) { + throw new Error("No fee data available"); + } + + return { + [FeeOption.Average]: { + l1GasPrice, + gasPrice, + maxFeePerGas, + maxPriorityFeePerGas, + }, + [FeeOption.Fast]: { + l1GasPrice: ((l1GasPrice || 0n) * 15n) / 10n, + gasPrice: (price * 15n) / 10n, + maxFeePerGas, + maxPriorityFeePerGas: (maxPriorityFeePerGas * 15n) / 10n, + }, + [FeeOption.Fastest]: { + l1GasPrice: (l1GasPrice || 0n) * 2n, + gasPrice: price * 2n, + maxFeePerGas, + maxPriorityFeePerGas: maxPriorityFeePerGas * 2n, + }, + }; + } catch (error) { + throw new Error( + `Failed to estimate gas price: ${(error as any).msg ?? (error as any).toString()}`, + ); } + }; +} - return { - [FeeOption.Average]: { - l1GasPrice, - gasPrice, - maxFeePerGas, - maxPriorityFeePerGas, - }, - [FeeOption.Fast]: { - l1GasPrice: ((l1GasPrice || 0n) * 15n) / 10n, - gasPrice: (price * 15n) / 10n, - maxFeePerGas, - maxPriorityFeePerGas: (maxPriorityFeePerGas * 15n) / 10n, - }, - [FeeOption.Fastest]: { - l1GasPrice: (l1GasPrice || 0n) * 2n, - gasPrice: price * 2n, - maxFeePerGas, - maxPriorityFeePerGas: maxPriorityFeePerGas * 2n, - }, - }; - } catch (error) { - throw new Error( - `Failed to estimate gas price: ${(error as any).msg ?? (error as any).toString()}`, - ); - } -}; - -export const OPToolbox = ({ +export function OPToolbox

({ provider, signer, -}: { signer?: Signer; provider: JsonRpcProvider | BrowserProvider }) => { - const evmToolbox = EVMToolbox({ provider, signer }); +}: { signer?: S; provider: P }) { + const evmToolbox = BaseEVMToolbox({ provider, signer }); + const getL1GasPrice = getL1GasPriceFetcher(provider); return { ...evmToolbox, - estimateTotalGasCost: (tx: TransactionRequest) => estimateTotalGasCost(provider, tx), - estimateL1GasCost: (tx: TransactionRequest) => estimateL1GasCost(provider, tx), - estimateL2GasCost: (tx: TransactionRequest) => estimateL2GasCost(provider, tx), - getL1GasPrice: () => getL1GasPrice(provider), - estimateL1Gas: (tx: TransactionRequest) => estimateL1Gas(provider, tx), + estimateGasPrices: estimateGasPrices(provider), + estimateL1Gas: estimateL1Gas(provider), + estimateL1GasCost: estimateL1GasCost(provider), + estimateL2GasCost: estimateL2GasCost(provider), + estimateTotalGasCost: estimateTotalGasCost(provider), + getL1GasPrice, getNetworkParams, - estimateGasPrices: () => estimateGasPrices(provider), getBalance: ( address: string, potentialScamFilter = true, @@ -160,4 +157,4 @@ export const OPToolbox = ({ potentialScamFilter, }), }; -}; +} diff --git a/packages/toolboxes/src/evm/types.ts b/packages/toolboxes/src/evm/types.ts index 69e7421c3..54e3bf0d0 100644 --- a/packages/toolboxes/src/evm/types.ts +++ b/packages/toolboxes/src/evm/types.ts @@ -64,7 +64,7 @@ export type TransferParams = WalletTxParams & { assetValue: AssetValue; }; -export type EVMToolboxType = ReturnType< +export type BaseEVMToolboxType = ReturnType< | typeof ARBToolbox | typeof AVAXToolbox | typeof BASEToolbox @@ -76,7 +76,7 @@ export type EVMToolboxType = ReturnType< export type EVMMaxSendableAmountsParams = { from: string; - toolbox: EVMToolboxType; + toolbox: BaseEVMToolboxType; assetValue: AssetValue; feeOptionKey?: FeeOption; memo?: string; @@ -108,11 +108,3 @@ export type LegacyEVMTxParams = EVMTxBaseParams & { }; export type EVMTxParams = EIP1559TxParams | LegacyEVMTxParams; - -export type NonETHToolbox = - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType; diff --git a/packages/toolboxes/src/utxo/toolbox/bitcoinCash.ts b/packages/toolboxes/src/utxo/toolbox/bitcoinCash.ts index a672150c8..e8a101f10 100644 --- a/packages/toolboxes/src/utxo/toolbox/bitcoinCash.ts +++ b/packages/toolboxes/src/utxo/toolbox/bitcoinCash.ts @@ -32,40 +32,11 @@ import type { import { BaseUTXOToolbox } from "./utxo"; -// needed because TS can not infer types -type BCHMethods = { - stripPrefix: (address: string) => string; - stripToCashAddress: (address: string) => string; - validateAddress: (address: string, chain?: UTXOChain) => boolean; - createKeysForPath: (params: { - wif?: string; - phrase?: string; - derivationPath?: string; - }) => Promise<{ getAddress: (index?: number) => string }>; - getAddressFromKeys: (keys: { getAddress: (index?: number) => string }) => string; - buildBCHTx: ( - params: UTXOBuildTxParams, - ) => Promise<{ builder: TransactionBuilderType; utxos: UTXOType[] }>; - buildTx: (params: UTXOBuildTxParams) => Promise<{ psbt: Psbt }>; - transfer: ( - params: UTXOWalletTransferParams< - { builder: TransactionBuilderType; utxos: UTXOType[] }, - TransactionType - >, - ) => Promise; -}; - const chain = Chain.BitcoinCash as UTXOChain; export const stripToCashAddress = (address: string) => stripPrefix(toCashAddress(address)); -const buildBCHTx: BCHMethods["buildBCHTx"] = async ({ - assetValue, - recipient, - memo, - feeRate, - sender, -}) => { +const buildBCHTx = async ({ assetValue, recipient, memo, feeRate, sender }: UTXOBuildTxParams) => { if (!validateAddress(recipient)) throw new Error("Invalid address"); const utxos = await getUtxoApi(chain).scanUTXOs({ address: stripToCashAddress(sender), @@ -223,11 +194,11 @@ export const validateAddress = (address: string) => { ); }; -const createKeysForPath: BCHMethods["createKeysForPath"] = async ({ +const createKeysForPath = async ({ phrase, derivationPath = `${DerivationPath.BCH}/0`, wif, -}) => { +}: { wif?: string; phrase?: string; derivationPath?: string }) => { const { ECPairFactory } = await import("ecpair"); const network = getNetwork(chain); @@ -252,11 +223,7 @@ const getAddressFromKeys = (keys: { getAddress: (index?: number) => string }) => return stripToCashAddress(address); }; -export const createBCHToolbox = (): Omit< - ReturnType, - "getAddressFromKeys" | "transfer" | "createKeysForPath" -> & - BCHMethods => { +export const createBCHToolbox = () => { const { getBalance, ...toolbox } = BaseUTXOToolbox(Chain.BitcoinCash); return { diff --git a/packages/toolboxes/src/utxo/toolbox/utxo.ts b/packages/toolboxes/src/utxo/toolbox/utxo.ts index e82f80235..18fb51140 100644 --- a/packages/toolboxes/src/utxo/toolbox/utxo.ts +++ b/packages/toolboxes/src/utxo/toolbox/utxo.ts @@ -29,45 +29,50 @@ import type { BCHToolbox, BTCToolbox, DASHToolbox, DOGEToolbox, LTCToolbox } fro export const nonSegwitChains = [Chain.Dash, Chain.Dogecoin]; -async function createKeysForPath({ - phrase, - wif, - derivationPath, - chain, -}: { phrase?: string; wif?: string; derivationPath: string; chain: Chain }) { - const { ECPairFactory } = await import("ecpair"); - if (!(wif || phrase)) throw new Error("Either phrase or wif must be provided"); +function createKeysForPath(chain: Chain) { + return async function createKeysForPath({ + phrase, + wif, + derivationPath, + }: { phrase?: string; wif?: string; derivationPath: string }) { + const { ECPairFactory } = await import("ecpair"); + if (!(wif || phrase)) throw new Error("Either phrase or wif must be provided"); - const factory = ECPairFactory(secp256k1); - const network = getNetwork(chain); + const factory = ECPairFactory(secp256k1); + const network = getNetwork(chain); - if (wif) return factory.fromWIF(wif, network); + if (wif) return factory.fromWIF(wif, network); - const seed = mnemonicToSeedSync(phrase as string); - const master = HDKey.fromMasterSeed(seed, network).derive(derivationPath); - if (!master.privateKey) throw new Error("Could not get private key from phrase"); + const seed = mnemonicToSeedSync(phrase as string); + const master = HDKey.fromMasterSeed(seed, network).derive(derivationPath); + if (!master.privateKey) throw new Error("Could not get private key from phrase"); - return factory.fromPrivateKey(Buffer.from(master.privateKey), { network }); + return factory.fromPrivateKey(Buffer.from(master.privateKey), { network }); + }; } -function validateAddress({ address, chain }: { address: string; chain: UTXOChain }) { - try { - initEccLib(secp256k1); - btcLibAddress.toOutputScript(address, getNetwork(chain)); - return true; - } catch (_error) { - return false; - } +function validateAddress(chain: UTXOChain) { + return function validateAddress(address: string) { + try { + initEccLib(secp256k1); + btcLibAddress.toOutputScript(address, getNetwork(chain)); + return true; + } catch (_error) { + return false; + } + }; } -function getAddressFromKeys({ keys, chain }: { chain: UTXOChain; keys: ECPairInterface }) { - if (!keys) throw new Error("Keys must be provided"); +function getAddressFromKeys(chain: UTXOChain) { + return function getAddressFromKeys(keys: ECPairInterface) { + if (!keys) throw new Error("Keys must be provided"); - const method = nonSegwitChains.includes(chain) ? payments.p2pkh : payments.p2wpkh; - const { address } = method({ pubkey: keys.publicKey, network: getNetwork(chain) }); - if (!address) throw new Error("Address not defined"); + const method = nonSegwitChains.includes(chain) ? payments.p2pkh : payments.p2wpkh; + const { address } = method({ pubkey: keys.publicKey, network: getNetwork(chain) }); + if (!address) throw new Error("Address not defined"); - return address; + return address; + }; } function transfer(chain: UTXOChain) { @@ -307,15 +312,13 @@ export const BaseUTXOToolbox = (chain: UTXOChain) => ({ getInputsOutputsFee: getInputsOutputsFee(chain), broadcastTx: (txHash: string) => getUtxoApi(chain).broadcastTx(txHash), - getAddressFromKeys: (keys: ECPairInterface) => getAddressFromKeys({ keys, chain }), - validateAddress: (address: string) => validateAddress({ address, chain }), - createKeysForPath: (params: any) => createKeysForPath({ ...params, chain }), + getAddressFromKeys: getAddressFromKeys(chain), + validateAddress: validateAddress(chain), + createKeysForPath: createKeysForPath(chain), - getPrivateKeyFromMnemonic: async (params: { - phrase: string; - derivationPath: string; - }) => { - const keys = await createKeysForPath({ ...params, chain }); + getPrivateKeyFromMnemonic: async (params: { phrase: string; derivationPath: string }) => { + const getKeysForPath = createKeysForPath(chain); + const keys = await getKeysForPath(params); return keys.toWIF(); }, @@ -346,7 +349,7 @@ export const BaseUTXOToolbox = (chain: UTXOChain) => ({ export function utxoValidateAddress({ chain, address }: { chain: UTXOChain; address: string }) { return chain === Chain.BitcoinCash ? validateBCHAddress(address) - : validateAddress({ address, chain }); + : validateAddress(chain)(address); } export type BaseUTXOWallet = ReturnType; diff --git a/packages/wallets/src/bitget/helpers.ts b/packages/wallets/src/bitget/helpers.ts index cebd7d75c..46db1ed9e 100644 --- a/packages/wallets/src/bitget/helpers.ts +++ b/packages/wallets/src/bitget/helpers.ts @@ -175,7 +175,8 @@ export const getWeb3WalletMethods = async ({ const provider = new BrowserProvider(walletProvider, "any"); const signer = await provider.getSigner(); - const toolbox = getToolboxByChain(chain)({ provider, signer }); + const getToolbox = getToolboxByChain(chain); + const toolbox = getToolbox({ provider, signer }); try { if (chain !== Chain.Ethereum && "getNetworkParams" in toolbox) { diff --git a/packages/wallets/src/ctrl/ctrlWallet.ts b/packages/wallets/src/ctrl/ctrlWallet.ts index d9eb2c7c8..1332222a2 100644 --- a/packages/wallets/src/ctrl/ctrlWallet.ts +++ b/packages/wallets/src/ctrl/ctrlWallet.ts @@ -7,7 +7,6 @@ import { createWallet, filterSupportedChains, } from "@swapkit/helpers"; -import type { NonETHToolbox } from "@swapkit/toolboxes/evm"; import { getWalletSupportedChains } from "../helpers"; import { @@ -149,7 +148,7 @@ async function getWalletMethods(chain: (typeof CTRL_SUPPORTED_CHAINS)[number]) { try { if (chain !== Chain.Ethereum) { - const networkParams = (toolbox as NonETHToolbox).getNetworkParams(); + const networkParams = toolbox.getNetworkParams(); await switchEVMWalletNetwork(provider, chain, networkParams); } } catch (_error) { diff --git a/packages/wallets/src/ctrl/walletHelpers.ts b/packages/wallets/src/ctrl/walletHelpers.ts index 604c2e641..01c81078d 100644 --- a/packages/wallets/src/ctrl/walletHelpers.ts +++ b/packages/wallets/src/ctrl/walletHelpers.ts @@ -239,13 +239,14 @@ export function getCtrlMethods(provider: BrowserProvider) { if (!contractAddress) { throw new SwapKitError("wallet_ctrl_contract_address_not_provided"); } - const { createContract, createContractTxObject, isStateChangingCall, toHexString } = + const { createContract, getCreateContractTxObject, isStateChangingCall, toHexString } = await import("@swapkit/toolboxes/evm"); - const isStateChanging = isStateChangingCall(abi, funcName); + const isStateChanging = isStateChangingCall({ abi, funcName }); if (isStateChanging) { - const { value, from, to, data } = await createContractTxObject(contractProvider, { + const createTx = getCreateContractTxObject(contractProvider); + const { value, from, to, data } = await createTx({ contractAddress, abi, funcName, @@ -269,7 +270,7 @@ export function getCtrlMethods(provider: BrowserProvider) { return typeof result?.hash === "string" ? result?.hash : result; }, approve: async ({ assetAddress, spenderAddress, amount, from }: ApproveParams) => { - const { MAX_APPROVAL, createContractTxObject, toHexString } = await import( + const { MAX_APPROVAL, getCreateContractTxObject, toHexString } = await import( "@swapkit/toolboxes/evm" ); const funcParams = [spenderAddress, BigInt(amount || MAX_APPROVAL)]; @@ -283,7 +284,8 @@ export function getCtrlMethods(provider: BrowserProvider) { txOverrides, }; - const { value, to, data } = await createContractTxObject(provider, functionCallParams); + const createTx = getCreateContractTxObject(provider); + const { value, to, data } = await createTx(functionCallParams); return provider.send("eth_sendTransaction", [ { diff --git a/packages/wallets/src/evm-extensions/index.ts b/packages/wallets/src/evm-extensions/index.ts index 1e28afc04..b59b3f890 100644 --- a/packages/wallets/src/evm-extensions/index.ts +++ b/packages/wallets/src/evm-extensions/index.ts @@ -10,7 +10,6 @@ import { prepareNetworkSwitch, switchEVMWalletNetwork, } from "@swapkit/helpers"; -import type { NonETHToolbox } from "@swapkit/toolboxes/evm"; import type { BrowserProvider, Eip1193Provider } from "ethers"; import { getWalletSupportedChains } from "../helpers"; @@ -56,14 +55,13 @@ export const getWeb3WalletMethods = async ({ const { getToolboxByChain } = await import("@swapkit/toolboxes/evm"); const signer = await provider.getSigner(); - const toolbox = getToolboxByChain(chain)({ provider, signer }); if (chain !== Chain.Ethereum) { const currentNetwork = await provider.getNetwork(); if (currentNetwork.chainId.toString() !== ChainToHexChainId[chain]) { try { - const networkParams = (toolbox as NonETHToolbox).getNetworkParams(); + const networkParams = toolbox.getNetworkParams(); await switchEVMWalletNetwork(provider, chain, networkParams); } catch (_error) { throw new Error(`Failed to add/switch ${chain} network: ${chain}`); @@ -71,7 +69,7 @@ export const getWeb3WalletMethods = async ({ } } - return prepareNetworkSwitch({ toolbox, chain, provider }); + return prepareNetworkSwitch({ toolbox, chain, provider }); }; export const evmWallet = createWallet({ diff --git a/packages/wallets/src/exodus/index.ts b/packages/wallets/src/exodus/index.ts index d8742a4f3..de49e7018 100644 --- a/packages/wallets/src/exodus/index.ts +++ b/packages/wallets/src/exodus/index.ts @@ -9,7 +9,6 @@ import { prepareNetworkSwitch, switchEVMWalletNetwork, } from "@swapkit/helpers"; -import type { NonETHToolbox } from "@swapkit/toolboxes/evm"; import type { UTXOTransferParams } from "@swapkit/toolboxes/utxo"; import type { Psbt } from "@swapkit/toolboxes/utxo"; import type { BrowserProvider, Eip1193Provider } from "ethers"; @@ -120,7 +119,7 @@ export const getWalletMethods = async ({ try { if (chain !== Chain.Ethereum) { - const networkParams = (toolbox as NonETHToolbox).getNetworkParams(); + const networkParams = toolbox.getNetworkParams(); await switchEVMWalletNetwork(browserProvider, chain, networkParams); } } catch (_error) { @@ -129,7 +128,7 @@ export const getWalletMethods = async ({ return { address, - ...prepareNetworkSwitch({ toolbox, chain, provider: browserProvider }), + ...prepareNetworkSwitch({ toolbox, chain, provider: browserProvider }), }; } default: diff --git a/packages/wallets/src/keepkey-bex/index.ts b/packages/wallets/src/keepkey-bex/index.ts index 849f8f2e6..f7dd5e470 100644 --- a/packages/wallets/src/keepkey-bex/index.ts +++ b/packages/wallets/src/keepkey-bex/index.ts @@ -6,7 +6,6 @@ import { createWallet, filterSupportedChains, } from "@swapkit/helpers"; -import type { NonETHToolbox } from "@swapkit/toolboxes/evm"; import type { Eip1193Provider } from "ethers"; import { getWalletSupportedChains } from "../helpers"; import { @@ -135,7 +134,7 @@ async function getWalletMethods(chain: (typeof KEEPKEY_BEX_SUPPORTED_CHAINS)[num try { if (chain !== Chain.Ethereum) { - const networkParams = (toolbox as NonETHToolbox).getNetworkParams(); + const networkParams = toolbox.getNetworkParams(); await switchEVMWalletNetwork(provider, chain, networkParams); } } catch (_error) { diff --git a/packages/wallets/src/keepkey-bex/walletHelpers.ts b/packages/wallets/src/keepkey-bex/walletHelpers.ts index 0526f20e1..0282b24e8 100644 --- a/packages/wallets/src/keepkey-bex/walletHelpers.ts +++ b/packages/wallets/src/keepkey-bex/walletHelpers.ts @@ -226,13 +226,14 @@ export function getKEEPKEYMethods(provider: BrowserProvider) { if (!contractAddress) { throw new SwapKitError("wallet_keepkey_contract_address_not_provided"); } - const { createContract, createContractTxObject, isStateChangingCall, toHexString } = + const { createContract, getCreateContractTxObject, isStateChangingCall, toHexString } = await import("@swapkit/toolboxes/evm"); - const isStateChanging = isStateChangingCall(abi, funcName); + const isStateChanging = isStateChangingCall({ abi, funcName }); if (isStateChanging) { - const { value, from, to, data } = await createContractTxObject(provider, { + const createTx = getCreateContractTxObject(provider); + const { value, from, to, data } = await createTx({ contractAddress, abi, funcName, @@ -251,11 +252,12 @@ export function getKEEPKEYMethods(provider: BrowserProvider) { return typeof result?.hash === "string" ? result?.hash : result; }, approve: async ({ assetAddress, spenderAddress, amount, from }: ApproveParams) => { - const { MAX_APPROVAL, createContractTxObject, toHexString } = await import( + const { MAX_APPROVAL, getCreateContractTxObject, toHexString } = await import( "@swapkit/toolboxes/evm" ); - const { value, to, data } = await createContractTxObject(provider, { + const createTx = getCreateContractTxObject(provider); + const { value, to, data } = await createTx({ contractAddress: assetAddress, abi: erc20ABI, funcName: "approve", diff --git a/packages/wallets/src/talisman/index.ts b/packages/wallets/src/talisman/index.ts index 22b3dd3ee..3bb6ef2fc 100644 --- a/packages/wallets/src/talisman/index.ts +++ b/packages/wallets/src/talisman/index.ts @@ -9,7 +9,6 @@ import { prepareNetworkSwitch, switchEVMWalletNetwork, } from "@swapkit/helpers"; -import type { NonETHToolbox } from "@swapkit/toolboxes/evm"; import { type InjectedWindow, Network } from "@swapkit/toolboxes/substrate"; import type { Eip1193Provider } from "ethers"; import { getWalletSupportedChains } from "../helpers"; @@ -67,13 +66,11 @@ async function getWeb3WalletMethods({ const provider = new BrowserProvider(walletProvider, "any"); const signer = await provider.getSigner(); - const toolbox = getToolboxByChain(chain)({ provider, signer }); try { if (chain !== Chain.Ethereum) { - const networkParams = (toolbox as NonETHToolbox).getNetworkParams(); - await switchEVMWalletNetwork(provider, chain, networkParams); + await switchEVMWalletNetwork(provider, chain, toolbox.getNetworkParams()); } } catch (_error) { throw new SwapKitError({ @@ -82,7 +79,7 @@ async function getWeb3WalletMethods({ }); } - return prepareNetworkSwitch({ toolbox, chain, provider }); + return prepareNetworkSwitch({ toolbox, chain, provider }); } async function getWalletMethods(chain: Chain) {