Skip to content

Releases: ProjectOpenSea/tool-sdk

v0.29.0

Choose a tag to compare

@ryanio ryanio released this 23 Aug 19:05

What's changed

Breaking. A paid tool whose settlement fails now returns 502 without the output, instead of 200 with the result. createToolHandler gains settlement, defaulting to "required". Set settlement: "best-effort" to restore the previous behavior, which only suits callers who reconcile failed settlements out of band. This is a minor version because the package is pre-1.0, not because the change is small.

Also in this release:

  • replayGuard on the hosted x402 gates and paidPredicateGate, an optional single-use claim over each authorization's (payer, nonce) pair. Off by default, since it needs storage shared across instances.
  • RPC_URL is resolved as a universal RPC fallback for all wallet providers.
  • Hostnames are resolved and re-checked against private ranges before anything is fetched, in probe-endpoint and in inspect. The previous guard only inspected the hostname string, so a public name whose A record points inward was fetched. inspect matters most here because its metadataURI comes from a permissionlessly writable registry. A DNS-rebinding window remains and needs a connect-time-pinned dial.
  • deploy runs vercel link and vercel env add by argv rather than building a shell string. It interpolated the working directory's package.json name, variable names parsed from .env.local.example, and vercel whoami output into a string passed to execSync.
  • The usage reporters refuse a plaintext aggregator URL consistently. Only one of the three checked, while all three send an x-api-key and one forwards a signed authorization.

