diff --git a/config-mainnet.json b/config-mainnet.json index 63f1567d..1fd8caa0 100644 --- a/config-mainnet.json +++ b/config-mainnet.json @@ -7,6 +7,8 @@ "USDC_ADDRESS": "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", "BTC_ADDRESS": "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", "STRK_ADDRESS": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "VE_CRM_ADDRESS": "0x3c0286e9e428a130ae7fbbe911b794e8a829c367dd788e7cfe3efb0367548fa", + "CRM_ADDRESS": "0x51c4b1fe3bf6774b87ad0b15ef5d1472759076e42944fff9b9f641ff13e5bbe", "ETH_USDC_CALL_ADDRESS": "0x70cad6be2c3fc48c745e4a4b70ef578d9c79b46ffac4cd93ec7b61f951c7c5c", "ETH_USDC_PUT_ADDRESS": "0x466e3a6731571cf5d74c5b0d9c508bfb71438de10f9a13269177b01d6f07159", "BTC_USDC_CALL_ADDRESS": "0x35db72a814c9b30301f646a8fa8c192ff63a0dc82beb390a36e6e9eba55b6db", diff --git a/config-testnet.json b/config-testnet.json index 27ea8f5f..65979b6a 100644 --- a/config-testnet.json +++ b/config-testnet.json @@ -2,11 +2,13 @@ "NETWORK": "testnet", "API_URL": "https://api.carmine.finance", "AMM_ADDRESS": "0x07587280e108db0681eb60190ed1f5bd737965177f6c13551ab2e50d6644d382", - "GOVERNANCE_ADDRESS": "TODO", + "GOVERNANCE_ADDRESS": "0x02c027aad2668aa66d232d846c190785ade993b032f9ad44893739b365b89d34", "ETH_ADDRESS": "0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", "USDC_ADDRESS": "0x07b5be4ebf7c50f67d54d328c45ee21b06de8e39240c7943b25ab811c07c43e4", "BTC_ADDRESS": "0x00c6164da852d230360333d6ade3551ee3e48124c815704f51fa7f12d8287dcc", "STRK_ADDRESS": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "VE_CRM_ADDRESS": "0x4a6bd0934f92e8419280e3b7d83db9a1ed15c25991ee91713042dddebe72b7e", + "CRM_ADDRESS": "0x5e5bf796ce003158104836ce0eb92ba4387676cc43ba9bfa540cdabe66c2c7e", "ETH_USDC_CALL_ADDRESS": "0x201f9513450a32a1f3803f289ee7d104735cd1f933712fffc1cdae98ad6c008", "ETH_USDC_PUT_ADDRESS": "0x3271dbd7dc85550648cd561595fae76393490a8650b9225e9b4392e09b20c7c", "BTC_USDC_CALL_ADDRESS": "0x6fbe70f97f93f9b42707b7cadabba472eb810af5fe1f06da04583b1724a8c2b", diff --git a/package-lock.json b/package-lock.json index 11094a8e..087ecef8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "carmine-finance-app", - "version": "0.1.0", + "version": "1.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "carmine-finance-app", - "version": "0.1.0", + "version": "1.2.0", "dependencies": { "@avnu/avnu-sdk": "^1.2.4", "@emotion/react": "^11.10.4", @@ -33,6 +33,7 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "*", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", "@semantic-release/github": "^10.0.6", @@ -112,81 +113,17 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/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==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/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==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", @@ -271,13 +208,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -285,11 +222,11 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -330,18 +267,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.9.tgz", - "integrity": "sha512-B2L9neXTIyPQoXDm+NtovPvG6VOLWnaXu3BIeVDWwdKFgG30oNa6CqVGiJPDWQwIAK49t9gnQI9c6K6RzabiKw==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz", + "integrity": "sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", "semver": "^6.3.1" }, "engines": { @@ -399,42 +336,46 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz", + "integrity": "sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==", "dependencies": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -470,20 +411,20 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "engines": { "node": ">=6.9.0" } @@ -505,13 +446,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -532,39 +473,40 @@ } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "engines": { "node": ">=6.9.0" } @@ -604,13 +546,14 @@ } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -681,9 +624,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1678,13 +1621,13 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -2154,31 +2097,31 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2187,12 +2130,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -3215,13 +3158,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -3236,9 +3179,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -3258,9 +3201,9 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -25075,63 +25018,12 @@ "requires": {} }, "@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "requires": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "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==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { @@ -25196,22 +25088,22 @@ } }, "@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "requires": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, "@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { @@ -25242,18 +25134,18 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.9.tgz", - "integrity": "sha512-B2L9neXTIyPQoXDm+NtovPvG6VOLWnaXu3BIeVDWwdKFgG30oNa6CqVGiJPDWQwIAK49t9gnQI9c6K6RzabiKw==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz", + "integrity": "sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", "semver": "^6.3.1" }, "dependencies": { @@ -25294,33 +25186,37 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "requires": { + "@babel/types": "^7.24.7" + } }, "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz", + "integrity": "sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==", "requires": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-module-imports": { @@ -25344,17 +25240,17 @@ } }, "@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" } }, "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==" }, "@babel/helper-remap-async-to-generator": { "version": "7.22.20", @@ -25367,13 +25263,13 @@ } }, "@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" } }, "@babel/helper-simple-access": { @@ -25385,30 +25281,31 @@ } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "requires": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" } }, "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==" }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==" }, "@babel/helper-validator-option": { "version": "7.23.5", @@ -25436,13 +25333,14 @@ } }, "@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "requires": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "dependencies": { "ansi-styles": { @@ -25497,9 +25395,9 @@ } }, "@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==" + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.23.3", @@ -26109,13 +26007,13 @@ } }, "@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", "requires": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, @@ -26439,39 +26337,39 @@ } }, "@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "requires": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", "debug": "^4.3.1", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, @@ -27169,13 +27067,13 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { @@ -27184,9 +27082,9 @@ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" }, "@jridgewell/source-map": { "version": "0.3.5", @@ -27203,9 +27101,9 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "requires": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" diff --git a/package.json b/package.json index 521cad04..a0cab802 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ ] }, "devDependencies": { - "@babel/plugin-proposal-private-property-in-object": "*", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", "@semantic-release/github": "^10.0.6", @@ -74,4 +74,4 @@ "typescript": "^4.8.4", "web-vitals": "^2.1.4" } -} +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 4122e876..6d738a03 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -45,8 +45,8 @@ const App = () => { {acceptedTermsAndConditions ? ( <> - + {oldPathRedirects.map(([oldPath, newPath], i) => ( { } /> } /> } /> - } /> + } /> } /> } /> } /> diff --git a/src/abi/governance_abi.json b/src/abi/governance_abi.json index e419cbea..d7b6fdac 100644 --- a/src/abi/governance_abi.json +++ b/src/abi/governance_abi.json @@ -1,132 +1,787 @@ [ { + "name": "Governance", + "type": "impl", + "interface_name": "konoha::contract::IGovernance" + }, + { + "name": "konoha::contract::IGovernance", + "type": "interface", + "items": [ + { + "name": "get_governance_token_address", + "type": "function", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "view" + } + ] + }, + { + "name": "CarmineGovernance", + "type": "impl", + "interface_name": "amm_governance::contract::ICarmineGovernance" + }, + { + "name": "amm_governance::contract::ICarmineGovernance", + "type": "interface", + "items": [ + { + "name": "get_amm_address", + "type": "function", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "view" + } + ] + }, + { + "name": "Migrate", + "type": "impl", + "interface_name": "amm_governance::contract::IMigrate" + }, + { + "name": "amm_governance::contract::IMigrate", + "type": "interface", + "items": [ + { + "name": "add_custom_proposals", + "type": "function", + "inputs": [], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "name": "Airdrop", + "type": "impl", + "interface_name": "konoha::airdrop::IAirdrop" + }, + { + "name": "konoha::airdrop::IAirdrop", + "type": "interface", + "items": [ + { + "name": "claim", + "type": "function", + "inputs": [ + { + "name": "claimee", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u128" + }, + { + "name": "proof", + "type": "core::array::Array::" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "name": "Proposals", + "type": "impl", + "interface_name": "amm_governance::proposals::IProposals" + }, + { + "name": "konoha::types::PropDetails", "type": "struct", - "name": "governance::types::PropDetails", "members": [ - { "name": "impl_hash", "type": "core::felt252" }, - { "name": "to_upgrade", "type": "core::felt252" } + { + "name": "payload", + "type": "core::felt252" + }, + { + "name": "to_upgrade", + "type": "core::felt252" + } ] }, { - "type": "function", - "name": "get_proposal_details", - "inputs": [{ "name": "prop_id", "type": "core::felt252" }], - "outputs": [{ "type": "governance::types::PropDetails" }], - "state_mutability": "view" + "name": "core::array::Span::", + "type": "struct", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] }, { - "type": "function", - "name": "get_vote_counts", - "inputs": [{ "name": "prop_id", "type": "core::felt252" }], - "outputs": [{ "type": "(core::integer::u128, core::integer::u128)" }], - "state_mutability": "view" + "name": "core::bool", + "type": "enum", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] }, { - "type": "function", - "name": "submit_proposal", - "inputs": [ - { "name": "impl_hash", "type": "core::felt252" }, - { "name": "to_upgrade", "type": "core::felt252" } - ], - "outputs": [{ "type": "core::felt252" }], - "state_mutability": "external" + "name": "konoha::types::CustomProposalConfig", + "type": "struct", + "members": [ + { + "name": "target", + "type": "core::felt252" + }, + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "library_call", + "type": "core::bool" + } + ] }, { - "type": "function", - "name": "vote", - "inputs": [ - { "name": "prop_id", "type": "core::felt252" }, - { "name": "opinion", "type": "core::felt252" } - ], - "outputs": [], - "state_mutability": "external" + "name": "amm_governance::proposals::IProposals", + "type": "interface", + "items": [ + { + "name": "vote", + "type": "function", + "inputs": [ + { + "name": "prop_id", + "type": "core::felt252" + }, + { + "name": "opinion", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "name": "get_proposal_details", + "type": "function", + "inputs": [ + { + "name": "prop_id", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "konoha::types::PropDetails" + } + ], + "state_mutability": "view" + }, + { + "name": "get_vote_counts", + "type": "function", + "inputs": [ + { + "name": "prop_id", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "(core::integer::u128, core::integer::u128)" + } + ], + "state_mutability": "view" + }, + { + "name": "submit_proposal", + "type": "function", + "inputs": [ + { + "name": "payload", + "type": "core::felt252" + }, + { + "name": "to_upgrade", + "type": "core::integer::u64" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "external" + }, + { + "name": "get_proposal_status", + "type": "function", + "inputs": [ + { + "name": "prop_id", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "name": "get_live_proposals", + "type": "function", + "inputs": [], + "outputs": [ + { + "type": "core::array::Array::" + } + ], + "state_mutability": "view" + }, + { + "name": "get_user_voted", + "type": "function", + "inputs": [ + { + "name": "user_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "prop_id", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "name": "submit_custom_proposal", + "type": "function", + "inputs": [ + { + "name": "custom_proposal_type", + "type": "core::integer::u32" + }, + { + "name": "calldata", + "type": "core::array::Span::" + } + ], + "outputs": [ + { + "type": "core::integer::u32" + } + ], + "state_mutability": "external" + }, + { + "name": "get_custom_proposal_type", + "type": "function", + "inputs": [ + { + "name": "i", + "type": "core::integer::u32" + } + ], + "outputs": [ + { + "type": "konoha::types::CustomProposalConfig" + } + ], + "state_mutability": "view" + } + ] }, { - "type": "function", - "name": "get_proposal_status", - "inputs": [{ "name": "prop_id", "type": "core::felt252" }], - "outputs": [{ "type": "core::felt252" }], - "state_mutability": "view" + "name": "Upgrades", + "type": "impl", + "interface_name": "amm_governance::upgrades::IUpgrades" }, { - "type": "function", - "name": "vote_investor", - "inputs": [ - { "name": "prop_id", "type": "core::felt252" }, - { "name": "opinion", "type": "core::felt252" } - ], - "outputs": [], - "state_mutability": "external" + "name": "amm_governance::upgrades::IUpgrades", + "type": "interface", + "items": [ + { + "name": "apply_passed_proposal", + "type": "function", + "inputs": [ + { + "name": "prop_id", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] }, { - "type": "function", - "name": "get_governance_token_address", - "inputs": [], - "outputs": [ - { "type": "core::starknet::contract_address::ContractAddress" } - ], - "state_mutability": "view" + "name": "Staking", + "type": "impl", + "interface_name": "amm_governance::staking::IStaking" }, { - "type": "function", - "name": "get_amm_address", - "inputs": [], - "outputs": [ - { "type": "core::starknet::contract_address::ContractAddress" } - ], - "state_mutability": "view" + "name": "amm_governance::staking::staking::Stake", + "type": "struct", + "members": [ + { + "name": "amount_staked", + "type": "core::integer::u128" + }, + { + "name": "amount_voting_token", + "type": "core::integer::u128" + }, + { + "name": "start_date", + "type": "core::integer::u64" + }, + { + "name": "length", + "type": "core::integer::u64" + }, + { + "name": "withdrawn", + "type": "core::bool" + } + ] }, { - "type": "function", - "name": "apply_passed_proposal", - "inputs": [{ "name": "prop_id", "type": "core::felt252" }], - "outputs": [], - "state_mutability": "external" + "name": "amm_governance::staking::IStaking", + "type": "interface", + "items": [ + { + "name": "stake", + "type": "function", + "inputs": [ + { + "name": "length", + "type": "core::integer::u64" + }, + { + "name": "amount", + "type": "core::integer::u128" + } + ], + "outputs": [ + { + "type": "core::integer::u32" + } + ], + "state_mutability": "external" + }, + { + "name": "unstake", + "type": "function", + "inputs": [ + { + "name": "id", + "type": "core::integer::u32" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "name": "unstake_airdrop", + "type": "function", + "inputs": [], + "outputs": [], + "state_mutability": "external" + }, + { + "name": "set_curve_point", + "type": "function", + "inputs": [ + { + "name": "length", + "type": "core::integer::u64" + }, + { + "name": "conversion_rate", + "type": "core::integer::u16" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "name": "set_floating_token_address", + "type": "function", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "name": "initialize_floating_token_address", + "type": "function", + "inputs": [], + "outputs": [], + "state_mutability": "external" + }, + { + "name": "get_floating_token_address", + "type": "function", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "view" + }, + { + "name": "get_stake", + "type": "function", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "stake_id", + "type": "core::integer::u32" + } + ], + "outputs": [ + { + "type": "amm_governance::staking::staking::Stake" + } + ], + "state_mutability": "view" + }, + { + "name": "get_total_voting_power", + "type": "function", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::integer::u128" + } + ], + "state_mutability": "view" + }, + { + "name": "get_adjusted_voting_power", + "type": "function", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::integer::u128" + } + ], + "state_mutability": "view" + } + ] }, { - "type": "function", - "name": "claim", + "name": "constructor", + "type": "constructor", "inputs": [ { + "name": "voting_token_class", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "floating_token_class", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "recipient", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "kind": "struct", + "name": "konoha::airdrop::airdrop::Claimed", + "type": "event", + "members": [ + { + "kind": "data", "name": "address", "type": "core::starknet::contract_address::ContractAddress" }, - { "name": "amount", "type": "core::integer::u128" }, - { "name": "proof", "type": "core::array::Array::" } - ], - "outputs": [], - "state_mutability": "external" + { + "kind": "data", + "name": "received", + "type": "core::integer::u128" + } + ] }, { + "kind": "enum", + "name": "konoha::airdrop::airdrop::Event", "type": "event", - "name": "Proposed", - "inputs": [ - { "name": "prop_id", "type": "core::felt252" }, - { "name": "impl_hash", "type": "core::felt252" }, - { "name": "to_upgrade", "type": "core::felt252" } + "variants": [ + { + "kind": "nested", + "name": "Claimed", + "type": "konoha::airdrop::airdrop::Claimed" + } ] }, { + "kind": "struct", + "name": "amm_governance::proposals::proposals::Proposed", "type": "event", - "name": "Voted", - "inputs": [ - { "name": "prop_id", "type": "core::felt252" }, + "members": [ { + "kind": "data", + "name": "prop_id", + "type": "core::felt252" + }, + { + "kind": "data", + "name": "payload", + "type": "core::felt252" + }, + { + "kind": "data", + "name": "to_upgrade", + "type": "core::integer::u64" + } + ] + }, + { + "kind": "struct", + "name": "amm_governance::proposals::proposals::Voted", + "type": "event", + "members": [ + { + "kind": "data", + "name": "prop_id", + "type": "core::felt252" + }, + { + "kind": "data", "name": "voter", "type": "core::starknet::contract_address::ContractAddress" }, - { "name": "opinion", "type": "core::felt252" } + { + "kind": "data", + "name": "opinion", + "type": "core::felt252" + } + ] + }, + { + "kind": "enum", + "name": "amm_governance::proposals::proposals::Event", + "type": "event", + "variants": [ + { + "kind": "nested", + "name": "Proposed", + "type": "amm_governance::proposals::proposals::Proposed" + }, + { + "kind": "nested", + "name": "Voted", + "type": "amm_governance::proposals::proposals::Voted" + } ] }, { + "kind": "struct", + "name": "amm_governance::upgrades::upgrades::Upgraded", "type": "event", - "name": "Claimed", - "inputs": [ + "members": [ { - "name": "address", + "kind": "data", + "name": "prop_id", + "type": "core::integer::u64" + }, + { + "kind": "data", + "name": "upgrade_type", + "type": "core::integer::u64" + } + ] + }, + { + "kind": "enum", + "name": "amm_governance::upgrades::upgrades::Event", + "type": "event", + "variants": [ + { + "kind": "nested", + "name": "Upgraded", + "type": "amm_governance::upgrades::upgrades::Upgraded" + } + ] + }, + { + "kind": "struct", + "name": "amm_governance::staking::staking::Staked", + "type": "event", + "members": [ + { + "kind": "data", + "name": "user", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "kind": "data", + "name": "stake_id", + "type": "core::integer::u32" + }, + { + "kind": "data", + "name": "amount", + "type": "core::integer::u128" + }, + { + "kind": "data", + "name": "amount_voting_token", + "type": "core::integer::u128" + }, + { + "kind": "data", + "name": "start_date", + "type": "core::integer::u64" + }, + { + "kind": "data", + "name": "length", + "type": "core::integer::u64" + } + ] + }, + { + "kind": "struct", + "name": "amm_governance::staking::staking::Unstaked", + "type": "event", + "members": [ + { + "kind": "data", + "name": "user", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "kind": "data", + "name": "stake_id", + "type": "core::integer::u32" + }, + { + "kind": "data", + "name": "amount", + "type": "core::integer::u128" + }, + { + "kind": "data", + "name": "amount_voting_token", + "type": "core::integer::u128" + }, + { + "kind": "data", + "name": "start_date", + "type": "core::integer::u64" + }, + { + "kind": "data", + "name": "length", + "type": "core::integer::u64" + } + ] + }, + { + "kind": "struct", + "name": "amm_governance::staking::staking::UnstakedAirdrop", + "type": "event", + "members": [ + { + "kind": "data", + "name": "user", "type": "core::starknet::contract_address::ContractAddress" }, - { "name": "received", "type": "core::integer::u128" } + { + "kind": "data", + "name": "amount", + "type": "core::integer::u128" + } + ] + }, + { + "kind": "enum", + "name": "amm_governance::staking::staking::Event", + "type": "event", + "variants": [ + { + "kind": "nested", + "name": "Staked", + "type": "amm_governance::staking::staking::Staked" + }, + { + "kind": "nested", + "name": "Unstaked", + "type": "amm_governance::staking::staking::Unstaked" + }, + { + "kind": "nested", + "name": "UnstakedAirdrop", + "type": "amm_governance::staking::staking::UnstakedAirdrop" + } + ] + }, + { + "kind": "enum", + "name": "amm_governance::contract::Governance::Event", + "type": "event", + "variants": [ + { + "kind": "nested", + "name": "AirdropEvent", + "type": "konoha::airdrop::airdrop::Event" + }, + { + "kind": "nested", + "name": "ProposalsEvent", + "type": "amm_governance::proposals::proposals::Event" + }, + { + "kind": "nested", + "name": "UpgradesEvent", + "type": "amm_governance::upgrades::upgrades::Event" + }, + { + "kind": "nested", + "name": "StakingEvent", + "type": "amm_governance::staking::staking::Event" + } ] } -] +] \ No newline at end of file diff --git a/src/calls/balanceOf.ts b/src/calls/balanceOf.ts index ac62cf83..3224b051 100644 --- a/src/calls/balanceOf.ts +++ b/src/calls/balanceOf.ts @@ -6,11 +6,10 @@ import { ETH_ADDRESS, STRK_ADDRESS, USDC_ADDRESS, + VE_CRM_ADDRESS, } from "../constants/amm"; import { Token, TokenKey } from "../classes/Token"; - -const CARM_TOKEN_ADDRESS = - "0x3c0286e9e428a130ae7fbbe911b794e8a829c367dd788e7cfe3efb0367548fa"; +import { provider } from "../network/provider"; export const balanceFromTokenAddress = async ( account: AccountInterface, @@ -57,7 +56,16 @@ export const balanceOfStrk = async ( export const balanceOfCarmineToken = async ( account: AccountInterface -): Promise => balanceFromTokenAddress(account, CARM_TOKEN_ADDRESS); +): Promise => balanceFromTokenAddress(account, VE_CRM_ADDRESS); + +export const balanceOf = async ( + address: string, + token: string +): Promise => { + const contract = new Contract(ABI, token, provider); + const balance = await contract.balanceOf(address); + return balance; +}; export const getUserBalance = async ( account: AccountInterface diff --git a/src/calls/carmineStake.ts b/src/calls/carmineStake.ts new file mode 100644 index 00000000..f2569cad --- /dev/null +++ b/src/calls/carmineStake.ts @@ -0,0 +1,172 @@ +import { AccountInterface } from "starknet"; +import { governanceContract } from "../constants/starknet"; +import { CarmineStakeResult } from "../types/governance"; + +import GovernanceABI from "../abi/governance_abi.json"; +import { GOVERNANCE_ADDRESS } from "../constants/amm"; +import { + addTx, + markTxAsDone, + markTxAsFailed, + showToast, +} from "../redux/actions"; +import { TransactionAction } from "../redux/reducers/transactions"; +import { afterTransaction } from "../utils/blockchain"; +import { ToastType } from "../redux/reducers/ui"; +import { TransactionState, TxTracking } from "../types/network"; +import { CarmineStake } from "../classes/CarmineStake"; + +const isEmptyStake = (stake: CarmineStakeResult): boolean => { + if (stake.amount_staked === 0n && stake.start_date === 0n) { + return true; + } + return false; +}; + +export const getStakes = async (address: string): Promise => { + const increment = 5; + const stakes = []; + let lastId = 0; + + while (true) { + const promises = []; + for (let i = lastId; i < lastId + increment; i++) { + promises.push(governanceContract.get_stake(address, i)); + } + const values = (await Promise.all(promises)) as CarmineStakeResult[]; + stakes.push(...values.filter((v) => !isEmptyStake(v))); + if (values.find((v) => isEmptyStake(v))) { + break; + } + lastId += increment; + } + + return stakes.map((s) => new CarmineStake(s)); +}; + +export const stakeCarmineToken = async ( + account: AccountInterface, + length: bigint, + amount: bigint, + setState: TxTracking +) => { + setState(TransactionState.Processing); + const call = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "stake", + calldata: [length, amount], + }; + const res = await account.execute(call, [GovernanceABI]).catch(() => { + showToast("Failed to stake CRM", ToastType.Error); + setState(TransactionState.Fail); + return undefined; + }); + + if (!res) { + return; + } + + const { transaction_hash: hash } = res; + + addTx(hash, `stake-${hash}`, TransactionAction.TradeOpen); + afterTransaction( + hash, + () => { + markTxAsDone(hash); + showToast("Successfully staked CRM", ToastType.Success); + setState(TransactionState.Success); + }, + () => { + markTxAsFailed(hash); + showToast("Failed to stake CRM", ToastType.Error); + setState(TransactionState.Fail); + } + ); +}; + +export const claimAndStakeCarmineToken = async ( + account: AccountInterface, + claimData: string[], + length: bigint, + amount: bigint, + setState: TxTracking +) => { + setState(TransactionState.Processing); + const [address, claimAmount, ...proof] = claimData; + const claimCall = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "claim", + calldata: [address, claimAmount, String(proof.length), ...proof], + }; + const stakeCall = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "stake", + calldata: [length, amount], + }; + const res = await account + .execute([claimCall, stakeCall], [GovernanceABI]) + .catch(() => { + showToast("Failed to claim & stake", ToastType.Error); + setState(TransactionState.Fail); + return undefined; + }); + + if (!res) { + return; + } + + const { transaction_hash: hash } = res; + + addTx(hash, `stake-${hash}`, TransactionAction.TradeOpen); + afterTransaction( + hash, + () => { + markTxAsDone(hash); + showToast("Successfully claimed & staked CRM", ToastType.Success); + setState(TransactionState.Success); + }, + () => { + markTxAsFailed(hash); + showToast("Failed to claim & stake CRM", ToastType.Error); + setState(TransactionState.Fail); + } + ); +}; + +export const unstakeAirdrop = async ( + account: AccountInterface, + setTxState: TxTracking +) => { + setTxState(TransactionState.Processing); + const call = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "unstake_airdrop", + calldata: [], + }; + const res = await account.execute(call, [GovernanceABI]).catch(() => { + showToast("Failed to unstake", ToastType.Error); + return undefined; + }); + + if (!res) { + setTxState(TransactionState.Fail); + return; + } + + const { transaction_hash: hash } = res; + + addTx(hash, `unstake-${hash}`, TransactionAction.ClaimAirdrop); + afterTransaction( + hash, + () => { + markTxAsDone(hash); + showToast("Successfully unstaked CRM", ToastType.Success); + setTxState(TransactionState.Success); + }, + () => { + markTxAsFailed(hash); + showToast("Failed to unstake CRM", ToastType.Error); + setTxState(TransactionState.Fail); + } + ); +}; diff --git a/src/classes/CarmineStake.ts b/src/classes/CarmineStake.ts new file mode 100644 index 00000000..611d97bd --- /dev/null +++ b/src/classes/CarmineStake.ts @@ -0,0 +1,84 @@ +import { CARMINE_STAKING_MONTH, CARMINE_STAKING_YEAR } from "../constants/amm"; +import { CarmineStakeResult } from "../types/governance"; +import { shortInteger } from "../utils/computations"; + +const formatDate = (ts: number) => + new Intl.DateTimeFormat("default", { + hour: "numeric", + minute: "numeric", + month: "numeric", + day: "numeric", + year: "numeric", + timeZoneName: "short", + }).format(ts * 1000); + +export class CarmineStake { + public amountStaked; + public amountVotingToken; + public start; + public length; + public withdrawn; + public end; + + constructor({ + amount_staked, + amount_voting_token, + start_date, + length, + withdrawn, + }: CarmineStakeResult) { + const numStart = Number(start_date); + const numLength = Number(length); + this.amountStaked = amount_staked; + this.amountVotingToken = amount_voting_token; + this.start = numStart; + this.length = numLength; + this.withdrawn = withdrawn; + this.end = numStart + numLength; + } + + get isActive(): boolean { + const now = Date.now() / 1000; + return !this.withdrawn && this.end > now; + } + + get isExpired(): boolean { + const now = Date.now() / 1000; + return !this.withdrawn && this.end <= now; + } + + get isNotWithdrawn(): boolean { + return !this.withdrawn; + } + + get startDate(): string { + return formatDate(this.start); + } + + get endDate(): string { + return formatDate(this.end); + } + + get period(): string { + const months = this.length / CARMINE_STAKING_MONTH; + + if (this.length === CARMINE_STAKING_MONTH) { + return "1 month"; + } + if (this.length === CARMINE_STAKING_YEAR) { + return "1 year"; + } + if (months > 12) { + return months / 12 + "years"; + } + return months + " months"; + } + + get amountStakedHumanReadable(): number { + return shortInteger(this.amountStaked, 18); + } + + get amountVotingTokenHumanReadable(): number { + return shortInteger(this.amountVotingToken, 18); + } +} diff --git a/src/components/Airdrop/Airdrop.tsx b/src/components/Airdrop/Airdrop.tsx index 7c8e85e5..e140bd08 100644 --- a/src/components/Airdrop/Airdrop.tsx +++ b/src/components/Airdrop/Airdrop.tsx @@ -1,97 +1,112 @@ -import { ClaimButton } from "./ClaimButton"; -import { useAccount } from "../../hooks/useAccount"; -import { useEffect, useState } from "react"; -import { useNetwork } from "../../hooks/useNetwork"; -import { ProofResult, getProof } from "./getProof"; +import { useState } from "react"; +import { useQuery } from "react-query"; import { AccountInterface } from "starknet"; + +import { useAccount } from "../../hooks/useAccount"; +import { Eligible, getAirdropDataQuery } from "./getProof"; import { shortInteger } from "../../utils/computations"; -import { NETWORK } from "../../constants/amm"; -import styles from "../../style/table.module.css"; +import { isMainnet } from "../../constants/amm"; +import { QueryKeys } from "../../queries/keys"; +import { AirdropModal } from "./AirdropModal"; -type Props = { - account: AccountInterface | undefined; - message: string; - data?: string[]; +import buttonStyles from "../../style/button.module.css"; +import airdropStyles from "./airdrop.module.css"; + +const ClaimAndStake = ({ + account, + data, +}: { + account: AccountInterface; + data: Eligible; +}) => { + const [open, setOpen] = useState(false); + const amountHumanReadable = shortInteger(data.claimable, 18); + + return ( +
+

Airdrop

+
+ + You are eligible to claim {amountHumanReadable} veCRM! + + +
+ +
+ ); }; -const AirdropTemplate = ({ account, message, data }: Props) => ( +const AirdropTemplate = ({ message }: { message: string }) => (

Airdrop

-
- {message} {account && } -
+
{message}
); -export const Airdrop = () => { - const account = useAccount(); - const network = useNetwork(); - const [loading, setLoading] = useState(false); - const [data, setData] = useState(); - - const isMainnet = NETWORK === "mainnet"; - - useEffect(() => { - if (account && isMainnet) { - setLoading(true); - getProof(account).then((res) => { - setData(res); - setLoading(false); - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [account, network]); - - if (!isMainnet) { - return ( - - ); - } +export const AirdropWithAccount = ({ + account, +}: { + account: AccountInterface; +}) => { + const { isLoading, isError, data } = useQuery( + [QueryKeys.airdropData, account.address], + getAirdropDataQuery + ); - if (!account) { + if (isError) { return ( - + ); } - if (loading || !data) { + if (isLoading || !data) { return ( - + ); } if (data.eligible) { - if (data.claimable === "0") { + if (data.claimable === 0n) { const amount = shortInteger(data.claimed, 18); return ( ); } - const amount = shortInteger(data.claimable, 18); - const message = `${amount} Tokens available.`; + return ; + } + + return ( + + ); +}; + +export const Airdrop = () => { + const account = useAccount(); + if (!account) { return ( - + ); } - return ( - - ); + if (!isMainnet) { + return ( + + ); + } + + return ; }; diff --git a/src/components/Airdrop/AirdropModal.tsx b/src/components/Airdrop/AirdropModal.tsx new file mode 100644 index 00000000..fdaf5494 --- /dev/null +++ b/src/components/Airdrop/AirdropModal.tsx @@ -0,0 +1,294 @@ +import { Dialog, Tooltip } from "@mui/material"; +import { AccountInterface } from "starknet"; +import { Eligible } from "./getProof"; + +import { shortInteger } from "../../utils/computations"; +import { + CARMINE_STAKING_MONTH, + CARMINE_STAKING_YEAR, + CRM_ADDRESS, + GOVERNANCE_ADDRESS, +} from "../../constants/amm"; +import { + addTx, + markTxAsDone, + markTxAsFailed, + showToast, +} from "../../redux/actions"; +import { afterTransaction } from "../../utils/blockchain"; +import { TransactionAction } from "../../redux/reducers/transactions"; +import { ToastType } from "../../redux/reducers/ui"; +import { useState } from "react"; +import { TransactionState, TxTracking } from "../../types/network"; +import { LoadingAnimation } from "../Loading/Loading"; + +import styles from "./airdrop.module.css"; +import buttonStyles from "../../style/button.module.css"; + +import GovernanceABI from "../../abi/governance_abi.json"; +import TokenABI from "../../abi/lptoken_abi.json"; +import { invalidateKey } from "../../queries/client"; +import { QueryKeys } from "../../queries/keys"; + +export const claim = async ( + account: AccountInterface, + data: string[], + setTxState: TxTracking +) => { + setTxState(TransactionState.Processing); + const [address, amount, ...proof] = data; + + // calldata structure explained here: https://github.com/CarmineOptions/carmine-api/tree/master/carmine-api-airdrop + // in Cairo, to send array you need to insert the length of array before the array items - "String(proof.length)" + const calldata = [address, amount, String(proof.length), ...proof]; + const call = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "claim", + calldata, + }; + const res = await account.execute(call, [GovernanceABI]).catch(() => null); + + if (res?.transaction_hash) { + const hash = res.transaction_hash; + + addTx(hash, "airdrop-claim", TransactionAction.ClaimAirdrop); + afterTransaction( + res.transaction_hash, + () => { + setTxState(TransactionState.Success); + showToast("Successfully claimed airdrop", ToastType.Success); + markTxAsDone(hash); + invalidateKey(QueryKeys.airdropData); + }, + () => { + setTxState(TransactionState.Fail); + showToast("Failed claiming airdrop", ToastType.Error); + markTxAsFailed(hash); + } + ); + } else { + setTxState(TransactionState.Fail); + showToast("Failed claiming airdrop", ToastType.Error); + } +}; + +export const claimAndStake = async ( + account: AccountInterface, + data: string[], + airdropAmount: bigint, + length: number, + setTxState: TxTracking +) => { + setTxState(TransactionState.Processing); + const [address, amount, ...proof] = data; + + // calldata structure explained here: https://github.com/CarmineOptions/carmine-api/tree/master/carmine-api-airdrop + // in Cairo, to send array you need to insert the length of array before the array items - "String(proof.length)" + const claimCall = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "claim", + calldata: [address, amount, String(proof.length), ...proof], + }; + const unstakeAirdropCall = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "unstake_airdrop", + calldata: [], + }; + const approveCall = { + contractAddress: CRM_ADDRESS, + entrypoint: "approve", + calldata: [GOVERNANCE_ADDRESS, airdropAmount.toString(10)], + }; + const stakeCall = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "stake", + calldata: [length, airdropAmount.toString(10)], + }; + + const res = await account + .execute( + [claimCall, unstakeAirdropCall, approveCall, stakeCall], + [GovernanceABI, GovernanceABI, TokenABI, GovernanceABI] + ) + .catch(() => null); + + if (res?.transaction_hash) { + const hash = res.transaction_hash; + + addTx(hash, `airdrop-stake-${length}`, TransactionAction.ClaimAirdrop); + afterTransaction( + res.transaction_hash, + () => { + setTxState(TransactionState.Success); + showToast("Successfully claimed and staked airdrop", ToastType.Success); + markTxAsDone(hash); + }, + () => { + setTxState(TransactionState.Fail); + showToast("Failed claiming airdrop", ToastType.Error); + markTxAsFailed(hash); + } + ); + } else { + setTxState(TransactionState.Fail); + showToast("Failed claiming airdrop", ToastType.Error); + } +}; + +type Props = { + account: AccountInterface; + data: Eligible; + open: boolean; + setOpen: (open: boolean) => void; +}; + +const stateToClassName = (state: TransactionState) => { + if (state === TransactionState.Success) { + return buttonStyles.green; + } + if (state === TransactionState.Fail) { + return buttonStyles.fail; + } + if (state === TransactionState.Processing) { + return buttonStyles.disabled; + } + return buttonStyles.secondary; +}; + +export const AirdropModal = ({ account, data, open, setOpen }: Props) => { + const [claimState, setClaimState] = useState(TransactionState.Initial); + const [monthState, setMonthState] = useState(TransactionState.Initial); + const [sixMonthsState, setSixMonthsState] = useState( + TransactionState.Initial + ); + const [yearState, setYearState] = useState(TransactionState.Initial); + + const handleClose = () => { + setOpen(false); + setClaimState(TransactionState.Initial); + setMonthState(TransactionState.Initial); + setSixMonthsState(TransactionState.Initial); + setYearState(TransactionState.Initial); + }; + + const handleClaim = () => claim(account, data.proof, setClaimState); + + const handle1month = () => { + setSixMonthsState(TransactionState.Processing); + setYearState(TransactionState.Processing); + claimAndStake( + account, + data.proof, + data.claimable, + CARMINE_STAKING_MONTH, + setMonthState + ).then(() => { + setSixMonthsState(TransactionState.Initial); + setYearState(TransactionState.Initial); + }); + }; + const handle6months = () => { + setMonthState(TransactionState.Processing); + setYearState(TransactionState.Processing); + claimAndStake( + account, + data.proof, + data.claimable, + 6 * CARMINE_STAKING_MONTH, + setSixMonthsState + ).then(() => { + setMonthState(TransactionState.Initial); + setYearState(TransactionState.Initial); + }); + }; + const handleYear = () => { + setMonthState(TransactionState.Processing); + setSixMonthsState(TransactionState.Processing); + claimAndStake( + account, + data.proof, + data.claimable, + CARMINE_STAKING_YEAR, + setYearState + ).then(() => { + setMonthState(TransactionState.Initial); + setSixMonthsState(TransactionState.Initial); + }); + }; + + return ( + +
+

Claim Airdrop

+

+ Congratulations! You are eligible to claim{" "} + {shortInteger(data.claimable, 18)} veCRM! +

+

You can claim and stake for any of these periods:

+
+ + + + + + + + + +
+

Alternatively you can claim without staking:

+
+ +
+
+
+ ); +}; diff --git a/src/components/Airdrop/airdrop.module.css b/src/components/Airdrop/airdrop.module.css index a92c7a2b..10537927 100644 --- a/src/components/Airdrop/airdrop.module.css +++ b/src/components/Airdrop/airdrop.module.css @@ -5,6 +5,22 @@ padding: 25px 50px; } +.textcontainer { + flex-flow: row; + border: 1px solid white; + padding: 25px 50px; + display: inline-block; +} + +.claim { + border: 1px solid white; + display: inline-flex; + align-items: center; + justify-content: flex-start; + gap: 50px; + padding: 20px 50px; +} + .active { padding-left: 7px; cursor: pointer; @@ -14,4 +30,41 @@ .inactive { padding-left: 7px; color: gray; +} + +.modal { + background: black; + border: 1px solid white; + padding: 30px; +} + +.modal h3 { + margin-top: 0; +} + +.buttongroup { + display: flex; + justify-content: space-between; + align-items: center; +} + +.singlebutton { + display: flex; + justify-content: space-around; + align-items: center; +} + +@media (max-width: 800px) { + .claim { + flex-flow: column; + align-items: center; + justify-content: center; + gap: 50px; + padding: 20px 50px; + } + + .buttongroup { + flex-flow: column; + gap: 15px; + } } \ No newline at end of file diff --git a/src/components/Airdrop/getProof.ts b/src/components/Airdrop/getProof.ts index ccfefc55..4067e60d 100644 --- a/src/components/Airdrop/getProof.ts +++ b/src/components/Airdrop/getProof.ts @@ -1,14 +1,13 @@ -import { AccountInterface } from "starknet"; -import { coreTeamAddresses } from "../../constants/amm"; -import { balanceOfCarmineToken } from "../../calls/balanceOf"; -import { hexToBN, standardiseAddress } from "../../utils/utils"; +import { hexToBN } from "../../utils/utils"; import { debug } from "../../utils/debugger"; import { apiUrl } from "../../api"; +import { readStorage } from "../CarmineStaking/calls"; +import { QueryFunctionContext } from "react-query"; -type Eligible = { +export type Eligible = { eligible: true; - claimable: string; - claimed: string; + claimable: bigint; + claimed: bigint; proof: string[]; }; @@ -18,37 +17,25 @@ type NotEligible = { export type ProofResult = Eligible | NotEligible; -export const getProof = async ( - account: AccountInterface -): Promise => { - const merkleTreeRequest = fetch( - apiUrl(`airdrop?address=${account.address}`) - ).then((r) => r.json()); - // since CARM token cannot currently be transfered balanceOf is the amount claimed for tokens - // that are transferable a view function "claimedAmount" need to be added to airdrop SC - const carmBalanceRequest = balanceOfCarmineToken(account); +export const getProof = async (address: string): Promise => { + const merkleTreeRequest = fetch(apiUrl(`airdrop?address=${address}`)).then( + (r) => r.json() + ); + + const claimedPromise = readStorage(address); const [merkleTreeResponse, claimed] = await Promise.all([ merkleTreeRequest, - carmBalanceRequest, + claimedPromise, ]); if (merkleTreeResponse.status !== "success") { return { eligible: false }; } - const isCoreTeam = coreTeamAddresses.includes( - standardiseAddress(account.address) - ); - const total = hexToBN(merkleTreeResponse.data[1]); const diff = total - claimed; - // account for tiny differences - const claimable = isCoreTeam - ? total.toString(10) - : diff < 100n - ? "0" - : diff.toString(10); + const claimable = diff < 100n ? 0n : total - claimed; debug("CARM token claim data:", { total: total.toString(10), @@ -60,6 +47,13 @@ export const getProof = async ( eligible: true, proof: merkleTreeResponse.data, // proof generated by backend claimable, // how much can be claimed - claimed: claimed.toString(10), // how much has been claimed + claimed: claimed, // how much has been claimed }; }; + +export const getAirdropDataQuery = async ({ + queryKey, +}: QueryFunctionContext<[string, string]>): Promise => { + const address = queryKey[1]; + return getProof(address); +}; diff --git a/src/components/Banner/CrmBanner.tsx b/src/components/Banner/CrmBanner.tsx new file mode 100644 index 00000000..c2f0849e --- /dev/null +++ b/src/components/Banner/CrmBanner.tsx @@ -0,0 +1,18 @@ +import { useNavigate } from "react-router-dom"; +import styles from "./banner.module.css"; +import bannerImg from "./crm-banner.png"; + +export const CrmBanner = () => { + const navigate = useNavigate(); + + return ( +
navigate("/governance/airdrop")} + className={styles.crmbanner} + style={{ + backgroundImage: `url(${bannerImg})`, + backgroundSize: "contain", + }} + >
+ ); +}; diff --git a/src/components/Banner/banner.module.css b/src/components/Banner/banner.module.css new file mode 100644 index 00000000..66185330 --- /dev/null +++ b/src/components/Banner/banner.module.css @@ -0,0 +1,6 @@ +.crmbanner { + width: 100%; + aspect-ratio: 5.1863; + margin-bottom: 50px; + cursor: pointer; +} \ No newline at end of file diff --git a/src/components/Banner/crm-banner.png b/src/components/Banner/crm-banner.png new file mode 100644 index 00000000..a358554c Binary files /dev/null and b/src/components/Banner/crm-banner.png differ diff --git a/src/components/Banner/index.ts b/src/components/Banner/index.ts new file mode 100644 index 00000000..dc745a1b --- /dev/null +++ b/src/components/Banner/index.ts @@ -0,0 +1,2 @@ +import { CrmBanner } from "./CrmBanner"; +export { CrmBanner }; diff --git a/src/components/CarmineStaking/StakeCRM.tsx b/src/components/CarmineStaking/StakeCRM.tsx new file mode 100644 index 00000000..246d457d --- /dev/null +++ b/src/components/CarmineStaking/StakeCRM.tsx @@ -0,0 +1,206 @@ +import { AccountInterface } from "starknet"; +import { useState } from "react"; +import { longInteger, shortInteger } from "../../utils/computations"; +import { + CARMINE_STAKING_MONTH, + CARMINE_STAKING_YEAR, + CRM_ADDRESS, + GOVERNANCE_ADDRESS, +} from "../../constants/amm"; +import { TransactionState, TxTracking } from "../../types/network"; +import { stateToClassName } from "./StakingModal"; +import { LoadingAnimation } from "../Loading/Loading"; +import { TransactionAction } from "../../redux/reducers/transactions"; +import { + addTx, + markTxAsDone, + markTxAsFailed, + showToast, +} from "../../redux/actions"; +import { afterTransaction } from "../../utils/blockchain"; +import { ToastType } from "../../redux/reducers/ui"; +import { invalidateKey } from "../../queries/client"; +import { QueryKeys } from "../../queries/keys"; + +import styles from "./vest.module.css"; +import inputStyles from "../../style/input.module.css"; + +import GovernanceABI from "../../abi/governance_abi.json"; +import TokenABI from "../../abi/lptoken_abi.json"; +import { Tooltip } from "@mui/material"; + +type Props = { + account: AccountInterface; + carmBalance: bigint; +}; + +const stake = async ( + account: AccountInterface, + amount: bigint, + length: number, + setTxState: TxTracking +) => { + setTxState(TransactionState.Processing); + + const approveCall = { + contractAddress: CRM_ADDRESS, + entrypoint: "approve", + calldata: [GOVERNANCE_ADDRESS, amount.toString(10), 0], + }; + + const stakeCall = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "stake", + calldata: [length.toString(10), amount.toString(10)], + }; + + const res = await account + .execute([approveCall, stakeCall], [TokenABI, GovernanceABI]) + .catch(() => null); + + if (res?.transaction_hash) { + const hash = res.transaction_hash; + + addTx(hash, `stake-${length}`, TransactionAction.ClaimAirdrop); + afterTransaction( + res.transaction_hash, + () => { + setTxState(TransactionState.Success); + showToast("Successfully claimed and staked airdrop", ToastType.Success); + markTxAsDone(hash); + // success, refetch new CRM balance + invalidateKey(QueryKeys.carmineStakes); + }, + () => { + setTxState(TransactionState.Fail); + showToast("Failed claiming airdrop", ToastType.Error); + markTxAsFailed(hash); + } + ); + } else { + setTxState(TransactionState.Fail); + showToast("Failed claiming airdrop", ToastType.Error); + } +}; + +export const StakeCrm = ({ account, carmBalance }: Props) => { + const [inputValue, setInputValue] = useState(""); + + const [monthState, setMonthState] = useState(TransactionState.Initial); + const [sixMonthsState, setSixMonthsState] = useState( + TransactionState.Initial + ); + const [yearState, setYearState] = useState(TransactionState.Initial); + + const numCarmBalance = shortInteger(carmBalance, 18); + const amount = longInteger(parseFloat(inputValue), 18); + + const handle1month = () => { + setSixMonthsState(TransactionState.Processing); + setYearState(TransactionState.Processing); + stake(account, amount, CARMINE_STAKING_MONTH, setMonthState).then(() => { + setSixMonthsState(TransactionState.Initial); + setYearState(TransactionState.Initial); + }); + }; + const handle6months = () => { + setMonthState(TransactionState.Processing); + setYearState(TransactionState.Processing); + stake(account, amount, 6 * CARMINE_STAKING_MONTH, setSixMonthsState).then( + () => { + setMonthState(TransactionState.Initial); + setYearState(TransactionState.Initial); + } + ); + }; + const handleYear = () => { + setMonthState(TransactionState.Processing); + setSixMonthsState(TransactionState.Processing); + stake(account, amount, CARMINE_STAKING_YEAR, setYearState).then(() => { + setMonthState(TransactionState.Initial); + setSixMonthsState(TransactionState.Initial); + }); + }; + + const handleInputChange = (value: string) => { + // Allow empty string, valid number, or a single decimal point followed by numbers + const numericValue = + value === "" || /^\d*\.?\d{0,6}$/.test(value) ? value : inputValue; + + const num = parseFloat(numericValue); + + if (num && num > numCarmBalance) { + // cannot set more than holds + return; + } + + setInputValue(numericValue); + }; + + const handleAll = () => setInputValue(numCarmBalance.toString(10)); + + return ( +
+

+ Stake your CRM for a period +

+
+
+ handleInputChange(e.target.value)} + /> + +
+ +
+ + + + + + + + + +
+
+
+ ); +}; diff --git a/src/components/CarmineStaking/Stakes.tsx b/src/components/CarmineStaking/Stakes.tsx new file mode 100644 index 00000000..c234cdcc --- /dev/null +++ b/src/components/CarmineStaking/Stakes.tsx @@ -0,0 +1,154 @@ +import { + TableContainer, + Table, + TableHead, + TableRow, + TableCell, + TableBody, +} from "@mui/material"; +import { useState } from "react"; +import { AccountInterface } from "starknet"; + +import { CarmineStake } from "../../classes/CarmineStake"; +import { shortInteger } from "../../utils/computations"; +import { StakingModal } from "./StakingModal"; + +import tableStyles from "../../style/table.module.css"; +import buttonStyles from "../../style/button.module.css"; + +const Item = ({ stake }: { stake: CarmineStake }) => { + return ( + + {stake.startDate} + {stake.endDate} + {stake.period} + {stake.amountStakedHumanReadable} + {stake.amountVotingTokenHumanReadable} + + ); +}; + +const InitialVeCarmItem = ({ + amount, + account, +}: { + amount: bigint; + account: AccountInterface; +}) => { + const [open, setOpen] = useState(false); + + return ( + + -- + -- + -- + {shortInteger(amount, 18)} + 0 + + + + + + ); +}; + +const ExpiredItem = ({ stake }: { stake: CarmineStake }) => { + return ( + + {stake.startDate} + {stake.endDate} + {stake.period} + {stake.amountStakedHumanReadable} + 0 + + + + + ); +}; + +type Props = { + stakes: CarmineStake[]; + veBalance: bigint; + account: AccountInterface; +}; + +export const Stakes = ({ stakes, veBalance, account }: Props) => { + const balanceInStakes = stakes.reduce((acc, cur) => { + if (cur.isNotWithdrawn) { + return acc + cur.amountVotingToken; + } + return acc; + }, 0n); + + const active = stakes.filter((s) => s.isActive); + const expired = stakes.filter((s) => s.isExpired); + + const initialVeCarm = veBalance - balanceInStakes; + + return ( +
+

Expired stakes

+ {expired.length > 0 || initialVeCarm > 0n ? ( + + + + + Start + End + Period + Amount + Voting power + + + + + {initialVeCarm > 0n && ( + + )} + {expired.map((stake, i) => ( + + ))} + +
+
+ ) : ( +

No expired stakes

+ )} + +

Active stakes

+ {active.length > 0 ? ( + + + + + Start + End + Period + Amount + Voting power + + + + {active.map((stake, i) => ( + + ))} + +
+
+ ) : ( +

No active stakes

+ )} +
+ ); +}; diff --git a/src/components/CarmineStaking/Staking.tsx b/src/components/CarmineStaking/Staking.tsx new file mode 100644 index 00000000..89cb9030 --- /dev/null +++ b/src/components/CarmineStaking/Staking.tsx @@ -0,0 +1,69 @@ +import { AccountInterface } from "starknet"; +import { useQuery } from "react-query"; + +import { useAccount } from "../../hooks/useAccount"; +import { openWalletConnectDialog } from "../ConnectWallet/Button"; +import { shortInteger } from "../../utils/computations"; +import { Stakes } from "./Stakes"; +import { QueryKeys } from "../../queries/keys"; +import { fetchStakingData } from "./calls"; +import { StakeCrm } from "./StakeCRM"; +import { LoadingAnimation } from "../Loading/Loading"; + +export const StakeWithAccount = ({ + account, +}: { + account: AccountInterface; +}) => { + const { isLoading, isError, data } = useQuery( + [QueryKeys.carmineStakes, account.address], + fetchStakingData + ); + if (isLoading || !data) { + return ; + } + + if (isError) { + return
Something went wrong, please try again later
; + } + + const { veCarmBalance, carmBalance, stakes } = data; + const humanReadableVeCarmBalance = shortInteger(veCarmBalance, 18); + const humanReadableCarmBalance = shortInteger(carmBalance, 18); + + return ( +
+

+ Want to know more about CRM staking and veCRM?{" "} + + Find out here! + + . +

+ +

+ You have {humanReadableCarmBalance} CRM and{" "} + {humanReadableVeCarmBalance} veCRM +

+ {carmBalance > 0n && ( + + )} + + +
+ ); +}; + +export const CarmineStaking = () => { + const account = useAccount(); + + if (!account) { + return ; + } + + return ; +}; diff --git a/src/components/CarmineStaking/StakingModal.tsx b/src/components/CarmineStaking/StakingModal.tsx new file mode 100644 index 00000000..1bfa66f6 --- /dev/null +++ b/src/components/CarmineStaking/StakingModal.tsx @@ -0,0 +1,275 @@ +import { Dialog, Tooltip } from "@mui/material"; +import { AccountInterface } from "starknet"; + +import { longInteger, shortInteger } from "../../utils/computations"; +import { + CARMINE_STAKING_MONTH, + CARMINE_STAKING_YEAR, + CRM_ADDRESS, + GOVERNANCE_ADDRESS, +} from "../../constants/amm"; +import { + addTx, + markTxAsDone, + markTxAsFailed, + showToast, +} from "../../redux/actions"; +import { afterTransaction } from "../../utils/blockchain"; +import { TransactionAction } from "../../redux/reducers/transactions"; +import { ToastType } from "../../redux/reducers/ui"; +import { useState } from "react"; +import { TransactionState, TxTracking } from "../../types/network"; +import { LoadingAnimation } from "../Loading/Loading"; +import { unstakeAirdrop } from "../../calls/carmineStake"; + +import styles from "./modal.module.css"; +import buttonStyles from "../../style/button.module.css"; +import inputStyles from "../../style/input.module.css"; + +import GovernanceABI from "../../abi/governance_abi.json"; +import TokenABI from "../../abi/lptoken_abi.json"; + +export const unstakeAndStake = async ( + account: AccountInterface, + amount: bigint, + length: number, + setTxState: TxTracking +) => { + setTxState(TransactionState.Processing); + + const unstakeCall = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "unstake_airdrop", + calldata: [], + }; + const approveCall = { + contractAddress: CRM_ADDRESS, + entrypoint: "approve", + calldata: [GOVERNANCE_ADDRESS, amount.toString(10), 0], + }; + const stakeCall = { + contractAddress: GOVERNANCE_ADDRESS, + entrypoint: "stake", + calldata: [length.toString(10), amount.toString(10)], + }; + + const res = await account + .execute( + [unstakeCall, approveCall, stakeCall], + [GovernanceABI, TokenABI, GovernanceABI] + ) + .catch(() => null); + + if (res?.transaction_hash) { + const hash = res.transaction_hash; + + addTx(hash, `airdrop-stake-${length}`, TransactionAction.ClaimAirdrop); + afterTransaction( + res.transaction_hash, + () => { + setTxState(TransactionState.Success); + showToast("Successfully claimed and staked airdrop", ToastType.Success); + markTxAsDone(hash); + }, + () => { + setTxState(TransactionState.Fail); + showToast("Failed claiming airdrop", ToastType.Error); + markTxAsFailed(hash); + } + ); + } else { + setTxState(TransactionState.Fail); + showToast("Failed claiming airdrop", ToastType.Error); + } +}; + +type Props = { + account: AccountInterface; + amount: bigint; + open: boolean; + setOpen: (open: boolean) => void; +}; + +export const stateToClassName = (state: TransactionState) => { + if (state === TransactionState.Success) { + return buttonStyles.green; + } + if (state === TransactionState.Fail) { + return buttonStyles.fail; + } + if (state === TransactionState.Processing) { + return buttonStyles.disabled; + } + return buttonStyles.secondary; +}; + +export const StakingModal = ({ account, amount, open, setOpen }: Props) => { + const numCarmBalance = shortInteger(amount, 18); + const [inputValue, setInputValue] = useState(numCarmBalance.toString(10)); + const [unstakeState, setUnstakeState] = useState(TransactionState.Initial); + const [monthState, setMonthState] = useState(TransactionState.Initial); + const [sixMonthsState, setSixMonthsState] = useState( + TransactionState.Initial + ); + const [yearState, setYearState] = useState(TransactionState.Initial); + + const selectedAmount = longInteger(parseFloat(inputValue), 18); + + const handleClose = () => { + setOpen(false); + setUnstakeState(TransactionState.Initial); + setMonthState(TransactionState.Initial); + setSixMonthsState(TransactionState.Initial); + setYearState(TransactionState.Initial); + }; + + const handleUnstake = () => unstakeAirdrop(account, setUnstakeState); + + const handle1month = () => { + setSixMonthsState(TransactionState.Processing); + setYearState(TransactionState.Processing); + unstakeAndStake( + account, + selectedAmount, + CARMINE_STAKING_MONTH, + setMonthState + ).then(() => { + setSixMonthsState(TransactionState.Initial); + setYearState(TransactionState.Initial); + }); + }; + const handle6months = () => { + setMonthState(TransactionState.Processing); + setYearState(TransactionState.Processing); + unstakeAndStake( + account, + selectedAmount, + 6 * CARMINE_STAKING_MONTH, + setSixMonthsState + ).then(() => { + setMonthState(TransactionState.Initial); + setYearState(TransactionState.Initial); + }); + }; + const handleYear = () => { + setMonthState(TransactionState.Processing); + setSixMonthsState(TransactionState.Processing); + unstakeAndStake( + account, + selectedAmount, + CARMINE_STAKING_YEAR, + setYearState + ).then(() => { + setMonthState(TransactionState.Initial); + setSixMonthsState(TransactionState.Initial); + }); + }; + + const handleInputChange = (value: string) => { + // Allow empty string, valid number, or a single decimal point followed by numbers + const numericValue = + value === "" || /^\d*\.?\d{0,6}$/.test(value) ? value : inputValue; + + const num = parseFloat(numericValue); + + if (num && num > numCarmBalance) { + // cannot set more than holds + return; + } + + setInputValue(numericValue); + }; + + const handleAll = () => setInputValue(numCarmBalance.toString(10)); + + return ( + +
+

Restake & Unstake

+

+ Your stake of {shortInteger(amount, 18)} CRM has expired. +

+

You can stake again for a period:

+
+
+ handleInputChange(e.target.value)} + /> + +
+
+ + + + + + + + + +
+
+

+ Alternatively, you can unstake your veCRM to CRM: +

+
+ +
+
+
+ ); +}; diff --git a/src/components/CarmineStaking/calls.ts b/src/components/CarmineStaking/calls.ts new file mode 100644 index 00000000..9703b4c5 --- /dev/null +++ b/src/components/CarmineStaking/calls.ts @@ -0,0 +1,53 @@ +import { QueryFunctionContext } from "react-query"; +import { getStakes } from "../../calls/carmineStake"; +import { balanceOf } from "../../calls/balanceOf"; +import { + CRM_ADDRESS, + GOVERNANCE_ADDRESS, + VE_CRM_ADDRESS, +} from "../../constants/amm"; +import { CarmineStake } from "../../classes/CarmineStake"; +import { ec, hash, shortString } from "starknet"; +import { provider } from "../../network/provider"; + +export const fetchStakes = async ({ + queryKey, +}: QueryFunctionContext<[string, string]>): Promise => { + const address = queryKey[1]; + return getStakes(address); +}; + +type StakingData = { + veCarmBalance: bigint; + carmBalance: bigint; + stakes: CarmineStake[]; +}; + +export const fetchStakingData = async ({ + queryKey, +}: QueryFunctionContext<[string, string]>): Promise => { + const address = queryKey[1]; + const promises = [ + balanceOf(address, VE_CRM_ADDRESS), + balanceOf(address, CRM_ADDRESS), + getStakes(address), + ]; + const values = await Promise.all(promises); + const result = { + veCarmBalance: values[0] as bigint, + carmBalance: values[1] as bigint, + stakes: values[2] as CarmineStake[], + }; + + return result; +}; + +export const readStorage = async (address: string) => { + const selector_airdrop_claimed = hash.keccakBn( + shortString.encodeShortString("airdrop_claimed") + ); + const key = ec.starkCurve.pedersen(selector_airdrop_claimed, address); + + const storage_value = await provider.getStorageAt(GOVERNANCE_ADDRESS, key); + return BigInt(storage_value); +}; diff --git a/src/components/CarmineStaking/index.ts b/src/components/CarmineStaking/index.ts new file mode 100644 index 00000000..700b577b --- /dev/null +++ b/src/components/CarmineStaking/index.ts @@ -0,0 +1,3 @@ +import { CarmineStaking } from "./Staking"; + +export { CarmineStaking }; diff --git a/src/components/CarmineStaking/modal.module.css b/src/components/CarmineStaking/modal.module.css new file mode 100644 index 00000000..3a2c9b4f --- /dev/null +++ b/src/components/CarmineStaking/modal.module.css @@ -0,0 +1,43 @@ +.modal { + background: black; + border: 1px solid white; + padding: 30px; +} + +.modal h3 { + margin-top: 0; +} + +.buttongroup { + display: flex; + justify-content: space-between; + align-items: center; +} + +.singlebutton { + display: flex; + justify-content: space-around; + align-items: center; +} + +.inputall { + display: flex; + align-items: center; + padding-bottom: 20px; +} + +.inputall button { + border-left: 0; +} + +.inputall input { + max-width: none; + width: 100%; +} + +@media (max-width: 800px) { + .buttongroup { + flex-flow: column; + gap: 15px; + } +} \ No newline at end of file diff --git a/src/components/CarmineStaking/vest.module.css b/src/components/CarmineStaking/vest.module.css new file mode 100644 index 00000000..e27b9756 --- /dev/null +++ b/src/components/CarmineStaking/vest.module.css @@ -0,0 +1,20 @@ +.container { + display: flex; + align-items: center; + gap: 1rem; +} + +.inputall { + display: flex; + align-items: center; +} + +.inputall button { + border-left: 0; +} + +@media (max-width: 800px) { + .container { + flex-flow: column; + } +} \ No newline at end of file diff --git a/src/components/Slip/Slip.tsx b/src/components/Slip/Slip.tsx index 5ea86fd5..fd8deb65 100644 --- a/src/components/Slip/Slip.tsx +++ b/src/components/Slip/Slip.tsx @@ -1,9 +1,11 @@ import { useEffect, useState } from "react"; import styles from "./Slip.module.css"; +import { useNavigate } from "react-router-dom"; const MIN_WIDTH = 1200; -const SlipElem = () => ( +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const LegacyAppMessage = () => (
This App uses new Carmine Protocol with C2 contracts. Old App can be accessed at{" "} @@ -11,8 +13,26 @@ const SlipElem = () => (
); +const AirdropMessage = () => { + const navigate = useNavigate(); + + const handleClick = () => navigate("/governance/airdrop"); + + return ( +
+ Carmine Airdrop is now available! Claim it{" "} + + here + + . +
+ ); +}; + export const Slip = () => { - const [isWideScreen, setIsWideScreen] = useState(window.innerWidth > MIN_WIDTH); + const [isWideScreen, setIsWideScreen] = useState( + window.innerWidth > MIN_WIDTH + ); useEffect(() => { function handleResize() { @@ -25,14 +45,14 @@ export const Slip = () => { }, []); if (isWideScreen) { - return ; + return ; } return (
- - + +
); diff --git a/src/constants/amm.ts b/src/constants/amm.ts index 3e8fc74c..a4ac9cff 100644 --- a/src/constants/amm.ts +++ b/src/constants/amm.ts @@ -8,6 +8,8 @@ export const ETH_ADDRESS = config.ETH_ADDRESS; export const USDC_ADDRESS = config.USDC_ADDRESS; export const BTC_ADDRESS = config.BTC_ADDRESS; export const STRK_ADDRESS = config.STRK_ADDRESS; +export const VE_CRM_ADDRESS = config.VE_CRM_ADDRESS; +export const CRM_ADDRESS = config.CRM_ADDRESS; export const ETH_USDC_CALL_ADDRESS = config.ETH_USDC_CALL_ADDRESS; export const ETH_USDC_PUT_ADDRESS = config.ETH_USDC_PUT_ADDRESS; export const BTC_USDC_CALL_ADDRESS = config.BTC_USDC_CALL_ADDRESS; @@ -72,3 +74,6 @@ export const USDC_BASE_VALUE = BigInt(10) ** BigInt(USDC_DIGITS); export const BASE_MATH_64_61 = BigInt(2) ** BigInt(61); export const BASE_MATH_64 = BigInt(2) ** BigInt(64); export const USDC_PRECISSION = 1000; + +export const CARMINE_STAKING_MONTH = 2629743; +export const CARMINE_STAKING_YEAR = 31536000; diff --git a/src/constants/config.json b/src/constants/config.json index 63f1567d..1fd8caa0 100644 --- a/src/constants/config.json +++ b/src/constants/config.json @@ -7,6 +7,8 @@ "USDC_ADDRESS": "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", "BTC_ADDRESS": "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac", "STRK_ADDRESS": "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", + "VE_CRM_ADDRESS": "0x3c0286e9e428a130ae7fbbe911b794e8a829c367dd788e7cfe3efb0367548fa", + "CRM_ADDRESS": "0x51c4b1fe3bf6774b87ad0b15ef5d1472759076e42944fff9b9f641ff13e5bbe", "ETH_USDC_CALL_ADDRESS": "0x70cad6be2c3fc48c745e4a4b70ef578d9c79b46ffac4cd93ec7b61f951c7c5c", "ETH_USDC_PUT_ADDRESS": "0x466e3a6731571cf5d74c5b0d9c508bfb71438de10f9a13269177b01d6f07159", "BTC_USDC_CALL_ADDRESS": "0x35db72a814c9b30301f646a8fa8c192ff63a0dc82beb390a36e6e9eba55b6db", diff --git a/src/constants/starknet.ts b/src/constants/starknet.ts index eb0c8a8b..823e7593 100644 --- a/src/constants/starknet.ts +++ b/src/constants/starknet.ts @@ -1 +1,13 @@ +import { Contract } from "starknet"; +import { GOVERNANCE_ADDRESS } from "./amm"; +import { provider } from "../network/provider"; + +import GovernanceABI from "../abi/governance_abi.json"; + export const TESTNET_CHAINID = "0x534e5f474f45524c49"; + +export const governanceContract = new Contract( + GovernanceABI, + GOVERNANCE_ADDRESS, + provider +); diff --git a/src/hooks/useGovernanceSubpage.ts b/src/hooks/useGovernanceSubpage.ts new file mode 100644 index 00000000..4906edf5 --- /dev/null +++ b/src/hooks/useGovernanceSubpage.ts @@ -0,0 +1,7 @@ +import { useSelector } from "react-redux"; + +import { GovernanceSubpage } from "../redux/reducers/ui"; +import { RootState } from "../redux/store"; + +export const useGovernanceSubpage = (): GovernanceSubpage => + useSelector((s: RootState) => s.ui.governanceSubpage); diff --git a/src/network/account.ts b/src/network/account.ts index f637c6da..eb68f28e 100644 --- a/src/network/account.ts +++ b/src/network/account.ts @@ -97,7 +97,8 @@ export const connect = ( // do not open the dialog if the page is loading/just loaded return; } - openNetworkMismatchDialog(); + // TODO: fix this + // openNetworkMismatchDialog(); } addWalletEventHandlers(wallet); diff --git a/src/network/provider.ts b/src/network/provider.ts index 8817dd70..fdabe8e1 100644 --- a/src/network/provider.ts +++ b/src/network/provider.ts @@ -14,6 +14,7 @@ export const testnetOptions: RpcProviderOptions = { export const mainnetOptions: RpcProviderOptions = { nodeUrl: apiUrl("call", { network: "mainnet" }), + // nodeUrl: "http://34.22.208.73:5051", dev mainnet chainId: constants.StarknetChainId.SN_MAIN, }; diff --git a/src/network/walletEvents.ts b/src/network/walletEvents.ts index 1f515207..f53af2f6 100644 --- a/src/network/walletEvents.ts +++ b/src/network/walletEvents.ts @@ -32,7 +32,7 @@ export const walletNetworkChangeHandlerFactory = } // network mismatch - open the dialog - openNetworkMismatchDialog(); + // openNetworkMismatchDialog(); }; type EventList = { diff --git a/src/pages/governance.tsx b/src/pages/governance.tsx index 3778ed39..2ed3156f 100644 --- a/src/pages/governance.tsx +++ b/src/pages/governance.tsx @@ -1,39 +1,57 @@ -import { Box, Typography } from "@mui/material"; import { Helmet } from "react-helmet"; import { Layout } from "../components/Layout"; import { Proposals } from "../components/Proposal"; -import { isMainnet } from "../constants/amm"; +import { CarmineStaking } from "../components/CarmineStaking"; +import { useGovernanceSubpage } from "../hooks/useGovernanceSubpage"; +import { GovernanceSubpage } from "../redux/reducers/ui"; +import { useNavigate } from "react-router-dom"; +import buttonStyles from "../style/button.module.css"; +import { setGovernanceSubpage } from "../redux/actions"; +import { Airdrop } from "../components/Airdrop/Airdrop"; +import { useEffect } from "react"; -type Props = { - message: string; - data?: string[]; +const VotingSubpage = () => { + return ( +
+

Proposals

+

Vote on AMM defining proposals

+ +
+ ); }; -const Governance = () => { - const SwitchNetwork = ({ message, data }: Props) => ( - - - {message} - {/* */} - {/* {account && } */} - - +const StakingSubpage = () => { + return ( +
+

CRM Staking

+ +
); +}; + +const Governance = () => { + const subpage = useGovernanceSubpage(); + const navigate = useNavigate(); + + useEffect(() => { + const parts = window.location.pathname.split("/").filter((s) => s !== ""); + + if ( + parts.length === 2 && + Object.values(GovernanceSubpage).includes( + parts[1] as GovernanceSubpage + ) && + (parts[1] as GovernanceSubpage) !== subpage + ) { + setGovernanceSubpage(parts[1] as GovernanceSubpage); + } + }); + + const handleNavigateClick = (subpage: GovernanceSubpage) => { + setGovernanceSubpage(subpage); + navigate(`/governance/${subpage}`); + }; return ( @@ -44,11 +62,40 @@ const Governance = () => { content="Vote on proposals and take part in governing Carmine Options AMM" /> - {isMainnet ? ( - - ) : ( - - )} + + + + + {subpage === GovernanceSubpage.Voting && } + {subpage === GovernanceSubpage.Staking && } + {subpage === GovernanceSubpage.AirDrop && } ); }; diff --git a/src/pages/insurance.tsx b/src/pages/insurance.tsx index fff30e3e..9ff970ab 100644 --- a/src/pages/insurance.tsx +++ b/src/pages/insurance.tsx @@ -4,6 +4,7 @@ import { BuyInsuranceBox } from "../components/Insurance/BuyInsuranceBox"; import { ActiveInsurance } from "../components/Insurance/ActiveInsurance"; import { ClaimInsurance } from "../components/Insurance/ClaimInsurance"; import styles from "./insurance.module.css"; +import { CrmBanner } from "../components/Banner"; const Insurance = () => { return ( @@ -15,6 +16,7 @@ const Insurance = () => { content="Insure the value of your crypto assets" /> +

Insurance

diff --git a/src/pages/leaderboard.tsx b/src/pages/leaderboard.tsx index c6d7310e..13abaf79 100644 --- a/src/pages/leaderboard.tsx +++ b/src/pages/leaderboard.tsx @@ -2,6 +2,7 @@ import { useEffect } from "react"; import { Layout } from "../components/Layout"; import { Leaderboard } from "../components/Points"; +import { CrmBanner } from "../components/Banner"; const LeaderboardPage = () => { useEffect(() => { @@ -10,6 +11,8 @@ const LeaderboardPage = () => { return ( + +

Carmine Points Program

Elevate Your Status, Enhance Your Rewards

Leaderboard

diff --git a/src/pages/portfolio.tsx b/src/pages/portfolio.tsx index 7e747206..d84b9dd3 100644 --- a/src/pages/portfolio.tsx +++ b/src/pages/portfolio.tsx @@ -13,6 +13,7 @@ import { PortfolioParamType } from "../redux/reducers/ui"; import buttonStyles from "../style/button.module.css"; import { Referral } from "../components/Referral"; import { isMainnet } from "../constants/amm"; +import { CrmBanner } from "../components/Banner"; const Portfolio = () => { const portfolioParam = usePortfolioParam(); @@ -65,6 +66,8 @@ const Portfolio = () => { content="Your current positions and history of your activity" /> + +