Repository navigation
feat: add --idempotency-key to transfer and swap, and tx status - #239
brendanjryan wants to merge 3 commits into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
✅ Cyclops Security Review: safe to mergeLast reviewed: ec211c8 (latest) · no open findings
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d5f2c60736
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
638999f to
f9f6803
Compare
f9f6803 to
ec211c8
Compare
Motivation
Agents retry
transferandswapafter timeouts and lost responses, and today a retry sends the transaction again. When the CLI reports that a send may have gone through, there is also no command to check it.Summary
--idempotency-key <key>on tokentransferandswap. Asubmittingrecord is written before sending, then updated with the hash and result. Rerunning the key sends nothing and returns the recorded result, withstatusread from the chain andidempotent_replay: true.E_USAGEnaming the fields that differ.E_PAYMENT_OUTCOME_UNKNOWNand does not resend.transferandswapnow returnE_PAYMENT_OUTCOME_UNKNOWNwith acta. When the hash is known, the message names it and thectaistempo wallet tx status <hash> --network <n>. Otherwise thectaistempo wallet whoami.tempo wallet tx status <hash>(MCPtx_status: read-only, idempotent, open-world). It reportssuccess,reverted,pendingornot_found, plus the block, from, to and fee. A pending result gets a polling_nextwithuntil. The command is wired into--describeand completions._nextcarries the key.Key design considerations
~/.tempo/wallet/idempotency/(mode 0700). Each file is named by a sha256 of the wallet, chain ID and key. Per-key files avoid read-modify-write races between concurrent sends that use different keys.wx), so when two sends race with the same key, only one sends. The claim file and its directory are fsynced before the send, so the claim survives a host crash. The sqlite store was not used because it shells out tosqlite3, which transfers do not otherwise need.withFileLock.withWalletloads the wallet without the agent key check. The command returnskeyRequiredError(now exported fromrequire-wallet.ts) in place of sending under an unused key. Dry runs and sends without a key are checked up front as before.submitkeeps the claim, so a rerun never resends. The one exception is an error the CLI raises itself before signing, such as a wallet that is no longer logged in. That error frees the key.data) records the hash and returns anE_PAYMENT_OUTCOME_UNKNOWNthat names it.--yes, quoting and balance checks. A replay sends nothing, and a swap that already completed may no longer pass those checks.fee_tokenin the fingerprint is the--fee-tokenflag, or null when it is omitted, which matches what a retry of the same command passes.Examples