{"id":"ERC-5169","name":"Client Script URI (TokenScript)","status":"Final","chain":"both","category":{"id":"comprehension","name":"Comprehension & Display","description":"Making blockchain data readable to humans"},"journeyStages":[{"id":"specialized","name":"Specialized Interactions","description":"Physical items, AI, social, gaming"}],"uxImpact":"Supporting clients can discover token scripts through an array of scriptURI locations. TokenScript is one possible format. Verify authenticity and integrity, handle ScriptUpdate, and obtain consent before exposing script-driven actions. Format support, sandboxing and capability control belong to the client, not the URI interface.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-5169","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","hasDetailedContent":true,"content":{"id":"ERC-5169","sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-5169","type":"official-spec"}],"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","summary":"ERC-5169 lets token contracts publish script locations for compatible clients. The interface returns an array of URIs; it does not mandate TokenScript or universal wallet support. Clients must check authenticity, supported format and execution permissions before exposing script-driven actions.","designerTakeaways":["You can display scriptURI-linked actions dynamically per token.","Your UI can show script source and authenticity before execution.","You can require explicit user consent before running token scripts."],"applicability":{"whenToUse":["Tokens have official client scripts for custom actions.","Wallets want dynamic action discovery.","You can sandbox and verify script sources."],"whenToAvoid":["Token actions are fully covered by built-in wallet features.","Script trust model cannot be explained to users.","Security review cannot vet linked scripts."]},"prototypeFirst":[{"screen":"Primary happy path","why":"Prove the core user promise before edge cases.","covers":["Success state","Clear outcome copy"],"include":["Primary CTA","Confirmation feedback","Next step"]},{"screen":"Blocked or unsupported state","why":"Users discover limits when wallets or chains lack support.","covers":["Unsupported wallet","Wrong network"],"include":["Plain-language reason","Fallback action"]},{"screen":"Failure recovery","why":"Trust breaks when errors look like bugs.","covers":["User rejection","Transaction revert"],"include":["Retry path","Support context"]},{"screen":"Advanced disclosure","why":"Power users need technical detail without cluttering the default path.","covers":["Contract address","Token ID","Raw status"],"include":["Expandable section","Copy buttons","Explorer link"]}],"mentalModel":[{"label":"Token script link","description":"scriptURI() returns an array of script URIs. TokenScript is one possible client-supported format, not the format mandated by this standard."},{"label":"Discovery","description":"A supporting wallet or app selects a supported script format, verifies the source and integrity, and only then offers actions. ScriptUpdate notifies consumers that the locations changed."},{"label":"Trust review","description":"Show script source, publisher, and version before execution. Users must understand who authored the actions."},{"label":"User consent","description":"Each script-driven action needs explicit approval with plain-language preview, same as any transaction."},{"label":"Execution","description":"The script builds the contract call your UI submits. Failed or unverified scripts should disable actions, not fail silently."}],"statesToDesign":[{"state":"Ready","trigger":"Prerequisites met.","userNeed":"Understand what happens next.","designResponse":"Enable primary action with plain-language preview."},{"state":"Awaiting signature","trigger":"Wallet prompt open.","userNeed":"Know what they are approving.","designResponse":"Mirror human-readable summary in app and wallet."},{"state":"Pending","trigger":"Transaction submitted.","userNeed":"Confidence it is progressing.","designResponse":"Show status strip with explorer link."},{"state":"Succeeded","trigger":"On-chain confirmation.","userNeed":"See updated ownership or balance.","designResponse":"Celebrate outcome and show new state clearly."},{"state":"Failed or reverted","trigger":"Validation or execution failed.","userNeed":"Fix or retry without guessing.","designResponse":"Name the failed constraint and offer a concrete next step."}],"designDecisions":[{"question":"How much protocol detail do users see?","recommendation":"Lead with outcomes; tuck identifiers behind review.","rationale":"Users decide on consequences, not function selectors."},{"question":"What happens when support is missing?","recommendation":"Block with explanation and fallback path.","rationale":"Silent failure feels like a broken product."},{"question":"How do you label restricted assets?","recommendation":"Use persistent badges for non-transferable, locked, or expiring states.","rationale":"Hidden restrictions cause rage-quits at transfer time."}],"problemsSolved":[{"problem":"Inconsistent behavior across apps","oldWay":"Each team reinvents copy and edge cases","newWay":"Shared standard gives predictable UX patterns","impact":"high"},{"problem":"Users surprised by on-chain rules","oldWay":"Generic transfer UI fails at submit time","newWay":"Standard-aware UI sets expectations upfront","impact":"high"},{"problem":"Support burden from opaque errors","oldWay":"Raw revert reasons in toasts","newWay":"Mapped states explain what to do next","impact":"medium"}],"uxPatterns":[{"name":"Dynamic Token Actions","description":"Discover actions from scriptURI.","mockup":"concept/typed-data","components":["ActionList","ScriptBadge"],"userFlow":["User views a token in a supporting client","Client reads the scriptURI array and selects a supported resource","Client validates source authenticity and integrity under its trust policy","Expose supported actions only after verification"]},{"name":"Script Consent Modal","description":"Explicit approval before script execution.","mockup":"concept/verify-safety","components":["ConsentModal","SourceIndicator"],"userFlow":["Action selected","Script source shown","User approves","Script runs sandboxed"]}],"seenInTheWild":[{"app":"AlphaWallet","url":"https://alphawallet.com/","note":"TokenScript pioneer for dynamic token functionality."},{"app":"TokenScript","url":"https://tokenscript.org/","note":"Framework for token-linked client scripts."},{"app":"Rainbow","url":"https://rainbow.me/","note":"Wallet action discovery patterns for tokens."}],"antiPatterns":[{"pattern":"Hiding standard-imposed restrictions until submit","why":"Users feel tricked when actions fail at the last step","instead":"Show eligibility and badges before the primary CTA","severity":"critical"},{"pattern":"Protocol jargon in user-facing copy","why":"Non-technical users cannot consent informedly","instead":"Use outcome language with optional technical disclosure","severity":"high"},{"pattern":"No fallback when wallet lacks support","why":"Dead-end flows increase churn","instead":"Explain limitation and offer alternate path or network","severity":"high"}],"vocabulary":[{"use":"Your balance / Your item","avoid":"Token ID / Token contract","why":"Ownership language matches mental models."},{"use":"Cannot transfer yet","avoid":"Transfer reverted","why":"Explain restriction without EVM vocabulary."},{"use":"Confirm in wallet","avoid":"Sign transaction","why":"Matches wallet UX users already know."}],"technicalNotes":"ERC-5169 defines scriptURI() returning string[], an owner-controlled setScriptURI and the ScriptUpdate event. Consumers must validate an immutable location, a content hash in the URI, or the referenced authenticity mechanism. The ERC mandates neither TokenScript nor a sandbox/runtime. Clients must supply format support, execution isolation, capability limits and explicit user consent; failed verification disables actions.","relatedStandards":[{"id":"ERC-1046","relationship":"Token logo and metadata complement"},{"id":"EIP-747","relationship":"Token icon and metadata standards"}]},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-5169","type":"official-spec"},{"label":"Discussion","url":"https://ethereum-magicians.org/search?q=ERC-5169","type":"discussion"},{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-5169","type":"official-spec"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-5169","markdown":"https://www.eipsfordesigners.com/standards/ERC-5169/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-5169/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-5169","official":"https://ercs.ethereum.org/ERCS/erc-5169","discussion":"https://ethereum-magicians.org/search?q=ERC-5169"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}