feat(wallet(-dashboard)): support partial unstake#10064
feat(wallet(-dashboard)): support partial unstake#10064
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
|
Let me know if I should revert the wallet changes to keep the code less complex there |
Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com>
Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com>
…ages Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com>
Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com>
Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com>
Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com>
Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com>
| (!isPartialUnstake && remainingAmount < MIN_STAKING_THRESHOLD); | ||
|
|
||
| // Determine the appropriate error message | ||
| const getErrorMessage = () => { |
There was a problem hiding this comment.
For staking we use yup validation. Better use it instead of manual manage errors.
There was a problem hiding this comment.
When click on "partial unstake" button, user see error. Better to don't trigger validation before user change value. I think it can be fixed by validationSchema.
| currentEpochEndTime > 0 ? currentEpochEndTimeAgo : `Epoch #${epoch}`; | ||
|
|
||
| const maxUnstakeAmount = Number(principalAmount) / Number(NANOS_PER_IOTA); | ||
| const MIN_STAKING_THRESHOLD = 1_000_000_000n; // 1 IOTA in nanos |
There was a problem hiding this comment.
Better to keep this value in the apps/core folder, so we can reuse it.
| const currentEpochEndTimeFormatted = | ||
| currentEpochEndTime > 0 ? currentEpochEndTimeAgo : `Epoch #${epoch}`; | ||
|
|
||
| const maxUnstakeAmount = Number(principalAmount) / Number(NANOS_PER_IOTA); |
There was a problem hiding this comment.
I'd think about moving partial unstake logic to separate hook. If it's possible - reuse it between dashboard & wallet.
There was a problem hiding this comment.
Or at least create utility reusable functions
There was a problem hiding this comment.
For utility function would be good to cover it by unit tests.
panteleymonchuk
left a comment
There was a problem hiding this comment.
Looks good to me and works ⭐️
I'd suggest to improve it a bit to make code more clear.
Thanks for the review, I did some changes in c79c124 |
Description of change
Implements partial unstaking for both normal and timelocked stakes. Users can unstake portions of their principal while receiving proportionally calculated rewards. Enforces Move contract's
MIN_STAKING_THRESHOLD(1 IOTA) for both unstake and remaining amounts.Example: 100 IOTA staked + 10 IOTA rewards → unstake 10 IOTA → receive 11 IOTA (10 principal + 1 proportional reward)
Implementation
Transaction Builders
createPartialUnstakeTransaction: Calls0x3::staking_pool::splitthen0x3::iota_system::request_withdraw_stakecreatePartialTimelockedUnstakeTransaction: Uses0x3::timelocked_staking::splitvariantHooks
useNewPartialUnstakeTransaction: Builds transaction, dry-runs for gas estimationuseNewPartialUnstakeTimelockedTransaction: Timelocked variant with max size handlingUI Components (wallet-dashboard & wallet app)
unstakeAmount ≥ 1 IOTA && (remainingAmount ≥ 1 IOTA || remainingAmount === 0)Proportional Rewards Formula
Validation Examples
How the change has been tested
Validation logic tested with 8 edge cases including MIN_STAKING_THRESHOLD enforcement. CodeQL security scan passed (0 alerts). Proportional rewards calculation verified against reference implementation. Input parsing tested for edge cases (NaN, empty strings, invalid inputs).
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.