✨ [CW-28621] feat(ada): support putting token assets into change utxo for all tx types#1152
Merged
Merged
Conversation
afd9524 to
d029567
Compare
d029567 to
cebad1e
Compare
63ff148 to
995c157
Compare
|
Static Code Review 📊 ✅ All quality checks passed! |
hankliu418
previously approved these changes
Jun 26, 2026
auto-merge was automatically disabled
June 26, 2026 06:21
Pull request was converted to draft
995c157 to
c37eec3
Compare
When a user's UTXO holds native tokens, the change output must carry those tokens back or the node rejects the tx (ValueNotConservedUTxO). This makes every ADA tx type's change output token-aware through a single unified value-blob encoding, so a token-bearing UTXO can be spent without a dedicated tx type. - Each change output carries a pre-encoded CBOR value: a bare uint for ADA-only change, or `82 <lovelace> <multiasset>` when the change holds native tokens, canonically ordered (keys sorted by length then bytewise) - New ChangeOutput type (change field + optional assets: TokenAsset[]); the app passes structured token data, the SDK does the CBOR encoding - Single getChangeArgument (value-blob, 292 bytes) shared by Transfer and all six staking types; pure-ADA tx bodies stay byte-identical, so existing signatures and flows are unaffected - Card-side scripts regenerated in coolwallet-signing-tools (value-blob change + setBufferIntUnsafe for the >127-byte length field) and re-signed with CBPubKey - Signing matrix test: every tx type, with and without token, verified end-to-end on a real card; preserved pure-ADA baselines pass unchanged Paired with coolwallet-signing-tools (AdaScript unified change encoding). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
c37eec3 to
3bba222
Compare
hankliu418
approved these changes
Jun 26, 2026
jin860315
approved these changes
Jun 26, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Lets users spend ADA from UTXOs that contain Cardano native tokens. Previously these transactions failed (
ValueNotConservedUTxO) because the change output couldn't carry the tokens back. This makes every ADA transaction type's change output token-aware through a single unified encoding — no dedicated token tx type.82 <lovelace> <multiasset>when the change holds native tokens (canonically ordered — keys sorted by length then bytewise)ChangeOutputtype (the change field + optionalassets?: TokenAsset[]); the app passes structured token data, the SDK does the CBOR encodinggetChangeArgument(value-blob, 292 bytes) shared by Transfer and all six staking types; pure-ADA tx bodies stay byte-identical, so existing signatures and flows are unaffectedDesign notes
TransferWithTokenChangetx type to isolate risk, then merged into the existing types — the token change layout is a strict superset of pure ADA, so unifying drops a whole type and removes drift between the token and non-token paths.6AE2on-card throw: the change-value length field originally usedsetBufferInt(.., 0, 200), but the card's 1-byte range comparator can't take an upper bound ≥ 128, so it threw for every value. Switched tosetBufferIntUnsafe(the SDK already caps the value at 200 bytes ingetChangeArgument).buildMultiAssetCborenforces this.Status — verified on real card ✅
-ugetTransactionSizecovered for the token path (app fee estimation); every with-token case is a consistent +80 bytes over its no-token pairRemaining (out of this PR's scope)
🤖 Generated with Claude Code
PR Summary by Typo
Overview
This PR introduces support for including token assets in change UTXOs across all Cardano (ADA) transaction types. This enhancement allows for more complex transactions involving native tokens to be handled correctly.
Key Changes
2.0.2.TokenAssetandChangeOutputinterfaces, and updatedRawTransactionto utilizeChangeOutputfor handling token-bearing change UTXOs.buildMultiAssetCborandencodeOutputValueutilities to ensure correct and canonical CBOR encoding of multi-asset values.Work Breakdown
To turn off PR summary, please visit Notification settings.