diff --git a/ERCS/erc-7730.md b/ERCS/erc-7730.md index 3d54ff5f51a..7f8865b2aca 100644 --- a/ERCS/erc-7730.md +++ b/ERCS/erc-7730.md @@ -205,7 +205,7 @@ References to values in the container (here an EVM Tx container) #### Value Interpolation -The `interpolatedIntent` field supports embedding formatted field values directly within intent strings using interpolation syntax. This allows constructing dynamic, context-aware descriptions of transactions and messages. +The `interpolatedIntent` field supports embedding formatted field values directly within intent strings using interpolation syntax. This allows constructing dynamic, context-aware descriptions of transactions and messages as an alternative to using individual `intent` and `fields`. The `interpolatedIntent` makes transaction intents significantly shorter and easier to read by presenting all relevant information in a single, natural language sentence rather than as separate labeled fields. This is particularly valuable for: - Reducing the cognitive load on users reviewing transactions @@ -219,6 +219,8 @@ Values are interpolated using curly braces containing a path reference: `{path}` - Container values (e.g., `{@.value}`, `{@.from}`) - Metadata constants (e.g., `{$.metadata.constants.nativeAssetAddress}`) +Interpolated intents MUST only refer to paths that are noted as `required`. + **Formatting Behavior** When a wallet processes an `interpolatedIntent`: @@ -242,7 +244,8 @@ To include literal curly braces in the intent text, escape them by doubling: `{{ "fields": [ {"path": "_to", "format": "addressName"}, {"path": "_value", "format": "tokenAmount", "params": {"tokenPath": "@.to"}} - ] + ], + "required": [ "_to", "_value" ] } ``` Displays as: **"Send 100 USDT to cyberdrk.eth"** @@ -255,7 +258,8 @@ Displays as: **"Send 100 USDT to cyberdrk.eth"** "fields": [ {"path": "amountIn", "format": "tokenAmount", "params": {"tokenPath": "tokenIn"}}, {"path": "amountOutMinimum", "format": "tokenAmount", "params": {"tokenPath": "tokenOut"}} - ] + ], + "required": [ "amountIn", "amountOutMinimum" ] } ``` Displays as: **"Swap 1000 USDC for at least 0.25 WETH"** @@ -267,7 +271,8 @@ Displays as: **"Swap 1000 USDC for at least 0.25 WETH"** "interpolatedIntent": "Wrap {@.value} ETH for WETH", "fields": [ {"path": "@.value", "format": "amount"} - ] + ], + "required": [ "@.value" ] } ``` Displays as: **"Wrap 0.5 ETH for WETH"** @@ -280,75 +285,6 @@ Displays as: **"Wrap 0.5 ETH for WETH"** ``` Displays as: **"Execute {function} with 100 tokens"** -**Batch Transactions (EIP-5792)** - -When displaying batch transactions as defined in [EIP-5792](./eip-5792.md), wallets SHOULD concatenate the `interpolatedIntent` strings of individual operations using " and " as a separator to create a single, human-readable description of the entire batch. - -This approach provides users with a clear, natural language summary of complex multi-step operations without requiring them to mentally piece together separate transaction descriptions. - -*Permit + Swap example:* -```json -[ - { - "function": "permit", - "interpolatedIntent": "Approve {spender} to spend {value} USDC" - }, - { - "function": "swapExactTokensForTokens", - "interpolatedIntent": "Swap {amountIn} for at least {amountOutMin}" - } -] -``` -Combined display: **"Approve Uniswap Router to spend 1000 USDC and Swap 1000 USDC for at least 0.25 WETH"** - -*Approve + Swap example:* -```json -[ - { - "function": "approve", - "interpolatedIntent": "Approve {_spender} to spend {_value}" - }, - { - "function": "exactInputSingle", - "interpolatedIntent": "Swap {amountIn} for at least {amountOutMinimum}" - } -] -``` -Combined display: **"Approve Uniswap V3 Router to spend 5000 DAI and Swap 5000 DAI for at least 1.2 ETH"** - -*Approve + Swap + Mint NFT example:* -```json -[ - { - "function": "approve", - "interpolatedIntent": "Approve {_spender} to spend {_value}" - }, - { - "function": "swapExactTokensForETH", - "interpolatedIntent": "Swap {amountIn} for at least {amountOutMin} ETH" - }, - { - "function": "mint", - "interpolatedIntent": "Mint {quantity} NFT(s) from {collection}" - } -] -``` -Combined display: **"Approve DEX Router to spend 2000 USDC and Swap 2000 USDC for at least 0.5 ETH and Mint 2 NFT(s) from NftProject"** - -**Implementation Guidance for Batch Transactions** - -Wallets implementing batch transaction display SHOULD: -1. Process each transaction in the batch to generate its `interpolatedIntent` -2. Join the resulting intent strings with " and " (note the spaces) -3. Display the combined string as a single transaction summary -4. Provide a way for users to view individual transaction details if needed -5. Fall back to displaying individual `intent` fields if any `interpolatedIntent` processing fails - -Wallets MAY: -- Apply additional formatting (e.g., capitalizing the first letter, adding a period at the end) -- Truncate very long combined intents and provide expansion UI -- Group related operations visually while still showing the combined intent - #### Organizing files Smart contracts and EIP-712 messages are often re-using common interfaces or types that share similar display formatting. This specification supports a basic inclusion mechanism that enables sharing files describing specific interfaces or types. @@ -830,15 +766,9 @@ This snippet defines an intent for a withdrawal function on a contract, with an A string containing an intent description with embedded field values using [interpolation syntax](#value-interpolation). -The `interpolatedIntent` provides a more dynamic, contextual description than the static `intent` field by embedding actual transaction/message values directly in the intent string. This is particularly useful for: -- Displaying concise, single-line transaction summaries -- Improving UX on devices with limited screen space -- Reducing cognitive load by presenting values in natural language context +Wallets MUST display either `interpolatedIntent` strings or screens generated from `intent` and individual `fields`. -When both `intent` and `interpolatedIntent` are present: -- Wallets SHOULD prefer displaying `interpolatedIntent` when interpolation is successfully processed -- Wallets MUST fall back to `intent` if interpolation fails for any reason -- Wallets MAY display both fields, with `interpolatedIntent` as the primary description +Wallets MAY display both fields, with `interpolatedIntent` as the primary description. Interpolated paths MUST reference fields that have corresponding format specifications in the `fields` array. The formatting applied during interpolation MUST match the formatting that would be applied if the field were displayed separately. @@ -1370,6 +1300,77 @@ All display strings in ERC-7730 files—including intents, labels, field names, Future versions of this specification may consider standardized internationalization support once the base standard achieves wider adoption and the ecosystem can better assess the need for multilingual support. +### Batch Transactions (EIP-5792) + +When displaying batch transactions as defined in [EIP-5792](./eip-5792.md), wallets SHOULD either: +* Concatenate the `interpolatedIntent` strings of individual operations using " and " as a separator to create a single, human-readable description of the entire batch. +* Concatenate screens generated using `intent` and required `fields`, clearly separating individual transactions + +The `interpolatedIntent` approach provides users with a clear, natural language summary of complex multi-step operations without requiring them to mentally piece together separate transaction descriptions. The `intent` approach provide a more controllable wallet UI for space limited wallets. + +*Permit + Swap example:* +```json +[ + { + "function": "permit", + "interpolatedIntent": "Approve {spender} to spend {value} USDC" + }, + { + "function": "swapExactTokensForTokens", + "interpolatedIntent": "Swap {amountIn} for at least {amountOutMin}" + } +] +``` +Combined display: **"Approve Uniswap Router to spend 1000 USDC and Swap 1000 USDC for at least 0.25 WETH"** + +*Approve + Swap example:* +```json +[ + { + "function": "approve", + "interpolatedIntent": "Approve {_spender} to spend {_value}" + }, + { + "function": "exactInputSingle", + "interpolatedIntent": "Swap {amountIn} for at least {amountOutMinimum}" + } +] +``` +Combined display: **"Approve Uniswap V3 Router to spend 5000 DAI and Swap 5000 DAI for at least 1.2 ETH"** + +*Approve + Swap + Mint NFT example:* +```json +[ + { + "function": "approve", + "interpolatedIntent": "Approve {_spender} to spend {_value}" + }, + { + "function": "swapExactTokensForETH", + "interpolatedIntent": "Swap {amountIn} for at least {amountOutMin} ETH" + }, + { + "function": "mint", + "interpolatedIntent": "Mint {quantity} NFT(s) from {collection}" + } +] +``` +Combined display: **"Approve DEX Router to spend 2000 USDC and Swap 2000 USDC for at least 0.5 ETH and Mint 2 NFT(s) from NftProject"** + +**Implementation Guidance for Batch Transactions using interpolatedIntents** + +Wallets implementing batch transaction display SHOULD: +1. Process each transaction in the batch to generate its `interpolatedIntent` +2. Join the resulting intent strings with " and " (note the spaces) +3. Display the combined string as a single transaction summary +4. Provide a way for users to view individual transaction details if needed +5. Fall back to displaying individual `intent` fields if any `interpolatedIntent` processing fails + +Wallets MAY: +- Apply additional formatting (e.g., capitalizing the first letter, adding a period at the end) +- Truncate very long combined intents and provide expansion UI +- Group related operations visually while still showing the combined intent + ### Why is the ABI still necessary? The full signature of a function call does not contain information about the types of complex parameters that might be used in the function call, only their names, while the ABI does carry this information. This is why the ABI is the reference and the function signature MUST match it. The full form of the function call is allowed in order to simplify writing and reading the ERC-7730 file. diff --git a/assets/erc-7730/erc7730-v1.schema.json b/assets/erc-7730/erc7730-v1.schema.json index a9c8444dc10..950bad1db60 100644 --- a/assets/erc-7730/erc7730-v1.schema.json +++ b/assets/erc-7730/erc7730-v1.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "description": "ERC7730 Clear Signing Specification Schema. Specification located at https://github.com/LedgerHQ/clear-signing-erc7730-registry/tree/master/specs", @@ -53,7 +53,7 @@ "$ref": "#/$context/EIP712" } ], - "unresolvedProperties": false + "unevaluatedProperties": false }, "contract": { @@ -473,7 +473,7 @@ } ] }, - "unresolvedProperties": false + "unevaluatedProperties": false }, "nestedFields": { "title": "A single set of field formats, allowing recursivity in the schema", @@ -625,7 +625,7 @@ } } ], - "unresolvedProperties": false + "unevaluatedProperties": false }, "names": { "anyOf": [ @@ -1035,7 +1035,7 @@ "description": "fully qualified type name in solidity source code" }, "components": { - "type": "array", + "type": [ "array", "null" ], "items": { "$ref": "#/$definitions/abi-parameter" } diff --git a/assets/erc-7730/example-main.json b/assets/erc-7730/example-main.json index 5a658779533..9ee7634a5d1 100644 --- a/assets/erc-7730/example-main.json +++ b/assets/erc-7730/example-main.json @@ -40,7 +40,7 @@ { "path": "_to", "label": "To", - "format": "addressOrName" + "format": "addressName" }, { "path": "_value",