diff --git a/.env b/.env index 3856e64fa..a7264ca17 100644 --- a/.env +++ b/.env @@ -14,6 +14,8 @@ REACT_APP_COINGECKO_IMMUTABLE_URL="https://tokens.coingecko.com/immutable/all.js REACT_APP_COINGECKO_DOGE_URL="https://tokens.coingecko.com/dogechain/all.json" REACT_APP_COINGECKO_ASTAR_URL="https://tokens.coingecko.com/astar/all.json" REACT_APP_COINGECKO_KAVA_URL="https://tokens.coingecko.com/kava/all.json" +REACT_APP_COINGECKO_ETHEREUM_URL="https://tokens.coingecko.com/ethereum/all.json" + REACT_APP_STAKING_LIST_DEFAULT_URL="https://unpkg.com/quickswap-default-staking-list-address@latest/build/quickswap-default.lpfarms.json" REACT_APP_DUAL_STAKING_LIST_DEFAULT_URL="https://unpkg.com/quickswap-default-staking-list-address@latest/build/quickswap-default.dualfarms.json" REACT_APP_SYRUP_LIST_DEFAULT_URL="https://unpkg.com/quickswap-default-staking-list-address@latest/build/quickswap-default.syrups.json" diff --git a/package-lock.json b/package-lock.json index d28f781d7..9a16ea89d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,9 @@ "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", "@material-ui/styles": "^4.11.5", - "@orbs-network/twap-ui": "^0.10.23", - "@orbs-network/twap-ui-quickswap": "^0.10.23", + "@orbs-network/liquidity-hub-sdk": "^1.0.22", + "@orbs-network/swap-ui": "^0.0.8", + "@orbs-network/twap-sdk": "^2.0.18", "@orderly.network/hooks": "^1.4.3", "@orderly.network/react": "^1.4.3", "@orderly.network/types": "^1.4.3", @@ -4426,6 +4427,7 @@ "version": "0.8.1", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -4437,6 +4439,7 @@ "version": "0.3.9", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -4827,224 +4830,6 @@ "ms": "^2.1.1" } }, - "node_modules/@defi.org/chai-bignumber": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@defi.org/chai-bignumber/-/chai-bignumber-3.0.2.tgz", - "integrity": "sha512-zu0LUJUZrSE30isl91K7NoTSxe6EUtFrLiiTtEoUkCrowRjeUw+U3lg4Vs5WNmc2QurZvHrVPbGRF+9S9Tu8Kw==", - "optional": true, - "peerDependencies": { - "bignumber.js": "*" - } - }, - "node_modules/@defi.org/web3-candies": { - "version": "4.20.4", - "resolved": "https://registry.npmjs.org/@defi.org/web3-candies/-/web3-candies-4.20.4.tgz", - "integrity": "sha512-f9lm1pzNQj6zYZg6WdMX6oufzO3jThjjA8odqVDsSY5XF9I3fLh9Ttam3O8Beknr+uhU2bmJt0ZB3YhWzBXkRQ==", - "dependencies": { - "@types/lodash": "4.x", - "@uniswap/permit2-sdk": "1.x", - "bignumber.js": "9.x", - "debug": "4.x", - "ethereum-multicall": "2.x", - "isomorphic-fetch": "3.x", - "lodash": "4.x", - "prettier": "2.x", - "prettier-plugin-solidity": "latest", - "web3": "1.x" - }, - "optionalDependencies": { - "@defi.org/chai-bignumber": "3.x", - "@nomiclabs/hardhat-etherscan": "3.x", - "@nomiclabs/hardhat-web3": "2.x", - "@openzeppelin/contracts": "4.x", - "@typechain/hardhat": "6.x", - "@typechain/web3-v1": "6.x", - "@types/chai": "4.x", - "@types/fs-extra": "11.x", - "@types/mocha": "10.x", - "@types/node": "18.x", - "@types/prompts": "2.x", - "chai": "4.x", - "dotenv": "16.x", - "fs-extra": "11.x", - "hardhat": "2.x", - "hardhat-gas-reporter": "1.x", - "hardhat-spdx-license-identifier": "2.x", - "hardhat-tracer": "1.x", - "mocha": "10.x", - "patch-package": "7.x", - "prompts": "2.x", - "sinon": "^17.0.1", - "solhint": "3.x", - "ts-generator": "0.1.x", - "ts-node": "10.x", - "typechain": "8.x", - "typescript": "4.x" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "optional": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/@sinonjs/fake-timers": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", - "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", - "optional": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/@sinonjs/samsam": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", - "optional": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "optional": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/@solidity-parser/parser": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.2.tgz", - "integrity": "sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==", - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/@types/node": { - "version": "18.18.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz", - "integrity": "sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==", - "optional": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "optional": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/prettier-plugin-solidity": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.2.0.tgz", - "integrity": "sha512-fgxcUZpVAP+LlRfy5JI5oaAkXGkmsje2VJ5krv/YMm+rcTZbIUwFguSw5f+WFuttMjpDm6wB4UL7WVkArEfiVA==", - "dependencies": { - "@solidity-parser/parser": "^0.16.2", - "semver": "^7.5.4", - "solidity-comments-extractor": "^0.0.7" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "prettier": ">=2.3.0" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/sinon": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", - "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", - "optional": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^11.2.2", - "@sinonjs/samsam": "^8.0.0", - "diff": "^5.1.0", - "nise": "^5.1.5", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "optional": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@defi.org/web3-candies/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@defifofum/multicall": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@defifofum/multicall/-/multicall-1.1.2.tgz", @@ -5057,6 +4842,7 @@ "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", @@ -5074,12 +4860,14 @@ "node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==", + "peer": true }, "node_modules/@emotion/cache": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "peer": true, "dependencies": { "@emotion/memoize": "^0.8.1", "@emotion/sheet": "^1.2.2", @@ -5093,23 +4881,17 @@ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", - "dependencies": { - "@emotion/memoize": "^0.8.1" - } - }, "node_modules/@emotion/memoize": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", + "peer": true }, "node_modules/@emotion/react": { "version": "11.11.4", "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -5133,6 +4915,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "peer": true, "dependencies": { "@emotion/hash": "^0.9.1", "@emotion/memoize": "^0.8.1", @@ -5144,44 +4927,26 @@ "node_modules/@emotion/serialize/node_modules/@emotion/hash": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==", + "peer": true }, "node_modules/@emotion/sheet": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" - }, - "node_modules/@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1" - }, - "peerDependencies": { - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==", + "peer": true }, "node_modules/@emotion/unitless": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "peer": true }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peer": true, "peerDependencies": { "react": ">=16.8.0" } @@ -5189,12 +4954,14 @@ "node_modules/@emotion/utils": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==", + "peer": true }, "node_modules/@emotion/weak-memoize": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==", + "peer": true }, "node_modules/@enzoferey/ethers-error-parser": { "version": "0.2.3", @@ -5319,6 +5086,8 @@ "node_modules/@ethereumjs/tx": { "version": "3.3.2", "license": "MPL-2.0", + "optional": true, + "peer": true, "dependencies": { "@ethereumjs/common": "^2.5.0", "ethereumjs-util": "^7.1.2" @@ -5327,6 +5096,8 @@ "node_modules/@ethereumjs/tx/node_modules/ethereum-cryptography": { "version": "0.1.3", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -5348,6 +5119,8 @@ "node_modules/@ethereumjs/tx/node_modules/ethereumjs-util": { "version": "7.1.5", "license": "MPL-2.0", + "optional": true, + "peer": true, "dependencies": { "@types/bn.js": "^5.1.0", "bn.js": "^5.1.2", @@ -6060,6 +5833,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", + "peer": true, "engines": { "node": ">=14" } @@ -8268,272 +8042,6 @@ "tslib": "^2.3.1" } }, - "node_modules/@mui/base": { - "version": "5.0.0-beta.24", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.24.tgz", - "integrity": "sha512-bKt2pUADHGQtqWDZ8nvL2Lvg2GNJyd/ZUgZAJoYzRgmnxBL9j36MSlS3+exEdYkikcnvVafcBtD904RypFKb0w==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@floating-ui/react-dom": "^2.0.4", - "@mui/types": "^7.2.9", - "@mui/utils": "^5.14.18", - "@popperjs/core": "^2.11.8", - "clsx": "^2.0.0", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/base/node_modules/@floating-ui/react-dom": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.4.tgz", - "integrity": "sha512-CF8k2rgKeh/49UrnIBs4BdxPUV6vize/Db1d/YbCLyp9GiVZ0BEwf5AiDSxJRCr6yOkGqTFHtmrULxkEfYZ7dQ==", - "dependencies": { - "@floating-ui/dom": "^1.5.1" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@mui/base/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@mui/core-downloads-tracker": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.18.tgz", - "integrity": "sha512-yFpF35fEVDV81nVktu0BE9qn2dD/chs7PsQhlyaV3EnTeZi9RZBuvoEfRym1/jmhJ2tcfeWXiRuHG942mQXJJQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - } - }, - "node_modules/@mui/material": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.18.tgz", - "integrity": "sha512-y3UiR/JqrkF5xZR0sIKj6y7xwuEiweh9peiN3Zfjy1gXWXhz5wjlaLdoxFfKIEBUFfeQALxr/Y8avlHH+B9lpQ==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/base": "5.0.0-beta.24", - "@mui/core-downloads-tracker": "^5.14.18", - "@mui/system": "^5.14.18", - "@mui/types": "^7.2.9", - "@mui/utils": "^5.14.18", - "@types/react-transition-group": "^4.4.8", - "clsx": "^2.0.0", - "csstype": "^3.1.2", - "prop-types": "^15.8.1", - "react-is": "^18.2.0", - "react-transition-group": "^4.4.5" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/material/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@mui/material/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, - "node_modules/@mui/private-theming": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.18.tgz", - "integrity": "sha512-WSgjqRlzfHU+2Rou3HlR2Gqfr4rZRsvFgataYO3qQ0/m6gShJN+lhVEvwEiJ9QYyVzMDvNpXZAcqp8Y2Vl+PAw==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/utils": "^5.14.18", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/styled-engine": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.18.tgz", - "integrity": "sha512-pW8bpmF9uCB5FV2IPk6mfbQCjPI5vGI09NOLhtGXPeph/4xIfC3JdIX0TILU0WcTs3aFQqo6s2+1SFgIB9rCXA==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@emotion/cache": "^11.11.0", - "csstype": "^3.1.2", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - } - } - }, - "node_modules/@mui/system": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.18.tgz", - "integrity": "sha512-hSQQdb3KF72X4EN2hMEiv8EYJZSflfdd1TRaGPoR7CIAG347OxCslpBUwWngYobaxgKvq6xTrlIl+diaactVww==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@mui/private-theming": "^5.14.18", - "@mui/styled-engine": "^5.14.18", - "@mui/types": "^7.2.9", - "@mui/utils": "^5.14.18", - "clsx": "^2.0.0", - "csstype": "^3.1.2", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/system/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@mui/types": { - "version": "7.2.9", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.9.tgz", - "integrity": "sha512-k1lN/PolaRZfNsRdAqXtcR71sTnv3z/VCCGPxU8HfdftDkzi335MdJ6scZxvofMAd/K/9EbzCZTFBmlNpQVdCg==", - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/utils": { - "version": "5.14.18", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.18.tgz", - "integrity": "sha512-HZDRsJtEZ7WMSnrHV9uwScGze4wM/Y+u6pDVo+grUjt5yXzn+wI8QX/JwTHh9YSw/WpnUL80mJJjgCnWj2VrzQ==", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@types/prop-types": "^15.7.10", - "prop-types": "^15.8.1", - "react-is": "^18.2.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/utils/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, "node_modules/@multiformats/base-x": { "version": "4.0.1", "license": "MIT" @@ -8596,7 +8104,8 @@ "type": "individual", "url": "https://paulmillr.com/funding/" } - ] + ], + "peer": true }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -8634,6 +8143,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz", "integrity": "sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q==", + "peer": true, "dependencies": { "@nomicfoundation/ethereumjs-common": "4.0.2", "@nomicfoundation/ethereumjs-rlp": "5.0.2", @@ -8651,6 +8161,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -8673,6 +8184,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz", "integrity": "sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w==", + "peer": true, "dependencies": { "@nomicfoundation/ethereumjs-block": "5.0.2", "@nomicfoundation/ethereumjs-common": "4.0.2", @@ -8696,6 +8208,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -8718,6 +8231,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz", "integrity": "sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg==", + "peer": true, "dependencies": { "@nomicfoundation/ethereumjs-util": "9.0.2", "crc-32": "^1.2.0" @@ -8727,6 +8241,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz", "integrity": "sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg==", + "peer": true, "dependencies": { "@nomicfoundation/ethereumjs-block": "5.0.2", "@nomicfoundation/ethereumjs-rlp": "5.0.2", @@ -8743,6 +8258,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -8765,6 +8281,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz", "integrity": "sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ==", + "peer": true, "dependencies": { "@ethersproject/providers": "^5.7.1", "@nomicfoundation/ethereumjs-common": "4.0.2", @@ -8783,6 +8300,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -8805,6 +8323,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz", "integrity": "sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA==", + "peer": true, "bin": { "rlp": "bin/rlp" }, @@ -8816,6 +8335,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz", "integrity": "sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA==", + "peer": true, "dependencies": { "@nomicfoundation/ethereumjs-common": "4.0.2", "@nomicfoundation/ethereumjs-rlp": "5.0.2", @@ -8829,6 +8349,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -8851,6 +8372,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz", "integrity": "sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ==", + "peer": true, "dependencies": { "@nomicfoundation/ethereumjs-rlp": "5.0.2", "@nomicfoundation/ethereumjs-util": "9.0.2", @@ -8866,6 +8388,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -8888,6 +8411,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz", "integrity": "sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g==", + "peer": true, "dependencies": { "@chainsafe/ssz": "^0.9.2", "@ethersproject/providers": "^5.7.2", @@ -8903,12 +8427,14 @@ "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/@chainsafe/as-sha256": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz", - "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==" + "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==", + "peer": true }, "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/@chainsafe/persistent-merkle-tree": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz", "integrity": "sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==", + "peer": true, "dependencies": { "@chainsafe/as-sha256": "^0.3.1" } @@ -8917,6 +8443,7 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz", "integrity": "sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==", + "peer": true, "dependencies": { "@chainsafe/as-sha256": "^0.3.1", "@chainsafe/persistent-merkle-tree": "^0.4.2", @@ -8927,6 +8454,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -8949,6 +8477,7 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz", "integrity": "sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ==", + "peer": true, "dependencies": { "@chainsafe/ssz": "^0.10.0", "@nomicfoundation/ethereumjs-rlp": "5.0.2", @@ -8961,12 +8490,14 @@ "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/as-sha256": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz", - "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==" + "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==", + "peer": true }, "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/persistent-merkle-tree": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz", "integrity": "sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw==", + "peer": true, "dependencies": { "@chainsafe/as-sha256": "^0.3.1" } @@ -8975,6 +8506,7 @@ "version": "0.10.2", "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.10.2.tgz", "integrity": "sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg==", + "peer": true, "dependencies": { "@chainsafe/as-sha256": "^0.3.1", "@chainsafe/persistent-merkle-tree": "^0.5.0" @@ -8984,6 +8516,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -9006,6 +8539,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz", "integrity": "sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA==", + "peer": true, "dependencies": { "@nomicfoundation/ethereumjs-block": "5.0.2", "@nomicfoundation/ethereumjs-blockchain": "7.0.2", @@ -9029,6 +8563,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -9051,6 +8586,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", + "peer": true, "engines": { "node": ">= 12" }, @@ -9097,6 +8633,7 @@ "version": "3.1.7", "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz", "integrity": "sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==", + "peer": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@ethersproject/address": "^5.0.2", @@ -9117,6 +8654,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "peer": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -9130,6 +8668,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "peer": true, "engines": { "node": ">=0.8.0" } @@ -9138,6 +8677,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -9151,6 +8691,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -9159,23 +8700,11 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "peer": true, "engines": { "node": ">= 4.0.0" } }, - "node_modules/@nomiclabs/hardhat-web3": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-web3/-/hardhat-web3-2.0.0.tgz", - "integrity": "sha512-zt4xN+D+fKl3wW2YlTX3k9APR3XZgPkxJYf36AcliJn3oujnKEVRZaHu0PhgLjO+gR+F/kiYayo9fgd2L8970Q==", - "optional": true, - "dependencies": { - "@types/bignumber.js": "^5.0.0" - }, - "peerDependencies": { - "hardhat": "^2.0.0", - "web3": "^1.0.0-beta.36" - } - }, "node_modules/@opensea/seaport-js": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/@opensea/seaport-js/-/seaport-js-4.0.3.tgz", @@ -9414,65 +8943,34 @@ "node": ">=10.0.0" } }, - "node_modules/@orbs-network/twap": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/@orbs-network/twap/-/twap-1.18.2.tgz", - "integrity": "sha512-TJIIp709+5YteyzWyKYvDQEzIoXLvdL4sWnYVz/H623ur7NGAwqqY97LstArYlkOHfrQTCvs71NWX9mmymSJgA==", - "dependencies": { - "@defi.org/web3-candies": "^4.20.3" - } + "node_modules/@orbs-network/liquidity-hub-sdk": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@orbs-network/liquidity-hub-sdk/-/liquidity-hub-sdk-1.0.39.tgz", + "integrity": "sha512-cVTdRY1o8Vqf8iYBSwdZi8rZphNWEjjQ4xlgb3wNF/WKCxB27Zw5y6/CqTjRbC+0Oexny6vxKQ9mnF01nUsnRA==" }, - "node_modules/@orbs-network/twap-ui": { - "version": "0.10.23", - "resolved": "https://registry.npmjs.org/@orbs-network/twap-ui/-/twap-ui-0.10.23.tgz", - "integrity": "sha512-gx/kpl71eTdA0tTzqBFyFSzcvUGV3IeuPJjiFFw+fuesTzdnPvs3Pg4cGMN+wlI4siLi+eSm/vw0n8IapYDPug==", - "dependencies": { - "@defi.org/web3-candies": "^4.20", - "@emotion/react": "11.x", - "@emotion/styled": "11.x", - "@mui/material": "5.x", - "@mui/system": "5.x", - "@orbs-network/twap": "^1.18.x", - "@react-icons/all-files": "^4.1.0", - "@tanstack/react-query": "4.x", - "@types/async-retry": "^1.4.5", - "@types/lodash": "4.x", - "async-retry": "^1.3.3", - "bignumber.js": "9.x", - "emotion-theming": "11.x", - "isomorphic-fetch": "3.x", - "lodash": "4.x", - "moment": "2.x", - "qrcode.react": "^3.1.0", - "react-error-boundary": "^4.0.10", - "react-number-format": "5.x", - "react-text-overflow": "^1.0.2", - "web3": "1.x", - "zustand": "4.x" - }, + "node_modules/@orbs-network/swap-ui": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@orbs-network/swap-ui/-/swap-ui-0.0.8.tgz", + "integrity": "sha512-AJRoZhLENLIY+xelxMPWILo1FXL16AkFKlqVYgDEKqwVoEhp3cL4HA7vdJMvul295RQdLa46Dp6UW+8UM9kSIw==", "peerDependencies": { - "react": "*", - "react-dom": "*" + "react": ">=18.2.0", + "react-dom": ">=18.2.0" } }, - "node_modules/@orbs-network/twap-ui-quickswap": { - "version": "0.10.23", - "resolved": "https://registry.npmjs.org/@orbs-network/twap-ui-quickswap/-/twap-ui-quickswap-0.10.23.tgz", - "integrity": "sha512-n37S1p47s9hComz7pmC2yvgr/rHbg+6jAjyMxz1aDPl0m4x1NZZMknIBlDDP1vjtAHPUDy5KGRUlFLRY0uAg9Q==", + "node_modules/@orbs-network/twap-sdk": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@orbs-network/twap-sdk/-/twap-sdk-2.0.18.tgz", + "integrity": "sha512-fH6aBDKw4l6zBD7xavO3aLp3yo2O6dDb07beGTLWxbUP6IoRKEstjJb78Ry2Lyvz6X25bQfeDamT535C4DCZYw==", "dependencies": { - "@defi.org/web3-candies": "^4.20", - "@mui/material": "5.x", - "@mui/system": "5.x", - "@orbs-network/twap": "^1.18.x", - "@orbs-network/twap-ui": "^0.10.23", - "lodash": "4.x", - "web3": "1.x" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" + "@orbs-network/twap": "^2.0.1", + "bignumber.js": "9.x" } }, + "node_modules/@orbs-network/twap-sdk/node_modules/@orbs-network/twap": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@orbs-network/twap/-/twap-2.2.4.tgz", + "integrity": "sha512-SeEH45f4KXh6hXjbhhE4lPgTzIvMNx9Mun+pdX9plvdKpWAbcg6f1FKfv2MZ1ghtYxHlhuDcthlx159t8ReiOA==" + }, "node_modules/@orderly.network/core": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/@orderly.network/core/-/core-1.5.4.tgz", @@ -9954,15 +9452,6 @@ "node": ">= 8" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, "node_modules/@prisma/debug": { "version": "5.14.0", "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.14.0.tgz", @@ -11006,14 +10495,6 @@ "@babel/runtime": "^7.13.10" } }, - "node_modules/@react-icons/all-files": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", - "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", - "peerDependencies": { - "react": "*" - } - }, "node_modules/@reduxjs/toolkit": { "version": "1.9.5", "dev": true, @@ -11400,6 +10881,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "peer": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -11414,12 +10896,14 @@ "node_modules/@sentry/core/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true }, "node_modules/@sentry/hub": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "peer": true, "dependencies": { "@sentry/types": "5.30.0", "@sentry/utils": "5.30.0", @@ -11432,12 +10916,14 @@ "node_modules/@sentry/hub/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true }, "node_modules/@sentry/minimal": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "peer": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/types": "5.30.0", @@ -11450,12 +10936,14 @@ "node_modules/@sentry/minimal/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true }, "node_modules/@sentry/node": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "peer": true, "dependencies": { "@sentry/core": "5.30.0", "@sentry/hub": "5.30.0", @@ -11474,12 +10962,14 @@ "node_modules/@sentry/node/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true }, "node_modules/@sentry/tracing": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "peer": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -11494,12 +10984,14 @@ "node_modules/@sentry/tracing/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true }, "node_modules/@sentry/types": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "peer": true, "engines": { "node": ">=6" } @@ -11508,6 +11000,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "peer": true, "dependencies": { "@sentry/types": "5.30.0", "tslib": "^1.9.3" @@ -11519,7 +11012,8 @@ "node_modules/@sentry/utils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true }, "node_modules/@sideway/address": { "version": "4.1.4", @@ -11578,12 +11072,6 @@ "type-detect": "4.0.8" } }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "optional": true - }, "node_modules/@smithy/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.0.0.tgz", @@ -12238,15 +11726,6 @@ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, - "node_modules/@solidity-parser/parser": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", - "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", - "optional": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, "node_modules/@soulsolidity/soul-zap-trpc-client": { "version": "1.0.0-beta.0", "resolved": "https://registry.npmjs.org/@soulsolidity/soul-zap-trpc-client/-/soul-zap-trpc-client-1.0.0-beta.0.tgz", @@ -15762,22 +15241,26 @@ "node_modules/@tsconfig/node10": { "version": "1.0.9", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/@typechain/ethers-v5": { "version": "10.2.1", @@ -15803,71 +15286,6 @@ "typescript": ">=3.7.0" } }, - "node_modules/@typechain/hardhat": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-6.1.6.tgz", - "integrity": "sha512-BiVnegSs+ZHVymyidtK472syodx1sXYlYJJixZfRstHVGYTi8V1O7QG4nsjyb0PC/LORcq7sfBUcHto1y6UgJA==", - "optional": true, - "dependencies": { - "fs-extra": "^9.1.0" - }, - "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@typechain/ethers-v5": "^10.2.1", - "ethers": "^5.4.7", - "hardhat": "^2.9.9", - "typechain": "^8.1.1" - } - }, - "node_modules/@typechain/hardhat/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typechain/web3-v1": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/@typechain/web3-v1/-/web3-v1-6.0.7.tgz", - "integrity": "sha512-HWkGplyPL3eWiP0sszqKZh6Bjrdm23srtirUdKp/4BEWKp/o6zofLt8lDn468bRQlQdHaobrbfEeT+3gf/r4eg==", - "optional": true, - "dependencies": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" - }, - "peerDependencies": { - "typechain": "^8.3.2", - "web3": "^1", - "web3-core": "^1", - "web3-eth-contract": "^1" - } - }, - "node_modules/@typechain/web3-v1/node_modules/ts-essentials": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", - "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "optional": true, - "peerDependencies": { - "typescript": ">=3.7.0" - } - }, - "node_modules/@types/async-retry": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/@types/async-retry/-/async-retry-1.4.8.tgz", - "integrity": "sha512-Qup/B5PWLe86yI5I3av6ePGaeQrIHNKCwbsQotD6aHQ6YkHsMUxVZkZsmx/Ry3VZQ6uysHwTjQ7666+k6UjVJA==", - "dependencies": { - "@types/retry": "*" - } - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -15909,16 +15327,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/bignumber.js": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/bignumber.js/-/bignumber.js-5.0.0.tgz", - "integrity": "sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==", - "deprecated": "This is a stub types definition for bignumber.js (https://github.com/MikeMcl/bignumber.js/). bignumber.js provides its own type definitions, so you don't need @types/bignumber.js installed!", - "optional": true, - "dependencies": { - "bignumber.js": "*" - } - }, "node_modules/@types/bn.js": { "version": "5.1.1", "license": "MIT", @@ -15955,21 +15363,6 @@ "@types/responselike": "^1.0.0" } }, - "node_modules/@types/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-of+ICnbqjmFCiixUnqRulbylyXQrPqIGf/B3Jax1wIF3DvSheysQxAWvqHhZiW3IQrycvokcLcFQlveGp+vyNg==", - "optional": true - }, - "node_modules/@types/concat-stream": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", - "integrity": "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -16268,25 +15661,6 @@ "@types/send": "*" } }, - "node_modules/@types/form-data": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", - "integrity": "sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/fs-extra": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", - "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", - "optional": true, - "dependencies": { - "@types/jsonfile": "*", - "@types/node": "*" - } - }, "node_modules/@types/geojson": { "version": "7946.0.10", "dev": true, @@ -16378,15 +15752,6 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/jsonfile": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", - "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/keyv": { "version": "3.1.4", "license": "MIT", @@ -16396,6 +15761,7 @@ }, "node_modules/@types/lodash": { "version": "4.14.194", + "dev": true, "license": "MIT" }, "node_modules/@types/lodash.flatmap": { @@ -16413,7 +15779,8 @@ "node_modules/@types/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", + "peer": true }, "node_modules/@types/mime": { "version": "1.3.5", @@ -16429,21 +15796,6 @@ "version": "1.2.2", "license": "MIT" }, - "node_modules/@types/mkdirp": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", - "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/mocha": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.4.tgz", - "integrity": "sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==", - "optional": true - }, "node_modules/@types/ms": { "version": "0.7.31", "license": "MIT" @@ -16489,16 +15841,6 @@ "version": "2.7.2", "license": "MIT" }, - "node_modules/@types/prompts": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.8.tgz", - "integrity": "sha512-fPOEzviubkEVCiLduO45h+zFHB0RZX8tFt3C783sO5cT7fUXf3EEECpD26djtYdh4Isa9Z9tasMQuZnYPtvYzw==", - "optional": true, - "dependencies": { - "@types/node": "*", - "kleur": "^3.0.3" - } - }, "node_modules/@types/prop-types": { "version": "15.7.10", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.10.tgz", @@ -16511,7 +15853,7 @@ }, "node_modules/@types/qs": { "version": "6.9.7", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@types/range-parser": { @@ -16588,6 +15930,7 @@ "version": "2.3.15", "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", + "peer": true, "dependencies": { "@types/node": "*", "safe-buffer": "~5.1.1" @@ -16596,15 +15939,8 @@ "node_modules/@types/readable-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/@types/resolve": { - "version": "0.0.8", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "peer": true }, "node_modules/@types/responselike": { "version": "1.0.0", @@ -16613,11 +15949,6 @@ "@types/node": "*" } }, - "node_modules/@types/retry": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.5.tgz", - "integrity": "sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==" - }, "node_modules/@types/secp256k1": { "version": "4.0.3", "license": "MIT", @@ -17164,15 +16495,6 @@ "node": ">=10" } }, - "node_modules/@uniswap/permit2-sdk": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@uniswap/permit2-sdk/-/permit2-sdk-1.2.0.tgz", - "integrity": "sha512-Ietv3FxN7+RCXcPSED/i/8b0a2GUZrMdyX05k3FsSztvYKyPFAMS/hBXojF0NZqYB1bHecqYc7Ej+7tV/rdYXg==", - "dependencies": { - "ethers": "^5.3.1", - "tiny-invariant": "^1.3.1" - } - }, "node_modules/@uniswap/router-sdk": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@uniswap/router-sdk/-/router-sdk-1.9.2.tgz", @@ -18891,12 +18213,6 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "optional": true - }, "node_modules/@zxing/text-encoding": { "version": "0.9.0", "license": "(Unlicense OR Apache-2.0)", @@ -18944,12 +18260,15 @@ }, "node_modules/abortcontroller-polyfill": { "version": "1.7.5", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/abstract-level": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz", "integrity": "sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==", + "peer": true, "dependencies": { "buffer": "^6.0.3", "catering": "^2.1.0", @@ -18965,6 +18284,7 @@ }, "node_modules/accepts": { "version": "1.3.8", + "devOptional": true, "license": "MIT", "dependencies": { "mime-types": "~2.1.34", @@ -19059,6 +18379,7 @@ "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "peer": true, "engines": { "node": ">=0.3.0" } @@ -19091,6 +18412,7 @@ }, "node_modules/ajv": { "version": "6.12.6", + "devOptional": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -19262,20 +18584,6 @@ "node": ">=4" } }, - "node_modules/antlr4": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz", - "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==", - "optional": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/antlr4ts": { - "version": "0.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", - "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" - }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -19381,6 +18689,7 @@ }, "node_modules/array-flatten": { "version": "1.1.1", + "devOptional": true, "license": "MIT" }, "node_modules/array-includes": { @@ -19410,14 +18719,6 @@ "node": ">=8" } }, - "node_modules/array-uniq": { - "version": "1.0.3", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.3.tgz", @@ -19551,11 +18852,12 @@ }, "node_modules/asap": { "version": "2.0.6", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/asn1": { "version": "0.2.6", + "devOptional": true, "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" @@ -19589,26 +18891,12 @@ }, "node_modules/assert-plus": { "version": "1.0.0", + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.8" } }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/ast-parents": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz", - "integrity": "sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==", - "optional": true - }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -19629,7 +18917,9 @@ }, "node_modules/async-limiter": { "version": "1.0.1", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/async-mutex": { "version": "0.2.6", @@ -19652,7 +18942,7 @@ }, "node_modules/at-least-node": { "version": "1.0.0", - "devOptional": true, + "dev": true, "license": "ISC", "engines": { "node": ">= 4.0.0" @@ -19718,6 +19008,7 @@ }, "node_modules/aws-sign2": { "version": "0.7.0", + "devOptional": true, "license": "Apache-2.0", "engines": { "node": "*" @@ -19725,6 +19016,7 @@ }, "node_modules/aws4": { "version": "1.12.0", + "devOptional": true, "license": "MIT" }, "node_modules/axe-core": { @@ -20032,6 +19324,7 @@ }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", + "devOptional": true, "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" @@ -20039,6 +19332,7 @@ }, "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { "version": "0.14.5", + "devOptional": true, "license": "Unlicense" }, "node_modules/bech32": { @@ -20078,6 +19372,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz", "integrity": "sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==", + "peer": true, "engines": { "node": ">=14.0.0" } @@ -20190,6 +19485,7 @@ }, "node_modules/bluebird": { "version": "3.7.2", + "devOptional": true, "license": "MIT" }, "node_modules/bn.js": { @@ -20199,6 +19495,8 @@ "node_modules/body-parser": { "version": "1.20.2", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -20221,6 +19519,8 @@ "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "2.0.0" } @@ -20228,6 +19528,8 @@ "node_modules/body-parser/node_modules/iconv-lite": { "version": "0.4.24", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -20237,11 +19539,15 @@ }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/body-parser/node_modules/qs": { "version": "6.11.0", "license": "BSD-3-Clause", + "optional": true, + "peer": true, "dependencies": { "side-channel": "^1.0.4" }, @@ -20323,6 +19629,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz", "integrity": "sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==", + "peer": true, "dependencies": { "abstract-level": "^1.0.2", "catering": "^2.1.1", @@ -20343,7 +19650,8 @@ "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "peer": true }, "node_modules/browserify-aes": { "version": "1.2.0", @@ -20704,6 +20012,7 @@ "version": "1.6.3", "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", + "peer": true, "engines": { "node": ">= 0.8.0" } @@ -20719,12 +20028,14 @@ }, "node_modules/caseless": { "version": "0.12.0", + "devOptional": true, "license": "Apache-2.0" }, "node_modules/catering": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", + "peer": true, "engines": { "node": ">=6" } @@ -20733,6 +20044,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "peer": true, "dependencies": { "nofilter": "^3.1.0" }, @@ -20748,24 +20060,6 @@ "cborg": "cli.js" } }, - "node_modules/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", - "optional": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -20846,18 +20140,6 @@ "node": "*" } }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "optional": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/check-more-types": { "version": "2.24.0", "dev": true, @@ -20964,7 +20246,9 @@ }, "node_modules/class-is": { "version": "1.1.0", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/class-variance-authority": { "version": "0.6.1", @@ -20982,6 +20266,7 @@ "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.3.0.tgz", "integrity": "sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg==", "hasInstallScript": true, + "peer": true, "dependencies": { "abstract-level": "^1.0.2", "catering": "^2.1.0", @@ -21330,15 +20615,6 @@ "dev": true, "license": "MIT" }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "license": "MIT", @@ -21352,7 +20628,8 @@ "node_modules/command-exists": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "peer": true }, "node_modules/command-line-args": { "version": "5.2.1", @@ -21466,57 +20743,6 @@ "version": "0.0.1", "license": "MIT" }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "optional": true, - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/configstore": { "version": "5.0.1", "license": "BSD-2-Clause", @@ -21558,6 +20784,8 @@ "node_modules/content-hash": { "version": "2.5.2", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "cids": "^0.7.1", "multicodec": "^0.5.5", @@ -21581,6 +20809,8 @@ } ], "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -21589,6 +20819,8 @@ "node_modules/content-hash/node_modules/cids": { "version": "0.7.5", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "buffer": "^5.5.0", "class-is": "^1.1.0", @@ -21604,6 +20836,8 @@ "node_modules/content-hash/node_modules/cids/node_modules/multicodec": { "version": "1.0.4", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "buffer": "^5.6.0", "varint": "^5.0.0" @@ -21612,6 +20846,8 @@ "node_modules/content-hash/node_modules/multibase": { "version": "0.6.1", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "base-x": "^3.0.8", "buffer": "^5.5.0" @@ -21620,6 +20856,8 @@ "node_modules/content-hash/node_modules/multicodec": { "version": "0.5.7", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "varint": "^5.0.0" } @@ -21627,6 +20865,8 @@ "node_modules/content-hash/node_modules/multihashes": { "version": "0.4.21", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "buffer": "^5.5.0", "multibase": "^0.7.0", @@ -21636,6 +20876,8 @@ "node_modules/content-hash/node_modules/multihashes/node_modules/multibase": { "version": "0.7.0", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "base-x": "^3.0.8", "buffer": "^5.5.0" @@ -21643,10 +20885,13 @@ }, "node_modules/content-hash/node_modules/varint": { "version": "5.0.2", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/content-type": { "version": "1.0.5", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -21660,6 +20905,7 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "peer": true, "engines": { "node": ">= 0.6" } @@ -21671,6 +20917,7 @@ }, "node_modules/cookie-signature": { "version": "1.0.6", + "devOptional": true, "license": "MIT" }, "node_modules/cookiejar": { @@ -21735,11 +20982,14 @@ }, "node_modules/core-util-is": { "version": "1.0.2", + "devOptional": true, "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "object-assign": "^4", "vary": "^1" @@ -21872,7 +21122,8 @@ "node_modules/create-require": { "version": "1.1.1", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/cross-fetch": { "version": "3.1.6", @@ -22954,6 +22205,7 @@ }, "node_modules/dashdash": { "version": "1.14.1", + "devOptional": true, "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" @@ -23173,18 +22425,6 @@ } } }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "optional": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "license": "MIT", @@ -23358,6 +22598,7 @@ }, "node_modules/destroy": { "version": "1.2.0", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.8", @@ -23449,6 +22690,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "peer": true, "engines": { "node": ">=0.3.1" } @@ -24041,6 +23283,7 @@ }, "node_modules/ecc-jsbn": { "version": "0.1.2", + "devOptional": true, "license": "MIT", "dependencies": { "jsbn": "~0.1.0", @@ -24049,6 +23292,7 @@ }, "node_modules/ee-first": { "version": "1.1.1", + "devOptional": true, "license": "MIT" }, "node_modules/eip1193-provider": { @@ -24157,11 +23401,6 @@ "node": ">= 4" } }, - "node_modules/emotion-theming": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/emotion-theming/-/emotion-theming-11.0.0.tgz", - "integrity": "sha512-OhYpCGBjaLcD9c4ptwCr9SxHjfRTDqeqdzMobusJ+a/drlfnJ3AT9gmGKIhNHiXtr6626h6fsvLY22Or9CxUqw==" - }, "node_modules/enc-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/enc-utils/-/enc-utils-3.0.0.tgz", @@ -24177,6 +23416,7 @@ }, "node_modules/encodeurl": { "version": "1.0.2", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -24271,6 +23511,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "peer": true, "engines": { "node": ">=6" } @@ -24480,7 +23721,9 @@ }, "node_modules/es6-promise": { "version": "4.2.8", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/es6-symbol": { "version": "3.1.3", @@ -24506,6 +23749,7 @@ }, "node_modules/escape-html": { "version": "1.0.3", + "devOptional": true, "license": "MIT" }, "node_modules/escape-string-regexp": { @@ -25248,6 +24492,7 @@ }, "node_modules/etag": { "version": "1.8.1", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -25349,6 +24594,8 @@ "node_modules/eth-ens-namehash": { "version": "2.0.8", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "idna-uts46-hx": "^2.3.1", "js-sha3": "^0.5.7" @@ -25356,163 +24603,9 @@ }, "node_modules/eth-ens-namehash/node_modules/js-sha3": { "version": "0.5.7", - "license": "MIT" - }, - "node_modules/eth-gas-reporter": { - "version": "0.2.27", - "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz", - "integrity": "sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==", - "optional": true, - "dependencies": { - "@solidity-parser/parser": "^0.14.0", - "axios": "^1.5.1", - "cli-table3": "^0.5.0", - "colors": "1.4.0", - "ethereum-cryptography": "^1.0.3", - "ethers": "^5.7.2", - "fs-readdir-recursive": "^1.1.0", - "lodash": "^4.17.14", - "markdown-table": "^1.1.3", - "mocha": "^10.2.0", - "req-cwd": "^2.0.0", - "sha1": "^1.1.1", - "sync-request": "^6.0.0" - }, - "peerDependencies": { - "@codechecks/client": "^0.1.0" - }, - "peerDependenciesMeta": { - "@codechecks/client": { - "optional": true - } - } - }, - "node_modules/eth-gas-reporter/node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "optional": true - }, - "node_modules/eth-gas-reporter/node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "optional": true, - "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "optional": true, - "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", - "optional": true, - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/cli-table3": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", - "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", - "optional": true, - "dependencies": { - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "colors": "^1.1.2" - } - }, - "node_modules/eth-gas-reporter/node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "optional": true, - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" - } - }, - "node_modules/eth-gas-reporter/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "optional": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "license": "MIT", "optional": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } + "peer": true }, "node_modules/eth-json-rpc-filters": { "version": "6.0.0", @@ -25541,6 +24634,8 @@ "node_modules/eth-lib": { "version": "0.1.29", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bn.js": "^4.11.6", "elliptic": "^6.4.0", @@ -25552,15 +24647,21 @@ }, "node_modules/eth-lib/node_modules/bn.js": { "version": "4.12.0", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/eth-lib/node_modules/safe-buffer": { "version": "5.1.2", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/eth-lib/node_modules/ws": { "version": "3.3.3", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "async-limiter": "~1.0.0", "safe-buffer": "~5.1.0", @@ -25620,6 +24721,7 @@ "version": "0.6.8", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "peer": true, "dependencies": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -25628,12 +24730,14 @@ "node_modules/ethereumjs-abi/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "peer": true }, "node_modules/ethereumjs-util": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "peer": true, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -25648,6 +24752,7 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "peer": true, "dependencies": { "@types/node": "*" } @@ -25655,12 +24760,14 @@ "node_modules/ethereumjs-util/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "peer": true }, "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -25970,6 +25077,7 @@ "node_modules/ethjs-util": { "version": "0.1.6", "license": "MIT", + "peer": true, "dependencies": { "is-hex-prefixed": "1.0.0", "strip-hex-prefix": "1.0.0" @@ -26133,6 +25241,7 @@ }, "node_modules/express": { "version": "4.18.2", + "devOptional": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -26173,6 +25282,7 @@ }, "node_modules/express/node_modules/body-parser": { "version": "1.20.1", + "devOptional": true, "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -26195,6 +25305,7 @@ }, "node_modules/express/node_modules/content-disposition": { "version": "0.5.4", + "devOptional": true, "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -26205,6 +25316,7 @@ }, "node_modules/express/node_modules/cookie": { "version": "0.5.0", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -26212,6 +25324,7 @@ }, "node_modules/express/node_modules/debug": { "version": "2.6.9", + "devOptional": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -26219,6 +25332,7 @@ }, "node_modules/express/node_modules/iconv-lite": { "version": "0.4.24", + "devOptional": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -26229,14 +25343,17 @@ }, "node_modules/express/node_modules/ms": { "version": "2.0.0", + "devOptional": true, "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { "version": "0.1.7", + "devOptional": true, "license": "MIT" }, "node_modules/express/node_modules/qs": { "version": "6.11.0", + "devOptional": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" @@ -26250,6 +25367,7 @@ }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -26257,6 +25375,7 @@ }, "node_modules/express/node_modules/raw-body": { "version": "2.5.1", + "devOptional": true, "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -26281,6 +25400,7 @@ }, "node_modules/extend": { "version": "3.0.2", + "devOptional": true, "license": "MIT" }, "node_modules/extract-zip": { @@ -26304,6 +25424,7 @@ }, "node_modules/extsprintf": { "version": "1.3.0", + "devOptional": true, "engines": [ "node >=0.6.0" ], @@ -26320,7 +25441,7 @@ }, "node_modules/fast-diff": { "version": "1.2.0", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/fast-fifo": { @@ -26559,6 +25680,7 @@ }, "node_modules/finalhandler": { "version": "1.2.0", + "devOptional": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -26575,6 +25697,7 @@ }, "node_modules/finalhandler/node_modules/debug": { "version": "2.6.9", + "devOptional": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -26582,6 +25705,7 @@ }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", + "devOptional": true, "license": "MIT" }, "node_modules/find-cache-dir": { @@ -26614,7 +25738,8 @@ "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "peer": true }, "node_modules/find-up": { "version": "2.1.0", @@ -26626,19 +25751,11 @@ "node": ">=4" } }, - "node_modules/find-yarn-workspace-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", - "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", - "optional": true, - "dependencies": { - "micromatch": "^4.0.2" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "peer": true, "bin": { "flat": "cli.js" } @@ -26688,6 +25805,7 @@ }, "node_modules/forever-agent": { "version": "0.6.1", + "devOptional": true, "license": "Apache-2.0", "engines": { "node": "*" @@ -26847,6 +25965,7 @@ }, "node_modules/forwarded": { "version": "0.2.0", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -26855,7 +25974,8 @@ "node_modules/fp-ts": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==" + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", + "peer": true }, "node_modules/fraction.js": { "version": "4.3.7", @@ -26913,6 +26033,7 @@ }, "node_modules/fresh": { "version": "0.5.2", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -26923,32 +26044,12 @@ "dev": true, "license": "MIT" }, - "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "optional": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/fs-monkey": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", "dev": true }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "optional": true - }, "node_modules/fs.realpath": { "version": "1.0.0", "license": "ISC" @@ -27023,15 +26124,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "optional": true, - "engines": { - "node": "*" - } - }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -27081,15 +26173,6 @@ "node": ">=8.0.0" } }, - "node_modules/get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/get-port-please": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.1.2.tgz", @@ -27142,6 +26225,7 @@ }, "node_modules/getpass": { "version": "0.1.7", + "devOptional": true, "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" @@ -27434,6 +26518,8 @@ "node_modules/har-schema": { "version": "2.0.0", "license": "ISC", + "optional": true, + "peer": true, "engines": { "node": ">=4" } @@ -27441,6 +26527,8 @@ "node_modules/har-validator": { "version": "5.1.5", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -27460,6 +26548,7 @@ "version": "2.19.1", "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.19.1.tgz", "integrity": "sha512-bsWa63g1GB78ZyMN08WLhFElLPA+J+pShuKD1BFO2+88g3l+BL3R07vj9deIi9dMbssxgE714Gof1dBEDGqnCw==", + "peer": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", @@ -27526,43 +26615,6 @@ } } }, - "node_modules/hardhat-gas-reporter": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz", - "integrity": "sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==", - "optional": true, - "dependencies": { - "array-uniq": "1.0.3", - "eth-gas-reporter": "^0.2.25", - "sha1": "^1.1.1" - }, - "peerDependencies": { - "hardhat": "^2.0.2" - } - }, - "node_modules/hardhat-spdx-license-identifier": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hardhat-spdx-license-identifier/-/hardhat-spdx-license-identifier-2.2.0.tgz", - "integrity": "sha512-audxGrmLL/TGr0Ef/p3tEH8frtygCb+9RWbMQtd1w2p5V6HzQsSJUlAJFywZZ/igQ6B1qAKqAbeLePNclEe2Qw==", - "optional": true, - "peerDependencies": { - "hardhat": "^2.0.0" - } - }, - "node_modules/hardhat-tracer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/hardhat-tracer/-/hardhat-tracer-1.3.0.tgz", - "integrity": "sha512-mUYuRJWlxCwY4R2urCpNM4ecVSq/iMLiVP9YZKlfXyv4R8T+4HAcTfumilUOXHGe6wHI+8Ki2EaTon3KgzATDA==", - "optional": true, - "dependencies": { - "ethers": "^5.6.1" - }, - "peerDependencies": { - "chalk": "4.x", - "ethers": "5.x", - "hardhat": "2.x" - } - }, "node_modules/hardhat-watcher": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hardhat-watcher/-/hardhat-watcher-2.5.0.tgz", @@ -27578,6 +26630,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", + "peer": true, "dependencies": { "ethereumjs-abi": "^0.6.8", "ethereumjs-util": "^6.2.1", @@ -27598,7 +26651,8 @@ "type": "individual", "url": "https://paulmillr.com/funding/" } - ] + ], + "peer": true }, "node_modules/hardhat/node_modules/@scure/bip32": { "version": "1.1.5", @@ -27610,6 +26664,7 @@ "url": "https://paulmillr.com/funding/" } ], + "peer": true, "dependencies": { "@noble/hashes": "~1.2.0", "@noble/secp256k1": "~1.7.0", @@ -27626,6 +26681,7 @@ "url": "https://paulmillr.com/funding/" } ], + "peer": true, "dependencies": { "@noble/hashes": "~1.2.0", "@scure/base": "~1.1.0" @@ -27635,6 +26691,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "peer": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -27648,6 +26705,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "peer": true, "engines": { "node": ">=0.8.0" } @@ -27656,6 +26714,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "peer": true, "dependencies": { "@noble/hashes": "1.2.0", "@noble/secp256k1": "1.7.1", @@ -27667,6 +26726,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -27680,6 +26740,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -27688,6 +26749,7 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "peer": true, "dependencies": { "path-parse": "^1.0.6" }, @@ -27699,6 +26761,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "peer": true, "engines": { "node": ">= 4.0.0" } @@ -28060,21 +27123,6 @@ "entities": "^2.0.0" } }, - "node_modules/http-basic": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", - "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", - "optional": true, - "dependencies": { - "caseless": "^0.12.0", - "concat-stream": "^1.6.2", - "http-response-object": "^3.0.1", - "parse-cache-control": "^1.0.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/http-cache-semantics": { "version": "4.1.1", "license": "BSD-2-Clause" @@ -28173,21 +27221,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-response-object": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", - "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", - "optional": true, - "dependencies": { - "@types/node": "^10.0.3" - } - }, - "node_modules/http-response-object/node_modules/@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", - "optional": true - }, "node_modules/http-shutdown": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/http-shutdown/-/http-shutdown-1.2.2.tgz", @@ -28354,6 +27387,8 @@ "node_modules/idna-uts46-hx": { "version": "2.3.1", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "punycode": "2.1.0" }, @@ -28364,6 +27399,8 @@ "node_modules/idna-uts46-hx/node_modules/punycode": { "version": "2.1.0", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -28600,6 +27637,7 @@ "version": "1.10.4", "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", + "peer": true, "dependencies": { "fp-ts": "^1.0.0" } @@ -28613,6 +27651,7 @@ }, "node_modules/ipaddr.js": { "version": "1.9.1", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.10" @@ -29277,6 +28316,7 @@ "url": "https://feross.org/support" } ], + "peer": true, "engines": { "node": ">=4" } @@ -29820,7 +28860,7 @@ }, "node_modules/isarray": { "version": "0.0.1", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/isexe": { @@ -29861,15 +28901,6 @@ "node": ">=0.10.0" } }, - "node_modules/isomorphic-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", - "dependencies": { - "node-fetch": "^2.6.1", - "whatwg-fetch": "^3.4.1" - } - }, "node_modules/isomorphic-unfetch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", @@ -29889,6 +28920,7 @@ }, "node_modules/isstream": { "version": "0.1.2", + "devOptional": true, "license": "MIT" }, "node_modules/istanbul-lib-coverage": { @@ -32698,6 +31730,7 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" @@ -32728,6 +31761,7 @@ }, "node_modules/jsbn": { "version": "0.1.1", + "devOptional": true, "license": "MIT" }, "node_modules/jsdom": { @@ -32879,10 +31913,12 @@ }, "node_modules/json-schema": { "version": "0.4.0", + "devOptional": true, "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "0.4.1", + "devOptional": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -32892,6 +31928,7 @@ }, "node_modules/json-stringify-safe": { "version": "5.0.1", + "devOptional": true, "license": "ISC" }, "node_modules/json-text-sequence": { @@ -33053,12 +32090,6 @@ "node": ">=4.0" } }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "optional": true - }, "node_modules/jwt-decode": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", @@ -33099,22 +32130,14 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", + "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.9" } }, - "node_modules/klaw-sync": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.11" - } - }, "node_modules/kleur": { "version": "3.0.3", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -33179,6 +32202,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz", "integrity": "sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==", + "peer": true, "dependencies": { "browser-level": "^1.0.1", "classic-level": "^1.2.0" @@ -33195,6 +32219,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz", "integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==", + "peer": true, "engines": { "node": ">=12" } @@ -33203,6 +32228,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", + "peer": true, "dependencies": { "buffer": "^6.0.3", "module-error": "^1.0.1" @@ -33796,15 +32822,6 @@ "node": ">=0.10.0" } }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "optional": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -33824,7 +32841,8 @@ "node_modules/lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "peer": true }, "node_modules/lru-cache": { "version": "5.1.1", @@ -33886,7 +32904,8 @@ "node_modules/make-error": { "version": "1.3.6", "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/makeerror": { "version": "1.0.12", @@ -33910,16 +32929,11 @@ "version": "0.1.0", "dev": true }, - "node_modules/markdown-table": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "optional": true - }, "node_modules/mcl-wasm": { "version": "0.7.9", "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", "integrity": "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==", + "peer": true, "engines": { "node": ">=8.9.0" } @@ -33940,6 +32954,7 @@ }, "node_modules/media-typer": { "version": "0.3.0", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -33966,6 +32981,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz", "integrity": "sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==", + "peer": true, "dependencies": { "abstract-level": "^1.0.0", "functional-red-black-tree": "^1.0.1", @@ -33979,6 +32995,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "peer": true, "engines": { "node": ">= 0.10.0" } @@ -34160,6 +33177,7 @@ }, "node_modules/merge-descriptors": { "version": "1.0.1", + "devOptional": true, "license": "MIT" }, "node_modules/merge-options": { @@ -34201,6 +33219,7 @@ }, "node_modules/methods": { "version": "1.1.2", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -34238,6 +33257,7 @@ }, "node_modules/mime": { "version": "1.6.0", + "devOptional": true, "license": "MIT", "bin": { "mime": "cli.js" @@ -34415,6 +33435,7 @@ }, "node_modules/mkdirp": { "version": "0.5.6", + "devOptional": true, "license": "MIT", "dependencies": { "minimist": "^1.2.6" @@ -34426,6 +33447,8 @@ "node_modules/mkdirp-promise": { "version": "5.0.1", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "mkdirp": "*" }, @@ -34448,6 +33471,7 @@ "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", + "peer": true, "dependencies": { "obliterator": "^2.0.0" } @@ -34456,6 +33480,7 @@ "version": "10.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "peer": true, "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -34495,6 +33520,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "peer": true, "engines": { "node": ">=6" } @@ -34502,12 +33528,14 @@ "node_modules/mocha/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "peer": true }, "node_modules/mocha/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -34516,6 +33544,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -34531,6 +33560,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "peer": true, "engines": { "node": ">=8" } @@ -34539,6 +33569,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "peer": true, "dependencies": { "argparse": "^2.0.1" }, @@ -34550,6 +33581,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -34564,6 +33596,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "peer": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -34574,12 +33607,14 @@ "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "peer": true }, "node_modules/mocha/node_modules/nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "peer": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -34591,6 +33626,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -34605,6 +33641,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -34619,6 +33656,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "peer": true, "engines": { "node": ">=8" } @@ -34627,6 +33665,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -34641,30 +33680,26 @@ "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "peer": true, "engines": { "node": ">=10" } }, "node_modules/mock-fs": { "version": "4.14.0", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/module-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz", "integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==", + "peer": true, "engines": { "node": ">=10" } }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, "node_modules/motion": { "version": "10.16.2", "resolved": "https://registry.npmjs.org/motion/-/motion-10.16.2.tgz", @@ -34868,7 +33903,9 @@ }, "node_modules/nano-json-stream-parser": { "version": "0.1.2", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/nanoid": { "version": "3.3.7", @@ -34890,7 +33927,8 @@ "node_modules/napi-macros": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==" + "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", + "peer": true }, "node_modules/native-abort-controller": { "version": "1.0.4", @@ -34917,6 +33955,7 @@ }, "node_modules/negotiator": { "version": "0.6.3", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -34944,28 +33983,6 @@ "version": "1.0.5", "license": "MIT" }, - "node_modules/nise": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.5.tgz", - "integrity": "sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw==", - "optional": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "optional": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -37927,6 +36944,8 @@ "node_modules/oauth-sign": { "version": "0.9.0", "license": "Apache-2.0", + "optional": true, + "peer": true, "engines": { "node": "*" } @@ -38095,7 +37114,8 @@ "node_modules/obliterator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", + "peer": true }, "node_modules/oboe": { "version": "2.1.5", @@ -38143,6 +37163,7 @@ }, "node_modules/on-finished": { "version": "2.4.1", + "devOptional": true, "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -38227,6 +37248,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -38518,12 +37540,6 @@ "safe-buffer": "^5.1.1" } }, - "node_modules/parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", - "optional": true - }, "node_modules/parse-duration": { "version": "1.0.3", "license": "MIT" @@ -38556,6 +37572,7 @@ }, "node_modules/parseurl": { "version": "1.3.3", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -38571,156 +37588,6 @@ "tslib": "^2.0.3" } }, - "node_modules/patch-package": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-7.0.2.tgz", - "integrity": "sha512-PMYfL8LXxGIRmxXLqlEaBxzKPu7/SdP13ld6GSfAUJUZRmBDPp8chZs0dpzaAFn9TSPnFiMwkC6PJt6pBiAl8Q==", - "optional": true, - "dependencies": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^4.1.2", - "ci-info": "^3.7.0", - "cross-spawn": "^7.0.3", - "find-yarn-workspace-root": "^2.0.0", - "fs-extra": "^9.0.0", - "klaw-sync": "^6.0.0", - "minimist": "^1.2.6", - "open": "^7.4.2", - "rimraf": "^2.6.3", - "semver": "^7.5.3", - "slash": "^2.0.0", - "tmp": "^0.0.33", - "yaml": "^2.2.2" - }, - "bin": { - "patch-package": "index.js" - }, - "engines": { - "node": ">=14", - "npm": ">5" - } - }, - "node_modules/patch-package/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/patch-package/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/patch-package/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/patch-package/node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "optional": true, - "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/patch-package/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "optional": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/patch-package/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/patch-package/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/patch-package/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "optional": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/patch-package/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - }, - "node_modules/patch-package/node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", - "optional": true, - "engines": { - "node": ">= 14" - } - }, "node_modules/path": { "version": "0.12.7", "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", @@ -38757,7 +37624,7 @@ }, "node_modules/path-to-regexp": { "version": "1.8.0", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "isarray": "0.0.1" @@ -38788,15 +37655,6 @@ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "optional": true, - "engines": { - "node": "*" - } - }, "node_modules/pause-stream": { "version": "0.0.11", "dev": true, @@ -38829,6 +37687,7 @@ }, "node_modules/performance-now": { "version": "2.1.0", + "devOptional": true, "license": "MIT" }, "node_modules/pg": { @@ -39138,15 +37997,6 @@ "node": ">=6" } }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/pngjs": { "version": "5.0.0", "license": "MIT", @@ -40573,7 +39423,7 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/process-warning": { @@ -40590,7 +39440,7 @@ }, "node_modules/promise": { "version": "8.3.0", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "asap": "~2.0.6" @@ -40598,7 +39448,7 @@ }, "node_modules/prompts": { "version": "2.4.2", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "kleur": "^3.0.3", @@ -40665,6 +39515,7 @@ }, "node_modules/proxy-addr": { "version": "2.0.7", + "devOptional": true, "license": "MIT", "dependencies": { "forwarded": "0.2.0", @@ -40699,6 +39550,7 @@ }, "node_modules/psl": { "version": "1.9.0", + "devOptional": true, "license": "MIT" }, "node_modules/public-encrypt": { @@ -40729,6 +39581,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "devOptional": true, "engines": { "node": ">=6" } @@ -40784,14 +39637,6 @@ "node": ">=10.13.0" } }, - "node_modules/qrcode.react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz", - "integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/qrcode/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -40935,7 +39780,7 @@ }, "node_modules/qs": { "version": "6.11.2", - "devOptional": true, + "dev": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" @@ -41050,6 +39895,7 @@ "node_modules/raw-body": { "version": "2.5.2", "license": "MIT", + "peer": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -41063,6 +39909,7 @@ "node_modules/raw-body/node_modules/iconv-lite": { "version": "0.4.24", "license": "MIT", + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -41319,17 +40166,6 @@ "react": "^18.2.0" } }, - "node_modules/react-error-boundary": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.11.tgz", - "integrity": "sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "peerDependencies": { - "react": ">=16.13.1" - } - }, "node_modules/react-error-overlay": { "version": "6.0.11", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", @@ -41499,18 +40335,6 @@ "p-defer": "^3.0.0" } }, - "node_modules/react-number-format": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.3.1.tgz", - "integrity": "sha512-qpYcQLauIeEhCZUZY9jXZnnroOtdy3jYaS1zQ3M1Sr6r/KMOBEIGNIb7eKT19g2N1wbYgFgvDzs19hw5TrB8XQ==", - "dependencies": { - "prop-types": "^15.7.2" - }, - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-redux": { "version": "7.2.9", "dev": true, @@ -43142,15 +41966,6 @@ } } }, - "node_modules/react-text-overflow": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/react-text-overflow/-/react-text-overflow-1.0.2.tgz", - "integrity": "sha512-NGCcGupT3yZVpPRcOHghBIFMgctLVGL6z1SXOoEoztMt9DHIHQzAy/gKsxh93jDdfmvP9VzS7ibixyliZexI7g==", - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - } - }, "node_modules/react-tradingview-embed": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/react-tradingview-embed/-/react-tradingview-embed-3.0.6.tgz", @@ -43515,42 +42330,11 @@ "strip-ansi": "^6.0.1" } }, - "node_modules/req-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", - "integrity": "sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==", - "optional": true, - "dependencies": { - "req-from": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/req-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", - "integrity": "sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==", - "optional": true, - "dependencies": { - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/req-from/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/request": { "version": "2.88.2", "license": "Apache-2.0", + "optional": true, + "peer": true, "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -43588,6 +42372,8 @@ "node_modules/request/node_modules/form-data": { "version": "2.3.3", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -43600,6 +42386,8 @@ "node_modules/request/node_modules/http-signature": { "version": "1.2.0", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -43613,6 +42401,8 @@ "node_modules/request/node_modules/jsprim": { "version": "1.4.2", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -43626,6 +42416,8 @@ "node_modules/request/node_modules/qs": { "version": "6.5.3", "license": "BSD-3-Clause", + "optional": true, + "peer": true, "engines": { "node": ">=0.6" } @@ -43633,6 +42425,8 @@ "node_modules/request/node_modules/uuid": { "version": "3.4.0", "license": "MIT", + "optional": true, + "peer": true, "bin": { "uuid": "bin/uuid" } @@ -44045,6 +42839,7 @@ "url": "https://feross.org/support" } ], + "peer": true, "dependencies": { "queue-microtask": "^1.2.2" } @@ -44052,7 +42847,8 @@ "node_modules/rustbn.js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==" + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", + "peer": true }, "node_modules/rw": { "version": "1.3.3", @@ -44427,6 +43223,7 @@ }, "node_modules/send": { "version": "0.18.0", + "devOptional": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -44449,6 +43246,7 @@ }, "node_modules/send/node_modules/debug": { "version": "2.6.9", + "devOptional": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -44456,14 +43254,17 @@ }, "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", + "devOptional": true, "license": "MIT" }, "node_modules/send/node_modules/ms": { "version": "2.1.3", + "devOptional": true, "license": "MIT" }, "node_modules/send/node_modules/range-parser": { "version": "1.2.1", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -44557,6 +43358,7 @@ }, "node_modules/serve-static": { "version": "1.15.0", + "devOptional": true, "license": "MIT", "dependencies": { "encodeurl": "~1.0.2", @@ -44571,6 +43373,8 @@ "node_modules/servify": { "version": "0.1.12", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "body-parser": "^1.16.0", "cors": "^2.8.1", @@ -44760,7 +43564,7 @@ }, "node_modules/sisteransi": { "version": "1.0.5", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/slash": { @@ -44866,6 +43670,7 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", + "peer": true, "dependencies": { "command-exists": "^1.2.8", "commander": "3.0.2", @@ -44887,12 +43692,14 @@ "node_modules/solc/node_modules/commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "peer": true }, "node_modules/solc/node_modules/fs-extra": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", + "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^2.1.0", @@ -44905,6 +43712,7 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -44913,6 +43721,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -44924,6 +43733,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "peer": true, "bin": { "semver": "bin/semver" } @@ -44932,6 +43742,7 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "peer": true, "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -44939,187 +43750,6 @@ "node": ">=0.6.0" } }, - "node_modules/solhint": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-3.6.2.tgz", - "integrity": "sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==", - "optional": true, - "dependencies": { - "@solidity-parser/parser": "^0.16.0", - "ajv": "^6.12.6", - "antlr4": "^4.11.0", - "ast-parents": "^0.0.1", - "chalk": "^4.1.2", - "commander": "^10.0.0", - "cosmiconfig": "^8.0.0", - "fast-diff": "^1.2.0", - "glob": "^8.0.3", - "ignore": "^5.2.4", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "pluralize": "^8.0.0", - "semver": "^7.5.2", - "strip-ansi": "^6.0.1", - "table": "^6.8.1", - "text-table": "^0.2.0" - }, - "bin": { - "solhint": "solhint.js" - }, - "optionalDependencies": { - "prettier": "^2.8.3" - } - }, - "node_modules/solhint/node_modules/@solidity-parser/parser": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.2.tgz", - "integrity": "sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==", - "optional": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "node_modules/solhint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "optional": true - }, - "node_modules/solhint/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "optional": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/solhint/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/solhint/node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "optional": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/solhint/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "optional": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/solhint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "optional": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/solhint/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/solhint/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "optional": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/solhint/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "optional": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/solhint/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/solhint/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - }, "node_modules/solidity-ast": { "version": "0.4.55", "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.55.tgz", @@ -45128,11 +43758,6 @@ "array.prototype.findlast": "^1.2.2" } }, - "node_modules/solidity-comments-extractor": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", - "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==" - }, "node_modules/sonic-boom": { "version": "2.8.0", "license": "MIT", @@ -45149,6 +43774,7 @@ "node_modules/source-map": { "version": "0.5.7", "license": "BSD-3-Clause", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -45332,6 +43958,7 @@ }, "node_modules/sshpk": { "version": "1.17.0", + "devOptional": true, "license": "MIT", "dependencies": { "asn1": "~0.2.3", @@ -45355,6 +43982,7 @@ }, "node_modules/sshpk/node_modules/tweetnacl": { "version": "0.14.5", + "devOptional": true, "license": "Unlicense" }, "node_modules/stable": { @@ -45390,6 +44018,7 @@ "version": "0.1.10", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "peer": true, "dependencies": { "type-fest": "^0.7.1" }, @@ -45401,6 +44030,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "peer": true, "engines": { "node": ">=8" } @@ -45802,7 +44432,8 @@ "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "peer": true }, "node_modules/sucrase": { "version": "3.34.0", @@ -46106,6 +44737,8 @@ "node_modules/swarm-js": { "version": "0.1.42", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bluebird": "^3.5.0", "buffer": "^5.0.5", @@ -46137,6 +44770,8 @@ } ], "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -46144,11 +44779,15 @@ }, "node_modules/swarm-js/node_modules/chownr": { "version": "1.1.4", - "license": "ISC" + "license": "ISC", + "optional": true, + "peer": true }, "node_modules/swarm-js/node_modules/fs-extra": { "version": "4.0.3", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -46158,6 +44797,8 @@ "node_modules/swarm-js/node_modules/fs-minipass": { "version": "1.2.7", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "minipass": "^2.6.0" } @@ -46165,6 +44806,8 @@ "node_modules/swarm-js/node_modules/jsonfile": { "version": "4.0.0", "license": "MIT", + "optional": true, + "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -46172,6 +44815,8 @@ "node_modules/swarm-js/node_modules/minipass": { "version": "2.9.0", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -46180,6 +44825,8 @@ "node_modules/swarm-js/node_modules/minizlib": { "version": "1.3.3", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "minipass": "^2.9.0" } @@ -46187,6 +44834,8 @@ "node_modules/swarm-js/node_modules/tar": { "version": "4.4.19", "license": "ISC", + "optional": true, + "peer": true, "dependencies": { "chownr": "^1.1.4", "fs-minipass": "^1.2.7", @@ -46203,6 +44852,8 @@ "node_modules/swarm-js/node_modules/universalify": { "version": "0.1.2", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 4.0.0" } @@ -46225,29 +44876,6 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, - "node_modules/sync-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", - "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", - "optional": true, - "dependencies": { - "http-response-object": "^3.0.1", - "sync-rpc": "^1.2.1", - "then-request": "^6.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/sync-rpc": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", - "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", - "optional": true, - "dependencies": { - "get-port": "^3.1.0" - } - }, "node_modules/system-architecture": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/system-architecture/-/system-architecture-0.1.0.tgz", @@ -46652,51 +45280,9 @@ }, "node_modules/text-table": { "version": "0.2.0", - "devOptional": true, + "dev": true, "license": "MIT" }, - "node_modules/then-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", - "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", - "optional": true, - "dependencies": { - "@types/concat-stream": "^1.6.0", - "@types/form-data": "0.0.33", - "@types/node": "^8.0.0", - "@types/qs": "^6.2.31", - "caseless": "~0.12.0", - "concat-stream": "^1.6.0", - "form-data": "^2.2.0", - "http-basic": "^8.1.1", - "http-response-object": "^3.0.1", - "promise": "^8.0.0", - "qs": "^6.4.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/then-request/node_modules/@types/node": { - "version": "8.10.66", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", - "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", - "optional": true - }, - "node_modules/then-request/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "optional": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -46865,6 +45451,8 @@ "node_modules/tough-cookie": { "version": "2.5.0", "license": "BSD-3-Clause", + "optional": true, + "peer": true, "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" @@ -46944,70 +45532,6 @@ "typescript": ">=4.1.0" } }, - "node_modules/ts-generator": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ts-generator/-/ts-generator-0.1.1.tgz", - "integrity": "sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ==", - "optional": true, - "dependencies": { - "@types/mkdirp": "^0.5.2", - "@types/prettier": "^2.1.1", - "@types/resolve": "^0.0.8", - "chalk": "^2.4.1", - "glob": "^7.1.2", - "mkdirp": "^0.5.1", - "prettier": "^2.1.2", - "resolve": "^1.8.1", - "ts-essentials": "^1.0.0" - }, - "bin": { - "ts-generator": "dist/cli/run.js" - } - }, - "node_modules/ts-generator/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "optional": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ts-generator/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "optional": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ts-generator/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "optional": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/ts-generator/node_modules/ts-essentials": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-1.0.4.tgz", - "integrity": "sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==", - "optional": true - }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -47018,6 +45542,7 @@ "version": "10.9.1", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -47060,6 +45585,7 @@ "version": "8.2.0", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=0.4.0" } @@ -47067,12 +45593,14 @@ "node_modules/ts-node/node_modules/arg": { "version": "4.1.3", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", "license": "BSD-3-Clause", "optional": true, + "peer": true, "engines": { "node": ">=0.3.1" } @@ -47118,7 +45646,8 @@ "node_modules/tsort": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==" + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", + "peer": true }, "node_modules/tsutils": { "version": "3.21.0", @@ -47141,6 +45670,7 @@ }, "node_modules/tunnel-agent": { "version": "0.6.0", + "devOptional": true, "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -47151,11 +45681,13 @@ }, "node_modules/tweetnacl": { "version": "1.0.3", - "license": "Unlicense" + "license": "Unlicense", + "peer": true }, "node_modules/tweetnacl-util": { "version": "0.15.1", - "license": "Unlicense" + "license": "Unlicense", + "peer": true }, "node_modules/type": { "version": "1.2.0", @@ -47181,6 +45713,7 @@ }, "node_modules/type-is": { "version": "1.6.18", + "devOptional": true, "license": "MIT", "dependencies": { "media-typer": "0.3.0", @@ -47363,11 +45896,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "license": "MIT", - "optional": true - }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "license": "MIT", @@ -47432,7 +45960,9 @@ }, "node_modules/ultron": { "version": "1.1.1", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/unbox-primitive": { "version": "1.0.2", @@ -47456,6 +45986,7 @@ "version": "5.27.2", "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", + "peer": true, "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -47463,12 +45994,6 @@ "node": ">=14.0" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "optional": true - }, "node_modules/unenv": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/unenv/-/unenv-1.9.0.tgz", @@ -48039,6 +46564,7 @@ }, "node_modules/utils-merge": { "version": "1.0.1", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -48059,7 +46585,8 @@ "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/v8-to-istanbul": { "version": "9.2.0", @@ -48124,6 +46651,7 @@ }, "node_modules/vary": { "version": "1.1.2", + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -48131,6 +46659,7 @@ }, "node_modules/verror": { "version": "1.10.0", + "devOptional": true, "engines": [ "node >=0.6.0" ], @@ -48282,6 +46811,8 @@ "version": "1.10.0", "hasInstallScript": true, "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "web3-bzz": "1.10.0", "web3-core": "1.10.0", @@ -48299,6 +46830,8 @@ "version": "1.10.0", "hasInstallScript": true, "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "@types/node": "^12.12.6", "got": "12.1.0", @@ -48311,6 +46844,8 @@ "node_modules/web3-bzz/node_modules/@szmarczak/http-timer": { "version": "5.0.1", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "defer-to-connect": "^2.0.1" }, @@ -48320,22 +46855,30 @@ }, "node_modules/web3-bzz/node_modules/@types/node": { "version": "12.20.55", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/web3-bzz/node_modules/cacheable-lookup": { "version": "6.1.0", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=10.6.0" } }, "node_modules/web3-bzz/node_modules/form-data-encoder": { "version": "1.7.1", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/web3-bzz/node_modules/get-stream": { "version": "6.0.1", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=10" }, @@ -48346,6 +46889,8 @@ "node_modules/web3-bzz/node_modules/got": { "version": "12.1.0", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@sindresorhus/is": "^4.6.0", "@szmarczak/http-timer": "^5.0.1", @@ -48371,6 +46916,8 @@ "node_modules/web3-bzz/node_modules/http2-wrapper": { "version": "2.2.0", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" @@ -48382,6 +46929,8 @@ "node_modules/web3-bzz/node_modules/lowercase-keys": { "version": "3.0.0", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -48392,6 +46941,8 @@ "node_modules/web3-bzz/node_modules/p-cancelable": { "version": "3.0.0", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=12.20" } @@ -48399,6 +46950,8 @@ "node_modules/web3-core": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "@types/bn.js": "^5.1.1", "@types/node": "^12.12.6", @@ -48415,6 +46968,8 @@ "node_modules/web3-core-helpers": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "web3-eth-iban": "1.10.0", "web3-utils": "1.10.0" @@ -48426,6 +46981,8 @@ "node_modules/web3-core-method": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "@ethersproject/transactions": "^5.6.2", "web3-core-helpers": "1.10.0", @@ -48440,6 +46997,8 @@ "node_modules/web3-core-promievent": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "eventemitter3": "4.0.4" }, @@ -48449,11 +47008,15 @@ }, "node_modules/web3-core-promievent/node_modules/eventemitter3": { "version": "4.0.4", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/web3-core-requestmanager": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "util": "^0.12.5", "web3-core-helpers": "1.10.0", @@ -48468,6 +47031,8 @@ "node_modules/web3-core-subscriptions": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "eventemitter3": "4.0.4", "web3-core-helpers": "1.10.0" @@ -48478,15 +47043,21 @@ }, "node_modules/web3-core-subscriptions/node_modules/eventemitter3": { "version": "4.0.4", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/web3-core/node_modules/@types/node": { "version": "12.20.55", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/web3-eth": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "web3-core": "1.10.0", "web3-core-helpers": "1.10.0", @@ -48508,6 +47079,8 @@ "node_modules/web3-eth-abi": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "@ethersproject/abi": "^5.6.3", "web3-utils": "1.10.0" @@ -48519,6 +47092,8 @@ "node_modules/web3-eth-accounts": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "@ethereumjs/common": "2.5.0", "@ethereumjs/tx": "3.3.2", @@ -48538,6 +47113,8 @@ "node_modules/web3-eth-accounts/node_modules/eth-lib": { "version": "0.2.8", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "bn.js": "^4.11.6", "elliptic": "^6.4.0", @@ -48546,11 +47123,15 @@ }, "node_modules/web3-eth-accounts/node_modules/eth-lib/node_modules/bn.js": { "version": "4.12.0", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/web3-eth-accounts/node_modules/ethereum-cryptography": { "version": "0.1.3", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -48572,6 +47153,8 @@ "node_modules/web3-eth-accounts/node_modules/ethereumjs-util": { "version": "7.1.5", "license": "MPL-2.0", + "optional": true, + "peer": true, "dependencies": { "@types/bn.js": "^5.1.0", "bn.js": "^5.1.2", @@ -48586,6 +47169,8 @@ "node_modules/web3-eth-accounts/node_modules/uuid": { "version": "9.0.0", "license": "MIT", + "optional": true, + "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -48593,6 +47178,8 @@ "node_modules/web3-eth-contract": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "@types/bn.js": "^5.1.1", "web3-core": "1.10.0", @@ -48610,6 +47197,8 @@ "node_modules/web3-eth-ens": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "content-hash": "^2.5.2", "eth-ens-namehash": "2.0.8", @@ -48627,6 +47216,8 @@ "node_modules/web3-eth-iban": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "bn.js": "^5.2.1", "web3-utils": "1.10.0" @@ -48638,6 +47229,8 @@ "node_modules/web3-eth-personal": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "@types/node": "^12.12.6", "web3-core": "1.10.0", @@ -48652,11 +47245,15 @@ }, "node_modules/web3-eth-personal/node_modules/@types/node": { "version": "12.20.55", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/web3-net": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "web3-core": "1.10.0", "web3-core-method": "1.10.0", @@ -48669,6 +47266,8 @@ "node_modules/web3-providers-http": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "abortcontroller-polyfill": "^1.7.3", "cross-fetch": "^3.1.4", @@ -48682,6 +47281,8 @@ "node_modules/web3-providers-ipc": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "oboe": "2.1.5", "web3-core-helpers": "1.10.0" @@ -48693,6 +47294,8 @@ "node_modules/web3-providers-ws": { "version": "1.10.0", "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "eventemitter3": "4.0.4", "web3-core-helpers": "1.10.0", @@ -48704,12 +47307,16 @@ }, "node_modules/web3-providers-ws/node_modules/eventemitter3": { "version": "4.0.4", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/web3-shh": { "version": "1.10.0", "hasInstallScript": true, "license": "LGPL-3.0", + "optional": true, + "peer": true, "dependencies": { "web3-core": "1.10.0", "web3-core-method": "1.10.0", @@ -49686,7 +48293,8 @@ "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "peer": true }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -49978,6 +48586,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "peer": true, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -49992,6 +48601,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "peer": true, "engines": { "node": ">=10" }, @@ -50003,6 +48613,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "peer": true, "engines": { "node": ">=10" }, @@ -50023,6 +48634,7 @@ "version": "3.1.1", "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -50073,4 +48685,4 @@ } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 9455c238a..87d0158d0 100755 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ }, "scripts": { "analyze": "source-map-explorer 'build/static/js/*.js'", - "start": "react-app-rewired start --max-old-space-size=7168", + "start": "react-app-rewired start --max-old-space-size=7168 --force", "start-legacy": "react-app-rewired --openssl-legacy-provider start", "build": "GENERATE_SOURCEMAP=false CI=false react-app-rewired build --max-old-space-size=7168", "test": "react-app-rewired test --env=jsdom", @@ -97,8 +97,9 @@ "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.60", "@material-ui/styles": "^4.11.5", - "@orbs-network/twap-ui": "^0.10.23", - "@orbs-network/twap-ui-quickswap": "^0.10.23", + "@orbs-network/liquidity-hub-sdk": "^1.0.22", + "@orbs-network/swap-ui": "^0.0.8", + "@orbs-network/twap-sdk": "^2.0.18", "@orderly.network/hooks": "^1.4.3", "@orderly.network/react": "^1.4.3", "@orderly.network/types": "^1.4.3", diff --git a/public/locales/en.json b/public/locales/en.json index 57f983b9f..8f03394a6 100755 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -700,6 +700,7 @@ "wrapMATIC": "Wrap {{ symbol }}", "wrappingMATIC": "Wrapping {{ symbol }}", "unwrapMATIC": "Unwrap {{ symbol }}", + "successfullyUnwrappedMATIC": "Successfully unwrapped {{ symbol }}", "unwrappingMATIC": "Unwrapping {{ symbol }}", "fetchingBestRoute": "Fetching Best Route", "contest": "Contest", @@ -720,6 +721,7 @@ "bestTradeBanned": "Best trade is unavailable in your location. Please use v2 or v3.", "priceImpactReached": "Price impact is more than {{maxImpact}}%. Please use v2 or v3.", "priceImpactReachedV2": "Price impact is more than {{maxImpact}}%. Please use best trade or v3.", + "priceImpactReachedLiquidityHubEthereumTrade": "Price impact is more than {{maxImpact}}%. Please use v3.", "disclaimer": "Disclaimer", "disclaimerText1": "Please check the boxes below to confirm your agreement to the QuickSwap Terms and Conditions", "disclaimerText2": "I have read and understood, and do hereby agree to be legally bound as a ‘User’ under, the Terms, including all future amendments thereto. Such agreement is irrevocable and will apply to all of my uses of the Site without me providing confirmation in each specific instance.", @@ -986,5 +988,37 @@ "poolManager": "Pool Manager", "notEnoughBalance": "Not Enough Balance", "subNewsletter": "Subscribe to Newsletter", - "allRights": "All rights reserved." + "allRights": "All rights reserved.", + "hours": "hours", + "orders": "Orders", + "dca-market": "DCA Market", + "dca-limit": "DCA Limit", + "allocate": "Allocate", + "numOfTrades": "No. of trades", + "individualTradeSize": "Individual trade size", + "amountOut": "Amount out", + "createdAt": "Created at", + "expiry": "Expiry", + "limitPrice": "Limit price", + "progress": "Progress", + "excecutionPrice": "Avg. execution price", + "status": "Status", + "amountReceived": "Amount received", + "amountSent": "Amount sent", + "excecutionSummary": "Execution summary", + "orderInfo": "Order info", + "every": "Every", + "expiryTooltip": "This is the date and time marking the end of the period which you have selected for your order to be executed.", + "individualTradeSizeTooltip": "The number of input tokens that will be removed from your balance and swapped for the output token in each individual trade.", + "numOfTradesTooltip": "The total number of individual trades that will be scheduled as part of your order.", + "fillDelayTooltip": "The estimated minimum amount of time that will elapse between each trade in your order.", + "minimumReceivedTooltip": "This is the minimum number of tokens that may be received. NOTE: This minimum only refers to executed trades. Some trades may not be executed if the limit price is higher than the available market prices and your order may only be partially filled.", + "marketPriceWarning":"* Each individual trade in this order will be filled at the current market price at the time of execution.", + "orbs":"Orbs", + "approveToken":"Approve {{ symbol }} spending", + "tradeSizeWarning":"Trade size must be at least ${{ usd }}", + "minExpiryWarning":"Min. expiry is {{ value }} minutes", + "maxExpiryWarning":"Max. expiry is 30 days", + "minFillDelayWarning":"Min. trade interval is {{ value }} minutes", + "maxFillDelayWarning":"Max. trade interval is {{ value }} days" } diff --git a/src/components/ConfirmSwapModal/ConfirmSwapModal.tsx b/src/components/ConfirmSwapModal/ConfirmSwapModal.tsx index 13daf77a6..36f29734c 100755 --- a/src/components/ConfirmSwapModal/ConfirmSwapModal.tsx +++ b/src/components/ConfirmSwapModal/ConfirmSwapModal.tsx @@ -4,13 +4,13 @@ import { TransactionConfirmationModal, TransactionErrorContent, ConfirmationModalContent, + CustomModal, } from 'components'; import SwapModalHeader from './SwapModalHeader'; import { formatTokenAmount } from 'utils'; import 'components/styles/ConfirmSwapModal.scss'; import { useTranslation } from 'react-i18next'; import { OptimalRate } from '@paraswap/sdk'; -import { useLiquidityHubState } from 'state/swap/liquidity-hub/hooks'; /** * Returns true if the trade requires a confirmation of details before we can submit it @@ -100,7 +100,6 @@ const ConfirmSwapModal: React.FC = ({ outputCurrency, ]); - const liquidityHubState = useLiquidityHubState(); // text to show while loading const pendingText = t('swappingFor', { amount1: optimalRate @@ -110,8 +109,7 @@ const ConfirmSwapModal: React.FC = ({ ? trade?.inputAmount?.currency?.symbol : inputCurrency?.symbol, amount2: optimalRate - ? Number(liquidityHubState.outAmount || optimalRate.destAmount) / - 10 ** optimalRate.destDecimals + ? Number(optimalRate.destAmount) / 10 ** optimalRate.destDecimals : formatTokenAmount(trade?.outputAmount), symbol2: trade ? trade?.outputAmount?.currency?.symbol diff --git a/src/components/CurrencyInput/CurrencyInput.tsx b/src/components/CurrencyInput/CurrencyInput.tsx index 1012accc5..5e6bdd36f 100755 --- a/src/components/CurrencyInput/CurrencyInput.tsx +++ b/src/components/CurrencyInput/CurrencyInput.tsx @@ -38,6 +38,7 @@ interface CurrencyInputProps { classNames?: string; balancePrev?: string; balanceAfter?: string; + disabled?: boolean; } const CurrencyInput: React.FC = ({ @@ -58,6 +59,7 @@ const CurrencyInput: React.FC = ({ classNames, balancePrev, balanceAfter, + disabled, }) => { const { t } = useTranslation(); const { account, chainId } = useActiveWeb3React(); @@ -157,7 +159,12 @@ const CurrencyInput: React.FC = ({ sx={{ borderRadius: '10px', padding: '8px 16px' }} className='bg-input1' > - + - - -
-
{item.text}
-
- {item.isNew && } -
+ +
+
{item.text}
+
+ {item.isNew ? ( + new menu + ) : ( + <> + )}
- +
+
- {hasSubMenu ? ( - open ? ( - - ) : ( - - ) + {hasSubMenu ? ( + open ? ( + ) : ( - <> - )} - + + ) + ) : ( + <> + )} {hasSubMenu && ( = ({ onClick={() => setOpen(false)} /> ))} - - { - setOpen(false); - }} - > - - - Close - - - + { + setOpen(false); + }} + > + + + Close + + - - + + diff --git a/src/components/Header/StyledMenu.tsx b/src/components/Header/StyledMenu.tsx index b87eb5f2e..e533799e4 100644 --- a/src/components/Header/StyledMenu.tsx +++ b/src/components/Header/StyledMenu.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; -import { styled, alpha } from '@mui/material/styles'; -import Menu, { MenuProps } from '@mui/material/Menu'; +import { MenuProps, styled, Menu } from "@material-ui/core" export const StyledMenu = styled((props: MenuProps) => ( = ({ /> - +

{t('language')}

diff --git a/src/components/Swap/LiquidityHub.tsx b/src/components/Swap/LiquidityHub.tsx deleted file mode 100644 index f0a4de7d5..000000000 --- a/src/components/Swap/LiquidityHub.tsx +++ /dev/null @@ -1,1263 +0,0 @@ -import React, { useCallback, useMemo } from 'react'; -import Web3 from 'web3'; -import BN from 'bignumber.js'; -import { useExpertModeManager, useLiquidityHubManager } from 'state/user/hooks'; -import { useActiveWeb3React, useIsProMode } from 'hooks'; -import { useLocation } from 'react-router-dom'; -import { styled } from '@material-ui/styles'; -import { Box, Divider } from '@material-ui/core'; -import OrbsLogo from 'assets/images/orbs-logo.svg'; -import { - setWeb3Instance, - maxUint256, - permit2Address, - hasWeb3Instance, - zeroAddress, - web3, -} from '@defi.org/web3-candies'; -import { useTranslation } from 'react-i18next'; -import { - useLiquidityHubActionHandlers, - useLiquidityHubState, -} from 'state/swap/liquidity-hub/hooks'; -import { useTokenContract, useWETHContract } from 'hooks/useContract'; -import { getConfig } from 'config/index'; -import ToggleSwitch from 'components/ToggleSwitch'; -import { useUSDCPriceFromAddress } from 'utils/useUSDCPrice'; -import { ChainId, ETHER, Trade, WETH, Currency } from '@uniswap/sdk'; -import { Contract } from 'ethers'; -import { useSwapActionHandlers } from 'state/swap/hooks'; -import { Field } from 'state/swap/actions'; -import { Currency as CoreCurrency, Percent } from '@uniswap/sdk-core'; -import { ZERO_ADDRESS } from 'constants/v3/misc'; -import { wrappedCurrency } from 'utils/wrappedCurrency'; -import { parseUnits, _TypedDataEncoder } from 'ethers/lib/utils'; -import { getFixedValue } from 'utils'; -const ANALYTICS_VERSION = 0.5; -const WEBSITE = 'https://www.orbs.com'; -const BI_ENDPOINT = `https://bi.orbs.network/putes/liquidity-hub-ui-${ANALYTICS_VERSION}`; -const DEX_PRICE_BETTER_ERROR = 'Dex trade is better than Clob trade'; -const PARTNER = 'QuickSwap'; - -const getApiEndpoint = (chainId: number) => { - if (chainId === ChainId.ZKEVM) { - return 'https://zkevm.hub.orbs.network'; - } - return 'https://polygon.hub.orbs.network'; -}; - -export const useLiquidityHubCallback = ( - allowedSlippage: number, - inTokenAddress?: string, - outTokenAddress?: string, - inTokenCurrency?: Currency, - outTokenCurrency?: Currency, -) => { - const [liquidityHubDisabled] = useLiquidityHubManager(); - const { account, library, chainId } = useActiveWeb3React(); - const liquidityHubState = useLiquidityHubState(); - const { onSetLiquidityHubState } = useLiquidityHubActionHandlers(); - const { lhControl } = useQueryParam(); - const approve = useApprove(); - const wethContract = useWETHContract(); - const inTokenContract = useTokenContract(inTokenAddress); - const isApproved = useApproved(); - const swap = useSwap(); - const sign = useSign(); - const quote = useQuote(allowedSlippage); - const wrap = useWrap(); - const isSupported = useIsLiquidityHubSupported(); - const chainIdToUse = chainId ? chainId : ChainId.MATIC; - const nativeCurrency = ETHER[chainIdToUse]; - - const isNativeIn = nativeCurrency.symbol === inTokenCurrency?.symbol; - const isNativeOut = nativeCurrency.symbol === outTokenCurrency?.symbol; - - const { price: outTokenUSD } = useUSDCPriceFromAddress( - isNativeOut ? WETH[chainId].address : outTokenAddress || '', - ); - - const isProMode = useIsProMode(); - const [expertMode] = useExpertModeManager(); - - return async ( - srcAmount?: string, - minDestAmount?: string, - dexOutAmountWS?: string, - ) => { - liquidityHubAnalytics.clearState(); - const dstTokenUsdValue = new BN(minDestAmount || '0') - .multipliedBy(outTokenUSD || 0) - .dividedBy(new BN(10).pow(new BN(outTokenCurrency?.decimals || 0))) - .toNumber(); - const isForce = lhControl === LiquidityHubControl.FORCE; - - liquidityHubAnalytics.onBestTrade({ - dexAmountOut: minDestAmount, - dstTokenUsdValue, - srcTokenAddress: inTokenAddress, - srcTokenSymbol: inTokenCurrency?.symbol, - dstTokenAddress: outTokenAddress, - dstTokenSymbol: outTokenCurrency?.symbol, - srcAmount, - slippage: allowedSlippage / 100, - walletAddress: account, - chainId: chainIdToUse, - dexOutAmountWS, - }); - - if (isProMode) { - liquidityHubAnalytics.onIsProMode(); - } - if (expertMode) { - liquidityHubAnalytics.onExpertMode(); - } - if (isForce) { - liquidityHubAnalytics.onForceClob(); - } - - try { - if (liquidityHubState.isFailed) { - if (!isForce) { - throw new Error('previous failure'); - } - } - if (lhControl === LiquidityHubControl.SKIP) { - throw new Error('query param'); - } - if (!isSupported) { - throw new Error('clob not supported'); - } - if (liquidityHubDisabled) { - throw new Error('clob disabled'); - } - if (!minDestAmount) { - throw new Error('minDestAmount is not defined'); - } - if (!inTokenAddress) { - throw new Error('inTokenAddress is not defined'); - } - if (!outTokenAddress) { - throw new Error('outTokenAddress is not defined'); - } - if (!library) { - throw new Error('library is not defined'); - } - if (!account) { - throw new Error('account is not defined'); - } - if (!srcAmount) { - throw new Error('srcAmount is not defined'); - } - } catch (error) { - liquidityHubAnalytics.onNotClobTrade(error.message); - return; - } - liquidityHubAnalytics.onWallet(library); - - onSetLiquidityHubState({ - isLoading: true, - }); - - const quoteArgs: QuoteArgs = { - outToken: outTokenAddress, - inAmount: srcAmount, - inToken: isNativeIn ? zeroAddress : inTokenAddress, - minDestAmount, - }; - let wrapped = false; - const nativeInStartFlow = async () => { - await quote(quoteArgs); - wrapped = await wrap(srcAmount); - - const approved = await isApproved(srcAmount, wethContract); - if (!approved) { - liquidityHubAnalytics.onApprovedBeforeTheTrade(false); - await approve(wethContract); - } else { - liquidityHubAnalytics.onApprovedBeforeTheTrade(true); - } - }; - - const regularStartFlow = async () => { - const approved = await isApproved(srcAmount, inTokenContract); - if (!approved) { - liquidityHubAnalytics.onApprovedBeforeTheTrade(false); - await quote(quoteArgs); - await approve(inTokenContract); - } else { - liquidityHubAnalytics.onApprovedBeforeTheTrade(true); - } - }; - - try { - if (isNativeIn) { - await nativeInStartFlow(); - } else { - await regularStartFlow(); - } - - const quoteResult = await quote(quoteArgs); - onSetLiquidityHubState({ - isWon: true, - isLoading: false, - outAmount: quoteResult.outAmount, - }); - const signature = await sign(quoteResult.permitData); - - const response = await swap({ - srcToken: inTokenAddress, - destToken: outTokenAddress, - srcAmount, - minDestAmount, - signature, - quoteResult, - }); - liquidityHubAnalytics.onClobSuccess(response); - return response; - } catch (error) { - liquidityHubAnalytics.onClobFailure(); - onSetLiquidityHubState({ isFailed: true }); - if (wrapped) { - throw new Error( - 'Transaction reverted, Please try again. Note! Your MATIC has been wrapped and are now wMATIC', - ); - } - return undefined; - } finally { - onSetLiquidityHubState({ - isLoading: false, - isWon: false, - outAmount: '', - }); - } - }; -}; - -const useWrap = () => { - const wethContract = useWETHContract(); - const { onSetLiquidityHubState } = useLiquidityHubActionHandlers(); - const { onCurrencySelection } = useSwapActionHandlers(); - const { chainId } = useActiveWeb3React(); - - return async (inAmount: string) => { - const chainIdToUse = chainId ? chainId : ChainId.MATIC; - - const count = counter(); - onSetLiquidityHubState({ waitingForWrap: true }); - liquidityHubAnalytics.onWrapRequest(); - try { - const txReceipt = await wethContract?.deposit({ - value: `0x${new BN(inAmount).toString(16)}`, - }); - onCurrencySelection(Field.INPUT, WETH[chainIdToUse]); - const res = await txReceipt.wait(); - liquidityHubAnalytics.onWrapSuccess(res.transactionHash, count()); - return true; - } catch (error) { - liquidityHubAnalytics.onWrapFailed(error.message, count()); - throw new Error(error.message); - } finally { - onSetLiquidityHubState({ waitingForWrap: false }); - } - }; -}; - -const useApproved = () => { - const { account } = useActiveWeb3React(); - - return async (srcAmount: string, tokenContract: Contract | null) => { - try { - const allowance = await tokenContract?.allowance(account, permit2Address); - return BN(allowance?.toString() || '0').gte(BN(srcAmount)); - } catch (error) { - return false; - } - }; -}; - -const useApprove = () => { - const { onSetLiquidityHubState } = useLiquidityHubActionHandlers(); - - return async (tokenContract?: Contract | null) => { - const count = counter(); - try { - onSetLiquidityHubState({ waitingForApproval: true }); - liquidityHubAnalytics.onApprovalRequest(); - const response = await tokenContract?.approve( - permit2Address, - maxUint256, - { - gasLimit: 100_000, - }, - ); - - const res = await response.wait(); - liquidityHubAnalytics.onApprovalSuccess(count()); - return res; - } catch (error) { - liquidityHubAnalytics.onApprovalFailed(error.message, count()); - throw new Error(error.message); - } finally { - onSetLiquidityHubState({ waitingForApproval: false }); - } - }; -}; - -const useSign = () => { - const { account, library } = useActiveWeb3React(); - const { onSetLiquidityHubState } = useLiquidityHubActionHandlers(); - return async (permitData: any) => { - const count = counter(); - - try { - if (!account || !library) { - throw new Error('No account or library'); - } - onSetLiquidityHubState({ waitingForSignature: true }); - liquidityHubAnalytics.onSignatureRequest(); - if (!hasWeb3Instance()) { - setWeb3Instance(new Web3(library.provider as any)); - } - process.env.DEBUG = 'web3-candies'; - const signature = await signEIP712(account, permitData); - liquidityHubAnalytics.onSignatureSuccess(signature, count()); - return signature; - } catch (error) { - liquidityHubAnalytics.onSignatureFailed(error.message, count()); - throw new Error(error.message); - } finally { - onSetLiquidityHubState({ waitingForSignature: false }); - } - }; -}; - -const useSwap = () => { - const { library, account, chainId } = useActiveWeb3React(); - return async (args: { - srcToken: string; - destToken: string; - srcAmount: string; - minDestAmount: string; - signature: string; - quoteResult: QuoteResponse; - }) => { - const count = counter(); - try { - liquidityHubAnalytics.onSwapRequest(); - const txHashResponse = await fetch( - `${getApiEndpoint(chainId)}/swapx?chainId=${chainId}`, - { - method: 'POST', - body: JSON.stringify({ - inToken: args.srcToken, - outToken: args.destToken, - inAmount: args.srcAmount, - user: account, - signature: args.signature, - ...args.quoteResult, - }), - }, - ); - const swap = await txHashResponse.json(); - if (!swap) { - throw new Error('Missing swap response'); - } - - if (swap.error || (swap.message && !swap.txHash)) { - throw new Error(swap); - } - - if (!swap.txHash) { - throw new Error('Missing txHash'); - } - const tx = await waitForTx(swap.txHash, library); - liquidityHubAnalytics.onSwapSuccess(swap.txHash, count()); - return tx; - } catch (error) { - const message = JSON.stringify(error); - liquidityHubAnalytics.onSwapFailed(message, count()); - throw new Error(message); - } - }; -}; - -const useQuote = (allowedSlippage: number) => { - const { account, chainId } = useActiveWeb3React(); - const { lhControl } = useQueryParam(); - - return async (args: QuoteArgs) => { - let quoteResponse: any; - const count = counter(); - liquidityHubAnalytics.incrementQuoteIndex(); - liquidityHubAnalytics.onQuoteRequest(); - const abortController = new AbortController(); - - try { - const timeout = setTimeout(() => { - abortController.abort(); - }, 8_000); - - const response = await fetch( - `${getApiEndpoint(chainId)}/quote?chainId=${chainId}`, - { - method: 'POST', - body: JSON.stringify({ - inToken: args.inToken, - outToken: args.outToken, - inAmount: args.inAmount, - outAmount: args.minDestAmount, - user: account, - slippage: allowedSlippage / 100, - qs: encodeURIComponent(window.location.hash), - sessionId: liquidityHubAnalytics.data.sessionId, - }), - signal: abortController.signal, - }, - ); - quoteResponse = await response.json(); - clearTimeout(timeout); - if (!quoteResponse) { - throw new Error('Missing result from quote'); - } - if (quoteResponse.error) { - throw new Error(quoteResponse.error); - } - - if (quoteResponse.message) { - throw new Error(quoteResponse.message); - } - const isForce = lhControl === LiquidityHubControl.FORCE; - if ( - !isForce && - BN(quoteResponse.outAmount || '0').isLessThan( - BN(args.minDestAmount || '0'), - ) - ) { - throw new Error(DEX_PRICE_BETTER_ERROR); - } - liquidityHubAnalytics.onQuoteSuccess(quoteResponse, count()); - return quoteResponse as QuoteResponse; - } catch (error) { - liquidityHubAnalytics.onQuoteFailed( - error.message, - count(), - quoteResponse, - ); - - throw new Error(error.message); - } finally { - if (quoteResponse.sessionId) { - liquidityHubAnalytics.setSessionId(quoteResponse.sessionId); - } - } - }; -}; - -//utils - -const useIsLiquidityHubSupported = () => { - const { chainId } = useActiveWeb3React(); - - return useMemo(() => getConfig(chainId)?.swap?.liquidityHub, [chainId]); -}; - -export const useIsLiquidityHubEnabled = () => { - const isSupported = useIsLiquidityHubSupported(); - const [liquidityHubDisabled] = useLiquidityHubManager(); - - return isSupported && !liquidityHubDisabled; -}; - -async function waitForTx(txHash: string, library: any) { - for (let i = 0; i < 30; ++i) { - // due to swap being fetch and not web3 - - await delay(2_000); // to avoid potential rate limiting from public rpc - try { - const tx = await library.getTransaction(txHash); - if (tx && tx instanceof Object && tx.blockNumber) { - return tx; - } - } catch (error) {} - } -} - -function delay(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -export const useQueryParam = () => { - const location = useLocation(); - - const query = useMemo(() => new URLSearchParams(location.search), [ - location.search, - ]); - - return { - lhControl: query.get('liquidity-hub')?.toLowerCase(), - }; -}; - -enum TradeType { - V2 = 'V2', - V3 = 'V3', - BEST_TRADE = 'BEST_TRADE', - TWAP = 'TWAP', - LIMIT = 'LIMIT', -} - -type InitTradeArgs = { - srcTokenAddress?: string; - dstTokenAddress?: string; - srcTokenSymbol?: string; - dstTokenSymbol?: string; - walletAddress?: string; - slippage?: number; - srcAmount?: string; - dexAmountOut?: string; - dstTokenUsdValue?: number; - chainId: number; - dexOutAmountWS?: string; -}; -const sendBI = async (data: Partial) => { - try { - fetch(BI_ENDPOINT, { - method: 'POST', - body: JSON.stringify(data), - }); - } catch (error) {} -}; - -const initialData: Partial = { - _id: crypto.randomUUID(), - partner: PARTNER, - isClobTrade: false, - quoteIndex: 0, - isForceClob: false, - isDexTrade: false, - version: ANALYTICS_VERSION, -}; - -const counter = () => { - const now = Date.now(); - - return () => { - return Date.now() - now; - }; -}; - -class LiquidityHubAnalytics { - initialTimestamp = Date.now(); - data = initialData; - firstFailureSessionId = ''; - timeout: any = undefined; - - updateChainId(chainId: number) { - this.data.chainId = chainId; - } - - private updateAndSend(values = {} as Partial) { - this.data = { ...this.data, ...values }; - - clearTimeout(this.timeout); - this.timeout = setTimeout(() => { - sendBI(this.data); - }, 1_000); - } - - incrementQuoteIndex() { - this.updateAndSend({ - quoteIndex: !this.data.quoteIndex ? 1 : this.data.quoteIndex + 1, - }); - } - - onQuoteRequest() { - this.updateAndSend({ [`quote-${this.data.quoteIndex}-state`]: 'pending' }); - } - - onQuoteSuccess(quoteResponse: QuoteResponse, time: number) { - this.updateAndSend({ [`quote-${this.data.quoteIndex}-state`]: 'success' }); - this.onQuoteData(quoteResponse, time); - } - - onBestTrade(values: InitTradeArgs) { - this.updateAndSend({ tradeType: TradeType.BEST_TRADE, ...values }); - } - onTwapTrade(values: InitTradeArgs) { - this.updateAndSend({ tradeType: TradeType.TWAP, ...values }); - } - - onLimitTrade(values: InitTradeArgs) { - this.updateAndSend({ tradeType: TradeType.LIMIT, ...values }); - } - - onV2Trade(values: InitTradeArgs) { - this.updateAndSend({ tradeType: TradeType.V2, ...values }); - } - - onV3Trade(values: InitTradeArgs) { - this.updateAndSend({ tradeType: TradeType.V3, ...values }); - } - - onQuoteFailed(error: string, time: number, quoteResponse?: QuoteResponse) { - if (error == DEX_PRICE_BETTER_ERROR) { - this.updateAndSend({ - isNotClobTradeReason: DEX_PRICE_BETTER_ERROR, - [`quote-${this.data.quoteIndex}-state`]: 'success', - }); - } else { - this.updateAndSend({ - [`quote-${this.data.quoteIndex}-error`]: error, - [`quote-${this.data.quoteIndex}-state`]: 'failed', - isNotClobTradeReason: `quote-${this.data.quoteIndex}-failed`, - }); - } - - this.onQuoteData(quoteResponse, time); - } - - onQuoteData(quoteResponse?: QuoteResponse, time?: number) { - const getDiff = () => { - if (!quoteResponse?.outAmount || !this.data.dexAmountOut) { - return ''; - } - return new BN(quoteResponse?.outAmount) - .dividedBy(new BN(this.data.dexAmountOut)) - .minus(1) - .multipliedBy(100) - .toFixed(2); - }; - - this.updateAndSend({ - [`quote-${this.data.quoteIndex}-amount-out`]: quoteResponse?.outAmount, - [`quote-${this.data.quoteIndex}-serialized-order`]: quoteResponse?.serializedOrder, - [`quote-${this.data.quoteIndex}-quote-millis`]: time, - clobDexPriceDiffPercent: getDiff(), - }); - } - - onApprovedBeforeTheTrade(userWasApprovedBeforeTheTrade: boolean) { - this.updateAndSend({ userWasApprovedBeforeTheTrade }); - } - - onApprovalRequest() { - this.updateAndSend({ approvalState: 'pending' }); - } - - onDexSwapRequest() { - this.updateAndSend({ dexSwapState: 'pending', isDexTrade: true }); - } - - onDexSwapSuccess(response: any) { - this.updateAndSend({ - dexSwapState: 'success', - dexSwapTxHash: response.hash, - }); - - this.pollTransaction({ - response, - onSucess: () => { - this.updateAndSend({ onChainDexSwapState: 'success' }); - }, - onFailed: () => { - this.updateAndSend({ onChainDexSwapState: 'failed' }); - }, - }); - } - onDexSwapFailed(dexSwapError: string) { - this.updateAndSend({ dexSwapState: 'failed', dexSwapError }); - } - - onApprovalSuccess(time: number) { - this.updateAndSend({ approvalMillis: time, approvalState: 'success' }); - } - - onApprovalFailed(error: string, time: number) { - this.updateAndSend({ - approvalError: error, - approvalState: 'failed', - approvalMillis: time, - isNotClobTradeReason: 'approval failed', - }); - } - - onSignatureRequest() { - this.updateAndSend({ signatureState: 'pending' }); - } - - onWrapRequest() { - this.updateAndSend({ wrapState: 'pending' }); - } - - onWrapSuccess(txHash: string, time: number) { - this.updateAndSend({ - wrapTxHash: txHash, - wrapMillis: time, - wrapState: 'success', - }); - } - - onWrapFailed(error: string, time: number) { - this.updateAndSend({ - wrapError: error, - wrapState: 'failed', - wrapMillis: time, - isNotClobTradeReason: 'wrap failed', - }); - } - - onSignatureSuccess(signature: string, time: number) { - this.updateAndSend({ - signature, - signatureMillis: time, - signatureState: 'success', - }); - } - - onWallet = (library: any) => { - try { - const walletConnectName = (library as any)?.provider?.session?.peer - .metadata.name; - - if (library.provider.isRabby) { - this.updateAndSend({ walletConnectName, isRabby: true }); - } else if (library.provider.isWalletConnect) { - this.updateAndSend({ walletConnectName, isWalletConnect: true }); - } else if (library.provider.isCoinbaseWallet) { - this.updateAndSend({ walletConnectName, isCoinbaseWallet: true }); - } else if (library.provider.isOkxWallet) { - this.updateAndSend({ walletConnectName, isOkxWallet: true }); - } else if (library.provider.isTrustWallet) { - this.updateAndSend({ walletConnectName, isTrustWallet: true }); - } else if (library.provider.isMetaMask) { - this.updateAndSend({ walletConnectName, isMetaMask: true }); - } - } catch (error) { - console.log('Error on wallet', error); - } - }; - - onSignatureFailed(error: string, time: number) { - this.updateAndSend({ - signatureError: error, - signatureState: 'failed', - signatureMillis: time, - isNotClobTradeReason: 'signature failed', - }); - } - - onSwapRequest() { - this.updateAndSend({ swapState: 'pending' }); - } - - onSwapSuccess(txHash: string, time: number) { - this.updateAndSend({ - txHash, - swapMillis: time, - swapState: 'success', - isClobTrade: true, - onChainClobSwapState: 'pending', - }); - } - - onSwapFailed(error: string, time: number) { - this.updateAndSend({ - swapError: error, - swapState: 'failed', - swapMillis: time, - isNotClobTradeReason: 'swap failed', - }); - } - - setSessionId(id: string) { - this.data.sessionId = id; - } - - onForceClob() { - this.updateAndSend({ isForceClob: true }); - } - - onIsProMode() { - this.updateAndSend({ isProMode: true }); - } - - onExpertMode() { - this.updateAndSend({ expertMode: true }); - } - - clearState() { - this.data = { - ...initialData, - _id: crypto.randomUUID(), - firstFailureSessionId: this.firstFailureSessionId, - }; - } - - async pollTransaction({ - response, - onSucess, - onFailed, - }: { - response: any; - onSucess: () => void; - onFailed: () => void; - }) { - try { - const receipt = await response.wait(); - if (receipt.status === 1) { - onSucess(); - } else { - throw new Error('Transaction failed'); - } - } catch (error) { - onFailed(); - } - } - - async onClobSuccess(response: any) { - this.pollTransaction({ - response, - onSucess: () => { - this.updateAndSend({ onChainClobSwapState: 'success' }); - }, - onFailed: () => { - { - this.updateAndSend({ - onChainClobSwapState: 'failed', - isNotClobTradeReason: 'onchain swap error', - }); - } - }, - }); - } - - onNotClobTrade(message: string) { - this.updateAndSend({ isNotClobTradeReason: message }); - } - - onClobFailure() { - this.firstFailureSessionId = - this.firstFailureSessionId || this.data.sessionId || ''; - } -} - -export const liquidityHubAnalytics = new LiquidityHubAnalytics(); - -export const useConfirmationPendingContent = (pendingText?: string) => { - const { t } = useTranslation(); - const liquidityHubState = useLiquidityHubState(); - return useMemo(() => { - if (liquidityHubState?.waitingForApproval) { - return { - title: t('seekingBestPrice'), - confirm: t('awaitingApproval'), - }; - } - if (liquidityHubState?.waitingForWrap) { - return { - title: t('seekingBestPrice'), - confirm: t('awaitingWrap'), - }; - } - if (liquidityHubState?.isLoading) { - return { - title: t('seekingBestPrice'), - }; - } - if (liquidityHubState?.isWon) { - return { - title: t('optimizedRouteAvailable'), - pending: pendingText, - confirm: - liquidityHubState.waitingForSignature && - t('signToPerformGaslessSwap'), - }; - } - return { - title: t('waitingConfirm'), - pending: pendingText, - confirm: t('confirmTxinWallet'), - }; - }, [ - liquidityHubState?.isLoading, - liquidityHubState?.isWon, - pendingText, - t, - liquidityHubState?.waitingForApproval, - liquidityHubState.waitingForSignature, - liquidityHubState?.waitingForWrap, - ]); -}; - -// components - -export const LiquidityHubTxSettings = () => { - const [ - liquidityHubDisabled, - toggleLiquidityHubDisabled, - ] = useLiquidityHubManager(); - const { t } = useTranslation(); - - const isSupported = useIsLiquidityHubSupported(); - if (!isSupported) return null; - - return ( - <> - - -

{t('disableLiquidityHub')}

-

- - - {t('liquidityHub')} - - , {t('poweredBy').toLowerCase()}{' '} - - Orbs - - , {t('aboutLiquidityHub')}{' '} - - {t('forMoreInfo')} - -

-
- -
- - - ); -}; - -export const LiquidityHubConfirmationModalContent = ({ - txPending, -}: { - txPending?: boolean; -}) => { - const { t } = useTranslation(); - const liquidityHubState = useLiquidityHubState(); - - if (!liquidityHubState?.isWon || txPending) { - return null; - } - return ( - - {t('using')}{' '} - - {t('liquidityHub')} - {' '} - {t('by')}{' '} - - Orbs - - - - ); -}; - -// styles -const StyledLiquidityHubTrade = styled('p')({ - '& a': { - textDecoration: 'none', - display: 'inline-flex', - gap: 5, - fontWeight: 600, - color: 'white', - '&:hover': { - textDecoration: 'underline', - }, - }, - '& span': { - textTransform: 'capitalize', - fontSize: 'inherit', - }, - '& img': { - width: 22, - height: 22, - objectFit: 'contain', - }, -}); - -const StyledLiquidityHubTxSettings = styled(Box)({ - display: 'flex', - flexDirection: 'column', - '& .bottom-text': { - maxWidth: 500, - fontSize: 14, - lineHeight: '23px', - '& img': { - width: 22, - height: 22, - marginRight: 8, - position: 'relative', - top: 6, - }, - '& a': { - textDecoration: 'none', - fontWeight: 600, - color: '#6381e9', - '&:hover': { - textDecoration: 'underline', - }, - }, - '& .more-info': { - color: 'inherit', - fontWeight: 400, - textDecoration: 'underline', - }, - }, -}); - -// types - -type actionState = 'pending' | 'success' | 'failed' | 'null' | ''; - -interface LiquidityHubAnalyticsData { - _id: string; - partner: string; - chainId: number; - isForceClob: boolean; - firstFailureSessionId?: string; - sessionId?: string; - walletAddress: string; - dexAmountOut: string; - isClobTrade: boolean; - srcTokenAddress: string; - srcTokenSymbol: string; - dstTokenAddress: string; - dstTokenSymbol: string; - srcAmount: string; - quoteIndex: number; - slippage: number; - 'quote-1-state': actionState; - 'quote-2-state': string; - clobDexPriceDiffPercent: string; - - approvalState: actionState; - approvalError: string; - approvalMillis: number | null; - - signatureState: actionState; - signatureMillis: number | null; - signature: string; - signatureError: string; - - swapState: actionState; - txHash: string; - swapMillis: number | null; - swapError: string; - - wrapState: actionState; - wrapMillis: number | null; - wrapError: string; - wrapTxHash: string; - - dexSwapState: actionState; - dexSwapError: string; - dexSwapTxHash: string; - - userWasApprovedBeforeTheTrade?: boolean | string; - dstAmountOutUsd: number; - isProMode: boolean; - expertMode: boolean; - tradeType?: TradeType | null; - isNotClobTradeReason: string; - onChainClobSwapState: actionState; - version: number; - isDexTrade: boolean; - onChainDexSwapState: actionState; - dexOutAmountWS?: string; - walletConnectName?: string; - isRabby?: boolean; - isMetaMask?: boolean; - isCoinbaseWallet?: boolean; - isWalletConnect?: boolean; - isTrustWallet?: boolean; - isOkxWallet?: boolean; -} - -interface QuoteResponse { - outAmount: string; - permitData: any; - serializedOrder: string; - callData: string; - rawData: any; -} - -type QuoteArgs = { - minDestAmount: string; - inAmount: string; - inToken: string; - outToken: string; -}; - -enum LiquidityHubControl { - FORCE = '1', - SKIP = '2', -} - -const handleV3Token = (currency: CoreCurrency | undefined, value?: string) => { - if (!currency) { - return { - symbol: '', - address: '', - value: '', - }; - } - - return { - symbol: currency.isNative ? 'MATIC' : currency.wrapped.symbol, - address: currency.isNative ? ZERO_ADDRESS : currency.wrapped.address, - decimals: currency.decimals, - value: parseUnits( - getFixedValue(value || '0', currency.decimals), - currency.decimals, - ).toString(), - }; -}; - -export const useV3TradeTypeAnalyticsCallback = ( - currencies: { - INPUT?: CoreCurrency | undefined; - OUTPUT?: CoreCurrency | undefined; - }, - allowedSlippage: Percent, -) => { - const { account, chainId } = useActiveWeb3React(); - const outTokenUSD = useUSDCPriceFromAddress( - currencies[Field.OUTPUT]?.wrapped.address || '', - ).price; - - const srcTokenCurrency = currencies[Field.INPUT]; - const dstTokenCurrency = currencies[Field.OUTPUT]; - - return useCallback( - (formattedAmounts: { [x: string]: any; [x: number]: any }) => { - try { - const srcToken = handleV3Token( - srcTokenCurrency, - formattedAmounts[Field.INPUT], - ); - - const dstToken = handleV3Token( - dstTokenCurrency, - formattedAmounts[Field.OUTPUT], - ); - liquidityHubAnalytics.onV3Trade({ - srcTokenAddress: srcToken.address, - dstTokenAddress: dstToken.address, - dstTokenSymbol: dstToken.symbol, - srcTokenSymbol: srcToken.symbol, - srcAmount: srcToken.value, - dexAmountOut: dstToken.value, - dstTokenUsdValue: - outTokenUSD * Number(formattedAmounts[Field.OUTPUT]), - walletAddress: account || '', - slippage: Number(allowedSlippage.toFixed()), - chainId, - }); - } catch (error) {} - }, - [ - srcTokenCurrency, - dstTokenCurrency, - outTokenUSD, - account, - allowedSlippage, - chainId, - ], - ); -}; - -export const useV2TradeTypeAnalyticsCallback = ( - currencies: { - INPUT?: Currency | undefined; - OUTPUT?: Currency | undefined; - }, - allowedSlippage: number, -) => { - const { account, chainId } = useActiveWeb3React(); - - const srcTokenCurrency = currencies[Field.INPUT]; - const dstTokenCurrency = currencies[Field.OUTPUT]; - const inToken = wrappedCurrency(srcTokenCurrency, chainId); - const outToken = wrappedCurrency(dstTokenCurrency, chainId); - const outTokenUSD = useUSDCPriceFromAddress(outToken?.address).price; - - return useCallback( - (trade?: Trade) => { - try { - liquidityHubAnalytics.onV2Trade({ - srcTokenAddress: inToken?.address, - dstTokenAddress: outToken?.address, - srcTokenSymbol: inToken?.symbol, - dstTokenSymbol: outToken?.symbol, - srcAmount: trade?.inputAmount.raw.toString(), - dexAmountOut: trade?.outputAmount.raw.toString(), - dstTokenUsdValue: outTokenUSD * Number(trade?.outputAmount.toExact()), - walletAddress: account || '', - slippage: allowedSlippage / 100, - chainId, - }); - } catch (error) {} - }, - [account, inToken, outToken, outTokenUSD, allowedSlippage, chainId], - ); -}; - -async function signEIP712(signer: string, data: any) { - const typedDataMessage = _TypedDataEncoder.getPayload( - data.domain, - data.types, - data.values, - ); - - try { - return await signAsync('eth_signTypedData_v4', signer, typedDataMessage); - } catch (e) { - try { - return await signAsync('eth_signTypedData', signer, typedDataMessage); - } catch (e) { - throw e; - } - } -} - -async function signAsync( - method: 'eth_signTypedData_v4' | 'eth_signTypedData', - signer: string, - payload: any, -) { - const provider: any = (web3().currentProvider as any).send - ? web3().currentProvider - : (web3() as any)._provider; - return await new Promise((resolve, reject) => { - provider.send( - { - id: 1, - method, - params: [ - signer, - typeof payload === 'string' ? payload : JSON.stringify(payload), - ], - from: signer, - }, - (e: any, r: any) => { - if (e || !r?.result) return reject(e); - return resolve(r.result); - }, - ); - }); -} diff --git a/src/components/Swap/LowSrcAmountWarning.tsx b/src/components/Swap/LowSrcAmountWarning.tsx new file mode 100644 index 000000000..36f398693 --- /dev/null +++ b/src/components/Swap/LowSrcAmountWarning.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { Typography, styled } from '@material-ui/core'; +import { WarningOutlined } from '@material-ui/icons'; + +export function LowSrcAmountWarning() { + return ( + + Trade size must be at least 100$ + + ); +} + +const StyledWarning = styled(Typography)(({ theme }) => ({ + fontSize: '12px', + marginTop: '20px', + color: theme.palette.error.main, + '& .MuiSvgIcon-root': { + width: 12, + height: 12, + position: 'relative', + top: '-1px', + }, +})); diff --git a/src/components/Swap/Swap.tsx b/src/components/Swap/Swap.tsx index d1d56cd5f..512fe123e 100644 --- a/src/components/Swap/Swap.tsx +++ b/src/components/Swap/Swap.tsx @@ -67,7 +67,6 @@ import { getConfig } from 'config/index'; import { wrappedCurrency } from 'utils/wrappedCurrency'; import { useUSDCPriceFromAddress } from 'utils/useUSDCPrice'; import { V2_ROUTER_ADDRESS } from 'constants/v3/addresses'; -import { useV2TradeTypeAnalyticsCallback } from './LiquidityHub'; import { SLIPPAGE_AUTO } from 'state/user/reducer'; import { useWalletInfo } from '@web3modal/ethers5/react'; import { useAppDispatch } from 'state'; @@ -532,15 +531,9 @@ const Swap: React.FC<{ fromTokenWrapped?.address ?? '', ); - const onV2TradeAnalytics = useV2TradeTypeAnalyticsCallback( - currencies, - allowedSlippage, - ); - const { walletInfo } = useWalletInfo(); const handleSwap = useCallback(() => { - onV2TradeAnalytics(trade); if ( priceImpactWithoutFee && !confirmPriceImpactWithoutFee(priceImpactWithoutFee, t) @@ -636,7 +629,6 @@ const Swap: React.FC<{ }); }); }, [ - onV2TradeAnalytics, trade, priceImpactWithoutFee, t, diff --git a/src/components/Swap/SwapBestTrade.tsx b/src/components/Swap/SwapBestTrade.tsx index fc7273626..9ef71201c 100644 --- a/src/components/Swap/SwapBestTrade.tsx +++ b/src/components/Swap/SwapBestTrade.tsx @@ -87,6 +87,20 @@ import { useWalletInfo } from '@web3modal/ethers5/react'; import { useAppDispatch } from 'state'; import { updateUserBalance } from 'state/balance/actions'; +import { LowSrcAmountWarning } from './LowSrcAmountWarning'; +import { + useIsLiquidityHubTrade, +} from './orbs/LiquidityHub/hooks'; +import { useLiquidityHubQuote } from './orbs/LiquidityHub/hooks'; +import { LiquidityHubSwapConfirmation } from './orbs/LiquidityHub/LiquidityHubSwapConfirmation/LiquidityHubSwapConfirmation'; +import { LiquidityHubSwapDetails } from './orbs/LiquidityHub/LiquidityHubSwapDetails'; +import { isLowInAmountError } from './orbs/utils'; + +export const useIsliquidityHubOnly = () => { + const { chainId } = useActiveWeb3React(); + return useMemo(() => [ChainId.ETHEREUM].includes(chainId), [chainId]); +}; + const SwapBestTrade: React.FC<{ currencyBgClass?: string; }> = ({ currencyBgClass }) => { @@ -95,6 +109,8 @@ const SwapBestTrade: React.FC<{ const isProMode = useIsProMode(); const isSupportedNetwork = useIsSupportedNetwork(); const { walletInfo } = useWalletInfo(); + const [liquidityHubDisabled, setLiquidityHubDisabled] = useState(false); + const [showLiquidityHubConfirm, setShowLiquidityHubConfirm] = useState(false); // token warning stuff // const [loadedInputCurrency, loadedOutputCurrency] = [ @@ -136,6 +152,8 @@ const SwapBestTrade: React.FC<{ const { account, chainId, library } = useActiveWeb3React(); const { independentField, typedValue, recipient } = useSwapState(); const chainIdToUse = chainId ? chainId : ChainId.MATIC; + const isLiquidityHubOnly = useIsliquidityHubOnly(); + const { currencyBalances, parsedAmount, @@ -410,7 +428,9 @@ const SwapBestTrade: React.FC<{ ], queryFn: fetchOptimalRate, refetchInterval: 5000, + enabled: !isLiquidityHubOnly, }); + const optimalRate = useMemo(() => { if (!optimalRateData) return; @@ -422,7 +442,35 @@ const SwapBestTrade: React.FC<{ return optimalRateData.error; }, [optimalRateData]); - const isValid = !swapInputError && !optimalRateError && !!optimalRate; + const liquidityHubQuoteQuery = useLiquidityHubQuote( + allowedSlippage, + parsedAmount?.toExact(), + currencies[Field.INPUT], + currencies[Field.OUTPUT], + optimalRate?.destAmount, + liquidityHubDisabled, + ); + + const { + data: liquidityHubQuote, + isLoading: liquidityHubQuoteLoading, + error: liquidityHubQuoteError, + } = liquidityHubQuoteQuery; + + const tradeSrcAmount = isLiquidityHubOnly + ? liquidityHubQuote?.inAmount + : optimalRate?.srcAmount; + const tradeDestAmount = isLiquidityHubOnly + ? liquidityHubQuote?.outAmount + : optimalRate?.destAmount; + + const loadingTrade = isLiquidityHubOnly + ? liquidityHubQuoteLoading + : loadingOptimalRate; + + const isValid = isLiquidityHubOnly + ? !liquidityHubQuoteError && !!liquidityHubQuote + : !optimalRateError && !!optimalRate; const parsedAmounts = useMemo(() => { const parsedAmountInput = @@ -443,19 +491,19 @@ const SwapBestTrade: React.FC<{ [Field.INPUT]: independentField === Field.INPUT ? parsedAmountInput - : optimalRate && inputCurrencyV3 + : tradeSrcAmount && inputCurrencyV3 ? CurrencyAmount.fromRawAmount( inputCurrencyV3, - JSBI.BigInt(optimalRate.srcAmount), + JSBI.BigInt(tradeSrcAmount), ) : undefined, [Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmountOutput - : optimalRate && outputCurrencyV3 + : tradeDestAmount && outputCurrencyV3 ? CurrencyAmount.fromRawAmount( outputCurrencyV3, - JSBI.BigInt(optimalRate.destAmount), + JSBI.BigInt(tradeDestAmount), ) : undefined, }; @@ -466,7 +514,8 @@ const SwapBestTrade: React.FC<{ showWrap, showNativeConvert, independentField, - optimalRate, + tradeSrcAmount, + tradeDestAmount, ]); const maxAmountInputV2 = maxAmountSpend( @@ -522,7 +571,7 @@ const SwapBestTrade: React.FC<{ maxAmountInput && parsedAmounts[Field.INPUT]?.equalTo(maxAmountInput), ); - const [approval, approveCallback] = useApproveCallbackFromBestTrade( + const [_approval, approveCallback] = useApproveCallbackFromBestTrade( pct, inputCurrencyV3, optimalRate, @@ -530,12 +579,17 @@ const SwapBestTrade: React.FC<{ atMaxAmountInput, ); + const approval = isLiquidityHubOnly ? ApprovalState.APPROVED : _approval; + const [ nativeConvertApproval, nativeConvertApproveCallback, ] = useApproveCallback(parsedAmount, NATIVE_CONVERTER[chainId]); + const isLiquidityHubTrade = true + const showApproveFlow = + !isLiquidityHubOnly && !swapInputError && !showWrap && (showNativeConvert @@ -569,7 +623,7 @@ const SwapBestTrade: React.FC<{ const { callback: paraswapCallback, - error: paraswapCallbackError, + error: _paraswapCallbackError, } = useParaswapCallback( allowedSlippage, optimalRate, @@ -577,10 +631,21 @@ const SwapBestTrade: React.FC<{ inputCurrency, outputCurrency, ); + const isLowSrcAmountError = + isLiquidityHubOnly && isLowInAmountError(liquidityHubQuoteError); + + const paraswapCallbackError = isLiquidityHubOnly + ? undefined + : _paraswapCallbackError; + + const noRoute = isLiquidityHubOnly + ? !liquidityHubQuote?.outAmount + : !optimalRate || optimalRate.bestRoute.length < 0; - const noRoute = !optimalRate || optimalRate.bestRoute.length < 0; const swapInputAmountWithSlippage = - optimalRate && inputCurrencyV3 + isLiquidityHubOnly && inputCurrencyV3 && srcAmount + ? CurrencyAmount.fromRawAmount(inputCurrencyV3, srcAmount) + : optimalRate && inputCurrencyV3 ? CurrencyAmount.fromRawAmount( inputCurrencyV3, (optimalRate.side === SwapSide.BUY @@ -628,7 +693,7 @@ const SwapBestTrade: React.FC<{ : wrapType === WrapType.UNWRAPPING ? t('unwrappingMATIC', { symbol: WETH[chainId].symbol }) : ''; - } else if (loadingOptimalRate) { + } else if (loadingTrade) { return t('loading'); } else if ( optimalRateError === 'ESTIMATED_LOSS_GREATER_THAN_MAX_IMPACT' @@ -640,6 +705,8 @@ const SwapBestTrade: React.FC<{ : optimalRateError; } else if (swapInputError) { return swapInputError; + } else if (isLowSrcAmountError) { + return t('swap'); } else if (noRoute && userHasSpecifiedInputOutput) { return t('insufficientLiquidityTrade'); } else if ( @@ -666,7 +733,7 @@ const SwapBestTrade: React.FC<{ formattedAmounts, showNativeConvert, showWrap, - loadingOptimalRate, + loadingTrade, optimalRateError, swapInputError, noRoute, @@ -680,27 +747,29 @@ const SwapBestTrade: React.FC<{ wrapInputError, wrapType, maxImpactAllowed, + isLowSrcAmountError, ]); + const maxImpactReached = isLiquidityHubOnly + ? false + : optimalRate?.maxImpactReached; + const swapButtonDisabled = useMemo(() => { const isSwapError = (inputCurrencyV3 && inputCurrencyV3.isToken && approval === ApprovalState.UNKNOWN) || !isValid || - (optimalRate && optimalRate.maxImpactReached && !isExpertMode) || + (maxImpactReached && !isExpertMode) || !!paraswapCallbackError || - (optimalRate && - !parsedAmounts[Field.INPUT]?.equalTo( - JSBI.BigInt(optimalRate.srcAmount), - )) || - (optimalRate && - !parsedAmounts[Field.OUTPUT]?.equalTo( - JSBI.BigInt(optimalRate.destAmount), - )) || + (tradeSrcAmount && + !parsedAmounts[Field.INPUT]?.equalTo(JSBI.BigInt(tradeSrcAmount))) || + (tradeDestAmount && + !parsedAmounts[Field.OUTPUT]?.equalTo(JSBI.BigInt(tradeDestAmount))) || (swapInputAmountWithSlippage && swapInputBalance && swapInputAmountWithSlippage.greaterThan(swapInputBalance)); + if (account) { if (!isSupportedNetwork) return false; else if (showNativeConvert) { @@ -719,12 +788,15 @@ const SwapBestTrade: React.FC<{ return ( !isValid || approval !== ApprovalState.APPROVED || - (optimalRate && optimalRate.maxImpactReached && !isExpertMode) || + (maxImpactReached && !isExpertMode) || isSwapError ); } else { return isSwapError; } + } + if (isLowSrcAmountError) { + return true; } else { return false; } @@ -732,7 +804,6 @@ const SwapBestTrade: React.FC<{ inputCurrencyV3, approval, isValid, - optimalRate, isExpertMode, paraswapCallbackError, parsedAmounts, @@ -749,6 +820,10 @@ const SwapBestTrade: React.FC<{ convertType, wrapInputError, wrapType, + tradeSrcAmount, + tradeDestAmount, + maxImpactReached, + isLowSrcAmountError, ]); const [ @@ -792,6 +867,7 @@ const SwapBestTrade: React.FC<{ [onUserInput], ); + const handleAcceptChanges = useCallback(() => { setSwapState({ tradeToConfirm: undefined, @@ -962,6 +1038,16 @@ const SwapBestTrade: React.FC<{ handleParaswap, ]); + const onSubmitSwap = useCallback(() => { + if (isLiquidityHubTrade) { + setShowLiquidityHubConfirm(true); + } else { + onParaswap(); + } + }, [onParaswap, isLiquidityHubTrade]); + + + const paraRate = optimalRate ? (Number(optimalRate.destAmount) * 10 ** optimalRate.srcDecimals) / (Number(optimalRate.srcAmount) * 10 ** optimalRate.destDecimals) @@ -1124,6 +1210,16 @@ const SwapBestTrade: React.FC<{ }, [optimalRateNotExisting]); const [currentTime, setCurrentTime] = useState(Math.floor(Date.now() / 1000)); + const onLiquidityHubSwapFailed = useCallback( + () => setLiquidityHubDisabled(true), + [], + ); + const onLiquidityHubSwapSuccess = useCallback(() => handleTypeInput(''), []); + + const handleLiquidityHubConfirmDismiss = useCallback(() => { + setShowLiquidityHubConfirm(false); + }, []); + return ( + {showConfirm && ( {!showNativeConvert && !showWrap && isExpertMode && ( @@ -1237,6 +1345,19 @@ const SwapBestTrade: React.FC<{ )} )} + {isLiquidityHubOnly ? ( + + ) : ( + + )} + {isLowSrcAmountError && } {showApproveFlow && ( @@ -1253,6 +1374,7 @@ const SwapBestTrade: React.FC<{ approvalSubmitted } onClick={async () => { + setLiquidityHubDisabled(true); if (showNativeConvert) { setNativeConvertApproving(true); try { @@ -1294,7 +1416,9 @@ const SwapBestTrade: React.FC<{ : bonusRouteLoading || optimalRateError) || swapButtonDisabled) as boolean } - onClick={account && isSupportedNetwork ? onParaswap : connectWallet} + onClick={ + account && isSupportedNetwork ? onSubmitSwap : connectWallet + } > {swapButtonText} diff --git a/src/components/Swap/orbs/ConfirmationModal.tsx b/src/components/Swap/orbs/ConfirmationModal.tsx new file mode 100644 index 000000000..84cddbb6d --- /dev/null +++ b/src/components/Swap/orbs/ConfirmationModal.tsx @@ -0,0 +1,307 @@ +import React, { + createContext, + ReactNode, + useCallback, + useContext, + useMemo, + useState, +} from 'react'; +import { Box, Button } from '@material-ui/core'; +import { useTranslation } from 'react-i18next'; +import TransactionFailed from 'assets/images/TransactionFailed.png'; +import TransactionSubmitted from 'assets/images/TransactionSubmitted.png'; +import ModalBg from 'assets/images/ModalBG.svg'; +import { Currency, ETHER, WETH } from '@uniswap/sdk'; +import { useActiveWeb3React } from 'hooks'; +import { SwapFlow, SwapStatus, SwapStep } from '@orbs-network/swap-ui'; +import { ReactComponent as CloseIcon } from 'assets/images/CloseIcon.svg'; +import { formatNumber, getEtherscanLink } from 'utils'; +import useWrapCallback, { WrapType } from './hooks/useWrapCallback'; +import { Steps } from './types'; +import 'components/styles/orbs/ConfirmationModal.scss'; +import CustomModal from 'components/CustomModal'; +import { useGetLogoCallback } from './hooks'; + +const Context = createContext({} as ContextValues); + +interface ContextProps extends ContextValues { + children: React.ReactNode; +} + +export const useConfirmationContext = () => { + return useContext(Context); +}; + +export const ConfirmationProvider = (props: ContextProps) => { + return {props.children}; +}; + +interface SharedProps { + inCurrency?: Currency; + outCurrency?: Currency; + isOpen: boolean; + onDismiss: () => void; + swapStatus?: SwapStatus; + inAmount?: string; + outAmount?: string; +} + +interface ContextValues extends SharedProps { + currentStep?: number; + steps?: SwapStep[]; +} + +interface Props extends SharedProps { + errorContent?: React.ReactNode; + mainContent?: React.ReactNode; + successContent?: React.ReactNode; +} + +export const ConfirmationModal = (props: Props) => { + return ( + + + + ); +}; + +const Content = ({ + mainContent, + errorContent, + successContent, +}: { + mainContent: React.ReactNode; + errorContent: React.ReactNode; + successContent: React.ReactNode; +}) => { + const { isOpen, onDismiss, inAmount, outAmount } = useConfirmationContext(); + const getLogo = useGetLogoCallback(); + const { inCurrency, outCurrency, swapStatus } = useConfirmationContext(); + + const inToken = useMemo(() => { + return { + symbol: inCurrency?.symbol, + logo: getLogo(inCurrency), + }; + }, [inCurrency, getLogo]); + + const outToken = useMemo(() => { + return { + symbol: outCurrency?.symbol, + logo: getLogo(outCurrency), + }; + }, [outCurrency, getLogo]); + + return ( + + Modal Back + + + ); +}; + +export function ConfirmationContainer({ + title, + children, + className = '', +}: { + title?: string; + children: ReactNode; + className?: string; +}) { + const { onDismiss } = useConfirmationContext(); + return ( + + +
{title}
+ +
+ + {children} + +
+ ); +} + +export const Error = ({ + shouldUnwrap, + error, +}: { + shouldUnwrap?: boolean; + error?: string; +}) => { + const { onDismiss, inAmount } = useConfirmationContext(); + const { t } = useTranslation(); + const { chainId } = useActiveWeb3React(); + const nativeSymbol = ETHER[chainId].symbol; + + const { execute, wrapType } = useWrapCallback( + WETH[chainId], + ETHER[chainId], + inAmount, + ); + const [success, setSuccess] = useState(false); + const isLoading = wrapType === WrapType.UNWRAPPING; + const unwrap = useCallback(async () => { + try { + await execute?.(); + setSuccess(true); + } catch (error) { + console.error(error); + } + }, [execute]); + + if (success) { + return ( + + {t('successfullyUnwrappedMATIC', { + symbol: `${formatNumber(inAmount, 3)} ${nativeSymbol}`, + })} +

+ } + /> + ); + } + + if (isLoading) { + return ( + + {t('unwrappingMATIC', { symbol: nativeSymbol })}

} + /> +
+ ); + } + + return ( + + + Transaction Failed + {error &&

Transaction Failed

} +
+ {shouldUnwrap ? ( + + + + + ) : ( + <> + + + )} +
+ ); +}; + +export const Main = ({ + steps = [], + swapDetails, + swapButton, + currentStep, + inUsd, + outUsd, + inTitle, + outTitle, +}: { + steps?: SwapStep[]; + swapDetails: ReactNode; + swapButton: ReactNode; + currentStep?: Steps; + inUsd?: string; + outUsd?: string; + inTitle?: string; + outTitle?: string; +}) => { + const { swapStatus } = useConfirmationContext(); + const { t } = useTranslation(); + + return ( + + + {!swapStatus && ( + <> + {swapDetails} + {swapButton} + + )} + + ); +}; + +export const Success = ({ + txHash, + content, +}: { + txHash?: string; + content: ReactNode; +}) => { + const { t } = useTranslation(); + const { chainId } = useActiveWeb3React(); + const { onDismiss } = useConfirmationContext(); + + return ( + + Transaction Submitted + {content} +
+ {chainId && txHash && ( + + + + )} + +
+
+ ); +}; + +ConfirmationModal.Main = Main; +ConfirmationModal.Error = Error; +ConfirmationModal.Success = Success; diff --git a/src/components/Swap/orbs/LiquidityHub/LiquidityHubSettings.tsx b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSettings.tsx new file mode 100644 index 000000000..24de8d128 --- /dev/null +++ b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSettings.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import { useLiquidityHubManager } from 'state/user/hooks'; +import { styled } from '@material-ui/styles'; +import { Box, Divider } from '@material-ui/core'; +import OrbsLogo from 'assets/images/orbs-logo.svg'; +import { useTranslation } from 'react-i18next'; +import ToggleSwitch from 'components/ToggleSwitch'; +import { _TypedDataEncoder } from 'ethers/lib/utils'; +import { useIsLiquidityHubSupported } from './hooks'; +import { LIQUIDITY_HUB_WEBSITE, ORBS_WEBSITE } from '../consts'; + +export const LiquidityHubSettings = () => { + const [ + liquidityHubDisabled, + toggleLiquidityHubDisabled, + ] = useLiquidityHubManager(); + const { t } = useTranslation(); + + const isSupported = useIsLiquidityHubSupported(); + if (!isSupported) return null; + + return ( + <> + + +

{t('disableLiquidityHub')}

+

+ + + {t('liquidityHub')} + + , {t('poweredBy').toLowerCase()}{' '} + + Orbs + + , {t('aboutLiquidityHub')}{' '} + + {t('forMoreInfo')} + +

+
+ +
+ + + ); +}; + +const Container = styled(Box)({ + display: 'flex', + flexDirection: 'column', + '& .bottom-text': { + maxWidth: 500, + fontSize: 14, + lineHeight: '23px', + '& img': { + width: 22, + height: 22, + marginRight: 8, + display: 'inline', + }, + '& a': { + textDecoration: 'none', + fontWeight: 600, + color: '#6381e9', + '&:hover': { + textDecoration: 'underline', + }, + }, + '& .more-info': { + color: 'inherit', + fontWeight: 400, + textDecoration: 'underline', + }, + }, +}); diff --git a/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/LiquidityHubSwapConfirmation.tsx b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/LiquidityHubSwapConfirmation.tsx new file mode 100644 index 000000000..28c295c81 --- /dev/null +++ b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/LiquidityHubSwapConfirmation.tsx @@ -0,0 +1,205 @@ +import React, { useMemo } from 'react'; +import OrbsLogo from 'assets/images/orbs-logo.svg'; +import { useTranslation } from 'react-i18next'; +import { Box, Button, styled } from '@material-ui/core'; +import { formatCurrencyAmount } from 'utils/v3/formatCurrencyAmount'; +import { useLiquidityHubSwapCallback } from './useLiquidityHubSwapCallback'; +import { ContextProvider, useLiquidityHubConfirmationContext } from './context'; +import CheckCircleIcon from '@material-ui/icons/CheckCircle'; +import SwapVerticalCircleIcon from '@material-ui/icons/SwapVerticalCircle'; +import { LiquidityHubConfirmationProps, Steps } from '../../types'; +import { useGetLogoCallback } from '../../hooks'; +import { useLiquidityHubApproval } from '../useLiquidityHubApproval'; +import { + LIQUIDITY_HUB_WEBSITE, + ORBS_WEBSITE, + SIGNATURE_TIMEOUT, + SWAP_COUNTDOWN, +} from '../../consts'; +import { ConfirmationModal } from '../../ConfirmationModal'; +import useUSDCPrice from 'utils/useUSDCPrice'; + +export const useSteps = () => { + const { + inCurrency, + store: { signature, steps }, + } = useLiquidityHubConfirmationContext(); + const getLogo = useGetLogoCallback(); + + return useMemo(() => { + return steps?.map((step) => { + if (step === Steps.WRAP) { + return { + title: `Wrap ${inCurrency?.symbol}`, + icon: , + id: Steps.WRAP, + }; + } + if (step === Steps.APPROVE) { + return { + title: `Approve ${inCurrency?.symbol} spending`, + icon: , + id: Steps.APPROVE, + }; + } + + return { + id: Steps.SWAP, + title: !signature ? 'Confirm swap' : 'Swap pending...', + icon: , + timeout: !signature ? SIGNATURE_TIMEOUT : SWAP_COUNTDOWN, + }; + }); + }, [inCurrency, signature, steps, getLogo]); +}; + +const SuccessContent = () => { + const { + store: { txHash }, + } = useLiquidityHubConfirmationContext(); + const { t } = useTranslation(); + return ( + + {t('swapSuccess')} + {t(' using')}{' '} + + {t('liquidityHub')} + {' '} + {t('by')}{' '} + + Orbs + + + + } + /> + ); +}; + +const SwapButton = () => { + const { t } = useTranslation(); + const { mutate: swap } = useLiquidityHubSwapCallback(); + const { isPending } = useLiquidityHubApproval(); + + return ( + + + + + + ); +}; + +const SwapDetails = () => { + const { t } = useTranslation(); + const { minAmountOut } = useLiquidityHubConfirmationContext(); + + return ( + +

+ {t('outputEstimated1', { + amount: formatCurrencyAmount(minAmountOut, 4), + symbol: minAmountOut?.currency?.symbol, + })} +

+
+ ); +}; + +const MainContent = () => { + const steps = useSteps(); + const { + store: { currentStep }, + inAmount, + inCurrency, + outAmount, + outCurrency, + } = useLiquidityHubConfirmationContext(); + const inUsd = + Number(useUSDCPrice(inCurrency)?.toSignificant() ?? 0) * + Number(inAmount?.toExact() || 0); + const outUsd = + Number(useUSDCPrice(outCurrency)?.toSignificant() ?? 0) * + Number(outAmount?.toExact() || 0); + + return ( + } + swapDetails={} + currentStep={currentStep} + inUsd={inUsd.toLocaleString('en')} + outUsd={outUsd.toLocaleString('en')} + /> + ); +}; + +const ErrorContent = () => { + const { + store: { shouldUnwrap, error }, + } = useLiquidityHubConfirmationContext(); + return ; +}; + +export function Content() { + const { + inCurrency, + outCurrency, + isOpen, + onDismiss, + inAmount, + outAmount, + store: { swapStatus }, + } = useLiquidityHubConfirmationContext(); + return ( + } + mainContent={} + errorContent={} + /> + ); +} + +export const LiquidityHubSwapConfirmation = ( + props: LiquidityHubConfirmationProps, +) => { + return ( + + + + ); +}; + +const StyledSuccess = styled('p')({ + '& a': { + textDecoration: 'none', + display: 'inline-flex', + gap: 5, + fontWeight: 600, + color: 'white', + '&:hover': { + textDecoration: 'underline', + }, + }, + '& span': { + textTransform: 'capitalize', + fontSize: 'inherit', + }, + '& img': { + width: 22, + height: 22, + objectFit: 'contain', + }, +}); diff --git a/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/context.tsx b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/context.tsx new file mode 100644 index 000000000..3a134448d --- /dev/null +++ b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/context.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { createContext, useCallback } from 'react'; +import { CurrencyAmount, Currency } from '@uniswap/sdk-core'; +import { + LiquidityHubConfirmationProps, + LiquidityHubConfirmationState, +} from '../../types'; +import { fromRawAmount } from '../../utils'; +import { useConfirmationStore } from '../../hooks'; + +interface ContextValues extends LiquidityHubConfirmationProps { + inAmount?: CurrencyAmount; + outAmount?: CurrencyAmount; + minAmountOut?: CurrencyAmount; + store: LiquidityHubConfirmationState; + updateStore: (payload: Partial) => void; + resetStore: () => void; +} +const Context = createContext({} as ContextValues); + +interface ContextProps extends LiquidityHubConfirmationProps { + children: React.ReactNode; +} + +export const ContextProvider = ({ children, ...props }: ContextProps) => { + const { updateStore, store, resetStore } = useConfirmationStore< + LiquidityHubConfirmationState + >({} as LiquidityHubConfirmationState); + const quote = store.acceptedQuote || props.quoteQuery.data; + const onDismiss = useCallback(() => { + setTimeout(() => { + resetStore(); + }, 5_00); + props.onDismiss(); + }, [props, resetStore]); + + return ( + + {children} + + ); +}; + +export const useLiquidityHubConfirmationContext = () => { + return React.useContext(Context); +}; diff --git a/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/useLiquidityHubSwapCallback.ts b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/useLiquidityHubSwapCallback.ts new file mode 100644 index 000000000..f9dfd9bcb --- /dev/null +++ b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapConfirmation/useLiquidityHubSwapCallback.ts @@ -0,0 +1,339 @@ +import { useMutation } from '@tanstack/react-query'; +import { useAppDispatch } from 'state'; +import { updateUserBalance } from 'state/balance/actions'; +import { useCallback, useRef } from 'react'; +import { useLiquidityHubConfirmationContext } from './context'; +import { Steps } from '../../types'; +import { Token, WETH } from '@uniswap/sdk'; +import { useActiveWeb3React } from 'hooks'; +import { + getDexMinAmountOut, + isRejectedError, + isTimeoutError, + promiseWithTimeout, +} from '../../utils'; +import { OptimalRate, TransactionParams } from '@paraswap/sdk'; +import { useParaswap } from 'hooks/useParaswap'; +import { wrappedCurrency } from 'utils/wrappedCurrency'; +import { useLiquidityHubApproval } from '../useLiquidityHubApproval'; +import { useIsNativeCurrencyCallback } from '../../hooks'; +import { SIGNATURE_TIMEOUT } from '../../consts'; +import useWrapCallback from '../../hooks/useWrapCallback'; +import { SwapStatus } from '@orbs-network/swap-ui'; +import { _TypedDataEncoder } from 'ethers/lib/utils'; +import { useLiquidityHub } from '../hooks'; +import { Quote } from '@orbs-network/liquidity-hub-sdk'; + +const useGetStepsCallback = () => { + const { inCurrency } = useLiquidityHubConfirmationContext(); + const isNativeIn = useIsNativeCurrencyCallback(); + const { isApproved } = useLiquidityHubApproval(); + + return useCallback(() => { + const steps: Steps[] = []; + + if (isNativeIn(inCurrency)) { + steps.push(Steps.WRAP); + } + if (!isApproved) { + steps.push(Steps.APPROVE); + } + steps.push(Steps.SWAP); + return steps; + }, [inCurrency, isApproved, isNativeIn]); +}; + +const useWrapFlowCallback = () => { + const { inCurrency, inAmount } = useLiquidityHubConfirmationContext(); + const { chainId } = useActiveWeb3React(); + const liquidityHub = useLiquidityHub(); + const { execute: wrap } = useWrapCallback( + inCurrency, + WETH[chainId], + inAmount?.toExact(), + ); + + return useCallback(async () => { + try { + liquidityHub.analytics.onWrapRequest(); + await wrap?.(); + liquidityHub.analytics.onWrapSuccess(); + } catch (error) { + liquidityHub.analytics.onWrapFailed(error); + throw error; + } + }, [wrap]); +}; + +const useApproveCallback = () => { + const { approve } = useLiquidityHubApproval(); + const liquidityHub = useLiquidityHub(); + + return useCallback(async () => { + try { + liquidityHub.analytics.onApprovalRequest(); + await approve(); + liquidityHub.analytics.onApprovalSuccess(); + } catch (error) { + liquidityHub.analytics.onApprovalFailed(error); + throw error; + } + }, [approve]); +}; + +const useSwapCallback = () => { + const liquidityHub = useLiquidityHub(); + return useCallback( + async ({ + acceptedQuote, + signature, + paraswapTxParams, + }: { + acceptedQuote: Quote; + signature: string; + paraswapTxParams?: TransactionParams; + }) => { + const txHash = await liquidityHub.swap(acceptedQuote, signature, { + data: paraswapTxParams?.data || '', + to: paraswapTxParams?.to, + }); + const details = await liquidityHub.getTransactionDetails( + txHash, + acceptedQuote!, + ); + return { + txHash, + ...details, + }; + }, + [liquidityHub], + ); +}; + +export const useLiquidityHubSwapCallback = () => { + const { chainId, account } = useActiveWeb3React(); + const { + updateStore, + onSwapSuccess, + resetStore, + onSwapFailed, + optimalRate, + allowedSlippage, + inCurrency, + outCurrency, + quoteQuery, + } = useLiquidityHubConfirmationContext(); + const dispatch = useAppDispatch(); + const wrappedNative = useRef(false); + const signCallback = useSignEIP712Callback(); + const getParaswapTxParams = useParaswapTxParamsCallback(); + const getSteps = useGetStepsCallback(); + const { ensureQueryData } = quoteQuery; + const swapCallback = useSwapCallback(); + + const wrapCallback = useWrapFlowCallback(); + const approvalCallback = useApproveCallback(); + + return useMutation( + async () => { + const inToken = wrappedCurrency(inCurrency, chainId); + const outToken = wrappedCurrency(outCurrency, chainId); + if (!account) { + throw new Error('Account is not defined'); + } + if (!inToken) { + throw new Error('In token is not defined'); + } + if (!outToken) { + throw new Error('Out token is not defined'); + } + const steps = getSteps(); + updateStore({ + swapStatus: SwapStatus.LOADING, + steps, + }); + if (steps.includes(Steps.WRAP)) { + updateStore({ + currentStep: Steps.WRAP, + }); + await wrapCallback(); + wrappedNative.current = true; + } + if (steps.includes(Steps.APPROVE)) { + updateStore({ currentStep: Steps.APPROVE }); + await approvalCallback(); + // refetch approval + } + + const acceptedQuote = await ensureQueryData(); + + updateStore({ currentStep: Steps.SWAP, acceptedQuote }); + + const signature = await promiseWithTimeout( + signCallback(acceptedQuote.permitData), + SIGNATURE_TIMEOUT, + ); + + updateStore({ signature }); + let paraswapTxParams: TransactionParams | undefined; + if (optimalRate && allowedSlippage) { + try { + paraswapTxParams = await getParaswapTxParams({ + inToken, + optimalRate, + allowedSlippage, + chainId, + account, + }); + } catch (error) {} + } + return swapCallback({ + acceptedQuote, + signature, + paraswapTxParams, + }); + }, + { + onSuccess: () => { + onSwapSuccess?.(); + updateStore({ swapStatus: SwapStatus.SUCCESS }); + dispatch(updateUserBalance()); + }, + onError: (error) => { + const isRejectedOrTimeout = + isRejectedError(error) || isTimeoutError(error); + + if (!wrappedNative.current && isRejectedOrTimeout) { + resetStore(); + } else { + updateStore({ + shouldUnwrap: wrappedNative.current, + swapStatus: SwapStatus.FAILED, + error: (error as any).message, + }); + onSwapFailed?.(); + } + }, + onSettled: () => { + wrappedNative.current = false; + }, + }, + ); +}; + +const useParaswapTxParamsCallback = () => { + const paraswap = useParaswap(); + + return useCallback( + (args: { + inToken: Token; + optimalRate?: OptimalRate; + allowedSlippage?: number; + account: string; + chainId: number; + }) => { + if (!args.optimalRate) { + throw new Error('Optimal rate is not defined'); + } + return paraswap.buildTx({ + srcToken: args.inToken?.address, + destToken: args.optimalRate.destToken, + srcAmount: args.optimalRate.srcAmount, + destAmount: getDexMinAmountOut( + args.allowedSlippage || 0, + args.optimalRate.destAmount, + )!, + priceRoute: args.optimalRate, + userAddress: args.account, + receiver: args.account, + partner: 'quickswapv3', + }); + }, + [paraswap], + ); +}; + +export const useSignEIP712Callback = () => { + const { library, account } = useActiveWeb3React(); + const liquidityHub = useLiquidityHub(); + + return useCallback( + async (permitData: any) => { + liquidityHub.analytics.onSignatureRequest(); + if (!library || !account) { + throw new Error('No library or account'); + } + try { + const signature = await signEIP712( + account, + library.provider, + permitData, + ); + if (!signature) { + throw new Error('No signature'); + } + liquidityHub.analytics.onSignatureSuccess(signature); + return signature; + } catch (error) { + liquidityHub.analytics.onSignatureFailed((error as Error).message); + throw error; + } + }, + [account, library, liquidityHub], + ); +}; + +async function signEIP712(signer: string, provider: any, permitData: any) { + const populated = await _TypedDataEncoder.resolveNames( + permitData.domain, + permitData.types, + permitData.values, + async (name: string) => name, + ); + + const message = JSON.stringify( + _TypedDataEncoder.getPayload( + populated.domain, + permitData.types, + populated.value, + ), + ); + + try { + return await signAsync(signer, provider, 'eth_signTypedData_v4', message); + } catch (e) { + if (isRejectedError(e)) { + throw e; + } + try { + return await signAsync(signer, provider, 'eth_signTypedData', message); + } catch (error) { + if ( + typeof error.message === 'string' && + (error.message.match(/not (found|implemented)/i) || + error.message.match(/TrustWalletConnect.WCError error 1/) || + error.message.match(/Missing or invalid/)) + ) { + throw new Error('Wallet does not support EIP-712'); + } else { + throw error; + } + } + } +} + +async function signAsync( + signer: string, + provider: any, + method: 'eth_signTypedData_v4' | 'eth_signTypedData', + message: string, +) { + try { + return await provider?.request({ + method, + params: [signer, message], + }); + } catch (error) { + throw error; + } +} diff --git a/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapDetails.tsx b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapDetails.tsx new file mode 100644 index 000000000..605572603 --- /dev/null +++ b/src/components/Swap/orbs/LiquidityHub/LiquidityHubSwapDetails.tsx @@ -0,0 +1,203 @@ +import React from 'react'; +import { Box } from '@material-ui/core'; +import { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ReactComponent as PriceExchangeIcon } from 'assets/images/PriceExchangeIcon.svg'; +import { ReactComponent as EditIcon } from 'assets/images/EditIcon.svg'; +import { useUserSlippageTolerance } from 'state/user/hooks'; +import QuestionHelper from 'components/QuestionHelper'; +import { FormattedPriceImpact } from 'components/ConfirmSwapModal'; +import SettingsModal from 'components/SettingsModal'; +import { SLIPPAGE_AUTO } from 'state/user/reducer'; +import CurrencyLogo from 'components/CurrencyLogo'; +import { Quote } from '@orbs-network/liquidity-hub-sdk'; +import { useDerivedSwapInfo } from 'state/swap/hooks'; +import { useParseRawAmount } from './hooks'; +import useUSDCPrice from 'utils/useUSDCPrice'; +import BN from 'bignumber.js'; +import { Field } from 'state/swap/actions'; +import { JSBI, Percent } from '@uniswap/sdk'; +import { fromRawAmount } from '../utils'; +const SwapPrice = ({ quote }: { quote: Quote | null }) => { + const { t } = useTranslation(); + const { parsedAmount, currencies } = useDerivedSwapInfo(); + const inCurrency = currencies.INPUT; + const outCurrency = currencies.OUTPUT; + const parsedOutAmount = useParseRawAmount(outCurrency, quote?.outAmount); + + const [inverted, setInverted] = useState(false); + const price = useMemo(() => { + if (!parsedOutAmount || !parsedAmount) return ''; + + const priceFor1Token = + Number(parsedOutAmount.toExact()) / Number(parsedAmount?.toExact()); + const price = inverted + ? 1 / Number(priceFor1Token) + : Number(priceFor1Token); + return price.toLocaleString('us'); + }, [inverted, parsedAmount?.toExact(), parsedOutAmount?.toExact()]); + + const toggleInverted = useCallback(() => { + setInverted((prev) => !prev); + }, []); + + return ( + + {t('price')}: + + 1 {inverted ? outCurrency?.symbol : inCurrency?.symbol} = {price}{' '} + {inverted ? inCurrency?.symbol : outCurrency?.symbol}{' '} + + + + ); +}; + +export const LiquidityHubSwapDetails = ({ + quote, + allowedSlippage, +}: { + quote?: Quote | null; + allowedSlippage: number; +}) => { + if (!quote) return null; + + return ( + + + + + + + + + + ); +}; + +export const usePriceImpact = (quote: Quote, allowedSlippage: number) => { + const { currencies, parsedAmount } = useDerivedSwapInfo(); + const inAmount = parsedAmount?.toExact() ?? '0'; + const inCurrency = currencies.INPUT; + const outCurrency = currencies.OUTPUT; + const parsedOutAmount = useParseRawAmount( + outCurrency, + quote?.outAmount, + )?.raw.toString(); + const outAmount = useMemo(() => { + if (!parsedOutAmount || !outCurrency || !quote.gasAmountOut) return '0'; + const result = BN(parsedOutAmount) + .plus(quote.gasAmountOut) + .toString(); + return fromRawAmount(outCurrency, result)?.toExact() || '0'; + }, [parsedOutAmount, outCurrency, quote.gasAmountOut]); + + const srcUSD = + Number(useUSDCPrice(inCurrency)?.toSignificant() ?? 0) * Number(inAmount); + const dstUSD = + Number(useUSDCPrice(outCurrency)?.toSignificant() ?? 0) * Number(outAmount); + + return useMemo(() => { + if (!srcUSD || !dstUSD || !inAmount || !outAmount) return new Percent('0'); + const _srcUSD = JSBI.BigInt( + BN(srcUSD) + .multipliedBy(10 ** 10) + .toFixed(0), + ); + const _dstUSD = JSBI.BigInt( + BN(dstUSD) + .multipliedBy(10 ** 10) + .toFixed(0), + ); + const priceChange = JSBI.subtract(_srcUSD, _dstUSD); + return new Percent(priceChange, _srcUSD); + }, [srcUSD, dstUSD, inAmount, outAmount]); +}; + +const PriceImpact = ({ + quote, + allowedSlippage, +}: { + quote: Quote; + allowedSlippage: number; +}) => { + const { t } = useTranslation(); + const priceImpact = usePriceImpact(quote, allowedSlippage); + return ( + + + {t('priceimpact')}: + + + + + ); +}; + +const Slippage = () => { + const [open, setOpen] = useState(false); + const { t } = useTranslation(); + const [userSlippage] = useUserSlippageTolerance(); + + return ( + <> + {open && setOpen(false)} />} + + + {t('maxSlippage')}: + + + setOpen(true)} className='swapSlippage'> + {userSlippage === SLIPPAGE_AUTO ? 0.5 : userSlippage}% + + + + + ); +}; + +const NetworkFee = ({ quote }: { quote: Quote }) => { + const { currencies } = useDerivedSwapInfo(); + const outCurrency = currencies.OUTPUT; + const fee = useParseRawAmount(outCurrency, quote?.gasAmountOut)?.toExact(); + const usd = + Number(useUSDCPrice(outCurrency)?.toSignificant() ?? 0) * Number(fee || 0); + + const { t } = useTranslation(); + return ( + + + {t('Network fee')}: + + + {usd ? ${usd.toLocaleString('us')} : -} + + + ); +}; + +const MinReceived = ({ quote }: { quote: Quote }) => { + const { currencies } = useDerivedSwapInfo(); + const outCurrency = currencies[Field.OUTPUT]; + const parsedMinAmountOut = useParseRawAmount( + outCurrency, + quote?.minAmountOut, + ); + + const { t } = useTranslation(); + return ( + + + {t('minReceived')}: + + + + + {Number(parsedMinAmountOut?.toExact()).toLocaleString('us')}{' '} + {outCurrency?.symbol} + + + + + ); +}; diff --git a/src/components/Swap/orbs/LiquidityHub/hooks.ts b/src/components/Swap/orbs/LiquidityHub/hooks.ts new file mode 100644 index 000000000..0443d7f31 --- /dev/null +++ b/src/components/Swap/orbs/LiquidityHub/hooks.ts @@ -0,0 +1,198 @@ +import { + ChainId, + Currency, + CurrencyAmount, + JSBI, + Token, + TokenAmount, +} from '@uniswap/sdk'; +import { useActiveWeb3React } from 'hooks'; +import { useCallback, useMemo } from 'react'; +import { tryParseAmount } from 'state/swap/hooks'; +import { getConfig } from 'config'; +import { wrappedCurrency } from 'utils/wrappedCurrency'; +import { + constructSDK, + Quote, + QUOTE_ERRORS, + zeroAddress, +} from '@orbs-network/liquidity-hub-sdk'; +import { OptimalRate, SwapSide } from '@paraswap/sdk'; +import { useLiquidityHubManager } from 'state/user/hooks'; +import { useIsNativeCurrencyCallback } from '../hooks'; +import { getDexMinAmountOut, isLiquidityHubTrade } from '../utils'; +import { _TypedDataEncoder } from 'ethers/lib/utils'; +import useWrapCallback, { WrapType } from 'hooks/useWrapCallback'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; + +export const useLiquidityHub = () => { + const { chainId } = useActiveWeb3React(); + const chainIdToUse = chainId || ChainId.MATIC; + + return useMemo( + () => constructSDK({ chainId: chainIdToUse, partner: 'quickswap' }), + [chainIdToUse], + ); +}; + +export const useParseRawAmount = (currency?: Currency, amount?: string) => { + const { chainId } = useActiveWeb3React(); + return useMemo(() => { + if (!currency || !amount) return undefined; + return currency instanceof Token + ? new TokenAmount(currency, JSBI.BigInt(amount)) + : CurrencyAmount.ether(JSBI.BigInt(amount), chainId); + }, [chainId, amount, currency]); +}; + +export const useIsLiquidityHubTrade = ( + swapSide: SwapSide, + disabled: boolean, + allowedSlippage: number, + quote?: Quote | null, + optimalRate?: OptimalRate, + showWrap?: boolean, + isLiquidityHubOnly?: boolean, +) => { + const [liquidityHubDisabled] = useLiquidityHubManager(); + const isSupported = useIsLiquidityHubSupported(); + + return useMemo(() => { + if (showWrap) return false; + if (isLiquidityHubOnly) return true; + if (localStorage.getItem('force-lh')) return true; + + if ( + swapSide === SwapSide.BUY || + liquidityHubDisabled || + disabled || + !isSupported + ) { + return false; + } + + return isLiquidityHubTrade(allowedSlippage, quote, optimalRate); + }, [ + allowedSlippage, + quote, + optimalRate, + isSupported, + swapSide, + disabled, + liquidityHubDisabled, + isLiquidityHubOnly, + showWrap, + ]); +}; + +export const useIsLiquidityHubSupported = () => { + const { chainId } = useActiveWeb3React(); + const config = getConfig(chainId); + return !!config['swap']['liquidityHub']; +}; + +const isLowSrcAmountError = (error: any) => { + return (error as Error)?.message === QUOTE_ERRORS.ldv; +}; + +export const useLiquidityHubQuote = ( + allowedSlippage?: number, + typedAmount?: string, + inCurrency?: Currency, + outCurrency?: Currency, + dexOutAmount?: string, + disabled?: boolean, +) => { + const { account, chainId } = useActiveWeb3React(); + const inputCurrencyAmount = tryParseAmount(chainId, typedAmount, inCurrency); + const inAmount = inputCurrencyAmount?.raw.toString(); + const isNativeCurrency = useIsNativeCurrencyCallback(); + + const fromToken = wrappedCurrency(inCurrency, chainId)?.address; + const toToken = useMemo(() => { + if (!outCurrency) return; + return isNativeCurrency(outCurrency) + ? zeroAddress + : wrappedCurrency(outCurrency, chainId)?.address; + }, [outCurrency, isNativeCurrency, chainId]); + const queryClient = useQueryClient(); + const isSupported = useIsLiquidityHubSupported(); + const liquidityHub = useLiquidityHub(); + + const dexMinAmountOut = useMemo(() => { + return getDexMinAmountOut(allowedSlippage || 0, dexOutAmount); + }, [dexOutAmount, allowedSlippage]); + + const { wrapType } = useWrapCallback(inCurrency, outCurrency, typedAmount); + + const queryKey = [ + 'liquidity-hub-quote', + fromToken, + toToken, + inAmount, + allowedSlippage, + chainId, + ]; + + const fecthQuoteCallback = useCallback( + (signal?: AbortSignal) => { + return liquidityHub.getQuote({ + fromToken: fromToken!, + toToken: toToken!, + inAmount: inAmount!, + dexMinAmountOut, + account, + slippage: allowedSlippage! / 100, + signal, + }); + }, + [ + liquidityHub, + fromToken, + toToken, + inAmount, + dexMinAmountOut, + account, + allowedSlippage, + queryKey, + ], + ); + + const query = useQuery({ + queryKey, + queryFn: async ({ signal }) => { + return fecthQuoteCallback(signal); + }, + retry(failureCount, error) { + if (isLowSrcAmountError(error)) return false; + if (failureCount > 3) return false; + return true; + }, + refetchInterval: (data, query) => { + if (isLowSrcAmountError(query.state.fetchFailureReason)) return 0; + return 10_000; + }, + staleTime: Infinity, + enabled: + !!account && + !!inAmount && + !!fromToken && + !!toToken && + wrapType !== WrapType.WRAP && + wrapType !== WrapType.UNWRAP && + !disabled && + allowedSlippage !== undefined && + isSupported, + }); + + return useMemo(() => { + return { + ...query, + ensureQueryData: () => + queryClient.ensureQueryData({ + queryKey, + queryFn: ({ signal }) => fecthQuoteCallback(signal), + }), + }; + }, [query, queryClient, fecthQuoteCallback, queryKey]); +}; diff --git a/src/components/Swap/orbs/LiquidityHub/useLiquidityHubApproval.ts b/src/components/Swap/orbs/LiquidityHub/useLiquidityHubApproval.ts new file mode 100644 index 000000000..614d30b51 --- /dev/null +++ b/src/components/Swap/orbs/LiquidityHub/useLiquidityHubApproval.ts @@ -0,0 +1,12 @@ +import { permit2Address } from '@orbs-network/liquidity-hub-sdk'; +import { useApproval } from '../hooks'; +import { useLiquidityHubConfirmationContext } from './LiquidityHubSwapConfirmation/context'; + +export const useLiquidityHubApproval = () => { + const { inCurrency, inAmount } = useLiquidityHubConfirmationContext(); + return useApproval( + permit2Address, + inCurrency, + inAmount?.numerator.toString(), + ); +}; diff --git a/src/components/Swap/orbs/Twap/LimitPanel.tsx b/src/components/Swap/orbs/Twap/LimitPanel.tsx new file mode 100644 index 000000000..5975542c0 --- /dev/null +++ b/src/components/Swap/orbs/Twap/LimitPanel.tsx @@ -0,0 +1,212 @@ +import { Box } from '@material-ui/core'; +import React, { useCallback, useMemo } from 'react'; +import { useTwapState, useTwapSwapActionHandlers } from 'state/swap/twap/hooks'; +import { Card, SelectorButton } from './components'; +import NumericalInput from 'components/NumericalInput'; +import { Currency } from '@uniswap/sdk'; +import CurrencySelect from 'components/CurrencySelect'; +import { useActiveWeb3React, useIsProMode } from 'hooks'; +import useSwapRedirects from 'hooks/useSwapRedirect'; +import { fromRawAmount } from '../utils'; +import { useTwapContext } from './context'; +import CloseIcon from '@material-ui/icons/Close'; +import { tryParseAmount } from 'state/swap/hooks'; +import CurrencyLogo from 'components/CurrencyLogo'; +import SwapVertIcon from '@material-ui/icons/SwapVert'; +import { useTranslation } from 'react-i18next'; +const useInvertedAmount = (amount?: string) => { + const { chainId } = useActiveWeb3React(); + const { currencies } = useTwapContext(); + return useMemo(() => { + if (!amount || !currencies.OUTPUT) return; + const result = ( + 10 ** currencies.OUTPUT.decimals / + Number(amount) + ).toString(); + return tryParseAmount(chainId, result, currencies.OUTPUT); + }, [chainId, currencies.OUTPUT, amount]); +}; + +export function LimitInputPanel() { + const { redirectWithCurrency } = useSwapRedirects(); + const { onInvertLimitPrice } = useTwapSwapActionHandlers(); + const { currencies } = useTwapContext(); + const { isLimitPriceInverted } = useTwapState(); + const handleCurrencySelect = (currency: Currency) => { + redirectWithCurrency(currency, isLimitPriceInverted ? true : false); + }; + + const inCurrency = isLimitPriceInverted + ? currencies.OUTPUT + : currencies.INPUT; + const outCurrency = isLimitPriceInverted + ? currencies.INPUT + : currencies.OUTPUT; + + return ( + + + + When 1 {' '} + {outCurrency?.symbol} is worth + + + + + + + + + + ); +} + +const LimitPriceInput = () => { + const isProMode = useIsProMode(); + const { marketPrice, currencies } = useTwapContext(); + const { typedLimitPrice, isLimitPriceInverted } = useTwapState(); + const { onLimitPriceInput } = useTwapSwapActionHandlers(); + const invertedMarketPrice = useInvertedAmount(marketPrice); + + const value = useMemo(() => { + if (typedLimitPrice !== undefined) { + return typedLimitPrice; + } + if (isLimitPriceInverted) { + return invertedMarketPrice?.toExact(); + } + return fromRawAmount(currencies.OUTPUT, marketPrice)?.toExact(); + }, [ + typedLimitPrice, + marketPrice, + currencies.OUTPUT, + isLimitPriceInverted, + invertedMarketPrice?.toExact(), + ]); + + return ( + { + onLimitPriceInput(val); + }} + /> + ); +}; + +function useCalculatePercentageDiff() { + const context = useTwapContext(); + const { isLimitPriceInverted } = useTwapState(); + return useMemo(() => { + if (!context.marketPrice || !context.limitPrice) return 0; + const marketPrice = Number(context.marketPrice); + const limitPrice = Number(context.limitPrice); + + if (marketPrice === 0) return 0; + const diff = marketPrice - limitPrice; + let percentageDiff = (diff * 100) / marketPrice; + if (!isLimitPriceInverted) { + percentageDiff = -percentageDiff; + } + return parseFloat(percentageDiff.toFixed(2)); + }, [context.marketPrice, context.limitPrice, isLimitPriceInverted]); +} + +const PercentButtons = () => { + const { + swapData: {}, + marketPrice, + currencies, + } = useTwapContext(); + const { isLimitPriceInverted, limitPercent } = useTwapState(); + const { onLimitPriceInput } = useTwapSwapActionHandlers(); + const invertedAmount = useInvertedAmount(marketPrice); + + const onPercent = useCallback( + (percentage: number) => { + if (!marketPrice || !currencies.OUTPUT) return; + + const price = isLimitPriceInverted + ? invertedAmount?.toExact() + : fromRawAmount(currencies.OUTPUT, marketPrice)?.toExact(); + if (!price) return; + const adjustment = percentage / 100; + + const newLimitPrice = (Number(price) * (1 + adjustment)).toString(); + onLimitPriceInput(newLimitPrice.toString() || '', percentage); + }, + [marketPrice, currencies, onLimitPriceInput, isLimitPriceInverted], + ); + + return ( + + + {isLimitPriceInverted + ? [-1, -5, -10] + : [1, 5, 10].map((percent) => { + return ( + onPercent(percent)} + > + {isLimitPriceInverted ? '' : '+'} + {percent}% + + ); + })} + + ); +}; + +const ResetButton = () => { + const { onLimitPriceInput } = useTwapSwapActionHandlers(); + const priceDiff = useCalculatePercentageDiff(); + const { limitPercent, typedLimitPrice } = useTwapState(); + const { t } = useTranslation(); + const { isLimitPanel } = useTwapContext(); + const showPercent = priceDiff && !limitPercent; + + if (!showPercent) { + return ( + onLimitPriceInput(undefined)} + selected={Number(priceDiff) === 0 && typedLimitPrice !== ''} + > + {isLimitPanel ? '0%' : t('market')} + + ); + } + + return ( + + onLimitPriceInput(undefined)} + selected={true} + > + {Number(priceDiff) > 0 ? '+' : ''} + {priceDiff}% + + onLimitPriceInput(undefined)} + selected={true} + > + + + + ); +}; diff --git a/src/components/Swap/orbs/Twap/OrderDetails.tsx b/src/components/Swap/orbs/Twap/OrderDetails.tsx new file mode 100644 index 000000000..2ec4be4e5 --- /dev/null +++ b/src/components/Swap/orbs/Twap/OrderDetails.tsx @@ -0,0 +1,249 @@ +import { Box, Typography } from '@material-ui/core'; +import { getSrcChunkAmount } from '@orbs-network/twap-sdk'; +import { Currency } from '@uniswap/sdk'; +import QuestionHelper from 'components/QuestionHelper'; +import { useActiveWeb3React } from 'hooks'; +import React, { ReactNode, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { formatDateFromTimeStamp, formatNumber, getEtherscanLink } from 'utils'; +import { formatCurrencyAmount } from 'utils/v3/formatCurrencyAmount'; +import { fromRawAmount, makeElipsisAddress } from '../utils'; + +const ELIPSIS_PADDING = 5; + +const FillDelayAsText = ({ fillDelay }: { fillDelay?: number }) => { + const { t } = useTranslation(); + const text = useMemo(() => { + if (!fillDelay) return; + + const days = Math.floor(fillDelay / (1000 * 60 * 60 * 24)); + const hours = Math.floor( + (fillDelay % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60), + ); + const minutes = Math.floor((fillDelay % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((fillDelay % (1000 * 60)) / 1000); + + const arr: string[] = []; + + if (days) { + arr.push(`${days} ${t('days')} `); + } + if (hours) { + arr.push(`${hours} ${t('hours')} `); + } + if (minutes) { + arr.push(`${minutes} ${t('minutes')}`); + } + if (seconds) { + arr.push(`${seconds} ${t('seconds')}`); + } + + return arr.join(' '); + }, [fillDelay, t]); + + return <>{text}; +}; + +const FillDelay = ({ + fillDelay, + totalChunks, +}: { + fillDelay?: number; + totalChunks?: number; +}) => { + const { t } = useTranslation(); + + if (totalChunks === 1) return null; + + return ( + } + /> + ); +}; + +const Recipient = () => { + const { account, chainId } = useActiveWeb3React(); + const { t } = useTranslation(); + if (!account) return null; + + return ( + + {makeElipsisAddress(account, ELIPSIS_PADDING)} + + } + /> + ); +}; + +const Chunks = ({ totalChunks }: { totalChunks?: number }) => { + const { t } = useTranslation(); + if (totalChunks === 1) return null; + + return ( + + ); +}; + +const ChunkSize = ({ + srcAmount, + totalChunks, + inCurrency, +}: { + srcAmount?: string; + totalChunks?: number; + inCurrency?: Currency; +}) => { + const { t } = useTranslation(); + + const amount = useMemo(() => { + return fromRawAmount(inCurrency, getSrcChunkAmount(srcAmount, totalChunks)); + }, [srcAmount, totalChunks, inCurrency]); + + if (totalChunks === 1) return null; + + return ( + + ); +}; + +const SrcAmount = ({ + srcAmount, + currency, +}: { + srcAmount?: string; + currency?: Currency; +}) => { + const { t } = useTranslation(); + const amount = fromRawAmount(currency, srcAmount); + return ( + + ); +}; + +const MinReceived = ({ + isMarketOrder, + dstMinAmount, + currency, +}: { + isMarketOrder?: boolean; + dstMinAmount?: string; + currency?: Currency; +}) => { + const { t } = useTranslation(); + const amount = fromRawAmount(currency, dstMinAmount); + if (isMarketOrder) return null; + + return ( + + ); +}; + +const Deadline = ({ deadline }: { deadline?: number }) => { + const { t } = useTranslation(); + + if (!deadline) return null; + + return ( + + ); +}; + +const Price = ({ + price, + isMarketOrder, + inCurrency, + outCurrency, + usd, +}: { + price?: string; + isMarketOrder?: boolean; + inCurrency?: Currency; + outCurrency?: Currency; + usd?: number; +}) => { + const { t } = useTranslation(); + + return ( + + 1 {inCurrency?.symbol} = {formatNumber(price, 3)}{' '} + {outCurrency?.symbol}{' '} + {`($${usd?.toLocaleString('en')})`} + + ) + } + /> + ); +}; + +const OrderDetails = ({ children }: { children: ReactNode }) => { + return {children}; +}; + +export const TwapOrderDetailsRow = ({ + label, + value, + tooltip, +}: { + label: string; + value?: ReactNode; + tooltip?: string; +}) => { + return ( + + + {label} + {tooltip && } + + + {value || '-'} + + + ); +}; + +OrderDetails.Price = Price; +OrderDetails.Deadline = Deadline; +OrderDetails.SrcAmount = SrcAmount; +OrderDetails.MinReceived = MinReceived; +OrderDetails.ChunkSize = ChunkSize; +OrderDetails.Chunks = Chunks; +OrderDetails.Recipient = Recipient; +OrderDetails.FillDelay = FillDelay; +OrderDetails.DetailsRow = TwapOrderDetailsRow; + +export { OrderDetails }; diff --git a/src/components/Swap/orbs/Twap/Twap.tsx b/src/components/Swap/orbs/Twap/Twap.tsx new file mode 100644 index 000000000..c3a953d48 --- /dev/null +++ b/src/components/Swap/orbs/Twap/Twap.tsx @@ -0,0 +1,634 @@ +import React, { useState, useMemo, useCallback, useEffect } from 'react'; +import { + JSBI, + Token, + currencyEquals, + ETHER, + Fraction, + ChainId, + WETH, +} from '@uniswap/sdk'; +import { Currency, CurrencyAmount, NativeCurrency } from '@uniswap/sdk-core'; +import { Box, Button } from '@material-ui/core'; +import { + useExpertModeManager, + useUserSlippageTolerance, +} from 'state/user/hooks'; +import { Field } from 'state/swap/actions'; +import { useHistory } from 'react-router-dom'; +import { CurrencyInput } from 'components'; +import { useActiveWeb3React, useConnectWallet, useIsProMode } from 'hooks'; +import useWrapCallback, { WrapType } from 'hooks/useWrapCallback'; +import { + useIsSupportedNetwork, + maxAmountSpend, + basisPointsToPercent, + halfAmountSpend, +} from 'utils'; +import { ReactComponent as ExchangeIcon } from 'assets/images/ExchangeIcon.svg'; +import 'components/styles/Swap.scss'; +import { useTranslation } from 'react-i18next'; +import { SwapSide } from '@paraswap/sdk'; +import { useAllTokens, useCurrency } from 'hooks/Tokens'; +import TokenWarningModal from 'components/v3/TokenWarningModal'; +import useParsedQueryString from 'hooks/useParsedQueryString'; +import useSwapRedirects from 'hooks/useSwapRedirect'; +import { ONE } from 'v3lib/utils'; +import useNativeConvertCallback, { + ConvertType, +} from 'hooks/useNativeConvertCallback'; +import { useTwapSwapWarning } from './hooks'; +import { + useDefaultsFromURLSearch, + useTwapState, + useTwapSwapActionHandlers, +} from 'state/swap/twap/hooks'; +import { TwapContextProvider, useTwapContext } from './context'; +import { TwapSwapConfirmation } from './TwapSwapConfirmation/TwapSwapConfirmation'; +import { ChunksSelect, DurationSelect, FillDelaySelect, InputsContainer, LimitPriceWarning } from './components'; +import { LimitInputPanel } from './LimitPanel'; +import { TwapOrders } from './TwapOrders/TwapOrders'; +import 'components/styles/orbs/Twap.scss'; + + +const Content: React.FC<{ + currencyBgClass?: string; +}> = ({ currencyBgClass }) => { + const history = useHistory(); + const isProMode = useIsProMode(); + const isSupportedNetwork = useIsSupportedNetwork(); + const loadedUrlParams = useDefaultsFromURLSearch(); + + const [dismissTokenWarning, setDismissTokenWarning] = useState( + false, + ); + + const handleConfirmTokenWarning = useCallback(() => { + setDismissTokenWarning(true); + }, []); + + // reset if they close warning without tokens in params + const handleDismissTokenWarning = useCallback(() => { + setDismissTokenWarning(true); + history.push('/swap'); + }, [history]); + + // dismiss warning if all imported tokens are in active lists + const defaultTokens = useAllTokens(); + const [showConfirm, setShowConfirm] = useState(false); + + const { t } = useTranslation(); + const { account, chainId } = useActiveWeb3React(); + const { typedValue } = useTwapState(); + const chainIdToUse = chainId ? chainId : ChainId.MATIC; + const independentField = Field.INPUT; + + const { + currencyBalances, + parsedAmount, + currencies, + inputError: swapInputError, + maxImpactAllowed, + optimalRate, + tradeDestAmount, + loadingOptimalRate, + optimalRateError, + isLimitPanel, + } = useTwapContext(); + + const [isExpertMode] = useExpertModeManager(); + const { + wrapType, + execute: onWrap, + inputError: wrapInputError, + } = useWrapCallback( + currencies[Field.INPUT], + currencies[Field.OUTPUT], + typedValue, + ); + + const [swapType, setSwapType] = useState(SwapSide.SELL); + + const showWrap: boolean = wrapType !== WrapType.NOT_APPLICABLE; + + const { onCurrencySelection, onUserInput } = useTwapSwapActionHandlers(); + const [allowedSlippage] = useUserSlippageTolerance(); + + const pct = basisPointsToPercent(allowedSlippage); + + const dependentField = Field.OUTPUT; + const inputCurrency = currencies[Field.INPUT]; + const outputCurrency = currencies[Field.OUTPUT]; + + const inputCurrencyV3 = useMemo(() => { + if (!inputCurrency || !chainId) return; + if (currencyEquals(inputCurrency, ETHER[chainId])) { + return { + ...ETHER[chainId], + isNative: true, + isToken: false, + } as NativeCurrency; + } + return { ...inputCurrency, isNative: false, isToken: true } as Currency; + }, [chainId, inputCurrency]); + + const outputCurrencyV3 = useMemo(() => { + if (!outputCurrency || !chainId) return; + if (currencyEquals(outputCurrency, ETHER[chainId])) + return { + ...ETHER[chainId], + isNative: true, + isToken: false, + } as NativeCurrency; + return { ...outputCurrency, isNative: false, isToken: true } as Currency; + }, [chainId, outputCurrency]); + + const { + convertType, + execute: onConvert, + inputError: convertInputError, + } = useNativeConvertCallback( + inputCurrencyV3?.isToken ? inputCurrencyV3 : undefined, + outputCurrencyV3?.isToken ? outputCurrencyV3 : undefined, + typedValue, + ); + + const showNativeConvert = convertType !== ConvertType.NOT_APPLICABLE; + const { connectWallet } = useConnectWallet(isSupportedNetwork); + + const parsedQs = useParsedQueryString(); + const { redirectWithCurrency, redirectWithSwitch } = useSwapRedirects(); + const parsedCurrency0Id = (parsedQs.currency0 ?? + parsedQs.inputCurrency) as string; + const parsedCurrency1Id = (parsedQs.currency1 ?? + parsedQs.outputCurrency) as string; + + const handleCurrencySelect = useCallback( + (inputCurrency: any) => { + const isSwichRedirect = currencyEquals(inputCurrency, ETHER[chainIdToUse]) + ? parsedCurrency1Id === 'ETH' + : parsedCurrency1Id && + inputCurrency && + inputCurrency.address && + inputCurrency.address.toLowerCase() === + parsedCurrency1Id.toLowerCase(); + if (isSwichRedirect) { + redirectWithSwitch(); + setSwapType(swapType === SwapSide.BUY ? SwapSide.SELL : SwapSide.BUY); + } else { + if (!Boolean(inputCurrency.address in defaultTokens)) { + setDismissTokenWarning(false); + } + redirectWithCurrency(inputCurrency, true); + } + }, + [ + chainIdToUse, + defaultTokens, + parsedCurrency1Id, + redirectWithCurrency, + redirectWithSwitch, + swapType, + ], + ); + + const handleOtherCurrencySelect = useCallback( + (outputCurrency: any) => { + const isSwichRedirect = currencyEquals( + outputCurrency, + ETHER[chainIdToUse], + ) + ? parsedCurrency0Id === 'ETH' + : parsedCurrency0Id && + outputCurrency && + outputCurrency.address && + outputCurrency.address.toLowerCase() === + parsedCurrency0Id.toLowerCase(); + if (isSwichRedirect) { + redirectWithSwitch(); + setSwapType(swapType === SwapSide.BUY ? SwapSide.SELL : SwapSide.BUY); + } else { + if (!Boolean(outputCurrency.address in defaultTokens)) { + setDismissTokenWarning(false); + } + redirectWithCurrency(outputCurrency, false); + } + }, + [ + chainIdToUse, + parsedCurrency0Id, + redirectWithSwitch, + swapType, + redirectWithCurrency, + defaultTokens, + ], + ); + + const parsedCurrency0 = useCurrency(parsedCurrency0Id); + const parsedCurrency1 = useCurrency(parsedCurrency1Id); + const parsedCurrency0Fetched = !!parsedCurrency0; + const parsedCurrency1Fetched = !!parsedCurrency1; + + useEffect(() => { + if (parsedCurrency0 === undefined && !parsedCurrency1Id) { + redirectWithCurrency(ETHER[chainIdToUse], true); + } else { + if (parsedCurrency0) { + onCurrencySelection(Field.INPUT, parsedCurrency0); + } + if (parsedCurrency1) { + onCurrencySelection(Field.OUTPUT, parsedCurrency1); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + parsedCurrency0Id, + parsedCurrency1Id, + parsedCurrency0Fetched, + parsedCurrency1Fetched, + ]); + + const selectedTokens: Token[] = useMemo( + () => + [parsedCurrency0, parsedCurrency1]?.filter( + (c): c is Token => c instanceof Token, + ) ?? [], + [parsedCurrency0, parsedCurrency1], + ); + const selectedTokensNotInDefault = + selectedTokens && + selectedTokens.filter((token: Token) => { + return !Boolean(token.address in defaultTokens); + }); + + const parsedAmounts = useMemo(() => { + const parsedAmountInput = + inputCurrencyV3 && parsedAmount + ? CurrencyAmount.fromRawAmount(inputCurrencyV3, parsedAmount.raw) + : undefined; + const parsedAmountOutput = + outputCurrencyV3 && parsedAmount + ? CurrencyAmount.fromRawAmount(outputCurrencyV3, parsedAmount.raw) + : undefined; + + return showWrap || showNativeConvert + ? { + [Field.INPUT]: parsedAmountInput, + [Field.OUTPUT]: parsedAmountOutput, + } + : { + [Field.INPUT]: parsedAmountInput, + [Field.OUTPUT]: + tradeDestAmount && outputCurrencyV3 + ? CurrencyAmount.fromRawAmount( + outputCurrencyV3, + JSBI.BigInt(tradeDestAmount), + ) + : undefined, + }; + }, [ + inputCurrencyV3, + parsedAmount, + outputCurrencyV3, + showWrap, + showNativeConvert, + independentField, + tradeDestAmount, + ]); + + const maxAmountInputV2 = maxAmountSpend( + chainIdToUse, + currencyBalances[Field.INPUT], + ); + const halfAmountInputV2 = halfAmountSpend( + chainIdToUse, + currencyBalances[Field.INPUT], + ); + const formattedAmounts = useMemo(() => { + return { + [independentField]: typedValue, + [dependentField]: + showWrap || showNativeConvert + ? parsedAmounts[independentField]?.toExact() ?? '' + : parsedAmounts[dependentField]?.toExact() ?? '', + }; + }, [ + independentField, + typedValue, + dependentField, + showWrap, + showNativeConvert, + parsedAmounts, + ]); + + const maxAmountInput = + maxAmountInputV2 && inputCurrencyV3 + ? CurrencyAmount.fromRawAmount(inputCurrencyV3, maxAmountInputV2.raw) + : undefined; + + const halfAmountInput = + halfAmountInputV2 && inputCurrencyV3 + ? CurrencyAmount.fromRawAmount(inputCurrencyV3, halfAmountInputV2.raw) + : undefined; + + const handleMaxInput = useCallback(() => { + maxAmountInput && onUserInput(Field.INPUT, maxAmountInput.toExact()); + setSwapType(SwapSide.SELL); + }, [maxAmountInput, onUserInput]); + + const handleHalfInput = useCallback(() => { + if (!halfAmountInput) { + return; + } + + onUserInput(Field.INPUT, halfAmountInput.toExact()); + setSwapType(SwapSide.SELL); + }, [halfAmountInput, onUserInput]); + + const atMaxAmountInput = Boolean( + maxAmountInput && parsedAmounts[Field.INPUT]?.equalTo(maxAmountInput), + ); + + const userHasSpecifiedInputOutput = Boolean( + currencies[Field.INPUT] && + currencies[Field.OUTPUT] && + parsedAmounts[independentField]?.greaterThan(JSBI.BigInt(0)), + ); + + const noRoute = !optimalRate || optimalRate.bestRoute.length < 0; + const srcAmount = optimalRate?.srcAmount; + const twapSwapWarning = useTwapSwapWarning(); + + const swapInputAmountWithSlippage = + inputCurrencyV3 && srcAmount + ? CurrencyAmount.fromRawAmount(inputCurrencyV3, srcAmount) + : optimalRate && inputCurrencyV3 + ? CurrencyAmount.fromRawAmount( + inputCurrencyV3, + (optimalRate.side === SwapSide.BUY + ? new Fraction(ONE).add(pct) + : new Fraction(ONE) + ).multiply(optimalRate.srcAmount).quotient, + ) + : undefined; + + const swapInputBalanceCurrency = currencyBalances[Field.INPUT]; + + const swapInputBalance = + swapInputBalanceCurrency && inputCurrencyV3 + ? CurrencyAmount.fromRawAmount( + inputCurrencyV3, + swapInputBalanceCurrency.raw.toString(), + ) + : undefined; + + const swapButtonText = useMemo(() => { + if (account) { + if (!isSupportedNetwork) return t('switchNetwork'); + if (!currencies[Field.INPUT] || !currencies[Field.OUTPUT]) { + return t('selectToken'); + } else if ( + formattedAmounts[Field.INPUT] === '' && + formattedAmounts[Field.OUTPUT] === '' + ) { + return t('enterAmount'); + } else if (showNativeConvert) { + if (convertInputError) return convertInputError; + return convertType === ConvertType.CONVERT + ? t('convert') + : convertType === ConvertType.CONVERTING + ? t('converting', { symbol: ETHER[chainId].symbol }) + : ''; + } else if (showWrap) { + if (wrapInputError) return wrapInputError; + return wrapType === WrapType.WRAP + ? t('wrapMATIC', { symbol: ETHER[chainId].symbol }) + : wrapType === WrapType.UNWRAP + ? t('unwrapMATIC', { symbol: WETH[chainId].symbol }) + : wrapType === WrapType.WRAPPING + ? t('wrappingMATIC', { symbol: ETHER[chainId].symbol }) + : wrapType === WrapType.UNWRAPPING + ? t('unwrappingMATIC', { symbol: WETH[chainId].symbol }) + : ''; + } else if (loadingOptimalRate) { + return t('loading'); + } else if ( + optimalRateError === 'ESTIMATED_LOSS_GREATER_THAN_MAX_IMPACT' + ) { + return t('priceImpactReached', { maxImpact: maxImpactAllowed }); + } else if (optimalRateError) { + return optimalRateError.includes(' { + if (swapInputError) { + return true; + } + const isSwapError = + (maxImpactReached && !isExpertMode) || + (tradeSrcAmount && + !parsedAmounts[Field.INPUT]?.equalTo(JSBI.BigInt(tradeSrcAmount))) || + (tradeDestAmount && + !parsedAmounts[Field.OUTPUT]?.equalTo(JSBI.BigInt(tradeDestAmount))) || + (swapInputAmountWithSlippage && + swapInputBalance && + swapInputAmountWithSlippage.greaterThan(swapInputBalance)); + + if (account) { + if (!isSupportedNetwork) return false; + else if (showNativeConvert) { + return ( + Boolean(convertInputError) || convertType === ConvertType.CONVERTING + ); + } else if (showWrap) { + return ( + Boolean(wrapInputError) || + wrapType === WrapType.WRAPPING || + wrapType === WrapType.UNWRAPPING + ); + } else if (noRoute && userHasSpecifiedInputOutput) { + return true; + } else { + return isSwapError || twapSwapWarning; + } + } else { + return false; + } + }, [ + inputCurrencyV3, + isExpertMode, + parsedAmounts, + swapInputAmountWithSlippage, + swapInputBalance, + account, + isSupportedNetwork, + showNativeConvert, + showWrap, + noRoute, + userHasSpecifiedInputOutput, + convertInputError, + convertType, + wrapInputError, + wrapType, + tradeSrcAmount, + tradeDestAmount, + maxImpactReached, + twapSwapWarning, + swapInputError, + ]); + + const handleTypeInput = useCallback( + (value: string) => { + onUserInput(Field.INPUT, value); + setSwapType(SwapSide.SELL); + }, + [onUserInput], + ); + const handleTypeOutput = useCallback( + (value: string) => { + onUserInput(Field.OUTPUT, value); + setSwapType(SwapSide.BUY); + }, + [onUserInput], + ); + + const onSubmitSwap = useCallback(() => { + setShowConfirm(true); + }, []); + return ( + + 0 && !dismissTokenWarning} + tokens={selectedTokensNotInDefault} + onConfirm={handleConfirmTokenWarning} + onDismiss={handleDismissTokenWarning} + /> + + setShowConfirm(false)} + /> + + + + { + setSwapType( + swapType === SwapSide.BUY ? SwapSide.SELL : SwapSide.BUY, + ); + redirectWithSwitch(); + }} + /> + + + + {!isLimitPanel && } + {!isLimitPanel && } + {isLimitPanel && } + + + + + + + + + + + ); +}; + +export const SwapTwap: React.FC<{ + currencyBgClass?: string; + isLimitPanel?: boolean; +}> = ({ isLimitPanel, currencyBgClass }) => { + return ( + + + + ); +}; diff --git a/src/components/Swap/orbs/Twap/TwapOrders/ShowOrdersButton.tsx b/src/components/Swap/orbs/Twap/TwapOrders/ShowOrdersButton.tsx new file mode 100644 index 000000000..f8d80eb44 --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapOrders/ShowOrdersButton.tsx @@ -0,0 +1,33 @@ +import { Box, Typography } from '@material-ui/core'; +import React, { useCallback } from 'react'; +import { useGrouppedTwapOrders } from '../hooks'; +import ArrowForwardIcon from '@material-ui/icons/ArrowForward'; +import { Card } from '../components'; +import { useTwapOrdersContext } from './context'; +import { useTwapState } from 'state/swap/twap/hooks'; + +export const ShowOrdersButton = () => { + const grouped = useGrouppedTwapOrders(); + const { updatingOrders } = useTwapState(); + const { onOpen } = useTwapOrdersContext(); + + const isLoading = updatingOrders || !grouped; + + const onClick = useCallback(() => { + if (isLoading) return; + onOpen(); + }, [isLoading, onOpen]); + + return ( + + <> + {isLoading ? ( + Loading orders... + ) : ( + {grouped?.open?.length || 0} Open Orders + )}{' '} + + + + ); +}; diff --git a/src/components/Swap/orbs/Twap/TwapOrders/TwapOrders.tsx b/src/components/Swap/orbs/Twap/TwapOrders/TwapOrders.tsx new file mode 100644 index 000000000..eb38b7abd --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapOrders/TwapOrders.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { TwapOrdersList } from './TwapOrdersList'; +import { ShowOrdersButton } from './ShowOrdersButton'; +import { TwapOrdersModal } from './TwapOrdersModal'; +import { TwapSelectedOrder } from './TwapSelectedOrder'; +import { TwapOrdersProvider } from './context'; + +export function TwapOrders() { + return ( + + + + + + + + ); +} diff --git a/src/components/Swap/orbs/Twap/TwapOrders/TwapOrdersList.tsx b/src/components/Swap/orbs/Twap/TwapOrders/TwapOrdersList.tsx new file mode 100644 index 000000000..f7a38062c --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapOrders/TwapOrdersList.tsx @@ -0,0 +1,202 @@ +import { Box, Button, Card, LinearProgress, Menu, MenuItem, Typography } from '@material-ui/core'; +import { Close, KeyboardArrowDown } from '@material-ui/icons'; +import { Order, OrderStatus } from '@orbs-network/twap-sdk'; +import CurrencyLogo from 'components/CurrencyLogo'; +import React, { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Virtuoso } from 'react-virtuoso'; +import { formatDateFromTimeStamp } from 'utils'; +import { useGrouppedTwapOrders, useTwapOrderCurrency } from '../hooks'; +import { useTwapOrdersContext } from './context'; +import ArrowForwardIcon from '@material-ui/icons/ArrowForward'; + +export const TwapOrdersList = () => { + const groupedOrders = useGrouppedTwapOrders(); + const { t } = useTranslation(); + const [selectedStatus, setSelectedStatus] = useState(OrderStatus.All); + const { selectedOrderId, onDismiss } = useTwapOrdersContext(); + const Row = useCallback( + ({ data, index, style }: { data: Order[]; index: number; style?: any }) => { + const order = data[index]; + + return ( +
+ +
+ ); + }, + [], + ); + + if (selectedOrderId) return null; + + const orders = groupedOrders?.[selectedStatus] || []; + + return ( + + + + + + {orders.length === 0 ? ( + + ) : ( + Row({ data: orders, index })} + /> + )} + + ); +}; + +const EmptyList = ({ selectedStatus }: { selectedStatus: OrderStatus }) => { + const { t } = useTranslation(); + + return ( + + {' '} + {selectedStatus === OrderStatus.All + ? `No ${t('orders')}` + : `No ${t(selectedStatus)} orders`} + + ); +}; + +const OrderMenu = ({ + selectedStatus, + onSelect, +}: { + selectedStatus: OrderStatus; + onSelect: (status: OrderStatus) => void; +}) => { + const { t } = useTranslation(); + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + + const onOpen = useCallback( + (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }, + [setAnchorEl], + ); + + const handleClose = useCallback(() => { + setAnchorEl(null); + }, [setAnchorEl]); + + const handleMenuItemClick = useCallback( + (value: OrderStatus) => { + handleClose(); + onSelect(value); + }, + [handleClose, onSelect], + ); + + return ( + <> + + + {Object.values(OrderStatus).map((status, index) => { + const selected = selectedStatus === status; + return ( + handleMenuItemClick(status)} + > + {t(status)} + {selected && } + + ); + })} + + + ); +}; + + + +export function TwapOrdersListItem({ order }: { order: Order }) { + const onSelect = useTwapOrdersContext().setSelectedOrderId; + return ( + + onSelect(order.id)} + > +
+ + + + + ); +} + +const Header = ({ order }: { order: Order }) => { + return ( + + + # {order.id} {order.orderType}{' '} + {`(${formatDateFromTimeStamp( + order.createdAt / 1000, + 'MMM DD, YYYY HH:mm', + )})`} + + {order.status} + + ); +}; + +const Progress = ({ order }: { order: Order }) => { + return ( + + + {parseFloat(Number(order.progress).toFixed(2))}% + + ); +}; + +const Currencies = ({ order }: { order: Order }) => { + const inCurrency = useTwapOrderCurrency(order.srcTokenAddress); + const outCurrency = useTwapOrderCurrency(order.dstTokenAddress); + + return ( + + + + {inCurrency?.symbol} + + + + + {outCurrency?.symbol} + + + ); +}; diff --git a/src/components/Swap/orbs/Twap/TwapOrders/TwapOrdersModal.tsx b/src/components/Swap/orbs/Twap/TwapOrders/TwapOrdersModal.tsx new file mode 100644 index 000000000..b35e6b550 --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapOrders/TwapOrdersModal.tsx @@ -0,0 +1,21 @@ +import CustomModal from 'components/CustomModal'; +import React from 'react'; +import { useTwapOrdersContext } from './context'; + +export const TwapOrdersModal = ({ + children, +}: { + children: React.ReactNode; +}) => { + const { isOpen, onDismiss } = useTwapOrdersContext(); + return ( + + {children} + + ); +}; diff --git a/src/components/Swap/orbs/Twap/TwapOrders/TwapSelectedOrder.tsx b/src/components/Swap/orbs/Twap/TwapOrders/TwapSelectedOrder.tsx new file mode 100644 index 000000000..3c23d32d2 --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapOrders/TwapSelectedOrder.tsx @@ -0,0 +1,383 @@ +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Typography, +} from '@material-ui/core'; +import { Close } from '@material-ui/icons'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { + getOrderExcecutionPrice, + getOrderLimitPrice, +} from '@orbs-network/twap-sdk'; +import CurrencyLogo from 'components/CurrencyLogo'; +import { useActiveWeb3React } from 'hooks'; +import React, { ReactNode, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { formatDateFromTimeStamp, formatNumber, getEtherscanLink } from 'utils'; +import { formatCurrencyAmount } from 'utils/v3/formatCurrencyAmount'; +import { fromRawAmount, makeElipsisAddress } from '../../utils'; +import { useTwapOrderCurrency } from '../hooks'; +import { OrderDetails } from '../OrderDetails'; +import { useTwapOrdersContext } from './context'; + +const ELIPSIS_PADDING = 5; + +export function TwapSelectedOrder() { + const { selectedOrderId } = useTwapOrdersContext(); + if (!selectedOrderId) return null; + return ( + +
+ + + + + + ); +} + +const Accordions = () => { + const { t } = useTranslation(); + + return ( + + + + + + + + + + + + + + + + + + + + + + ); +}; + +const Header = () => { + const { t } = useTranslation(); + const { setSelectedOrderId, selectedOrder } = useTwapOrdersContext(); + if (!selectedOrder) return null; + + return ( + + + # {selectedOrder.id} {t(`${selectedOrder.orderType}`)}{' '} + {`(${formatDateFromTimeStamp( + selectedOrder.createdAt / 1000, + 'MMM DD, YYYY HH:mm', + )})`} + + setSelectedOrderId(undefined)} + /> + + ); +}; + +const Currencies = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { t } = useTranslation(); + if (!selectedOrder) return null; + + return ( + + + + + ); +}; + +const CurrenciesCurrency = ({ + label, + address, +}: { + label: string; + address: string; +}) => { + const currency = useTwapOrderCurrency(address); + + return ( + + + + {label} + + + {currency?.symbol} + + + + + ); +}; + +const FillDelay = () => { + const { selectedOrder } = useTwapOrdersContext(); + if (selectedOrder?.totalChunks === 1) return null; + + return ( + + ); +}; + +const TxHash = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { chainId } = useActiveWeb3React(); + const { t } = useTranslation(); + if (!selectedOrder?.txHash) return null; + + return ( + + {makeElipsisAddress(selectedOrder?.txHash, ELIPSIS_PADDING)} + + } + /> + ); +}; + +const Chunks = () => { + const { selectedOrder } = useTwapOrdersContext(); + if (selectedOrder?.totalChunks === 1) return null; + + return ; +}; + +const ChunkSize = () => { + const { selectedOrder } = useTwapOrdersContext(); + const inCurrency = useOrderCurrencies().inCurrency; + + return ( + + ); +}; + +const SrcAmount = () => { + const { selectedOrder } = useTwapOrdersContext(); + const currency = useOrderCurrencies().inCurrency; + + return ( + + ); +}; + +const MinReceived = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { t } = useTranslation(); + const currency = useOrderCurrencies().outCurrency; + + if (selectedOrder?.isMarketOrder) return null; + + return ( + + ); +}; + +const useOrderCurrencies = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { t } = useTranslation(); + + const inCurrency = useTwapOrderCurrency(selectedOrder?.srcTokenAddress); + const outCurrency = useTwapOrderCurrency(selectedOrder?.dstTokenAddress); + return { inCurrency, outCurrency }; +}; + +const CreatedAt = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { t } = useTranslation(); + + if (!selectedOrder) return null; + return ( + + ); +}; + +const Expiration = () => { + const { selectedOrder } = useTwapOrdersContext(); + if (!selectedOrder) return null; + + return ; +}; + +const LimitPrice = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { inCurrency, outCurrency } = useOrderCurrencies(); + + const price = useMemo(() => { + if (!selectedOrder || !inCurrency || !outCurrency) return; + return getOrderLimitPrice( + selectedOrder, + inCurrency?.decimals, + outCurrency?.decimals, + ); + }, [selectedOrder, inCurrency?.decimals, outCurrency?.decimals]); + if (selectedOrder?.isMarketOrder) return null; + + if (selectedOrder?.isMarketOrder) return null; + + return ( + + ); +}; + +const InfoAccordion = ({ + title, + children, + defaultExpanded, +}: { + title: string; + children: ReactNode; + defaultExpanded?: boolean; +}) => { + return ( + + }> + {title} + + {children} + + ); +}; + +const Progress = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { t } = useTranslation(); + if (selectedOrder?.totalChunks === 1) return null; + + return ( + + ); +}; + +const ExcecutionPrice = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { inCurrency, outCurrency } = useOrderCurrencies(); + const { t } = useTranslation(); + + const excecutionPrice = useMemo(() => { + if (!selectedOrder || !inCurrency || !outCurrency) return undefined; + return getOrderExcecutionPrice( + selectedOrder, + inCurrency?.decimals, + outCurrency?.decimals, + ); + }, [selectedOrder, inCurrency, outCurrency]); + + return ( + + ); +}; + +const Status = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { t } = useTranslation(); + + return ( + + ); +}; + +const AmountReceived = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { t } = useTranslation(); + + const currency = useOrderCurrencies().outCurrency; + + return ( + + ); +}; + +const AmountSent = () => { + const { selectedOrder } = useTwapOrdersContext(); + const { t } = useTranslation(); + + const currency = useOrderCurrencies().inCurrency; + + return ( + + ); +}; diff --git a/src/components/Swap/orbs/Twap/TwapOrders/context.tsx b/src/components/Swap/orbs/Twap/TwapOrders/context.tsx new file mode 100644 index 000000000..1a4f31730 --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapOrders/context.tsx @@ -0,0 +1,60 @@ +import { Order } from '@orbs-network/twap-sdk'; +import React, { createContext, useCallback, useMemo, useState } from 'react'; +import { useTwapOrdersQuery } from '../hooks'; + +interface State { + selectedOrderId: number | undefined; +} + +interface ContextValues { + selectedOrderId: number | undefined; + setSelectedOrderId: (payload?: number) => void; + selectedOrder?: Order; + onOpen: () => void; + onDismiss: () => void; + isOpen: boolean; +} + +const Context = createContext({} as ContextValues); + +interface Props { + children: React.ReactNode; +} + +export const TwapOrdersProvider = ({ children }: Props) => { + const [isOpen, setIsOpen] = useState(false); + const [selectedOrderId, setSelectedOrderId] = useState( + undefined, + ); + const onOpen = useCallback(() => { + setIsOpen(true); + }, []); + + const onDismiss = useCallback(() => { + setIsOpen(false); + }, []); + + const { data } = useTwapOrdersQuery(); + const selectedOrder = useMemo( + () => data?.find((order) => order.id === selectedOrderId), + [data, selectedOrderId], + ); + return ( + + {children} + + ); +}; + +export const useTwapOrdersContext = () => { + return React.useContext(Context); +}; diff --git a/src/components/Swap/orbs/Twap/TwapSwapConfirmation/TwapSwapConfirmation.tsx b/src/components/Swap/orbs/Twap/TwapSwapConfirmation/TwapSwapConfirmation.tsx new file mode 100644 index 000000000..a00a3ccfc --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapSwapConfirmation/TwapSwapConfirmation.tsx @@ -0,0 +1,233 @@ +import React, { useMemo } from 'react'; +import OrbsLogo from 'assets/images/orbs-logo.svg'; +import { useTranslation } from 'react-i18next'; +import { Box, Button } from '@material-ui/core'; +import { useCreateOrderCallback } from './useCreateOrderCallback'; +import { ContextProvider, useTwapConfirmationContext } from './context'; +import CheckCircleIcon from '@material-ui/icons/CheckCircle'; +import SwapVerticalCircleIcon from '@material-ui/icons/SwapVerticalCircle'; +import { useTwapApprovalCallback } from '../hooks'; +import { Steps } from 'components/Swap/orbs/types'; +import { useGetLogoCallback } from 'components/Swap/orbs/hooks'; +import { fromRawAmount } from 'components/Swap/orbs/utils'; +import { ORBS_WEBSITE, TWAP_WEBSITE } from '../../consts'; +import { useTwapContext } from '../context'; +import { SwapStep } from '@orbs-network/swap-ui'; +import useUSDCPrice from 'utils/useUSDCPrice'; +import { ConfirmationModal } from '../../ConfirmationModal'; +import { OrderDetails } from '../OrderDetails'; + +export const useSteps = () => { + const { currencies } = useTwapContext(); + const { t } = useTranslation(); + const { + state: { steps }, + } = useTwapConfirmationContext(); + const getLogo = useGetLogoCallback(); + const inCurrency = currencies.INPUT; + + return useMemo(() => { + if (!steps) return []; + const result: SwapStep[] = []; + if (steps.includes(Steps.WRAP)) { + result.push({ + title: t('wrapMATIC', { symbol: inCurrency?.symbol }), + icon: , + id: Steps.WRAP, + }); + } + if (steps.includes(Steps.APPROVE)) { + result.push({ + title: t('approveToken', { symbol: inCurrency?.symbol }), + icon: , + id: Steps.APPROVE, + }); + } + + result.push({ + title: t('createOrder'), + icon: , + id: Steps.SWAP, + }); + return result; + }, [steps, inCurrency, getLogo, t]); +}; + +const SuccessContent = ({ txHash }: { txHash?: string }) => { + const { isLimitPanel } = useTwapContext(); + const { t } = useTranslation(); + return ( + + {t('orderCreated')} + {t(' using')}{' '} + + {isLimitPanel ? 'dLimit' : 'dTWAP'} + {' '} + {t('by')}{' '} + + {t('orbs')} + + +

+ } + /> + ); +}; + +const SwapDetails = () => { + const { + swapData: { deadline, chunks, fillDelay, dstTokenMinAmount }, + parsedAmount, + currencies, + isMarketOrder, + } = useTwapContext(); + + return ( + + + + + + + + + + ); +}; + +const Price = () => { + const { t } = useTranslation(); + const { limitPrice, currencies, isMarketOrder } = useTwapContext(); + const parsedLimitPrice = fromRawAmount(currencies.OUTPUT, limitPrice); + const usd = + Number(useUSDCPrice(currencies.OUTPUT)?.toSignificant() ?? 0) * + Number(parsedLimitPrice?.toExact() || 0); + + return ( + + + {isMarketOrder && ( +

+ {t('marketPriceWarning')}{' '} + + {t('learnMore')} + +

+ )} +
+ ); +}; + +const SwapButton = () => { + const { t } = useTranslation(); + const { isPending: allowancePending } = useTwapApprovalCallback(); + const { mutate: createOrder } = useCreateOrderCallback(); + const { currencies } = useTwapContext(); + const usd = useUSDCPrice(currencies.INPUT)?.toSignificant(); + const isLoading = !usd || allowancePending; + + return ( + + + + + + ); +}; + +const MainContent = () => { + const { t } = useTranslation(); + const { currentStep } = useTwapConfirmationContext().state; + const { currencies, tradeDestAmount, parsedAmount } = useTwapContext(); + const steps = useSteps(); + const parsedTradeDestAmount = fromRawAmount( + currencies.OUTPUT, + tradeDestAmount, + ); + const inUsd = + Number(useUSDCPrice(currencies.INPUT)?.toSignificant() ?? 0) * + Number(parsedAmount?.toExact() || 0); + const outUsd = + Number(useUSDCPrice(currencies.OUTPUT)?.toSignificant() ?? 0) * + Number(parsedTradeDestAmount?.toExact() || 0); + + return ( + } + swapButton={} + inTitle={t('allocate')} + outTitle={t('buy')} + inUsd={inUsd.toLocaleString('en')} + outUsd={outUsd.toLocaleString('en')} + /> + ); +}; + +const ErrorContent = () => { + const { + state: { shouldUnwrap, error }, + } = useTwapConfirmationContext(); + return ; +}; + +export function Content() { + const { + isOpen, + onDismiss, + state: { swapStatus }, + } = useTwapConfirmationContext(); + const { currencies, parsedAmount, tradeDestAmount } = useTwapContext(); + + return ( + } + mainContent={} + errorContent={} + /> + ); +} + +export const TwapSwapConfirmation = (props: { + isOpen: boolean; + onDismiss: () => void; +}) => { + return ( + + + + ); +}; diff --git a/src/components/Swap/orbs/Twap/TwapSwapConfirmation/context.tsx b/src/components/Swap/orbs/Twap/TwapSwapConfirmation/context.tsx new file mode 100644 index 000000000..5d93cd76d --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapSwapConfirmation/context.tsx @@ -0,0 +1,57 @@ +import { ConfirmationState } from 'components/Swap/orbs/types'; +import React from 'react'; +import { createContext, useCallback } from 'react'; +import { Field } from 'state/swap/twap/actions'; +import { useTwapSwapActionHandlers } from 'state/swap/twap/hooks'; +import { useConfirmationStore } from '../../hooks'; + +const DISMISS_TIMEOUT = 500; + +interface ContextValues { + state: ConfirmationState; + updateStore: (payload: Partial) => void; + resetStore: () => void; + isOpen: boolean; + onDismiss: () => void; +} +const Context = createContext({} as ContextValues); + +interface ContextProps { + children: React.ReactNode; + isOpen: boolean; + onDismiss: () => void; +} + +export const ContextProvider = ({ children, ...props }: ContextProps) => { + const { updateStore, store, resetStore } = useConfirmationStore< + ConfirmationState + >({} as ConfirmationState); + + const { onUserInput } = useTwapSwapActionHandlers(); + + const onDismiss = useCallback(() => { + setTimeout(() => { + resetStore(); + onUserInput(Field.INPUT, ''); + }, DISMISS_TIMEOUT); + props.onDismiss(); + }, [props.onDismiss, resetStore, onUserInput]); + + return ( + + {children} + + ); +}; + +export const useTwapConfirmationContext = () => { + return React.useContext(Context); +}; diff --git a/src/components/Swap/orbs/Twap/TwapSwapConfirmation/useCreateOrderCallback.ts b/src/components/Swap/orbs/Twap/TwapSwapConfirmation/useCreateOrderCallback.ts new file mode 100644 index 000000000..cc11ea6d1 --- /dev/null +++ b/src/components/Swap/orbs/Twap/TwapSwapConfirmation/useCreateOrderCallback.ts @@ -0,0 +1,211 @@ +import { useMutation } from '@tanstack/react-query'; +import { useAppDispatch } from 'state'; +import { updateUserBalance } from 'state/balance/actions'; +import { + TwapAbi, + zeroAddress, +} from '@orbs-network/twap-sdk'; +import { useCallback, useMemo, useRef } from 'react'; +import { useTwapApprovalCallback, useTwapOrdersQuery } from '../hooks'; +import { wrappedCurrency } from 'utils/wrappedCurrency'; +import { useActiveWeb3React } from 'hooks'; +import { useContract } from 'hooks/useContract'; +import { calculateGasMargin } from 'utils'; +import { useTwapConfirmationContext } from './context'; +import { WETH } from '@uniswap/sdk'; +import { Steps } from 'components/Swap/orbs/types'; +import { useIsNativeCurrencyCallback } from '../../hooks'; +import { useTwapContext } from '../context'; +import { SwapStatus } from '@orbs-network/swap-ui'; +import useWrapCallback from '../../hooks/useWrapCallback'; +import { isRejectedError } from '../../utils'; +import { BigNumber } from 'ethers'; +import { useTwapSwapActionHandlers } from 'state/swap/twap/hooks'; + +const useGetStepsCallback = () => { + const { currencies, swapData } = useTwapContext(); + const isNativeIn = useIsNativeCurrencyCallback(); + const { isApproved } = useTwapApprovalCallback(); + + return useCallback(() => { + const steps: Steps[] = []; + + if (isNativeIn(currencies.INPUT)) { + steps.push(Steps.WRAP); + } + if (!isApproved) { + steps.push(Steps.APPROVE); + } + steps.push(Steps.SWAP); + return steps; + }, [currencies, isApproved, isNativeIn]); +}; + +const useWrapFlowCallback = () => { + const { currencies, parsedAmount, twapSDK} = useTwapContext(); + const { chainId } = useActiveWeb3React(); + const { execute: wrap } = useWrapCallback( + currencies.INPUT, + WETH[chainId], + parsedAmount?.toExact(), + ); + + return useCallback(async () => { + try { + twapSDK. onWrapRequest(); + await wrap?.(); + onWrapSuccess(); + } catch (error) { + onWrapError(error); + throw error; + } + }, [wrap]); +}; + +const useApprovalFlowCallback = () => { + const { approve } = useTwapApprovalCallback(); + + return useCallback(async () => { + try { + onApproveRequest(); + await approve(); + onApproveSuccess(); + } catch (error) { + onApproveError(error); + throw error; + } + }, [approve]); +}; + +const useCreateOrderFlowCallback = () => { + const { config } = useTwapContext(); + const onSuccess = useOnCreateOrderSuccess(); + const tokenContract = useContract(config.twapAddress, TwapAbi); + + return useCallback( + async (askParams: ReturnType) => { + onCreateOrderRequest(); + if (!tokenContract) { + throw new Error('Missing tokenContract'); + } + + try { + const gasEstimate = await tokenContract.estimateGas.ask(askParams); + + // Step 2: Send the transaction with calculated gas limit + const txResponse = await tokenContract.functions.ask(askParams, { + gasLimit: calculateGasMargin(gasEstimate), // Adjust gas limit with margin + }); + + console.log('Transaction sent:', txResponse); + + // Step 3: Wait for the transaction to be mined + const txReceipt = await txResponse.wait(); + try { + const id = BigNumber.from(txReceipt.events[0].args[0]).toNumber(); + onCreateOrderSuccess(txReceipt.transactionHash, id); + onSuccess(id); + } catch (error) { + console.log({ error }); + } + return txReceipt; // Return the receipt of the mined transaction + } catch (error) { + onCreateOrderError(error); + throw error; + } + }, + [tokenContract], + ); +}; + +const useOnCreateOrderSuccess = () => { + const { fetchUpdatedOrders } = useTwapOrdersQuery(); + const { onUpdatingOrders } = useTwapSwapActionHandlers(); + + return useCallback( + async (id?: number) => { + onUpdatingOrders(true); + await fetchUpdatedOrders(id); + onUpdatingOrders(false); + }, + [fetchUpdatedOrders, onUpdatingOrders], + ); +}; + +export const useCreateOrderCallback = () => { + const { config, parsedAmount, currencies, swapData } = useTwapContext(); + const { chainId, account } = useActiveWeb3React(); + const dispatch = useAppDispatch(); + const inCurrency = currencies?.INPUT; + const outCurrency = currencies?.OUTPUT; + const isNative = useIsNativeCurrencyCallback(); + const { updateStore } = useTwapConfirmationContext(); + const getSteps = useGetStepsCallback(); + const shouldUnwrap = useRef(false); + const approvalCallback = useApprovalFlowCallback(); + const wrapCallback = useWrapFlowCallback(); + const createOrderCallback = useCreateOrderFlowCallback(); + + return useMutation( + async () => { + const srcToken = wrappedCurrency(inCurrency, chainId); + const dstToken = wrappedCurrency(outCurrency, chainId); + + if (!parsedAmount || !srcToken || !dstToken) { + throw new Error('Missing args'); + } + const askParams = getAskParams({ + config, + fillDelay: swapData.fillDelay, + deadline: swapData.deadline, + srcAmount: parsedAmount?.raw.toString(), + dstTokenMinAmount: swapData.dstTokenMinAmount, + srcChunkAmount: swapData.srcChunkAmount, + srcTokenAddress: srcToken.address, + dstTokenAddress: isNative(outCurrency) ? zeroAddress : dstToken.address, + }); + + onSubmitOrder(config, askParams, account); + const steps = getSteps(); + updateStore({ steps, swapStatus: SwapStatus.LOADING }); + if (steps.includes(Steps.WRAP)) { + updateStore({ currentStep: Steps.WRAP }); + await wrapCallback(); + shouldUnwrap.current = true; + updateStore({ shouldUnwrap: true }); + } + + if (steps.includes(Steps.APPROVE)) { + updateStore({ currentStep: Steps.APPROVE }); + await approvalCallback(); + } + updateStore({ currentStep: Steps.SWAP }); + + const result = await createOrderCallback(askParams); + }, + { + onSuccess: () => { + updateStore({ + swapStatus: SwapStatus.SUCCESS, + }); + dispatch(updateUserBalance()); + }, + onError: (error) => { + if (isRejectedError(error) && !shouldUnwrap.current) { + updateStore({ + swapStatus: undefined, + }); + } else { + updateStore({ + shouldUnwrap: shouldUnwrap.current, + swapStatus: SwapStatus.FAILED, + error: (error as Error).message, + }); + } + }, + onSettled: () => { + shouldUnwrap.current = false; + }, + }, + ); +}; diff --git a/src/components/Swap/orbs/Twap/components.tsx b/src/components/Swap/orbs/Twap/components.tsx new file mode 100644 index 000000000..9ff0b25b3 --- /dev/null +++ b/src/components/Swap/orbs/Twap/components.tsx @@ -0,0 +1,320 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { Box, Button, Menu, MenuItem, Typography } from '@material-ui/core'; +import { styled } from '@material-ui/core'; +import { NumericalInput, QuestionHelper } from 'components'; +import { ReactNode } from 'react'; +import { formatNumber } from '@orderly.network/hooks/esm/utils'; +import { useTranslation } from 'react-i18next'; +import { useTwapSwapActionHandlers } from 'state/swap/twap/hooks'; +import { fromRawAmount } from '../utils'; +import { useTwapContext } from './context'; +import { TimeDuration, TimeUnit } from '@orbs-network/twap-sdk'; +import { KeyboardArrowDown } from '@material-ui/icons'; +import ReportProblemIcon from '@material-ui/icons/ReportProblem'; +import { TWAP_FAQ } from '../consts'; + +export const Section = ({ + title, + tootlip, + children, +}: { + title: string; + tootlip?: string; + children: React.ReactNode; +}) => { + return ( + + + {title} + {tootlip && } + + {children} + + ); +}; + +const StyledSection = styled(Box)({ + display: 'flex', + flexDirection: 'column', +}); + +const SectionTitle = styled('p')({ + marginRight: 7, +}); + +export const Card = ({ + children, + className = '', + onClick, +}: { + children: ReactNode; + className?: string; + onClick?: () => void; +}) => { + return ( + + {children} + + ); +}; + +const StyledCard = styled(Box)({ + padding: 15, + borderRadius: 10, + minHeight: 60, +}); + +export const InputsContainer = styled(Box)({ + display: 'flex', + flexDirection: 'column', + gap: 10, + marginTop: 10, +}); + + +export const ChunksSelect = () => { + const { t } = useTranslation(); + const { onChunksInput } = useTwapSwapActionHandlers(); + const chunks = useTwapContext().swapData.chunks; + + return ( +
+ + { + onChunksInput(Number(val)); + }} + /> +

{t('orders')}

+
+ +
+ ); +}; + +const ChunkSize = () => { + const { + swapData: { srcChunkAmount }, + srcChukAmountUsd, + currencies: { INPUT }, + } = useTwapContext(); + + const amount = fromRawAmount(INPUT, srcChunkAmount); + return ( + + {formatNumber(amount?.toExact())} {amount?.currency.symbol} per trade{' '} + {`($${formatNumber(srcChukAmountUsd)})`} + + ); +}; + + +const options: { unit: TimeUnit; value: number; label: string }[] = [ + { + label: 'day', + unit: TimeUnit.Days, + value: 1, + }, + { + label: 'week', + unit: TimeUnit.Days, + value: 7, + }, + { + label: 'month', + unit: TimeUnit.Days, + value: 30, + }, +]; + +export function DurationSelect() { + const { t } = useTranslation(); + const { onDurationInput } = useTwapSwapActionHandlers(); + const { + swapData: { duration }, + } = useTwapContext(); + + return ( + +

+ {t('expiry')} +

+ + {options.map((option) => { + const selected = + duration.unit * duration.value === option.unit * option.value; + return ( + + onDurationInput({ unit: option.unit, value: option.value }) + } + > + 1 {t(option.label)} + + ); + })} + +
+ ); +} + +export const FillDelaySelect = () => { + const fillDelay = useTwapContext().swapData.fillDelay; + const onChange = useTwapSwapActionHandlers().onFillDelayInput; + return ( +
+ + { + onChange({ ...fillDelay, value: Number(val) }); + }} + /> + + +
+ ); +}; + +const ResolutionSelect = ({ + duration, + onChange, +}: { + duration: TimeDuration; + onChange: (value: TimeDuration) => void; +}) => { + const { t } = useTranslation(); + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + + const onOpen = useCallback( + (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }, + [setAnchorEl], + ); + + const handleClose = useCallback(() => { + setAnchorEl(null); + }, [setAnchorEl]); + + const handleMenuItemClick = useCallback( + (unit: TimeUnit) => { + onChange({ ...duration, unit }); + handleClose(); + }, + [duration, onChange, handleClose], + ); + + const selected = useMemo( + () => options.find((option) => option.unit === duration.unit), + [duration], + ); + + return ( + + + + {options.map((option, index) => { + const selected = duration.unit === option.unit; + return ( + handleMenuItemClick(option.unit)} + > + {t(option.label)} + {selected && } + + ); + })} + + + ); +}; + + +export function LimitPriceWarning() { + const { isMarketOrder } = useTwapContext(); + if (isMarketOrder) return null; + return ( + + +

+ Limit orders may not execute when the token's price is equal or close to + the limit price, due to gas and standard swap fees.{' '} + + Learn more + +

+
+ ); +} + + +export function SelectorButton({ + selected, + onClick, + children, +}: { + selected?: boolean; + onClick: () => void; + children: ReactNode; +}) { + return ( + + ); +} diff --git a/src/components/Swap/orbs/Twap/context.tsx b/src/components/Swap/orbs/Twap/context.tsx new file mode 100644 index 000000000..4d9de3c2e --- /dev/null +++ b/src/components/Swap/orbs/Twap/context.tsx @@ -0,0 +1,298 @@ +import { + Config, + Configs, + constructSDK, + GetSwapValuesPayload, + TimeUnit, + TwapSDK, +} from '@orbs-network/twap-sdk'; +import { OptimalRate, SwapSide } from '@paraswap/sdk'; +import { useQuery } from '@tanstack/react-query'; +import { ChainId, Currency, CurrencyAmount } from '@uniswap/sdk'; +import { GlobalValue, paraswapTaxBuy, paraswapTaxSell } from 'constants/index'; +import { useActiveWeb3React } from 'hooks'; +import { useCurrency } from 'hooks/Tokens'; +import { useParaswap, getBestTradeCurrencyAddress } from 'hooks/useParaswap'; +import useParsedQueryString from 'hooks/useParsedQueryString'; +import React, { createContext, useEffect, useMemo } from 'react'; +import { Field } from 'state/swap/actions'; +import { tryParseAmount } from 'state/swap/hooks'; +import { useTwapState, useTwapSwapActionHandlers } from 'state/swap/twap/hooks'; +import { useExpertModeManager } from 'state/user/hooks'; +import { useCurrencyBalances } from 'state/wallet/hooks'; +import useUSDCPrice from 'utils/useUSDCPrice'; +import { fromRawAmount } from '../utils'; +import { useOptimalRateQuery } from './hooks'; + +export const useLimitPrice = () => { + const { isLimitPanel, maxImpactAllowed, currencies } = useTwapContext(); + const { typedLimitPrice, isLimitPriceInverted } = useTwapState(); + const { chainId } = useActiveWeb3React(); + + const { data, isLoading: loadingOptimalRate } = useOptimalRateQuery( + currencies, + maxImpactAllowed, + ); + const marketPrice = data?.rate?.destAmount; + return useMemo(() => { + let result = marketPrice; + if (!isLimitPanel) { + return marketPrice; + } + if (typedLimitPrice !== undefined) { + result = tryParseAmount( + chainId, + isLimitPriceInverted + ? (1 / Number(typedLimitPrice)).toString() + : typedLimitPrice, + currencies.OUTPUT, + )?.raw.toString(); + } + return result; + }, [ + typedLimitPrice, + chainId, + currencies.OUTPUT, + marketPrice, + isLimitPriceInverted, + isLimitPanel, + ]); +}; + +export const useSwapValues = () => { + const { parsedAmount, twapSDK, isLimitPanel, currencies } = useTwapContext(); + const { typedChunks, typedDuration, typedFillDelay } = useTwapState(); + const limitPrice = useLimitPrice(); + const oneSrcTokenUsd = Number( + useUSDCPrice(currencies.INPUT)?.toSignificant() ?? 0, + ); + + return twapSDK.getSwapValues({ + srcAmount: parsedAmount?.raw.toString(), + customChunks: typedChunks, + customDuration: typedDuration, + customFillDelay: typedFillDelay, + limitPrice, + isLimitPanel, + oneSrcTokenUsd, + srcDecimals: currencies.INPUT?.decimals, + dstDecimals: currencies.OUTPUT?.decimals, + isMarketOrder: !isLimitPanel, + }); +}; + +interface ContextValues { + currencies: { [field in Field]?: Currency }; + currencyBalances: { [field in Field]?: CurrencyAmount }; + parsedAmount: CurrencyAmount | undefined; + inputError: string | undefined; + config: Config; + maxImpactAllowed: number; + swapData: GetSwapValuesPayload; + limitPrice?: string; + marketPrice?: string; + optimalRate?: OptimalRate; + optimalRateError?: string; + loadingOptimalRate: boolean; + tradeDestAmount?: string; + isMarketOrder: boolean; + isLimitPanel: boolean; + twapSDK: TwapSDK; +} + +const Context = createContext({} as ContextValues); + +interface Props { + children: React.ReactNode; + isLimitPanel?: boolean; +} +const config = Configs.QuickSwap; +export const TwapContextProvider = ({ children, isLimitPanel }: Props) => { + const [isExpertMode] = useExpertModeManager(); + const { account, chainId } = useActiveWeb3React(); + const chainIdToUse = chainId ?? ChainId.MATIC; + const parsedQuery = useParsedQueryString(); + const swapType = parsedQuery?.swapIndex; + const { onDurationInput } = useTwapSwapActionHandlers(); + const twapSDK = useMemo(() => constructSDK({ config }), [config]); + + useEffect(() => { + if (isLimitPanel) { + onDurationInput({ unit: TimeUnit.Days, value: 7 }); + } else { + onDurationInput(undefined); + } + }, [isLimitPanel]); + + const { + typedValue, + [Field.INPUT]: { currencyId: inputCurrencyId }, + [Field.OUTPUT]: { currencyId: outputCurrencyId }, + typedChunks, + typedDuration, + typedFillDelay, + typedLimitPrice, + isMarketOrder: _isMarketOrder, + isLimitPriceInverted, + } = useTwapState(); + const inputCurrency = useCurrency(inputCurrencyId); + const outputCurrency = useCurrency(outputCurrencyId); + const isMarketOrder = isLimitPanel ? false : typedLimitPrice === undefined; + + const relevantTokenBalances = useCurrencyBalances(account ?? undefined, [ + inputCurrency ?? undefined, + outputCurrency ?? undefined, + ]); + + const parsedAmount = tryParseAmount( + chainIdToUse, + typedValue, + inputCurrency ?? undefined, + ); + + const currencyBalances = { + [Field.INPUT]: relevantTokenBalances[0], + [Field.OUTPUT]: relevantTokenBalances[1], + }; + + const currencies: { [field in Field]?: Currency } = { + [Field.INPUT]: inputCurrency ?? undefined, + [Field.OUTPUT]: outputCurrency ?? undefined, + }; + + const inputError = useMemo(() => { + if (!account) { + return 'Connect Wallet'; + } + if (!parsedAmount) { + return 'Enter an amount'; + } + + if (!currencies[Field.INPUT] || !currencies[Field.OUTPUT]) { + return 'Select a token'; + } + + const balanceIn = currencyBalances[Field.INPUT]; + const amountIn = parsedAmount; + + if ( + swapType !== '0' && + balanceIn && + amountIn && + balanceIn.lessThan(amountIn) + ) { + return 'Insufficient ' + amountIn.currency.symbol + ' balance'; + } + }, [ + account, + parsedAmount, + currencies, + swapType, + currencyBalances[Field.INPUT], + ]); + + const maxImpactAllowed = isExpertMode + ? 100 + : Number( + GlobalValue.percents.BLOCKED_PRICE_IMPACT_NON_EXPERT.multiply( + '100', + ).toFixed(4), + ); + + const { data, isLoading: loadingOptimalRate } = useOptimalRateQuery( + currencies, + maxImpactAllowed, + ); + const marketPrice = data?.rate?.destAmount; + const limitPrice = useMemo(() => { + let result = marketPrice; + if (isMarketOrder) { + return marketPrice; + } + if (typedLimitPrice !== undefined) { + result = tryParseAmount( + chainId, + isLimitPriceInverted + ? (1 / Number(typedLimitPrice)).toString() + : typedLimitPrice, + currencies.OUTPUT, + )?.raw.toString(); + } + return result; + }, [ + typedLimitPrice, + chainId, + currencies.OUTPUT, + marketPrice, + isMarketOrder, + isLimitPriceInverted, + ]); + + const oneSrcTokenUsd = Number( + useUSDCPrice(currencies.INPUT)?.toSignificant() ?? 0, + ); + + const swapData = twapSDK.getSwapValues({ + srcAmount: parsedAmount?.raw.toString(), + customChunks: typedChunks, + customDuration: typedDuration, + customFillDelay: typedFillDelay, + limitPrice, + isLimitPanel, + oneSrcTokenUsd, + srcDecimals: currencies.INPUT?.decimals, + dstDecimals: currencies.OUTPUT?.decimals, + isMarketOrder, + }); + + const tradeDestAmount = useMemo(() => { + if (!limitPrice || !typedValue || !currencies.OUTPUT || !currencies.INPUT) + return; + const SCALE = BigInt(10 ** 18); + + const scaledParsedAmount = BigInt( + Math.floor(Number(typedValue) * Number(SCALE)), + ); + + const result = + BigInt( + fromRawAmount(currencies.OUTPUT, limitPrice)?.numerator.toString() || 0, + ) * scaledParsedAmount; + return (result / SCALE).toString(); + }, [ + limitPrice, + typedValue, + currencies.OUTPUT, + currencies.INPUT, + parsedAmount?.toFixed(), + ]); + + return ( + + {children} + + ); +}; + +export const useTwapContext = () => { + return React.useContext(Context); +}; diff --git a/src/components/Swap/orbs/Twap/hooks.ts b/src/components/Swap/orbs/Twap/hooks.ts new file mode 100644 index 000000000..82eaad3ee --- /dev/null +++ b/src/components/Swap/orbs/Twap/hooks.ts @@ -0,0 +1,201 @@ +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { + MIN_FILL_DELAY_MINUTES, + MAX_FILL_DELAY_FORMATTED, + MIN_DURATION_MINUTES, + groupOrdersByStatus, + zeroAddress, + constructSDK +} from '@orbs-network/twap-sdk'; +import { ChainId, Currency, currencyEquals, ETHER } from '@uniswap/sdk'; +import { useActiveWeb3React } from 'hooks'; +import { useCallback, useMemo } from 'react'; +import { useTwapContext } from './context'; +import { V3Currency } from 'v3lib/entities/v3Currency'; +import { useApproval } from '../hooks'; +import { useCurrency } from 'hooks/Tokens'; +import { useTranslation } from 'react-i18next'; +import { SwapSide } from '@paraswap/sdk'; +import { GlobalValue, paraswapTaxBuy, paraswapTaxSell } from 'constants/index'; +import { getBestTradeCurrencyAddress, useParaswap } from '../../../../hooks/useParaswap'; +import { tryParseAmount } from 'state/swap/hooks'; +import { Field } from '../../../../state/swap/actions'; + + +export const useOptimalRateQuery = ( + currencies: { [field in Field]?: Currency }, + maxImpactAllowed: number, +) => { + const paraswap = useParaswap(); + const { chainId, account } = useActiveWeb3React(); + const chainIdToUse = chainId || ChainId.MATIC; + const inputCurrency = currencies[Field.INPUT]; + const outputCurrency = currencies[Field.OUTPUT]; + + // we always use 1 as the amount for the market price + const srcAmount = tryParseAmount( + chainIdToUse, + '1', + inputCurrency, + )?.raw.toString(); + + const srcToken = inputCurrency + ? getBestTradeCurrencyAddress(inputCurrency, chainIdToUse) + : undefined; + const destToken = outputCurrency + ? getBestTradeCurrencyAddress(outputCurrency, chainIdToUse) + : undefined; + + return useQuery({ + queryKey: [ + 'fetchTwapOptimalRate', + srcToken, + destToken, + srcAmount, + account, + chainId, + maxImpactAllowed, + ], + queryFn: async () => { + if (!srcToken || !destToken || !srcAmount || !account) + return { error: undefined, rate: undefined }; + try { + const rate = await paraswap.getRate({ + srcToken, + destToken, + srcDecimals: inputCurrency?.decimals, + destDecimals: outputCurrency?.decimals, + amount: srcAmount, + side: SwapSide.SELL, + options: { + includeDEXS: 'quickswap,quickswapv3,quickswapv3.1,quickperps', + maxImpact: maxImpactAllowed, + partner: 'quickswapv3', + //@ts-ignore + srcTokenTransferFee: paraswapTaxSell[srcToken.toLowerCase()], + destTokenTransferFee: paraswapTaxBuy[destToken.toLowerCase()], + }, + }); + + return { error: undefined, rate }; + } catch (err) { + return { error: err.message, rate: undefined }; + } + }, + refetchInterval: 5000, + enabled: !!srcToken && !!destToken && !!account, + }); +}; + + + +export const useTwapSwapWarning = () => { + const { t } = useTranslation(); + const { + swapData: { warnings }, + config, + } = useTwapContext(); + + const durationWarning = useMemo(() => { + if (warnings.minDuration) { + return t('minExpiryWarning', { value: MIN_DURATION_MINUTES }); + } + if (warnings.maxDuration) { + return t('maxExpiryWarning'); + } + }, [warnings.maxDuration, warnings.minDuration, t]); + + const tradeSizeWarning = useMemo(() => { + if (warnings.tradeSize) { + return t('tradeSizeWarning', { usd: config.minChunkSizeUsd }); + } + }, [warnings.tradeSize, config.minChunkSizeUsd, t]); + + const fillDelayWarning = useMemo(() => { + if (warnings.minFillDelay) { + return t('minFillDelayWarning', { value: MIN_FILL_DELAY_MINUTES }); + } + if (warnings.maxFillDelay) { + return t('maxFillDelayWarning', { value: MAX_FILL_DELAY_FORMATTED }); + } + }, [warnings.minFillDelay, warnings.maxFillDelay, t]); + + return tradeSizeWarning || fillDelayWarning || durationWarning; +}; + +export const isNativeCurrency = (currency?: Currency, chainId?: ChainId) => { + if (!currency || !chainId) return false; + const nativeCurrency = ETHER[chainId]; + return ( + currencyEquals(currency, nativeCurrency) || + (currency as V3Currency).isNative + ); +}; + +export const useTwapApprovalCallback = () => { + const { parsedAmount, config, currencies } = useTwapContext(); + + return useApproval( + config.twapAddress, + currencies.INPUT, + parsedAmount?.raw.toString(), + ); +}; + +export const useTwapOrdersQuery = () => { + const { account } = useActiveWeb3React(); + const { config } = useTwapContext(); + const queryClient = useQueryClient(); + const queryKey = ['useTwapOrders', account, config.chainId]; + const query = useQuery( + queryKey, + async ({ signal }) => { + if (!account) return null; + return getOrders(config, account!, signal); + }, + { + enabled: !!account, + }, + ); + const fetchUpdatedOrders = useCallback( + async (id?: number) => { + if (!id) { + query.refetch(); + } else { + try { + const orders = await waitForUpdatedOrders(config, id, account!); + if (orders) { + queryClient.setQueryData(queryKey, orders); + return orders; + } + } catch (error) { + console.error(error); + return query.data; + } + } + }, + [queryClient, queryKey, account, config, query.data], + ); + + return useMemo(() => { + return { + ...query, + fetchUpdatedOrders, + }; + }, [query, fetchUpdatedOrders]); +}; + +export const useGrouppedTwapOrders = () => { + const orders = useTwapOrdersQuery(); + + return useMemo(() => { + if (!orders.data) return; + return groupOrdersByStatus(orders.data); + }, [orders.data]); +}; + +export const useTwapOrderCurrency = (address?: string) => { + const _address = address?.toLowerCase() === zeroAddress ? 'ETH' : address; + const currency = useCurrency(_address); + return currency || undefined; +}; diff --git a/src/components/Swap/orbs/consts.ts b/src/components/Swap/orbs/consts.ts new file mode 100644 index 000000000..38bce51cc --- /dev/null +++ b/src/components/Swap/orbs/consts.ts @@ -0,0 +1,8 @@ +export const SIGNATURE_TIMEOUT = 40_000; +export const SWAP_COUNTDOWN = 59_000; +export const ORBS_WEBSITE = 'https://www.orbs.com'; +export const LIQUIDITY_HUB_WEBSITE = 'https://www.orbs.com/liquidity-hub'; +export const TWAP_WEBSITE = 'https://www.orbs.com/dtwap'; +export const LIMIT_WEBSITE = 'https://www.orbs.com/dlimit'; +export const TWAP_FAQ = 'https://www.orbs.com/dtwap-and-dlimit-faq/'; + diff --git a/src/components/Swap/orbs/hooks/index.ts b/src/components/Swap/orbs/hooks/index.ts new file mode 100644 index 000000000..08f5e1787 --- /dev/null +++ b/src/components/Swap/orbs/hooks/index.ts @@ -0,0 +1,123 @@ +import { Currency, currencyEquals, ETHER, WETH } from '@uniswap/sdk'; +import { useActiveWeb3React } from 'hooks'; +import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback'; +import { useCallback, useMemo, useReducer } from 'react'; +import { tryParseAmount } from 'state/swap/hooks'; +import { getTokenLogoURL } from 'utils/getTokenLogoURL'; +import { wrappedCurrency } from 'utils/wrappedCurrency'; +import { V3Currency } from 'v3lib/entities/v3Currency'; + +export const useLogo = (currency?: Currency) => { + const getLogo = useGetLogoCallback(); + return useMemo(() => { + return !currency ? undefined : getLogo(currency); + }, [currency]); +}; + +export const useGetLogoCallback = () => { + const { chainId } = useActiveWeb3React(); + const isNativeCurrency = useIsNativeCurrencyCallback(); + return useCallback( + (currency?: Currency | null) => { + if (!currency) return undefined; + if (isNativeCurrency(currency)) { + return '/' + currency?.symbol + '.png'; + } + const address = wrappedCurrency(currency, chainId)?.address; + if (!address) return undefined; + try { + return getTokenLogoURL(address, []).find((it) => it !== 'error') as any; + } catch (error) {} + }, + [chainId], + ); +}; + +export const useIsNativeCurrencyCallback = () => { + const { chainId } = useActiveWeb3React(); + return useCallback( + (currency?: Currency) => { + if (!chainId || !currency) return false; + const nativeCurrency = ETHER[chainId]; + return ( + currencyEquals(currency, nativeCurrency) || + (currency as V3Currency).isNative + ); + }, + [chainId], + ); +}; + +export const useApproval = ( + spender?: string, + inCurrency?: Currency, + amount?: string, +) => { + const { chainId } = useActiveWeb3React(); + const isNative = useIsNativeCurrencyCallback(); + + const approvalAmount = useMemo(() => { + return tryParseAmount( + chainId, + amount, + isNative(inCurrency) ? WETH[chainId] : inCurrency, + ); + }, [chainId, amount, inCurrency]); + + const [approvalState, approve] = useApproveCallback(approvalAmount, spender); + + return { + approve, + approvalState, + isApproved: approvalState === ApprovalState.APPROVED, + isPending: + approvalState === ApprovalState.PENDING || + approvalState === ApprovalState.UNKNOWN, + }; +}; + +type Action = + | { type: 'UPDATE_STATE'; payload: Partial } + | { type: 'RESET' }; + +function reducer( + state: TState, + action: Action, + initialState: TState, +): TState { + switch (action.type) { + case 'UPDATE_STATE': + return { ...state, ...action.payload }; + case 'RESET': + return initialState; + default: + return state; + } +} + +export const useConfirmationStore = ( + initialState: TState, +) => { + const [state, dispatch] = useReducer( + (state: TState, action: Action) => + reducer(state, action, initialState), + initialState, + ); + + const updateStore = useCallback( + (payload: Partial) => { + dispatch({ type: 'UPDATE_STATE', payload }); + }, + [dispatch], + ); + + const resetStore = useCallback(() => { + dispatch({ type: 'RESET' }); + }, [dispatch]); + + return { + store: state, + updateStore, + resetStore, + }; +}; diff --git a/src/components/Swap/orbs/hooks/useWrapCallback.ts b/src/components/Swap/orbs/hooks/useWrapCallback.ts new file mode 100755 index 000000000..e10b6f739 --- /dev/null +++ b/src/components/Swap/orbs/hooks/useWrapCallback.ts @@ -0,0 +1,126 @@ +import { ChainId, Currency, currencyEquals, ETHER, WETH } from '@uniswap/sdk'; +import { useMemo, useState } from 'react'; +import { tryParseAmount } from 'state/swap/hooks'; +import { useTransactionAdder } from 'state/transactions/hooks'; +import { useCurrencyBalance } from 'state/wallet/hooks'; +import { useActiveWeb3React } from 'hooks'; +import { formatTokenAmount } from 'utils'; +import { useAppDispatch } from 'state'; +import { updateUserBalance } from 'state/balance/actions'; +import { useWETHContract } from 'hooks/useContract'; + +export enum WrapType { + NOT_APPLICABLE, + WRAP, + UNWRAP, + WRAPPING, + UNWRAPPING, +} + +const NOT_APPLICABLE = { wrapType: WrapType.NOT_APPLICABLE }; +/** + * Given the selected input and output currency, return a wrap callback + * @param inputCurrency the selected input currency + * @param outputCurrency the selected output currency + * @param typedValue the user input value + */ +export default function useWrapCallback( + inputCurrency: Currency | undefined, + outputCurrency: Currency | undefined, + typedValue: string | undefined, +): { + wrapType: WrapType; + execute?: undefined | (() => Promise); + inputError?: string; +} { + const { chainId, account } = useActiveWeb3React(); + const chainIdToUse = chainId ? chainId : ChainId.MATIC; + const nativeCurrency = ETHER[chainIdToUse]; + const wethContract = useWETHContract(); + const balance = useCurrencyBalance(account ?? undefined, inputCurrency); + // we can always parse the amount typed as the input currency, since wrapping is 1:1 + const inputAmount = useMemo( + () => tryParseAmount(chainIdToUse, typedValue, inputCurrency), + [chainIdToUse, inputCurrency, typedValue], + ); + const addTransaction = useTransactionAdder(); + const [wrapping, setWrapping] = useState(false); + const [unwrapping, setUnWrapping] = useState(false); + const dispatch = useAppDispatch(); + return useMemo(() => { + if (!wethContract || !chainId || !inputCurrency || !outputCurrency) + return NOT_APPLICABLE; + + if ( + inputCurrency === nativeCurrency && + currencyEquals(WETH[chainId], outputCurrency) + ) { + return { + wrapType: wrapping ? WrapType.WRAPPING : WrapType.WRAP, + execute: inputAmount + ? async () => { + setWrapping(true); + try { + const txReceipt = await wethContract.deposit({ + value: `0x${inputAmount.raw.toString(16)}`, + }); + addTransaction(txReceipt, { + summary: `Wrap ${formatTokenAmount(inputAmount)} ${ + ETHER[chainId].symbol + } to ${WETH[chainId].symbol}`, + }); + await txReceipt.wait(); + dispatch(updateUserBalance()); + setWrapping(false); + } catch (error) { + setWrapping(false); + throw error; + } + } + : undefined, + }; + } else if ( + currencyEquals(WETH[chainId], inputCurrency) && + outputCurrency === nativeCurrency + ) { + return { + wrapType: unwrapping ? WrapType.UNWRAPPING : WrapType.UNWRAP, + execute: inputAmount + ? async () => { + setUnWrapping(true); + try { + const txReceipt = await wethContract.withdraw( + `0x${inputAmount.raw.toString(16)}`, + ); + addTransaction(txReceipt, { + summary: `Unwrap ${formatTokenAmount(inputAmount)} ${ + WETH[chainId].symbol + } to ${ETHER[chainId].symbol}`, + }); + await txReceipt.wait(); + dispatch(updateUserBalance()); + setUnWrapping(false); + } catch (error) { + setUnWrapping(false); + throw error; + } + } + : undefined, + }; + } else { + return NOT_APPLICABLE; + } + }, [ + wethContract, + chainId, + inputCurrency, + outputCurrency, + inputAmount, + balance, + nativeCurrency, + wrapping, + addTransaction, + dispatch, + unwrapping, + ]); +} diff --git a/src/components/Swap/orbs/types.ts b/src/components/Swap/orbs/types.ts new file mode 100644 index 000000000..83ca3dbc1 --- /dev/null +++ b/src/components/Swap/orbs/types.ts @@ -0,0 +1,37 @@ +import { Quote } from '@orbs-network/liquidity-hub-sdk'; +import { SwapStatus } from '@orbs-network/swap-ui'; +import { OptimalRate } from '@paraswap/sdk'; +import { Currency } from '@uniswap/sdk'; +import { useLiquidityHubQuote } from './LiquidityHub/hooks'; + +export enum Steps { + WRAP = 1, + APPROVE = 2, + SWAP = 3, +} + +export interface LiquidityHubConfirmationProps { + inCurrency?: Currency; + outCurrency?: Currency; + isOpen: boolean; + onDismiss: () => void; + quoteQuery: ReturnType; + onSwapFailed?: () => void; + onSwapSuccess?: () => void; + optimalRate?: OptimalRate; + allowedSlippage?: number; +} + +export type ConfirmationState = { + swapStatus?: SwapStatus; + currentStep?: Steps; + shouldUnwrap?: boolean; + txHash?: string; + steps?: Steps[]; + error?: string; +}; + +export interface LiquidityHubConfirmationState extends ConfirmationState { + acceptedQuote?: Quote | null; + signature?: string; +} diff --git a/src/components/Swap/orbs/utils.ts b/src/components/Swap/orbs/utils.ts new file mode 100644 index 000000000..ca86b85d7 --- /dev/null +++ b/src/components/Swap/orbs/utils.ts @@ -0,0 +1,84 @@ +import { Currency, JSBI } from '@uniswap/sdk'; +import { + CurrencyAmount as CurrencyAmountV3, + Currency as CurrencyV3, +} from '@uniswap/sdk-core'; +import { Quote, QUOTE_ERRORS } from '@orbs-network/liquidity-hub-sdk'; +import { OptimalRate } from '@paraswap/sdk'; +import BN from 'bignumber.js'; +import { BigNumber } from 'ethers'; + +export const getDexMinAmountOut = ( + allowedSlippage: number, + outAmount?: string, +) => { + if (!outAmount) return undefined; + + return BigNumber.from(outAmount) + .mul(BigNumber.from(10000 - Number(allowedSlippage.toFixed(0)))) + .div(BigNumber.from(10000)) + .toString(); +}; + +export const isLiquidityHubTrade = ( + allowedSlippage: number, + quote?: Quote | null, + optimalRate?: OptimalRate, +) => { + const dexMinAmountOut = getDexMinAmountOut( + allowedSlippage, + optimalRate?.destAmount, + ); + return BN(quote?.outAmount || 0).gt(dexMinAmountOut || 0); +}; + +export async function promiseWithTimeout( + promise: Promise, + timeout: number, +): Promise { + let timer: any; + + const timeoutPromise = new Promise((_, reject) => { + timer = setTimeout(() => { + reject(new Error('timeout')); + }, timeout); + }); + + try { + const result = await Promise.race([promise, timeoutPromise]); + clearTimeout(timer); + return result; + } catch (error) { + clearTimeout(timer); + throw error; + } +} + +export const fromRawAmount = (currency?: Currency, amount?: string) => { + if (!currency || !amount) return undefined; + return CurrencyAmountV3.fromRawAmount( + currency as CurrencyV3, + JSBI.BigInt(amount), + ); +}; + +export const isRejectedError = (error: any) => { + const message = error.message?.toLowerCase(); + return message?.includes('rejected') || message?.includes('denied'); +}; + +export const isTimeoutError = (error: any) => { + const message = error.message?.toLowerCase(); + return message?.includes('timeout'); +}; + +export const makeElipsisAddress = (address?: string, padding = 6): string => { + if (!address) return ''; + return `${address.substring(0, padding)}...${address.substring( + address.length - padding, + )}`; +}; + +export const isLowInAmountError = (error: any) => { + return (error as Error)?.message === QUOTE_ERRORS.ldv; +}; diff --git a/src/components/TransactionConfirmationModal/TransactionConfirmationModal.tsx b/src/components/TransactionConfirmationModal/TransactionConfirmationModal.tsx index 8204c55a9..0e43277d7 100755 --- a/src/components/TransactionConfirmationModal/TransactionConfirmationModal.tsx +++ b/src/components/TransactionConfirmationModal/TransactionConfirmationModal.tsx @@ -12,11 +12,6 @@ import SpinnerImage from '../../assets/images/spinner.svg'; import 'components/styles/TransactionConfirmationModal.scss'; import { useTranslation } from 'react-i18next'; import { CheckCircleOutline } from '@material-ui/icons'; -import { - LiquidityHubConfirmationModalContent, - useConfirmationPendingContent, -} from 'components/Swap/LiquidityHub'; -import { useLiquidityHubState } from 'state/swap/liquidity-hub/hooks'; interface ConfirmationPendingContentProps { onDismiss: () => void; @@ -27,8 +22,7 @@ export const ConfirmationPendingContent: React.FC { - const confirmationPendingContent = useConfirmationPendingContent(pendingText); - + const { t } = useTranslation(); return ( @@ -38,11 +32,9 @@ export const ConfirmationPendingContent: React.FC Spinner -
{confirmationPendingContent.title}
- {confirmationPendingContent.pending && ( -

{confirmationPendingContent.pending}

- )} -

{confirmationPendingContent.confirm || ''}

+
{t('waitingConfirm')}
+ {pendingText &&

{pendingText}

} +

{t('confirmTxinWallet')}

); @@ -77,7 +69,6 @@ export const TransactionSubmittedContent: React.FC {!txPending && } {modalContent} -

