-
Notifications
You must be signed in to change notification settings - Fork 63
feat(wallet-dashboard): collect vesting ptb #10912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
brancoder
merged 46 commits into
feature/sunset-vesting
from
tooling-wallet/collect-vesting-ptb
Apr 9, 2026
Merged
Changes from 31 commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
2243dff
fix(wallet-dashboard): Allow viewing vesting schedule rewards after l…
msarcev 328503b
update overviewhint to show action
evavirseda f2c6ce7
Update the vesting popup in the wallet
evavirseda 10dc396
fix format
evavirseda 08adbe6
Update dashboard
evavirseda 5795aeb
fix lint
evavirseda cc1c3ed
first steps
evavirseda 4e73ee3
bring back investors ui
evavirseda 7886dab
cleanup
evavirseda 6e57a43
cleanup
evavirseda 5444e50
cleanup
evavirseda 9e42d2b
format
evavirseda 40e5f2d
Merge branch 'tooling-wallet/update-vesting-ui' into tooling-wallet/c…
evavirseda 4b9b7eb
fix layout
evavirseda bac8954
add collect summary
evavirseda 8ee249e
fix
evavirseda 9e42028
remove debris
evavirseda 0665667
cleanup and add stake epoch to join stakes
evavirseda 0d01bb9
update summary
evavirseda 5c05dd3
remove duplicated
evavirseda 538624f
feat(wallet,dashboard): update vesting UI after sunset (#10803)
evavirseda f1c0a12
fix dialog content
evavirseda f82b84a
Merge branch 'feature/sunset-vesting' into tooling-wallet/collect-ves…
evavirseda 9eab1f3
remove useref
evavirseda 70a2cba
cleanup
evavirseda cee3ef8
fix tests
evavirseda b27d4d5
update with constants
evavirseda f11208d
cleanup
evavirseda af77349
move NestedResultType to types
evavirseda 8abeb1a
apply suggestions
evavirseda cd498f4
add suggestion
evavirseda fe0e23d
remove unused hook
evavirseda c8e45b5
feat(wallet,dashboard): update vesting UI after sunset (#10803)
evavirseda ac5e5e7
Merge branch 'feature/sunset-vesting' into tooling-wallet/collect-ves…
evavirseda 7d293d0
Merge branch 'feature/sunset-vesting' into tooling-wallet/collect-ves…
evavirseda 69c0599
feat(wallet-dashboard): handle inactive validator edge case (#10961)
evavirseda 9f01e0c
add inline comments
evavirseda 2f057c3
apply suggestions
evavirseda 9ad4bab
apply suggestion to improve logic
evavirseda f496b97
apply suggestions
evavirseda 44af2c8
show deleted objects in collect summary
evavirseda f99b9ec
use object changes
evavirseda 3de8fa2
improve comments
evavirseda 791c916
use standard transaction dialog instead collect summary dialog
evavirseda 68eceff
revert change
evavirseda 8ed1c60
disable the Collect button while isSendingTransaction
evavirseda File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // Copyright (c) 2026 IOTA Stiftung | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| export type NestedResultType = { | ||
| $kind: 'NestedResult'; | ||
| NestedResult: [number, number]; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
apps/core/src/utils/transaction/createCollectAllTimelocksTransaction.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| // Copyright (c) 2026 IOTA Stiftung | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| import { Transaction } from '@iota/iota-sdk/transactions'; | ||
| import { | ||
| IOTA_TYPE_ARG, | ||
| IOTA_FRAMEWORK_ADDRESS, | ||
| IOTA_CLOCK_OBJECT_ID, | ||
| IOTA_SYSTEM_ADDRESS, | ||
| } from '@iota/iota-sdk/utils'; | ||
| import { NestedResultType } from '../../types'; | ||
|
|
||
| // Timelocked stake: fields.staked_iota.fields.{pool_id, stake_activation_epoch} | ||
| export interface TimelockedStakeObjectInput { | ||
| objectId: string; | ||
| content: { | ||
| dataType: 'moveObject'; | ||
| fields: { | ||
| staked_iota: { | ||
| fields: { | ||
| pool_id: string; | ||
| stake_activation_epoch: string; | ||
| }; | ||
| }; | ||
| }; | ||
| }; | ||
| } | ||
|
|
||
| // Regular stake: fields.{pool_id, stake_activation_epoch} | ||
| export interface RegularStakeObjectInput { | ||
|
evavirseda marked this conversation as resolved.
Outdated
|
||
| objectId: string; | ||
| content: { | ||
| dataType: 'moveObject'; | ||
| fields: { | ||
| pool_id: string; | ||
| stake_activation_epoch: string; | ||
| }; | ||
| }; | ||
| } | ||
|
|
||
| interface CreateCollectAllTimelocksTransactionOptions { | ||
| address: string; | ||
| timelockObjectIds: string[]; | ||
| timelockedStakedObjects?: TimelockedStakeObjectInput[]; | ||
| existingStakedObjects?: RegularStakeObjectInput[]; | ||
| } | ||
|
|
||
| export function createCollectAllTimelocksTransaction({ | ||
| address, | ||
| timelockObjectIds, | ||
| timelockedStakedObjects = [], | ||
| existingStakedObjects = [], | ||
| }: CreateCollectAllTimelocksTransactionOptions) { | ||
| const ptb = new Transaction(); | ||
| const coins: NestedResultType[] = []; | ||
|
|
||
| // Unlock regular timelocks and convert to coins | ||
| for (const objectId of timelockObjectIds) { | ||
| const [unlock] = ptb.moveCall({ | ||
| target: `${IOTA_FRAMEWORK_ADDRESS}::timelock::unlock_with_clock`, | ||
| typeArguments: [`${IOTA_FRAMEWORK_ADDRESS}::balance::Balance<${IOTA_TYPE_ARG}>`], | ||
| arguments: [ptb.object(objectId), ptb.object(IOTA_CLOCK_OBJECT_ID)], | ||
| }); | ||
|
|
||
| const [coin] = ptb.moveCall({ | ||
| target: `${IOTA_FRAMEWORK_ADDRESS}::coin::from_balance`, | ||
| typeArguments: [IOTA_TYPE_ARG], | ||
| arguments: [ptb.object(unlock)], | ||
| }); | ||
|
|
||
| coins.push(coin); | ||
| } | ||
|
evavirseda marked this conversation as resolved.
|
||
|
|
||
| // Unlock timelock stakes and group by (pool_id, stake_activation_epoch) | ||
| const stakedIotaByKey = new Map<string, NestedResultType[]>(); | ||
|
|
||
| for (const stakedObject of timelockedStakedObjects) { | ||
| const [unlockedStakedIota] = ptb.moveCall({ | ||
| target: `${IOTA_SYSTEM_ADDRESS}::timelocked_staking::unlock_with_clock`, | ||
| arguments: [ptb.object(stakedObject.objectId), ptb.object(IOTA_CLOCK_OBJECT_ID)], | ||
| }); | ||
|
|
||
| const poolKey = extractPoolKey(stakedObject); | ||
| if (poolKey) { | ||
| if (!stakedIotaByKey.has(poolKey)) { | ||
| stakedIotaByKey.set(poolKey, []); | ||
| } | ||
| stakedIotaByKey.get(poolKey)!.push(unlockedStakedIota); | ||
| } else { | ||
| ptb.transferObjects([unlockedStakedIota], ptb.pure.address(address)); | ||
| } | ||
| } | ||
|
|
||
| for (const [poolKey, stakedIotaObjects] of stakedIotaByKey.entries()) { | ||
| const existingStake = findExistingStakeForKey(existingStakedObjects, poolKey); | ||
|
|
||
| if (existingStake) { | ||
| // Join all unlocked stakes into the existing regular stake | ||
| for (const stake of stakedIotaObjects) { | ||
| ptb.moveCall({ | ||
| target: `${IOTA_SYSTEM_ADDRESS}::staking_pool::join_staked_iota`, | ||
| arguments: [ptb.object(existingStake.objectId), stake], | ||
| }); | ||
| } | ||
| } else if (stakedIotaObjects.length === 1) { | ||
| ptb.transferObjects([stakedIotaObjects[0]], ptb.pure.address(address)); | ||
| } else { | ||
| // Join all into the first one, then transfer | ||
| const [first, ...rest] = stakedIotaObjects; | ||
| for (const stake of rest) { | ||
| ptb.moveCall({ | ||
| target: `${IOTA_SYSTEM_ADDRESS}::staking_pool::join_staked_iota`, | ||
| arguments: [first, stake], | ||
| }); | ||
| } | ||
| ptb.transferObjects([first], ptb.pure.address(address)); | ||
| } | ||
| } | ||
|
|
||
| // Transfer all collected coins | ||
| if (coins.length > 0) { | ||
| ptb.transferObjects(coins, ptb.pure.address(address)); | ||
| } | ||
|
|
||
| return ptb; | ||
| } | ||
|
|
||
| function extractPoolKey(stakedObject: TimelockedStakeObjectInput): string | null { | ||
| const stakedIotaFields = stakedObject.content.fields.staked_iota?.fields; | ||
| if (stakedIotaFields?.pool_id && stakedIotaFields?.stake_activation_epoch) { | ||
| return `${stakedIotaFields.pool_id}:${stakedIotaFields.stake_activation_epoch}`; | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| function findExistingStakeForKey( | ||
| existingStakes: RegularStakeObjectInput[], | ||
| poolKey: string, | ||
| ): RegularStakeObjectInput | undefined { | ||
| return existingStakes.find( | ||
| (s) => `${s.content.fields.pool_id}:${s.content.fields.stake_activation_epoch}` === poolKey, | ||
| ); | ||
| } | ||
|
evavirseda marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.