Skip to content

fix(stakes): refresh the neuron when a stake retry is a duplicate - #592

Open
yhabib wants to merge 1 commit into
mainfrom
fix/increase-stake-retry
Open

yhabib wants to merge 1 commit into
mainfrom
fix/increase-stake-retry

Conversation

@yhabib

@yhabib yhabib commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

Motivation

On the Internet Identity path, the transfer can land and the refresh can fail. createdAtRef keeps its value, so a retry with the same amount sends the same transaction. The ledger answers TxDuplicate, the hook throws, and the refresh never runs. The ICP stays on the neuron account, the stake does not count it, and each retry shows an error.

Changes

  • Fixed the Internet Identity path of useIncreaseStake: a duplicate now counts as a landed transfer and the refresh runs, same as the device path.
  • Kept every other transfer error as a failure, with no refresh.
  • Added tests for the retry after a failed refresh and for a rejected transfer.
  • Known limit: the Internet Identity path does not persist the key. If the view unmounts, createdAtRef is lost and a new attempt is a second real transfer.

On the Internet Identity path, the transfer can land and the refresh
can fail. The retry sends the same transaction, the ledger answers
TxDuplicate, and the refresh never runs. The ICP stays on the neuron
account and the stake does not count it.

Treat a duplicate as a landed transfer, as the device path does.
@yhabib
yhabib requested a review from a team as a code owner November 7, 2026 07:32
Copilot AI balanced review requested due to automatic review settings November 7, 2026 07:32
@zeropath-ai

zeropath-ai Bot commented Nov 7, 2026

Copy link
Copy Markdown

✅ No security or compliance issues detected. Reviewed everything up to 0a916a6.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► src/governance-app-frontend/src/features/stakes/hooks/useIncreaseStake.tsx
    Update to handle duplicate and error-driven flow during transfer
► src/governance-app-frontend/src/features/stakes/hooks/useIncreaseStake.test.tsx
    Add tests for refresh behavior on duplicate transfer and error handling
    Add test for no refresh on insufficient funds

@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown

📊 Build Bundle Stats

The latest build generated the following assets:

