SDK: Permit2 interactions (stacked on #23) - #24
Conversation
1f7b7b4 to
2cadb51
Compare
2cadb51 to
ad7d0a4
Compare
d31c44f to
fa2daa4
Compare
🦋 Changeset detectedLatest commit: 8f7d178 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
fa2daa4 to
a42a4d4
Compare
a42a4d4 to
4de5806
Compare
New src/permit2.ts with viem actions and a permit2Actions() client extension for the canonical Permit2 contract, covering both flows: - SignatureTransfer: signPermit2Transfer (PermitTransferFrom, or PermitWitnessTransferFrom with a witness), permit2TransferFrom for the spender, isPermit2NonceUsed against the nonce bitmap, random nonces. - AllowanceTransfer: signPermit2Allowance (PermitSingle, nonce read from Permit2), permit2Permit, permit2AllowanceTransferFrom, getPermit2Allowance. - approvePermit2 / getPermit2Approval for the one-time ERC-20 approval. The EIP-712 domain, type sets, witness hash and witness type string are exported; the type string is derived with EIP-712's ordering rule and tested against the x402 layout and viem's type hash. Tests use the in-memory node from the ERC-20 change and recover every signature to the owner. Examples: fresh-wallet reads the Permit2 approval through the new action; permit2-pull.mjs signs a transfer off-chain and pulls it from a second account. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D1P1hkDQJ1iTaqumjZWtg8
The Permit2 actions and EIP-712 helpers import viem, which the root entry point must not load at runtime. Their runtime exports move to radius-sdk/client alongside the balance and ERC-20 actions; the root keeps only the types. Add the changeset. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…etwork
Mirror the ERC-20 change: only the Radius presets have a default token, a
custom chain throws a `config` error naming the action until `token` is
given, and `permit2Actions({ network })` resolves the default from the
network's payment asset after checking it is the client's chain. Document
`wait: false` as `pending`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
4de5806 to
8f7d178
Compare
erikzrekz
left a comment
There was a problem hiding this comment.
Just a few comments and ideas. Nothing major blocking from my POV.
| veto, every allowance the payment client grants. The plain `erc20Actions().approve` on your own | ||
| wallet client has no hook: it is you signing, not the SDK. | ||
|
|
||
| ## Permit2 |
There was a problem hiding this comment.
EIP-3009 will come next, yes?
| * Uniswap Permit2 interactions as viem actions, for the canonical Permit2 contract every | ||
| * Radius network shares (`PERMIT2_ADDRESS`). Two Permit2 flows are covered: | ||
| * | ||
| * SignatureTransfer (what x402 uses): the owner signs a one-off `PermitTransferFrom` |
There was a problem hiding this comment.
We may want to include a way to invalidate a nonce if the buyer never ends up using it. Maybe something like invalidatePermit2Nonce()? Agents will probably find this useful.
There's also revoking permit2 allowance entirely, which is a lockdown sort of feature.
|
|
||
| const word = (v: bigint | number) => numberToHex(BigInt(v), { size: 32 }); | ||
|
|
||
| /** Permit2 + SBC view answers. */ |
There was a problem hiding this comment.
Could we get a real e2e witness bound permit produced by this code against the test facilitator? That would be a good demonstration that this works against another service.
|
I've created issues to track the above as follow up work |
Stacked on #23 (ERC-20 interactions), which is stacked on #22 (balances). Review only the last commit.
What
packages/sdk/src/permit2.ts: viem actions plus apermit2Actions()client extension for the canonical Permit2 contract (PERMIT2_ADDRESS, shared by every Radius network), covering both of its flows.approvePermit2(unlimited by default, the x402 model),getPermit2ApprovalsignPermit2Transfersigns aPermitTransferFrom, orPermitWitnessTransferFromwhen a witness is given;permit2TransferFromsubmits it from the spender (permitTransferFromorpermitWitnessTransferFromwith the witness hash and type string);isPermit2NonceUsedreads the nonce bitmap; nonces are random by defaultsignPermit2Allowancesigns aPermitSinglewith the nonce read from Permit2;permit2Permitrecords it;permit2AllowanceTransferFromdraws on it;getPermit2Allowancereturns{ amount, expiration, nonce }permit2Domain,PERMIT_TRANSFER_FROM_TYPES,PERMIT_SINGLE_TYPES,permit2WitnessTypeString,permit2WitnessHash,PERMIT2_ABIThe witness type string is derived with EIP-712's ordering rule (referenced structs sorted by name). Tests pin it against the x402
Witness(address to,address facilitator,uint256 validAfter)layout radius-cli signs, and check it against viem's own type hash so the on-chain string verifies the signed digest.Examples
examples/agent-buyer/permit2-pull.mjs(new): payer signs a transfer off-chain, a collector account pulls the SBC with it and shows the nonce flipping to used.examples/agent-buyer/fresh-wallet.mjs: reads the Permit2 approval throughgetPermit2Approval.Tests
18 new tests; every signature is recovered to the owner and every submitted call is decoded from the raw transaction. SDK total 110 passing. Not run against a live node from this environment;
permit2-pull.mjsis the live check.🤖 Generated with Claude Code
https://claude.ai/code/session_01D1P1hkDQJ1iTaqumjZWtg8
Generated by Claude Code