Repository navigation
feat(cli): add escrow redeem and report the release phase #312
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
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
6a2e658
feat(cli): add escrow redeem and report the release phase
charlesHetterich 4f94fbc
refactor(cli): keep preflight to asserts and pass the clock in
charlesHetterich 413582c
refactor(cli): derive EscrowPositionView from ReleasePosition
charlesHetterich 89b02ce
test(cli): reuse ReleasePosition and nowSeconds in the redeem tests
charlesHetterich a16cc16
Merge origin/main into feat/escrow-redeem-command
charlesHetterich 76bc3d4
feat(cli): show the release phase in the escrow positions table
charlesHetterich eada442
refactor(cli): gather the pure escrow rules in escrowStatus
charlesHetterich 006ea18
fix(cli): say a withdrawn deposit ends redemption in release and regi…
charlesHetterich aeb951c
Merge origin/main into feat/escrow-redeem-command
charlesHetterich 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
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
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,69 @@ | ||
| import type { ReleasePosition } from "./inspectName"; | ||
| import { formatUnixSeconds } from "../utils/formatting"; | ||
|
|
||
| /// Time-gated escrow rules kept pure, with no chain access, so the commands, the display | ||
| /// layer and the preflight asserts all read one definition of each state. | ||
|
|
||
| /// A position is the user's escrow deposit only while it holds a refundable amount. Zero-amount | ||
| /// entries are PopFull/PopLite lifecycle markers or already-withdrawn slots, not staked deposits. | ||
| export function isRefundableDeposit(position: Pick<ReleasePosition, "amount">): boolean { | ||
| return position.amount > 0n; | ||
| } | ||
|
|
||
| /// Total still locked across positions. Withdrawn positions carry amount 0 (the contract | ||
| /// zeroes it on withdraw), so they fall out of the sum naturally. | ||
| export function totalEscrowAmount(positions: readonly Pick<ReleasePosition, "amount">[]): bigint { | ||
| return positions.reduce((sum, position) => sum + position.amount, 0n); | ||
| } | ||
|
|
||
| /// Seconds left on a released position's cooldown before it becomes withdrawable. | ||
| export function cooldownRemainingSeconds( | ||
| position: Pick<ReleasePosition, "withdrawAvailableAt">, | ||
| nowSeconds: bigint, | ||
| ): bigint { | ||
| const remaining = position.withdrawAvailableAt - nowSeconds; | ||
| return remaining > 0n ? remaining : 0n; | ||
| } | ||
|
|
||
| export function formatCooldown(seconds: bigint): string { | ||
| if (seconds <= 0n) return "0s"; | ||
| const total = Number(seconds); | ||
| const minutes = Math.floor(total / 60); | ||
| const rest = total % 60; | ||
| return minutes > 0 ? `${minutes}m ${rest}s` : `${rest}s`; | ||
| } | ||
|
|
||
| /// Plain status text for a position, embedding the live cooldown countdown while a | ||
| /// released name waits out its cooldown. | ||
| export function formatPositionStatus(position: ReleasePosition, nowSeconds: bigint): string { | ||
| if (position.claimed) return "claimed"; | ||
| if (!position.released) return "held"; | ||
| const remaining = cooldownRemainingSeconds(position, nowSeconds); | ||
| return remaining > 0n ? `cooldown ${formatCooldown(remaining)}` : "claimable"; | ||
| } | ||
|
|
||
| export type ReleasePhase = "held" | "redeemable" | "awaiting" | "reclaimable"; | ||
|
|
||
| /// The escrow's own predicates: `redeem` needs `released && !claimed && now < redeemableUntil`, | ||
| /// `isReclaimable` is `released && now >= redeemableUntil`. "awaiting" is the gap where the | ||
| /// holder withdrew the deposit inside the window, forfeiting redemption, and nobody can act yet. | ||
| export function releasePhase(position: ReleasePosition, nowSeconds: bigint): ReleasePhase { | ||
| if (!position.released) return "held"; | ||
| if (nowSeconds >= position.redeemableUntil) return "reclaimable"; | ||
| return position.claimed ? "awaiting" : "redeemable"; | ||
| } | ||
|
|
||
| /// One line naming the phase and, when a clock decides it, the time it changes. | ||
| export function formatReleasePhase(position: ReleasePosition, nowSeconds: bigint): string { | ||
| const until = formatUnixSeconds(position.redeemableUntil); | ||
| switch (releasePhase(position, nowSeconds)) { | ||
| case "held": | ||
| return "held; not released"; | ||
| case "redeemable": | ||
| return `released; redeemable by the previous holder until ${until}, then reclaimable by anyone`; | ||
| case "awaiting": | ||
| return `released; deposit withdrawn so no longer redeemable; reclaimable by anyone from ${until}`; | ||
| case "reclaimable": | ||
| return `released; redeem window closed at ${until}; reclaimable by anyone through registration`; | ||
| } | ||
| } |
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The positions table shows when the deposit can be withdrawn, and it leaves out whether the name itself can still be taken back.
fix: lease also add
phaseto the default table atdotns-sdk/packages/cli/src/cli/views/escrow.ts
Lines 24 to 28 in 78349c0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 76bc3d4