dist/index.html                                           6.12 kB │ gzip:   1.73 kB
dist/assets/index-DHR8rj0Y.css                          150.06 kB │ gzip:  24.02 kB
dist/assets/icpLedger-B3o0G2sn.js                         0.23 kB │ gzip:   0.21 kB
dist/assets/useNowInSeconds-WXg72yi8.js                   0.43 kB │ gzip:   0.31 kB
dist/assets/Skeleton-5ZW29ZEN.js                          0.44 kB │ gzip:   0.32 kB
dist/assets/webhid-D0yio6wG.js                            0.53 kB │ gzip:   0.32 kB
dist/assets/advancedFeatures-Pnj6Ljib.js                  0.53 kB │ gzip:   0.27 kB
dist/assets/useTvlValue-D4QZjKht.js                       0.60 kB │ gzip:   0.41 kB
dist/assets/webVitals-D86iFmW2.js                         0.63 kB │ gzip:   0.45 kB
dist/assets/nnsDapp-CJLhA5zj.js                           0.68 kB │ gzip:   0.25 kB
dist/assets/SkeletonPageHeader-CEDuagB8.js                0.76 kB │ gzip:   0.47 kB
dist/assets/PageHeader-jXzaR6sL.js                        0.77 kB │ gzip:   0.45 kB
dist/assets/CertifiedBadge-DidGkrYK.js                    0.81 kB │ gzip:   0.48 kB
dist/assets/SkeletonStatCard-XlFXqr0E.js                  0.81 kB │ gzip:   0.50 kB
dist/assets/Separator-CSYLVwYv.js                         0.83 kB │ gzip:   0.50 kB
dist/assets/useForecastPeriod-BwwhaDDn.js                 1.00 kB │ gzip:   0.60 kB
dist/assets/utils-CPStM75Z.js                             1.02 kB │ gzip:   0.59 kB
dist/assets/useIcpIndex-BUKKn9wJ.js                       1.09 kB │ gzip:   0.64 kB
dist/assets/useSubaccountsMetadata-D2Qv8ek7.js            1.10 kB │ gzip:   0.62 kB
dist/assets/numbers-CWQdLSd5.js                           1.15 kB │ gzip:   0.57 kB
dist/assets/routeLoaders-Bgr4lksW.js                      1.19 kB │ gzip:   0.55 kB
dist/assets/rolldown-runtime-DAXXjFlN.js                  1.26 kB │ gzip:   0.70 kB
dist/assets/useHardwareWalletsMetadata-C3-1N8X0.js        1.39 kB │ gzip:   0.69 kB
dist/assets/events-BSJoZoff.js                            1.66 kB │ gzip:   0.86 kB
dist/assets/SkeletonListRows-CYEg3dle.js                  1.69 kB │ gzip:   0.53 kB
dist/assets/useLedgerNeuronCall-BMbq3SUk.js               1.90 kB │ gzip:   1.04 kB
dist/assets/errors-C_oENL0S.js                            1.95 kB │ gzip:   0.97 kB
dist/assets/AnimatedNumber-BeA7GlNE.js                    1.98 kB │ gzip:   1.12 kB
dist/assets/useCommandPaletteSettings-66fMAufr.js         2.12 kB │ gzip:   1.06 kB
dist/assets/addressBook-B58Goyd0.js                       2.14 kB │ gzip:   1.19 kB
dist/assets/useIcpIndexTransactionsPolling-5Ie7NbAD.js    2.17 kB │ gzip:   1.16 kB
dist/assets/useGovernanceAppCanister-BlXZvLZJ.js          2.41 kB │ gzip:   1.07 kB
dist/assets/useShortcutSettings-0_Rp2zhV.js               2.41 kB │ gzip:   1.19 kB
dist/assets/useAddHotkey-CKwD9yi5.js                      2.61 kB │ gzip:   1.34 kB
dist/assets/governance-CO1pwZE5.js                        2.99 kB │ gzip:   1.15 kB
dist/assets/ToggleGroup-Ge6aXAim.js                       3.09 kB │ gzip:   1.41 kB
dist/assets/useClaimPendingDeviceStakes-Dd36Slpo.js       3.12 kB │ gzip:   1.42 kB
dist/assets/SkeletonText-CaI6BaxZ.js                      3.71 kB │ gzip:   1.29 kB
dist/assets/useAccounts-BC2RnePm.js                       4.98 kB │ gzip:   2.20 kB
dist/assets/tickers-eNHDYaUL.js                           6.54 kB │ gzip:   2.73 kB
dist/assets/AlertDialog-CbOZ64Jq.js                       7.73 kB │ gzip:   2.72 kB
dist/assets/DeviceActionDetail-D0LJGhVQ.js                8.45 kB │ gzip:   3.03 kB
dist/assets/TopicFollowingAccordion-Bl7ggoyo.js           8.55 kB │ gzip:   3.41 kB
dist/assets/routes-4_X1O-Sl.js                            8.96 kB │ gzip:   3.08 kB
dist/assets/ledgerIdentity-CbGbEww2.js                   10.16 kB │ gzip:   3.70 kB
dist/assets/MutationDialog-kAne-fHS.js                   11.55 kB │ gzip:   4.04 kB
dist/assets/spamFilter-BN-giZ2S.js                       11.77 kB │ gzip:   5.02 kB
dist/assets/ResponsiveDialog-BX-0QFr5.js                 14.56 kB │ gzip:   4.06 kB
dist/assets/_id-DlGqSWBW.js                              16.61 kB │ gzip:   5.32 kB
dist/assets/AmountInput-DkATj0wH.js                      16.96 kB │ gzip:   6.77 kB
dist/assets/_auth-qfDU9oTR.js                            22.49 kB │ gzip:   8.29 kB
dist/assets/HideBalancesToggle-VdM5KiiN.js               22.99 kB │ gzip:   8.58 kB
dist/assets/vendor-buffer-EX-AqChq.js                    26.95 kB │ gzip:   8.18 kB
dist/assets/accounts-BLZjmSll.js                         32.08 kB │ gzip:  10.90 kB
dist/assets/SendICPButton-BW24zs7H.js                    37.11 kB │ gzip:  13.54 kB
dist/assets/settings-D-JQVTCn.js                         54.47 kB │ gzip:  15.55 kB
dist/assets/dashboard-GlyeG6yA.js                        57.76 kB │ gzip:  19.10 kB
dist/assets/voting-DqMfsG6Y.js                           69.29 kB │ gzip:  21.73 kB
dist/assets/index-0dj_-rL3.js                            69.56 kB │ gzip:  20.57 kB
dist/assets/vendor-md-DQa12sMs.js                        73.29 kB │ gzip:  19.98 kB
dist/assets/button-CuReLpZl.js                           86.42 kB │ gzip:  29.04 kB
dist/assets/neurons-DJ-rE7Eg.js                          90.51 kB │ gzip:  27.15 kB
dist/assets/DisburseModal-C964BPVQ.js                   101.52 kB │ gzip:  29.64 kB
dist/assets/vendor-tanstack-D12Yy7ks.js                 120.02 kB │ gzip:  39.22 kB
dist/assets/vendor-jsqr-CjiBYtfG.js                     129.98 kB │ gzip:  47.50 kB
dist/assets/vendor-core-react-bRRjyX41.js               189.81 kB │ gzip:  59.76 kB
dist/assets/vendor-recharts-DQ8kALIQ.js                 280.26 kB │ gzip:  76.83 kB
dist/assets/vendor-ledger-Bz6feAP8.js                   403.26 kB │ gzip:  98.84 kB
dist/assets/vendor-icp-e5O_ocwA.js                      468.31 kB │ gzip: 117.84 kB
dist/assets/vendor-libs-BjQATLf3.js                     587.62 kB │ gzip: 189.56 kB

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

No active review issues remain for the change allowing duplicate Internet Identity transfers to trigger a neuron refresh.

No open issues 🎉

What changed in this PR

Fixes Internet Identity stake-increase retries so a duplicate ledger transfer still triggers a neuron refresh, allowing an already-landed transfer to count toward the stake.

Changes:

  • Treats duplicate transfers as successful in the Internet Identity path, matching device-path behavior.
  • Preserves failure handling for all other transfer errors without refreshing the neuron.
  • Adds tests for duplicate retries, transaction timestamp reuse and reset, and rejected transfers.
File Description
src/​governance-app-frontend/​src/​features/​stakes/​hooks/​useIncreaseStake.tsx Allows neuron refresh after a duplicate Internet Identity transfer.
src/​governance-app-frontend/​src/​features/​stakes/​hooks/​useIncreaseStake.test.tsx Tests retry recovery, timestamp handling, and non-duplicate rejection behavior.

Review effort: Balanced

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants