Compare commits
No commits in common. "126a89099960ddc11659f43dcb5948aacc73ec5a" and "a2a4b86ccc418b3b76c4ce5e5ea738e325abad62" have entirely different histories.
126a890999
...
a2a4b86ccc
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ghost-dao-interface",
|
"name": "ghost-dao-interface",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.5.10",
|
"version": "0.4.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@ -16,7 +16,6 @@
|
|||||||
"@ethersproject/bignumber": "^5.8.0",
|
"@ethersproject/bignumber": "^5.8.0",
|
||||||
"@ethersproject/units": "^5.8.0",
|
"@ethersproject/units": "^5.8.0",
|
||||||
"@mui/icons-material": "^6.4.7",
|
"@mui/icons-material": "^6.4.7",
|
||||||
"@mui/lab": "6.0.1-beta.36",
|
|
||||||
"@mui/material": "^6.4.7",
|
"@mui/material": "^6.4.7",
|
||||||
"@mui/utils": "^6.4.6",
|
"@mui/utils": "^6.4.6",
|
||||||
"@polkadot-api/metadata-builders": "0.13.0",
|
"@polkadot-api/metadata-builders": "0.13.0",
|
||||||
|
|||||||
218
pnpm-lock.yaml
218
pnpm-lock.yaml
@ -26,9 +26,6 @@ importers:
|
|||||||
'@mui/icons-material':
|
'@mui/icons-material':
|
||||||
specifier: ^6.4.7
|
specifier: ^6.4.7
|
||||||
version: 6.4.7(@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)
|
version: 6.4.7(@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)
|
||||||
'@mui/lab':
|
|
||||||
specifier: 6.0.1-beta.36
|
|
||||||
version: 6.0.1-beta.36(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
'@mui/material':
|
'@mui/material':
|
||||||
specifier: ^6.4.7
|
specifier: ^6.4.7
|
||||||
version: 6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
@ -528,21 +525,6 @@ packages:
|
|||||||
'@ethersproject/units@5.8.0':
|
'@ethersproject/units@5.8.0':
|
||||||
resolution: {integrity: sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==}
|
resolution: {integrity: sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==}
|
||||||
|
|
||||||
'@floating-ui/core@1.7.4':
|
|
||||||
resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==}
|
|
||||||
|
|
||||||
'@floating-ui/dom@1.7.5':
|
|
||||||
resolution: {integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==}
|
|
||||||
|
|
||||||
'@floating-ui/react-dom@2.1.7':
|
|
||||||
resolution: {integrity: sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: '>=16.8.0'
|
|
||||||
react-dom: '>=16.8.0'
|
|
||||||
|
|
||||||
'@floating-ui/utils@0.2.10':
|
|
||||||
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
|
|
||||||
|
|
||||||
'@humanfs/core@0.19.1':
|
'@humanfs/core@0.19.1':
|
||||||
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
||||||
engines: {node: '>=18.18.0'}
|
engines: {node: '>=18.18.0'}
|
||||||
@ -656,18 +638,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==}
|
resolution: {integrity: sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==}
|
||||||
engines: {node: '>=16.0.0'}
|
engines: {node: '>=16.0.0'}
|
||||||
|
|
||||||
'@mui/base@5.0.0-beta.70':
|
|
||||||
resolution: {integrity: sha512-Tb/BIhJzb0pa5zv/wu7OdokY9ZKEDqcu1BDFnohyvGCoHuSXbEr90rPq1qeNW3XvTBIbNWHEF7gqge+xpUo6tQ==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
deprecated: This package has been replaced by @base-ui/react
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
react: ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@mui/core-downloads-tracker@6.4.7':
|
'@mui/core-downloads-tracker@6.4.7':
|
||||||
resolution: {integrity: sha512-XjJrKFNt9zAKvcnoIIBquXyFyhfrHYuttqMsoDS7lM7VwufYG4fAPw4kINjBFg++fqXM2BNAuWR9J7XVIuKIKg==}
|
resolution: {integrity: sha512-XjJrKFNt9zAKvcnoIIBquXyFyhfrHYuttqMsoDS7lM7VwufYG4fAPw4kINjBFg++fqXM2BNAuWR9J7XVIuKIKg==}
|
||||||
|
|
||||||
@ -682,27 +652,6 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@mui/lab@6.0.1-beta.36':
|
|
||||||
resolution: {integrity: sha512-af9lDmA9SZGEWF1XXk0EVBpfCITk9IKsvh9lLOZGdYaaHfQeCsqxGEDMvNO66j0P8EYoxpyry84LFCJYuLVtVw==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@emotion/react': ^11.5.0
|
|
||||||
'@emotion/styled': ^11.3.0
|
|
||||||
'@mui/material': ^6.5.0
|
|
||||||
'@mui/material-pigment-css': ^6.5.0
|
|
||||||
'@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
react: ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@emotion/react':
|
|
||||||
optional: true
|
|
||||||
'@emotion/styled':
|
|
||||||
optional: true
|
|
||||||
'@mui/material-pigment-css':
|
|
||||||
optional: true
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@mui/material@6.4.7':
|
'@mui/material@6.4.7':
|
||||||
resolution: {integrity: sha512-K65StXUeGAtFJ4ikvHKtmDCO5Ab7g0FZUu2J5VpoKD+O6Y3CjLYzRi+TMlI3kaL4CL158+FccMoOd/eaddmeRQ==}
|
resolution: {integrity: sha512-K65StXUeGAtFJ4ikvHKtmDCO5Ab7g0FZUu2J5VpoKD+O6Y3CjLYzRi+TMlI3kaL4CL158+FccMoOd/eaddmeRQ==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@ -733,16 +682,6 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@mui/private-theming@6.4.9':
|
|
||||||
resolution: {integrity: sha512-LktcVmI5X17/Q5SkwjCcdOLBzt1hXuc14jYa7NPShog0GBDCDvKtcnP0V7a2s6EiVRlv7BzbWEJzH6+l/zaCxw==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
react: ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@mui/styled-engine@6.4.6':
|
'@mui/styled-engine@6.4.6':
|
||||||
resolution: {integrity: sha512-vSWYc9ZLX46be5gP+FCzWVn5rvDr4cXC5JBZwSIkYk9xbC7GeV+0kCvB8Q6XLFQJy+a62bbqtmdwS4Ghi9NBlQ==}
|
resolution: {integrity: sha512-vSWYc9ZLX46be5gP+FCzWVn5rvDr4cXC5JBZwSIkYk9xbC7GeV+0kCvB8Q6XLFQJy+a62bbqtmdwS4Ghi9NBlQ==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@ -756,19 +695,6 @@ packages:
|
|||||||
'@emotion/styled':
|
'@emotion/styled':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@mui/styled-engine@6.5.0':
|
|
||||||
resolution: {integrity: sha512-8woC2zAqF4qUDSPIBZ8v3sakj+WgweolpyM/FXf8jAx6FMls+IE4Y8VDZc+zS805J7PRz31vz73n2SovKGaYgw==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@emotion/react': ^11.4.1
|
|
||||||
'@emotion/styled': ^11.3.0
|
|
||||||
react: ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@emotion/react':
|
|
||||||
optional: true
|
|
||||||
'@emotion/styled':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@mui/system@6.4.7':
|
'@mui/system@6.4.7':
|
||||||
resolution: {integrity: sha512-7wwc4++Ak6tGIooEVA9AY7FhH2p9fvBMORT4vNLMAysH3Yus/9B9RYMbrn3ANgsOyvT3Z7nE+SP8/+3FimQmcg==}
|
resolution: {integrity: sha512-7wwc4++Ak6tGIooEVA9AY7FhH2p9fvBMORT4vNLMAysH3Yus/9B9RYMbrn3ANgsOyvT3Z7nE+SP8/+3FimQmcg==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@ -785,22 +711,6 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@mui/system@6.5.0':
|
|
||||||
resolution: {integrity: sha512-XcbBYxDS+h/lgsoGe78ExXFZXtuIlSBpn/KsZq8PtZcIkUNJInkuDqcLd2rVBQrDC1u+rvVovdaWPf2FHKJf3w==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@emotion/react': ^11.5.0
|
|
||||||
'@emotion/styled': ^11.3.0
|
|
||||||
'@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
react: ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@emotion/react':
|
|
||||||
optional: true
|
|
||||||
'@emotion/styled':
|
|
||||||
optional: true
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@mui/types@7.2.21':
|
'@mui/types@7.2.21':
|
||||||
resolution: {integrity: sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==}
|
resolution: {integrity: sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -809,14 +719,6 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@mui/types@7.2.24':
|
|
||||||
resolution: {integrity: sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@mui/utils@6.4.6':
|
'@mui/utils@6.4.6':
|
||||||
resolution: {integrity: sha512-43nZeE1pJF2anGafNydUcYFPtHwAqiBiauRtaMvurdrZI3YrUjHkAu43RBsxef7OFtJMXGiHFvq43kb7lig0sA==}
|
resolution: {integrity: sha512-43nZeE1pJF2anGafNydUcYFPtHwAqiBiauRtaMvurdrZI3YrUjHkAu43RBsxef7OFtJMXGiHFvq43kb7lig0sA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@ -827,16 +729,6 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@mui/utils@6.4.9':
|
|
||||||
resolution: {integrity: sha512-Y12Q9hbK9g+ZY0T3Rxrx9m2m10gaphDuUMgWxyV5kNJevVxXYCLclYUCC9vXaIk1/NdNDTcW2Yfr2OGvNFNmHg==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
react: ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@noble/ciphers@1.2.1':
|
'@noble/ciphers@1.2.1':
|
||||||
resolution: {integrity: sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==}
|
resolution: {integrity: sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==}
|
||||||
engines: {node: ^14.21.3 || >=16}
|
engines: {node: ^14.21.3 || >=16}
|
||||||
@ -3531,23 +3423,6 @@ snapshots:
|
|||||||
'@ethersproject/constants': 5.8.0
|
'@ethersproject/constants': 5.8.0
|
||||||
'@ethersproject/logger': 5.8.0
|
'@ethersproject/logger': 5.8.0
|
||||||
|
|
||||||
'@floating-ui/core@1.7.4':
|
|
||||||
dependencies:
|
|
||||||
'@floating-ui/utils': 0.2.10
|
|
||||||
|
|
||||||
'@floating-ui/dom@1.7.5':
|
|
||||||
dependencies:
|
|
||||||
'@floating-ui/core': 1.7.4
|
|
||||||
'@floating-ui/utils': 0.2.10
|
|
||||||
|
|
||||||
'@floating-ui/react-dom@2.1.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@floating-ui/dom': 1.7.5
|
|
||||||
react: 19.0.0
|
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
|
||||||
|
|
||||||
'@floating-ui/utils@0.2.10': {}
|
|
||||||
|
|
||||||
'@humanfs/core@0.19.1': {}
|
'@humanfs/core@0.19.1': {}
|
||||||
|
|
||||||
'@humanfs/node@0.16.6':
|
'@humanfs/node@0.16.6':
|
||||||
@ -3740,20 +3615,6 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@mui/base@5.0.0-beta.70(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@babel/runtime': 7.27.6
|
|
||||||
'@floating-ui/react-dom': 2.1.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
'@mui/types': 7.2.24(@types/react@19.0.10)
|
|
||||||
'@mui/utils': 6.4.9(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
'@popperjs/core': 2.11.8
|
|
||||||
clsx: 2.1.1
|
|
||||||
prop-types: 15.8.1
|
|
||||||
react: 19.0.0
|
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
'@mui/core-downloads-tracker@6.4.7': {}
|
'@mui/core-downloads-tracker@6.4.7': {}
|
||||||
|
|
||||||
'@mui/icons-material@6.4.7(@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)':
|
'@mui/icons-material@6.4.7(@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)':
|
||||||
@ -3764,23 +3625,6 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.0.10
|
'@types/react': 19.0.10
|
||||||
|
|
||||||
'@mui/lab@6.0.1-beta.36(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@babel/runtime': 7.27.6
|
|
||||||
'@mui/base': 5.0.0-beta.70(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
'@mui/material': 6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
'@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
'@mui/types': 7.2.24(@types/react@19.0.10)
|
|
||||||
'@mui/utils': 6.4.9(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
clsx: 2.1.1
|
|
||||||
prop-types: 15.8.1
|
|
||||||
react: 19.0.0
|
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
|
||||||
optionalDependencies:
|
|
||||||
'@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
'@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
'@mui/material@6.4.7(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.26.9
|
'@babel/runtime': 7.26.9
|
||||||
@ -3804,38 +3648,16 @@ snapshots:
|
|||||||
|
|
||||||
'@mui/private-theming@6.4.6(@types/react@19.0.10)(react@19.0.0)':
|
'@mui/private-theming@6.4.6(@types/react@19.0.10)(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.27.6
|
'@babel/runtime': 7.26.9
|
||||||
'@mui/utils': 6.4.6(@types/react@19.0.10)(react@19.0.0)
|
'@mui/utils': 6.4.6(@types/react@19.0.10)(react@19.0.0)
|
||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.0.10
|
'@types/react': 19.0.10
|
||||||
|
|
||||||
'@mui/private-theming@6.4.9(@types/react@19.0.10)(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@babel/runtime': 7.27.6
|
|
||||||
'@mui/utils': 6.4.9(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
prop-types: 15.8.1
|
|
||||||
react: 19.0.0
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
'@mui/styled-engine@6.4.6(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(react@19.0.0)':
|
'@mui/styled-engine@6.4.6(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.27.6
|
'@babel/runtime': 7.26.9
|
||||||
'@emotion/cache': 11.14.0
|
|
||||||
'@emotion/serialize': 1.3.3
|
|
||||||
'@emotion/sheet': 1.4.0
|
|
||||||
csstype: 3.1.3
|
|
||||||
prop-types: 15.8.1
|
|
||||||
react: 19.0.0
|
|
||||||
optionalDependencies:
|
|
||||||
'@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
|
|
||||||
'@mui/styled-engine@6.5.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@babel/runtime': 7.27.6
|
|
||||||
'@emotion/cache': 11.14.0
|
'@emotion/cache': 11.14.0
|
||||||
'@emotion/serialize': 1.3.3
|
'@emotion/serialize': 1.3.3
|
||||||
'@emotion/sheet': 1.4.0
|
'@emotion/sheet': 1.4.0
|
||||||
@ -3862,30 +3684,10 @@ snapshots:
|
|||||||
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)
|
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)
|
||||||
'@types/react': 19.0.10
|
'@types/react': 19.0.10
|
||||||
|
|
||||||
'@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@babel/runtime': 7.27.6
|
|
||||||
'@mui/private-theming': 6.4.9(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
'@mui/styled-engine': 6.5.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(react@19.0.0)
|
|
||||||
'@mui/types': 7.2.24(@types/react@19.0.10)
|
|
||||||
'@mui/utils': 6.4.9(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
clsx: 2.1.1
|
|
||||||
csstype: 3.1.3
|
|
||||||
prop-types: 15.8.1
|
|
||||||
react: 19.0.0
|
|
||||||
optionalDependencies:
|
|
||||||
'@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
'@mui/types@7.2.21(@types/react@19.0.10)':
|
'@mui/types@7.2.21(@types/react@19.0.10)':
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.0.10
|
'@types/react': 19.0.10
|
||||||
|
|
||||||
'@mui/types@7.2.24(@types/react@19.0.10)':
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
'@mui/utils@6.4.6(@types/react@19.0.10)(react@19.0.0)':
|
'@mui/utils@6.4.6(@types/react@19.0.10)(react@19.0.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.26.9
|
'@babel/runtime': 7.26.9
|
||||||
@ -3898,18 +3700,6 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.0.10
|
'@types/react': 19.0.10
|
||||||
|
|
||||||
'@mui/utils@6.4.9(@types/react@19.0.10)(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@babel/runtime': 7.27.6
|
|
||||||
'@mui/types': 7.2.24(@types/react@19.0.10)
|
|
||||||
'@types/prop-types': 15.7.14
|
|
||||||
clsx: 2.1.1
|
|
||||||
prop-types: 15.8.1
|
|
||||||
react: 19.0.0
|
|
||||||
react-is: 19.0.0
|
|
||||||
optionalDependencies:
|
|
||||||
'@types/react': 19.0.10
|
|
||||||
|
|
||||||
'@noble/ciphers@1.2.1': {}
|
'@noble/ciphers@1.2.1': {}
|
||||||
|
|
||||||
'@noble/ciphers@1.3.0': {}
|
'@noble/ciphers@1.3.0': {}
|
||||||
@ -5252,7 +5042,7 @@ snapshots:
|
|||||||
|
|
||||||
babel-plugin-macros@3.1.0:
|
babel-plugin-macros@3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.27.6
|
'@babel/runtime': 7.26.9
|
||||||
cosmiconfig: 7.1.0
|
cosmiconfig: 7.1.0
|
||||||
resolve: 1.22.10
|
resolve: 1.22.10
|
||||||
|
|
||||||
@ -5448,7 +5238,7 @@ snapshots:
|
|||||||
|
|
||||||
dom-helpers@5.2.1:
|
dom-helpers@5.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.27.6
|
'@babel/runtime': 7.26.9
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
|
|
||||||
dot-case@3.0.4:
|
dot-case@3.0.4:
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import Sidebar from "./components/Sidebar/Sidebar";
|
|||||||
import TopBar from "./components/TopBar/TopBar";
|
import TopBar from "./components/TopBar/TopBar";
|
||||||
|
|
||||||
import { shouldTriggerSafetyCheck } from "./helpers";
|
import { shouldTriggerSafetyCheck } from "./helpers";
|
||||||
import { isNetworkAvailable, isNetworkLegacy, isGovernanceAvailable } from "./constants";
|
import { isNetworkAvailable, isNetworkLegacy } from "./constants";
|
||||||
import useTheme from "./hooks/useTheme";
|
import useTheme from "./hooks/useTheme";
|
||||||
import { useUnstableProvider } from "./hooks/ghost";
|
import { useUnstableProvider } from "./hooks/ghost";
|
||||||
import { dark as darkTheme } from "./themes/dark.js";
|
import { dark as darkTheme } from "./themes/dark.js";
|
||||||
@ -31,9 +31,6 @@ const Wrapper = lazy(() => import("./containers/WethWrapper/WethWrapper"));
|
|||||||
const Dex = lazy(() => import("./containers/Dex/Dex"));
|
const Dex = lazy(() => import("./containers/Dex/Dex"));
|
||||||
const Bridge = lazy(() => import("./containers/Bridge/Bridge"));
|
const Bridge = lazy(() => import("./containers/Bridge/Bridge"));
|
||||||
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));
|
const NotFound = lazy(() => import("./containers/NotFound/NotFound"));
|
||||||
const Governance = lazy(() => import("./containers/Governance/Governance"));
|
|
||||||
const ProposalDetails = lazy(() => import("./containers/Governance/ProposalDetails"));
|
|
||||||
const NewProposal = lazy(() => import("./containers/Governance/NewProposal"));
|
|
||||||
|
|
||||||
const PREFIX = "App";
|
const PREFIX = "App";
|
||||||
|
|
||||||
@ -216,9 +213,6 @@ function App() {
|
|||||||
}
|
}
|
||||||
<Route path="/bridge" element={<Bridge config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
<Route path="/bridge" element={<Bridge config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||||
<Route path="/dex/:name" element={<Dex connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
<Route path="/dex/:name" element={<Dex connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />
|
||||||
{isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance" element={<Governance config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />}
|
|
||||||
{isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance/:id" element={<ProposalDetails config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />}
|
|
||||||
{isGovernanceAvailable(chainId, addressChainId) && <Route path="/governance/create" element={<NewProposal config={config} connect={tryConnectInjected} address={address} chainId={addressChainId ? addressChainId : chainId} />} />}
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
<Route path="/empty" element={<NotFound
|
<Route path="/empty" element={<NotFound
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -20,7 +20,7 @@ const StyledMuiChip = styled(MuiChip, {
|
|||||||
: template === "gray"
|
: template === "gray"
|
||||||
? theme.colors.gray[500]
|
? theme.colors.gray[500]
|
||||||
: template === "darkGray"
|
: template === "darkGray"
|
||||||
? theme.colors.primary[300]
|
? theme.colors.gray[600]
|
||||||
: theme.colors.feedback[template]
|
: theme.colors.feedback[template]
|
||||||
: theme.palette.mode === "light"
|
: theme.palette.mode === "light"
|
||||||
? theme.colors.gray[90]
|
? theme.colors.gray[90]
|
||||||
@ -34,7 +34,7 @@ const StyledMuiChip = styled(MuiChip, {
|
|||||||
: template === "gray"
|
: template === "gray"
|
||||||
? theme.colors.gray[10]
|
? theme.colors.gray[10]
|
||||||
: template === "darkGray"
|
: template === "darkGray"
|
||||||
? theme.colors.gray[800]
|
? theme.colors.gray[90]
|
||||||
: theme.colors.gray[600],
|
: theme.colors.gray[600],
|
||||||
fontWeight: strong ? 700 : 450,
|
fontWeight: strong ? 700 : 450,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
import { Box, LinearProgress as MuiLinearProgress } from "@mui/material";
|
|
||||||
import { styled } from "@mui/material/styles";
|
|
||||||
|
|
||||||
const PREFIX = "MuiLinearProgress";
|
|
||||||
|
|
||||||
const classes = {
|
|
||||||
chip: `${PREFIX}-bar`,
|
|
||||||
};
|
|
||||||
|
|
||||||
const StyledMuiLinearProgress = styled(MuiLinearProgress, {
|
|
||||||
shouldForwardProp: (prop) => prop !== "barBackground" && prop !== 'barColor' && prop !== 'height'
|
|
||||||
})(({ theme, barColor, barBackground, height }) => ({
|
|
||||||
height: height || 8,
|
|
||||||
borderRadius: 4,
|
|
||||||
backgroundColor: barBackground || theme.palette.grey[300],
|
|
||||||
'& .MuiLinearProgress-bar': {
|
|
||||||
backgroundColor: barColor || theme.palette.primary.main
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
const LinearProgressBar = (props) => {
|
|
||||||
return (
|
|
||||||
<Box sx={{ position: 'relative', width: '100%', py: 1 }}>
|
|
||||||
<StyledMuiLinearProgress {...props} />
|
|
||||||
{props.target && <Box
|
|
||||||
sx={{
|
|
||||||
position: 'absolute',
|
|
||||||
left: `${props.target}%`,
|
|
||||||
top: props.targetTop || 0,
|
|
||||||
bottom: props.targetBottom || 0,
|
|
||||||
width: props.targetWidth || "2px",
|
|
||||||
backgroundColor: props.targetBackgroundColor || 'white',
|
|
||||||
}}
|
|
||||||
></Box>}
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LinearProgressBar;
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
import { Box, MenuItem, Select as MuiSelect, Typography, useTheme } from "@mui/material";
|
|
||||||
import { styled } from "@mui/material/styles";
|
|
||||||
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
|
||||||
|
|
||||||
const StyledSelectInput = styled(MuiSelect, {
|
|
||||||
shouldForwardProp: prop => prop !== "inputWidth"
|
|
||||||
})(({ theme, inputWidth }) => ({
|
|
||||||
width: "100%",
|
|
||||||
"& .MuiSelect-select": {
|
|
||||||
padding: 0,
|
|
||||||
height: "24px !important",
|
|
||||||
minHeight: "24px !important",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
fontSize: "18px",
|
|
||||||
fontWeight: 500,
|
|
||||||
paddingRight: "24px",
|
|
||||||
},
|
|
||||||
"& .MuiOutlinedInput-notchedOutline": {
|
|
||||||
border: "none",
|
|
||||||
},
|
|
||||||
"& .MuiSelect-icon": {
|
|
||||||
right: 0,
|
|
||||||
position: "absolute",
|
|
||||||
color: theme.colors.gray[500],
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
const Select = ({
|
|
||||||
label,
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
options,
|
|
||||||
inputWidth,
|
|
||||||
renderValue = null,
|
|
||||||
width = "100%",
|
|
||||||
}) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
display="flex"
|
|
||||||
flexDirection="column"
|
|
||||||
width={width}
|
|
||||||
sx={{ backgroundColor: theme.colors.gray[750] }}
|
|
||||||
borderRadius="12px"
|
|
||||||
padding="15px"
|
|
||||||
>
|
|
||||||
{label && (
|
|
||||||
<Typography color={theme.colors.gray[500]} fontSize="12px" marginBottom="8px">
|
|
||||||
{label}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
|
||||||
<StyledSelectInput
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
inputWidth={inputWidth}
|
|
||||||
IconComponent={KeyboardArrowDownIcon}
|
|
||||||
renderValue={renderValue}
|
|
||||||
displayEmpty
|
|
||||||
>
|
|
||||||
{options.map((opt) => (
|
|
||||||
<MenuItem key={opt.value} value={opt.value}>
|
|
||||||
{opt.label}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</StyledSelectInput>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Select;
|
|
||||||
@ -24,8 +24,6 @@ import TelegramIcon from '@mui/icons-material/Telegram';
|
|||||||
import HowToVoteIcon from '@mui/icons-material/HowToVote';
|
import HowToVoteIcon from '@mui/icons-material/HowToVote';
|
||||||
import HubIcon from '@mui/icons-material/Hub';
|
import HubIcon from '@mui/icons-material/Hub';
|
||||||
import PublicIcon from '@mui/icons-material/Public';
|
import PublicIcon from '@mui/icons-material/Public';
|
||||||
import ForkRightIcon from '@mui/icons-material/ForkRight';
|
|
||||||
import GavelIcon from '@mui/icons-material/Gavel';
|
|
||||||
import ForumIcon from '@mui/icons-material/Forum';
|
import ForumIcon from '@mui/icons-material/Forum';
|
||||||
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
||||||
import BookIcon from '@mui/icons-material/Book';
|
import BookIcon from '@mui/icons-material/Book';
|
||||||
@ -39,7 +37,7 @@ import BondIcon from "../Icon/BondIcon";
|
|||||||
import StakeIcon from "../Icon/StakeIcon";
|
import StakeIcon from "../Icon/StakeIcon";
|
||||||
import WrapIcon from "../Icon/WrapIcon";
|
import WrapIcon from "../Icon/WrapIcon";
|
||||||
|
|
||||||
import { isNetworkAvailable, isNetworkLegacy, isGovernanceAvailable } from "../../constants";
|
import { isNetworkAvailable, isNetworkLegacy } from "../../constants";
|
||||||
import { AVAILABLE_DEXES } from "../../constants/dexes";
|
import { AVAILABLE_DEXES } from "../../constants/dexes";
|
||||||
import { ECOSYSTEM } from "../../constants/ecosystem";
|
import { ECOSYSTEM } from "../../constants/ecosystem";
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
@ -179,8 +177,7 @@ const NavContent = ({ chainId, addressChainId }) => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<NavItem icon={StakeIcon} label={`Stake`} to="/stake" />
|
<NavItem icon={StakeIcon} label={`Stake`} to="/stake" />
|
||||||
<NavItem icon={ForkRightIcon} label={`Bridge`} to="/bridge" />
|
<NavItem icon={PublicIcon} label={`Bridge`} to="/bridge" />
|
||||||
{isGovernanceAvailable(chainId, addressChainId) && <NavItem icon={GavelIcon} label={`Governance`} to="/governance" />}
|
|
||||||
<Box className="menu-divider">
|
<Box className="menu-divider">
|
||||||
<Divider />
|
<Divider />
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import Token from "../Token/Token";
|
|||||||
|
|
||||||
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
||||||
|
|
||||||
export const StyledInputBase = styled(InputBase, { shouldForwardProp: prop => prop !== "inputWidth" })(
|
const StyledInputBase = styled(InputBase, { shouldForwardProp: prop => prop !== "inputWidth" })(
|
||||||
({ inputWidth, inputFontSize }) => ({
|
({ inputWidth, inputFontSize }) => ({
|
||||||
"& .MuiInputBase-input": {
|
"& .MuiInputBase-input": {
|
||||||
padding: 0,
|
padding: 0,
|
||||||
|
|||||||
@ -4,19 +4,6 @@ export enum NetworkId {
|
|||||||
TESTNET_MORDOR = 63,
|
TESTNET_MORDOR = 63,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isGovernanceAvailable = (chainId, addressChainId) => {
|
|
||||||
chainId = addressChainId ? addressChainId : chainId;
|
|
||||||
let exists = false;
|
|
||||||
switch (chainId) {
|
|
||||||
case 11155111:
|
|
||||||
exists = true
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isNetworkAvailable = (chainId, addressChainId) => {
|
export const isNetworkAvailable = (chainId, addressChainId) => {
|
||||||
chainId = addressChainId ? addressChainId : chainId;
|
chainId = addressChainId ? addressChainId : chainId;
|
||||||
let exists = false;
|
let exists = false;
|
||||||
@ -39,6 +26,9 @@ export const isNetworkAvailable = (chainId, addressChainId) => {
|
|||||||
export const isNetworkLegacy = (chainId) => {
|
export const isNetworkLegacy = (chainId) => {
|
||||||
let exists = false;
|
let exists = false;
|
||||||
switch (chainId) {
|
switch (chainId) {
|
||||||
|
case 11155111:
|
||||||
|
exists = true
|
||||||
|
break;
|
||||||
case 560048:
|
case 560048:
|
||||||
exists = true
|
exists = true
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -1,25 +1,25 @@
|
|||||||
import { NetworkId } from "../constants";
|
import { NetworkId } from "../constants";
|
||||||
|
|
||||||
export const STAKING_ADDRESSES = {
|
export const STAKING_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xC2C579631Bf6daA93252154080fecfd68c6aa506",
|
[NetworkId.TESTNET_SEPOLIA]: "0xd90E63E88282596E1ea33765b41Ba3d650f4aD52",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
[NetworkId.TESTNET_HOODI]: "0x25F62eDc6C89FF84E957C22336A35d2dfc861a86",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0xC25C9C56a89ebd6ef291b415d00ACfa7913c55e7",
|
[NetworkId.TESTNET_MORDOR]: "0xC25C9C56a89ebd6ef291b415d00ACfa7913c55e7",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BOND_DEPOSITORY_ADDRESSES = {
|
export const BOND_DEPOSITORY_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x46BF6F7c3e96351eab7542f2B14c9f2ac6d08dF0",
|
[NetworkId.TESTNET_SEPOLIA]: "0xdcE486113280e49ca2fB200258E5Ee1B2D21D495",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571",
|
[NetworkId.TESTNET_HOODI]: "0x6Ad50B1E293E68B2fC230c576220a93A9D311571",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0x7C85cDEddBAd0f50453d373F7332BEa11ECa7BAf",
|
[NetworkId.TESTNET_MORDOR]: "0x7C85cDEddBAd0f50453d373F7332BEa11ECa7BAf",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DAO_TREASURY_ADDRESSES = {
|
export const DAO_TREASURY_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x05D797f9F34844594C956da58f1785997397f02E",
|
[NetworkId.TESTNET_SEPOLIA]: "0x93dd30f819403710de7933B79A74C4A42438458D",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8",
|
[NetworkId.TESTNET_HOODI]: "0x1a1b29b18f714fac9dDabEf530dFc4f85b56A6e8",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0x5883C8e2259556B534036c7fDF4555E09dE9f243",
|
[NetworkId.TESTNET_MORDOR]: "0x5883C8e2259556B534036c7fDF4555E09dE9f243",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FTSO_DAI_LP_ADDRESSES = {
|
export const FTSO_DAI_LP_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xCd1505E5d169525e0241c177aF5929A92E02276D",
|
[NetworkId.TESTNET_SEPOLIA]: "0x1394dC3f7bABaa2F0CA80353648087DAB1BF3fd6",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50",
|
[NetworkId.TESTNET_HOODI]: "0xf7B2d44209E70782d93A70F7D8eC50010dF7ae50",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0xE6546D12665dB5B22Cb92FB9e0221aE51A57aeaa",
|
[NetworkId.TESTNET_MORDOR]: "0xE6546D12665dB5B22Cb92FB9e0221aE51A57aeaa",
|
||||||
};
|
};
|
||||||
@ -31,47 +31,49 @@ export const FTSO_STNK_LP_ADDRESSES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const RESERVE_ADDRESSES = {
|
export const RESERVE_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
|
[NetworkId.TESTNET_SEPOLIA]: "0x5f63a27a9214a0352F2EF8dAF1eD4974d713192B",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58",
|
[NetworkId.TESTNET_HOODI]: "0x80c6676c334BCcE60b3CC852085B72143379CE58",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC",
|
[NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WETH_ADDRESSES = {
|
export const WETH_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
|
[NetworkId.TESTNET_SEPOLIA]: "0xfff9976782d46cc05630d1f6ebab18b2324d6b14",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xE69a5c6dd88cA798b93c3C92fc50c51Fd5305eB4",
|
[NetworkId.TESTNET_HOODI]: "0xE69a5c6dd88cA798b93c3C92fc50c51Fd5305eB4",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC",
|
[NetworkId.TESTNET_MORDOR]: "0x6af91B3763b5d020E0985f85555EB50e5852d7AC",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GHST_ADDRESSES = {
|
export const GHST_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x1eCee8BfceC44e535B3Ee92Aca70507668781392",
|
[NetworkId.TESTNET_SEPOLIA]: "0xdf2e5306A3dCcfA4e21bbF4226C17Ff5B008dDC4",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46",
|
[NetworkId.TESTNET_HOODI]: "0xE98f7426457E6533B206e91B7EcA97aa8A258B46",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0x14b5787F8a1E62786F50A7998A9b14aa24298423",
|
[NetworkId.TESTNET_MORDOR]: "0x14b5787F8a1E62786F50A7998A9b14aa24298423",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const STNK_ADDRESSES = {
|
export const STNK_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xa31cf59baC26Dd8A8b422b999eB1Ba541C941EA7",
|
[NetworkId.TESTNET_SEPOLIA]: "0x02C296A27eA779d5a16F934337c12062C5E3c0D9",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F",
|
[NetworkId.TESTNET_HOODI]: "0xF07e9303A9f16Afd82f4f57Fd6fca68Aa0AB6D7F",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0x137bA9403885D8ECEa95AaFBb8734F5a16121bAC",
|
[NetworkId.TESTNET_MORDOR]: "0x137bA9403885D8ECEa95AaFBb8734F5a16121bAC",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FTSO_ADDRESSES = {
|
export const FTSO_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x7ebd1224D36d64eA09312073e60f352d1383801A",
|
[NetworkId.TESTNET_SEPOLIA]: "0xcFedFFEB3FdeCd2196820Ba3b71f3F84A1255f93",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033",
|
[NetworkId.TESTNET_HOODI]: "0xb184e423811b644A1924334E63985c259F5D0033",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0xeA170CC0faceC531a6a9e93a28C4330Ac50343a1",
|
[NetworkId.TESTNET_MORDOR]: "0xeA170CC0faceC531a6a9e93a28C4330Ac50343a1",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DISTRIBUTOR_ADDRESSES = {
|
export const DISTRIBUTOR_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xfa524772eec78FAeD0db2cF8A831FDDa9F5B0544",
|
[NetworkId.TESTNET_SEPOLIA]: "0x8fbF8eB4Fcd451EF62Aee33508D46FE120963194",
|
||||||
[NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842",
|
[NetworkId.TESTNET_HOODI]: "0xdF49dC81c457c6f92e26cf6d686C7a8715255842",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0xaf5e76706520db7fb01096E322940206bf3fce57",
|
[NetworkId.TESTNET_MORDOR]: "0xaf5e76706520db7fb01096E322940206bf3fce57",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GHOST_GOVERNANCE_ADDRESSES = {
|
export const GHOST_GOVERNANCE_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0x4823F1DC785D721eAdD2bD218E1eeD63aF67fBF4",
|
[NetworkId.TESTNET_SEPOLIA]: "0xDab0c51918E6990d8763FAC8a04AE159e44e0c4f",
|
||||||
|
[NetworkId.TESTNET_HOODI]: "0x1B96B792840d4d19d5097ee007392Ed4d851e64F",
|
||||||
|
[NetworkId.TESTNET_MORDOR]: "0x3dD438416D9593A58193fC52850E588efAa3D57E",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BONDING_CALCULATOR_ADDRESSES = {
|
export const BONDING_CALCULATOR_ADDRESSES = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: "0xfA821181de76D3EAdb404dDe971A6d28289F22b3",
|
[NetworkId.TESTNET_SEPOLIA]: "0x4896bFc6256A57Df826d7144E48c9633d51d6319",
|
||||||
[NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd",
|
[NetworkId.TESTNET_HOODI]: "0x2635d526Ad24b98082563937f7b996075052c6Fd",
|
||||||
[NetworkId.TESTNET_MORDOR]: "0x0c4C7C49a173E2a3f9Eed93125F3F146D8e17bCb",
|
[NetworkId.TESTNET_MORDOR]: "0x0c4C7C49a173E2a3f9Eed93125F3F146D8e17bCb",
|
||||||
}
|
}
|
||||||
@ -109,10 +111,6 @@ export const NATIVE_TICKERS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const CEX_TICKERS = {
|
export const CEX_TICKERS = {
|
||||||
[NetworkId.TESTNET_SEPOLIA]: [
|
|
||||||
"https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT",
|
|
||||||
"https://api.coinbase.com/v2/prices/ETH-USDT/spot",
|
|
||||||
],
|
|
||||||
[NetworkId.TESTNET_MORDOR]: [
|
[NetworkId.TESTNET_MORDOR]: [
|
||||||
"https://api.binance.com/api/v3/ticker/price?symbol=ETCUSDT",
|
"https://api.binance.com/api/v3/ticker/price?symbol=ETCUSDT",
|
||||||
"https://api.coinbase.com/v2/prices/ETC-USDT/spot",
|
"https://api.coinbase.com/v2/prices/ETC-USDT/spot",
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Box, Tab, Tabs, Typography, Container, useMediaQuery } from "@mui/material";
|
import { Box, Tab, Tabs, Container, useMediaQuery } from "@mui/material";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import ReactGA from "react-ga4";
|
import ReactGA from "react-ga4";
|
||||||
|
|
||||||
import Paper from "../../components/Paper/Paper";
|
import Paper from "../../components/Paper/Paper";
|
||||||
@ -20,6 +21,7 @@ import { useTokenSymbol } from "../../hooks/tokens";
|
|||||||
|
|
||||||
const Bonds = ({ chainId, address, connect }) => {
|
const Bonds = ({ chainId, address, connect }) => {
|
||||||
const [isZoomed] = useState(false);
|
const [isZoomed] = useState(false);
|
||||||
|
const navigate = useNavigate();
|
||||||
const [secondsTo, setSecondsTo] = useState(0);
|
const [secondsTo, setSecondsTo] = useState(0);
|
||||||
|
|
||||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
||||||
@ -27,7 +29,7 @@ const Bonds = ({ chainId, address, connect }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
ReactGA.send({ hitType: "pageview", page: "/bonds" });
|
ReactGA.send({ hitType: "pageview", page: "/bonds" });
|
||||||
}, []);
|
}, [])
|
||||||
|
|
||||||
const { liveBonds } = useLiveBonds(chainId);
|
const { liveBonds } = useLiveBonds(chainId);
|
||||||
const totalReserves = useTotalReserves(chainId);
|
const totalReserves = useTotalReserves(chainId);
|
||||||
@ -57,17 +59,7 @@ const Bonds = ({ chainId, address, connect }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box display="flex" alignItems="center" justifyContent="center" flexDirection="column">
|
<Box display="flex" alignItems="center" justifyContent="center" flexDirection="column">
|
||||||
<Paper
|
<Paper headerText="Active bonds" fullWidth enableBackground>
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Active bonds
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<MetricCollection>
|
<MetricCollection>
|
||||||
<Metric
|
<Metric
|
||||||
label={`Treasury Balance`}
|
label={`Treasury Balance`}
|
||||||
|
|||||||
@ -83,17 +83,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
|
|||||||
warmupLength={warmupInfo.expiry - epoch.number}
|
warmupLength={warmupInfo.expiry - epoch.number}
|
||||||
setPreClaimConfirmed={() => setPreClaimConfirmed(true)}
|
setPreClaimConfirmed={() => setPreClaimConfirmed(true)}
|
||||||
/>
|
/>
|
||||||
<Paper
|
<Paper headerText="Your Bonds" fullWidth enableBackground>
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Your Bonds
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Box display="flex" flexDirection="column" alignItems="center">
|
<Box display="flex" flexDirection="column" alignItems="center">
|
||||||
<Typography variant="h4" align="center" color="textSecondary">
|
<Typography variant="h4" align="center" color="textSecondary">
|
||||||
Payout Options
|
Payout Options
|
||||||
|
|||||||
@ -129,18 +129,10 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
});
|
});
|
||||||
const blockCommitments = useBlockCommitments({ evmChainId: chainId });
|
const blockCommitments = useBlockCommitments({ evmChainId: chainId });
|
||||||
const disabledValidators = useDisabledValidators();
|
const disabledValidators = useDisabledValidators();
|
||||||
const transactionApplausedDirect = useApplauseDetails({
|
const transactionApplaused = useApplauseDetails({
|
||||||
currentSession: watchTransaction?.sessionIndex ?? currentSession,
|
currentSession: watchTransaction?.sessionIndex ?? currentSession,
|
||||||
argsHash: hashedArguments
|
argsHash: hashedArguments
|
||||||
});
|
});
|
||||||
const transactionApplausedIncremented = useApplauseDetails({
|
|
||||||
currentSession: watchTransaction ? watchTransaction.sessionIndex + 1 : undefined,
|
|
||||||
argsHash: hashedArguments
|
|
||||||
});
|
|
||||||
|
|
||||||
const transactionApplaused = useMemo(() => {
|
|
||||||
return transactionApplausedDirect || transactionApplausedIncremented;
|
|
||||||
}, [transactionApplausedDirect, transactionApplausedIncremented]);
|
|
||||||
|
|
||||||
const finalityDelay = Number(evmNetwork?.finality_delay ?? 0n);
|
const finalityDelay = Number(evmNetwork?.finality_delay ?? 0n);
|
||||||
|
|
||||||
@ -252,10 +244,10 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
if (commit.disabled || blockNumber < blocksInFourHours) {
|
if (commit.disabled || blockNumber < blocksInFourHours) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
certainty += (commit?.lastStoredBlock ?? 0n) + BigInt(finalityDelay) - (blockNumber - blocksInFourHours);
|
certainty += (commit?.lastStoredBlock ?? 0n) - (blockNumber - blocksInFourHours);
|
||||||
}
|
}
|
||||||
return Math.max(Number(certainty * 100n / (blocksInFourHours * BigInt(length))), 0);
|
return Math.max(Number(certainty * 100n / (blocksInFourHours * BigInt(length))), 0);
|
||||||
}, [latestCommits, blockNumber, finalityDelay]);
|
}, [latestCommits, blockNumber]);
|
||||||
|
|
||||||
const timeToNextEpoch = useMemo(() => {
|
const timeToNextEpoch = useMemo(() => {
|
||||||
if (!currentSession || !genesisSlot || !currentSlot) {
|
if (!currentSession || !genesisSlot || !currentSlot) {
|
||||||
@ -280,11 +272,8 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const storeTransactionHash = (txHash, receiver, amount) => {
|
const storeTransactionHash = (txHash, receiver, amount) => {
|
||||||
const expectedSessionIndex = (currentSession ?? 0) + (evmNetwork
|
|
||||||
? Number((evmNetwork.avg_block_speed * evmNetwork.finality_delay) / (1000n * 14400n))
|
|
||||||
: 0);
|
|
||||||
const transaction = {
|
const transaction = {
|
||||||
sessionIndex: expectedSessionIndex,
|
sessionIndex: currentSession ?? 0,
|
||||||
transactionHash: txHash,
|
transactionHash: txHash,
|
||||||
receiverAddress: receiver,
|
receiverAddress: receiver,
|
||||||
amount: amount,
|
amount: amount,
|
||||||
@ -302,7 +291,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageTitle name="GHOST Bridge" subtitle={`Bridge $${ghstSymbol} via the only pure Web3 protocol`} />
|
<PageTitle name="GHOST Bridge" subtitle="The only pure Web3 decentralized bridge." />
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||||
@ -343,7 +332,6 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
transactionEta={slowestEvmBlock ? Number(slowestEvmBlock) : undefined}
|
transactionEta={slowestEvmBlock ? Number(slowestEvmBlock) : undefined}
|
||||||
timeToNextEpoch={timeToNextEpoch ? Number(timeToNextEpoch) : undefined}
|
timeToNextEpoch={timeToNextEpoch ? Number(timeToNextEpoch) : undefined}
|
||||||
isSmallScreen={isSmallScreen}
|
isSmallScreen={isSmallScreen}
|
||||||
maxDelay={14400 + finalityDelay * Number(networkAvgBlockSpeed(chainId))}
|
|
||||||
/>
|
/>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -359,7 +347,7 @@ const Bridge = ({ chainId, address, config, connect }) => {
|
|||||||
onClick={() => setBridgeAction(!bridgeAction)}
|
onClick={() => setBridgeAction(!bridgeAction)}
|
||||||
/>)}
|
/>)}
|
||||||
<Typography variant="h4">{
|
<Typography variant="h4">{
|
||||||
bridgeAction ? `Bridge-In $${ghstSymbol}` : "Transaction History"
|
bridgeAction ? `Bridge $${ghstSymbol}` : "Transaction History"
|
||||||
}</Typography>
|
}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,6 @@ export const BridgeHeader = ({
|
|||||||
bridgeStability,
|
bridgeStability,
|
||||||
transactionEta,
|
transactionEta,
|
||||||
timeToNextEpoch,
|
timeToNextEpoch,
|
||||||
maxDelay,
|
|
||||||
isSmallScreen
|
isSmallScreen
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -93,7 +92,7 @@ export const BridgeHeader = ({
|
|||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
<Grid item xs={isSmallScreen ? 12 : 4}>
|
||||||
<Metric
|
<Metric
|
||||||
isLoading={transactionEta === undefined}
|
isLoading={transactionEta === undefined}
|
||||||
metric={transactionEta > maxDelay ? "∞" : formatTime(transactionEta)}
|
metric={transactionEta > 14400 ? "∞" : formatTime(transactionEta)}
|
||||||
label="Max Bridge ETA"
|
label="Max Bridge ETA"
|
||||||
tooltip="Maximum estimated time for finalizing bridge transactions based on the latest update."
|
tooltip="Maximum estimated time for finalizing bridge transactions based on the latest update."
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -186,7 +186,7 @@ const Dex = ({ chainId, address, connect }) => {
|
|||||||
|
|
||||||
<PageTitle
|
<PageTitle
|
||||||
name={`${pathname.name.charAt(0).toUpperCase() + pathname.name.slice(1).toLowerCase()} V2 Classic`}
|
name={`${pathname.name.charAt(0).toUpperCase() + pathname.name.slice(1).toLowerCase()} V2 Classic`}
|
||||||
subtitle="Swap via Uniswap V2 Fork"
|
subtitle="Classic interface to V2 smart contracts."
|
||||||
/>
|
/>
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@ -159,7 +159,7 @@ const Faucet = ({ chainId, address, config, connect }) => {
|
|||||||
<meta name="twitter:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
|
<meta name="twitter:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
||||||
<PageTitle name={`${reserveSymbol} Faucet`} subtitle={`Swap Sepolia ${nativeInfo.symbol} for ${reserveSymbol}`} />
|
<PageTitle name={`${reserveSymbol} Faucet`} subtitle={`Swap Sepolia ${nativeInfo.symbol} for ${reserveSymbol}.`} />
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||||
|
|||||||
@ -1,94 +0,0 @@
|
|||||||
import { useEffect } from "react";
|
|
||||||
import ReactGA from "react-ga4";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
import { Box, Container, Grid, Divider, Typography, useMediaQuery } from "@mui/material";
|
|
||||||
|
|
||||||
import Paper from "../../components/Paper/Paper";
|
|
||||||
import PageTitle from "../../components/PageTitle/PageTitle";
|
|
||||||
import { PrimaryButton } from "../../components/Button";
|
|
||||||
|
|
||||||
import GovernanceInfoText from "./components/GovernanceInfoText";
|
|
||||||
import ProposalsList from "./components/ProposalsList";
|
|
||||||
import { ProposalsCount, MinQuorumPercentage, ProposalThreshold } from "./components/Metric";
|
|
||||||
|
|
||||||
import { useTokenSymbol } from "../../hooks/tokens";
|
|
||||||
|
|
||||||
const Governance = ({ connect, config, address, chainId }) => {
|
|
||||||
const isSemiSmallScreen = useMediaQuery("(max-width: 745px)");
|
|
||||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
|
||||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
|
||||||
|
|
||||||
const handleModal = () => {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
ReactGA.send({ hitType: "pageview", page: "/governance" });
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<PageTitle name="Protocol Governance" subtitle={`Cast $${ghstSymbol} to facilitate DAO decisions`} />
|
|
||||||
<Container
|
|
||||||
style={{
|
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
|
||||||
paddingRight: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
|
||||||
minHeight: "calc(100vh - 128px)",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ mt: "15px" }}>
|
|
||||||
<Paper
|
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Proposal Requirements
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Grid container spacing={1}>
|
|
||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
|
||||||
<ProposalsCount chainId={chainId} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
|
||||||
<MinQuorumPercentage chainId={chainId} ghstSymbol={ghstSymbol} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={isSmallScreen ? 12 : 4}>
|
|
||||||
<ProposalThreshold chainId={chainId} ghstSymbol={ghstSymbol} />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Divider sx={{ marginTop: "30px" }} />
|
|
||||||
<Box display="flex" justifyContent="center">Claimes for locked funds could be here</Box>
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
<Box mt="15px" display="flex" flexDirection="column" alignItems="center" justifyContent="center">
|
|
||||||
<PrimaryButton
|
|
||||||
fullWidth
|
|
||||||
onClick={() => navigate(`/governance/create`)}
|
|
||||||
sx={{ maxWidth: isSemiSmallScreen ? "100%" : "350px" }}
|
|
||||||
>
|
|
||||||
Create Proposal
|
|
||||||
</PrimaryButton>
|
|
||||||
<Box textAlign="center" mt="15px">
|
|
||||||
<GovernanceInfoText />
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
|
||||||
<ProposalsList config={config} chainId={chainId} />
|
|
||||||
</Box>
|
|
||||||
</Container>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Governance;
|
|
||||||
@ -1,156 +0,0 @@
|
|||||||
import { useState, useMemo } from "react";
|
|
||||||
import toast from "react-hot-toast";
|
|
||||||
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Container,
|
|
||||||
TableContainer,
|
|
||||||
Table,
|
|
||||||
TableRow,
|
|
||||||
TableBody,
|
|
||||||
TableHead,
|
|
||||||
TableCell,
|
|
||||||
Typography,
|
|
||||||
Link,
|
|
||||||
OutlinedInput,
|
|
||||||
InputLabel,
|
|
||||||
FormControl,
|
|
||||||
useMediaQuery,
|
|
||||||
useTheme
|
|
||||||
} from "@mui/material";
|
|
||||||
|
|
||||||
import GhostStyledIcon from "../../components/Icon/GhostIcon";
|
|
||||||
import ArrowUpIcon from "../../assets/icons/arrow-up.svg?react";
|
|
||||||
|
|
||||||
import Paper from "../../components/Paper/Paper";
|
|
||||||
import PageTitle from "../../components/PageTitle/PageTitle";
|
|
||||||
import { PrimaryButton, TertiaryButton } from "../../components/Button";
|
|
||||||
import { useTokenSymbol } from "../../hooks/tokens";
|
|
||||||
|
|
||||||
import ProposalModal from "./components/ProposalModal";
|
|
||||||
import { parseFunctionCalldata } from "./components/functions/index";
|
|
||||||
|
|
||||||
const NewProposal = ({ config, address, connect, chainId }) => {
|
|
||||||
const isSemiSmallScreen = useMediaQuery("(max-width: 745px)");
|
|
||||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
|
||||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
|
||||||
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
|
||||||
|
|
||||||
const [isModalOpened, setIsModalOpened] = useState(false);
|
|
||||||
const [proposalFunctions, setProposalFunctions] = useState([]);
|
|
||||||
|
|
||||||
const addCalldata = (calldata) => setProposalFunctions(prev => [...prev, calldata]);
|
|
||||||
const removeCalldata = (index) => setProposalFunctions(prev => prev.filter((_, i) => i !== index));
|
|
||||||
|
|
||||||
const nativeCurrency = useMemo(() => {
|
|
||||||
const client = config?.getClient();
|
|
||||||
return client?.chain?.nativeCurrency?.symbol;
|
|
||||||
}, [config]);
|
|
||||||
|
|
||||||
const submitProposal = () => {
|
|
||||||
toast.success("Coming soon! It's already connected to the chain data!", { duration: 5000 });
|
|
||||||
setProposalFunctions([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<ProposalModal
|
|
||||||
nativeCurrency={nativeCurrency}
|
|
||||||
ftsoSymbol={ftsoSymbol}
|
|
||||||
chainId={chainId}
|
|
||||||
addCalldata={addCalldata}
|
|
||||||
isOpened={isModalOpened}
|
|
||||||
closeModal={() => setIsModalOpened(false)}
|
|
||||||
/>
|
|
||||||
<Box>
|
|
||||||
<PageTitle name="Create Proposal" subtitle="Cool text describing what's goinf on there" />
|
|
||||||
<Container
|
|
||||||
style={{
|
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
|
||||||
paddingRight: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
|
||||||
minHeight: "calc(100vh - 128px)",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ mt: "15px" }}>
|
|
||||||
<Paper
|
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Proposal Functions
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Box>
|
|
||||||
<Box>
|
|
||||||
{proposalFunctions.length === 0 && <Box
|
|
||||||
width="100%"
|
|
||||||
display="flex"
|
|
||||||
flexDirection="column"
|
|
||||||
justifyContent="center"
|
|
||||||
alignItems="center"
|
|
||||||
marginBottom="50px"
|
|
||||||
marginTop="25px"
|
|
||||||
>
|
|
||||||
<Typography variant="subtitle1">
|
|
||||||
Create new proposal by adding functions below
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<PrimaryButton
|
|
||||||
variant="text"
|
|
||||||
href="https://forum.ghostchain.io"
|
|
||||||
>
|
|
||||||
Learn more
|
|
||||||
</PrimaryButton>
|
|
||||||
</Box>}
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
<Box display="flex" flexDirection="column" alignItems="center">
|
|
||||||
<TertiaryButton sx={{ maxWidth: isSemiSmallScreen ? "100%" : "350px" }} fullWidth onClick={() => setIsModalOpened(true)}>Add New</TertiaryButton>
|
|
||||||
<PrimaryButton sx={{ maxWidth: isSemiSmallScreen ? "100%" : "350px" }} fullWidth onClick={() => submitProposal()}>Submit Proposal</PrimaryButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
|
||||||
|
|
||||||
{proposalFunctions.length > 0 && <Paper
|
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Proposal Functions
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TableContainer>
|
|
||||||
<Table aria-label="Available bonds" style={{ tableLayout: "fixed" }}>
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>Function</TableCell>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>Target</TableCell>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>Value</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>{proposalFunctions.map((metadata, index) => {
|
|
||||||
return parseFunctionCalldata(metadata, index, chainId, nativeCurrency, removeCalldata);
|
|
||||||
})}</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
</Paper>}
|
|
||||||
</Box>
|
|
||||||
</Container>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default NewProposal;
|
|
||||||
@ -1,285 +0,0 @@
|
|||||||
import { useEffect, useState, useMemo } from "react";
|
|
||||||
import ReactGA from "react-ga4";
|
|
||||||
import { useParams } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { Box, Container, Typography, Link, useMediaQuery, useTheme } from "@mui/material";
|
|
||||||
|
|
||||||
import Paper from "../../components/Paper/Paper";
|
|
||||||
import PageTitle from "../../components/PageTitle/PageTitle";
|
|
||||||
import LinearProgressBar from "../../components/Progress/LinearProgressBar";
|
|
||||||
import InfoTooltip from "../../components/Tooltip/InfoTooltip";
|
|
||||||
import Chip from "../../components/Chip/Chip";
|
|
||||||
import { SecondaryButton } from "../../components/Button";
|
|
||||||
|
|
||||||
import GhostStyledIcon from "../../components/Icon/GhostIcon";
|
|
||||||
import ArrowUpIcon from "../../assets/icons/arrow-up.svg?react";
|
|
||||||
|
|
||||||
import { formatNumber } from "../../helpers";
|
|
||||||
import { prettifySecondsInDays } from "../../helpers/timeUtil";
|
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
|
||||||
|
|
||||||
import { convertStatusToTemplate } from "./helpers";
|
|
||||||
|
|
||||||
import { useTokenSymbol, useTotalSupply, useBalance } from "../../hooks/tokens";
|
|
||||||
import {
|
|
||||||
useProposalStatus,
|
|
||||||
useProposalProposer,
|
|
||||||
useProposalLocked,
|
|
||||||
useProposalQuorum,
|
|
||||||
useProposalVotes,
|
|
||||||
useProposalSnapshot,
|
|
||||||
useProposalDeadline,
|
|
||||||
useProposalVotingDelay
|
|
||||||
} from "../../hooks/governance";
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
|
||||||
import Timeline from '@mui/lab/Timeline';
|
|
||||||
import TimelineItem from '@mui/lab/TimelineItem';
|
|
||||||
import TimelineSeparator from '@mui/lab/TimelineSeparator';
|
|
||||||
import TimelineConnector from '@mui/lab/TimelineConnector';
|
|
||||||
import TimelineContent from '@mui/lab/TimelineContent';
|
|
||||||
import TimelineOppositeContent from '@mui/lab/TimelineOppositeContent';
|
|
||||||
import TimelineDot from '@mui/lab/TimelineDot';
|
|
||||||
///////////////////////////
|
|
||||||
import FastfoodIcon from '@mui/icons-material/Fastfood';
|
|
||||||
import LaptopMacIcon from '@mui/icons-material/LaptopMac';
|
|
||||||
import HotelIcon from '@mui/icons-material/Hotel';
|
|
||||||
import RepeatIcon from '@mui/icons-material/Repeat';
|
|
||||||
|
|
||||||
const HUNDRED = new DecimalBigNumber(100n, 0);
|
|
||||||
|
|
||||||
const ProposalDetails = ({ chainId, address }) => {
|
|
||||||
const { id } = useParams();
|
|
||||||
const [selectedDiscussionUrl, setSelectedDiscussionUrl] = useState(undefined);
|
|
||||||
|
|
||||||
const isSemiSmallScreen = useMediaQuery("(max-width: 745px)");
|
|
||||||
const isSmallScreen = useMediaQuery("(max-width: 650px)");
|
|
||||||
const isVerySmallScreen = useMediaQuery("(max-width: 379px)");
|
|
||||||
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
|
|
||||||
const { balance } = useBalance(chainId, "GHST", address);
|
|
||||||
const { totalSupply } = useTotalSupply(chainId, "GHST"); // TODO: revisit
|
|
||||||
|
|
||||||
const { status: proposalStatus } = useProposalStatus(chainId, id);
|
|
||||||
const { proposer: proposalProposer } = useProposalProposer(chainId, id);
|
|
||||||
const { locked: proposalLocked } = useProposalLocked(chainId, id);
|
|
||||||
const { quorum: proposalQuorum } = useProposalQuorum(chainId, id);
|
|
||||||
const { forVotes, againstVotes, totalVotes } = useProposalVotes(chainId, id);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
ReactGA.send({ hitType: "pageview", page: `/governance/${id}` });
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const isDiscussionModalOpened = useMemo(() => {
|
|
||||||
return selectedDiscussionUrl !== undefined;
|
|
||||||
}, [selectedDiscussionUrl]);
|
|
||||||
|
|
||||||
const quorumPercentage = useMemo(() => {
|
|
||||||
if (totalSupply._value === 0n) return 0;
|
|
||||||
return proposalQuorum / totalSupply * HUNDRED;
|
|
||||||
}, [proposalQuorum, totalSupply]);
|
|
||||||
|
|
||||||
const votePercentage = useMemo(() => {
|
|
||||||
if (totalSupply._value === 0n) return 0;
|
|
||||||
return totalVotes / totalSupply * HUNDRED;
|
|
||||||
}, [totalVotes, totalSupply]);
|
|
||||||
|
|
||||||
const voteWeightPercentage = useMemo(() => {
|
|
||||||
if (totalSupply._value === 0n) return 0;
|
|
||||||
return balance / totalSupply * HUNDRED;
|
|
||||||
}, [balance, totalSupply]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<PageTitle name={`GBP: ${id} - NAME`} subtitle={`By: ${proposalProposer} | BONDED: $${proposalLocked} ${ghstSymbol}`} />
|
|
||||||
<Container
|
|
||||||
style={{
|
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
|
||||||
paddingRight: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
|
||||||
minHeight: "calc(100vh - 128px)",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ mt: "15px" }}>
|
|
||||||
<Box display="flex" justifyContent="space-between" gap="20px">
|
|
||||||
<Paper
|
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="10px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Progress
|
|
||||||
</Typography>
|
|
||||||
<Chip
|
|
||||||
sx={{ marginTop: "4px", width: "88px" }}
|
|
||||||
label={proposalStatus}
|
|
||||||
template={convertStatusToTemplate(proposalStatus)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
topRight={
|
|
||||||
<Link
|
|
||||||
color={theme.colors.primary[300]}
|
|
||||||
href="https://forum.ghostchain.io"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
display="flex"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
View Forum
|
|
||||||
<GhostStyledIcon
|
|
||||||
style={{ marginTop: "7px" }}
|
|
||||||
viewBox="0 0 30 30"
|
|
||||||
className="external-site-link-icon"
|
|
||||||
component={ArrowUpIcon}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Box height="200px" display="flex" flexDirection="column" justifyContent="space-between" gap="20px">
|
|
||||||
<Box display="flex" flexDirection="column">
|
|
||||||
<Box display="flex" justifyContent="space-between">
|
|
||||||
<Typography sx={{ textShadow: "0 0 black", fontWeight: 600 }} variant="body1" color={theme.colors.feedback.success}>
|
|
||||||
For: {formatNumber(forVotes.toString(), 2)} ({formatNumber(forVotes * HUNDRED / proposalQuorum, 1)}%)
|
|
||||||
</Typography>
|
|
||||||
<Typography sx={{ textShadow: "0 0 black", fontWeight: 600 }} variant="body1" color={theme.colors.feedback.error}>
|
|
||||||
Against: {formatNumber(againstVotes.toString(), 2)} ({formatNumber(againstVotes * HUNDRED / proposalQuorum, 1)}%)
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<LinearProgressBar
|
|
||||||
barColor={theme.colors.feedback.success}
|
|
||||||
barBackground={theme.colors.feedback.error}
|
|
||||||
variant="determinate"
|
|
||||||
value={69}
|
|
||||||
target={Math.floor(Math.random() * 101)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box display="flex" flexDirection="column">
|
|
||||||
<Box display="flex" justifyContent="space-between">
|
|
||||||
<Box display="flex" flexDirection="row">
|
|
||||||
<Typography>Quorum</Typography>
|
|
||||||
<InfoTooltip message={`Minimum $${ghstSymbol} turnout required for the proposal to become valid, as percentage of the total $${ghstSymbol} supply at the time when proposal was created`} />
|
|
||||||
</Box>
|
|
||||||
<Typography>{formatNumber(proposalQuorum.toString(), 4)} ({formatNumber(quorumPercentage, 1)}%)</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box display="flex" justifyContent="space-between">
|
|
||||||
<Box display="flex" flexDirection="row">
|
|
||||||
<Typography>Total</Typography>
|
|
||||||
<InfoTooltip message={`Total votes for the proposal, as percentage of the total $${ghstSymbol} supply at the time when proposal was created`}/>
|
|
||||||
</Box>
|
|
||||||
<Typography>{formatNumber(totalSupply.toString(), 4)} ({formatNumber(votePercentage, 1)}%)</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box display="flex" justifyContent="space-between">
|
|
||||||
<Box display="flex" flexDirection="row">
|
|
||||||
<Typography>Votes</Typography>
|
|
||||||
<InfoTooltip message={`Your voting power, as percentage of total $${ghstSymbol} at the time when proposal was created`} />
|
|
||||||
</Box>
|
|
||||||
<Typography>{formatNumber(balance.toString(), 4)} ({formatNumber(voteWeightPercentage, 1)}%)</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box display="flex" gap="20px">
|
|
||||||
<SecondaryButton fullWidth onClick={() => alert("For vote casted")}>For</SecondaryButton>
|
|
||||||
<SecondaryButton fullWidth onClick={() => alert("Against vote casted")}>Against</SecondaryButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
|
||||||
|
|
||||||
<Paper
|
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Timeline
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<VotingTimeline chainId={chainId} proposalId={id} />
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Paper
|
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Executable Code
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Here will be a list of decoded calldatas
|
|
||||||
</Paper>
|
|
||||||
</Container>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const VotingTimeline = ({ proposalId, chainId }) => {
|
|
||||||
const { delay: propsalVotingDelay } = useProposalVotingDelay(chainId, proposalId);
|
|
||||||
const { snapshot: proposalSnapshot } = useProposalSnapshot(chainId, proposalId);
|
|
||||||
const { deadline: proposalDeadline } = useProposalDeadline(chainId, proposalId);
|
|
||||||
|
|
||||||
const voteStarted = useMemo(() => {
|
|
||||||
if (proposalSnapshot && propsalVotingDelay) {
|
|
||||||
return proposalSnapshot > propsalVotingDelay ? proposalSnapshot - propsalVotingDelay : 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}, [proposalSnapshot, propsalVotingDelay]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Timeline sx={{ margin: 0, padding: 0 }}>
|
|
||||||
<VotingTimelineItem time={voteStarted} message="Proposed on:" isFirst />
|
|
||||||
<VotingTimelineItem time={proposalSnapshot} message="Voting started:" />
|
|
||||||
<VotingTimelineItem time={proposalDeadline} message="Voting ends:" isLast />
|
|
||||||
</Timeline>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const VotingTimelineItem = ({ isFirst, isLast, time, message }) => {
|
|
||||||
return (
|
|
||||||
<TimelineItem>
|
|
||||||
<TimelineOppositeContent
|
|
||||||
sx={{
|
|
||||||
maxWidth: "120px",
|
|
||||||
textAlign: "left",
|
|
||||||
paddingLeft: "0",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography>{message}</Typography>
|
|
||||||
</TimelineOppositeContent>
|
|
||||||
|
|
||||||
<TimelineSeparator>
|
|
||||||
<TimelineConnector sx={{ background: isFirst ? "transparent" : "#fff" }} />
|
|
||||||
<TimelineDot sx={{ width: "15px", height: "15px", background: "#fff", margin: "12px 0" }} />
|
|
||||||
<TimelineConnector sx={{ background: isLast ? "transparent" : "#fff" }} />
|
|
||||||
</TimelineSeparator>
|
|
||||||
|
|
||||||
<TimelineContent
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography>
|
|
||||||
{new Date(time * 1000).toLocaleString()}
|
|
||||||
</Typography>
|
|
||||||
</TimelineContent>
|
|
||||||
</TimelineItem>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ProposalDetails;
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
import { Link, Typography, useTheme } from "@mui/material";
|
|
||||||
|
|
||||||
const GovernanceInfoText = () => {
|
|
||||||
const theme = useTheme();
|
|
||||||
return (
|
|
||||||
<Typography
|
|
||||||
variant="body2"
|
|
||||||
color="textSecondary"
|
|
||||||
fontSize="0.875em"
|
|
||||||
lineHeight="15px"
|
|
||||||
>
|
|
||||||
ghostDAO’s adaptive governance system algorithmically sets minimum collateral based on activity.
|
|
||||||
<Link
|
|
||||||
color={theme.colors.primary[300]}
|
|
||||||
href="https://docs.dao.ghostchain.io/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>Learn more here.</Link>
|
|
||||||
</Typography>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GovernanceInfoText;
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
import Metric from "../../../components/Metric/Metric";
|
|
||||||
|
|
||||||
import { formatCurrency, formatNumber } from "../../../helpers";
|
|
||||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";
|
|
||||||
import { getTokenDecimals } from "../../../hooks/helpers";
|
|
||||||
import { useTotalSupply } from "../../../hooks/tokens";
|
|
||||||
import {
|
|
||||||
useMinQuorum,
|
|
||||||
useProposalThreshold,
|
|
||||||
useProposalCount
|
|
||||||
} from "../../../hooks/governance";
|
|
||||||
|
|
||||||
export const MinQuorumPercentage = props => {
|
|
||||||
const { numerator, denominator, percentage } = useMinQuorum(props.chainId);
|
|
||||||
const { totalSupply } = useTotalSupply(props.chainId, "GHST");
|
|
||||||
const decimals = getTokenDecimals(props.ghstSymbol);
|
|
||||||
|
|
||||||
const value = new DecimalBigNumber(
|
|
||||||
(totalSupply?._value ?? 0n) * numerator / denominator,
|
|
||||||
decimals
|
|
||||||
);
|
|
||||||
|
|
||||||
const _props = {
|
|
||||||
...props,
|
|
||||||
label: `Min Quorum`,
|
|
||||||
tooltip: `Minimum $${props.ghstSymbol} turnout required for the proposal to become valid`,
|
|
||||||
};
|
|
||||||
const tokenValue = formatCurrency(value?.toString(), 2, props.ghstSymbol);
|
|
||||||
const percentageValue = formatNumber(percentage * 100, 2);
|
|
||||||
|
|
||||||
if (percentage) _props.metric = `${tokenValue} (${percentageValue}%)`;
|
|
||||||
else _props.isLoading = true;
|
|
||||||
|
|
||||||
return <Metric {..._props} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ProposalThreshold = props => {
|
|
||||||
const { threshold } = useProposalThreshold(props.chainId, props.ghstSymbol);
|
|
||||||
|
|
||||||
const _props = {
|
|
||||||
...props,
|
|
||||||
label: "Min Collateral",
|
|
||||||
tooltip: `Minimum $${props.ghstSymbol} required to be locked to create a proposal`,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (threshold) _props.metric = `${formatCurrency(threshold.toString(), 2, props.ghstSymbol)}`;
|
|
||||||
else _props.isLoading = true;
|
|
||||||
|
|
||||||
return <Metric {..._props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ProposalsCount = props => {
|
|
||||||
const { proposalCount } = useProposalCount(props.chainId);
|
|
||||||
|
|
||||||
const _props = {
|
|
||||||
...props,
|
|
||||||
label: `Proposal Count`,
|
|
||||||
tooltip: `Total proposals created`,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (proposalCount || proposalCount === 0n) _props.metric = `${formatNumber(proposalCount.toString(), 0)}`;
|
|
||||||
else _props.isLoading = true;
|
|
||||||
|
|
||||||
return <Metric {..._props} />;
|
|
||||||
}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
import { Link, Typography, useTheme } from "@mui/material";
|
|
||||||
|
|
||||||
const ProposalInfoText = () => {
|
|
||||||
const theme = useTheme();
|
|
||||||
return (
|
|
||||||
<Typography
|
|
||||||
variant="body2"
|
|
||||||
color="textSecondary"
|
|
||||||
fontSize="0.875em"
|
|
||||||
lineHeight="15px"
|
|
||||||
>
|
|
||||||
Important: Only the 10 most recent proposals are displayed. Only one proposal can be active at a time.
|
|
||||||
<Link
|
|
||||||
color={theme.colors.primary[300]}
|
|
||||||
href="https://ghostchain.io/ghostdao_litepaper"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>Learn more here.</Link>
|
|
||||||
</Typography>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ProposalInfoText;
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
import { useState, useEffect, useMemo, useCallback } from "react";
|
|
||||||
import { Box, Typography, useTheme } from "@mui/material";
|
|
||||||
|
|
||||||
import Modal from "../../../components/Modal/Modal";
|
|
||||||
import Select from "../../../components/Select/Select";
|
|
||||||
import { PrimaryButton, TertiaryButton } from "../../../components/Button";
|
|
||||||
|
|
||||||
import {
|
|
||||||
getFunctionArguments,
|
|
||||||
getFunctionCalldata,
|
|
||||||
getFunctionDescription,
|
|
||||||
allPossibleFunctions
|
|
||||||
} from "./functions";
|
|
||||||
|
|
||||||
const ProposalModal = ({ isOpened, closeModal, nativeCurrency, ftsoSymbol, addCalldata, chainId }) => {
|
|
||||||
const [selectedOption, setSelectedOption] = useState();
|
|
||||||
const [renderArguments, setRenderArguments] = useState(false);
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
|
||||||
setSelectedOption(event.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const headerLabel = useMemo(() => {
|
|
||||||
const data = allPossibleFunctions.find(obj => obj.value === selectedOption);
|
|
||||||
if (data && renderArguments) {
|
|
||||||
return data.label;
|
|
||||||
}
|
|
||||||
return "Executable Code";
|
|
||||||
}, [selectedOption, renderArguments]);
|
|
||||||
|
|
||||||
const handleCalldata = useCallback(() => {
|
|
||||||
addCalldata(getFunctionCalldata(selectedOption, chainId));
|
|
||||||
setSelectedOption(null);
|
|
||||||
closeModal();
|
|
||||||
}, [selectedOption, chainId]);
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
setSelectedOption(null);
|
|
||||||
setRenderArguments(false);
|
|
||||||
closeModal();
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAddCalldata = (calldata) => {
|
|
||||||
addCalldata(calldata);
|
|
||||||
handleClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
const ArgumentsSteps = useMemo(() => getFunctionArguments(selectedOption, chainId), [selectedOption]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" justifyContent="center" alignItems="center" gap="15px">
|
|
||||||
<Typography variant="h4">{headerLabel}</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
open={isOpened}
|
|
||||||
onClose={handleClose}
|
|
||||||
maxWidth="460px"
|
|
||||||
minHeight="200px"
|
|
||||||
>
|
|
||||||
<Box minHeight="220px" display="flex" alignItems="start" justifyContent="space-between" flexDirection="column">
|
|
||||||
{renderArguments
|
|
||||||
? <ArgumentsSteps
|
|
||||||
nativeCurrency={nativeCurrency}
|
|
||||||
ftsoSymbol={ftsoSymbol}
|
|
||||||
chainId={chainId}
|
|
||||||
addCalldata={handleAddCalldata}
|
|
||||||
toInitialStep={() => setRenderArguments(false)}
|
|
||||||
/>
|
|
||||||
: <InitialStep
|
|
||||||
selectedOption={selectedOption}
|
|
||||||
handleChange={handleChange}
|
|
||||||
handleCalldata={handleCalldata}
|
|
||||||
handleProceed={() => setRenderArguments(true)}
|
|
||||||
ready={ArgumentsSteps !== null}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</Box>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const InitialStep = ({ selectedOption, handleChange, handleCalldata, handleProceed, ready }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const functionDescription = useMemo(() => getFunctionDescription(selectedOption), [selectedOption]);
|
|
||||||
return (
|
|
||||||
<Box minHeight="220px" display="flex" alignItems="start" justifyContent="space-between" flexDirection="column">
|
|
||||||
<Select
|
|
||||||
value={selectedOption ?? ""}
|
|
||||||
onChange={handleChange}
|
|
||||||
options={allPossibleFunctions}
|
|
||||||
inputWidth="100%"
|
|
||||||
renderValue={(selected) => {
|
|
||||||
if (!selected || selected.length === 0) {
|
|
||||||
return (
|
|
||||||
<span style={{ color: theme.colors.gray[500], opacity: 0.7 }}>
|
|
||||||
Select function
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return allPossibleFunctions.find(opt => opt.value === selected)?.label || selected;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Typography align="center" variant="body2">{functionDescription}</Typography>
|
|
||||||
{ready
|
|
||||||
? <TertiaryButton disabled={!selectedOption} onClick={() => handleProceed()} fullWidth>Proceed</TertiaryButton>
|
|
||||||
: <PrimaryButton disabled={!selectedOption} onClick={() => handleCalldata()} fullWidth>Create Function</PrimaryButton>
|
|
||||||
}
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ProposalModal;
|
|
||||||
@ -1,319 +0,0 @@
|
|||||||
import { useState, useMemo } from "react";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Link,
|
|
||||||
Tabs,
|
|
||||||
Tab,
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableContainer,
|
|
||||||
TableHead,
|
|
||||||
TableRow,
|
|
||||||
Typography,
|
|
||||||
useTheme,
|
|
||||||
useMediaQuery
|
|
||||||
} from "@mui/material";
|
|
||||||
import { getBlockNumber } from "@wagmi/core";
|
|
||||||
|
|
||||||
import GhostStyledIcon from "../../../components/Icon/GhostIcon";
|
|
||||||
import ArrowUpIcon from "../../../assets/icons/arrow-up.svg?react";
|
|
||||||
|
|
||||||
import { networkAvgBlockSpeed } from "../../../constants";
|
|
||||||
import { prettifySecondsInDays } from "../../../helpers/timeUtil";
|
|
||||||
|
|
||||||
import Chip from "../../../components/Chip/Chip";
|
|
||||||
import Modal from "../../../components/Modal/Modal";
|
|
||||||
import Paper from "../../../components/Paper/Paper";
|
|
||||||
import LinearProgressBar from "../../../components/Progress/LinearProgressBar";
|
|
||||||
import { PrimaryButton, TertiaryButton } from "../../../components/Button";
|
|
||||||
|
|
||||||
import ProposalInfoText from "./ProposalInfoText";
|
|
||||||
import { convertStatusToTemplate } from "../helpers";
|
|
||||||
|
|
||||||
import { useScreenSize } from "../../../hooks/useScreenSize";
|
|
||||||
|
|
||||||
import {
|
|
||||||
useProposals,
|
|
||||||
} from "../../../hooks/governance";
|
|
||||||
|
|
||||||
const MAX_PROPOSALS_TO_SHOW = 10;
|
|
||||||
|
|
||||||
const ProposalsList = ({ chainId, config }) => {
|
|
||||||
const isSmallScreen = useScreenSize("md");
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const [blockNumber, setBlockNumber] = useState(0n);
|
|
||||||
const [proposalsFilter, setProposalFilter] = useState("active");
|
|
||||||
const { proposals } = useProposals(chainId, MAX_PROPOSALS_TO_SHOW);
|
|
||||||
|
|
||||||
getBlockNumber(config).then(block => setBlockNumber(block));
|
|
||||||
|
|
||||||
const filteredProposals = useMemo(() => {
|
|
||||||
switch (proposalsFilter) {
|
|
||||||
case "voted":
|
|
||||||
return proposals.filter(obj => obj.status === "Succeeded" || obj.status === "Defeated");
|
|
||||||
case "created":
|
|
||||||
return proposals.filter(obj => obj.status === "Executed");
|
|
||||||
default:
|
|
||||||
return proposals;
|
|
||||||
}
|
|
||||||
}, [proposals, proposalsFilter]);
|
|
||||||
|
|
||||||
if (proposals?.length === 0) {
|
|
||||||
return (
|
|
||||||
<Box display="flex" justifyContent="center">
|
|
||||||
<Typography variant="h4">No proposals yet</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSmallScreen) {
|
|
||||||
return (
|
|
||||||
<Paper
|
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Proposals
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Box display="flex" flexDirection="column" gap="40px">
|
|
||||||
{filteredProposals?.map(proposal => (
|
|
||||||
<ProposalCard
|
|
||||||
key={proposal.id}
|
|
||||||
proposal={proposal}
|
|
||||||
blockNumber={blockNumber}
|
|
||||||
chainId={chainId}
|
|
||||||
openProposal={() => navigate(`/governance/${proposal.id}`)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{proposalsFilter === "active" && <Box my="24px" textAlign="center">
|
|
||||||
<ProposalInfoText />
|
|
||||||
</Box>}
|
|
||||||
</Paper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Paper
|
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
display="flex"
|
|
||||||
alignItems="center"
|
|
||||||
justifyContent="space-between"
|
|
||||||
flexDirection="row"
|
|
||||||
gap="5px"
|
|
||||||
>
|
|
||||||
<Typography variant="h6">
|
|
||||||
Proposals
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<PrimaryButton
|
|
||||||
variant="text"
|
|
||||||
href="https://forum.ghostchain.io"
|
|
||||||
>
|
|
||||||
View Forum
|
|
||||||
</PrimaryButton>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ProposalFilterTrigger trigger={proposalsFilter} setTrigger={setProposalFilter} />
|
|
||||||
|
|
||||||
<ProposalTable>
|
|
||||||
{filteredProposals?.map(proposal => (
|
|
||||||
<ProposalRow
|
|
||||||
key={proposal.id}
|
|
||||||
proposal={proposal}
|
|
||||||
blockNumber={blockNumber}
|
|
||||||
chainId={chainId}
|
|
||||||
openProposal={() => navigate(`/governance/${proposal.id}`)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</ProposalTable>
|
|
||||||
|
|
||||||
{proposalsFilter === "active" && <Box mt="24px" textAlign="center" width="70%" mx="auto">
|
|
||||||
<ProposalInfoText />
|
|
||||||
</Box>}
|
|
||||||
</Paper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ProposalTable = ({ children }) => (
|
|
||||||
<TableContainer>
|
|
||||||
<Table aria-label="Available bonds" style={{ tableLayout: "fixed" }}>
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>Proposal ID</TableCell>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>Status</TableCell>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>Vote Ends</TableCell>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>Voting Stats</TableCell>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}></TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
|
|
||||||
<TableBody>{children}</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
);
|
|
||||||
|
|
||||||
const ProposalRow = ({ proposal, blockNumber, openProposal, chainId }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TableRow id={proposal.id + `--proposal`} data-testid={proposal.id + `--proposal`}>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>
|
|
||||||
<Typography>GDP-{proposal.id}</Typography>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>
|
|
||||||
<Chip
|
|
||||||
sx={{ width: "100px" }}
|
|
||||||
label={proposal.status}
|
|
||||||
template={convertStatusToTemplate(proposal.status)}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>
|
|
||||||
<Typography>
|
|
||||||
{convertVoteEnds(
|
|
||||||
proposal.id % 2n === 0n,
|
|
||||||
proposal.voteEnds,
|
|
||||||
blockNumber,
|
|
||||||
chainId
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>
|
|
||||||
<Box marginLeft="15px" marginRight="15px">
|
|
||||||
<LinearProgressBar
|
|
||||||
barColor={theme.colors.feedback.success}
|
|
||||||
barBackground={theme.colors.feedback.error}
|
|
||||||
variant="determinate"
|
|
||||||
value={69}
|
|
||||||
target={Math.floor(Math.random() * 101)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>
|
|
||||||
{(proposal.status === "Active" || proposal.status === "Succeeded") && <PrimaryButton
|
|
||||||
fullWidth
|
|
||||||
onClick={() => openProposal()}
|
|
||||||
sx={{ maxWidth: "130px" }}
|
|
||||||
>
|
|
||||||
{proposal.status === "Succeeded" ? "Execute" : "Vote"}
|
|
||||||
</PrimaryButton>}
|
|
||||||
{(proposal.status !== "Active" && proposal.status !== "Succeeded") && <TertiaryButton
|
|
||||||
fullWidth
|
|
||||||
onClick={() => openProposal()}
|
|
||||||
sx={{ maxWidth: "130px" }}
|
|
||||||
>
|
|
||||||
View
|
|
||||||
</TertiaryButton>}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ProposalCard = ({ proposal, blockNumber, openProposal, chainId }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const isSmallScreen = useMediaQuery('(max-width: 450px)');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box id={proposal.id + `--proposal`} data-testid={proposal.id + `--proposal`}>
|
|
||||||
<Box display="flex" flexDirection={isSmallScreen ? "column" : "row"} justifyContent="space-between">
|
|
||||||
<Box display="flex" flexDirection="column" width="100%">
|
|
||||||
<Box display="flex" flexDirection="row" alignItems="center" width="100%" gap="10px">
|
|
||||||
<Typography variant="h3">GIP-{proposal.id}</Typography>
|
|
||||||
<Chip
|
|
||||||
sx={{ width: "88px" }}
|
|
||||||
label={proposal.status}
|
|
||||||
template={convertStatusToTemplate(proposal.status)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Typography>
|
|
||||||
{convertVoteEnds(
|
|
||||||
proposal.id % 2n === 0n,
|
|
||||||
proposal.voteEnds,
|
|
||||||
blockNumber,
|
|
||||||
chainId
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box marginTop="15px" marginBottom="15px">
|
|
||||||
<LinearProgressBar
|
|
||||||
barColor={theme.colors.feedback.success}
|
|
||||||
barBackground={theme.colors.feedback.error}
|
|
||||||
variant="determinate"
|
|
||||||
value={69}
|
|
||||||
target={Math.floor(Math.random() * 101)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Box marginBottom="20px">
|
|
||||||
{(proposal.status === "Active" || proposal.status === "Succeeded") && <PrimaryButton
|
|
||||||
fullWidth
|
|
||||||
onClick={() => openProposal()}
|
|
||||||
>
|
|
||||||
{proposal.status === "Succeeded" ? "Execute" : "Vote"}
|
|
||||||
</PrimaryButton>}
|
|
||||||
{(proposal.status !== "Active" && proposal.status !== "Succeeded") && <TertiaryButton
|
|
||||||
fullWidth
|
|
||||||
onClick={() => openProposal()}
|
|
||||||
>
|
|
||||||
View
|
|
||||||
</TertiaryButton>}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ProposalFilterTrigger = ({ trigger, setTrigger }) => {
|
|
||||||
return (
|
|
||||||
<Tabs
|
|
||||||
centered
|
|
||||||
textColor="primary"
|
|
||||||
indicatorColor="primary"
|
|
||||||
value={trigger}
|
|
||||||
aria-label="Proposal filter tabs"
|
|
||||||
onChange={(_, view) => setTrigger(view)}
|
|
||||||
TabIndicatorProps={{ style: { display: "none" } }}
|
|
||||||
>
|
|
||||||
<Tab aria-label="proposal-filter-active-button" value="active" label="Active" style={{ fontSize: "1rem" }} />
|
|
||||||
<Tab aria-label="proposal-filter-voted-button" value="voted" label="Voted" style={{ fontSize: "1rem" }} />
|
|
||||||
<Tab aria-label="proposal-filter-created-button" value="created" label="Created" style={{ fontSize: "1rem" }} />
|
|
||||||
</Tabs>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const convertVoteEnds = (tmp, voteEnds, blockNumber, chainId) => {
|
|
||||||
const tmpVoteSeconds = Number(voteEnds * networkAvgBlockSpeed(chainId));
|
|
||||||
const tmpSeconds = (tmp ? tmpVoteSeconds : -tmpVoteSeconds);
|
|
||||||
|
|
||||||
const result = prettifySecondsInDays(tmpSeconds);
|
|
||||||
if (result === "now") {
|
|
||||||
return new Date(Date.now()).toLocaleDateString('en-US', {
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'short',
|
|
||||||
day: 'numeric'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return `in ${result}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ProposalsList;
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
import { useMemo } from "react";
|
|
||||||
import { encodeFunctionData } from 'viem';
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
|
||||||
DAO_TREASURY_ADDRESSES,
|
|
||||||
} from "../../../../constants/addresses";
|
|
||||||
import { abi as TreasuryAbi } from "../../../../abi/GhostTreasury.json";
|
|
||||||
|
|
||||||
import { ParsedCell } from "./index";
|
|
||||||
|
|
||||||
export const prepareAuditReservesCalldata = (chainId) => {
|
|
||||||
const value = 0n;
|
|
||||||
const label = "Audit Reserves";
|
|
||||||
const target = DAO_TREASURY_ADDRESSES[chainId];
|
|
||||||
const calldata = encodeFunctionData({
|
|
||||||
abi: TreasuryAbi,
|
|
||||||
functionName: 'auditReserves',
|
|
||||||
});
|
|
||||||
return { label, target, calldata, value };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const prepareAuditReservesDescription = "Audit Reserves function audits and updates the protocol's total reserve value. It sums the value of all approved reserve and liquidity tokens, then stores and logs the new total.";
|
|
||||||
|
|
||||||
export const AuditReservesSteps = () => {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AuditReservesParsed = (props) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{props.isTable && <AuditReservesParsedCell {...props} />}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuditReservesParsedCell = (props) => {
|
|
||||||
return <ParsedCell {...props} />
|
|
||||||
}
|
|
||||||
@ -1,296 +0,0 @@
|
|||||||
import { useRef, useMemo, useState, useEffect } from "react";
|
|
||||||
import { encodeFunctionData } from 'viem';
|
|
||||||
import { Box, Typography, TableRow, TableCell, useTheme } from "@mui/material";
|
|
||||||
|
|
||||||
import Select from "../../../../components/Select/Select";
|
|
||||||
import { PrimaryButton, TertiaryButton } from "../../../../components/Button";
|
|
||||||
import { shorten } from "../../../../helpers";
|
|
||||||
import { BooleanTrigger, ArgumentInput, ParsedCell } from "./index";
|
|
||||||
|
|
||||||
import {
|
|
||||||
RESERVE_ADDRESSES,
|
|
||||||
FTSO_DAI_LP_ADDRESSES,
|
|
||||||
BOND_DEPOSITORY_ADDRESSES,
|
|
||||||
} from "../../../../constants/addresses";
|
|
||||||
import { abi as DepositoryAbi } from "../../../../abi/GhostBondDepository.json";
|
|
||||||
|
|
||||||
export const prepareCreateBondCalldata = (chainId, markets, terms, quoteToken, intervals, booleans) => {
|
|
||||||
const value = 0n;
|
|
||||||
const label = "Create Bond";
|
|
||||||
const target = BOND_DEPOSITORY_ADDRESSES[chainId];
|
|
||||||
const calldata = encodeFunctionData({
|
|
||||||
abi: DepositoryAbi,
|
|
||||||
functionName: 'create',
|
|
||||||
args: [markets, terms, quoteToken, intervals, booleans]
|
|
||||||
});
|
|
||||||
return { label, target, calldata, value };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const prepareCreateBondDescription = "Create Bond function creates a new bond market by processing pricing, capacity, and term inputs. It initializes and stores the new bond market's complete configuration in the protocol.";
|
|
||||||
|
|
||||||
export const CreateBondParsed = (props) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{props.isTable && <CreateBondParsedCell {...props} />}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const CreateBondParsedCell = (props) => {
|
|
||||||
return <ParsedCell {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CreateBondSteps = ({ nativeCurrency, ftsoSymbol, chainId, toInitialStep, addCalldata }) => {
|
|
||||||
const [step, setStep] = useState(1);
|
|
||||||
const [nextDisabled, setNextDisabled] = useState(false);
|
|
||||||
|
|
||||||
const [capacity, setCapacity] = useState();
|
|
||||||
const [initialPrice, setInitialPrice] = useState();
|
|
||||||
const [debtBuffer, setDebtBuffer] = useState();
|
|
||||||
|
|
||||||
const [depositInterval, setDepositInterval] = useState();
|
|
||||||
const [tuneInterval, setTuneInterval] = useState();
|
|
||||||
|
|
||||||
const [tokenAddress, setTokenAddress] = useState();
|
|
||||||
const [capacityInQuote, setCapacityInQuote] = useState(true);
|
|
||||||
const [fixedTerm, setFixedTerm] = useState(false);
|
|
||||||
|
|
||||||
const [vestingLength, setVestingLength] = useState();
|
|
||||||
const [conclusionTimestamp, setConclusionTimestamp] = useState();
|
|
||||||
|
|
||||||
const handleProceed = () => {
|
|
||||||
const markets = [capacity, initialPrice, debtBuffer];
|
|
||||||
const terms = [vestingLength, conclusionTimestamp];
|
|
||||||
const intervals = [depositInterval, tuneInterval];
|
|
||||||
const booleans = [capacityInQuote, fixedTerm];
|
|
||||||
|
|
||||||
addCalldata(prepareCreateBondCalldata(chainId, markets, terms, tokenAddress, intervals, booleans))
|
|
||||||
}
|
|
||||||
|
|
||||||
const incrementStep = () => {
|
|
||||||
setStep(prev => prev + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const decrementStep = () => {
|
|
||||||
if (step > 1) setStep(prev => prev - 1);
|
|
||||||
else toInitialStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
const isNextDisabled = useMemo(() => {
|
|
||||||
switch (step) {
|
|
||||||
case 1:
|
|
||||||
return tokenAddress === undefined;
|
|
||||||
case 2:
|
|
||||||
return !capacity || !initialPrice || !debtBuffer;
|
|
||||||
case 3:
|
|
||||||
return !depositInterval || !tuneInterval;
|
|
||||||
case 4:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}, [step, tokenAddress, capacity, initialPrice, debtBuffer, depositInterval, tuneInterval]);
|
|
||||||
|
|
||||||
const possibleTokens = [
|
|
||||||
{ value: FTSO_DAI_LP_ADDRESSES[chainId], label: `${ftsoSymbol}-${nativeCurrency} LP: ${shorten(FTSO_DAI_LP_ADDRESSES[chainId])}` },
|
|
||||||
{ value: RESERVE_ADDRESSES[chainId], label: `${ftsoSymbol}: ${shorten(RESERVE_ADDRESSES[chainId])}` },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box height="100%" width="100%" display="flex" flexDirection="column" justifyContent="space-between">
|
|
||||||
{step === 1 && <TokenAndBooleansArguments
|
|
||||||
possibleTokens={possibleTokens}
|
|
||||||
setTokenAddress={setTokenAddress}
|
|
||||||
nativeCurrency={nativeCurrency}
|
|
||||||
ftsoSymbol={ftsoSymbol}
|
|
||||||
capacityInQuote={capacityInQuote}
|
|
||||||
setCapacityInQuote={setCapacityInQuote}
|
|
||||||
fixedTerm={fixedTerm}
|
|
||||||
setFixedTerm={setFixedTerm}
|
|
||||||
/>}
|
|
||||||
{step === 2 && <MarketArguments
|
|
||||||
capacityInQuote={capacityInQuote}
|
|
||||||
nativeCurrency={nativeCurrency}
|
|
||||||
ftsoSymbol={ftsoSymbol}
|
|
||||||
capacity={capacity}
|
|
||||||
setCapacity={setCapacity}
|
|
||||||
initialPrice={initialPrice}
|
|
||||||
setInitialPrice={setInitialPrice}
|
|
||||||
debtBuffer={debtBuffer}
|
|
||||||
setDebtBuffer={setDebtBuffer}
|
|
||||||
/>}
|
|
||||||
{step === 3 && <IntervalsArguments
|
|
||||||
depositInterval={depositInterval}
|
|
||||||
setDepositInterval={setDepositInterval}
|
|
||||||
tuneInterval={tuneInterval}
|
|
||||||
setTuneInterval={setTuneInterval}
|
|
||||||
/>}
|
|
||||||
{step === 4 && <TermsAgruments
|
|
||||||
fixedTerm={fixedTerm}
|
|
||||||
vestingLength={vestingLength}
|
|
||||||
setVestingLength={setVestingLength}
|
|
||||||
conclusionTimestamp={conclusionTimestamp}
|
|
||||||
setConclusionTimestamp={setConclusionTimestamp}
|
|
||||||
/>}
|
|
||||||
<Box width="100%" sx={{ marginTop: "20px" }} display="flex" flexDirection="column" gap="5px">
|
|
||||||
<Box display="flex" gap="10px">
|
|
||||||
<TertiaryButton onClick={() => decrementStep()} fullWidth>Back</TertiaryButton>
|
|
||||||
<TertiaryButton disabled={isNextDisabled} onClick={() => incrementStep()} fullWidth>Next</TertiaryButton>
|
|
||||||
</Box>
|
|
||||||
{step === 4 && <PrimaryButton onClick={() => handleProceed()} fullWidth>Create Function</PrimaryButton>}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const MarketArguments = ({
|
|
||||||
capacityInQuote,
|
|
||||||
nativeCurrency,
|
|
||||||
ftsoSymbol,
|
|
||||||
capacity,
|
|
||||||
setCapacity,
|
|
||||||
initialPrice,
|
|
||||||
setInitialPrice,
|
|
||||||
debtBuffer,
|
|
||||||
setDebtBuffer
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<ArgumentInput
|
|
||||||
endString={capacityInQuote ? nativeCurrency : ftsoSymbol}
|
|
||||||
label="Bond Capacity"
|
|
||||||
value={capacity ?? ""}
|
|
||||||
setValue={setCapacity}
|
|
||||||
tooltip={`Bond market capacity, denominated in ${capacityInQuote ? nativeCurrency : ftsoSymbol}. This determines how the total bond supply is capped`}
|
|
||||||
/>
|
|
||||||
<ArgumentInput
|
|
||||||
endString={nativeCurrency}
|
|
||||||
label="Bond Initial Price"
|
|
||||||
value={initialPrice ?? ""}
|
|
||||||
setValue={setInitialPrice}
|
|
||||||
tooltip={`The initial price used to bootstrap the Bond Control Variable (BCV). This price will dynamically adjust based on market demand once trading begins`}
|
|
||||||
/>
|
|
||||||
<ArgumentInput
|
|
||||||
endString="%"
|
|
||||||
label="Debt buffer"
|
|
||||||
value={debtBuffer ?? ""}
|
|
||||||
setValue={setDebtBuffer}
|
|
||||||
tooltip="Safety threshold (in basis points) to cap rapid bond sales. For example, 30,000 equals a 30% buffer above the target debt level"
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const IntervalsArguments = ({
|
|
||||||
depositInterval,
|
|
||||||
setDepositInterval,
|
|
||||||
tuneInterval,
|
|
||||||
setTuneInterval,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<ArgumentInput
|
|
||||||
endString="seconds"
|
|
||||||
label="Deposit Interval"
|
|
||||||
value={depositInterval ?? ""}
|
|
||||||
setValue={setDepositInterval}
|
|
||||||
tooltip="Target timeframe for selling out the market. It regulates price sensitivity: a shorter interval causes the price to drop faster during periods of inactivity"
|
|
||||||
/>
|
|
||||||
<ArgumentInput
|
|
||||||
endString="seconds"
|
|
||||||
label="Tune interval"
|
|
||||||
value={tuneInterval ?? ""}
|
|
||||||
setValue={setTuneInterval}
|
|
||||||
tooltip="The frequency at which the system ensures the bond's internal price stays aligned with the target market price by auto-tuning at specific intervals"
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const TermsAgruments = ({
|
|
||||||
fixedTerm,
|
|
||||||
vestingLength,
|
|
||||||
setVestingLength,
|
|
||||||
conclusionTimestamp,
|
|
||||||
setConclusionTimestamp,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<ArgumentInput
|
|
||||||
endString="seconds"
|
|
||||||
label={fixedTerm ? "Vesting Duration" : "Vested Timestamp"}
|
|
||||||
value={vestingLength ?? ""}
|
|
||||||
setValue={setVestingLength}
|
|
||||||
tooltip={`Determines the vesting schedule: ${fixedTerm
|
|
||||||
? "a relative time offset from the point of purchase"
|
|
||||||
: "a static maturity timestamp"}`}
|
|
||||||
/>
|
|
||||||
<ArgumentInput
|
|
||||||
endString="seconds"
|
|
||||||
label="Bond Conclusion"
|
|
||||||
value={conclusionTimestamp ?? ""}
|
|
||||||
setValue={setConclusionTimestamp}
|
|
||||||
tooltip="The timestamp that marks the end of the market's lifespan. It defines the point at which the market stops accepting new deposits and the decay mechanism ceases"
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const TokenAndBooleansArguments = ({
|
|
||||||
possibleTokens,
|
|
||||||
nativeCurrency,
|
|
||||||
ftsoSymbol,
|
|
||||||
setTokenAddress,
|
|
||||||
capacityInQuote,
|
|
||||||
setCapacityInQuote,
|
|
||||||
fixedTerm,
|
|
||||||
setFixedTerm,
|
|
||||||
}) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const [selectedOption, setSelectedOption] = useState();
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
|
||||||
setSelectedOption(event.target.value);
|
|
||||||
setTokenAddress(event.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<BooleanTrigger
|
|
||||||
value={capacityInQuote}
|
|
||||||
label="Capacity Type"
|
|
||||||
leftText={nativeCurrency}
|
|
||||||
rightText={ftsoSymbol}
|
|
||||||
setLeftValue={() => setCapacityInQuote(true)}
|
|
||||||
setRightValue={() => setCapacityInQuote(false)}
|
|
||||||
tooltip="Capacity is set in terms of the asset being paid, otherwise it is set in the asset being earned"
|
|
||||||
/>
|
|
||||||
<BooleanTrigger
|
|
||||||
value={fixedTerm}
|
|
||||||
label="Fixed Term"
|
|
||||||
leftText="Yes"
|
|
||||||
rightText="No"
|
|
||||||
setLeftValue={() => setFixedTerm(true)}
|
|
||||||
setRightValue={() => setFixedTerm(false)}
|
|
||||||
tooltip="Determines whether the bond has a fixed expiration date or a fixed duration starting from the time of purchase"
|
|
||||||
/>
|
|
||||||
<Select
|
|
||||||
value={selectedOption ?? ""}
|
|
||||||
onChange={handleChange}
|
|
||||||
options={possibleTokens}
|
|
||||||
inputWidth="100%"
|
|
||||||
renderValue={(selected) => {
|
|
||||||
if (!selected || selected.length === 0) {
|
|
||||||
return (
|
|
||||||
<span style={{ color: theme.colors.gray[500], opacity: 0.7 }}>
|
|
||||||
Select payment token
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return possibleTokens.find(opt => opt.value === selected)?.label || selected;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
import { useState } from "react";
|
|
||||||
import { encodeFunctionData } from 'viem';
|
|
||||||
import { Box, Typography, TableRow, TableCell, useTheme } from "@mui/material";
|
|
||||||
|
|
||||||
import { PrimaryButton, TertiaryButton } from "../../../../components/Button";
|
|
||||||
|
|
||||||
import {
|
|
||||||
DISTRIBUTOR_ADDRESSES,
|
|
||||||
} from "../../../../constants/addresses";
|
|
||||||
import { abi as DistributorAbi } from "../../../../abi/GhostDistributor.json";
|
|
||||||
|
|
||||||
import { BooleanTrigger, ArgumentInput, ParsedCell } from "./index";
|
|
||||||
|
|
||||||
export const prepareSetAdjustmentCalldata = (chainId, rateChange, targetRate, increase) => {
|
|
||||||
const value = 0n;
|
|
||||||
const label = "Set Adjustment";
|
|
||||||
const target = DISTRIBUTOR_ADDRESSES[chainId];
|
|
||||||
const calldata = encodeFunctionData({
|
|
||||||
abi: DistributorAbi,
|
|
||||||
functionName: 'setAdjustment',
|
|
||||||
args: [rateChange, targetRate, increase]
|
|
||||||
});
|
|
||||||
return { label, target, calldata, value };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const prepareSetAdjustmentDescription = "Set Adjustment function schedules a gradual change to the staking APY. It increases or decreases the staking APY by a specified rate per epoch until a target rate reached.";
|
|
||||||
|
|
||||||
export const SetAdjustmentParsed = (props) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{props.isTable && <SetAdjustmentParsedCell {...props} />}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const SetAdjustmentParsedCell = (props) => {
|
|
||||||
return <ParsedCell {...props} />
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SetAdjustmentSteps = ({ chainId, toInitialStep, addCalldata }) => {
|
|
||||||
const [rate, setRate] = useState();
|
|
||||||
const [target, setTarget] = useState();
|
|
||||||
const [increase, setIncrease] = useState(false);
|
|
||||||
|
|
||||||
const handleProceed = () => {
|
|
||||||
addCalldata(prepareSetAdjustmentCalldata(chainId, rate, target, increase));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box height="100%" width="100%" display="flex" flexDirection="column" justifyContent="space-between">
|
|
||||||
<Box>
|
|
||||||
<BooleanTrigger
|
|
||||||
value={increase}
|
|
||||||
leftText="Add"
|
|
||||||
rightText="Sub"
|
|
||||||
setLeftValue={() => setIncrease(true)}
|
|
||||||
setRightValue={() => setIncrease(false)}
|
|
||||||
label="Direction"
|
|
||||||
tooltip="Determines the direction of the adjustment. When Add the parameter value will gradually increase; when Sub, it will decrease toward the target rate"
|
|
||||||
/>
|
|
||||||
<ArgumentInput
|
|
||||||
endString="%"
|
|
||||||
label="Change Rate"
|
|
||||||
value={rate ?? ""}
|
|
||||||
setValue={setRate}
|
|
||||||
tooltip="Each epoch, the current staking reward rate changes by this amount until the target rate is reached"
|
|
||||||
/>
|
|
||||||
<ArgumentInput
|
|
||||||
endString="%"
|
|
||||||
label="Target Rate"
|
|
||||||
value={target ?? ""}
|
|
||||||
setValue={setTarget}
|
|
||||||
tooltip="The final desired value for the reward rate, the adjustment process will continue automatically until this specific level is reached"
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Box width="100%" sx={{ marginTop: "20px" }} display="flex" flexDirection="column" gap="5px">
|
|
||||||
<Box display="flex" gap="10px">
|
|
||||||
<TertiaryButton onClick={toInitialStep} fullWidth>Back</TertiaryButton>
|
|
||||||
<TertiaryButton disabled fullWidth>Next</TertiaryButton>
|
|
||||||
</Box>
|
|
||||||
<PrimaryButton
|
|
||||||
disabled={!target || !rate}
|
|
||||||
onClick={() => handleProceed()}
|
|
||||||
fullWidth
|
|
||||||
>
|
|
||||||
Create Function
|
|
||||||
</PrimaryButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,277 +0,0 @@
|
|||||||
import { useRef, useMemo } from "react";
|
|
||||||
import { Box, Typography, Link, TableCell, TableRow, useTheme } from "@mui/material";
|
|
||||||
import { decodeFunctionData } from 'viem';
|
|
||||||
|
|
||||||
import { StyledInputBase } from "../../../../components/Swap/SwapCard";
|
|
||||||
import { TertiaryButton } from "../../../../components/Button";
|
|
||||||
import InfoTooltip from "../../../../components/Tooltip/InfoTooltip";
|
|
||||||
|
|
||||||
import { abi as TreasuryAbi } from "../../../../abi/GhostTreasury.json";
|
|
||||||
import { abi as DistributorAbi } from "../../../../abi/GhostDistributor.json";
|
|
||||||
import { abi as DepositoryAbi } from "../../../../abi/GhostBondDepository.json";
|
|
||||||
|
|
||||||
import { config } from "../../../../config";
|
|
||||||
import { shorten, formatCurrency } from "../../../../helpers";
|
|
||||||
|
|
||||||
import { prepareAuditReservesDescription, prepareAuditReservesCalldata, AuditReservesSteps, AuditReservesParsed } from "./AuditReserves";
|
|
||||||
import { prepareSetAdjustmentDescription, prepareSetAdjustmentCalldata, SetAdjustmentSteps, SetAdjustmentParsed } from "./SetAdjustment";
|
|
||||||
import { prepareCreateBondDescription, prepareCreateBondCalldata, CreateBondSteps, CreateBondParsed } from "./CreateBond";
|
|
||||||
|
|
||||||
const DEFAULT_DESCRIPTION = "Please select the function to include in your proposal. Multi-functional proposals are allowed, but each included function should be clearly specified."
|
|
||||||
|
|
||||||
export const allPossibleFunctions = [
|
|
||||||
{ value: "auditReserves", label: "Audit Reserves" },
|
|
||||||
{ value: "setAdjustment", label: "Change APY" },
|
|
||||||
{ value: "createBond", label: "Create Bond" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const allAbis = [TreasuryAbi, DistributorAbi, DepositoryAbi];
|
|
||||||
|
|
||||||
const identifyAction = (calldata) => {
|
|
||||||
let decoded = { functionName: "Unknown", args: [] };
|
|
||||||
for (const abi of allAbis) {
|
|
||||||
try {
|
|
||||||
decoded = decodeFunctionData({
|
|
||||||
abi: abi,
|
|
||||||
data: calldata,
|
|
||||||
});
|
|
||||||
return decoded;
|
|
||||||
} catch (err) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return decoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const parseFunctionCalldata = (metadata, index, chainId, nativeCoin, removeCalldata) => {
|
|
||||||
const { label, calldata, target, value } = metadata;
|
|
||||||
const { functionName, args } = identifyAction(calldata);
|
|
||||||
|
|
||||||
const remove = () => removeCalldata(index);
|
|
||||||
|
|
||||||
console.log(`function arguments for ${label}: ${args}`);
|
|
||||||
|
|
||||||
switch (functionName) {
|
|
||||||
case "auditReserves":
|
|
||||||
return <AuditReservesParsed
|
|
||||||
isTable
|
|
||||||
key={index}
|
|
||||||
label={label}
|
|
||||||
chainId={chainId}
|
|
||||||
remove={remove}
|
|
||||||
nativeCoin={nativeCoin}
|
|
||||||
value={value}
|
|
||||||
target={target}
|
|
||||||
id={index}
|
|
||||||
/>;
|
|
||||||
case "setAdjustment":
|
|
||||||
return <SetAdjustmentParsed
|
|
||||||
isTable
|
|
||||||
key={index}
|
|
||||||
label={label}
|
|
||||||
remove={remove}
|
|
||||||
nativeCoin={nativeCoin}
|
|
||||||
value={value}
|
|
||||||
target={target}
|
|
||||||
id={index}
|
|
||||||
/>;
|
|
||||||
case "create":
|
|
||||||
return <CreateBondParsed
|
|
||||||
isTable
|
|
||||||
key={index}
|
|
||||||
label={label}
|
|
||||||
remove={remove}
|
|
||||||
nativeCoin={nativeCoin}
|
|
||||||
value={value}
|
|
||||||
target={target}
|
|
||||||
id={index}
|
|
||||||
/>;
|
|
||||||
default:
|
|
||||||
return <ParsedCell
|
|
||||||
isTable
|
|
||||||
key={index}
|
|
||||||
label={label}
|
|
||||||
remove={remove}
|
|
||||||
nativeCoin={nativeCoin}
|
|
||||||
value={value}
|
|
||||||
target={target}
|
|
||||||
id={index}
|
|
||||||
/>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getFunctionArguments = (functionName) => {
|
|
||||||
switch (functionName) {
|
|
||||||
case "auditReserves":
|
|
||||||
return null;
|
|
||||||
case "setAdjustment":
|
|
||||||
return SetAdjustmentSteps;
|
|
||||||
case "createBond":
|
|
||||||
return CreateBondSteps;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getFunctionCalldata = (functionName, chainId) => {
|
|
||||||
switch (functionName) {
|
|
||||||
case "auditReserves":
|
|
||||||
return prepareAuditReservesCalldata(chainId);
|
|
||||||
case "setAdjustment":
|
|
||||||
return prepareSetAdjustmentCalldata(chainId);
|
|
||||||
case "createBond":
|
|
||||||
return prepareCreateBondCalldata(chainId);
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getFunctionDescription = (functionName) => {
|
|
||||||
switch (functionName) {
|
|
||||||
case "auditReserves":
|
|
||||||
return prepareAuditReservesDescription;
|
|
||||||
case "setAdjustment":
|
|
||||||
return prepareSetAdjustmentDescription;
|
|
||||||
case "createBond":
|
|
||||||
return prepareCreateBondDescription;
|
|
||||||
default:
|
|
||||||
return DEFAULT_DESCRIPTION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const BooleanValue = ({ left, text, isSelected, setSelected }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
onClick={() => setSelected()}
|
|
||||||
display="flex"
|
|
||||||
justifyContent="center"
|
|
||||||
alignItems="center"
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
borderRadius: left ? "12px 0 0 12px" : "0 12px 12px 0",
|
|
||||||
flex: 1,
|
|
||||||
border: "2px solid #fff",
|
|
||||||
borderLeft: left ? "2px solid #fff" : "none",
|
|
||||||
borderRight: left ? "none" : "2px solid #fff",
|
|
||||||
background: `${isSelected ? "#fff" : theme.colors.gray[600] }`
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
color={isSelected ? theme.colors.gray[600] : "#fff"}
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
{text}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ArgumentsWrapper = ({ label, tooltip, children }) => {
|
|
||||||
return (
|
|
||||||
<Box sx={{ marginBottom: "18px" }}>
|
|
||||||
<Box sx={{ marginLeft: "5px", marginBottom: "5px" }} display="flex" flexDirection="row" alignItems="center">
|
|
||||||
<Typography>{label}</Typography>
|
|
||||||
<InfoTooltip message={tooltip} />
|
|
||||||
</Box>
|
|
||||||
{children}
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const BooleanTrigger = ({ value, label, tooltip, leftText, rightText, setLeftValue, setRightValue }) => {
|
|
||||||
return (
|
|
||||||
<ArgumentsWrapper label={label} tooltip={tooltip}>
|
|
||||||
<Box display="flex" width="100%" height="40px">
|
|
||||||
<BooleanValue setSelected={setLeftValue} left isSelected={value} text={leftText} />
|
|
||||||
<BooleanValue setSelected={setRightValue} isSelected={!value} text={rightText} />
|
|
||||||
</Box>
|
|
||||||
</ArgumentsWrapper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ArgumentInput = ({
|
|
||||||
endString,
|
|
||||||
label,
|
|
||||||
tooltip,
|
|
||||||
value,
|
|
||||||
setValue,
|
|
||||||
inputType = "number",
|
|
||||||
placeholder = "0",
|
|
||||||
maxWidth = "100%"
|
|
||||||
}) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const ref = useRef(null);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box sx={{ marginBottom: "15px" }}>
|
|
||||||
<Box sx={{ marginLeft: "5px", marginBottom: "5px" }} display="flex" flexDirection="row" alignItems="center">
|
|
||||||
<Typography>{label}</Typography>
|
|
||||||
<InfoTooltip message={tooltip} />
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
display="flex"
|
|
||||||
flexDirection="column"
|
|
||||||
maxWidth={maxWidth}
|
|
||||||
sx={{ backgroundColor: theme.colors.gray[750] }}
|
|
||||||
borderRadius="12px"
|
|
||||||
padding="6px"
|
|
||||||
onClick={() => {
|
|
||||||
ref.current && ref.current.focus();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box width="100%" display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<StyledInputBase
|
|
||||||
placeholder={placeholder}
|
|
||||||
type={inputType}
|
|
||||||
fontSize="20px"
|
|
||||||
value={value}
|
|
||||||
onChange={(e) => setValue(e.target.value)}
|
|
||||||
sx={{ flex: 1 }}
|
|
||||||
/>
|
|
||||||
{endString && (
|
|
||||||
<Box sx={{ paddingRight: "10px", color: theme.colors.gray[500] }} fontSize="12px" lineHeight="15px">
|
|
||||||
{endString}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ParsedCell = (props) => {
|
|
||||||
const etherscanLink = useMemo(() => {
|
|
||||||
const client = config.getClient();
|
|
||||||
let url = client?.chain?.blockExplorers?.default?.url;
|
|
||||||
if (url) {
|
|
||||||
url = url + `/address/${props.target}`;
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}, [props]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TableRow id={props.id + `--proposalFunction`} data-testid={props.id + `--proposalFunction`}>
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>
|
|
||||||
<Typography>{props.label}</Typography>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>
|
|
||||||
<Link href={etherscanLink} target="_blank" rel="noopener noreferrer">
|
|
||||||
<Typography>{shorten(props.target)}</Typography>
|
|
||||||
</Link>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
<TableCell align="center" style={{ padding: "8px 0" }}>
|
|
||||||
<Typography>{formatCurrency(props.value, 2, props.nativeCoin)}</Typography>
|
|
||||||
</TableCell>
|
|
||||||
|
|
||||||
{props.remove && <TableCell>
|
|
||||||
<div style={{ display: 'flex', gap: '8px' }}>
|
|
||||||
<TertiaryButton fullWidth onClick={() => alert("Do we need it????")}>Edit</TertiaryButton>
|
|
||||||
<TertiaryButton fullWidth onClick={() => props.remove()}>Delete</TertiaryButton>
|
|
||||||
</div>
|
|
||||||
</TableCell>}
|
|
||||||
</TableRow>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
export const convertStatusToTemplate = (status) => {
|
|
||||||
switch (status.toUpperCase()) {
|
|
||||||
case "EXECUTED":
|
|
||||||
return 'darkGray';
|
|
||||||
case "CANCELED":
|
|
||||||
return 'warning';
|
|
||||||
case "SUCCEEDED":
|
|
||||||
return 'success';
|
|
||||||
case "DEFEATED":
|
|
||||||
return 'error';
|
|
||||||
default:
|
|
||||||
return 'darkGray';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { Dispatch, SetStateAction, useState, useEffect } from "react";
|
import { Dispatch, SetStateAction, useState, useEffect } from "react";
|
||||||
import { Box, Container, Grid, Divider, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Container, Grid, Divider, Typography, Link, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import ReactGA from "react-ga4";
|
import ReactGA from "react-ga4";
|
||||||
|
|
||||||
import Paper from "../../components/Paper/Paper";
|
import Paper from "../../components/Paper/Paper";
|
||||||
@ -47,7 +47,7 @@ export const StakeContainer = ({ chainId, address, connect }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box >
|
||||||
<PageTitle name="Protocol Staking" subtitle={`Stake your ${ftsoSymbol} to earn rebase yields`} />
|
<PageTitle name="Protocol Staking" subtitle={`Stake your ${ftsoSymbol} to earn rebase yields`} />
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@ -61,17 +61,7 @@ const FarmPools = ({ chainId }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper headerText="Farm Pools" fullWidth enableBackground>
|
||||||
fullWidth
|
|
||||||
enableBackground
|
|
||||||
headerContent={
|
|
||||||
<Box display="flex" alignItems="center" flexDirection="row" gap="5px">
|
|
||||||
<Typography variant="h6">
|
|
||||||
Farm Pools
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<Table aria-label="Farm pools" style={{ tableLayout: "fixed" }}>
|
<Table aria-label="Farm pools" style={{ tableLayout: "fixed" }}>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
|
|||||||
@ -137,7 +137,7 @@ const WethWrapper = ({ chainId, address, config, connect }) => {
|
|||||||
<meta name="twitter:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
|
<meta name="twitter:image" content="https://ghostchain.io/wp-content/uploads/2025/03/ghostFaucet-Featured_Image.png" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
||||||
<PageTitle name={`${reserveSymbol} Wrapper`} subtitle={`Wrap ${nativeInfo.symbol} into ${reserveSymbol}`} />
|
<PageTitle name={`${reserveSymbol} Wrapper`} subtitle={`Wrap ${nativeInfo.symbol} into ${reserveSymbol}.`} />
|
||||||
<Container
|
<Container
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { createClient } from "@polkadot-api/substrate-client"
|
|||||||
import { getObservableClient } from "@polkadot-api/observable-client"
|
import { getObservableClient } from "@polkadot-api/observable-client"
|
||||||
import useSWR from "swr"
|
import useSWR from "swr"
|
||||||
|
|
||||||
const DEFAULT_CHAIN_ID = "0x475e48fab52f3d0587b6b03101d224560c549e984d1dee197b7d8b55830e7da3"
|
const DEFAULT_CHAIN_ID = "0x5e1190682f1a6409cdfd691c0b23a6db792864d8994e591e9c19a31d8163989f"
|
||||||
const UnstableProvider = createContext(null)
|
const UnstableProvider = createContext(null)
|
||||||
export const useUnstableProvider = () => useContext(UnstableProvider)
|
export const useUnstableProvider = () => useContext(UnstableProvider)
|
||||||
|
|
||||||
|
|||||||
@ -1,147 +0,0 @@
|
|||||||
import { useReadContract, useReadContracts } from "wagmi";
|
|
||||||
import { simulateContract, writeContract, waitForTransactionReceipt } from "@wagmi/core";
|
|
||||||
import toast from "react-hot-toast";
|
|
||||||
|
|
||||||
import { config } from "../../config";
|
|
||||||
|
|
||||||
import {
|
|
||||||
GHOST_GOVERNANCE_ADDRESSES,
|
|
||||||
} from "../../constants/addresses";
|
|
||||||
import { abi as GovernorAbi } from "../../abi/Governor.json";
|
|
||||||
import { abi as GovernorStorageAbi } from "../../abi/GovernorStorage.json";
|
|
||||||
import { abi as GovernorVotesQuorumFractionAbi } from "../../abi/GovernorVotesQuorumFraction.json";
|
|
||||||
|
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
|
||||||
import { getTokenDecimals } from "../helpers";
|
|
||||||
|
|
||||||
export const useMinQuorum = (chainId) => {
|
|
||||||
const { data: quorumNumerator, refetch: quorumNumeratorRefetch } = useReadContract({
|
|
||||||
abi: GovernorVotesQuorumFractionAbi,
|
|
||||||
address: GHOST_GOVERNANCE_ADDRESSES[chainId],
|
|
||||||
functionName: "quorumNumerator",
|
|
||||||
scopeKey: `quorumNumerator-${chainId}`,
|
|
||||||
chainId: chainId,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data: quorumDenominator, refetch: quorumDenominatorRefetch } = useReadContract({
|
|
||||||
abi: GovernorVotesQuorumFractionAbi,
|
|
||||||
address: GHOST_GOVERNANCE_ADDRESSES[chainId],
|
|
||||||
functionName: "quorumDenominator",
|
|
||||||
scopeKey: `quorumDenominator-${chainId}`,
|
|
||||||
chainId: chainId,
|
|
||||||
});
|
|
||||||
|
|
||||||
const numerator = quorumNumerator ?? 0n;
|
|
||||||
const denominator = quorumDenominator ?? 1n;
|
|
||||||
const percentage = Number(100n * numerator / denominator) / 100;
|
|
||||||
|
|
||||||
return { numerator, denominator, percentage }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalThreshold = (chainId, name) => {
|
|
||||||
const decimals = getTokenDecimals(name);
|
|
||||||
const { data, refetch } = useReadContract({
|
|
||||||
abi: GovernorStorageAbi,
|
|
||||||
address: GHOST_GOVERNANCE_ADDRESSES[chainId],
|
|
||||||
functionName: "proposalThreshold",
|
|
||||||
scopeKey: `proposalThreshold-${chainId}`,
|
|
||||||
chainId: chainId,
|
|
||||||
});
|
|
||||||
|
|
||||||
const threshold = new DecimalBigNumber(data ?? 0n, decimals);
|
|
||||||
|
|
||||||
return { threshold };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalCount = (chainId) => {
|
|
||||||
const { data, refetch } = useReadContract({
|
|
||||||
abi: GovernorStorageAbi,
|
|
||||||
address: GHOST_GOVERNANCE_ADDRESSES[chainId],
|
|
||||||
functionName: "proposalCount",
|
|
||||||
scopeKey: `proposalCount-${chainId}`,
|
|
||||||
chainId: chainId,
|
|
||||||
});
|
|
||||||
|
|
||||||
const proposalCount = data ?? 0n;
|
|
||||||
|
|
||||||
return { proposalCount };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalStatus = (chainId, proposalId) => {
|
|
||||||
const status = "Succeeded";
|
|
||||||
return { status };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalProposer = (chainId, proposalId) => {
|
|
||||||
const proposer = "0x71C7656EC7ab88b098defB751B7401B5f6d8976F";
|
|
||||||
return { proposer };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalLocked = (chainId, proposalId) => {
|
|
||||||
const decimals = getTokenDecimals(name);
|
|
||||||
const locked = new DecimalBigNumber(420_000_000_000_000_000_000n, decimals);
|
|
||||||
return { locked }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalQuorum = (chainId, proposalId) => {
|
|
||||||
const decimals = getTokenDecimals(name);
|
|
||||||
const quorum = new DecimalBigNumber(1337_000_000_000_000_000_000n, decimals);
|
|
||||||
return { quorum }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalVotes = (chainId, proposalId) => {
|
|
||||||
const decimals = getTokenDecimals(name);
|
|
||||||
const forVotes = new DecimalBigNumber(420_000_000_000_000_000_000n, decimals);
|
|
||||||
const againstVotes = new DecimalBigNumber(69_000_000_000_000_000_000n, decimals);
|
|
||||||
const totalVotes = new DecimalBigNumber(489_000_000_000_000_000_000n, decimals);
|
|
||||||
return { forVotes, againstVotes, totalVotes }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalSnapshot = (chainId, proposalId) => {
|
|
||||||
const snapshot = Math.floor((Date.now() - (3 * 24 * 60 * 60 * 1000)) / 1000);
|
|
||||||
return { snapshot };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalDeadline = (chainId, proposalId) => {
|
|
||||||
const deadline = Math.floor(Date.now() / 1000);
|
|
||||||
return { deadline };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposalVotingDelay = (chainId, proposalId) => {
|
|
||||||
const delay = 1;
|
|
||||||
return { delay };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useProposals = (chainId, depth) => {
|
|
||||||
const decimals = getTokenDecimals(name);
|
|
||||||
const { proposalCount } = useProposalCount(chainId);
|
|
||||||
|
|
||||||
const statuses = [
|
|
||||||
"Active",
|
|
||||||
"Executed",
|
|
||||||
"Canceled",
|
|
||||||
"Succeeded",
|
|
||||||
"Defeated"
|
|
||||||
];
|
|
||||||
let proposals = [];
|
|
||||||
|
|
||||||
const start = Number(proposalCount);
|
|
||||||
const end = Math.max(0, start - depth);
|
|
||||||
|
|
||||||
for (let i = start - 1; i >= end; --i) {
|
|
||||||
const voteEnds = 50n;
|
|
||||||
const yesVotes = new DecimalBigNumber(1337_000_000_000_000_000_000, decimals);
|
|
||||||
const noVotes = new DecimalBigNumber(420_000_000_000_000_000_000, decimals);
|
|
||||||
|
|
||||||
proposals.push({
|
|
||||||
id: i,
|
|
||||||
discussion: "https://google.com",
|
|
||||||
status: statuses[i % statuses.length],
|
|
||||||
voteEnds,
|
|
||||||
yesVotes,
|
|
||||||
noVotes
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return { proposals };
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user