Community contributions

  • Shell interpolation in deploy, thanks @ygd58 for the fix (#18) and @bilguunbicktivism for the report (#14), which identified all three call sites and recommended the argv approach used here.
  • Lexical-only private address guard, thanks @ygd58 for the fix (#19) and @bilguunbicktivism for the report (#13), which demonstrated the bypass through inspect.

Full changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.28.5...tool-sdk-v0.29.0

v0.28.5

Choose a tag to compare

@ryanio ryanio released this 21 Jul 04:39

What's Changed

  • Normalize x402 registry references to the public usage-reporting source tokens.

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.28.4...tool-sdk-v0.28.5

v0.28.4

Choose a tag to compare

@ryanio ryanio released this 12 Jul 20:43

What's Changed

  • Reject negative and malformed x402 payment amounts. A negative maxAmountRequired previously slipped under the signed-BigInt maxAmount cap check and, when signed, wrapped into a huge positive uint256 EIP-3009 authorization, bypassing the caller's spending limit. Amounts are now validated as canonical non-negative integers in validatePaymentRequirements (unconditionally, even without a cap) and again in the EIP-3009 signer as defense-in-depth for direct signX402Payment callers. (#530)
  • Updated dependency @opensea/wallet-adapters to 0.3.3 (EIP-712 encoding hardening).

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.28.3...tool-sdk-v0.28.4

v0.28.3

Choose a tag to compare

@ryanio ryanio released this 12 Jul 03:13

What's Changed

  • fix(tool-sdk): scope predicate gate reads to the configured chain (#520): predicateGate/paidPredicateGate no longer force reads to the Base RPC when rpcUrl is unset, so a non-Base registry chain is actually queried. The x402 identity/payment chain (Base/Base-Sepolia) is decoupled from the registry chain so non-Base gating no longer fails closed. Includes regression tests for a non-Base registry with Base identity/payment.

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.28.2...tool-sdk-v0.28.3

v0.28.2

Choose a tag to compare

@ryanio ryanio released this 10 Jul 18:13

What's Changed

Security and hardening patch release.

Security

  • paidAuthenticatedFetch per-invocation maxAmount cap (#508): at most one nonzero x402 authorization is signed per call, and cumulative authorized value can never exceed maxAmount. Closes a double-challenge bypass where a malicious tool could obtain two independently-settleable authorizations, each under the cap.
  • verifyXPaymentAuth hardening (#509): the free predicateGate rejects non-zero-value X-Payment authorizations, validBefore is capped to 1h, the resolved chainId is pinned to the gate's chain, and the operator-recipient check fails closed when unset.
  • inspect metadataURI SSRF guard (#511): validate the registry-supplied metadataURI before fetching (http(s) + reject private/internal hosts). isPrivateHostname now numerically parses IP literals, closing decimal/octal/hex/partial-dotted IPv4 and IPv4-mapped IPv6 encoding bypasses, and covers 0.0.0.0/8, link-local 169.254.0.0/16, CGNAT 100.64.0.0/10, and IPv6 unique-local fc00::/7.

Fixes

  • Audit findings (#510): pin EIP-712 domain name/version for canonical USDC, surface the default registry lookup-block window, cache resolved manifests in createToolHandler, and decouple caller API-key provisioning from per-request abort signals.

Community Contributions

  • Thanks to @Nexory for reporting the inspect metadataURI SSRF that #511 fixes (tool-sdk#12).

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.28.1...tool-sdk-v0.28.2

v0.28.1

Choose a tag to compare

@ryanio ryanio released this 10 Jul 15:07

What's Changed

Security

  • eip3009AuthenticatedFetch now validates the 402 challenge's asset and network before signing: the network must be supported and the asset must be the canonical USDC contract for that network. This closes a signature-phishing surface where a zero-value challenge could name an arbitrary verifying contract / EIP-712 domain and still get signed (#507).
  • eip3009AuthenticatedFetch enforces the documented zero-value guarantee: it only signs X-Payment authorizations with value: 0, and returns non-zero (or unparseable-amount) 402 challenges as-is instead of signing an authorization that could move USDC to the server's advertised payTo (#504).

Internal

  • Deduplicate CLI command boilerplate: shared WALLET_PROVIDER_OPTION_DESCRIPTION constant and parseToolId() helper in cli/commands/shared.ts. No behavior change (#501).
  • Deduplicate predicate-client boilerplate: shared openSeaAssetLinks() helper plus typed read()/write() helpers on BasePredicateClient. No behavior change (#503).

Community Contributions

  • Thanks to @Nexory for raising the x402-signing hardening that motivated the eip3009AuthenticatedFetch asset/network and zero-value validation in this release (tool-sdk#11).

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.28.0...tool-sdk-v0.28.1

v0.28.0

Choose a tag to compare

@ryanio ryanio released this 08 Jul 19:52

What's Changed

  • Add Robinhood Chain (4663) support: --network robinhood on all CLI commands (custom viem chain definition until viem ships one) and 4663 added to every canonical Deployment.chains array in chains.ts.
  • Fix x402 CAIP-2 network handling asymmetry: server-side predicate gates now accept CAIP-2 (eip155:8453) and numeric (8453) network identifiers in the X-Payment payload, and the client normalizes the v1 payload network to the canonical short name.
  • Fix x402 usage reporting when the facilitator returns a CAIP-2/numeric network: settle() resolves the settlement network via resolveNetwork, so settlementChainId is populated for eip155:8453/8453 responses.
  • tool-registry: add an explicit Etherscan v2 url to the monad entry in foundry.toml so forge script --verify config resolution no longer aborts.

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.27.0...tool-sdk-v0.28.0

v0.27.0

Choose a tag to compare

@ryanio ryanio released this 02 Jul 17:59

What's Changed

  • feat: add Monad (chain 143) support. The --network flag now accepts monad in addition to base, mainnet, shape, and abstract. Monad is defined locally (mirroring viem's definition) because the pinned viem version predates Monad mainnet. 143 is added to every Deployment.chains array in chains.ts, and the deployed-address docs are updated: the canonical v0.2 addresses are identical on Monad (verified via CREATE2 dry-run). (#477)

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.26.1...tool-sdk-v0.27.0

v0.26.1

Choose a tag to compare

@ryanio ryanio released this 01 Jul 02:58

What's Changed

  • Fix createBankrAccount reading the wrong shape from Bankr's /wallet/me. The endpoint returns { wallets: [{ chain, address }, ...] } (no top-level address), so the account was created with an undefined address. Now resolves the EVM entry from wallets[]. (#473)
  • Picks up the @opensea/wallet-adapters@0.3.2 dependency bump (BigInt EIP-712 signing fix).

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.26.0...tool-sdk-v0.26.1

v0.26.0

Choose a tag to compare

@ryanio ryanio released this 30 Jun 23:06

What's Changed

Minor Changes

  • BREAKING: Unify predicateGate to use the standard 402 + X-Payment (EIP-3009) auth flow only (#471).
    • PredicateGateConfig.operatorAddress is now required (was optional)
    • Authorization: EIP-3009 <token> header is no longer accepted: use the X-Payment header via the 402 challenge flow
    • Authorization: SIWE <msg>.<sig> header is no longer accepted (was already deprecated)
    • CLI dry-run-predicate-gate now requires --operator-address and asserts a 402 response

Fixes

  • Use the Bankr /wallet/me endpoint instead of /wallet/info (#470).

Full Changelog: ProjectOpenSea/opensea-devtools@tool-sdk-v0.25.0...tool-sdk-v0.26.0