diff options
| author | Adam Soltys <[email protected]> | 2026-09-27 23:17:12 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-27 23:17:12 -0700 |
| commit | a9a5d1fdce7a342394c2facb2344adbc7aa69aea (patch) | |
| tree | 76bc49039c6a11442ab4112373e6fc94a4b5269d /src | |
| parent | 44bc9d0596f1d195367799797aca5e76e4924fe9 (diff) | |
| download | coinosv3-a9a5d1fdce7a342394c2facb2344adbc7aa69aea.tar.gz coinosv3-a9a5d1fdce7a342394c2facb2344adbc7aa69aea.zip | |
A renewal the round would refuse is retired, not resubmitted every sync; /feed opened before the wallet no longer doubles Popular.
A refresh at the created step with an input past its expiry (only the
server's backstop can renew it now), or whose fee leaves less than the
330-sat floor (a 21-sat coin with a 150-sat fee sat "in progress" for
days), is failed quietly and its inputs go back to spendable.
/feed read before the wallet restored made a visitor's session copy of
Popular beside the built-in one; the wallet's arrival now folds it away.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
Diffstat (limited to 'src')
| -rw-r--r-- | src/ark/manager.js | 17 | ||||
| -rw-r--r-- | src/features/messages.js | 7 |
2 files changed, 24 insertions, 0 deletions
diff --git a/src/ark/manager.js b/src/ark/manager.js index bfb4a4e..b828d7e 100644 --- a/src/ark/manager.js +++ b/src/ark/manager.js @@ -1989,6 +1989,23 @@ export class ArkManager { const inputRecs = action.inputIds.map((id) => this._vtxo(id)); if (action.step === 'created') { + // A set the round would refuse anyway is retired here, not resubmitted + // every sync: an input past its expiry (only the server's backstop can + // renew it now), or an output the fee leaves under the 330-sat dust + // floor (a 21-sat coin with a 150-sat fee sat "in progress" for days). + // Nothing was spent, so the inputs go back to spendable. + const tip = this._tipH || (await this.chain.tipHeight().catch(() => 0)); + const inSat = inputRecs.reduce((n, v) => n + (v ? v.amountSat : 0), 0); + const expired = inputRecs.some((v) => v && v.expiryHeight && tip && v.expiryHeight <= tip); + if (expired || inSat - (action.feeSat || 0) < 330 || inputRecs.some((v) => !v)) { + for (const v of inputRecs) if (v && v.state === 'pending') v.state = 'spendable'; + action.step = 'failed'; + action.superseded = true; // no row: the renewal never began + action.lastError = expired ? 'an input has expired: only the server can renew it now' + : inputRecs.some((v) => !v) ? 'an input is no longer held' : 'the fee leaves less than the 330-sat minimum'; + this._save(); + return; + } const inputBytes = inputRecs.map((v) => vtxoBytesFromStr(v.bytes)); await registerVtxoTransactions(this.arkUrl, inputBytes); let unlockHash; diff --git a/src/features/messages.js b/src/features/messages.js index 756e9e1..fdd5643 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -9088,6 +9088,13 @@ export function messagesFeature(ctx) { init() { const session = ++feedWarmSession; returnAfterSignin(); // a visitor who signed in from a feed or profile lands back on it + // /feed opened before the wallet restored made a visitor's session copy + // of Popular; with the wallet here, the built-in one takes over (two + // Popular chips otherwise) + if (adhocFeeds.has('all:visitor')) { + adhocFeeds.delete('all:visitor'); dropFeedState('all:visitor'); + if (curFeedId === 'all:visitor') { ui.feedId = EVERYTHING; curFeedId = EVERYTHING; } + } // this wallet's cached faces, from its own namespace — the keys are // in place now, whatever the header asked for before profilesWarmed = false; |
