feat: EIP-712 typed data signing via API key#148
feat: EIP-712 typed data signing via API key#148njdawn merged 18 commits intoopen-wallet-standard:mainfrom
Conversation
|
@ggonzalez94 is attempting to deploy a commit to the MoonPay Team on Vercel. A member of the Team first needs to authorize it. |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the core EIP-712 typed data signing function for API key (agent) mode. Gates on EVM-only, parses typed data JSON before policy evaluation to populate TypedDataContext, and calls EvmSigner::sign_typed_data. Includes 6 integration tests covering happy path, non-EVM rejection, wrong contract denial, malformed JSON, expired key, and wallet scope. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove hard-blocks in ops.rs and sign_message.rs that rejected API key usage for typed data signing. Wire up the dispatcher to delegate to sign_typed_data_with_api_key, and handle the new AllowedTypedDataContracts policy rule in the CLI policy display. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rule Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t bypass Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@njdawn this has been a blocker missing feature for me. Please take a look when you can(especially at the tradeoffs, since they impact the consistency of what is possible to express with typed data signing vs tx and message signing). I've tested it on my use case that needed EIP-712 signatures, and it is working well as far as I can tell. |
- Fix Node.js and Python binding tests: the denied-chain test case used typed data with chainId=8453 but chain="ethereum", which now correctly triggers the new chain mismatch check instead of AllowedChains. Updated tests to use matching chainId so AllowedChains is exercised. - Run cargo fmt to satisfy CI formatting checks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…efactor Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3ddd96b to
7c07de8
Compare
#153 explains this better |
Merge the two separate `use ows_signer` statements into a single import block, resolving the CI cargo fmt check failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deduplicate the chainId parsing logic that was repeated in the domain validation (step 5b) and TypedDataContext construction (step 6) of sign_typed_data_with_api_key. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verify that an empty contracts list [] in AllowedTypedDataContracts denies all typed data signing, confirming no accidental allow-all behavior when no contracts are specified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use consistent terminology across the codebase — the rest of OWS uses 'allowlist', so the AllowedTypedDataContracts docs should too. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the `import copy` statement from inside the function body to the module-level imports where it belongs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use a shared EVM chain-id helper instead of ad hoc parsing in typed-data and x402 flows. Stop reusing transaction.raw_hex for typed-data JSON bytes and validate the executable policy path against typed_data.raw_json instead. Add Node and Python binding coverage for AllowedTypedDataContracts.
njdawn
left a comment
There was a problem hiding this comment.
lgtm! fix ci, and then can merge
should be fixed now |
|
@njdawn CI should be green now — anything else needed before we can merge this? |
Fixes #147
Summary
The feature adds policy-gated EIP-712 typed data signing for API key holders (agents). Before this PR,
signTypedDataonly worked in owner mode (with a passphrase). Now agents usingows_key_tokens can sign typed data too — but only if their policy allows it..What changed
TypedDataContextinPolicyContext— structured EIP-712 domain fields (verifyingContract, chainId, primaryType, name, version) are now available to both declarative rules and executable policies during typed data signing. OnlyAllowedTypedDataContractshas been wired to keep the scope small. But this can be easily extendedAllowedTypedDataContractsrule — new declarative policy rule that whitelistsdomain.verifyingContractaddresses. If not set by the policy, anything can be signed.Design tradeoffs
sign_messagealready provides equivalent blast radius (EIP-191 messages can authorize off-chain operations too). Users who want to restrict typed data signing addAllowedTypedDataContractsto their policies.TransactionContextvalues insign_with_api_keyandsign_message_with_api_keyare populated with none, this means typed data gets rich, structured context with a dedicated declarative rule. Transactions get nothing — to, value, and data are all None despite the struct having those fields. The TransactionContext was designed for this but never wired up. This PR establishes what I think is the right pattern and can be later extended to tx and message signing. But if consistency is more important we could drop this more richTransactionContextfrom typed data and only add it together with the other tx types.