diff --git a/.changeset/swidge-feature.md b/.changeset/swidge-feature.md new file mode 100644 index 0000000..7dea8ef --- /dev/null +++ b/.changeset/swidge-feature.md @@ -0,0 +1,13 @@ +--- +"@walletconnect/companion-wallet": minor +"@walletconnect/cli-sdk": minor +--- + +feat: add swidge (swap/bridge) functionality via LI.FI SDK + +Companion wallet now auto-detects insufficient funds before sending transactions +and seamlessly bridges from another chain using LI.FI. In TTY mode, prompts for +confirmation. In pipe/agent mode, auto-bridges. + +New CLI operation: `companion-wallet swidge` for manual cross-chain bridging. +WalletConnect CLI now warns when target account has insufficient funds. diff --git a/package-lock.json b/package-lock.json index 2d13345..7426a04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,34 @@ "turbo": "^2.8.0" } }, + "node_modules/@0no-co/graphql.web": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.2.0.tgz", + "integrity": "sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==", + "license": "MIT", + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "graphql": { + "optional": true + } + } + }, + "node_modules/@0no-co/graphqlsp": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@0no-co/graphqlsp/-/graphqlsp-1.15.2.tgz", + "integrity": "sha512-Ys031WnS3sTQQBtRTkQsYnw372OlW72ais4sp0oh2UMPRNyxxnq85zRfU4PIdoy9kWriysPT5BYAkgIxhbonFA==", + "license": "MIT", + "dependencies": { + "@gql.tada/internal": "^1.0.0", + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", + "typescript": "^5.0.0" + } + }, "node_modules/@adraffy/ens-normalize": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", @@ -29,12 +57,55 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, + "node_modules/@bigmi/core": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@bigmi/core/-/core-0.7.0.tgz", + "integrity": "sha512-77br/G4rr4LFgLwYPQs/TZUlB/XVljgSrsseb0J6xCSs3DxomfnKQuKqTksN7IcwuDDEL22xBpyt9JZpoO+lQg==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.8.0", + "bech32": "^2.0.0", + "bitcoinjs-lib": "^7.0.1", + "bs58": "^6.0.0", + "eventemitter3": "^5.0.4", + "zustand": "^5.0.11" + }, + "peerDependencies": { + "bs58": "^6.0.0" + } + }, + "node_modules/@bigmi/core/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@bigmi/core/node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/@bitcoinerlab/secp256k1": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@bitcoinerlab/secp256k1/-/secp256k1-1.2.0.tgz", + "integrity": "sha512-jeujZSzb3JOZfmJYI0ph1PVpCRV5oaexCgy+RvCXV8XlY+XFB/2n3WOcvBsKLsOw78KYgnQrQWb2HrKE4be88Q==", + "license": "MIT", + "dependencies": { + "@noble/curves": "^1.7.0" + } + }, "node_modules/@changesets/apply-release-plan": { "version": "7.0.14", "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.14.tgz", @@ -968,6 +1039,54 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@gql.tada/cli-utils": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@gql.tada/cli-utils/-/cli-utils-1.7.2.tgz", + "integrity": "sha512-Qbc7hbLvCz6IliIJpJuKJa9p05b2Jona7ov7+qofCsMRxHRZE1kpAmZMvL8JCI4c0IagpIlWNaMizXEQUe8XjQ==", + "license": "MIT", + "dependencies": { + "@0no-co/graphqlsp": "^1.12.13", + "@gql.tada/internal": "1.0.8", + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0" + }, + "peerDependencies": { + "@0no-co/graphqlsp": "^1.12.13", + "@gql.tada/svelte-support": "1.0.1", + "@gql.tada/vue-support": "1.0.1", + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "@gql.tada/svelte-support": { + "optional": true + }, + "@gql.tada/vue-support": { + "optional": true + } + } + }, + "node_modules/@gql.tada/internal": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@gql.tada/internal/-/internal-1.0.8.tgz", + "integrity": "sha512-XYdxJhtHC5WtZfdDqtKjcQ4d7R1s0d1rnlSs3OcBEUbYiPoJJfZU7tWsVXuv047Z6msvmr4ompJ7eLSK5Km57g==", + "license": "MIT", + "dependencies": { + "@0no-co/graphql.web": "^1.0.5" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", + "typescript": "^5.0.0" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/@hono/node-server": { "version": "1.19.9", "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", @@ -1093,6 +1212,67 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lifi/sdk": { + "version": "3.15.7", + "resolved": "https://registry.npmjs.org/@lifi/sdk/-/sdk-3.15.7.tgz", + "integrity": "sha512-Rhptfhv10TnsluFgmE7XCsZ7uM2A9mwvq5iCNkwhQmBLAksiehbr8jz0CEyArKxijXQrdvCTGLxNrGIUMfvMjw==", + "license": "Apache-2.0", + "dependencies": { + "@bigmi/core": "^0.7.0", + "@bitcoinerlab/secp256k1": "^1.2.0", + "@lifi/types": "17.65.0", + "@mysten/sui": "^1.45.2", + "@mysten/wallet-standard": "^0.19.9", + "@noble/curves": "^1.9.7", + "@solana/wallet-adapter-base": "^0.9.27", + "@solana/web3.js": "^1.98.4", + "bech32": "^2.0.0", + "bitcoinjs-lib": "^7.0.1", + "bs58": "^6.0.0", + "viem": "^2.46.3" + }, + "peerDependencies": { + "@solana/wallet-adapter-base": "^0.9.0", + "@solana/web3.js": "^1.98.0", + "viem": "^2.21.0" + } + }, + "node_modules/@lifi/sdk/node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@lifi/sdk/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@lifi/types": { + "version": "17.65.0", + "resolved": "https://registry.npmjs.org/@lifi/types/-/types-17.65.0.tgz", + "integrity": "sha512-2COF1WimbFiPv51x4T1lvXSs8sRB6CP0SzOTCt7xCwaaeMBLczuuJmF0r10pY9JPxdzbJtVMM83Za3uCslqlWA==", + "license": "Apache-2.0", + "dependencies": { + "viem": "^2.33.2" + } + }, "node_modules/@manypkg/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", @@ -1292,6 +1472,88 @@ "node": ">= 18" } }, + "node_modules/@mysten/bcs": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@mysten/bcs/-/bcs-1.9.2.tgz", + "integrity": "sha512-kBk5xrxV9OWR7i+JhL/plQrgQ2/KJhB2pB5gj+w6GXhbMQwS3DPpOvi/zN0Tj84jwPvHMllpEl0QHj6ywN7/eQ==", + "license": "Apache-2.0", + "dependencies": { + "@mysten/utils": "0.2.0", + "@scure/base": "^1.2.6" + } + }, + "node_modules/@mysten/sui": { + "version": "1.45.2", + "resolved": "https://registry.npmjs.org/@mysten/sui/-/sui-1.45.2.tgz", + "integrity": "sha512-gftf7fNpFSiXyfXpbtP2afVEnhc7p2m/MEYc/SO5pov92dacGKOpQIF7etZsGDI1Wvhv+dpph+ulRNpnYSs7Bg==", + "license": "Apache-2.0", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "@mysten/bcs": "1.9.2", + "@mysten/utils": "0.2.0", + "@noble/curves": "=1.9.4", + "@noble/hashes": "^1.8.0", + "@protobuf-ts/grpcweb-transport": "^2.11.1", + "@protobuf-ts/runtime": "^2.11.1", + "@protobuf-ts/runtime-rpc": "^2.11.1", + "@scure/base": "^1.2.6", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "gql.tada": "^1.8.13", + "graphql": "^16.11.0", + "poseidon-lite": "0.2.1", + "valibot": "^1.2.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@mysten/sui/node_modules/@noble/curves": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.4.tgz", + "integrity": "sha512-2bKONnuM53lINoDrSmK8qP8W271ms7pygDhZt4SiLOoLwBtoHqeCFi6RG42V8zd3mLHuJFhU/Bmaqo4nX0/kBw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@mysten/sui/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@mysten/utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@mysten/utils/-/utils-0.2.0.tgz", + "integrity": "sha512-CM6kJcJHX365cK6aXfFRLBiuyXc5WSBHQ43t94jqlCAIRw8umgNcTb5EnEA9n31wPAQgLDGgbG/rCUISCTJ66w==", + "license": "Apache-2.0", + "dependencies": { + "@scure/base": "^1.2.6" + } + }, + "node_modules/@mysten/wallet-standard": { + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@mysten/wallet-standard/-/wallet-standard-0.19.9.tgz", + "integrity": "sha512-jHFt+62os7x7y+4ZVMLck8WSanEO9b8deCD+VApUQkdAHA99TuxbREaujQTjnGQN5DaGEz8wQgeBPqxRY/vKQA==", + "license": "Apache-2.0", + "dependencies": { + "@mysten/sui": "1.45.2", + "@wallet-standard/core": "1.1.1" + } + }, "node_modules/@noble/ciphers": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", @@ -1369,6 +1631,31 @@ "node": ">= 8" } }, + "node_modules/@protobuf-ts/grpcweb-transport": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/grpcweb-transport/-/grpcweb-transport-2.11.1.tgz", + "integrity": "sha512-1W4utDdvOB+RHMFQ0soL4JdnxjXV+ddeGIUg08DvZrA8Ms6k5NN6GBFU2oHZdTOcJVpPrDJ02RJlqtaoCMNBtw==", + "license": "Apache-2.0", + "dependencies": { + "@protobuf-ts/runtime": "^2.11.1", + "@protobuf-ts/runtime-rpc": "^2.11.1" + } + }, + "node_modules/@protobuf-ts/runtime": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz", + "integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@protobuf-ts/runtime-rpc": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime-rpc/-/runtime-rpc-2.11.1.tgz", + "integrity": "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ==", + "license": "Apache-2.0", + "dependencies": { + "@protobuf-ts/runtime": "^2.11.1" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.57.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", @@ -1794,6 +2081,161 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", + "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "license": "MIT", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@solana/codecs-core": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz", + "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/codecs-numbers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz", + "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/errors": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz", + "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^14.0.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/errors/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@solana/errors/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/wallet-adapter-base": { + "version": "0.9.27", + "resolved": "https://registry.npmjs.org/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.27.tgz", + "integrity": "sha512-kXjeNfNFVs/NE9GPmysBRKQ/nf+foSaq3kfVSeMcO/iVgigyRmB551OjU3WyAolLG/1jeEfKLqF9fKwMCRkUqg==", + "license": "Apache-2.0", + "dependencies": { + "@solana/wallet-standard-features": "^1.3.0", + "@wallet-standard/base": "^1.1.0", + "@wallet-standard/features": "^1.1.0", + "eventemitter3": "^5.0.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@solana/web3.js": "^1.98.0" + } + }, + "node_modules/@solana/wallet-standard-features": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@solana/wallet-standard-features/-/wallet-standard-features-1.3.0.tgz", + "integrity": "sha512-ZhpZtD+4VArf6RPitsVExvgkF+nGghd1rzPjd97GmBximpnt1rsUxMOEyoIEuH3XBxPyNB6Us7ha7RHWQR+abg==", + "license": "Apache-2.0", + "dependencies": { + "@wallet-standard/base": "^1.1.0", + "@wallet-standard/features": "^1.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.98.4", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz", + "integrity": "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@noble/curves": "^1.4.2", + "@noble/hashes": "^1.4.0", + "@solana/buffer-layout": "^4.0.1", + "@solana/codecs-numbers": "^2.1.0", + "agentkeepalive": "^4.5.0", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.3", + "fast-stable-stringify": "^1.0.0", + "jayson": "^4.1.1", + "node-fetch": "^2.7.0", + "rpc-websockets": "^9.0.2", + "superstruct": "^2.0.2" + } + }, + "node_modules/@solana/web3.js/node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/@solana/web3.js/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, "node_modules/@spruceid/siwe-parser": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@spruceid/siwe-parser/-/siwe-parser-2.1.2.tgz", @@ -1837,6 +2279,21 @@ "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==", "license": "MIT" }, + "node_modules/@swc/helpers": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.19.tgz", + "integrity": "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@swc/helpers/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/@toon-format/toon": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@toon-format/toon/-/toon-2.1.0.tgz", @@ -1854,6 +2311,15 @@ "assertion-error": "^2.0.1" } }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -1879,12 +2345,26 @@ "version": "25.2.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz", "integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.16.0" } }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.55.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.55.0.tgz", @@ -2233,6 +2713,104 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@wallet-standard/app": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wallet-standard/app/-/app-1.1.0.tgz", + "integrity": "sha512-3CijvrO9utx598kjr45hTbbeeykQrQfKmSnxeWOgU25TOEpvcipD/bYDQWIqUv1Oc6KK4YStokSMu/FBNecGUQ==", + "license": "Apache-2.0", + "dependencies": { + "@wallet-standard/base": "^1.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@wallet-standard/base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wallet-standard/base/-/base-1.1.0.tgz", + "integrity": "sha512-DJDQhjKmSNVLKWItoKThJS+CsJQjR9AOBOirBVT1F9YpRyC9oYHE+ZnSf8y8bxUphtKqdQMPVQ2mHohYdRvDVQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=16" + } + }, + "node_modules/@wallet-standard/core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@wallet-standard/core/-/core-1.1.1.tgz", + "integrity": "sha512-5Xmjc6+Oe0hcPfVc5n8F77NVLwx1JVAoCVgQpLyv/43/bhtIif+Gx3WUrDlaSDoM8i2kA2xd6YoFbHCxs+e0zA==", + "license": "Apache-2.0", + "dependencies": { + "@wallet-standard/app": "^1.1.0", + "@wallet-standard/base": "^1.1.0", + "@wallet-standard/errors": "^0.1.1", + "@wallet-standard/features": "^1.1.0", + "@wallet-standard/wallet": "^1.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@wallet-standard/errors": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@wallet-standard/errors/-/errors-0.1.1.tgz", + "integrity": "sha512-V8Ju1Wvol8i/VDyQOHhjhxmMVwmKiwyxUZBnHhtiPZJTWY0U/Shb2iEWyGngYEbAkp2sGTmEeNX1tVyGR7PqNw==", + "license": "Apache-2.0", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^13.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@wallet-standard/errors/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@wallet-standard/errors/node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@wallet-standard/features": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wallet-standard/features/-/features-1.1.0.tgz", + "integrity": "sha512-hiEivWNztx73s+7iLxsuD1sOJ28xtRix58W7Xnz4XzzA/pF0+aicnWgjOdA10doVDEDZdUuZCIIqG96SFNlDUg==", + "license": "Apache-2.0", + "dependencies": { + "@wallet-standard/base": "^1.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@wallet-standard/wallet": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wallet-standard/wallet/-/wallet-1.1.0.tgz", + "integrity": "sha512-Gt8TnSlDZpAl+RWOOAB/kuvC7RpcdWAlFbHNoi4gsXsfaWa1QCT6LBcfIYTPdOZC9OVZUDwqGuGAcqZejDmHjg==", + "license": "Apache-2.0", + "dependencies": { + "@wallet-standard/base": "^1.1.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@walletconnect/cli-sdk": { "resolved": "packages/cli-sdk", "link": true @@ -2674,6 +3252,18 @@ "license": "MIT", "peer": true }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2857,6 +3447,32 @@ "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", "license": "MIT" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "license": "MIT" + }, "node_modules/better-path-resolve": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", @@ -2870,12 +3486,49 @@ "node": ">=4" } }, + "node_modules/bip174": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-3.0.0.tgz", + "integrity": "sha512-N3vz3rqikLEu0d6yQL8GTrSkpYb35NQKWMR7Hlza0lOj6ZOlvQ3Xr7N9Y+JPebaCVoEUHdBeBSuLxcHr71r+Lw==", + "license": "MIT", + "dependencies": { + "uint8array-tools": "^0.0.9", + "varuint-bitcoin": "^2.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/bitcoinjs-lib": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-7.0.1.tgz", + "integrity": "sha512-vwEmpL5Tpj0I0RBdNkcDMXePoaYSTeKY6mL6/l5esbnTs+jGdPDuLp4NY1hSh6Zk5wSgePygZ4Wx5JJao30Pww==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.2.0", + "bech32": "^2.0.0", + "bip174": "^3.0.0", + "bs58check": "^4.0.0", + "uint8array-tools": "^0.0.9", + "valibot": "^1.2.0", + "varuint-bitcoin": "^2.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", "license": "MIT" }, + "node_modules/bn.js": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", + "license": "MIT" + }, "node_modules/body-parser": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", @@ -2900,6 +3553,35 @@ "url": "https://opencollective.com/express" } }, + "node_modules/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/borsh/node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/borsh/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, "node_modules/brace-expansion": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -2907,29 +3589,77 @@ "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", + "dependencies": { + "base-x": "^5.0.0" + } + }, + "node_modules/bs58check": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-4.0.0.tgz", + "integrity": "sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.2.0", + "bs58": "^6.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, + "node_modules/bufferutil": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz", + "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", + "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { - "fill-range": "^7.1.1" + "node-gyp-build": "^4.3.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/bs58": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", - "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", - "license": "MIT", - "dependencies": { - "base-x": "^5.0.0" + "node": ">=6.14.2" } }, "node_modules/bundle-name": { @@ -3343,6 +4073,18 @@ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", "license": "MIT" }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3493,6 +4235,21 @@ "benchmarks" ] }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "license": "MIT", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, "node_modules/esbuild": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", @@ -4032,6 +4789,14 @@ "dev": true, "license": "MIT" }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4082,6 +4847,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-stable-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", + "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==", + "license": "MIT" + }, "node_modules/fast-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", @@ -4408,6 +5179,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gql.tada": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/gql.tada/-/gql.tada-1.9.0.tgz", + "integrity": "sha512-1LMiA46dRs5oF7Qev6vMU32gmiNvM3+3nHoQZA9K9j2xQzH8xOAWnnJrLSbZOFHTSdFxqn86TL6beo1/7ja/aA==", + "license": "MIT", + "dependencies": { + "@0no-co/graphql.web": "^1.0.5", + "@0no-co/graphqlsp": "^1.12.13", + "@gql.tada/cli-utils": "1.7.2", + "@gql.tada/internal": "1.0.8" + }, + "bin": { + "gql-tada": "bin/cli.js", + "gql.tada": "bin/cli.js" + }, + "peerDependencies": { + "typescript": "^5.0.0" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4415,6 +5205,15 @@ "dev": true, "license": "ISC" }, + "node_modules/graphql": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.1.tgz", + "integrity": "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/h3": { "version": "1.15.5", "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.5.tgz", @@ -4548,6 +5347,15 @@ "human-id": "dist/cli.js" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", @@ -4570,6 +5378,26 @@ "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", "license": "Apache-2.0" }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", @@ -4781,6 +5609,15 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/isows": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", @@ -4796,6 +5633,53 @@ "ws": "*" } }, + "node_modules/jayson": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.3.0.tgz", + "integrity": "sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==", + "license": "MIT", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "stream-json": "^1.9.1", + "uuid": "^8.3.2", + "ws": "^7.5.10" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" + }, + "node_modules/jayson/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/jayson/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/jose": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", @@ -4862,6 +5746,12 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -5194,7 +6084,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -5226,6 +6115,18 @@ "node": ">= 6.13.0" } }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-mock-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", @@ -5654,6 +6555,12 @@ "pathe": "^2.0.1" } }, + "node_modules/poseidon-lite": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/poseidon-lite/-/poseidon-lite-0.2.1.tgz", + "integrity": "sha512-xIr+G6HeYfOhCuswdqcFpSX47SPhm0EpisWJ6h7fHlWwaVIvH3dLnejpatrtw6Xc6HaLrpq05y7VRfvDmDGIog==", + "license": "MIT" + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -6060,6 +6967,86 @@ "node": ">= 18" } }, + "node_modules/rpc-websockets": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.5.tgz", + "integrity": "sha512-4mAmr+AEhPYJ9TmDtxF3r3ZcbWy7W8kvZ4PoZYw/Xgp2J7WixjwTgiQZsoTDvch5nimmg3Ay6/0Kuh9oIvVs9A==", + "license": "LGPL-3.0-only", + "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/uuid": "^10.0.0", + "@types/ws": "^8.2.2", + "buffer": "^6.0.3", + "eventemitter3": "^5.0.1", + "uuid": "^11.0.0", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^6.0.0" + } + }, + "node_modules/rpc-websockets/node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/rpc-websockets/node_modules/utf-8-validate": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz", + "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/rpc-websockets/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/rpc-websockets/node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -6096,6 +7083,26 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-stable-stringify": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", @@ -6406,6 +7413,21 @@ "dev": true, "license": "MIT" }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6491,6 +7513,15 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/superstruct": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", + "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6517,6 +7548,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -6636,7 +7672,6 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, "license": "MIT" }, "node_modules/tree-kill": { @@ -6897,7 +7932,6 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -6913,6 +7947,15 @@ "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", "license": "MIT" }, + "node_modules/uint8array-tools": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.9.tgz", + "integrity": "sha512-9vqDWmoSXOoi+K14zNaf6LBV51Q8MayF0/IiQs3GlygIKUYtog603e6virExkjjFosfJUBI4LhbQK1iq8IG11A==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/uint8arrays": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", @@ -6932,7 +7975,6 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, "license": "MIT" }, "node_modules/universalify": { @@ -7100,11 +8142,43 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/valibot": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz", + "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==", + "license": "MIT", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/valid-url": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" }, + "node_modules/varuint-bitcoin": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-2.0.0.tgz", + "integrity": "sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog==", + "license": "MIT", + "dependencies": { + "uint8array-tools": "^0.0.8" + } + }, + "node_modules/varuint-bitcoin/node_modules/uint8array-tools": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.8.tgz", + "integrity": "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -7115,9 +8189,9 @@ } }, "node_modules/viem": { - "version": "2.45.3", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.45.3.tgz", - "integrity": "sha512-axOD7rIbGiDHHA1MHKmpqqTz3CMCw7YpE/FVypddQMXL5i364VkNZh9JeEJH17NO484LaZUOMueo35IXyL76Mw==", + "version": "2.47.0", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.47.0.tgz", + "integrity": "sha512-jU5e1E1s5E5M1y+YrELDnNar/34U8NXfVcRfxtVETigs2gS1vvW2ngnBoQUGBwLnNr0kNv+NUu4m10OqHByoFw==", "funding": [ { "type": "github", @@ -7132,7 +8206,7 @@ "@scure/bip39": "1.6.0", "abitype": "1.2.3", "isows": "1.0.7", - "ox": "0.12.1", + "ox": "0.14.0", "ws": "8.18.3" }, "peerDependencies": { @@ -7172,9 +8246,9 @@ } }, "node_modules/viem/node_modules/ox": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.12.1.tgz", - "integrity": "sha512-uU0llpthaaw4UJoXlseCyBHmQ3bLrQmz9rRLIAUHqv46uHuae9SE+ukYBRIPVCnlEnHKuWjDUcDFHWx9gbGNoA==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.0.tgz", + "integrity": "sha512-WLOB7IKnmI3Ol6RAqY7CJdZKl8QaI44LN91OGF1061YIeN6bL5IsFcdp7+oQShRyamE/8fW/CBRWhJAOzI35Dw==", "funding": [ { "type": "github", @@ -7397,14 +8471,12 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -7594,9 +8666,38 @@ "zod": "^3.25 || ^4" } }, + "node_modules/zustand": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.11.tgz", + "integrity": "sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + }, "packages/cli-sdk": { "name": "@walletconnect/cli-sdk", - "version": "0.6.0", + "version": "0.7.0", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@walletconnect/keyvaluestorage": "1.1.1", @@ -7622,9 +8723,10 @@ }, "packages/companion-wallet": { "name": "@walletconnect/companion-wallet", - "version": "0.6.0", + "version": "0.7.0", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { + "@lifi/sdk": "^3.15.7", "@walletconnect/cli-sdk": "*", "viem": "^2.30.0" }, @@ -7644,7 +8746,7 @@ }, "packages/pay-cli": { "name": "@walletconnect/pay-cli", - "version": "0.6.0", + "version": "0.7.0", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@walletconnect/cli-sdk": "*", @@ -7665,7 +8767,7 @@ }, "packages/staking-cli": { "name": "@walletconnect/staking-cli", - "version": "0.6.0", + "version": "0.7.0", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@walletconnect/cli-sdk": "*", diff --git a/packages/cli-sdk/src/cli.ts b/packages/cli-sdk/src/cli.ts index 3acbcca..2682da5 100644 --- a/packages/cli-sdk/src/cli.ts +++ b/packages/cli-sdk/src/cli.ts @@ -228,6 +228,9 @@ async function cmdSendTransaction(jsonInput: string, browser: boolean): Promise< // EVM: existing eth_sendTransaction flow const from = tx.from || parseAccount(result.accounts[0]).address; + // Pre-flight balance check — non-blocking warning + const balanceWarning = warnIfInsufficientBalance(chainId, from, tx.value); + const txHash = await sdk.request({ chainId, request: { @@ -236,6 +239,7 @@ async function cmdSendTransaction(jsonInput: string, browser: boolean): Promise< }, }); + await balanceWarning; process.stdout.write(JSON.stringify({ transactionHash: txHash })); } } finally { @@ -243,6 +247,49 @@ async function cmdSendTransaction(jsonInput: string, browser: boolean): Promise< } } +const EVM_RPC_URLS: Record = { + "eip155:1": "https://eth.drpc.org", + "eip155:8453": "https://mainnet.base.org", + "eip155:10": "https://mainnet.optimism.io", +}; + +async function checkBalanceRpc(rpcUrl: string, address: string): Promise { + const res = await fetch(rpcUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "eth_getBalance", + params: [address, "latest"], + }), + }); + const json = (await res.json()) as { result: string }; + return BigInt(json.result); +} + +async function warnIfInsufficientBalance( + chainId: string, + address: string, + txValue: string | undefined, +): Promise { + const rpcUrl = EVM_RPC_URLS[chainId]; + if (!rpcUrl || !txValue) return; + + try { + const balance = await checkBalanceRpc(rpcUrl, address); + const value = BigInt(txValue); + if (balance < value) { + process.stderr.write( + `\nWarning: Wallet may have insufficient balance on ${chainId}.\n` + + ` Consider: companion-wallet swidge --to-chain ${chainId} --to-token eth --amount \n\n`, + ); + } + } catch { + // Silently ignore balance check failures + } +} + async function cmdDisconnect(): Promise { const projectId = getProjectId(); const sdk = createSDK({ projectId }); diff --git a/packages/companion-wallet/package.json b/packages/companion-wallet/package.json index 69436f1..55a1807 100644 --- a/packages/companion-wallet/package.json +++ b/packages/companion-wallet/package.json @@ -30,6 +30,7 @@ "lint": "eslint --fix 'src/**/*.ts'" }, "dependencies": { + "@lifi/sdk": "^3.15.7", "@walletconnect/cli-sdk": "*", "viem": "^2.30.0" }, diff --git a/packages/companion-wallet/src/chains.ts b/packages/companion-wallet/src/chains.ts index ea47050..0c8f38b 100644 --- a/packages/companion-wallet/src/chains.ts +++ b/packages/companion-wallet/src/chains.ts @@ -65,6 +65,17 @@ export function parseChainId(caip2: string): number { return parseInt(parts[1], 10); } +/** + * Resolve a viem Chain object by its numeric chain ID. + * Used by the LI.FI SDK switchChain callback. + */ +export function resolveChainByNumericId(numericId: number): Chain { + for (const entry of Object.values(CHAIN_REGISTRY)) { + if (entry.chain.id === numericId) return entry.chain; + } + throw new Error(`Unsupported numeric chain ID: ${numericId}`); +} + /** * Get the human-readable name for a CAIP-2 chain. */ diff --git a/packages/companion-wallet/src/cli.ts b/packages/companion-wallet/src/cli.ts index 6dab906..d2a483d 100644 --- a/packages/companion-wallet/src/cli.ts +++ b/packages/companion-wallet/src/cli.ts @@ -32,6 +32,7 @@ import { type GetSessionInput, type ErrorResponse, type HistoryInput, + type SwidgeInput, } from "./types.js"; function getVersion(): string { @@ -119,6 +120,7 @@ async function handleInfo(): Promise { "fund", "drain", "history", + "swidge", ], chains: SUPPORTED_CHAINS, }; @@ -415,6 +417,70 @@ async function handleDrain(): Promise { } } +async function handleSwidge(): Promise { + warnBeta(); + let account = parseCliArg("account"); + let fromChain = parseCliArg("from-chain"); + let toChain = parseCliArg("to-chain"); + let fromToken = parseCliArg("from-token"); + let toToken = parseCliArg("to-token"); + let amount = parseCliArg("amount"); + + // Also accept piped JSON input + const input = await parseInput(); + if (input?.fromChain) fromChain = input.fromChain; + if (input?.toChain) toChain = input.toChain; + if (input?.fromToken) fromToken = input.fromToken; + if (input?.toToken) toToken = input.toToken; + if (input?.amount) amount = input.amount; + if (input?.account) account = input.account; + + try { + // Interactive prompts when flags missing and TTY + if (process.stdin.isTTY) { + if (!fromChain) fromChain = await selectChain(); + if (!fromToken) fromToken = await selectToken(fromChain); + if (!toChain) toChain = await selectChain(); + if (!toToken) toToken = await selectToken(toChain); + if (!amount) amount = await inputAmount(fromToken); + } + + if (!fromChain || !toChain || !amount) { + respondError( + "Missing required flags: --from-chain, --to-chain, --amount", + "INVALID_INPUT", + ); + process.exit(ExitCode.ERROR); + } + + if (!account) { + const addresses = listAddresses(); + if (addresses.length === 0) { + respondError("No wallet found. Run 'generate' first.", "INVALID_INPUT"); + process.exit(ExitCode.ERROR); + } + account = addresses[0]; + } + + const privateKey = loadKey(account); + const { swidge } = await import("./swidge.js"); + const result = await swidge(privateKey, { + fromChain, + toChain, + fromToken: fromToken || "eth", + toToken: toToken || "eth", + amount, + }); + respond(result); + } catch (err) { + respondError( + err instanceof Error ? err.message : "Swidge failed", + "SWIDGE_ERROR", + ); + process.exit(ExitCode.ERROR); + } +} + async function handleHistory(): Promise { try { const lastRaw = parseCliArg("last"); @@ -471,6 +537,7 @@ const HANDLERS: Record Promise> = { fund: handleFund, drain: handleDrain, history: handleHistory, + swidge: handleSwidge, }; async function main(): Promise { diff --git a/packages/companion-wallet/src/index.ts b/packages/companion-wallet/src/index.ts index 43314c2..4e66627 100644 --- a/packages/companion-wallet/src/index.ts +++ b/packages/companion-wallet/src/index.ts @@ -2,9 +2,11 @@ export { generateAndStore, loadKey, loadMnemonic, listAddresses, resolveAccount, export { signMessage, signTypedData, signTransaction, normalizeTransaction } from "./signer.js"; export { sendTransaction, getBalance, getTokenBalance, getBalances } from "./rpc.js"; export { resolveChain, getTransport, parseChainId, getChainName, SUPPORTED_CHAINS } from "./chains.js"; -export { getToken, getTokenSymbols, parseTokenAmount, buildErc20Transfer } from "./tokens.js"; +export { getToken, getTokenSymbols, parseTokenAmount, buildErc20Transfer, getLifiTokenAddress, findTokenSymbolByAddress } from "./tokens.js"; export type { TokenInfo } from "./tokens.js"; -export { selectChain, selectToken, inputAmount, inputAddress } from "./prompt.js"; +export { resolveChainByNumericId } from "./chains.js"; +export { swidge, swidgeIfNeeded } from "./swidge.js"; +export { ask, selectChain, selectToken, inputAmount, inputAddress } from "./prompt.js"; export { fund } from "./fund.js"; export type { FundOptions, FundResult } from "./fund.js"; export { drain } from "./drain.js"; @@ -46,4 +48,8 @@ export type { ErrorResponse, AuditEntry, HistoryInput, + SwidgeOptions, + SwidgeResult, + BridgeResult, + SwidgeInput, } from "./types.js"; diff --git a/packages/companion-wallet/src/prompt.ts b/packages/companion-wallet/src/prompt.ts index e589bbb..1a13346 100644 --- a/packages/companion-wallet/src/prompt.ts +++ b/packages/companion-wallet/src/prompt.ts @@ -1,10 +1,14 @@ -import { createInterface } from "node:readline/promises"; +import { createInterface, type Interface } from "node:readline/promises"; import { stdin, stdout } from "node:process"; +import type { Writable } from "node:stream"; import { SUPPORTED_CHAINS, getChainName } from "./chains.js"; import { getTokenSymbols } from "./tokens.js"; -async function ask(question: string): Promise { - const rl = createInterface({ input: stdin, output: stdout }); +export async function ask( + question: string, + output: Writable = stdout, +): Promise { + const rl: Interface = createInterface({ input: stdin, output }); try { const answer = await rl.question(question); return answer.trim(); diff --git a/packages/companion-wallet/src/rpc.ts b/packages/companion-wallet/src/rpc.ts index 3d16cda..8a98f4b 100644 --- a/packages/companion-wallet/src/rpc.ts +++ b/packages/companion-wallet/src/rpc.ts @@ -76,6 +76,7 @@ export async function getBalances( /** * Send a transaction: estimate gas, set nonce, sign, and broadcast. + * Automatically checks balance and bridges from another chain if needed. * Returns the transaction hash. */ export async function sendTransaction( @@ -83,9 +84,35 @@ export async function sendTransaction( transaction: Record, caip2Chain: string, ): Promise { + const account = privateKeyToAccount(privateKey); + + // Check balance and bridge if needed (dynamic import to avoid circular dep) + try { + const { swidgeIfNeeded } = await import("./swidge.js"); + const swidgeResult = await swidgeIfNeeded( + privateKey, + account.address, + transaction, + caip2Chain, + ); + if (swidgeResult.bridged && swidgeResult.bridgeResult) { + const br = swidgeResult.bridgeResult; + process.stderr.write( + `\nSwidged: ${br.fromAmount} ${br.fromToken} (${br.fromChain}) -> ` + + `${br.toAmount} ${br.toToken} (${br.toChain})\n\n`, + ); + } + } catch (err) { + // Swidge check is best-effort; log and proceed with transaction + if (err instanceof Error && !err.message.includes("Cannot find module")) { + process.stderr.write( + `Swidge check skipped: ${err.message}\n`, + ); + } + } + const chain = resolveChain(caip2Chain); const transport = getTransport(caip2Chain); - const account = privateKeyToAccount(privateKey); const publicClient = createPublicClient({ chain, transport }); const walletClient = createWalletClient({ account, chain, transport }); diff --git a/packages/companion-wallet/src/swidge.ts b/packages/companion-wallet/src/swidge.ts new file mode 100644 index 0000000..15e7105 --- /dev/null +++ b/packages/companion-wallet/src/swidge.ts @@ -0,0 +1,424 @@ +import { + createConfig, + EVM, + getQuote, + convertQuoteToRoute, + executeRoute, + type RouteExtended, +} from "@lifi/sdk"; +import { + createWalletClient, + createPublicClient, + http, + type Hex, + formatUnits, +} from "viem"; +import { mainnet } from "viem/chains"; +import { privateKeyToAccount } from "viem/accounts"; +import { + resolveChain, + getTransport, + parseChainId, + resolveChainByNumericId, + SUPPORTED_CHAINS, +} from "./chains.js"; +import { getBalance, getTokenBalance, getBalances } from "./rpc.js"; +import { + getToken, + getLifiTokenAddress, + parseTokenAmount, + findTokenSymbolByAddress, +} from "./tokens.js"; +import { ask } from "./prompt.js"; +import type { + BalanceEntry, + SwidgeNeeded, + SwidgeResult, + BridgeResult, + SwidgeOptions, +} from "./types.js"; + +/** Track LI.FI SDK init state by account address (not private key) */ +let lifiInitAddress: string | null = null; + +/** Initialize LI.FI SDK with companion wallet's viem wallet client */ +function initLifi(privateKey: Hex): void { + const account = privateKeyToAccount(privateKey); + if (lifiInitAddress === account.address) return; + + createConfig({ + integrator: "walletconnect-agent-sdk", + providers: [ + EVM({ + getWalletClient: async () => + createWalletClient({ + account, + chain: mainnet, + transport: http(mainnet.rpcUrls.default.http[0]), + }), + switchChain: async (chainId: number) => { + const chain = resolveChainByNumericId(chainId); + return createWalletClient({ + account, + chain, + transport: http(chain.rpcUrls.default.http[0]), + }); + }, + }), + ], + }); + + lifiInitAddress = account.address; +} + +/** Check if a transaction has sufficient funds, returns deficit details if not */ +export async function checkSufficiency( + address: Hex, + tx: Record, + caip2Chain: string, +): Promise { + const chain = resolveChain(caip2Chain); + const transport = getTransport(caip2Chain); + const publicClient = createPublicClient({ chain, transport }); + + const nativeBalance = await getBalance(address, caip2Chain); + + // Estimate gas cost + let gasCost: bigint; + try { + const gas = await publicClient.estimateGas({ + account: address, + to: tx.to as Hex, + value: tx.value ? BigInt(tx.value as string | number) : undefined, + data: tx.data as Hex | undefined, + }); + const gasPrice = await publicClient.getGasPrice(); + gasCost = gas * gasPrice; + } catch { + // Fallback: 21k gas * 50 gwei + gasCost = 21_000n * 50_000_000_000n; + } + + const data = (tx.data as string | undefined) || ""; + const value = tx.value ? BigInt(tx.value as string | number) : 0n; + + // ERC-20 transfer (selector: 0xa9059cbb) + if (data.startsWith("0xa9059cbb") && tx.to) { + const amountHex = "0x" + data.slice(74, 138); + const transferAmount = BigInt(amountHex); + const tokenBalance = await getTokenBalance( + address, + tx.to as Hex, + caip2Chain, + ); + + if (tokenBalance < transferAmount) { + const tokenSymbol = findTokenSymbolByAddress( + tx.to as string, + caip2Chain, + ); + return { + token: tokenSymbol || (tx.to as string), + needed: transferAmount, + available: tokenBalance, + deficit: transferAmount - tokenBalance, + isGas: false, + }; + } + + if (nativeBalance < gasCost) { + return { + token: "eth", + needed: gasCost, + available: nativeBalance, + deficit: gasCost - nativeBalance, + isGas: true, + }; + } + + return null; + } + + // ERC-20 approve (selector: 0x095ea7b3) - only need gas + if (data.startsWith("0x095ea7b3")) { + if (nativeBalance < gasCost) { + return { + token: "eth", + needed: gasCost, + available: nativeBalance, + deficit: gasCost - nativeBalance, + isGas: true, + }; + } + return null; + } + + // Native transfer or generic contract call + const totalNeeded = value + gasCost; + if (nativeBalance < totalNeeded) { + return { + token: "eth", + needed: totalNeeded, + available: nativeBalance, + deficit: totalNeeded - nativeBalance, + isGas: value === 0n, + }; + } + + return null; +} + +/** Scan supported chains for token balances, optionally excluding a chain */ +export async function scanAllBalances( + address: Hex, + excludeChain?: string, +): Promise> { + const chains = excludeChain + ? SUPPORTED_CHAINS.filter((c) => c !== excludeChain) + : SUPPORTED_CHAINS; + const result = new Map(); + await Promise.all( + chains.map(async (chain) => { + try { + const balances = await getBalances(address, chain); + result.set(chain, balances); + } catch { + result.set(chain, []); + } + }), + ); + return result; +} + +/** Source candidate for bridging */ +interface SourceCandidate { + chain: string; + token: string; + balance: bigint; + decimals: number; +} + +/** Find the best source chain/token with enough funds to bridge */ +export function findBestSource( + allBalances: Map, + targetChain: string, + targetToken: string, +): SourceCandidate | null { + let best: SourceCandidate | null = null; + + for (const [chain, balances] of allBalances) { + if (chain === targetChain) continue; + + for (const entry of balances) { + const raw = BigInt(entry.raw); + if (raw === 0n) continue; + + const sym = entry.token.toLowerCase(); + let tokenInfo; + try { + tokenInfo = getToken(sym, chain); + } catch { + continue; + } + + const candidate: SourceCandidate = { + chain, + token: sym, + balance: raw, + decimals: tokenInfo.decimals, + }; + + // Prefer same token on another chain + if (sym === targetToken.toLowerCase()) { + if ( + !best || + best.token !== targetToken.toLowerCase() || + raw > best.balance + ) { + best = candidate; + } + } else if (!best || best.token !== targetToken.toLowerCase()) { + // Any token with balance as fallback (prefer higher balance) + if (!best || raw > best.balance) { + best = candidate; + } + } + } + } + + return best; +} + +/** Core LI.FI route execution — shared by swidgeIfNeeded and swidge */ +async function executeLifiRoute( + privateKey: Hex, + fromChain: string, + toChain: string, + fromToken: string, + toToken: string, + amount: bigint, +): Promise { + initLifi(privateKey); + + const account = privateKeyToAccount(privateKey); + const fromChainId = parseChainId(fromChain); + const toChainId = parseChainId(toChain); + const fromTokenAddress = getLifiTokenAddress(fromToken, fromChain); + const toTokenAddress = getLifiTokenAddress(toToken, toChain); + + const quote = await getQuote({ + fromChain: fromChainId, + toChain: toChainId, + fromToken: fromTokenAddress, + toToken: toTokenAddress, + fromAmount: amount.toString(), + fromAddress: account.address, + }); + + const route = convertQuoteToRoute(quote); + + const executedRoute: RouteExtended = await executeRoute(route, { + updateRouteHook: (updatedRoute: RouteExtended) => { + const step = updatedRoute.steps[0]; + if (step?.execution?.status) { + process.stderr.write(`\r Bridge status: ${step.execution.status}`); + } + }, + }); + + process.stderr.write("\n"); + + const txHash = + executedRoute.steps[0]?.execution?.process?.find( + (p: { txHash?: string }) => p.txHash, + )?.txHash || "0x"; + + const fromTokenInfo = getToken(fromToken, fromChain); + const toTokenInfo = getToken(toToken, toChain); + + return { + fromChain, + toChain, + fromToken: fromTokenInfo.symbol, + toToken: toTokenInfo.symbol, + fromAmount: formatUnits(amount, fromTokenInfo.decimals), + toAmount: quote.estimate?.toAmount + ? formatUnits(BigInt(quote.estimate.toAmount), toTokenInfo.decimals) + : "unknown", + txHash, + }; +} + +/** Prompt for bridge confirmation in TTY mode */ +async function confirmBridge( + source: SourceCandidate, + targetChain: string, + targetToken: string, + deficit: bigint, +): Promise { + const fromTokenInfo = getToken(source.token, source.chain); + let toTokenInfo; + try { + toTokenInfo = getToken(targetToken, targetChain); + } catch { + toTokenInfo = { symbol: targetToken, decimals: 18 }; + } + + const deficitFormatted = formatUnits(deficit, toTokenInfo.decimals); + + process.stderr.write( + `\nInsufficient ${toTokenInfo.symbol} on ${targetChain}.\n` + + ` Bridge ~${deficitFormatted} ${toTokenInfo.symbol} from ${source.chain} (${fromTokenInfo.symbol})?\n`, + ); + + const answer = await ask(" Proceed? (y/n) ", process.stderr); + return answer.toLowerCase() === "y"; +} + +/** + * Check balance before a transaction and auto-bridge if needed. + * In TTY mode, prompts for confirmation. In pipe/agent mode, auto-bridges. + */ +export async function swidgeIfNeeded( + privateKey: Hex, + address: Hex, + tx: Record, + caip2Chain: string, +): Promise { + let needed: SwidgeNeeded | null; + try { + needed = await checkSufficiency(address, tx, caip2Chain); + } catch (err) { + process.stderr.write( + `Swidge check skipped: ${err instanceof Error ? err.message : String(err)}\n`, + ); + return { bridged: false }; + } + + if (!needed) return { bridged: false }; + + // Scan other chains for available funds (skip target chain) + const allBalances = await scanAllBalances(address, caip2Chain); + const source = findBestSource(allBalances, caip2Chain, needed.token); + + if (!source) { + process.stderr.write( + `\nInsufficient ${needed.token} on ${caip2Chain} and no funds found on other chains to bridge.\n`, + ); + return { bridged: false }; + } + + // TTY mode: prompt for confirmation + if (process.stdin.isTTY) { + const confirmed = await confirmBridge( + source, + caip2Chain, + needed.token, + needed.deficit, + ); + if (!confirmed) { + return { bridged: false }; + } + } else { + // Pipe/agent mode: auto-bridge, log to stderr + let toTokenInfo; + try { + toTokenInfo = getToken(needed.token, caip2Chain); + } catch { + toTokenInfo = { symbol: needed.token, decimals: 18 }; + } + process.stderr.write( + `Auto-bridging ${formatUnits(needed.deficit, toTokenInfo.decimals)} ${toTokenInfo.symbol} from ${source.chain}...\n`, + ); + } + + const bridgeResult = await executeLifiRoute( + privateKey, + source.chain, + caip2Chain, + source.token, + needed.token, + needed.deficit, + ); + + return { bridged: true, bridgeResult }; +} + +/** + * Standalone bridge/swap between chains via LI.FI SDK. + */ +export async function swidge( + privateKey: Hex, + options: SwidgeOptions, +): Promise { + const fromTokenInfo = getToken(options.fromToken, options.fromChain); + const amount = parseTokenAmount(options.amount, fromTokenInfo.decimals); + return executeLifiRoute( + privateKey, + options.fromChain, + options.toChain, + options.fromToken, + options.toToken, + amount, + ); +} diff --git a/packages/companion-wallet/src/tokens.ts b/packages/companion-wallet/src/tokens.ts index 074a146..d383cae 100644 --- a/packages/companion-wallet/src/tokens.ts +++ b/packages/companion-wallet/src/tokens.ts @@ -61,6 +61,39 @@ export function getToken(symbol: string, chain: string): TokenInfo { throw new Error(`Unknown token: ${symbol}`); } +/** + * Reverse-lookup: find a token symbol by its contract address on a chain. + * Returns null if no registered token matches. + */ +export function findTokenSymbolByAddress( + address: string, + chain: string, +): string | null { + const symbols = getTokenSymbols(chain); + for (const sym of symbols) { + const token = getToken(sym, chain); + if ( + token.address && + token.address.toLowerCase() === address.toLowerCase() + ) { + return sym; + } + } + return null; +} + +/** Native token address used by LI.FI SDK */ +const NATIVE_TOKEN_ADDRESS = "0x0000000000000000000000000000000000000000"; + +/** + * Get the token address in the format expected by LI.FI SDK. + * Returns the zero address for native tokens (ETH). + */ +export function getLifiTokenAddress(symbol: string, chain: string): string { + const token = getToken(symbol, chain); + return token.address || NATIVE_TOKEN_ADDRESS; +} + /** * Parse a human-readable amount into its smallest unit (wei / micro-USDC). */ diff --git a/packages/companion-wallet/src/types.ts b/packages/companion-wallet/src/types.ts index e48e1da..0e39395 100644 --- a/packages/companion-wallet/src/types.ts +++ b/packages/companion-wallet/src/types.ts @@ -26,7 +26,8 @@ export type Operation = | "balance" | "fund" | "drain" - | "history"; + | "history" + | "swidge"; /** Info response */ export interface InfoResponse { @@ -196,6 +197,51 @@ export interface AuditEntry { error?: string; } +/** Swidge (swap/bridge) options for manual bridging */ +export interface SwidgeOptions { + fromChain: string; + toChain: string; + fromToken: string; + toToken: string; + amount: string; +} + +/** Result of a sufficiency check — what's missing */ +export interface SwidgeNeeded { + token: string; + needed: bigint; + available: bigint; + deficit: bigint; + isGas: boolean; +} + +/** Result of the swidgeIfNeeded check */ +export interface SwidgeResult { + bridged: boolean; + bridgeResult?: BridgeResult; +} + +/** Result of an executed bridge/swap */ +export interface BridgeResult { + fromChain: string; + toChain: string; + fromToken: string; + toToken: string; + fromAmount: string; + toAmount: string; + txHash: string; +} + +/** Piped JSON input for the swidge CLI operation */ +export interface SwidgeInput { + fromChain: string; + toChain: string; + fromToken: string; + toToken: string; + amount: string; + account?: string; +} + /** History query input (CLI flags) */ export interface HistoryInput { operation?: string; diff --git a/packages/companion-wallet/test/swidge.test.ts b/packages/companion-wallet/test/swidge.test.ts new file mode 100644 index 0000000..b7f2985 --- /dev/null +++ b/packages/companion-wallet/test/swidge.test.ts @@ -0,0 +1,224 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; + +// Mock @lifi/sdk before any imports +vi.mock("@lifi/sdk", () => ({ + createConfig: vi.fn(), + EVM: vi.fn().mockReturnValue({}), + getQuote: vi.fn(), + convertQuoteToRoute: vi.fn(), + executeRoute: vi.fn(), +})); + +// Mock rpc.ts to avoid real network calls +vi.mock("../src/rpc.js", () => ({ + getBalance: vi.fn(), + getTokenBalance: vi.fn(), + getBalances: vi.fn(), + sendTransaction: vi.fn(), +})); + +import { findBestSource, checkSufficiency } from "../src/swidge.js"; +import { getLifiTokenAddress } from "../src/tokens.js"; +import { resolveChainByNumericId } from "../src/chains.js"; +import { getBalance, getTokenBalance } from "../src/rpc.js"; +import { mainnet, base, optimism } from "viem/chains"; +import type { BalanceEntry } from "../src/types.js"; + +describe("swidge", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe("getLifiTokenAddress", () => { + it("returns zero address for native ETH", () => { + const addr = getLifiTokenAddress("eth", "eip155:1"); + expect(addr).toBe("0x0000000000000000000000000000000000000000"); + }); + + it("returns contract address for USDC", () => { + const addr = getLifiTokenAddress("usdc", "eip155:1"); + expect(addr).toBe("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); + }); + + it("returns contract address for WCT on Optimism", () => { + const addr = getLifiTokenAddress("wct", "eip155:10"); + expect(addr).toBe("0xeF4461891DfB3AC8572cCf7C794664A8DD927945"); + }); + + it("returns USDC address on Base", () => { + const addr = getLifiTokenAddress("usdc", "eip155:8453"); + expect(addr).toBe("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"); + }); + }); + + describe("resolveChainByNumericId", () => { + it("resolves Ethereum mainnet (1)", () => { + expect(resolveChainByNumericId(1).id).toBe(mainnet.id); + }); + + it("resolves Base (8453)", () => { + expect(resolveChainByNumericId(8453).id).toBe(base.id); + }); + + it("resolves Optimism (10)", () => { + expect(resolveChainByNumericId(10).id).toBe(optimism.id); + }); + + it("throws for unsupported chain ID", () => { + expect(() => resolveChainByNumericId(999)).toThrow( + "Unsupported numeric chain ID: 999", + ); + }); + }); + + describe("findBestSource", () => { + function makeBalances( + entries: Record, + ): Map { + return new Map(Object.entries(entries)); + } + + it("returns null when no funds on other chains", () => { + const balances = makeBalances({ + "eip155:10": [{ token: "ETH", balance: "0", raw: "0" }], + "eip155:1": [{ token: "ETH", balance: "0", raw: "0" }], + "eip155:8453": [{ token: "ETH", balance: "0", raw: "0" }], + }); + + const result = findBestSource(balances, "eip155:10", "eth"); + expect(result).toBeNull(); + }); + + it("prefers same token on another chain", () => { + const balances = makeBalances({ + "eip155:10": [{ token: "ETH", balance: "0", raw: "0" }], + "eip155:1": [ + { token: "ETH", balance: "5", raw: "5000000000000000000" }, + { token: "USDC", balance: "100", raw: "100000000" }, + ], + "eip155:8453": [ + { token: "ETH", balance: "2", raw: "2000000000000000000" }, + ], + }); + + const result = findBestSource(balances, "eip155:10", "eth"); + expect(result).not.toBeNull(); + expect(result!.token).toBe("eth"); + expect(result!.chain).toBe("eip155:1"); // Higher balance + }); + + it("falls back to different token when same token not available", () => { + const balances = makeBalances({ + "eip155:10": [{ token: "WCT", balance: "0", raw: "0" }], + "eip155:1": [ + { token: "ETH", balance: "0", raw: "0" }, + { token: "USDC", balance: "50", raw: "50000000" }, + ], + "eip155:8453": [ + { token: "ETH", balance: "0", raw: "0" }, + { token: "USDC", balance: "100", raw: "100000000" }, + ], + }); + + const result = findBestSource(balances, "eip155:10", "wct"); + expect(result).not.toBeNull(); + // Should pick USDC on Base (higher balance) + expect(result!.token).toBe("usdc"); + expect(result!.chain).toBe("eip155:8453"); + }); + + it("skips target chain", () => { + const balances = makeBalances({ + "eip155:10": [ + { token: "ETH", balance: "10", raw: "10000000000000000000" }, + ], + "eip155:1": [{ token: "ETH", balance: "0", raw: "0" }], + }); + + const result = findBestSource(balances, "eip155:10", "eth"); + expect(result).toBeNull(); + }); + }); + + describe("checkSufficiency", () => { + it("returns null when native balance covers value + gas", async () => { + vi.mocked(getBalance).mockResolvedValue( + 10n * 10n ** 18n, // 10 ETH + ); + + const result = await checkSufficiency( + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + { to: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", value: "1000000000000000000" }, + "eip155:1", + ); + + expect(result).toBeNull(); + }); + + it("returns deficit for insufficient native balance", async () => { + vi.mocked(getBalance).mockResolvedValue(0n); + + const result = await checkSufficiency( + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + { to: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", value: "1000000000000000000" }, + "eip155:1", + ); + + expect(result).not.toBeNull(); + expect(result!.token).toBe("eth"); + expect(result!.deficit).toBeGreaterThan(0n); + }); + + it("checks ERC-20 transfer sufficiency", async () => { + // Native balance sufficient for gas + vi.mocked(getBalance).mockResolvedValue(10n ** 18n); + // Token balance insufficient + vi.mocked(getTokenBalance).mockResolvedValue(5000000n); // 5 USDC + + // ERC-20 transfer of 10 USDC: selector(4) + to(32) + amount(32) = 68 bytes + const to = "f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; + const amount = "0000000000000000000000000000000000000000000000000000000000989680"; // 10_000_000 (10 USDC) + const data = `0xa9059cbb000000000000000000000000${to}${amount}`; + + const result = await checkSufficiency( + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + { + to: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", // USDC on Optimism + data, + }, + "eip155:10", + ); + + expect(result).not.toBeNull(); + expect(result!.token).toBe("usdc"); + expect(result!.isGas).toBe(false); + expect(result!.deficit).toBe(10_000_000n - 5_000_000n); + }); + + it("only checks gas for ERC-20 approve", async () => { + vi.mocked(getBalance).mockResolvedValue(10n ** 18n); // Enough for gas + + const to = "f39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; + const amount = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + const data = `0x095ea7b3000000000000000000000000${to}${amount}`; + + const result = await checkSufficiency( + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + { + to: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", + data, + }, + "eip155:10", + ); + + expect(result).toBeNull(); + }); + }); + + describe("TTY detection", () => { + it("detects TTY mode", () => { + // process.stdin.isTTY is undefined in test environment (non-TTY) + expect(process.stdin.isTTY).toBeUndefined(); + }); + }); +});