From 8b157a78210e16058e033cafc8bcdfbf20288be7 Mon Sep 17 00:00:00 2001 From: Julien Delaigues <0xju@pm.me> Date: Mon, 13 May 2024 12:37:38 +0800 Subject: [PATCH] feat: implement redelegation --- next.config.mjs | 11 +- package-lock.json | 578 ++++++++---------- package.json | 2 +- public/down-arrow.svg | 3 + src/features/core/components/table.tsx | 18 +- .../staking/components/delegation-details.tsx | 137 +++-- .../staking/components/modals/redelegate.tsx | 387 ++++++++++++ .../staking/components/staking-modals.tsx | 3 + src/features/staking/context/actions.ts | 145 +++-- src/features/staking/context/reducer.ts | 52 ++ src/features/staking/context/state.tsx | 17 + src/features/staking/lib/core/base.ts | 6 + src/features/staking/lib/core/tx.ts | 57 +- 13 files changed, 986 insertions(+), 430 deletions(-) create mode 100644 public/down-arrow.svg create mode 100644 src/features/staking/components/modals/redelegate.tsx diff --git a/next.config.mjs b/next.config.mjs index 738ee37..fbd1a9b 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -8,6 +8,16 @@ const nextConfig = { typescript: { ignoreBuildErrors: process.env.QUICK_BUILD === "true", }, + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 's3.amazonaws.com', + port: '', + pathname: '**', + }, + ], + }, ...(useProxy ? { rewrites: async () => [ @@ -22,7 +32,6 @@ const nextConfig = { process.env.NEXT_PUBLIC_IS_DEPLOYMENT === "true" ? "/xion-staking" : undefined, - output: "export", }), }; diff --git a/package-lock.json b/package-lock.json index 69e053d..b4cd069 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "abstraxion-staking-poc", "version": "0.1.0", "dependencies": { - "@burnt-labs/abstraxion": "^1.0.0-alpha.39", + "@burnt-labs/abstraxion": "^1.0.0-alpha.43", "@burnt-labs/constants": "^0.1.0-alpha.6", "@burnt-labs/ui": "^0.1.0-alpha.7", "@cosmjs/cosmwasm-stargate": "^0.32.2", @@ -73,9 +73,9 @@ } }, "node_modules/@apollo/client": { - "version": "3.9.6", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.9.6.tgz", - "integrity": "sha512-+zpddcnZ4G2VZ0xIEnvIHFsLqeopNOnWuE2ZVbRuetLLpj/biLPNN719B/iofdd1/iHRclKfv0XaAmX6PBhYKA==", + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.10.3.tgz", + "integrity": "sha512-4EIgZnFmRO1laWv3NCxlVIxcvimG63djuAXvyXhpQH3wkNMv9SykrasKRN08+z+cn/fVisBOLmkSRdyNyP9f4A==", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@wry/caches": "^1.0.0", @@ -85,7 +85,7 @@ "hoist-non-react-statics": "^3.3.2", "optimism": "^0.18.0", "prop-types": "^15.7.2", - "rehackt": "0.0.6", + "rehackt": "^0.1.0", "response-iterator": "^0.2.6", "symbol-observable": "^4.0.0", "ts-invariant": "^0.10.3", @@ -376,14 +376,14 @@ } }, "node_modules/@burnt-labs/abstraxion": { - "version": "1.0.0-alpha.39", - "resolved": "https://registry.npmjs.org/@burnt-labs/abstraxion/-/abstraxion-1.0.0-alpha.39.tgz", - "integrity": "sha512-3yxzzik1yY/W8HJbsB79kG8gC6UBiXg6wIgduR8yreLVDzsJFXMi3gx7APwVdlUBaOclbA6HaF2Lgw3/AH4g3g==", - "dependencies": { - "@burnt-labs/abstraxion-core": "1.0.0-alpha.36", - "@burnt-labs/constants": "0.1.0-alpha.6", - "@burnt-labs/signers": "0.1.0-alpha.9", - "@burnt-labs/ui": "0.1.0-alpha.7", + "version": "1.0.0-alpha.44", + "resolved": "https://registry.npmjs.org/@burnt-labs/abstraxion/-/abstraxion-1.0.0-alpha.44.tgz", + "integrity": "sha512-rf1ZvRFQ08p8g618CqohjrGVO+ReuLiLyI0SsXmJw2uiGPWVrUYsIaQlHCXJuWX+HuCL4Y/vunniY1VxsgVCnA==", + "dependencies": { + "@burnt-labs/abstraxion-core": "1.0.0-alpha.40", + "@burnt-labs/constants": "0.1.0-alpha.8", + "@burnt-labs/signers": "0.1.0-alpha.10", + "@burnt-labs/ui": "0.1.0-alpha.11", "@cosmjs/amino": "^0.32.2", "@cosmjs/cosmwasm-stargate": "^0.32.2", "@cosmjs/crypto": "^0.32.2", @@ -405,30 +405,36 @@ } }, "node_modules/@burnt-labs/abstraxion-core": { - "version": "1.0.0-alpha.36", - "resolved": "https://registry.npmjs.org/@burnt-labs/abstraxion-core/-/abstraxion-core-1.0.0-alpha.36.tgz", - "integrity": "sha512-wef0+bfrbV2ojioomdZStMazlh/JtkOGOxjaDjqWTOcGCc+15HNjt7ouwvflxcSu+Ss5DWeWDBi16XoLE2yi8Q==", + "version": "1.0.0-alpha.40", + "resolved": "https://registry.npmjs.org/@burnt-labs/abstraxion-core/-/abstraxion-core-1.0.0-alpha.40.tgz", + "integrity": "sha512-GVSlv0XsrOGg0U/ELEuRzOwMnQJQ+yB8XDFjNk3tb5q5X8T82MDjbHZl14spnJVyV6I+xhQX8k/Emo9ii2NK0w==", "dependencies": { - "@burnt-labs/constants": "0.1.0-alpha.6", - "@burnt-labs/signers": "0.1.0-alpha.9", + "@burnt-labs/constants": "0.1.0-alpha.8", + "@burnt-labs/signers": "0.1.0-alpha.10", + "@cosmjs/amino": "^0.32.2", "@cosmjs/cosmwasm-stargate": "^0.32.2", + "@cosmjs/crypto": "^0.32.2", + "@cosmjs/encoding": "^0.32.2", "@cosmjs/proto-signing": "^0.32.2", "@cosmjs/stargate": "^0.32.2", "@cosmjs/tendermint-rpc": "^0.32.2", + "@cosmjs/utils": "^0.32.2", + "@keplr-wallet/cosmos": "^0.12.67", + "@keplr-wallet/crypto": "^0.12.69", "cosmjs-types": "^0.9.0", "graz": "^0.0.51", "jose": "^5.1.3" } }, "node_modules/@burnt-labs/constants": { - "version": "0.1.0-alpha.6", - "resolved": "https://registry.npmjs.org/@burnt-labs/constants/-/constants-0.1.0-alpha.6.tgz", - "integrity": "sha512-k6DfdDFxxY4N72d6NoAPF7CXI4BNRnKvbsz+FdXQ+ws+4CzvrVuGBXhgpa1zs+PllXrouUnq+Dmds7Gz79vJOw==" + "version": "0.1.0-alpha.8", + "resolved": "https://registry.npmjs.org/@burnt-labs/constants/-/constants-0.1.0-alpha.8.tgz", + "integrity": "sha512-1oHGi7JFFuw5He4yOI04KXCQzukZsJFH9AJwnPyrFLZokA1U3ZWSfHD4CCnFGtSsLuPbozdpBGOpWSzZsXt/NQ==" }, "node_modules/@burnt-labs/signers": { - "version": "0.1.0-alpha.9", - "resolved": "https://registry.npmjs.org/@burnt-labs/signers/-/signers-0.1.0-alpha.9.tgz", - "integrity": "sha512-BBT7+OKxx6p+B78BVrF64+q6l6rRizThdUtbQiJFQMjttkkj+e0OvsmlHwFwSWGBZhVVD22sMB2QHNpzikaUFA==", + "version": "0.1.0-alpha.10", + "resolved": "https://registry.npmjs.org/@burnt-labs/signers/-/signers-0.1.0-alpha.10.tgz", + "integrity": "sha512-m9EfSQhPQp3JyqcY8ztsPQMgf/sg8GAyxMxeBNdim6Z5G7onJp500+O0eGoa4FY1sXCVmTFnclS2sJFNRnEvpg==", "dependencies": { "@apollo/client": "^3.8.8", "@cosmjs/amino": "^0.32.2", @@ -450,9 +456,9 @@ } }, "node_modules/@burnt-labs/ui": { - "version": "0.1.0-alpha.7", - "resolved": "https://registry.npmjs.org/@burnt-labs/ui/-/ui-0.1.0-alpha.7.tgz", - "integrity": "sha512-hX5re6/WHyVQNXHyky3GtrzZGQ5NwbrhjUp8AHIJhV9W+rMoDS9dZ/B6FMNLSrf2Q0wHxqC2Pzm2hAUHwdSS2Q==", + "version": "0.1.0-alpha.11", + "resolved": "https://registry.npmjs.org/@burnt-labs/ui/-/ui-0.1.0-alpha.11.tgz", + "integrity": "sha512-g48CvZBGYRHovPfjTBInenI+okShmBWNKqp4N4GbOr7qiFtUxlO9V0iCkxn5YSkJYM7OcAfkuJ8LUqFeFVWjuw==", "dependencies": { "@radix-ui/react-dialog": "^1.0.5", "@types/react-dom": "^18.2.18" @@ -1004,11 +1010,6 @@ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1102,29 +1103,31 @@ } }, "node_modules/@keplr-wallet/common": { - "version": "0.12.72", - "resolved": "https://registry.npmjs.org/@keplr-wallet/common/-/common-0.12.72.tgz", - "integrity": "sha512-raVgr36BaGJHsILAivWzS/OJzc/IUrK3xI7hiGOImqAVxQMMSqBbScCs0wEMqnua1zwRZ6sdbKzl15pCOh9NhQ==", + "version": "0.12.87", + "resolved": "https://registry.npmjs.org/@keplr-wallet/common/-/common-0.12.87.tgz", + "integrity": "sha512-Wq8L8I2SdsTgvsvbmg1+YMFr2aWPDLc90oc8ybSqD8yq8cR1CjMzRx0aXbTWH9MT9klq9yyhk9vyzAzfgGOqmQ==", "dependencies": { - "@keplr-wallet/crypto": "0.12.72", - "@keplr-wallet/types": "0.12.72", + "@keplr-wallet/crypto": "0.12.87", + "@keplr-wallet/types": "0.12.87", "buffer": "^6.0.3", - "delay": "^4.4.0", - "mobx": "^6.1.7" + "delay": "^4.4.0" + }, + "peerDependencies": { + "mobx": "^6" } }, "node_modules/@keplr-wallet/cosmos": { - "version": "0.12.72", - "resolved": "https://registry.npmjs.org/@keplr-wallet/cosmos/-/cosmos-0.12.72.tgz", - "integrity": "sha512-GqQIY408z3ZK2b0qSb9Ft9qU/TvS8k6z5InUeZ2Qk75SefF6ScRmkrquemp4mI+6LKJX6fMVC20uOzKKuOW0Eg==", + "version": "0.12.87", + "resolved": "https://registry.npmjs.org/@keplr-wallet/cosmos/-/cosmos-0.12.87.tgz", + "integrity": "sha512-SB8BOlPyDgu8a7p/53YZ6Jz9bB7CtAKRTOITWoIbtJ8r0DQrYXTlr0Omll0xLOMljiq/XeEcZqaEkJF6gL9Iqg==", "dependencies": { "@ethersproject/address": "^5.6.0", - "@keplr-wallet/common": "0.12.72", - "@keplr-wallet/crypto": "0.12.72", - "@keplr-wallet/proto-types": "0.12.72", - "@keplr-wallet/simple-fetch": "0.12.72", - "@keplr-wallet/types": "0.12.72", - "@keplr-wallet/unit": "0.12.72", + "@keplr-wallet/common": "0.12.87", + "@keplr-wallet/crypto": "0.12.87", + "@keplr-wallet/proto-types": "0.12.87", + "@keplr-wallet/simple-fetch": "0.12.87", + "@keplr-wallet/types": "0.12.87", + "@keplr-wallet/unit": "0.12.87", "bech32": "^1.1.4", "buffer": "^6.0.3", "long": "^4.0.0", @@ -1137,9 +1140,9 @@ "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" }, "node_modules/@keplr-wallet/crypto": { - "version": "0.12.72", - "resolved": "https://registry.npmjs.org/@keplr-wallet/crypto/-/crypto-0.12.72.tgz", - "integrity": "sha512-lo7vPNDYGMWIxEEtbOoNdaIwE7qT4gkHzEekrf3QZI8inwadPkp8lDm8oAiWIMCNSAF/6qN+SyaImVdrJyETvQ==", + "version": "0.12.87", + "resolved": "https://registry.npmjs.org/@keplr-wallet/crypto/-/crypto-0.12.87.tgz", + "integrity": "sha512-g0hH6mB/gau4mTUQSQ8a+lhiL7GVypFeNM0CKhpYE87t5UG3edtv0m/m4Bs7ueifx20HJDdKmzvgB8urJbvqGw==", "dependencies": { "@ethersproject/keccak256": "^5.5.0", "bip32": "^2.0.6", @@ -1152,33 +1155,33 @@ } }, "node_modules/@keplr-wallet/proto-types": { - "version": "0.12.72", - "resolved": "https://registry.npmjs.org/@keplr-wallet/proto-types/-/proto-types-0.12.72.tgz", - "integrity": "sha512-GVTq9Id9i3hQKUAs2cbP1+k2XpUP+Mih0LTV/1BN2//IHa3BSBsGP8DELlG75Yyz9zGseBgvj36PSv4/wKhnhA==", + "version": "0.12.87", + "resolved": "https://registry.npmjs.org/@keplr-wallet/proto-types/-/proto-types-0.12.87.tgz", + "integrity": "sha512-omkxYa6UbVLcOa2W3WlnXHmnvMzOICx59LxSBpfzf7IU3nVJbhl24kAQX8eChYs5NlU1kF1k5HCIUfpY0IqAMA==", "dependencies": { "long": "^4.0.0", "protobufjs": "^6.11.2" } }, "node_modules/@keplr-wallet/simple-fetch": { - "version": "0.12.72", - "resolved": "https://registry.npmjs.org/@keplr-wallet/simple-fetch/-/simple-fetch-0.12.72.tgz", - "integrity": "sha512-PyiZy4Ykh1y30HaYhyeoctPBwLCgcF0QKebdmRKp9uSRyZri5mOu6DckJa8QCXji4pBZkLitGXjwwnSj2eoheg==" + "version": "0.12.87", + "resolved": "https://registry.npmjs.org/@keplr-wallet/simple-fetch/-/simple-fetch-0.12.87.tgz", + "integrity": "sha512-M6tiKYDRDzqNwpwq6pFAUReBeDPQvfqkM2YkIjfrXXYLZ22KYvpsGoOXawWhsmvo3mNqy4j3v+C0A/soYyS1Gg==" }, "node_modules/@keplr-wallet/types": { - "version": "0.12.72", - "resolved": "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.12.72.tgz", - "integrity": "sha512-gDP+NCPa4seTT1xU9bkIKbMw7N/LPla9/4/amDLIGyFb6OEjfnFkRuReI/cZe/8aEvlkYAKnfB0UMipHobsn5g==", + "version": "0.12.87", + "resolved": "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.12.87.tgz", + "integrity": "sha512-E13u8Z/sRjwZLEAPBcq91MNnFfs5YJcTLQgUv4ojpvncfGBiSfq8Z3hMWVXDk9VZhXodYoEsii+R1Hv6RSzbHg==", "dependencies": { "long": "^4.0.0" } }, "node_modules/@keplr-wallet/unit": { - "version": "0.12.72", - "resolved": "https://registry.npmjs.org/@keplr-wallet/unit/-/unit-0.12.72.tgz", - "integrity": "sha512-egrh0L/uo6MQrAfVi1V8GQB1eml1ZbfWDiv5gpU6AkeAte4Q1DIe8qkYqeJOJ+KW1TurnxDw9L+9/T/i4Lu8Jg==", + "version": "0.12.87", + "resolved": "https://registry.npmjs.org/@keplr-wallet/unit/-/unit-0.12.87.tgz", + "integrity": "sha512-aCoKhua9G575Ua1VA1dnoi0ECIXoh/clYMf/3M9U2rjX0vG+rWiUtNU6foYs2SZ54HCJ7a8gL2BOdleSKOmSvg==", "dependencies": { - "@keplr-wallet/types": "0.12.72", + "@keplr-wallet/types": "0.12.87", "big-integer": "^1.6.48", "utility-types": "^3.10.0" } @@ -1231,9 +1234,9 @@ } }, "node_modules/@metamask/safe-event-emitter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.0.0.tgz", - "integrity": "sha512-j6Z47VOmVyGMlnKXZmL0fyvWfEYtKWCA9yGZkU3FCsGZUT5lHGmvaV9JA5F2Y+010y7+ROtR3WMXIkvl/nVzqQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.1.tgz", + "integrity": "sha512-ihb3B0T/wJm1eUuArYP4lCTSEoZsClHhuWyfo/kMX3m/odpqNcPfsz5O2A3NT7dXCAgWPGDQGPqygCpgeniKMw==", "engines": { "node": ">=12.0.0" } @@ -1891,9 +1894,9 @@ } }, "node_modules/@protobuf-ts/runtime": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.9.3.tgz", - "integrity": "sha512-nivzCpg/qYD0RX2OmHOahJALb8ndjGmUhNBcTJ0BbXoqKwCSM6vYA+vegzS3rhuaPgbyC7Ec8idlnizzUfIRuw==" + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.9.4.tgz", + "integrity": "sha512-vHRFWtJJB/SiogWDF0ypoKfRIZ41Kq+G9cEFj6Qm1eQaAhJ1LDFvgZ7Ja4tb3iLOQhz0PaoPnnOijF1qmEqTxg==" }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", @@ -2519,11 +2522,11 @@ } }, "node_modules/@tanstack/match-sorter-utils": { - "version": "8.11.8", - "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.11.8.tgz", - "integrity": "sha512-3VPh0SYMGCa5dWQEqNab87UpCMk+ANWHDP4ALs5PeEW9EpfTAbrezzaOk/OiM52IESViefkoAOYuxdoa04p6aA==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.15.1.tgz", + "integrity": "sha512-PnVV3d2poenUM31ZbZi/yXkBu3J7kd5k2u51CGwwNojag451AjTH9N6n41yjXz2fpLeewleyLBmNS6+HcGDlXw==", "dependencies": { - "remove-accents": "0.4.2" + "remove-accents": "0.5.0" }, "engines": { "node": ">=12" @@ -2921,27 +2924,27 @@ } }, "node_modules/@walletconnect/core": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.11.2.tgz", - "integrity": "sha512-bB4SiXX8hX3/hyBfVPC5gwZCXCl+OPj+/EDVM71iAO3TDsh78KPbrVAbDnnsbHzZVHlsMohtXX3j5XVsheN3+g==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.13.0.tgz", + "integrity": "sha512-blDuZxQenjeXcVJvHxPznTNl6c/2DO4VNrFnus+qHmO6OtT5lZRowdMtlCaCNb1q0OxzgrmBDcTOCbFcCpio/g==", "dependencies": { - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-provider": "1.0.13", - "@walletconnect/jsonrpc-types": "1.0.3", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", "@walletconnect/jsonrpc-utils": "1.0.8", "@walletconnect/jsonrpc-ws-connection": "1.0.14", - "@walletconnect/keyvaluestorage": "^1.1.1", - "@walletconnect/logger": "^2.0.1", - "@walletconnect/relay-api": "^1.0.9", - "@walletconnect/relay-auth": "^1.0.4", - "@walletconnect/safe-json": "^1.0.2", - "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.11.2", - "@walletconnect/utils": "2.11.2", - "events": "^3.3.0", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.10", + "@walletconnect/relay-auth": "1.0.4", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.13.0", + "@walletconnect/utils": "2.13.0", + "events": "3.3.0", "isomorphic-unfetch": "3.1.0", "lodash.isequal": "4.5.0", - "uint8arrays": "^3.1.0" + "uint8arrays": "3.1.0" } }, "node_modules/@walletconnect/environment": { @@ -2972,49 +2975,34 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@walletconnect/heartbeat": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.1.tgz", - "integrity": "sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", + "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", "dependencies": { "@walletconnect/events": "^1.0.1", "@walletconnect/time": "^1.0.2", - "tslib": "1.14.1" + "events": "^3.3.0" } }, - "node_modules/@walletconnect/heartbeat/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@walletconnect/jsonrpc-provider": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz", - "integrity": "sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", + "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", "dependencies": { "@walletconnect/jsonrpc-utils": "^1.0.8", "@walletconnect/safe-json": "^1.0.2", - "tslib": "1.14.1" + "events": "^3.3.0" } }, - "node_modules/@walletconnect/jsonrpc-provider/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@walletconnect/jsonrpc-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz", - "integrity": "sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", + "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", "dependencies": { - "keyvaluestorage-interface": "^1.0.0", - "tslib": "1.14.1" + "events": "^3.3.0", + "keyvaluestorage-interface": "^1.0.0" } }, - "node_modules/@walletconnect/jsonrpc-types/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@walletconnect/jsonrpc-utils": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", @@ -3060,33 +3048,22 @@ } }, "node_modules/@walletconnect/logger": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.0.1.tgz", - "integrity": "sha512-SsTKdsgWm+oDTBeNE/zHxxr5eJfZmE9/5yp/Ku+zJtcTAjELb3DXueWkDXmE9h8uHIbJzIb5wj5lPdzyrjT6hQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.1.2.tgz", + "integrity": "sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==", "dependencies": { - "pino": "7.11.0", - "tslib": "1.14.1" + "@walletconnect/safe-json": "^1.0.2", + "pino": "7.11.0" } }, - "node_modules/@walletconnect/logger/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@walletconnect/relay-api": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.9.tgz", - "integrity": "sha512-Q3+rylJOqRkO1D9Su0DPE3mmznbAalYapJ9qmzDgK28mYF9alcP3UwG/og5V7l7CFOqzCLi7B8BvcBUrpDj0Rg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.10.tgz", + "integrity": "sha512-tqrdd4zU9VBNqUaXXQASaexklv6A54yEyQQEXYOCr+Jz8Ket0dmPBDyg19LVSNUN2cipAghQc45/KVmfFJ0cYw==", "dependencies": { - "@walletconnect/jsonrpc-types": "^1.0.2", - "tslib": "1.14.1" + "@walletconnect/jsonrpc-types": "^1.0.2" } }, - "node_modules/@walletconnect/relay-api/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@walletconnect/relay-auth": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz", @@ -3119,19 +3096,19 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@walletconnect/sign-client": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.11.2.tgz", - "integrity": "sha512-MfBcuSz2GmMH+P7MrCP46mVE5qhP0ZyWA0FyIH6/WuxQ6G+MgKsGfaITqakpRPsykWOJq8tXMs3XvUPDU413OQ==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.13.0.tgz", + "integrity": "sha512-En7KSvNUlQFx20IsYGsFgkNJ2lpvDvRsSFOT5PTdGskwCkUfOpB33SQJ6nCrN19gyoKPNvWg80Cy6MJI0TjNYA==", "dependencies": { - "@walletconnect/core": "2.11.2", - "@walletconnect/events": "^1.0.1", - "@walletconnect/heartbeat": "1.2.1", + "@walletconnect/core": "2.13.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/logger": "^2.0.1", - "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.11.2", - "@walletconnect/utils": "2.11.2", - "events": "^3.3.0" + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.13.0", + "@walletconnect/utils": "2.13.0", + "events": "3.3.0" } }, "node_modules/@walletconnect/time": { @@ -3148,37 +3125,37 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@walletconnect/types": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.11.2.tgz", - "integrity": "sha512-p632MFB+lJbip2cvtXPBQslpUdiw1sDtQ5y855bOlAGquay+6fZ4h1DcDePeKQDQM3P77ax2a9aNPZxV6y/h1Q==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.13.0.tgz", + "integrity": "sha512-MWaVT0FkZwzYbD3tvk8F+2qpPlz1LUSWHuqbINUtMXnSzJtXN49Y99fR7FuBhNFtDalfuWsEK17GrNA+KnAsPQ==", "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-types": "1.0.3", - "@walletconnect/keyvaluestorage": "^1.1.1", - "@walletconnect/logger": "^2.0.1", - "events": "^3.3.0" + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" } }, "node_modules/@walletconnect/utils": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.11.2.tgz", - "integrity": "sha512-LyfdmrnZY6dWqlF4eDrx5jpUwsB2bEPjoqR5Z6rXPiHJKUOdJt7az+mNOn5KTSOlRpd1DmozrBrWr+G9fFLYVw==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.13.0.tgz", + "integrity": "sha512-q1eDCsRHj5iLe7fF8RroGoPZpdo2CYMZzQSrw1iqL+2+GOeqapxxuJ1vaJkmDUkwgklfB22ufqG6KQnz78sD4w==", "dependencies": { "@stablelib/chacha20poly1305": "1.0.1", "@stablelib/hkdf": "1.0.1", - "@stablelib/random": "^1.0.2", + "@stablelib/random": "1.0.2", "@stablelib/sha256": "1.0.1", - "@stablelib/x25519": "^1.0.3", - "@walletconnect/relay-api": "^1.0.9", - "@walletconnect/safe-json": "^1.0.2", - "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.11.2", - "@walletconnect/window-getters": "^1.0.1", - "@walletconnect/window-metadata": "^1.0.1", + "@stablelib/x25519": "1.0.3", + "@walletconnect/relay-api": "1.0.10", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.13.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", "detect-browser": "5.3.0", "query-string": "7.1.3", - "uint8arrays": "^3.1.0" + "uint8arrays": "3.1.0" } }, "node_modules/@walletconnect/window-getters": { @@ -4143,14 +4120,6 @@ "node": ">=6" } }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -4192,6 +4161,11 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==" + }, "node_modules/consola": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", @@ -4201,9 +4175,9 @@ } }, "node_modules/cookie-es": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.0.0.tgz", - "integrity": "sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.1.0.tgz", + "integrity": "sha512-L2rLOcK0wzWSfSDA33YR+PUHDG10a8px7rUHKWbGLP4YfbsMed2KFUw5fczvDPbT98DDe3LEzviswl810apTEw==" }, "node_modules/copy-anything": { "version": "3.0.5", @@ -4335,6 +4309,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -4425,14 +4400,6 @@ "node": ">=0.4.0" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -5544,9 +5511,9 @@ "dev": true }, "node_modules/fast-redact": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.4.0.tgz", - "integrity": "sha512-2gwPvyna0zwBdxKnng1suu/dTL5s8XEy2ZqH8mwDUwJdDkV8w5kp+JV26mupdK68HmPMbm6yjW9m7/Ys/BHEHg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", "engines": { "node": ">=6" } @@ -6576,33 +6543,10 @@ "loose-envify": "^1.0.0" } }, - "node_modules/ioredis": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", - "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", - "dependencies": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" - } - }, "node_modules/iron-webcrypto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.0.0.tgz", - "integrity": "sha512-anOK1Mktt8U1Xi7fCM3RELTuYbnFikQY5VtrDj7kPgpejV7d43tWKhzgioO0zpkazLEL/j/iayRqnJhrGfqUsg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", "funding": { "url": "https://github.com/sponsors/brc-dd" } @@ -7096,9 +7040,9 @@ } }, "node_modules/jose": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.2.3.tgz", - "integrity": "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.2.4.tgz", + "integrity": "sha512-6ScbIk2WWCeXkmzF6bRPmEuaqy1m8SbsRFMa/FLrSCkGIhj8OLVG/IH+XHVmNMx/KUo8cVWEE6oKR4dJ+S0Rkg==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -7197,11 +7141,6 @@ "json5": "lib/cli.js" } }, - "node_modules/jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==" - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -7381,16 +7320,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" - }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", @@ -7570,20 +7499,21 @@ } }, "node_modules/mlly": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", - "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.0.tgz", + "integrity": "sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==", "dependencies": { "acorn": "^8.11.3", "pathe": "^1.1.2", - "pkg-types": "^1.0.3", - "ufo": "^1.3.2" + "pkg-types": "^1.1.0", + "ufo": "^1.5.3" } }, "node_modules/mobx": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.12.0.tgz", - "integrity": "sha512-Mn6CN6meXEnMa0a5u6a5+RKrqRedHBhZGd15AWLk9O6uFY4KYHzImdt8JI8WODo1bjTSRnwXhJox+FCUZhCKCQ==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.12.3.tgz", + "integrity": "sha512-c8NKkO4R2lShkSXZ2Ongj1ycjugjzFFo/UswHBnS62y07DMcTc9Rvo03/3nRyszIvwPNljlkd4S828zIBv/piw==", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/mobx" @@ -7613,7 +7543,8 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/multiformats": { "version": "9.9.0", @@ -7765,9 +7696,9 @@ } }, "node_modules/node-fetch-native": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.2.tgz", - "integrity": "sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==" + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==" }, "node_modules/node-forge": { "version": "1.3.1", @@ -7952,13 +7883,13 @@ } }, "node_modules/ofetch": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.3.3.tgz", - "integrity": "sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.3.4.tgz", + "integrity": "sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==", "dependencies": { - "destr": "^2.0.1", - "node-fetch-native": "^1.4.0", - "ufo": "^1.3.0" + "destr": "^2.0.3", + "node-fetch-native": "^1.6.3", + "ufo": "^1.5.3" } }, "node_modules/ohash": { @@ -8228,13 +8159,13 @@ } }, "node_modules/pkg-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", - "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.1.tgz", + "integrity": "sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==", "dependencies": { - "jsonc-parser": "^3.2.0", - "mlly": "^1.2.0", - "pathe": "^1.1.0" + "confbox": "^0.1.7", + "mlly": "^1.7.0", + "pathe": "^1.1.2" } }, "node_modules/pngjs": { @@ -8667,9 +8598,9 @@ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" }, "node_modules/radix3": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.0.tgz", - "integrity": "sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==" }, "node_modules/react": { "version": "18.2.0", @@ -8877,25 +8808,6 @@ "node": ">= 12.13.0" } }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/reflect.getprototypeof": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz", @@ -8941,9 +8853,9 @@ } }, "node_modules/rehackt": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.0.6.tgz", - "integrity": "sha512-l3WEzkt4ntlEc/IB3/mF6SRgNHA6zfQR7BlGOgBTOmx7IJJXojDASav+NsgXHFjHn+6RmwqsGPFgZpabWpeOdw==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.1.0.tgz", + "integrity": "sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==", "peerDependencies": { "@types/react": "*", "react": "*" @@ -8958,9 +8870,9 @@ } }, "node_modules/remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" }, "node_modules/require-directory": { "version": "2.1.1", @@ -9390,11 +9302,6 @@ "node": ">= 10.x" } }, - "node_modules/standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" - }, "node_modules/std-env": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", @@ -10121,14 +10028,14 @@ } }, "node_modules/ufo": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", - "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==" + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==" }, "node_modules/uint8arrays": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", - "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.0.tgz", + "integrity": "sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==", "dependencies": { "multiformats": "^9.4.2" } @@ -10154,9 +10061,9 @@ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==" }, "node_modules/undici": { - "version": "5.28.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", - "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -10199,35 +10106,35 @@ } }, "node_modules/unstorage": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.10.1.tgz", - "integrity": "sha512-rWQvLRfZNBpF+x8D3/gda5nUCQL2PgXy2jNG4U7/Rc9BGEv9+CAJd0YyGCROUBKs9v49Hg8huw3aih5Bf5TAVw==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.10.2.tgz", + "integrity": "sha512-cULBcwDqrS8UhlIysUJs2Dk0Mmt8h7B0E6mtR+relW9nZvsf/u4SkAYyNliPiPW7XtFNb5u3IUMkxGxFTTRTgQ==", "dependencies": { "anymatch": "^3.1.3", - "chokidar": "^3.5.3", - "destr": "^2.0.2", - "h3": "^1.8.2", - "ioredis": "^5.3.2", - "listhen": "^1.5.5", - "lru-cache": "^10.0.2", + "chokidar": "^3.6.0", + "destr": "^2.0.3", + "h3": "^1.11.1", + "listhen": "^1.7.2", + "lru-cache": "^10.2.0", "mri": "^1.2.0", - "node-fetch-native": "^1.4.1", + "node-fetch-native": "^1.6.2", "ofetch": "^1.3.3", - "ufo": "^1.3.1" + "ufo": "^1.4.0" }, "peerDependencies": { - "@azure/app-configuration": "^1.4.1", + "@azure/app-configuration": "^1.5.0", "@azure/cosmos": "^4.0.0", "@azure/data-tables": "^13.2.2", - "@azure/identity": "^3.3.2", - "@azure/keyvault-secrets": "^4.7.0", - "@azure/storage-blob": "^12.16.0", - "@capacitor/preferences": "^5.0.6", - "@netlify/blobs": "^6.2.0", - "@planetscale/database": "^1.11.0", - "@upstash/redis": "^1.23.4", - "@vercel/kv": "^0.2.3", - "idb-keyval": "^6.2.1" + "@azure/identity": "^4.0.1", + "@azure/keyvault-secrets": "^4.8.0", + "@azure/storage-blob": "^12.17.0", + "@capacitor/preferences": "^5.0.7", + "@netlify/blobs": "^6.5.0 || ^7.0.0", + "@planetscale/database": "^1.16.0", + "@upstash/redis": "^1.28.4", + "@vercel/kv": "^1.0.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.3.2" }, "peerDependenciesMeta": { "@azure/app-configuration": { @@ -10265,6 +10172,9 @@ }, "idb-keyval": { "optional": true + }, + "ioredis": { + "optional": true } } }, @@ -10373,9 +10283,9 @@ } }, "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -10413,6 +10323,14 @@ } } }, + "node_modules/valtio/node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/warning": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", @@ -10903,6 +10821,14 @@ "optional": true } } + }, + "node_modules/zustand/node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } } } } diff --git a/package.json b/package.json index fa47b3a..2daaf84 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { - "@burnt-labs/abstraxion": "^1.0.0-alpha.39", + "@burnt-labs/abstraxion": "^1.0.0-alpha.43", "@burnt-labs/constants": "^0.1.0-alpha.6", "@burnt-labs/ui": "^0.1.0-alpha.7", "@cosmjs/cosmwasm-stargate": "^0.32.2", diff --git a/public/down-arrow.svg b/public/down-arrow.svg new file mode 100644 index 0000000..baacdc5 --- /dev/null +++ b/public/down-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/features/core/components/table.tsx b/src/features/core/components/table.tsx index 814f4eb..d1b4331 100644 --- a/src/features/core/components/table.tsx +++ b/src/features/core/components/table.tsx @@ -1,3 +1,4 @@ +import Image from "next/image"; import type { PropsWithChildren } from "react"; import { chevron } from "../lib/icons"; @@ -65,14 +66,23 @@ export const HeaderTitleBase = ({ ); }; -export const ValidatorLogo = ({ logo }: { logo: null | string }) => ( +export const ValidatorLogo = ({ + height = 50, + logo, + width = 50, +}: { + height?: number; + logo: null | string; + width?: number; +}) => (
{logo ? ( - Validator logo ) : ( diff --git a/src/features/staking/components/delegation-details.tsx b/src/features/staking/components/delegation-details.tsx index f18ad11..5769e29 100644 --- a/src/features/staking/components/delegation-details.tsx +++ b/src/features/staking/components/delegation-details.tsx @@ -1,3 +1,4 @@ +import type { Coin } from "@cosmjs/stargate"; import BigNumber from "bignumber.js"; import { BondStatus, @@ -130,6 +131,20 @@ const DelegationRowBase = ({ isMobile ? "flex md:hidden" : "hidden md:flex", ].join(" ")} > + { + if (!validator) return; + + staking.dispatch( + setModalOpened({ + content: { validator }, + type: "redelegate", + }), + ); + }} + > + Redelegate + { @@ -254,19 +269,25 @@ const DelegationRowBase = ({ const DelegationRow = memo(DelegationRowBase); -type UnbondingRowProps = { - disabled?: boolean; +type UnbondingRedelegationRowProps = { + balance: Coin; + completionTime: number; + onCancel?: () => void; stakingRef: ReturnType; - unbonding: NonNullable["items"][number]; + status: string; validator?: Validator; + validatorAddress: string; }; -const UnbondingRow = ({ - disabled, +const UnbondingRedelegationRow = ({ + balance, + completionTime, + onCancel, stakingRef, - unbonding, + status, validator, -}: UnbondingRowProps) => { + validatorAddress, +}: UnbondingRedelegationRowProps) => { const { staking } = stakingRef; const logo = useValidatorLogo( @@ -274,8 +295,6 @@ const UnbondingRow = ({ validator?.operatorAddress, ); - const validatorAddress = unbonding.validator; - useEffect(() => { if (validatorAddress) { getAndSetValidatorAction(validatorAddress, staking); @@ -283,15 +302,8 @@ const UnbondingRow = ({ }, [validatorAddress, staking]); const cancelProps = { - disabled, - onClick: () => { - staking.dispatch( - setModalOpened({ - content: { unbondings: [unbonding] }, - type: "cancel-unstaking", - }), - ); - }, + disabled: !onCancel, + onClick: onCancel, }; return ( @@ -310,16 +322,18 @@ const UnbondingRow = ({
- +
Unbonding
- {formatUnbondingCompletionTime(unbonding.completionTime)} + {formatUnbondingCompletionTime(completionTime)}
- - Cancel Unstake - + {!!onCancel && ( + + Cancel Unstake + + )}
Amount - +
Status - Unbonding + {status}
Completion - {formatUnbondingCompletionTime(unbonding.completionTime)} -
-
- - Cancel Unstake - + {formatUnbondingCompletionTime(completionTime)}
+ {!!onCancel && ( +
+ + Cancel Unstake + +
+ )}
); @@ -393,12 +409,13 @@ const DelegationDetails = () => { const validatorsMap = getAllValidators(staking.state); - const { delegations, unbondings } = staking.state; + const { delegations, redelegations, unbondings } = staking.state; const hasDelegations = !!delegations?.items.length; const hasUnbondings = !!unbondings?.items.length; + const hasRedelegations = !!redelegations?.items.length; - if (!hasDelegations && !hasUnbondings) { + if (!hasDelegations && !hasUnbondings && !hasRedelegations) { return null; } @@ -487,9 +504,12 @@ const DelegationDetails = () => { ); })()} - {hasUnbondings && + {(hasUnbondings || hasRedelegations) && (() => { - const sortedUnbondings = unbondings.items.slice().sort((a, b) => { + const sortedUnbondings = [ + ...(unbondings?.items ?? []), + ...(redelegations?.items ?? []), + ].sort((a, b) => { switch (unbondingsSortMethod) { case "amount-asc": case "amount-desc": @@ -517,12 +537,14 @@ const DelegationDetails = () => { return (
- Unstakings + + Unstakings/Redelegations +
Staked Amount
@@ -533,19 +555,42 @@ const DelegationDetails = () => { onSort={setUnbondingsSortMethod} rigthAlign sort={unbondingsSortMethod} - sorting={["date-asc", "date-desc"]} + sorting={["completion-asc", "completion-desc"]} >
Completion Time
- {sortedUnbondings.map((unbonding, index) => ( - - ))} + {sortedUnbondings.map((unbondingRedelegation, index) => { + const isUnbonding = "validator" in unbondingRedelegation; + + const validatorAddress = isUnbonding + ? unbondingRedelegation.validator + : unbondingRedelegation.dstValidator; + + const onCancel = isUnbonding + ? () => { + staking.dispatch( + setModalOpened({ + content: { unbondings: [unbondingRedelegation] }, + type: "cancel-unstaking", + }), + ); + } + : undefined; + + return ( + + ); + })}
); })()} diff --git a/src/features/staking/components/modals/redelegate.tsx b/src/features/staking/components/modals/redelegate.tsx new file mode 100644 index 0000000..a01fb51 --- /dev/null +++ b/src/features/staking/components/modals/redelegate.tsx @@ -0,0 +1,387 @@ +import type { SelectOption } from "@mui/base"; +import { Option, Select } from "@mui/base"; +import BigNumber from "bignumber.js"; +import type { Validator } from "cosmjs-types/cosmos/staking/v1beta1/staking"; +import Image from "next/image"; +import type { FormEventHandler } from "react"; +import { useEffect, useState } from "react"; +import { toast } from "react-toastify"; + +import { unbondingDays, xionToUSD } from "@/constants"; +import { + Button, + FormError, + Heading2, + Heading8, + HeroText, + InputBox, + OpenInput, +} from "@/features/core/components/base"; +import CommonModal, { + ModalDescription, +} from "@/features/core/components/common-modal"; +import { ValidatorLogo } from "@/features/core/components/table"; +import AddressShort from "@/features/staking/components/address-short"; +import { useValidatorLogo } from "@/features/staking/hooks"; + +import { redelegateAction } from "../../context/actions"; +import { useStaking } from "../../context/hooks"; +import { setModalOpened } from "../../context/reducer"; +import { getTotalDelegation } from "../../context/selectors"; +import { getXionCoin } from "../../lib/core/coins"; +import { + formatCoin, + formatToSmallDisplay, + formatXionToUSD, +} from "../../lib/formatters"; + +type Step = "completed" | "input" | "review"; + +const initialStep: Step = "input"; + +const ValidatorOption = ({ + validator: { + description: { identity, moniker }, + operatorAddress, + }, +}: { + validator: Validator; +}) => { + const logo = useValidatorLogo(identity, operatorAddress); + + return ( + + ); +}; + +const SelectArrow = ({ open = false }: { open?: boolean }) => ( + down-arrow +); + +const NoValidatorSelected = () => ( +
+ +
+ Select Validator + XION Address +
+ +
+); + +const ValidatorSelected = ({ validator }: { validator: Validator }) => { + const logo = useValidatorLogo( + validator.description.identity, + validator.operatorAddress, + ); + + return ( +
+ +
+ {validator.description.moniker} + +
+ +
+ ); +}; + +const RedelegateModal = () => { + const stakingRef = useStaking(); + const { client } = stakingRef; + const [step, setStep] = useState(initialStep); + const [isLoading, setIsLoading] = useState(false); + + const [formError, setFormError] = useState< + Record + >({ amount: undefined, memo: undefined }); + + const [dstValidator, setDstValidator] = useState(); + const [amountXION, setAmount] = useState(""); + const [memo, setMemo] = useState(""); + + const { account, staking } = stakingRef; + const { modal } = staking.state; + const isOpen = modal?.type === "redelegate"; + + useEffect( + () => () => { + setStep(initialStep); + setAmount(""); + setFormError({}); + setMemo(""); + }, + [isOpen], + ); + + const { validators: validatorsObj } = staking.state; + + const validators = [ + validatorsObj.bonded?.items, + validatorsObj.unbonded?.items, + ] + .flat(1) + .filter((v): v is Validator => !!v); + + const validatorsPerAddress = validators.reduce>( + (acc, v) => ({ + ...acc, + [v.operatorAddress]: v, + }), + {}, + ); + + if (!isOpen) return null; + + const { validator } = modal?.content; + + if (!validator) return null; + + const amountXIONParsed = new BigNumber(amountXION); + + const amountUSD = (() => { + if (amountXIONParsed.isNaN()) return ""; + + return amountXIONParsed.times(xionToUSD); + })(); + + const delegatedTokens = getTotalDelegation( + staking.state, + validator.operatorAddress, + ); + + const validateAmount = () => { + if ( + !amountUSD || + !delegatedTokens || + amountXIONParsed.lte(0) || + amountXIONParsed.gt(new BigNumber(delegatedTokens.amount)) + ) { + setFormError({ + ...formError, + amount: "Invalid amount", + }); + + return true; + } + }; + + const onSubmit: FormEventHandler = (e) => { + e?.stopPropagation(); + e?.preventDefault(); + + if (validateAmount()) return; + + if (!client || !amountXIONParsed.gt(0)) return; + + setStep("review"); + }; + + return ( + { + if (isLoading) return; + + stakingRef.staking.dispatch(setModalOpened(null)); + }} + > +
+ {(() => { + const getUnstakingSummary = () => ( + <> +
+ Redelegation Amount (XION) + {formatToSmallDisplay(amountXIONParsed)} + + {formatXionToUSD(getXionCoin(amountXIONParsed))} + +
+ {!!memo && ( +
+
{memo}
+
+ )} + + ); + + if (step === "completed") { + return ( + <> +
+
+ SUCCESS! +
+ + You have successfully redelegate from{" "} + {validator.description.moniker} + to {dstValidator?.description.moniker} + +
+ {getUnstakingSummary()} + + + ); + } + + if (step === "review") { + return ( + <> +
+
+ REVIEW +
+ + You are about to redelegate your token from{" "} + {validator.description.moniker} to + {dstValidator?.description.moniker}. Remember, you will not + able to redelegate these token within {unbondingDays} days. + +
+ {getUnstakingSummary()} + + + ); + } + + return ( + <> +
+ + Redelegate From {validator.description.moniker} + +
+
+ To +
+ Available:{" "} + {!!delegatedTokens && + formatCoin(delegatedTokens, undefined, true)}{" "} + XION +
+
+ +
+
Amount
+ {!!amountUSD && ( + =${formatToSmallDisplay(amountUSD)} + )} +
+
+
+ { + validateAmount(); + }} + onChange={(e) => { + if (formError.amount) { + setFormError({ ...formError, amount: undefined }); + } + + setAmount(e.target.value); + }} + value={amountXION} + /> + {formError.amount && ( + {formError.amount} + )} +
+
+ { + setMemo(e.target.value); + }} + placeholder="Memo (Optional)" + value={memo} + /> +
+
+ +
+
+ + ); + })()} +
+
+ ); +}; + +export default RedelegateModal; diff --git a/src/features/staking/components/staking-modals.tsx b/src/features/staking/components/staking-modals.tsx index 1e47ced..064c885 100644 --- a/src/features/staking/components/staking-modals.tsx +++ b/src/features/staking/components/staking-modals.tsx @@ -1,3 +1,5 @@ +import RedelegateModal from "@/features/staking/components/modals/redelegate"; + import CancelUnstakingModal from "./modals/cancel-unstaking"; import RewardsModal from "./modals/rewards"; import StakingModal from "./modals/staking"; @@ -9,6 +11,7 @@ const StakingModals = () => ( + ); diff --git a/src/features/staking/context/actions.ts b/src/features/staking/context/actions.ts index 1457664..9772c17 100644 --- a/src/features/staking/context/actions.ts +++ b/src/features/staking/context/actions.ts @@ -5,6 +5,7 @@ import { getDelegations, getInflation, getPool, + getRedelegation, getRewards, getUnbondingDelegations, getValidatorDetails, @@ -12,10 +13,11 @@ import { } from "../lib/core/base"; import type { AbstraxionSigningClient } from "../lib/core/client"; import { sumAllCoins } from "../lib/core/coins"; -import type { StakeAddresses } from "../lib/core/tx"; -import { stakeAmount, unstakeAmount } from "../lib/core/tx"; +import type { RedelegateParams, StakeAddresses } from "../lib/core/tx"; +import { redelegate, stakeAmount, unstakeAmount } from "../lib/core/tx"; import { addDelegations, + addRedelegations, addUnbondings, setExtraValidators, setInflation, @@ -26,7 +28,7 @@ import { setValidators, } from "./reducer"; import { getAllValidators } from "./selectors"; -import type { StakingContextType, Unbonding } from "./state"; +import type { Redelegation, StakingContextType, Unbonding } from "./state"; export const fetchStakingDataAction = async (staking: StakingContextType) => { try { @@ -82,51 +84,80 @@ export const fetchUserDataAction = async ( try { staking.dispatch(setIsInfoLoading(true)); - const [balance, delegations, unbondings] = await Promise.all([ - getBalance(address), - getDelegations(address).then(async (newDelegations) => ({ - items: await Promise.all( - newDelegations.delegationResponses.map(async (del) => ({ - balance: del.balance, - rewards: await getRewards( - address, - del.delegation.validatorAddress, - ).then((rewards) => sumAllCoins(rewards)), - validatorAddress: del.delegation.validatorAddress, + const [balance, delegations, unbondings, redelegations] = await Promise.all( + [ + getBalance(address), + getDelegations(address).then(async (newDelegations) => ({ + items: await Promise.all( + newDelegations.delegationResponses.map(async (del) => ({ + balance: del.balance, + rewards: await getRewards( + address, + del.delegation.validatorAddress, + ).then((rewards) => sumAllCoins(rewards)), + validatorAddress: del.delegation.validatorAddress, + })), + ), + pagination: newDelegations.pagination, + })), + getUnbondingDelegations(address) + .then((unbondingResponse) => ({ + items: unbondingResponse.unbondingResponses.reduce((acc, res) => { + acc.push( + ...res.entries.map( + (entry) => + ({ + balance: { amount: entry.balance, denom: "uxion" }, + completionTime: Number(entry.completionTime.seconds), + completionTimeNanos: entry.completionTime.nanos, + creationHeight: entry.creationHeight, + id: entry.unbondingId.toString(), + validator: res.validatorAddress, + }) satisfies Unbonding, + ), + ); + + return acc; + }, [] as Unbonding[]), + pagination: unbondingResponse.pagination, + })) + .catch(() => + // It is expected that this will throw when there are no unbondings + ({ items: [], pagination: null }), + ) + .then((result) => ({ + items: result.items, + pagination: result.pagination, })), - ), - pagination: newDelegations.pagination, - })), - getUnbondingDelegations(address) - .then((unbondingResponse) => ({ - items: unbondingResponse.unbondingResponses.reduce((acc, res) => { - acc.push( - ...res.entries.map( - (entry) => - ({ + getRedelegation(address) + .then((redelegationsResponses) => ({ + items: redelegationsResponses.redelegationResponses + .map((res) => + res.entries.map( + (entry): Redelegation => ({ balance: { amount: entry.balance, denom: "uxion" }, - completionTime: Number(entry.completionTime.seconds), - completionTimeNanos: entry.completionTime.nanos, - creationHeight: entry.creationHeight, - id: entry.unbondingId.toString(), - validator: res.validatorAddress, - }) satisfies Unbonding, - ), - ); - - return acc; - }, [] as Unbonding[]), - pagination: unbondingResponse.pagination, - })) - .catch(() => - // It is expected that this will throw when there are no unbondings - ({ items: [], pagination: null }), - ) - .then((result) => ({ - items: result.items, - pagination: result.pagination, - })), - ]); + completionTime: Number( + entry.redelegationEntry.completionTime.seconds, + ), + completionTimeNanos: + entry.redelegationEntry.completionTime.nanos, + creationHeight: entry.redelegationEntry.creationHeight, + delegatorAddress: res.redelegation.delegatorAddress, + dstValidator: res.redelegation.validatorDstAddress, + id: entry.redelegationEntry.unbondingId.toString(), + srcValidator: res.redelegation.validatorSrcAddress, + }), + ), + ) + .flat(1), + pagination: redelegationsResponses.pagination, + })) + .catch(() => + // It is expected that this will throw when there are no redeledations + ({ items: [], pagination: null }), + ), + ], + ); staking.dispatch(setTokens(balance)); @@ -152,6 +183,17 @@ export const fetchUserDataAction = async ( ), ); + staking.dispatch( + addRedelegations( + { + items: redelegations.items, + nextKey: redelegations.pagination?.nextKey || null, + total: redelegations.pagination?.total || null, + }, + true, + ), + ); + staking.dispatch(setIsInfoLoading(false)); } catch (error) { console.error("error fetching staking data:", error); @@ -186,6 +228,17 @@ export const unstakeValidatorAction = async ( }; }; +export const redelegateAction = async ( + redelegateParams: RedelegateParams, + staking: StakingContextType, +) => { + await redelegate(redelegateParams); + + return async () => { + await fetchUserDataAction(redelegateParams.delegatorAddress, staking); + }; +}; + export const getValidatorDetailsAction = async ( validatorAddress: string, staking: StakingContextType, diff --git a/src/features/staking/context/reducer.ts b/src/features/staking/context/reducer.ts index 06990f6..af01273 100644 --- a/src/features/staking/context/reducer.ts +++ b/src/features/staking/context/reducer.ts @@ -6,6 +6,11 @@ export type StakingAction = reset: boolean; type: "ADD_DELEGATIONS"; } + | { + content: NonNullable; + reset: boolean; + type: "ADD_REDELEGATIONS"; + } | { content: NonNullable; reset: boolean; @@ -96,6 +101,15 @@ export const addUnbondings = ( type: "ADD_UNBONDINGS", }); +export const addRedelegations = ( + redelegation: Content<"ADD_REDELEGATIONS">, + reset: boolean, +): StakingAction => ({ + content: redelegation, + reset, + type: "ADD_REDELEGATIONS", +}); + export const setValidatorDetails = ( content: Content<"SET_VALIDATOR_DETAILS">, ): StakingAction => ({ @@ -185,6 +199,24 @@ const getUniqueUnbondings = ( }); }; +const getUniqueRedelegations = ( + redelegations: NonNullable["items"], +) => { + const validatorIds = new Set(); + + return redelegations.filter((redelegation) => { + const key = redelegation.id; + + if (validatorIds.has(key)) { + return false; + } + + validatorIds.add(key); + + return true; + }); +}; + export const reducer = ( state: StakingState, action: StakingAction, @@ -257,6 +289,26 @@ export const reducer = ( }; } + case "ADD_REDELEGATIONS": { + const currentRedelegations = (!action.reset && state.redelegations) || { + items: [], + nextKey: null, + total: null, + }; + + currentRedelegations.total = action.content.total; + currentRedelegations.nextKey = action.content.nextKey; + + currentRedelegations.items = getUniqueRedelegations( + action.content.items.concat(currentRedelegations.items), + ); + + return { + ...state, + redelegations: currentRedelegations, + }; + } + case "SET_IS_INFO_LOADING": { return { ...state, diff --git a/src/features/staking/context/state.tsx b/src/features/staking/context/state.tsx index 30de6b9..26194b8 100644 --- a/src/features/staking/context/state.tsx +++ b/src/features/staking/context/state.tsx @@ -23,6 +23,17 @@ export type Unbonding = { validator: string; }; +export type Redelegation = { + balance: Coin; + completionTime: number; + completionTimeNanos: number; + creationHeight: bigint; + delegatorAddress: string; + dstValidator: string; + id: string; + srcValidator: string; +}; + type Delegation = { balance: Coin; rewards: Coin; @@ -42,6 +53,10 @@ type ModalContent = content: { validator: Validator }; type: "delegate"; } + | { + content: { validator: Validator }; + type: "redelegate"; + } | { content: { validator: Validator }; type: "undelegate"; @@ -57,6 +72,7 @@ export type StakingState = { isInfoLoading: boolean; modal: ModalContent | null; pool: null | Pool; + redelegations: Paginated; tokens: Coin | null; unbondings: Paginated; validatorDetails: null | Validator; @@ -75,6 +91,7 @@ export const defaultState: StakingState = { isInfoLoading: false, modal: null, pool: null, + redelegations: null, tokens: null, unbondings: null, validatorDetails: null, diff --git a/src/features/staking/lib/core/base.ts b/src/features/staking/lib/core/base.ts index a147711..e1608fa 100644 --- a/src/features/staking/lib/core/base.ts +++ b/src/features/staking/lib/core/base.ts @@ -81,6 +81,12 @@ export const getUnbondingDelegations = async (address: string) => { return await queryClient.staking.delegatorUnbondingDelegations(address); }; +export const getRedelegation = async (delegatorAddress: string) => { + const queryClient = await getStakingQueryClient(); + + return await queryClient.staking.redelegations(delegatorAddress, "", ""); +}; + export const getRewards = async (address: string, validatorAddress: string) => { const queryClient = await getStakingQueryClient(); diff --git a/src/features/staking/lib/core/tx.ts b/src/features/staking/lib/core/tx.ts index b9668a2..99dffd0 100644 --- a/src/features/staking/lib/core/tx.ts +++ b/src/features/staking/lib/core/tx.ts @@ -1,13 +1,15 @@ -import { - type Coin, - type DeliverTxResponse, - type MsgDelegateEncodeObject, - type MsgUndelegateEncodeObject, - type MsgWithdrawDelegatorRewardEncodeObject, +import type { + Coin, + DeliverTxResponse, + MsgBeginRedelegateEncodeObject, + MsgDelegateEncodeObject, + MsgUndelegateEncodeObject, + MsgWithdrawDelegatorRewardEncodeObject, } from "@cosmjs/stargate"; import BigNumber from "bignumber.js"; import { MsgWithdrawDelegatorReward } from "cosmjs-types/cosmos/distribution/v1beta1/tx"; import { + MsgBeginRedelegate, MsgCancelUnbondingDelegation, MsgDelegate, MsgUndelegate, @@ -125,6 +127,49 @@ export const unstakeAmount = async ( .catch(handleTxError); }; +export type RedelegateParams = { + amount: Coin; + client: NonNullable; + delegatorAddress: string; + memo: string; + validatorDstAddress: string; + validatorSrcAddress: string; +}; + +export const redelegate = async ({ + amount: initialAmount, + client, + delegatorAddress, + memo, + validatorDstAddress, + validatorSrcAddress, +}: RedelegateParams) => { + const amount = getUxionAmount(initialAmount); + + const msg = MsgBeginRedelegate.fromPartial({ + amount, + delegatorAddress, + validatorDstAddress, + validatorSrcAddress, + }); + + const messageWrapper: MsgBeginRedelegateEncodeObject = { + typeUrl: "/cosmos.staking.v1beta1.MsgBeginRedelegate", + value: msg, + }; + + const fee = await getCosmosFee({ + address: delegatorAddress, + memo, + msgs: [messageWrapper], + }); + + return await client + .signAndBroadcast(delegatorAddress, [messageWrapper], fee, memo) + .then(getTxVerifier("redelegate")) + .catch(handleTxError); +}; + export const claimRewards = async ( addresses: StakeAddresses, client: NonNullable,