diff --git a/src/components/styles/orbs/ConfirmationModal.scss b/src/components/styles/orbs/ConfirmationModal.scss new file mode 100644 index 000000000..8659256fa --- /dev/null +++ b/src/components/styles/orbs/ConfirmationModal.scss @@ -0,0 +1,56 @@ +@use 'styles/variables' as *; + + +.orbsErrorContent { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + &Text{ + margin-top: 20px; + font-size: 18px; + margin-bottom: 20px; + } + .txSubmitButton { + width: 100%; + } + &Buttons { + margin-top: 30px; + width: 100%; + display: flex; + gap: 20px; + width: 100%; + } +} + + +.orbsTxModalContent { + margin-top: 20px; + padding: 16px 0; + padding-bottom: 0px; + color: $textPrimary; + text-align: center; + & .orbs_StepsStepLogo { + border: 7px solid #1b1e29; + + } +} + +.orbsModalWrapper { + max-width: 500px; +} + +.orbsSuccessContentButtons { + display: flex; + justify-content: space-between; + gap: 20px; + width: 100%; + .txSubmitButton { + width: 100%; + } + &Link { + width: 100%; + text-decoration: none; + } +} diff --git a/src/components/styles/orbs/Twap.scss b/src/components/styles/orbs/Twap.scss new file mode 100644 index 000000000..387d4a817 --- /dev/null +++ b/src/components/styles/orbs/Twap.scss @@ -0,0 +1,413 @@ +@use 'styles/variables' as *; +@use 'styles/breakpoints' as *; + +.TwapOrdersModalWrapper { + max-width: 600px; +} + +.TwapLimitPanelInputContainer { + display: flex; + width: 100%; + gap: 20px; + & .styledInput { + width: unset; + flex: 1; + } +} + +.TwapLimitPanelHeader { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 10px; + &Title { + display: flex; + align-items: center; + justify-content: flex-start; + .currencyLogo { + margin-left: 5px; + margin-right: 5px; + } + } + &Invert { + padding: 6px; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + transition: 0.2s all; + svg { + width: 23px; + height: 23px; + } + &:hover { + background: rgba(255, 255, 255, 0.08); + } + } +} +.TwapLimitPanel { + margin-bottom: 8px; + &Input { + flex: 1; + } + &Percent { + margin-top: 10px; + display: flex; + justify-content: flex-end; + gap: 6px; + .TwapSelectorButton { + padding: 2px 10px; + } + } +} +.TwapLimitPanelPercentReset { + display: flex; + gap: 2px; + + .TwapSelectorButton { + &:first-child { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; + } + &:last-child { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + padding: 2px 5px; + } + .MuiSvgIcon-root { + width: 16px; + height: 16px; + } + } +} + +.TwapFillDelaySelect { + display: flex; + width: 100%; + justify-content: space-between; + align-items: center; + gap: 20px; + padding-top: 0px; + padding-bottom: 0px; +} + +.TwapChunkSelect { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + &Text { + color: $textHint; + font-size: 15px; + } + &Size { + font-size: 14px; + margin-top: 10px; + color: $textHint; + small { + font-size: 12px; + } + } +} +.TwapLimitPriceWarning { + display: flex; + align-items: flex-start; + gap: 10px; + margin-top: 20px; + p { + font-size: 14px; + flex: 1; + } + svg { + width: 19px; + height: 19px; + } +} +.TwapShowOrdersButton { + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + margin-top: 20px; + &Spinner { + } + p { + font-size: 14px; + } +} + +.TwapSelectorButton { + font-size: 14px; + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 10px; + padding: 4px 10px; + &Selected { + background: rgba(255, 255, 255, 0.04); + } +} +.TwapDurationSelect { + display: flex; + justify-content: space-between; + + &Title { + font-size: 14px; + display: flex; + gap: 5px; + align-items: center; + } + .TwapSelectorButton { + span { + text-transform: capitalize; + } + } + &Buttons { + display: flex; + gap: 10px; + } +} +.TwapConfirmationPrice { + display: flex; + flex-direction: column; + gap: 5px; + &Warning { + font-size: 14px; + line-height: 18px; + color: $textHint; + text-align: left; + svg { + margin-right: 5px; + width: 15px; + height: 15px; + } + } + a { + text-decoration: underline; + } +} +.TwapOrderDetails { + display: flex; + flex-direction: column; + gap: 10px; + width: 100%; + margin-top: 20px; + padding-top: 20px; + border-top: 1px solid rgba(130, 177, 255, 0.08); +} +.TwapOrderDetailsRow { + display: flex; + justify-content: space-between; + align-items: center; + &Left { + display: flex; + gap: 5px; + } + &Value { + font-size: 14px; + } + &Label { + font-size: 14px; + font-weight: 600; + color: $textSecondary; + } + small { + opacity: 0.7; + font-size: 13px; + } +} + +.TwapOrderTitle { + font-size: 15px; + small { + font-size: 13px; + color: $textSecondary; + } +} +.TwapSelectedOrderAccordions { + display: flex; + flex-direction: column; + gap: 20px; +} + +.TwapSelectedOrderAccordion { + border-radius: 12px; + &.Mui-expanded { + margin: 0; + } + &:first-child { + border-radius: 12px; + } + &:last-child { + border-radius: 12px; + } + .MuiAccordionDetails-root { + display: flex; + flex-direction: column; + gap: 8px; + } + + .MuiAccordionSummary-expandIcon { + color: $textSecondary; + } + .MuiAccordionSummary-root.Mui-expanded { + min-height: 48px; + } + .MuiAccordionSummary-content.Mui-expanded { + margin: 0px 0; + min-height: auto; + } +} + +.TwapSelectedOrder { + padding: 24px 24px 0; + padding-bottom: 30px; + max-height: 80vh; + height: auto; + width: 100%; + border-radius: 20px; + display: flex; + flex-direction: column; + background: $bgColor; + backdrop-filter: blur(9.9px); + border: 1px solid $grey2; + overflow-y: auto; +} + +.TwapSelectedOrderBody { + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; + -webkit-overflow-scrolling: touch; /* For smooth scrolling on touch devices */ + scrollbar-width: none; /* For Firefox */ + -ms-overflow-style: none; /* For Internet Explorer and Edge */ + &::-webkit-scrollbar { + display: none; /* For Chrome, Safari, and Edge */ + } +} + +.TwapSelectedOrderCurrencies { + display: flex; + flex-direction: column; + gap: 20px; + margin-bottom: 30px; + & .TwapSelectedOrderCurrency { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + &Left { + display: flex; + flex-direction: column; + gap: 5px; + } + &Symbol { + font-weight: 600; + font-size: 18px; + } + &Label { + font-size: 15px; + } + } +} + +.TwapOrdersList { + padding: 24px 24px 0; + padding-bottom: 20px; + height: 80vh; + border-radius: 20px; + display: flex; + flex-direction: column; + background: $bgColor; + backdrop-filter: blur(9.9px); + border: 1px solid $grey2; + overflow: hidden; + &Empty { + text-align: center; + width: 100%; + margin-top: 40px; + font-size: 18px; + } + + @include media('screen', ' { - liquidityHubAnalytics.onDexSwapRequest(); const estimatedCalls: EstimatedSwapCall[] = await Promise.all( swapCalls.map((call) => { const { @@ -278,7 +276,6 @@ export function useSwapCallback( : { from: account }), }) .then((response: TransactionResponse) => { - liquidityHubAnalytics.onDexSwapSuccess(response.hash); const inputSymbol = trade.inputAmount.currency.symbol; const outputSymbol = trade.outputAmount.currency.symbol; const inputAmount = formatTokenAmount(trade.inputAmount); @@ -307,7 +304,6 @@ export function useSwapCallback( return { response, summary: withVersion }; }) .catch((error: any) => { - liquidityHubAnalytics.onDexSwapFailed(error.message); // if the user rejected the tx, pass this along if (error?.code === 'ACTION_REJECTED') { throw new Error('Transaction rejected.'); diff --git a/src/hooks/v3/useSwapCallback.ts b/src/hooks/v3/useSwapCallback.ts index b7ec13ada..76b301f3f 100644 --- a/src/hooks/v3/useSwapCallback.ts +++ b/src/hooks/v3/useSwapCallback.ts @@ -15,7 +15,6 @@ import { SwapRouter } from 'lib/src/swapRouter'; import useTransactionDeadline from 'hooks/useTransactionDeadline'; import { getTradeVersion } from 'utils/v3/getTradeVersion'; import { useTransactionAdder } from 'state/transactions/hooks'; -import { liquidityHubAnalytics } from 'components/Swap/LiquidityHub'; import { TransactionType } from 'models/enums'; enum SwapCallbackState { @@ -266,7 +265,6 @@ export function useSwapCallback( response: TransactionResponse; summary: string; }> { - liquidityHubAnalytics.onDexSwapRequest(); const estimatedCalls: SwapCallEstimate[] = await Promise.all( swapCalls.map((call) => { const { address, calldata, value } = call; @@ -356,7 +354,6 @@ export function useSwapCallback( ...(value && !isZero(value) ? { value } : {}), }) .then((response) => { - liquidityHubAnalytics.onDexSwapSuccess(response.hash); const inputSymbol = trade.inputAmount.currency.symbol; const outputSymbol = trade.outputAmount.currency.symbol; const inputAmount = trade.inputAmount.toSignificant(4); @@ -387,7 +384,6 @@ export function useSwapCallback( return { response, summary: withVersion }; }) .catch((error) => { - liquidityHubAnalytics.onDexSwapFailed(error.message); // if the user rejected the tx, pass this along if (error?.code === 'ACTION_REJECTED') { throw new Error('Transaction rejected.'); diff --git a/src/layouts/PageLayout.tsx b/src/layouts/PageLayout.tsx index f23756b6b..89eb3ac14 100755 --- a/src/layouts/PageLayout.tsx +++ b/src/layouts/PageLayout.tsx @@ -127,8 +127,8 @@ const PageLayout: React.FC = ({ children, name }) => { const displayNewsletter = false; return ( - - {openPassModal && } + + {/* {openPassModal && } */} {showBetaBanner && } {displayNewsletter && }
{data.map((row) => ( - + {row.date} {row.price.toFixed(3)} @@ -112,7 +112,7 @@ export const HistoricalTable: React.FC<{ > {row.change.toFixed(2)}% - + ))} @@ -121,3 +121,9 @@ export const HistoricalTable: React.FC<{ ); }; + +const StyledTableRow = styled(TableRow)({ + '&:last-child td, &:last-child th': { + border: 0, + }, +}); diff --git a/src/pages/PerpsPage/Pairs.tsx b/src/pages/PerpsPage/Pairs.tsx index 052d2c32e..06fc324e9 100644 --- a/src/pages/PerpsPage/Pairs.tsx +++ b/src/pages/PerpsPage/Pairs.tsx @@ -2,15 +2,7 @@ import React, { useState } from 'react'; import { useMarketsStream } from '@orderly.network/hooks'; import { OrderSide, OrderStatus, OrderType } from '@orderly.network/types'; import { FC } from 'react'; -import { - AppBar, - Toolbar, - Typography, - MenuItem, - Select, - SelectChangeEvent, - Box, -} from '@mui/material'; +import { AppBar, Box, MenuItem, Select, Toolbar, Typography } from '@material-ui/core'; interface Ticker { symbol: string; @@ -60,7 +52,7 @@ export const Pairs: FC = () => { tickers[0].symbol, ); - const handleChange = (event: SelectChangeEvent) => { + const handleChange = (event: any) => { setSelectedSymbol(event.target.value as string); }; @@ -75,7 +67,7 @@ export const Pairs: FC = () => {