diff --git a/.changeset/abi-anonymous-events.md b/.changeset/abi-anonymous-events.md new file mode 100644 index 00000000..18977836 --- /dev/null +++ b/.changeset/abi-anonymous-events.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `AbiEvent.encode` and `AbiEvent.decode` to honor the `anonymous` flag -- anonymous events no longer prepend or expect a selector topic. diff --git a/.changeset/abi-constructor-bytecode-prefix.md b/.changeset/abi-constructor-bytecode-prefix.md new file mode 100644 index 00000000..a7eea289 --- /dev/null +++ b/.changeset/abi-constructor-bytecode-prefix.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `AbiConstructor.decode` to assert that `data` begins with the provided `bytecode` and allowed constructor encoding and decoding without an ABI constructor when no arguments are present. diff --git a/.changeset/abi-decode-checksum-default.md b/.changeset/abi-decode-checksum-default.md new file mode 100644 index 00000000..97bb2bdd --- /dev/null +++ b/.changeset/abi-decode-checksum-default.md @@ -0,0 +1,10 @@ +--- +'ox': major +--- + +**Breaking:** Changed ABI decode helpers to checksum decoded addresses by default. + +```diff +- AbiParameters.decode(parameters, data) ++ AbiParameters.decode(parameters, data, { checksumAddress: false }) +``` diff --git a/.changeset/abi-error-extract.md b/.changeset/abi-error-extract.md new file mode 100644 index 00000000..ced15cb6 --- /dev/null +++ b/.changeset/abi-error-extract.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added `AbiError.extract` for selecting and decoding ABI errors from revert data. diff --git a/.changeset/abi-event-decode-log.md b/.changeset/abi-event-decode-log.md new file mode 100644 index 00000000..a35feb07 --- /dev/null +++ b/.changeset/abi-event-decode-log.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added `AbiEvent.decodeLog` and `AbiEvent.extractLogs` for decoding and extracting event logs directly from an ABI. diff --git a/.changeset/abi-event-hex-topic-normalization.md b/.changeset/abi-event-hex-topic-normalization.md new file mode 100644 index 00000000..0beffbee --- /dev/null +++ b/.changeset/abi-event-hex-topic-normalization.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `AbiEvent.assertArgs` and `AbiEvent.encode` to always hash `string`/`bytes` indexed inputs to hex via `Hash.keccak256(value, { as: 'Hex' })`, so topic comparisons and emitted topics are reliably hex regardless of whether the input is a `Hex.Hex` or a `Bytes.Bytes`. diff --git a/.changeset/abi-function-decode-data-selector.md b/.changeset/abi-function-decode-data-selector.md new file mode 100644 index 00000000..f9717977 --- /dev/null +++ b/.changeset/abi-function-decode-data-selector.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added an `AbiFunction.decodeData(abi, data)` overload that extracts the ABI function from the calldata selector. diff --git a/.changeset/abi-function-selector-only-calldata.md b/.changeset/abi-function-selector-only-calldata.md new file mode 100644 index 00000000..aef7b97a --- /dev/null +++ b/.changeset/abi-function-selector-only-calldata.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `AbiFunction.decodeData` to throw `AbiParameters.DataSizeTooSmallError` when the calldata is exactly the 4-byte selector but the function declares inputs, instead of silently returning `undefined`. diff --git a/.changeset/abi-human-readable-ox.md b/.changeset/abi-human-readable-ox.md new file mode 100644 index 00000000..bd00fc2e --- /dev/null +++ b/.changeset/abi-human-readable-ox.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added human-readable ABI parsing and formatting utilities from `abitype` to ox, including runtime validation and type-level safety for `Abi`, `AbiItem`, `AbiParameters`, and the new `AbiParameter` module. diff --git a/.changeset/abi-parameters-data-size-bound.md b/.changeset/abi-parameters-data-size-bound.md new file mode 100644 index 00000000..9f3b514e --- /dev/null +++ b/.changeset/abi-parameters-data-size-bound.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `AbiParameters.decode` to surface a `DataSizeTooSmallError` (with parameter context) instead of leaking a `Cursor.PositionOutOfBoundsError` when the encoded payload is shorter than the parameter list requires. diff --git a/.changeset/abi-parameters-encode-packed.md b/.changeset/abi-parameters-encode-packed.md new file mode 100644 index 00000000..5bc14669 --- /dev/null +++ b/.changeset/abi-parameters-encode-packed.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `AbiParameters.encodePacked` to validate that fixed-array lengths match the supplied value, throwing `ArrayLengthMismatchError` (e.g. for `uint256[2]` with three elements) instead of silently encoding the wrong arity. diff --git a/.changeset/abi-standalone-zero-width-arrays.md b/.changeset/abi-standalone-zero-width-arrays.md new file mode 100644 index 00000000..2c5a742b --- /dev/null +++ b/.changeset/abi-standalone-zero-width-arrays.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `AbiParameters.decode` for standalone zero-length fixed arrays of dynamic types (e.g. `string[0]`). diff --git a/.changeset/account-proof-converters.md b/.changeset/account-proof-converters.md new file mode 100644 index 00000000..0e2f7541 --- /dev/null +++ b/.changeset/account-proof-converters.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `AccountProof.fromRpc` and `AccountProof.toRpc` for converting between RPC and instantiated `AccountProof` shapes returned by `eth_getProof`. diff --git a/.changeset/address-keys-keystore-async-pbkdf2.md b/.changeset/address-keys-keystore-async-pbkdf2.md new file mode 100644 index 00000000..5aaff35b --- /dev/null +++ b/.changeset/address-keys-keystore-async-pbkdf2.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Keystore.toKeyAsync` to use the async PBKDF2 implementation -- previously it called the synchronous `pbkdf2` helper and blocked the main thread when decrypting PBKDF2-backed keystores. diff --git a/.changeset/address-keys-keystore-kdf-validation.md b/.changeset/address-keys-keystore-kdf-validation.md new file mode 100644 index 00000000..3f2cf2a2 --- /dev/null +++ b/.changeset/address-keys-keystore-kdf-validation.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added validation of KDF parameters in `Keystore.pbkdf2`, `Keystore.pbkdf2Async`, `Keystore.scrypt`, and `Keystore.scryptAsync` -- PBKDF2 now requires `iterations` to be an integer `>= 1000`, and scrypt now requires `n` to be a power of two `>= 1024` with positive integer `r` and `p`, rejecting trivially weak parameters that previously produced formally valid but cryptographically insecure keystores. diff --git a/.changeset/address-keys-keystore-scrypt-async-pr.md b/.changeset/address-keys-keystore-scrypt-async-pr.md new file mode 100644 index 00000000..7448ebbf --- /dev/null +++ b/.changeset/address-keys-keystore-scrypt-async-pr.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Keystore.scryptAsync` to honor caller-provided `p` and `r` options -- previously they were silently overridden with `p=8` and `r=1`, producing keystores that disagreed with the synchronous `Keystore.scrypt` for the same inputs. diff --git a/.changeset/address-keys-mnemonic-default.md b/.changeset/address-keys-mnemonic-default.md new file mode 100644 index 00000000..aac96a3e --- /dev/null +++ b/.changeset/address-keys-mnemonic-default.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Mnemonic.toPrivateKey` to return `Bytes` by default to match its declared return type -- previously it returned a `Hex` string at runtime even though the default `as` was `'Bytes'`. diff --git a/.changeset/anchor-crypto-webcrypto-verify-padding.md b/.changeset/anchor-crypto-webcrypto-verify-padding.md new file mode 100644 index 00000000..f7cc442d --- /dev/null +++ b/.changeset/anchor-crypto-webcrypto-verify-padding.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `WebCryptoP256.verify` rejecting valid signatures whose `r` or `s` value has a leading zero byte by padding both components to 32 bytes. diff --git a/.changeset/anchor-publickey-assert-shape.md b/.changeset/anchor-publickey-assert-shape.md new file mode 100644 index 00000000..1c31d501 --- /dev/null +++ b/.changeset/anchor-publickey-assert-shape.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `PublicKey.assert` so it rejects objects missing `x`/`y` when the `compressed` option is set explicitly. diff --git a/.changeset/anchor-publickey-fromhex-validate.md b/.changeset/anchor-publickey-fromhex-validate.md new file mode 100644 index 00000000..a3dbd663 --- /dev/null +++ b/.changeset/anchor-publickey-fromhex-validate.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `PublicKey.fromHex` and `PublicKey.fromBytes` so they reject deserialized public keys with an invalid SEC1 prefix. diff --git a/.changeset/block-state-block-fromrpc-required-fields.md b/.changeset/block-state-block-fromrpc-required-fields.md new file mode 100644 index 00000000..175399a5 --- /dev/null +++ b/.changeset/block-state-block-fromrpc-required-fields.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Preserved `Block.fromRpc().totalDifficulty` as `undefined` instead of silently coercing missing values to `0n`. diff --git a/.changeset/block-state-bloom-contains-validate-length.md b/.changeset/block-state-bloom-contains-validate-length.md new file mode 100644 index 00000000..5fb6b0ab --- /dev/null +++ b/.changeset/block-state-bloom-contains-validate-length.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Made `Bloom.contains` validate the bloom argument length and throw `Bloom.InvalidBloomError` instead of silently returning `false` for malformed bloom inputs. diff --git a/.changeset/block-state-filter-torpc-address-null.md b/.changeset/block-state-filter-torpc-address-null.md new file mode 100644 index 00000000..0c5b3851 --- /dev/null +++ b/.changeset/block-state-filter-torpc-address-null.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Made `Filter.toRpc` preserve explicit `address: null` (and `topics: null`) instead of stripping it via truthy checks. diff --git a/.changeset/block-state-log-block-timestamp.md b/.changeset/block-state-log-block-timestamp.md new file mode 100644 index 00000000..a11a01de --- /dev/null +++ b/.changeset/block-state-log-block-timestamp.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added `Log.fromRpc` and `Log.toRpc` support for optional `blockTimestamp` fields. diff --git a/.changeset/block-state-quantity-converters.md b/.changeset/block-state-quantity-converters.md new file mode 100644 index 00000000..8ca2844d --- /dev/null +++ b/.changeset/block-state-quantity-converters.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Unified the RPC-quantity conversion blocks across `Block`, `BlockOverrides`, and `StateOverrides` behind an internal helper so optional bigint fields with explicit `'0x0'` (e.g. `baseFeePerGas: '0x0'` on a post-merge block) round-trip as `0n` instead of being silently dropped by the previous truthy checks. diff --git a/.changeset/block-state-typed-data-array-validation.md b/.changeset/block-state-typed-data-array-validation.md new file mode 100644 index 00000000..8a8ab0ad --- /dev/null +++ b/.changeset/block-state-typed-data-array-validation.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Validated array element types and fixed-array lengths in `TypedData.assert` and `TypedData.encodeField`, throwing `InvalidArrayError`/`InvalidArrayLengthError` instead of silently passing malformed input through to the encoder. diff --git a/.changeset/block-state-validator-data-validate-address.md b/.changeset/block-state-validator-data-validate-address.md new file mode 100644 index 00000000..99a95f22 --- /dev/null +++ b/.changeset/block-state-validator-data-validate-address.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Made `ValidatorData.encode` call `Address.assert` on the validator argument so malformed validator addresses are rejected instead of producing invalid ERC-191 payloads. diff --git a/.changeset/block-state-value-validation.md b/.changeset/block-state-value-validation.md new file mode 100644 index 00000000..84464adf --- /dev/null +++ b/.changeset/block-state-value-validation.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Tightened `Value.from` input validation to reject malformed numeric strings (`''`, `'.'`, `'-'`, `'-.'`) and to reject non-integer or negative `decimals`, and replaced `Number`/`Math.round` rounding with string-carry rounding so very long fractions no longer lose precision. diff --git a/.changeset/bloom-prepared.md b/.changeset/bloom-prepared.md new file mode 100644 index 00000000..a714f27f --- /dev/null +++ b/.changeset/bloom-prepared.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `Bloom.prepare`, `Bloom.containsPrepared`, and `Bloom.containsHash` for membership checks against a precomputed bloom filter. Use `Bloom.prepare(bloom)` once and `Bloom.containsPrepared(prepared, input)` (or `Bloom.containsHash(prepared, hash)` when the caller already has the keccak hash) inside hot loops to avoid the per-call `Bytes.fromHex` allocation that `Bloom.contains` pays. diff --git a/.changeset/bytes-rlp-odd-length-pad.md b/.changeset/bytes-rlp-odd-length-pad.md new file mode 100644 index 00000000..744aa3c8 --- /dev/null +++ b/.changeset/bytes-rlp-odd-length-pad.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Bytes.fromNumber` and `Rlp.fromHex` rejecting valid odd-nibble hex output produced by `Hex.fromNumber` (e.g. `0x7`, `0x311`); both now even-pad before handing the value to the strict `Bytes.fromHex` parser. diff --git a/.changeset/config.json b/.changeset/config.json index 94baecfe..b1d0ddae 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -5,7 +5,10 @@ "changelog": ["@changesets/changelog-github", { "repo": "wevm/ox" }], "commit": false, "fixed": [], - "ignore": ["webauthn-p256"], "linked": [], + "privatePackages": { + "version": true, + "tag": true + }, "updateInternalDependencies": "patch" } diff --git a/.changeset/cosekey-topublickey-bytes-options.md b/.changeset/cosekey-topublickey-bytes-options.md new file mode 100644 index 00000000..b6f878df --- /dev/null +++ b/.changeset/cosekey-topublickey-bytes-options.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `returnByteLength` and `returnDecoded` options to `CoseKey.toPublicKey` and accepted `Uint8Array` input in addition to `Hex`. diff --git a/.changeset/crypto-bls-aggregate-validate.md b/.changeset/crypto-bls-aggregate-validate.md new file mode 100644 index 00000000..3444934d --- /dev/null +++ b/.changeset/crypto-bls-aggregate-validate.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Bls.aggregate` to reject empty arrays and mixed G1/G2 input, and added a fast path that returns the input directly when only one point is supplied. diff --git a/.changeset/crypto-blspoint-frombytes-group.md b/.changeset/crypto-blspoint-frombytes-group.md new file mode 100644 index 00000000..19099f8d --- /dev/null +++ b/.changeset/crypto-blspoint-frombytes-group.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `BlsPoint.fromBytes` to honor its declared `group` argument and assert the input length matches the requested G1 (48 bytes) or G2 (96 bytes) shape. diff --git a/.changeset/crypto-cosekey-validate-header.md b/.changeset/crypto-cosekey-validate-header.md new file mode 100644 index 00000000..c602c22e --- /dev/null +++ b/.changeset/crypto-cosekey-validate-header.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Hardened `CoseKey.toPublicKey` to reject COSE_Key inputs with a non-P-256 `kty`, `alg`, or `crv` header, or with `x`/`y` byte arrays that are not exactly 32 bytes long. diff --git a/.changeset/crypto-extra-entropy-default-doc.md b/.changeset/crypto-extra-entropy-default-doc.md new file mode 100644 index 00000000..ab9b74e2 --- /dev/null +++ b/.changeset/crypto-extra-entropy-default-doc.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Documented `extraEntropy` on `Secp256k1.sign` and `P256.sign` correctly as `@default false` so the JSDoc matches the runtime default. diff --git a/.changeset/crypto-kzg-from-receiver.md b/.changeset/crypto-kzg-from-receiver.md new file mode 100644 index 00000000..640a34a0 --- /dev/null +++ b/.changeset/crypto-kzg-from-receiver.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Kzg.from` to preserve `this` binding by wrapping method calls instead of destructuring, so class instances or method-style implementations work correctly. diff --git a/.changeset/crypto-serialized-inputs-and-as-option.md b/.changeset/crypto-serialized-inputs-and-as-option.md new file mode 100644 index 00000000..3b285b65 --- /dev/null +++ b/.changeset/crypto-serialized-inputs-and-as-option.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `as: 'Hex' | 'Bytes' | 'Object'` option to `Secp256k1.sign` / `getPublicKey` / `recoverPublicKey`, `P256.sign` / `getPublicKey` / `recoverPublicKey`, `WebCryptoP256.sign`, and `Bls.sign` / `getPublicKey` (default `'Object'` keeps existing behavior); plus accept `Hex.Hex | Bytes.Bytes | Signature.Signature` for `signature` params and `Hex.Hex | Bytes.Bytes | PublicKey.PublicKey` for `publicKey` params on `verify`, `recoverAddress`, `recoverPublicKey`, `getSharedSecret` across the same modules. diff --git a/.changeset/crypto-webcrypto-doc-corrections.md b/.changeset/crypto-webcrypto-doc-corrections.md new file mode 100644 index 00000000..b8403984 --- /dev/null +++ b/.changeset/crypto-webcrypto-doc-corrections.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Documented `WebCryptoP256.sign` low-S normalization as always-on and corrected the `WebCryptoP256.createKeyPair` / `createKeyPairECDH` JSDoc to describe `publicKey` as a `PublicKey.PublicKey`. diff --git a/.changeset/crypto-webcrypto-shared-secret-typed-error.md b/.changeset/crypto-webcrypto-shared-secret-typed-error.md new file mode 100644 index 00000000..55a6af53 --- /dev/null +++ b/.changeset/crypto-webcrypto-shared-secret-typed-error.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Replaced the plain `Error` thrown by `WebCryptoP256.getSharedSecret` when given an ECDSA private key with a typed `WebCryptoP256.InvalidPrivateKeyAlgorithmError`. diff --git a/.changeset/ens-to-coin-type.md b/.changeset/ens-to-coin-type.md new file mode 100644 index 00000000..2b13b34d --- /dev/null +++ b/.changeset/ens-to-coin-type.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added `Ens.toCoinType` for converting chain IDs to ENS coin types. diff --git a/.changeset/erc4337-entry-point-v09.md b/.changeset/erc4337-entry-point-v09.md new file mode 100644 index 00000000..f46db0ac --- /dev/null +++ b/.changeset/erc4337-entry-point-v09.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added EntryPoint 0.9 ABI, address, UserOperation types, `paymasterSignature` packing, hashing, and RPC support. diff --git a/.changeset/erc4337-user-operation-from-packed-typing.md b/.changeset/erc4337-user-operation-from-packed-typing.md new file mode 100644 index 00000000..872fce67 --- /dev/null +++ b/.changeset/erc4337-user-operation-from-packed-typing.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Narrowed `UserOperation.fromPacked` return type to `UserOperation<'0.7', true>` to reflect that the packed format does not carry v0.8 `authorization`. diff --git a/.changeset/erc4337-user-operation-gas-v08.md b/.changeset/erc4337-user-operation-gas-v08.md new file mode 100644 index 00000000..4db8e65f --- /dev/null +++ b/.changeset/erc4337-user-operation-gas-v08.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added EntryPoint 0.8 and 0.9 support to `UserOperationGas` through version-specific aliases over the 0.7 gas shape. diff --git a/.changeset/erc4337-user-operation-rpc.md b/.changeset/erc4337-user-operation-rpc.md new file mode 100644 index 00000000..5272a140 --- /dev/null +++ b/.changeset/erc4337-user-operation-rpc.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `UserOperation.toRpc` to preserve v0.6 `paymasterAndData` and corrected `eth_getUserOperationByHash` result typing. diff --git a/.changeset/erc4337-user-operation-v08-authorization.md b/.changeset/erc4337-user-operation-v08-authorization.md new file mode 100644 index 00000000..8a1982d0 --- /dev/null +++ b/.changeset/erc4337-user-operation-v08-authorization.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `UserOperation` RPC codecs to map native `authorization` to wire `eip7702Auth` for EntryPoint 0.8 and 0.9. diff --git a/.changeset/erc6492-strip-magic-and-validate.md b/.changeset/erc6492-strip-magic-and-validate.md new file mode 100644 index 00000000..6565004e --- /dev/null +++ b/.changeset/erc6492-strip-magic-and-validate.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `SignatureErc6492.unwrap` to strip the trailing magic bytes before ABI-decoding, and made `SignatureErc6492.from` and `assert` validate object inputs by throwing the new `InvalidUnwrappedSignatureError` on malformed values. diff --git a/.changeset/erc7821-execute-structural-detection.md b/.changeset/erc7821-execute-structural-detection.md new file mode 100644 index 00000000..6bbaf036 --- /dev/null +++ b/.changeset/erc7821-execute-structural-detection.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Replaced the exception-driven opData fallback in `Execute.decodeBatchOfBatchesData` with structural detection of the ABI head word, so malformed inputs surface as decode errors instead of being masked by the catch. diff --git a/.changeset/erc8010-assert-suffix-and-recovery.md b/.changeset/erc8010-assert-suffix-and-recovery.md new file mode 100644 index 00000000..fe89c01d --- /dev/null +++ b/.changeset/erc8010-assert-suffix-and-recovery.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Hardened ERC-8010 by validating the full unwrapped object in `SignatureErc8010.assert`, capping the suffix length parsed by `unwrap` against the wrapped size to reject overflowing inputs, and skipping `Secp256k1.recoverAddress` in `wrap` when `to` is already provided. diff --git a/.changeset/eth-get-raw-transaction-by-hash.md b/.changeset/eth-get-raw-transaction-by-hash.md index d4299f91..10c1d4cc 100644 --- a/.changeset/eth-get-raw-transaction-by-hash.md +++ b/.changeset/eth-get-raw-transaction-by-hash.md @@ -1,5 +1,5 @@ --- -"ox": patch +'ox': patch --- -Added `eth_getRawTransactionByHash` to `RpcSchema.Eth`. +Added `eth_getRawTransactionByHash` to `RpcSchema.Eth` and `z.RpcSchema.Eth`. diff --git a/.changeset/fee-helpers.md b/.changeset/fee-helpers.md new file mode 100644 index 00000000..185989b3 --- /dev/null +++ b/.changeset/fee-helpers.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `Fee.fromHistoryRpc`, `Fee.toHistoryRpc`, `Fee.estimateMaxFeePerGas`, and `Fee.effectiveGasPrice` for converting between RPC/instantiated `FeeHistory` shapes and computing common EIP-1559 fee values. diff --git a/.changeset/filter-blockhash-branch.md b/.changeset/filter-blockhash-branch.md new file mode 100644 index 00000000..2acacfde --- /dev/null +++ b/.changeset/filter-blockhash-branch.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added the EIP-234 `blockHash` branch to `Filter.Filter` (and `Filter.Rpc`) so log filters can be discriminated against `fromBlock`/`toBlock` and `blockHash`, matching the execution-apis `filter.yaml` `oneOf` schema. `Filter.toRpc` now forwards `blockHash` when present. diff --git a/.changeset/hex-tobytes-buffer-pool-fix.md b/.changeset/hex-tobytes-buffer-pool-fix.md new file mode 100644 index 00000000..17ed0ba1 --- /dev/null +++ b/.changeset/hex-tobytes-buffer-pool-fix.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Hex.toBytes` and `Bytes.fromHex` returning a `Uint8Array` view that aliased Node's shared `Buffer` pool memory, which broke callers that read `.buffer` (e.g. WebAuthn `attestationObject` round-trips). diff --git a/.changeset/log-empty-topics.md b/.changeset/log-empty-topics.md new file mode 100644 index 00000000..04383372 --- /dev/null +++ b/.changeset/log-empty-topics.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed the zod `Log` schema to accept logs with zero topics (e.g. `LOG0`/anonymous events) and widened `Log.topics` to `Hex.Hex[]`. diff --git a/.changeset/multisig-remove-config-id.md b/.changeset/multisig-remove-config-id.md new file mode 100644 index 00000000..51314a7b --- /dev/null +++ b/.changeset/multisig-remove-config-id.md @@ -0,0 +1,17 @@ +--- +'ox': patch +--- + +`ox/tempo`: Removed the TIP-1061 multisig `config_id` concept to match the updated Tempo reference implementation: multisig account addresses now derive directly from the initial config, owner approval digests bind only `account`, the signature wire format is `0x05 || rlp([account, signatures, init?])`, `MultisigConfig.maxOwners` is now 255 with `u8` weights, and owner approvals may be nested multisig signatures. + +```diff +- const id = MultisigConfig.toId(genesisConfig) +- const account = MultisigConfig.getAddress({ genesisConfigId: id }) ++ const account = MultisigConfig.getAddress(genesisConfig) + +- MultisigConfig.getSignPayload({ payload, account, genesisConfigId }) ++ MultisigConfig.getSignPayload({ payload, account }) + +- SignatureEnvelope.from({ account, genesisConfigId, signatures }) ++ SignatureEnvelope.from({ account, signatures }) +``` diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 00000000..2c3ada35 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,122 @@ +{ + "mode": "pre", + "tag": "beta", + "initialVersions": { + "ox": "0.14.22" + }, + "changesets": [ + "abi-anonymous-events", + "abi-constructor-bytecode-prefix", + "abi-decode-checksum-default", + "abi-error-extract", + "abi-event-decode-log", + "abi-event-hex-topic-normalization", + "abi-function-decode-data-selector", + "abi-function-selector-only-calldata", + "abi-human-readable-ox", + "abi-parameters-data-size-bound", + "abi-parameters-encode-packed", + "abi-standalone-zero-width-arrays", + "account-proof-converters", + "address-keys-keystore-async-pbkdf2", + "address-keys-keystore-kdf-validation", + "address-keys-keystore-scrypt-async-pr", + "address-keys-mnemonic-default", + "anchor-crypto-webcrypto-verify-padding", + "anchor-publickey-assert-shape", + "anchor-publickey-fromhex-validate", + "block-state-block-fromrpc-required-fields", + "block-state-bloom-contains-validate-length", + "block-state-filter-torpc-address-null", + "block-state-log-block-timestamp", + "block-state-quantity-converters", + "block-state-typed-data-array-validation", + "block-state-validator-data-validate-address", + "block-state-value-validation", + "bloom-prepared", + "bytes-rlp-odd-length-pad", + "cosekey-topublickey-bytes-options", + "crypto-bls-aggregate-validate", + "crypto-blspoint-frombytes-group", + "crypto-cosekey-validate-header", + "crypto-extra-entropy-default-doc", + "crypto-kzg-from-receiver", + "crypto-serialized-inputs-and-as-option", + "crypto-webcrypto-doc-corrections", + "crypto-webcrypto-shared-secret-typed-error", + "ens-to-coin-type", + "erc4337-entry-point-v09", + "erc4337-user-operation-from-packed-typing", + "erc4337-user-operation-gas-v08", + "erc4337-user-operation-rpc", + "erc4337-user-operation-v08-authorization", + "erc6492-strip-magic-and-validate", + "erc7821-execute-structural-detection", + "erc8010-assert-suffix-and-recovery", + "eth-get-raw-transaction-by-hash", + "fee-helpers", + "filter-blockhash-branch", + "hex-tobytes-buffer-pool-fix", + "keyauthorization-fromrpc-type", + "log-empty-topics", + "multisig-remove-config-id", + "promise-with-timeout-single-reject", + "provider-from-prototype", + "provider-from-strict-eip1193", + "rlp-decode-depth-limit", + "rlp-strict-boundaries", + "rpc-response-from-validation", + "rpc-response-parse-error-preserve", + "rpc-response-parse-validation", + "rpc-schema-block-identifier-wire-type", + "rpc-schema-codecs", + "rpc-schema-eth-call-block-overrides", + "rpc-schema-eth-fill-transaction", + "rpc-schema-from-zod", + "rpc-schema-item-codecs", + "rpc-schema-request-numberish-params", + "rpc-transport-empty-body", + "rpc-transport-http-error-details", + "rpc-transport-json-empty-error", + "rpc-transport-signal-compose", + "signature-byte-helpers", + "siwe-bigint-chain-id", + "solidity-helpers", + "tempo-authorization-signature-normalize", + "tempo-key-authorization-null-rpc-fields", + "tempo-noncekey-random", + "tempo-poolid-canonical", + "tempo-receipt-type", + "tempo-request-wire-fields", + "tempo-token-address-inputs", + "tempo-transaction-null-rpc-fields", + "tempo-transaction-request-envelope-conversion", + "tempo-txenvelope-validate-prefix", + "torpc-numberish-inputs", + "transaction-request-envelope-conversion", + "transactions-access-list-strict-storage-keys", + "transactions-authorization-fromtuplelist-return-type", + "transactions-eip4844-blob-validation", + "transactions-eip4844-deserialize-error-attributes", + "transactions-eip4844-input-alias", + "transactions-eip7702-torpc", + "transactions-legacy-v-fromrpc", + "transactions-legacy-v-torpc", + "transactions-transaction-request-fromrpc-no-mutate", + "transactions-transaction-rpc-transaction-index-zero", + "tx-envelope-router", + "typed-data-type-hashes-memo", + "upgrade-noble-v2", + "v1-blob-cells", + "v1-deprecate-4844-sidecar", + "v1-hex-coords", + "v1-remove-tempo-address", + "webauthn-authentication-getsignpayload-hash", + "webauthn-authentication-sign-utf8", + "webauthn-authentication-verify-at-ed-flags", + "webauthn-authenticator-bytes-first", + "webauthn-registration-verify-attestation-default-docs", + "zero-width-abi-types", + "zod-schema-entrypoint" + ] +} diff --git a/.changeset/promise-with-timeout-single-reject.md b/.changeset/promise-with-timeout-single-reject.md new file mode 100644 index 00000000..0def507f --- /dev/null +++ b/.changeset/promise-with-timeout-single-reject.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `RpcTransport.fromHttp` (via internal `withTimeout`) producing an unhandled rejection when the wrapped fetch threw a non-`AbortError` after the timeout setup ran. diff --git a/.changeset/provider-from-prototype.md b/.changeset/provider-from-prototype.md new file mode 100644 index 00000000..99443bd0 --- /dev/null +++ b/.changeset/provider-from-prototype.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Provider.from` to preserve wrapped providers' prototype methods, accessors, and non-enumerable property descriptors instead of dropping them via object spread. diff --git a/.changeset/provider-from-strict-eip1193.md b/.changeset/provider-from-strict-eip1193.md new file mode 100644 index 00000000..8a7eab83 --- /dev/null +++ b/.changeset/provider-from-strict-eip1193.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Provider.from` to stop sniffing successful EIP-1193 payloads for a `jsonrpc` field and reparsing them as JSON-RPC envelopes. diff --git a/.changeset/rlp-decode-depth-limit.md b/.changeset/rlp-decode-depth-limit.md new file mode 100644 index 00000000..b706204a --- /dev/null +++ b/.changeset/rlp-decode-depth-limit.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added a decode depth limit (1024) to `Rlp.toBytes` / `Rlp.toHex`, throwing `Rlp.DepthLimitExceededError` instead of overflowing the call stack on deeply nested untrusted RLP input. diff --git a/.changeset/rlp-strict-boundaries.md b/.changeset/rlp-strict-boundaries.md new file mode 100644 index 00000000..58e18ecd --- /dev/null +++ b/.changeset/rlp-strict-boundaries.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed RLP decoding to reject malformed payloads with trailing bytes (`Rlp.TrailingBytesError`) or list items overrunning the declared list length (`Rlp.ListBoundaryExceededError`). diff --git a/.changeset/rpc-response-from-validation.md b/.changeset/rpc-response-from-validation.md new file mode 100644 index 00000000..f45ded9c --- /dev/null +++ b/.changeset/rpc-response-from-validation.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `RpcResponse.from` crashing when called without a `request` option and missing `jsonrpc` -- it now validates the envelope and throws `RpcResponse.ParseError` for missing `id`/`jsonrpc`. diff --git a/.changeset/rpc-response-parse-error-preserve.md b/.changeset/rpc-response-parse-error-preserve.md new file mode 100644 index 00000000..113375f4 --- /dev/null +++ b/.changeset/rpc-response-parse-error-preserve.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `RpcResponse.parseError` re-wrapping existing `RpcResponse.BaseError` instances as `InternalError` -- existing instances are now returned as-is. diff --git a/.changeset/rpc-response-parse-validation.md b/.changeset/rpc-response-parse-validation.md new file mode 100644 index 00000000..bda67062 --- /dev/null +++ b/.changeset/rpc-response-parse-validation.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `RpcResponse.parse` silently returning `undefined` for malformed payloads -- it now validates the JSON-RPC envelope (`jsonrpc === '2.0'`, presence of `id`, and presence of either `result` or `error`) and throws `RpcResponse.ParseError` otherwise. diff --git a/.changeset/rpc-schema-block-identifier-wire-type.md b/.changeset/rpc-schema-block-identifier-wire-type.md new file mode 100644 index 00000000..741eff29 --- /dev/null +++ b/.changeset/rpc-schema-block-identifier-wire-type.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed the EIP-1898 block identifier param type in the core `eth`/`tempo` RPC request schemas to be wire-typed (`Block.Identifier`), so its `blockNumber` field is hex like the sibling `Block.Number` branch instead of native `bigint`. This makes `z.RpcSchema.encodeParams` output assignable to the core request param types for block-selector methods (`eth_call`, `eth_getBalance`, `eth_getCode`, `eth_getStorageAt`, `eth_getTransactionCount`, `eth_getBlockTransactionCountByNumber`, `eth_getUncleCountByBlockNumber`, `eth_estimateGas`, etc.). diff --git a/.changeset/rpc-schema-codecs.md b/.changeset/rpc-schema-codecs.md new file mode 100644 index 00000000..20058126 --- /dev/null +++ b/.changeset/rpc-schema-codecs.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added directional codec helpers to the `ox/zod` `RpcSchema` namespace: `decodeParams`/`encodeParams`, `decodeReturns`/`encodeReturns`, and `decodeRequest`/`encodeRequest` (`decode` maps wire → native, `encode` maps native → wire), alongside `parseItem` for method lookup and `parse` as an alias of `decodeRequest`. Scalar quantity returns in `z.RpcSchema.Eth` now decode to their native representation (`eth_blockNumber`, `eth_gasPrice`, `eth_blobBaseFee`, `eth_estimateGas`, `eth_getBalance`, `eth_maxPriorityFeePerGas` → `bigint`; `eth_chainId`, `eth_getTransactionCount`, `eth_getBlockTransactionCountBy*`, `eth_getUncleCountByBlock*` → `number`), while raw transport typing (`RpcSchema.FromZod`) continues to use wire types. diff --git a/.changeset/rpc-schema-eth-call-block-overrides.md b/.changeset/rpc-schema-eth-call-block-overrides.md new file mode 100644 index 00000000..22b6b795 --- /dev/null +++ b/.changeset/rpc-schema-eth-call-block-overrides.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added an optional 4th `blockOverrides` parameter to the `eth_call` and `eth_estimateGas` schemas (`RpcSchema.Default` and the zod `RpcSchema.Eth`), matching Geth/Anvil's `eth_call(transaction, block, stateOverrides, blockOverrides)` signature. diff --git a/.changeset/rpc-schema-eth-fill-transaction.md b/.changeset/rpc-schema-eth-fill-transaction.md new file mode 100644 index 00000000..41e8b51f --- /dev/null +++ b/.changeset/rpc-schema-eth-fill-transaction.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added `eth_fillTransaction` to `RpcSchema.Eth`. diff --git a/.changeset/rpc-schema-from-zod.md b/.changeset/rpc-schema-from-zod.md new file mode 100644 index 00000000..245fed6a --- /dev/null +++ b/.changeset/rpc-schema-from-zod.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added Zod-backed RPC schema support: `z.RpcSchema.from` (in `ox/zod`) now accepts a record of `{ params, returns }` Zod schemas keyed by method name and returns a parseable `RpcSchema.Namespace`; `RpcSchema.Schema`/`RpcSchema.ToGeneric`/`RpcSchema.FromZod` were added; and `Provider.from` / `RpcTransport.fromHttp` accept a Zod namespace as their `schema` option, deriving request/return types from it. diff --git a/.changeset/rpc-schema-item-codecs.md b/.changeset/rpc-schema-item-codecs.md new file mode 100644 index 00000000..9be8999f --- /dev/null +++ b/.changeset/rpc-schema-item-codecs.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +The `ox/zod` `RpcSchema` codecs (`decodeParams`/`encodeParams`, `decodeReturns`/`encodeReturns`) now also accept a resolved `RpcSchema.Item` in place of a `(namespace, method)` pair. A method can be looked up once with `z.RpcSchema.parseItem` and passed to each codec, so encoding params and decoding returns no longer repeats the namespace and method name. diff --git a/.changeset/rpc-schema-request-numberish-params.md b/.changeset/rpc-schema-request-numberish-params.md new file mode 100644 index 00000000..c5d0d0c2 --- /dev/null +++ b/.changeset/rpc-schema-request-numberish-params.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Updated the zod `RpcSchema.Eth` request-bearing methods (`eth_call`, `eth_estimateGas`, `eth_sendTransaction`, `eth_signTransaction`, `eth_simulateV1`) to encode their transaction-request params with `TransactionRequestToRpc`, so `RpcSchema.encodeParams` now accepts numberish (`bigint | number | Hex`) quantities. Decoded output is unchanged. diff --git a/.changeset/rpc-transport-empty-body.md b/.changeset/rpc-transport-empty-body.md new file mode 100644 index 00000000..7b072b38 --- /dev/null +++ b/.changeset/rpc-transport-empty-body.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `RpcTransport.fromHttp` to throw `RpcTransport.MalformedResponseError` for empty `2xx` HTTP bodies instead of silently returning `undefined`. diff --git a/.changeset/rpc-transport-http-error-details.md b/.changeset/rpc-transport-http-error-details.md new file mode 100644 index 00000000..b97917f6 --- /dev/null +++ b/.changeset/rpc-transport-http-error-details.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `RpcTransport.HttpError.details` to render raw-text error bodies verbatim instead of JSON-stringifying them with surrounding quotes. diff --git a/.changeset/rpc-transport-json-empty-error.md b/.changeset/rpc-transport-json-empty-error.md new file mode 100644 index 00000000..39db800e --- /dev/null +++ b/.changeset/rpc-transport-json-empty-error.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `RpcTransport.fromHttp` to surface an `HttpError` (instead of a `SyntaxError`) when servers return `Content-Type: application/json` with an empty body for non-`2xx` responses. diff --git a/.changeset/rpc-transport-signal-compose.md b/.changeset/rpc-transport-signal-compose.md new file mode 100644 index 00000000..bf125cd3 --- /dev/null +++ b/.changeset/rpc-transport-signal-compose.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `RpcTransport.fromHttp` ignoring its own `timeout` when the caller supplied a `fetchOptions.signal`; both signals are now composed via `AbortSignal.any` so the timeout always fires. diff --git a/.changeset/signature-byte-helpers.md b/.changeset/signature-byte-helpers.md new file mode 100644 index 00000000..4fadec80 --- /dev/null +++ b/.changeset/signature-byte-helpers.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `Signature.toCompactBytes`, `Signature.fromCompactBytes`, `Signature.toRecoveredBytes`, and `Signature.fromRecoveredBytes` for direct 64 and 65 byte encoded signature interop. diff --git a/.changeset/siwe-bigint-chain-id.md b/.changeset/siwe-bigint-chain-id.md new file mode 100644 index 00000000..6004c85b --- /dev/null +++ b/.changeset/siwe-bigint-chain-id.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Changed `Siwe.Message.chainId` to bigint, parsed SIWE messages to bigint chain IDs, and generated SIWE nonces with cryptographically secure randomness. diff --git a/.changeset/solidity-helpers.md b/.changeset/solidity-helpers.md new file mode 100644 index 00000000..6b18ec09 --- /dev/null +++ b/.changeset/solidity-helpers.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `Solidity.intRange(bits, signed)` and `Solidity.maxUint(bits)` helpers that compute the inclusive range or maximum unsigned value of a Solidity integer of the given bit width without importing one of the `Solidity.maxInt*`/`Solidity.maxUint*` constants by name. diff --git a/.changeset/tempo-authorization-signature-normalize.md b/.changeset/tempo-authorization-signature-normalize.md new file mode 100644 index 00000000..69fd51fa --- /dev/null +++ b/.changeset/tempo-authorization-signature-normalize.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `tempo.AuthorizationTempo.from` to normalize `options.signature` through `SignatureEnvelope.from` so serialized or convenience-shape signatures are accepted as documented. diff --git a/.changeset/tempo-key-authorization-null-rpc-fields.md b/.changeset/tempo-key-authorization-null-rpc-fields.md new file mode 100644 index 00000000..63e2994d --- /dev/null +++ b/.changeset/tempo-key-authorization-null-rpc-fields.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed Tempo key authorization RPC decoding to tolerate `null` optional fields and preserve `witness`, `isAdmin`, and `account` through the zod codec. diff --git a/.changeset/tempo-noncekey-random.md b/.changeset/tempo-noncekey-random.md new file mode 100644 index 00000000..dd7b8927 --- /dev/null +++ b/.changeset/tempo-noncekey-random.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `tempo.TransactionRequest.toRpc` to generate a full 192-bit `nonceKey` when called with `nonceKey: 'random'`, matching the documented field width. diff --git a/.changeset/tempo-poolid-canonical.md b/.changeset/tempo-poolid-canonical.md new file mode 100644 index 00000000..3e40daed --- /dev/null +++ b/.changeset/tempo-poolid-canonical.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `PoolId.from` to be order-independent by sorting token addresses canonically before hashing. diff --git a/.changeset/tempo-receipt-type.md b/.changeset/tempo-receipt-type.md new file mode 100644 index 00000000..a5ae7561 --- /dev/null +++ b/.changeset/tempo-receipt-type.md @@ -0,0 +1,5 @@ +--- +"ox": patch +--- + +Fixed Tempo `TransactionReceipt.fromRpc`/`toRpc` to map the `type` field between `'0x76'` and `'tempo'`. diff --git a/.changeset/tempo-request-wire-fields.md b/.changeset/tempo-request-wire-fields.md new file mode 100644 index 00000000..4b0a3ae6 --- /dev/null +++ b/.changeset/tempo-request-wire-fields.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added the Tempo fields `keyId`, `multisigInit`, `multisigSignatureCount`, and `capabilities` to `TransactionRequest`. \ No newline at end of file diff --git a/.changeset/tempo-token-address-inputs.md b/.changeset/tempo-token-address-inputs.md new file mode 100644 index 00000000..ba5abdb1 --- /dev/null +++ b/.changeset/tempo-token-address-inputs.md @@ -0,0 +1,13 @@ +--- +'ox': major +--- + +Removed the Tempo `TokenId` module and narrowed Tempo token inputs (`feeToken`, `Channel.token`, `PoolId.from` tokens) to `Address.Address`; also removed the now-redundant `Channel.Resolved` type. + +```diff + TxEnvelopeTempo.from({ + // ... +- feeToken: 1n, ++ feeToken: '0x20c0000000000000000000000000000000000001', + }) +``` diff --git a/.changeset/tempo-transaction-null-rpc-fields.md b/.changeset/tempo-transaction-null-rpc-fields.md new file mode 100644 index 00000000..5b35240b --- /dev/null +++ b/.changeset/tempo-transaction-null-rpc-fields.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed Tempo transaction RPC decoding to tolerate `null` optional fields and to omit fabricated flat `data`/`to`/`value` call fields. diff --git a/.changeset/tempo-transaction-request-envelope-conversion.md b/.changeset/tempo-transaction-request-envelope-conversion.md new file mode 100644 index 00000000..5bf490f2 --- /dev/null +++ b/.changeset/tempo-transaction-request-envelope-conversion.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `TransactionRequest.toEnvelope` (in `ox/tempo`) and `TxEnvelopeTempo.toTransactionRequest` for converting between Tempo `TransactionRequest` and `TxEnvelopeTempo` shapes. `toEnvelope` folds flat `{ to, data, value }` requests into `calls[]`, resolves `nonceKey: 'random'`, and drops fields not supported by the Tempo envelope (`blobs`, `gasPrice`, core `r`/`s`/`yParity`/`v`). Extended Tempo's `TransactionRequest` with optional `signature` (`SignatureEnvelope`) and `feePayerSignature` (`Signature.Signature`) fields so signed envelopes can be round-tripped without information loss; `fromRpc`/`toRpc` translate them via the existing `SignatureEnvelope.fromRpc`/`toRpc` and `Signature.fromRpc`/`toRpc` helpers. diff --git a/.changeset/tempo-txenvelope-validate-prefix.md b/.changeset/tempo-txenvelope-validate-prefix.md new file mode 100644 index 00000000..3b99d8a6 --- /dev/null +++ b/.changeset/tempo-txenvelope-validate-prefix.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `tempo.TxEnvelopeTempo.deserialize` to validate the `0x76` envelope-type prefix before RLP decoding, rejecting payloads from other envelope types. diff --git a/.changeset/torpc-numberish-inputs.md b/.changeset/torpc-numberish-inputs.md new file mode 100644 index 00000000..499997d6 --- /dev/null +++ b/.changeset/torpc-numberish-inputs.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Widened `toRpc` inputs (and their symmetric zod `*ToRpc` encode schemas) to accept numberish values -- `Hex.Hex | bigint | number` for bigint-typed quantities and `Hex.Hex | number` for number-typed quantities -- while keeping decoded/`fromRpc` output types strictly `bigint`/`number`. diff --git a/.changeset/transaction-request-envelope-conversion.md b/.changeset/transaction-request-envelope-conversion.md new file mode 100644 index 00000000..30631575 --- /dev/null +++ b/.changeset/transaction-request-envelope-conversion.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added `TransactionRequest.toEnvelope` and `TransactionEnvelope.toTransactionRequest` for converting between `TransactionRequest` and `TxEnvelope*` shapes (e.g. when handling `eth_sendTransaction`). Extended `TransactionRequest` with optional `r`, `s`, `yParity`, `v` fields so signed payloads can be carried in the same type (with hex↔native coercion in `fromRpc`/`toRpc`). Also tightened `TransactionEnvelope.getType` to throw on accidental RPC-style type strings (`'0x0'`–`'0x4'`); pass payloads through `TransactionRequest.fromRpc` first. diff --git a/.changeset/transactions-access-list-strict-storage-keys.md b/.changeset/transactions-access-list-strict-storage-keys.md new file mode 100644 index 00000000..109248bb --- /dev/null +++ b/.changeset/transactions-access-list-strict-storage-keys.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `AccessList.fromTupleList` silently normalizing non-32-byte storage keys; it now throws `InvalidStorageKeySizeError` to match the symmetric `toTupleList` validation. diff --git a/.changeset/transactions-authorization-fromtuplelist-return-type.md b/.changeset/transactions-authorization-fromtuplelist-return-type.md new file mode 100644 index 00000000..33093929 --- /dev/null +++ b/.changeset/transactions-authorization-fromtuplelist-return-type.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Authorization.fromTupleList` declaring its return type as `TupleList` instead of `List`. diff --git a/.changeset/transactions-eip4844-blob-validation.md b/.changeset/transactions-eip4844-blob-validation.md new file mode 100644 index 00000000..00b59869 --- /dev/null +++ b/.changeset/transactions-eip4844-blob-validation.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Required `blobVersionedHashes` to be present and non-empty in `TxEnvelopeEip4844.assert`; the previous `if (blobVersionedHashes)` guard let envelopes serialize as "blob transactions with no blob hashes". diff --git a/.changeset/transactions-eip4844-deserialize-error-attributes.md b/.changeset/transactions-eip4844-deserialize-error-attributes.md new file mode 100644 index 00000000..9abfbefb --- /dev/null +++ b/.changeset/transactions-eip4844-deserialize-error-attributes.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Improved `TxEnvelopeEip4844.deserialize` `InvalidSerializedError` diagnostics by including `maxFeePerBlobGas` and `blobVersionedHashes` in the attributes map and using the EIP-4844 signature-presence threshold (`length > 11`) instead of the EIP-1559 `> 9` copy-paste. diff --git a/.changeset/transactions-eip4844-input-alias.md b/.changeset/transactions-eip4844-input-alias.md new file mode 100644 index 00000000..de9120ae --- /dev/null +++ b/.changeset/transactions-eip4844-input-alias.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `TxEnvelopeEip4844.serialize` ignoring the `input` alias for `data`; calldata supplied via `input` is now included in the serialized envelope and sign payload. diff --git a/.changeset/transactions-eip7702-torpc.md b/.changeset/transactions-eip7702-torpc.md new file mode 100644 index 00000000..6f721a14 --- /dev/null +++ b/.changeset/transactions-eip7702-torpc.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Added the missing `TxEnvelopeEip7702.toRpc` to mirror `Eip1559`/`Eip2930`/`Eip4844`/`Legacy`, restoring symmetry for callers building EIP-7702 RPC requests. diff --git a/.changeset/transactions-legacy-v-fromrpc.md b/.changeset/transactions-legacy-v-fromrpc.md new file mode 100644 index 00000000..a6ead583 --- /dev/null +++ b/.changeset/transactions-legacy-v-fromrpc.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Transaction.fromRpc` clobbering legacy (`type: '0x0'`) `v` with `27`/`28`; the original RPC `v` is now preserved when present. diff --git a/.changeset/transactions-legacy-v-torpc.md b/.changeset/transactions-legacy-v-torpc.md new file mode 100644 index 00000000..5566b5ba --- /dev/null +++ b/.changeset/transactions-legacy-v-torpc.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `TxEnvelopeLegacy.toRpc` collapsing every signed legacy envelope to `v: '0x1b'`/`'0x1c'`; it now preserves an explicit `envelope.v`, otherwise derives EIP-155 `v = chainId * 2 + 35 + yParity` when a chain ID is present. diff --git a/.changeset/transactions-transaction-request-fromrpc-no-mutate.md b/.changeset/transactions-transaction-request-fromrpc-no-mutate.md new file mode 100644 index 00000000..ac7936dc --- /dev/null +++ b/.changeset/transactions-transaction-request-fromrpc-no-mutate.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `TransactionRequest.fromRpc` mutating the caller-provided RPC object by cloning before assigning parsed fields. diff --git a/.changeset/transactions-transaction-rpc-transaction-index-zero.md b/.changeset/transactions-transaction-rpc-transaction-index-zero.md new file mode 100644 index 00000000..4742b9c0 --- /dev/null +++ b/.changeset/transactions-transaction-rpc-transaction-index-zero.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `Transaction.toRpc` emitting `null` for `transactionIndex: 0` instead of `0x0`. diff --git a/.changeset/tx-envelope-router.md b/.changeset/tx-envelope-router.md new file mode 100644 index 00000000..5ccb67fc --- /dev/null +++ b/.changeset/tx-envelope-router.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added generic `TxEnvelope` routing helpers with property-based type inference for parsing, serialization, validation, hashing, signing payloads, and RPC conversion. diff --git a/.changeset/typed-data-type-hashes-memo.md b/.changeset/typed-data-type-hashes-memo.md new file mode 100644 index 00000000..f5744c57 --- /dev/null +++ b/.changeset/typed-data-type-hashes-memo.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Threaded an optional `typeHashes` cache through `TypedData.encode`, `TypedData.hashStruct`, and `TypedData.hashDomain` so `keccak256(encodeType(t))` is computed once per `(primaryType, types)` per call instead of once per nested struct or array element (with `TypedData.encode` populating a fresh map internally and advanced callers able to share a `Map` across calls). diff --git a/.changeset/upgrade-noble-v2.md b/.changeset/upgrade-noble-v2.md new file mode 100644 index 00000000..53d3fa2a --- /dev/null +++ b/.changeset/upgrade-noble-v2.md @@ -0,0 +1,10 @@ +--- +'ox': major +--- + +Upgraded `@noble/ciphers`, `@noble/curves`, `@noble/hashes`, `@scure/bip32`, and `@scure/bip39` to v2. + +Notable behavioral changes inherited from noble v2: + +- ECDSA signatures now default to `lowS: true` for both `Secp256k1` and `P256`. Previously `P256` signatures could have high-S values. +- The `noble` re-exports on `Secp256k1`, `P256`, `Ed25519`, `X25519`, and `Bls` now reference the v2 APIs (e.g. `randomSecretKey()` instead of `randomPrivateKey()`, `Point` instead of `ProjectivePoint`/`ExtendedPoint`, `bls.longSignatures.*` instead of top-level `bls.sign`/`verify`). If you depended on the v1 shape via `Module.noble`, refer to the noble v2 changelog. diff --git a/.changeset/v1-blob-cells.md b/.changeset/v1-blob-cells.md new file mode 100644 index 00000000..671c33dc --- /dev/null +++ b/.changeset/v1-blob-cells.md @@ -0,0 +1,12 @@ +--- +'ox': minor +--- + +**Added:** `BlobCells` module exposing PeerDAS (EIP-7594) cell-level helpers — `fromBlob` derives the 128 cells + cell KZG proofs of an extended blob, `verify` verifies a batch of cell proofs against their commitments, `recover` reconstructs the full set of cells/proofs from ≥ 64 known cells, and `toDataColumns` builds the 128 per-column packs for a list of blobs. + +```diff ++ import { BlobCells, Blobs } from 'ox' ++ ++ const blobs = Blobs.from('0xdeadbeef') ++ const columns = BlobCells.toDataColumns(blobs, { kzg }) // 128 columns +``` diff --git a/.changeset/v1-deprecate-4844-sidecar.md b/.changeset/v1-deprecate-4844-sidecar.md new file mode 100644 index 00000000..8f97b22c --- /dev/null +++ b/.changeset/v1-deprecate-4844-sidecar.md @@ -0,0 +1,20 @@ +--- +'ox': major +--- + +**Breaking:** Removed the 4844-only blob-sidecar surface in favor of PeerDAS +(EIP-7594). + +- `Kzg.Kzg` no longer includes `computeBlobKzgProof`. Bring a PeerDAS-capable + backend (e.g. `c-kzg` ≥ v1.5, `micro-eth-signer/advanced/kzg.js` ≥ v0.18, or + equivalent). The backend must implement `computeCells`, + `computeCellsAndKzgProofs`, `recoverCellsAndKzgProofs`, and + `verifyCellKzgProofBatch` in addition to `blobToKzgCommitment`. +- Removed `Blobs.toSidecars`, `Blobs.toProofs`, + `Blobs.sidecarsToVersionedHashes`, `Blobs.BlobSidecar`, and + `Blobs.BlobSidecars`. Use the upcoming `BlobCells` module (next phase) for + PeerDAS data-column construction. `Kzg.Kzg.blobToKzgCommitment` and + `Blobs.toVersionedHashes` remain for transaction versioned-hash derivation. +- Removed `TxEnvelopeEip4844.sidecars` (the legacy "network wrapper" RLP form + for `eth_sendRawTransaction`). PeerDAS replaces the network wrapper with + cell/column propagation; the on-chain envelope is unchanged. diff --git a/.changeset/v1-hex-coords.md b/.changeset/v1-hex-coords.md new file mode 100644 index 00000000..ef79bf72 --- /dev/null +++ b/.changeset/v1-hex-coords.md @@ -0,0 +1,14 @@ +--- +'ox': major +--- + +Migrated ECDSA and BLS coordinate fields (`r`, `s`, `x`, `y`, BLS `Fp`/`Fp2`) from `bigint` to padded `Hex.Hex` strings (32-byte for `secp256k1`/`P256`/`WebAuthnP256`, 48-byte for BLS12-381) on `Signature`, `PublicKey`, `BlsPoint`, `Transaction`, `Authorization`, `TxEnvelope`, and related Tempo and ERC envelopes, dropping the `bigintType` generic. + +```diff +- Signature.from({ r: 0x6e10...n, s: 0x4a90...n, yParity: 1 }) ++ Signature.from({ ++ r: '0x6e100a352ec6ad1b70802290e18aeed190704973570f3b8ed42cb9808e2ea6bf', ++ s: '0x4a90a229a244495b41890987806fcbd2d5d23fc0dbe5f5256c2613c039d76db8', ++ yParity: 1, ++ }) +``` diff --git a/.changeset/v1-remove-tempo-address.md b/.changeset/v1-remove-tempo-address.md new file mode 100644 index 00000000..48e9734c --- /dev/null +++ b/.changeset/v1-remove-tempo-address.md @@ -0,0 +1,12 @@ +--- +'ox': major +--- + +Removed the `TempoAddress` module and its `tempox`-prefixed address format. All Tempo modules now accept plain hex `Address.Address` values; remove any `TempoAddress.format` / `TempoAddress.parse` / `TempoAddress.resolve` calls at the boundary. The `addressType` type parameter has also been dropped from `Call`, `TxEnvelopeTempo`, `KeyAuthorization`, `AuthorizationTempo`, `TransactionRequest`, and `TokenId.TokenIdOrAddress`. + +```diff +- import { TempoAddress } from 'ox/tempo' +- const formatted = TempoAddress.format('0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28') +- const { address } = TempoAddress.parse(formatted) ++ const address = '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28' +``` diff --git a/.changeset/webauthn-authentication-getsignpayload-hash.md b/.changeset/webauthn-authentication-getsignpayload-hash.md new file mode 100644 index 00000000..e02d265b --- /dev/null +++ b/.changeset/webauthn-authentication-getsignpayload-hash.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `webauthn.Authentication.getSignPayload` to honor the documented `hash` option by SHA-256 hashing the returned payload when `hash: true` is passed. diff --git a/.changeset/webauthn-authentication-sign-utf8.md b/.changeset/webauthn-authentication-sign-utf8.md new file mode 100644 index 00000000..3bbfcbc1 --- /dev/null +++ b/.changeset/webauthn-authentication-sign-utf8.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `webauthn.Authentication.sign` to decode `clientDataJSON` bytes as UTF-8 via `Bytes.toString` instead of `String.fromCharCode(...bytes)`, which corrupted non-ASCII payloads and could throw `RangeError` on large inputs. diff --git a/.changeset/webauthn-authentication-verify-at-ed-flags.md b/.changeset/webauthn-authentication-verify-at-ed-flags.md new file mode 100644 index 00000000..1750193c --- /dev/null +++ b/.changeset/webauthn-authentication-verify-at-ed-flags.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `webauthn.Authentication.verify` to reject assertion `authenticatorData` whose flags imply structure not allowed for assertions: the `AT` (attested credential data) bit is now refused, and an `ED` (extension data) bit must be backed by a CBOR-decodable trailing extension map. diff --git a/.changeset/webauthn-authenticator-bytes-first.md b/.changeset/webauthn-authenticator-bytes-first.md new file mode 100644 index 00000000..b75ae141 --- /dev/null +++ b/.changeset/webauthn-authenticator-bytes-first.md @@ -0,0 +1,5 @@ +--- +'ox': minor +--- + +Added an `as: 'Hex' | 'Bytes'` option to `webauthn.Authenticator.getAuthenticatorData`. The bytes path assembles into a single `Uint8Array` directly, while the legacy hex path stays in hex throughout to avoid `Bytes <-> Hex` round trips. `getSignCount` now accepts `Hex` or `Uint8Array`, eliminating the unconditional `Bytes.fromHex` decode for byte-input callers. diff --git a/.changeset/webauthn-registration-verify-attestation-default-docs.md b/.changeset/webauthn-registration-verify-attestation-default-docs.md new file mode 100644 index 00000000..7a66ddf9 --- /dev/null +++ b/.changeset/webauthn-registration-verify-attestation-default-docs.md @@ -0,0 +1,5 @@ +--- +'ox': patch +--- + +Fixed `webauthn.Registration.verify` JSDoc for the `attestation` option to document the actual runtime default of `'none'` (matching `Registration.getOptions`) instead of `'required'`. diff --git a/.changeset/zod-schema-entrypoint.md b/.changeset/zod-schema-entrypoint.md new file mode 100644 index 00000000..8103af45 --- /dev/null +++ b/.changeset/zod-schema-entrypoint.md @@ -0,0 +1,5 @@ +--- +"ox": minor +--- + +Added the `ox/zod` entrypoint with module-scoped Zod schemas, direct integer quantity schemas, account proofs, authorizations, blocks, filters, override schemas, logs, RPC responses, RPC method schemas (`RpcSchema.Eth` / `RpcSchema.Wallet` per-method `params` / `returnType` plus `Request` envelopes), transaction envelopes, transactions, transaction requests, transaction receipts, ABI, and EIP-712 Typed Data. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 6709bd5f..17a1c88b 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -6,7 +6,7 @@ If you want to contribute, but aren't sure where to start, you can create a [new ## Rules -1. Significant changes to the API or implementation must be reviewed before a Pull Request is created. Create a [Feature Request](https://github.com/wevm/ox/discussions/new?category=ideas) first to discuss any API changes or new ideas. +1. Significant changes to the API or implementation must be reviewed before a Pull Request is created. Create a [Feature Request](https://github.com/wevm/ox/discussions/new?category=ideas) first to discuss any API changes or new ideas. 2. Contributors must be humans, not bots. 3. Contributor GitHub Accounts must have at least one non-trivial contribution to another repository. @@ -17,11 +17,11 @@ This guide is intended to help you get started with contributing. By following t 1. [Cloning the repository](#cloning-the-repository) 2. [Installing Node.js and pnpm](#installing-nodejs-and-pnpm) 3. [Installing Foundry & Tempo](#installing-foundry--tempo) -5. [Installing dependencies](#installing-dependencies) -6. [Running the test suite](#running-the-test-suite) -7. [Writing documentation](#writing-documentation) -8. [Submitting a pull request](#submitting-a-pull-request) -9. [Versioning](#versioning) +4. [Installing dependencies](#installing-dependencies) +5. [Running the test suite](#running-the-test-suite) +6. [Writing documentation](#writing-documentation) +7. [Submitting a pull request](#submitting-a-pull-request) +8. [Versioning](#versioning) --- @@ -69,7 +69,7 @@ If the versions are not correct or you don't have Node.js or pnpm installed, dow ### Installing Foundry & Tempo -Ox uses [Foundry](https://book.getfoundry.sh/) & [Tempo](https://github.com/tempoxyz/tempo) for testing. +Ox uses [Foundry](https://book.getfoundry.sh/) & [Tempo](https://github.com/tempoxyz/tempo) for testing. We run a local [Anvil](https://github.com/foundry-rs/foundry/tree/master/anvil) instance against a forked Ethereum node, where we can also use tools like [Forge](https://book.getfoundry.sh/forge/) to deploy test contracts to it. @@ -129,7 +129,7 @@ When adding new features or fixing bugs, it's important to add test cases to cov Documentation is crucial to helping developers of all experience levels use Ox. Ox uses [Vocs](https://vocs.dev) and Markdown for the documentation site (located at [`site`](../site)). To start the site in dev mode, run: ```bash -pnpm docs:dev +pnpm docs:dev ``` Try to keep documentation brief and use plain language so folks of all experience levels can understand. If you think something is unclear or could be explained better, you are welcome to open a pull request. @@ -182,4 +182,3 @@ If your PR is making changes to an area that already has a changeset (e.g. there
↑ back to top
- diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 07b1668d..e79a5079 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -49,7 +49,7 @@ body: id: reproduction attributes: label: Link to Minimal Reproducible Example - description: "Please provide a link that can reproduce the problem: GitHub repo/fork with failing test or [StackBlitz](https://stackblitz.com) for runtime issues or [TypeScript Playground](https://www.typescriptlang.org/play) for type issues. For most issues, you will likely get asked to provide a minimal reproducible example so why not add one now :) If a report is vague (e.g. just snippets, generic error message, screenshot, etc.) and has no reproduction, it will receive a \"Needs Reproduction\" label and be auto-closed." + description: 'Please provide a link that can reproduce the problem: GitHub repo/fork with failing test or [StackBlitz](https://stackblitz.com) for runtime issues or [TypeScript Playground](https://www.typescriptlang.org/play) for type issues. For most issues, you will likely get asked to provide a minimal reproducible example so why not add one now :) If a report is vague (e.g. just snippets, generic error message, screenshot, etc.) and has no reproduction, it will receive a "Needs Reproduction" label and be auto-closed.' placeholder: https://github.com/wevm/ox validations: required: false diff --git a/.github/ISSUE_TEMPLATE/docs_issue.yml b/.github/ISSUE_TEMPLATE/docs_issue.yml index c36d6d0a..60c38228 100644 --- a/.github/ISSUE_TEMPLATE/docs_issue.yml +++ b/.github/ISSUE_TEMPLATE/docs_issue.yml @@ -32,4 +32,3 @@ body: description: Please provide the URL(s) where you found this issue. validations: required: true - diff --git a/.github/README.md b/.github/README.md index c4694ff3..4c4006a4 100644 --- a/.github/README.md +++ b/.github/README.md @@ -46,7 +46,7 @@ The example below demonstrates how to construct, sign, and broadcast a transacti ```ts import { Provider, Secp256k1, TxEnvelopeEip1559, Value } from 'ox' - + // 1. Construct a transaction envelope. const envelope = TxEnvelopeEip1559.from({ chainId: 1, @@ -57,10 +57,10 @@ const envelope = TxEnvelopeEip1559.from({ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', value: Value.fromEther('1'), }) - + // 2. Get the signing payload for the envelope. -const payload = TxEnvelopeEip1559.getSignPayload(envelope) - +const payload = TxEnvelopeEip1559.getSignPayload(envelope) + // 3. Sign the payload with your private key using secp256k1. const signature = Secp256k1.sign({ payload, privateKey: '0x...' }) @@ -91,11 +91,9 @@ Check out the following places for more Ox-related content: - [Gitcoin Grant](https://wagmi.sh/gitcoin) - [wevm.eth](https://etherscan.io/enslookup-search?search=wevm.eth) -

Powered by Vercel - diff --git a/.github/actions/install-dependencies/action.yml b/.github/actions/install-dependencies/action.yml index fd6b6682..d7915eb0 100644 --- a/.github/actions/install-dependencies/action.yml +++ b/.github/actions/install-dependencies/action.yml @@ -1,14 +1,14 @@ -name: "Install dependencies" -description: "Prepare repository and all dependencies" +name: 'Install dependencies' +description: 'Prepare repository and all dependencies' inputs: skip-cache: - description: "Skip dependency cache restore/save" + description: 'Skip dependency cache restore/save' required: false - default: "false" + default: 'false' runs: - using: "composite" + using: 'composite' steps: - name: Set up foundry uses: foundry-rs/foundry-toolchain@8b0419c685ef46cb79ec93fbdc131174afceb730 # v1.6.0 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index aa013c03..bdbc87b8 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -10,4 +10,3 @@ Before creating the pull request, please make sure you do the following: Thank you for contributing to Ox! -----------------------------------------------------------------------> - diff --git a/.github/workflows/changesets.yml b/.github/workflows/changesets.yml index 86c41432..1379801d 100644 --- a/.github/workflows/changesets.yml +++ b/.github/workflows/changesets.yml @@ -1,34 +1,29 @@ name: Changesets on: push: - branches: [main] - -permissions: {} # each job should declare only the permissions it needs + branches: [main, v1] concurrency: group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false + cancel-in-progress: ${{ github.ref == 'refs/heads/main' }} jobs: verify: name: Verify - permissions: - contents: read # checkout repository contents in the reusable workflow + if: github.ref == 'refs/heads/main' uses: ./.github/workflows/verify.yml secrets: inherit changesets: name: Changesets needs: verify - # prevents this action from running on forks - if: github.repository == 'wevm/ox' + if: github.ref == 'refs/heads/main' permissions: - contents: write # commit version/changelog updates to the release pull request - pull-requests: write # create or update the Changesets release pull request + contents: write + id-token: write + pull-requests: write runs-on: ubuntu-latest timeout-minutes: 5 - outputs: - hasChangesets: ${{ steps.changesets.outputs.hasChangesets }} steps: - name: Clone repository @@ -40,76 +35,51 @@ jobs: - name: Install dependencies uses: ./.github/actions/install-dependencies - with: - skip-cache: true # avoid cache poisoning attacks - - name: Create version pull request - id: changesets + - name: PR or publish uses: changesets/action@e0145edc7d9d8679003495b11f87bd8ef63c0cba # v1.5.3 with: title: 'chore: version packages' commit: 'chore: version packages' - version: pnpm changeset:version - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - release: - name: Release - needs: [verify, changesets] - # prevents this action from running on forks - if: github.repository == 'wevm/ox' && needs.changesets.outputs.hasChangesets == 'false' - permissions: - contents: write # create GitHub releases and tags after npm publish - id-token: write # authenticate to npm via trusted publishing - runs-on: ubuntu-latest - timeout-minutes: 5 - - steps: - - name: Clone repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - submodules: 'recursive' - - - name: Install dependencies - uses: ./.github/actions/install-dependencies - with: - skip-cache: true # avoid cache poisoning attacks - - - name: Publish to npm - uses: changesets/action@e0145edc7d9d8679003495b11f87bd8ef63c0cba # v1.5.3 - with: - createGithubReleases: true + createGithubReleases: ${{ github.ref == 'refs/heads/main' }} publish: pnpm changeset:publish + version: pnpm changeset:version env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - canary: - name: Canary release - needs: [verify, changesets] - # prevents this action from running on forks - if: github.repository == 'wevm/ox' && needs.changesets.outputs.hasChangesets == 'true' + beta: + name: Publish beta + if: >- + github.repository == 'wevm/ox' && + github.ref == 'refs/heads/v1' && + github.event.head_commit.message != 'chore: version beta packages' permissions: - contents: read # checkout repository contents - id-token: write # authenticate to npm via trusted publishing + contents: write + id-token: write runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 steps: - name: Clone repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: + fetch-depth: 0 submodules: 'recursive' - name: Install dependencies uses: ./.github/actions/install-dependencies - with: - skip-cache: true # avoid cache poisoning attacks - - name: Publish snapshot packages - continue-on-error: true + - name: Version and publish beta env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - pnpm changeset version --no-git-tag --snapshot canary - pnpm changeset:prepublish - pnpm changeset publish --no-git-tag --snapshot canary --tag canary + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + pnpm exec changeset version + pnpm version:update + if ! git diff --quiet -- .changeset package.json src/CHANGELOG.md src/version.ts; then + git add .changeset package.json src/CHANGELOG.md src/version.ts + git commit --no-verify -m "chore: version beta packages" + git push + fi + pnpm changeset:publish diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml index 681066f1..8f998d8f 100644 --- a/.github/workflows/issue-labeled.yml +++ b/.github/workflows/issue-labeled.yml @@ -17,4 +17,3 @@ jobs: [Minimal reproductions are required](https://antfu.me/posts/why-reproductions-are-required) as they save us a lot of time reproducing your config/environment and issue, and allow us to help you faster. Once a minimal reproduction is added, a team member will confirm it works, then re-open the issue. - diff --git a/.github/workflows/lock-issue.yml b/.github/workflows/lock-issue.yml index da3c5284..3b06157e 100644 --- a/.github/workflows/lock-issue.yml +++ b/.github/workflows/lock-issue.yml @@ -13,5 +13,3 @@ jobs: This issue has been locked since it has been closed for more than 14 days. If you found a concrete bug or regression related to it, please open a new [bug report](https://github.com/wevm/ox/issues/new?template=bug_report.yml) with a reproduction against the latest Ox version. If you have any questions or comments you can create a new [discussion thread](https://github.com/wevm/ox/discussions). - - diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index 3747fe93..9daaefc2 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -14,8 +14,7 @@ jobs: - name: Install dependencies uses: ./.github/actions/install-dependencies - - name: Prepublish + - name: Prerelease run: | - cd src && pnpm version prerelease --preid $(git rev-parse --short=7 HEAD) && cd .. - pnpm changeset:prepublish - pnpx pkg-pr-new publish --pnpm --compact './src' + pnpm exec zile publish:prepare + pnpx pkg-pr-new publish --pnpm diff --git a/.github/workflows/prune-tags.yml b/.github/workflows/prune-tags.yml index 3170cb75..4a0c68f3 100644 --- a/.github/workflows/prune-tags.yml +++ b/.github/workflows/prune-tags.yml @@ -2,7 +2,7 @@ name: Prune NPM tags on: workflow_dispatch: schedule: - - cron: '0 0 * * *' + - cron: '0 0 * * *' jobs: prune: @@ -11,7 +11,7 @@ jobs: steps: - name: Clone repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: + with: submodules: 'recursive' - name: Setup .npmrc file diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 00000000..e9e9e2b0 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,35 @@ +name: Snapshot +on: + workflow_dispatch: + +jobs: + canary: + name: Release snapshot version + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + timeout-minutes: 5 + + steps: + - name: Clone repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + submodules: 'recursive' + + - name: Install dependencies + uses: ./.github/actions/install-dependencies + + - name: Publish Snapshots + continue-on-error: true + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + snapshot=$(git branch --show-current | tr -cs '[:alnum:]-' '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//') + npm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN" + pnpm clean + pnpm changeset version --no-git-tag --snapshot $snapshot + pnpm exec zile publish:prepare + pnpm changeset publish --no-git-tag --snapshot $snapshot --tag $snapshot + pnpm exec zile publish:post diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 61a8b631..cb50dac3 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Clone repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: + with: submodules: 'recursive' - name: Install dependencies @@ -24,8 +24,8 @@ jobs: - name: Check types run: pnpm check:types - - name: Check TSDoc - run: pnpm check:tsdoc + - name: Check examples + run: pnpm zile examples:check test-core: name: Test Runtime (core) @@ -34,7 +34,7 @@ jobs: steps: - name: Clone repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: + with: submodules: 'recursive' - name: Install dependencies @@ -42,7 +42,7 @@ jobs: - name: Run tests run: pnpm test --project core --bail=1 --coverage - env: + env: VITE_ANVIL_FORK_URL: ${{ secrets.VITE_ANVIL_FORK_URL }} test-browser: @@ -52,7 +52,7 @@ jobs: steps: - name: Clone repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: + with: submodules: 'recursive' - name: Install dependencies @@ -72,14 +72,14 @@ jobs: # `edge` tracks `tempoxyz/tempo` main and includes unreleased # features the tests depend on (e.g. TIP-1049 admin keys). The # `latest` tag is pinned to released versions and lags behind. - tag: + tag: - edge # - https://rpc.moderato.tempo.xyz steps: - name: Clone repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: + with: submodules: 'recursive' - name: Install dependencies @@ -87,7 +87,7 @@ jobs: - name: Run tests run: pnpm test --project tempo-unit --project tempo --bail=1 --coverage - env: + env: VITE_TEMPO_CREDENTIALS: ${{ secrets.VITE_TEMPO_CREDENTIALS }} VITE_TEMPO_TAG: ${{ matrix.tag }} @@ -96,14 +96,14 @@ jobs: # runs-on: ubuntu-latest # strategy: # matrix: - # tempo-env: + # tempo-env: # # - devnet TODO: re-enable. # - testnet # steps: # - name: Clone repository # uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - # with: + # with: # submodules: 'recursive' # - name: Install dependencies @@ -115,13 +115,30 @@ jobs: # VITE_TEMPO_CREDENTIALS: ${{ secrets.VITE_TEMPO_CREDENTIALS }} # VITE_TEMPO_ENV: ${{ matrix.tempo-env }} + fuzz: + name: Fuzz + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Clone repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + submodules: 'recursive' + + - name: Install dependencies + uses: ./.github/actions/install-dependencies + + - name: Run bounded fuzz tests + run: pnpm test:fuzz:ci + vectors: name: Vectors runs-on: ubuntu-latest steps: - name: Clone repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: + with: submodules: 'recursive' - name: Install dependencies diff --git a/.gitignore b/.gitignore index 51093831..f6ba40ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,31 @@ *.map +.bench +.claude/ .DS_Store .attest .env .local .pnpm-store -_esm -_cjs -_types dist coverage node_modules +tasks/ tsconfig.*.tsbuildinfo tsconfig.tsbuildinfo tsdoc.d.tson ox.api.json +erc4337.api.json +tempo.api.json lookup.json config-generated.ts -site/pages/api -site/pages/ercs -site/pages/tempo -site/pages/webauthn -site/pages/glossary +site/.vocs +site/src/pages.gen.ts +site/src/pages/api +site/src/pages/ercs +site/src/pages/tempo +site/src/pages/webauthn +site/src/pages/zod +site/src/pages/glossary tsdoc-metadata.json *.timestamp* diff --git a/.gitmodules b/.gitmodules index d8e58dd1..bab06ca5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "contracts/lib/forge-std"] path = contracts/lib/forge-std - url = git@github.com:foundry-rs/forge-std.git + url = https://github.com/foundry-rs/forge-std.git diff --git a/.npmrc b/.npmrc deleted file mode 100644 index bf827275..00000000 --- a/.npmrc +++ /dev/null @@ -1,3 +0,0 @@ -auto-install-peers=false -link-workspace-packages=true -strict-peer-dependencies=false diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 699ed733..46cef3bd 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["biomejs.biome"] + "recommendations": ["VoidZero.vite-plus-extension-pack"] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 176b21d2..621bb51e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,24 +1,29 @@ { - "editor.defaultFormatter": "biomejs.biome", + "editor.defaultFormatter": "oxc.oxc-vscode", "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file", + "editor.codeActionsOnSave": { + "source.fixAll.oxc": "explicit" + }, + "oxc.fmt.configPath": "./vite.config.ts", "typescript.tsdk": "node_modules/typescript/lib", "typescript.enablePromptUseWorkspaceTsdk": true, "javascript.preferences.autoImportFileExcludePatterns": ["**/index.js"], "typescript.preferences.autoImportFileExcludePatterns": ["**/index.js"], "[json]": { - "editor.defaultFormatter": "biomejs.biome" + "editor.defaultFormatter": "oxc.oxc-vscode" }, "[javascript]": { - "editor.defaultFormatter": "biomejs.biome" + "editor.defaultFormatter": "oxc.oxc-vscode" }, "[javascriptreact]": { - "editor.defaultFormatter": "biomejs.biome" + "editor.defaultFormatter": "oxc.oxc-vscode" }, "[typescript]": { - "editor.defaultFormatter": "biomejs.biome" + "editor.defaultFormatter": "oxc.oxc-vscode" }, "[typescriptreact]": { - "editor.defaultFormatter": "biomejs.biome" + "editor.defaultFormatter": "oxc.oxc-vscode" }, "[markdown]": { "editor.defaultFormatter": "yzhang.markdown-all-in-one" diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..3e94c91b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,130 @@ +# ox -- Agent Guidelines + +> **Update after learnings or mistakes** -- when a correction, new convention, or hard-won lesson emerges during development, append it to the relevant section of this file immediately. AGENTS.md is the source of truth for project conventions and should grow as the project does. + +## TypeScript Conventions + +- **Exact optional properties** -- `exactOptionalPropertyTypes` is enabled in tsconfig. Optional properties must include `| undefined` in their type if they can be assigned `undefined` (e.g. `foo?: string | undefined`, not `foo?: string`). +- **No unchecked indexed reads** -- `noUncheckedIndexedAccess` is enabled. Narrow indexed reads before use, or make the invariant obvious with the smallest possible assertion. +- **`readonly` arrays** -- use `readonly T[]` for array types in type definitions. +- **Existing `readonly` properties are fine** -- ox has DOM-shaped WebAuthn types, type snapshots, and inference-heavy literals that intentionally preserve `readonly` properties. Do not churn them just to satisfy a style preference. +- **`type` over `interface` by default** -- use `type` for project-owned shapes. Ambient declarations and DOM-shaped compatibility types may use `interface`. +- **`.js` extensions** -- all relative source imports include `.js` for ESM compatibility. +- **Follow local import style** -- ox uses both namespace imports and named internal imports. Match the surrounding file instead of mass-converting import lists. +- **Zod import aliases** -- import `zod/mini` as `z`, and import zod module namespaces as `z_` (for example, `import * as z_Hex from '../Hex.js'`). +- **Classes for errors only** -- all other APIs use functions and plain data. +- **Errors live next to the code that throws them** -- module-specific failure classes live inside the module that owns the failure mode. Place each error class near the bottom of the module so the public functions and types are what the reader sees first. Set `name` to the namespaced form (`'Hex.InvalidHexValueError'`, `'SignatureEnvelope.VerificationError'`, etc.). +- **No enums** -- use union types or `as const` objects for fixed sets. +- **camelCase constants** -- prefer `camelCase` for local constants unless the surrounding file already uses protocol-style uppercase names for numeric constants. +- **`const` generic modifier** -- use to preserve literal types for full inference. +- **Options default `= {}`** -- use `options: Options = {}` not `options?: Options`. +- **Namespace params and return types** -- place function parameter, return, and error types in a `declare namespace` matching the function name (e.g. `from.Options`, `serialize.ErrorType`). Do not lift the params type to a sibling export unless the surrounding module already has a shared type. +- **`options` over `args`** -- use `options` for typed option bags. Use domain nouns only when the parameter is not an options bag. +- **Minimal variable names** -- prefer short, obvious names. Use `options` not `serializeOptions`, `fn` not `callbackFunction`, etc. Context makes meaning clear. +- **No redundant type annotations** -- if the return type of a function already covers it, do not annotate intermediate variables. Let the return type do the work. +- **No inline object types on locals** -- when a local variable needs an explicit object-type annotation, declare a named `type` on the line directly above and reference it. +- **Return directly** -- do not declare a variable just to return it. Use `return { ... }` unless the variable is needed for reuse or readability. +- **IIFE expressions for fallible local derivations** -- when a local needs `try`/`catch` to parse or normalize a value, prefer an IIFE expression over `let value: T` followed by assignment inside `try`. +- **Skip braces for single-statement blocks** -- omit `{}` for single-statement `if`, `for`, etc., when the surrounding file follows that style. +- **No section separator comments** -- do not use `// ---` or `// ===` divider comments. Let JSDoc and whitespace provide structure. +- **Static imports by default** -- use static `import` declarations. Dynamic imports are reserved for real runtime boundaries already present in ox, such as worker or WASM loading. +- **Minimize `as any`** -- avoid new `as any` where a safer assertion is practical, but do not mass-rewrite existing crypto, tuple, and inference glue that already relies on it. +- **Destructure when accessing multiple properties** -- prefer `const { a, b } = options` over repeated `options.a`, `options.b`. +- **Read from `options.x` when normalizing a single field** -- when transforming exactly one option into a local of the same name, read it directly from `options` instead of destructuring and inventing a second name. +- **Hex helpers over ad hoc conversion** -- use ox helpers like `Hex.fromNumber`, `Hex.toBytes`, `Bytes.fromHex`, `Value.fromGwei`, etc. instead of open-coded conversions. +- **Use ox branded types** -- prefer existing ox types such as `Hex.Hex`, `Bytes.Bytes`, and `Address.Address` over raw template literal types when the branded module type exists. +- **Keep property order readable** -- preserve the local ordering style. Do not alphabetize arrays, RLP tuples, ABI parameters, transaction fields, or other order-sensitive wire shapes. + +## Type Inference Conventions + +- **Preserve literals** -- use `const` generics and narrow helper signatures when an API should preserve literal inputs. +- **Type tests in `.test-d.ts`** -- use Vitest's `expectTypeOf` in colocated `.test-d.ts` files to assert generic inference works. Type tests are first-class; write them alongside implementation. +- **Snapshot inferred public types** -- use `.snap-d.ts` when the repo's existing type snapshot pattern fits the change. +- **No `any` leakage** -- user-facing callback, return, and option types should not leak `any` unless the surrounding API already intentionally does. +- **Type inference after every feature** -- after implementing any feature, check if new types can be narrowed. Add or update type tests alongside behavioral tests when public inference changes. + +## API Conventions + +- **Stateless module APIs** -- public APIs are module namespaces full of functions and types. Do not introduce stateful classes for normal library behavior. +- **Public entrypoint docs** -- when adding a public module or export, update `src/index.ts` with the module export and TSDoc block. +- **Package exports are generated** -- run `pnpm exports:update` only when intentionally adding, removing, or renaming public subpath exports. +- **Keep public APIs lean** -- avoid exposing options for values the library can derive from existing inputs. +- **Wire formats stay explicit** -- serialization, RPC, RLP, ABI, and transaction-envelope code should keep wire-order and field-shape decisions visible at the call site. +- **Internal helpers stay internal** -- keep helper modules under `internal/` unless they are part of the public API. + +## Documentation Conventions + +- **TSDoc on public exports** -- every exported public function, type, and constant gets a TSDoc comment. Type properties get TSDoc when they are part of the public surface. +- **Doc-driven API changes** -- write or update the TSDoc before or alongside the implementation, not as an afterthought. +- **Examples should be small** -- public examples should show the minimum useful shape and avoid unrelated setup. +- **Source docs first** -- public API documentation usually belongs in TSDoc near the exported source. +- **Site pages** -- human guides live under `site/src/pages/`. +- **Generated docs** -- `site/src/pages/api`, `site/src/pages/ercs`, `site/src/pages/tempo`, `site/src/pages/webauthn`, `site/src/pages/glossary`, and `site/src/pages.gen.ts` are generated outputs. Do not edit them by hand unless explicitly requested. +- **Check TSDoc when touching docs** -- run `pnpm check:tsdoc` after changing public comments or examples. +- **SEO descriptions are auto-derived** -- every generated docs page emits a `description` frontmatter (used for `` and OG images), targeting 5-15 words. It is derived from the TSDoc summary (markdown stripped, first paragraph, clamped). Add an optional `@description` TSDoc block tag to a function/namespace/schema to override the auto-derived text with hand-written SEO copy. Hand-written site pages should set their own `description` frontmatter (or a `# Title [description]` heading). + +## Type Conventions + +- **No eager type definitions** -- do not extract a named type until it is used in more than one place or makes a difficult local shape easier to read. +- **Shared domain types live near their module** -- keep reusable public types in the module that owns the domain concept. +- **Error unions live in namespaces** -- exported function error unions should live in that function's namespace as `ErrorType`. + +## Abstraction Conventions + +- **Prefer duplication over the wrong abstraction** -- duplicated code with a clear bug-fix burden is better than a bad abstraction that is scary to change. +- **Do not abstract until the commonalities scream** -- wait for 3+ concrete use cases where the right abstraction becomes obvious. Do not abstract for 1-2 instances. +- **Optimize for change** -- code that is easy to change beats code that is cleverly DRY. We do not know future requirements. +- **No flags or mode parameters** -- if an abstraction needs `if` branches or boolean params to handle different call sites, it is usually the wrong abstraction. Inline it. +- **Start concrete, extract later** -- begin inline. Extract only when a clear pattern emerges across multiple real usages. + +## Testing Conventions + +- **Use `pnpm test` for tests** -- run tests through package scripts, not `vitest` directly. +- **Target the relevant project** -- prefer `pnpm test --project core --bail=1`, `pnpm test --project browser --bail=1`, or `pnpm test --project tempo-unit --project tempo --bail=1` over the full matrix while iterating. +- **Colocate tests** -- unit tests live beside their modules in `src/**/_test/*.test.ts`. +- **Wrap function exports in `describe`** -- every test file targets one or more exported functions; each function gets its own `describe('functionName', () => { ... })` block. +- **Inline snapshots over direct assertions** -- prefer `toMatchInlineSnapshot()` over `.toBe()`, `.toEqual()`, etc. for stable return values. Use `toThrowErrorMatchingInlineSnapshot()` for error assertions. +- **Snapshot whole objects, omit nondeterministic properties** -- destructure out nondeterministic fields and snapshot the rest, rather than cherry-picking individual fields to assert. +- **Browser tests use browser suffixes** -- browser-specific behavior uses `*.browser.test.ts` and the `browser` Vitest project. +- **Fuzz tests stay gated** -- fuzz harnesses use `*.fuzz.ts` and run through `pnpm test:fuzz` or `pnpm test:fuzz:ci`; default `pnpm test` should not pick them up. +- **Fuzz regressions become deterministic** -- when a property fails, add the minimized case as a regular `*.test.ts` or vector fixture. +- **Vectors use Bun** -- run vector tests with `pnpm vectors`. +- **Unit and type tests as you go** -- write unit tests and `.test-d.ts` type tests alongside implementation for each public behavior change. + +## Workflow Conventions + +- **Use targeted commands** -- prefer the smallest command that covers the touched behavior. +- **Types** -- run `pnpm check:types` after TypeScript changes. +- **TSDoc** -- run `pnpm check:tsdoc` after public documentation changes. +- **Repo checks** -- run `pnpm check:repo` when package metadata or workspace shape changes. +- **Docs dev server** -- use `pnpm docs:dev` for documentation UI work. +- **`pnpm check` mutates** -- it runs `biome check . --fix --unsafe`. Use it only when intentionally applying lint/format fixes. +- **`pnpm format` mutates** -- it runs `biome format --write`. +- **`pnpm exports:update` mutates** -- it rewrites `package.json#exports`. +- **`pnpm docs:gen` and `pnpm docs:build` mutate generated docs output** -- run only when docs generation is part of the task. +- **`pnpm contracts:build` mutates generated contract artifacts** -- it runs Forge and `contracts/scripts/generate-typed-artifacts.ts`. +- **Install hooks can mutate** -- `pnpm install` runs `postinstall`, which initializes submodules, builds contracts, and runs `pnpm dev`. + +## Changeset Conventions + +- **Changesets only for public behavior** -- add or update a changeset when a change affects public API or existing behavior. +- **Update existing changesets first** -- if the branch already has a changeset for the same area, update it instead of adding a duplicate. +- **One sentence, past tense** -- changeset entries are a single sentence written in past tense. +- **Breaking changes include migration shape** -- major changes include a `diff` fence showing the before/after migration shape. + +## Git Conventions + +- **Conventional commits** -- use `feat:`, `fix:`, `refactor:`, `docs:`, `test:`, `chore:` prefixes. Scope is optional (e.g. `feat(abi): add tuple formatter`). +- **Preserve dirty work** -- do not revert, clean, or overwrite existing local changes unless explicitly asked. + +## Learned Workspace Facts + +- **Source layout** -- source lives in `src/`; tests live under `src/**/_test`; docs live in `site`; shared test utilities live in `test`; vectors live in `vectors`; contracts live in `contracts`. +- **Node and pnpm** -- the repo expects Node.js `>=22` and `pnpm@11.0.8`. +- **Generated exports** -- `scripts/exports:update.ts` derives `package.json#exports` from `src/`. It flattens `src/core/.ts` to root package subpaths and ignores test/bench/snapshot files. +- **Generated site pages** -- API/reference pages under `site/src/pages/api`, `site/src/pages/ercs`, `site/src/pages/tempo`, `site/src/pages/webauthn`, and `site/src/pages/glossary` are generated. +- **Contracts submodule** -- `contracts/lib/forge-std` is a submodule path. Treat submodule status changes as user work unless the task is specifically about contracts setup. +- **Secrets are local** -- `.env` is local. Do not print, rewrite, or commit secrets. +- **Docgen export comments** -- `extractNamespaceDocComments` should read the nearest JSDoc on an export declaration. ts-morph can include earlier file-level JSDoc descendants on the first export. +- **Type snapshot config** -- `@ark/attest` 0.16 does not follow root project references. Point `ATTEST_CONFIG.tsconfig` at `test/tsconfig.json`. +- **Node local storage** -- Node 24+ needs a valid `--localstorage-file` for the `@typescript/vfs` dependency used by attest. diff --git a/biome.json b/biome.json deleted file mode 100644 index 64f2778e..00000000 --- a/biome.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "$schema": "https://biomejs.dev/schemas/2.2.2/schema.json", - "files": { - "includes": [ - "**", - "!**/contracts/", - "!**/contracts/generated.ts", - "!**/test/kzg", - "!**/tsconfig.json", - "!**/tsconfig.*.json" - ] - }, - "assist": { "actions": { "source": { "organizeImports": "on" } } }, - "formatter": { - "enabled": true, - "indentStyle": "space", - "indentWidth": 2 - }, - "linter": { - "enabled": true, - "rules": { - "recommended": true, - "complexity": { - "noBannedTypes": "off" - }, - "performance": { - "noDelete": "off" - }, - "style": { - "noNonNullAssertion": "off", - "useTemplate": "off" - }, - "suspicious": { - "noAssignInExpressions": "off", - "noExplicitAny": "off", - "noShadowRestrictedNames": "off", - "noTemplateCurlyInString": "off", - "noConsole": { "level": "error", "options": { "allow": ["log"] } } - } - } - }, - "javascript": { - "formatter": { - "quoteStyle": "single", - "trailingCommas": "all", - "semicolons": "asNeeded" - } - }, - "vcs": { - "enabled": true, - "clientKind": "git", - "useIgnoreFile": true - } -} diff --git a/contracts/generated.ts b/contracts/generated.ts index 014ced28..bebeff61 100644 --- a/contracts/generated.ts +++ b/contracts/generated.ts @@ -65,7 +65,7 @@ export const VerifySig = { } ], "bytecode": { - "object": "0x6080604052348015600e575f5ffd5b50610c628061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c806398ef1ed81461002d575b5f5ffd5b610047600480360381019061004291906106d0565b61005d565b6040516100549190610756565b60405180910390f35b5f7f64926492649264926492649264926492649264926492649264926492649264925f1b61008a836104b9565b03610246575f606080848060200190518101906100a79190610826565b8093508194508295505050505f8373ffffffffffffffffffffffffffffffffffffffff16836040516100d991906108f2565b5f604051808303815f865af19150503d805f8114610112576040519150601f19603f3d011682016040523d82523d5f602084013e610117565b606091505b505090505f8873ffffffffffffffffffffffffffffffffffffffff163b0361017a5780610179576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017090610962565b60405180910390fd5b5b631626ba7e60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168873ffffffffffffffffffffffffffffffffffffffff16631626ba7e89856040518363ffffffff1660e01b81526004016101dc9291906109d7565b602060405180830381865afa1580156101f7573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061021b9190610a5a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149450505050506104b2565b5f8473ffffffffffffffffffffffffffffffffffffffff163b111561032d57631626ba7e60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff16631626ba7e85856040518363ffffffff1660e01b81526004016102c79291906109d7565b602060405180830381865afa1580156102e2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103069190610a5a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161490506104b2565b6041825114610371576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036890610af5565b60405180910390fd5b6103796104d4565b8290505f8160016003811061039157610390610b13565b5b602002015190505f826002600381106103ad576103ac610b13565b5b602002015190505f856040815181106103c9576103c8610b13565b5b602001015160f81c60f81b60f81c9050601b8160ff16141580156103f15750601c8160ff1614155b15610431576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042890610bb0565b60405180910390fd5b8773ffffffffffffffffffffffffffffffffffffffff166001888386866040515f815260200160405260405161046a9493929190610be9565b6020604051602081039080840390855afa15801561048a573d5f5f3e3d5ffd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff16149450505050505b9392505050565b5f6020825110156104c8575f5ffd5b81518201519050919050565b6040518060600160405280600390602082028036833780820191505090505090565b5f604051905090565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61053082610507565b9050919050565b61054081610526565b811461054a575f5ffd5b50565b5f8135905061055b81610537565b92915050565b5f819050919050565b61057381610561565b811461057d575f5ffd5b50565b5f8135905061058e8161056a565b92915050565b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6105e28261059c565b810181811067ffffffffffffffff82111715610601576106006105ac565b5b80604052505050565b5f6106136104f6565b905061061f82826105d9565b919050565b5f67ffffffffffffffff82111561063e5761063d6105ac565b5b6106478261059c565b9050602081019050919050565b828183375f83830152505050565b5f61067461066f84610624565b61060a565b9050828152602081018484840111156106905761068f610598565b5b61069b848285610654565b509392505050565b5f82601f8301126106b7576106b6610594565b5b81356106c7848260208601610662565b91505092915050565b5f5f5f606084860312156106e7576106e66104ff565b5b5f6106f48682870161054d565b935050602061070586828701610580565b925050604084013567ffffffffffffffff81111561072657610725610503565b5b610732868287016106a3565b9150509250925092565b5f8115159050919050565b6107508161073c565b82525050565b5f6020820190506107695f830184610747565b92915050565b5f61077982610507565b9050919050565b6107898161076f565b8114610793575f5ffd5b50565b5f815190506107a481610780565b92915050565b8281835e5f83830152505050565b5f6107ca6107c584610624565b61060a565b9050828152602081018484840111156107e6576107e5610598565b5b6107f18482856107aa565b509392505050565b5f82601f83011261080d5761080c610594565b5b815161081d8482602086016107b8565b91505092915050565b5f5f5f6060848603121561083d5761083c6104ff565b5b5f61084a86828701610796565b935050602084015167ffffffffffffffff81111561086b5761086a610503565b5b610877868287016107f9565b925050604084015167ffffffffffffffff81111561089857610897610503565b5b6108a4868287016107f9565b9150509250925092565b5f81519050919050565b5f81905092915050565b5f6108cc826108ae565b6108d681856108b8565b93506108e68185602086016107aa565b80840191505092915050565b5f6108fd82846108c2565b915081905092915050565b5f82825260208201905092915050565b7f5369676e617475726556616c696461746f723a206465706c6f796d656e7400005f82015250565b5f61094c601e83610908565b915061095782610918565b602082019050919050565b5f6020820190508181035f83015261097981610940565b9050919050565b61098981610561565b82525050565b5f82825260208201905092915050565b5f6109a9826108ae565b6109b3818561098f565b93506109c38185602086016107aa565b6109cc8161059c565b840191505092915050565b5f6040820190506109ea5f830185610980565b81810360208301526109fc818461099f565b90509392505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610a3981610a05565b8114610a43575f5ffd5b50565b5f81519050610a5481610a30565b92915050565b5f60208284031215610a6f57610a6e6104ff565b5b5f610a7c84828501610a46565b91505092915050565b7f5369676e617475726556616c696461746f72237265636f7665725369676e65725f8201527f3a20696e76616c6964207369676e6174757265206c656e677468000000000000602082015250565b5f610adf603a83610908565b9150610aea82610a85565b604082019050919050565b5f6020820190508181035f830152610b0c81610ad3565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f5369676e617475726556616c696461746f72237265636f7665725369676e65725f8201527f3a20696e76616c6964207369676e617475726520762076616c75650000000000602082015250565b5f610b9a603b83610908565b9150610ba582610b40565b604082019050919050565b5f6020820190508181035f830152610bc781610b8e565b9050919050565b5f60ff82169050919050565b610be381610bce565b82525050565b5f608082019050610bfc5f830187610980565b610c096020830186610bda565b610c166040830185610980565b610c236060830184610980565b9594505050505056fea26469706673582212202129bba2dd4e24d8e6d4cfcc28d4fe35910091ca42140981d277bef20a8fe3a264736f6c634300081d0033", + "object": "0x6080604052348015600e575f5ffd5b50610c628061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c806398ef1ed81461002d575b5f5ffd5b610047600480360381019061004291906106d0565b61005d565b6040516100549190610756565b60405180910390f35b5f7f64926492649264926492649264926492649264926492649264926492649264925f1b61008a836104b9565b03610246575f606080848060200190518101906100a79190610826565b8093508194508295505050505f8373ffffffffffffffffffffffffffffffffffffffff16836040516100d991906108f2565b5f604051808303815f865af19150503d805f8114610112576040519150601f19603f3d011682016040523d82523d5f602084013e610117565b606091505b505090505f8873ffffffffffffffffffffffffffffffffffffffff163b0361017a5780610179576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017090610962565b60405180910390fd5b5b631626ba7e60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168873ffffffffffffffffffffffffffffffffffffffff16631626ba7e89856040518363ffffffff1660e01b81526004016101dc9291906109d7565b602060405180830381865afa1580156101f7573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061021b9190610a5a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149450505050506104b2565b5f8473ffffffffffffffffffffffffffffffffffffffff163b111561032d57631626ba7e60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168473ffffffffffffffffffffffffffffffffffffffff16631626ba7e85856040518363ffffffff1660e01b81526004016102c79291906109d7565b602060405180830381865afa1580156102e2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103069190610a5a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161490506104b2565b6041825114610371576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036890610af5565b60405180910390fd5b6103796104d4565b8290505f8160016003811061039157610390610b13565b5b602002015190505f826002600381106103ad576103ac610b13565b5b602002015190505f856040815181106103c9576103c8610b13565b5b602001015160f81c60f81b60f81c9050601b8160ff16141580156103f15750601c8160ff1614155b15610431576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042890610bb0565b60405180910390fd5b8773ffffffffffffffffffffffffffffffffffffffff166001888386866040515f815260200160405260405161046a9493929190610be9565b6020604051602081039080840390855afa15801561048a573d5f5f3e3d5ffd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff16149450505050505b9392505050565b5f6020825110156104c8575f5ffd5b81518201519050919050565b6040518060600160405280600390602082028036833780820191505090505090565b5f604051905090565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61053082610507565b9050919050565b61054081610526565b811461054a575f5ffd5b50565b5f8135905061055b81610537565b92915050565b5f819050919050565b61057381610561565b811461057d575f5ffd5b50565b5f8135905061058e8161056a565b92915050565b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6105e28261059c565b810181811067ffffffffffffffff82111715610601576106006105ac565b5b80604052505050565b5f6106136104f6565b905061061f82826105d9565b919050565b5f67ffffffffffffffff82111561063e5761063d6105ac565b5b6106478261059c565b9050602081019050919050565b828183375f83830152505050565b5f61067461066f84610624565b61060a565b9050828152602081018484840111156106905761068f610598565b5b61069b848285610654565b509392505050565b5f82601f8301126106b7576106b6610594565b5b81356106c7848260208601610662565b91505092915050565b5f5f5f606084860312156106e7576106e66104ff565b5b5f6106f48682870161054d565b935050602061070586828701610580565b925050604084013567ffffffffffffffff81111561072657610725610503565b5b610732868287016106a3565b9150509250925092565b5f8115159050919050565b6107508161073c565b82525050565b5f6020820190506107695f830184610747565b92915050565b5f61077982610507565b9050919050565b6107898161076f565b8114610793575f5ffd5b50565b5f815190506107a481610780565b92915050565b8281835e5f83830152505050565b5f6107ca6107c584610624565b61060a565b9050828152602081018484840111156107e6576107e5610598565b5b6107f18482856107aa565b509392505050565b5f82601f83011261080d5761080c610594565b5b815161081d8482602086016107b8565b91505092915050565b5f5f5f6060848603121561083d5761083c6104ff565b5b5f61084a86828701610796565b935050602084015167ffffffffffffffff81111561086b5761086a610503565b5b610877868287016107f9565b925050604084015167ffffffffffffffff81111561089857610897610503565b5b6108a4868287016107f9565b9150509250925092565b5f81519050919050565b5f81905092915050565b5f6108cc826108ae565b6108d681856108b8565b93506108e68185602086016107aa565b80840191505092915050565b5f6108fd82846108c2565b915081905092915050565b5f82825260208201905092915050565b7f5369676e617475726556616c696461746f723a206465706c6f796d656e7400005f82015250565b5f61094c601e83610908565b915061095782610918565b602082019050919050565b5f6020820190508181035f83015261097981610940565b9050919050565b61098981610561565b82525050565b5f82825260208201905092915050565b5f6109a9826108ae565b6109b3818561098f565b93506109c38185602086016107aa565b6109cc8161059c565b840191505092915050565b5f6040820190506109ea5f830185610980565b81810360208301526109fc818461099f565b90509392505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610a3981610a05565b8114610a43575f5ffd5b50565b5f81519050610a5481610a30565b92915050565b5f60208284031215610a6f57610a6e6104ff565b5b5f610a7c84828501610a46565b91505092915050565b7f5369676e617475726556616c696461746f72237265636f7665725369676e65725f8201527f3a20696e76616c6964207369676e6174757265206c656e677468000000000000602082015250565b5f610adf603a83610908565b9150610aea82610a85565b604082019050919050565b5f6020820190508181035f830152610b0c81610ad3565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f5369676e617475726556616c696461746f72237265636f7665725369676e65725f8201527f3a20696e76616c6964207369676e617475726520762076616c75650000000000602082015250565b5f610b9a603b83610908565b9150610ba582610b40565b604082019050919050565b5f6020820190508181035f830152610bc781610b8e565b9050919050565b5f60ff82169050919050565b610be381610bce565b82525050565b5f608082019050610bfc5f830187610980565b610c096020830186610bda565b610c166040830185610980565b610c236060830184610980565b9594505050505056fea26469706673582212209109586a683feac2580e75fe8e500db062fae5d1ff962674086c47959962d34764736f6c63430008210033", "sourceMap": "285:2507:0:-:0;;;;;;;;;;;;;;;;;;;", "linkReferences": {} } @@ -118,7 +118,7 @@ export const NonConformingEvents = { } ], "bytecode": { - "object": "0x6080604052348015600e575f5ffd5b506101e78061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063a9059cbb1461002d575b5f5ffd5b6100476004803603810190610042919061012e565b610049565b005b3373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef838360405161009192919061018a565b60405180910390a25050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100ca826100a1565b9050919050565b6100da816100c0565b81146100e4575f5ffd5b50565b5f813590506100f5816100d1565b92915050565b5f819050919050565b61010d816100fb565b8114610117575f5ffd5b50565b5f8135905061012881610104565b92915050565b5f5f604083850312156101445761014361009d565b5b5f610151858286016100e7565b92505060206101628582860161011a565b9150509250929050565b610175816100c0565b82525050565b610184816100fb565b82525050565b5f60408201905061019d5f83018561016c565b6101aa602083018461017b565b939250505056fea26469706673582212202e493b13b94ee161ebf7e3630f602931207c763465d25d279e96f59a65c2f8e364736f6c634300081d0033", + "object": "0x6080604052348015600e575f5ffd5b506101e78061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063a9059cbb1461002d575b5f5ffd5b6100476004803603810190610042919061012e565b610049565b005b3373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef838360405161009192919061018a565b60405180910390a25050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100ca826100a1565b9050919050565b6100da816100c0565b81146100e4575f5ffd5b50565b5f813590506100f5816100d1565b92915050565b5f819050919050565b61010d816100fb565b8114610117575f5ffd5b50565b5f8135905061012881610104565b92915050565b5f5f604083850312156101445761014361009d565b5b5f610151858286016100e7565b92505060206101628582860161011a565b9150509250929050565b610175816100c0565b82525050565b610184816100fb565b82525050565b5f60408201905061019d5f83018561016c565b6101aa602083018461017b565b939250505056fea264697066735822122008a236c6ee950bd6c50a565d706bfeed727632540a5c0617ff5a127d3b046d4b64736f6c63430008210033", "sourceMap": "64:296:5:-:0;;;;;;;;;;;;;;;;;;;", "linkReferences": {} } @@ -160,7 +160,7 @@ export const Events = { } ], "bytecode": { - "object": "0x6080604052348015600e575f5ffd5b506101578061001c5f395ff3fe60806040526004361061001d575f3560e01c80636146195414610021575b5f5ffd5b61002961002b565b005b3373ffffffffffffffffffffffffffffffffffffffff167f7b2cff6dbed2a9cdb935eb6c46afadba8c4436a7aef48222ff62fce1ece4fcf3345f36604051610075939291906100f1565b60405180910390a2565b5f819050919050565b6100918161007f565b82525050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f6100d08385610097565b93506100dd8385846100a7565b6100e6836100b5565b840190509392505050565b5f6040820190506101045f830186610088565b81810360208301526101178184866100c5565b905094935050505056fea2646970667358221220aace77a9470f9d20993332839954dfc6e3d33444399a5064bf51004bcbad317364736f6c634300081d0033", + "object": "0x6080604052348015600e575f5ffd5b506101578061001c5f395ff3fe60806040526004361061001d575f3560e01c80636146195414610021575b5f5ffd5b61002961002b565b005b3373ffffffffffffffffffffffffffffffffffffffff167f7b2cff6dbed2a9cdb935eb6c46afadba8c4436a7aef48222ff62fce1ece4fcf3345f36604051610075939291906100f1565b60405180910390a2565b5f819050919050565b6100918161007f565b82525050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f6100d08385610097565b93506100dd8385846100a7565b6100e6836100b5565b840190509392505050565b5f6040820190506101045f830186610088565b81810360208301526101178184866100c5565b905094935050505056fea2646970667358221220027fdd8a1166f9f9acb1137726252a1ae390dd3b60c37573e1080a3dee98e10b64736f6c63430008210033", "sourceMap": "64:203:4:-:0;;;;;;;;;;;;;;;;;;;", "linkReferences": {} } @@ -348,7 +348,7 @@ export const Errors = { } ], "bytecode": { - "object": "0x6080604052348015600e575f5ffd5b506107f78061001c5f395ff3fe608060405234801561000f575f5ffd5b50600436106100f3575f3560e01c80638de18b9111610095578063c66cf13311610064578063c66cf1331461018d578063d44de866146101ab578063eb1aba20146101c9578063efbbf995146101d3576100f3565b80638de18b9114610165578063940b88021461016f5780639f55870914610179578063a997732e14610183576100f3565b80634a9bc278116100d15780634a9bc278146101295780634adac6eb14610133578063699389ca1461015157806388452b851461015b576100f3565b806304696152146100f75780631515d7681461010157806324db9ba01461010b575b5f5ffd5b6100ff6101dd565b005b6101096101ed565b005b610113610258565b60405161012091906104e7565b60405180910390f35b61013161027a565b005b61013b610285565b60405161014891906104e7565b60405180910390f35b6101596102c7565b005b6101636102d2565b005b61016d61030d565b005b610177610378565b005b6101816103b3565b005b61018b6103ee565b005b610195610429565b6040516101a291906104e7565b60405180910390f35b6101b361044b565b6040516101c091906104e7565b60405180910390f35b6101d161048d565b005b6101db61049d565b005b5f6101eb576101ea610500565b5b565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001604581525060456040517fdb731cf400000000000000000000000000000000000000000000000000000000815260040161024f929190610644565b60405180910390fd5b5f5f604590505f5f90505f818361026f91906106d8565b905080935050505090565b5f610283575f5ffd5b565b5f5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505f600190505f81836102bc9190610708565b905080935050505090565b5f6102d0575f5ffd5b565b6040517ff90063980000000000000000000000000000000000000000000000000000000081526004016103049061073b565b60405180910390fd5b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001604581525060456040517fdb731cf400000000000000000000000000000000000000000000000000000000815260040161036f929190610644565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103aa906107a3565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103e5906107a3565b60405180910390fd5b6040517ff90063980000000000000000000000000000000000000000000000000000000081526004016104209061073b565b60405180910390fd5b5f5f604590505f5f90505f818361044091906106d8565b905080935050505090565b5f5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505f600190505f81836104829190610708565b905080935050505090565b5f61049b5761049a610500565b5b565b6040517f67476b9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f819050919050565b6104e1816104cf565b82525050565b5f6020820190506104fa5f8301846104d8565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6105568261052d565b9050919050565b6105668161054c565b82525050565b610575816104cf565b82525050565b604082015f82015161058f5f85018261055d565b5060208201516105a2602085018261056c565b50505050565b5f82825260208201905092915050565b7f62756767657200000000000000000000000000000000000000000000000000005f82015250565b5f6105ec6006836105a8565b91506105f7826105b8565b602082019050919050565b5f819050919050565b5f819050919050565b5f61062e61062961062484610602565b61060b565b6104cf565b9050919050565b61063e81610614565b82525050565b5f6080820190506106575f83018561057b565b8181036040830152610668816105e0565b90506106776060830184610635565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6106e2826104cf565b91506106ed836104cf565b9250826106fd576106fc61067e565b5b828204905092915050565b5f610712826104cf565b915061071d836104cf565b9250828201905080821115610735576107346106ab565b5b92915050565b5f6020820190508181035f830152610752816105e0565b9050919050565b7f54686973206973206120726576657274206d65737361676500000000000000005f82015250565b5f61078d6018836105a8565b915061079882610759565b602082019050919050565b5f6020820190508181035f8301526107ba81610781565b905091905056fea264697066735822122019210d99bf94a8477f12b7f428062f3da7ae7e6c9973f12b2145e978d1a30c1064736f6c634300081d0033", + "object": "0x6080604052348015600e575f5ffd5b506107f78061001c5f395ff3fe608060405234801561000f575f5ffd5b50600436106100f3575f3560e01c80638de18b9111610095578063c66cf13311610064578063c66cf1331461018d578063d44de866146101ab578063eb1aba20146101c9578063efbbf995146101d3576100f3565b80638de18b9114610165578063940b88021461016f5780639f55870914610179578063a997732e14610183576100f3565b80634a9bc278116100d15780634a9bc278146101295780634adac6eb14610133578063699389ca1461015157806388452b851461015b576100f3565b806304696152146100f75780631515d7681461010157806324db9ba01461010b575b5f5ffd5b6100ff6101dd565b005b6101096101ed565b005b610113610258565b60405161012091906104e7565b60405180910390f35b61013161027a565b005b61013b610285565b60405161014891906104e7565b60405180910390f35b6101596102c7565b005b6101636102d2565b005b61016d61030d565b005b610177610378565b005b6101816103b3565b005b61018b6103ee565b005b610195610429565b6040516101a291906104e7565b60405180910390f35b6101b361044b565b6040516101c091906104e7565b60405180910390f35b6101d161048d565b005b6101db61049d565b005b5f6101eb576101ea610500565b5b565b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001604581525060456040517fdb731cf400000000000000000000000000000000000000000000000000000000815260040161024f929190610644565b60405180910390fd5b5f5f604590505f5f90505f818361026f91906106d8565b905080935050505090565b5f610283575f5ffd5b565b5f5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505f600190505f81836102bc9190610708565b905080935050505090565b5f6102d0575f5ffd5b565b6040517ff90063980000000000000000000000000000000000000000000000000000000081526004016103049061073b565b60405180910390fd5b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff168152602001604581525060456040517fdb731cf400000000000000000000000000000000000000000000000000000000815260040161036f929190610644565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103aa906107a3565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103e5906107a3565b60405180910390fd5b6040517ff90063980000000000000000000000000000000000000000000000000000000081526004016104209061073b565b60405180910390fd5b5f5f604590505f5f90505f818361044091906106d8565b905080935050505090565b5f5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505f600190505f81836104829190610708565b905080935050505090565b5f61049b5761049a610500565b5b565b6040517f67476b9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f819050919050565b6104e1816104cf565b82525050565b5f6020820190506104fa5f8301846104d8565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6105568261052d565b9050919050565b6105668161054c565b82525050565b610575816104cf565b82525050565b604082015f82015161058f5f85018261055d565b5060208201516105a2602085018261056c565b50505050565b5f82825260208201905092915050565b7f62756767657200000000000000000000000000000000000000000000000000005f82015250565b5f6105ec6006836105a8565b91506105f7826105b8565b602082019050919050565b5f819050919050565b5f819050919050565b5f61062e61062961062484610602565b61060b565b6104cf565b9050919050565b61063e81610614565b82525050565b5f6080820190506106575f83018561057b565b8181036040830152610668816105e0565b90506106776060830184610635565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6106e2826104cf565b91506106ed836104cf565b9250826106fd576106fc61067e565b5b828204905092915050565b5f610712826104cf565b915061071d836104cf565b9250828201905080821115610735576107346106ab565b5b92915050565b5f6020820190508181035f830152610752816105e0565b9050919050565b7f54686973206973206120726576657274206d65737361676500000000000000005f82015250565b5f61078d6018836105a8565b915061079882610759565b602082019050919050565b5f6020820190508181035f8301526107ba81610781565b905091905056fea26469706673582212205d410a391e05649611303c8a3682e4519420a7c4373ef3616fb9bef0f04e285364736f6c63430008210033", "sourceMap": "64:2024:3:-:0;;;;;;;;;;;;;;;;;;;", "linkReferences": {} } @@ -434,7 +434,7 @@ export const Constructor = { } ], "bytecode": { - "object": "0x608060405234801561000f575f5ffd5b50604051610151380380610151833981810160405281019061003191906100c9565b5050610107565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100658261003c565b9050919050565b6100758161005b565b811461007f575f5ffd5b50565b5f815190506100908161006c565b92915050565b5f819050919050565b6100a881610096565b81146100b2575f5ffd5b50565b5f815190506100c38161009f565b92915050565b5f5f604083850312156100df576100de610038565b5b5f6100ec85828601610082565b92505060206100fd858286016100b5565b9150509250929050565b603e806101135f395ff3fe60806040525f5ffdfea2646970667358221220ffffb9ea97b58311e9036d4e20d4065f80cd556c59bddc668d96b8f9f33b6cce64736f6c634300081d0033", + "object": "0x608060405234801561000f575f5ffd5b50604051610151380380610151833981810160405281019061003191906100c9565b5050610107565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6100658261003c565b9050919050565b6100758161005b565b811461007f575f5ffd5b50565b5f815190506100908161006c565b92915050565b5f819050919050565b6100a881610096565b81146100b2575f5ffd5b50565b5f815190506100c38161009f565b92915050565b5f5f604083850312156100df576100de610038565b5b5f6100ec85828601610082565b92505060206100fd858286016100b5565b9150509250929050565b603e806101135f395ff3fe60806040525f5ffdfea2646970667358221220281b0a06a216dfc53e964ae1d7fbeb5becfbf67331307943c38e8dba2f9b309064736f6c63430008210033", "sourceMap": "64:78:2:-:0;;;91:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;64:78;;88:117:6;197:1;194;187:12;334:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:143::-;753:5;784:6;778:13;769:22;;800:33;827:5;800:33;:::i;:::-;696:143;;;;:::o;845:77::-;882:7;911:5;900:16;;845:77;;;:::o;928:122::-;1001:24;1019:5;1001:24;:::i;:::-;994:5;991:35;981:63;;1040:1;1037;1030:12;981:63;928:122;:::o;1056:143::-;1113:5;1144:6;1138:13;1129:22;;1160:33;1187:5;1160:33;:::i;:::-;1056:143;;;;:::o;1205:507::-;1284:6;1292;1341:2;1329:9;1320:7;1316:23;1312:32;1309:119;;;1347:79;;:::i;:::-;1309:119;1467:1;1492:64;1548:7;1539:6;1528:9;1524:22;1492:64;:::i;:::-;1482:74;;1438:128;1605:2;1631:64;1687:7;1678:6;1667:9;1663:22;1631:64;:::i;:::-;1621:74;;1576:129;1205:507;;;;;:::o;64:78:2:-;;;;;;;", "linkReferences": {} } diff --git a/examples/webauthn-p256/.gitignore b/examples/webauthn-p256/.gitignore deleted file mode 100644 index a547bf36..00000000 --- a/examples/webauthn-p256/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/examples/webauthn-p256/CHANGELOG.md b/examples/webauthn-p256/CHANGELOG.md deleted file mode 100644 index 6335f168..00000000 --- a/examples/webauthn-p256/CHANGELOG.md +++ /dev/null @@ -1,43 +0,0 @@ -# webauthn-p256 - -## 0.0.6 - -### Patch Changes - -- Updated dependencies [[`644b96a`](https://github.com/wevm/ox/commit/644b96a169a118c6f0606eda5354785523ed099b)]: - - ox@0.1.5 - -## 0.0.5 - -### Patch Changes - -- Updated dependencies [[`777fe42`](https://github.com/wevm/ox/commit/777fe4249c5225c676ff690fda58c5fcfb35d1f0)]: - - ox@0.1.4 - -## 0.0.4 - -### Patch Changes - -- Updated dependencies [[`868d431`](https://github.com/wevm/ox/commit/868d4319a8cda77345f85f9f2e88ca786f0c8cfe)]: - - ox@0.1.3 - -## 0.0.3 - -### Patch Changes - -- Updated dependencies [[`f438faf`](https://github.com/wevm/ox/commit/f438fafbd396248283876eba220f4c661c47bfd2)]: - - ox@0.1.2 - -## 0.0.2 - -### Patch Changes - -- Updated dependencies [[`b7de4f2`](https://github.com/wevm/ox/commit/b7de4f2180520fd7f2bf08955df6e676d75db93e)]: - - ox@0.1.1 - -## 0.0.1 - -### Patch Changes - -- Updated dependencies [[`4297bcf`](https://github.com/wevm/ox/commit/4297bcf0acef7f1f208ba3770d679fefa0c2cb8d)]: - - ox@0.1.0 diff --git a/examples/webauthn-p256/index.html b/examples/webauthn-p256/index.html deleted file mode 100644 index 7ff31eb6..00000000 --- a/examples/webauthn-p256/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - WebAuthnP256 Example - - -

WebAuthnP256 Example

-
- - - diff --git a/examples/webauthn-p256/package.json b/examples/webauthn-p256/package.json deleted file mode 100644 index 56fe92a3..00000000 --- a/examples/webauthn-p256/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "webauthn-p256", - "private": true, - "type": "module", - "scripts": { - "dev": "vite" - }, - "dependencies": { - "ox": "workspace:*", - "react": "^18.3.1", - "react-dom": "^18.3.1" - }, - "devDependencies": { - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@vitejs/plugin-react": "^4.3.1", - "globals": "^15.9.0", - "typescript": "^5.5.3", - "vite": "^5.4.1" - } -} diff --git a/examples/webauthn-p256/public/vite.svg b/examples/webauthn-p256/public/vite.svg deleted file mode 100644 index e7b8dfb1..00000000 --- a/examples/webauthn-p256/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/webauthn-p256/src/App.tsx b/examples/webauthn-p256/src/App.tsx deleted file mode 100644 index ec4d7da0..00000000 --- a/examples/webauthn-p256/src/App.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import { type Hex, Json, PublicKey, WebAuthnP256 } from 'ox' -import { useState } from 'react' - -export function App() { - const [credential, setCredential] = useState() - const [signResponse, setSignResponse] = - useState() - const [verified, setVerified] = useState() - - return ( -
-

Create Credential

-
{ - e.preventDefault() - const formData = new FormData(e.target as HTMLFormElement) - - const credential = await WebAuthnP256.createCredential({ - name: formData.get('name') as string, - }) - setCredential(credential) - }} - > - - -
-
- {credential && ( -
- Credential ID: -
- {credential.id} -
-
- Public Key: -
-
{Json.stringify(credential.publicKey, null, 2)}
- Public Key (serialized): -
-
{PublicKey.toHex(credential.publicKey)}
-
- )} -
-
-

Sign

-
-
{ - e.preventDefault() - const formData = new FormData(e.target as HTMLFormElement) - const challenge = formData.get('challenge') as Hex.Hex - - const response = await WebAuthnP256.sign({ - credentialId: credential?.id, - challenge, - }) - setSignResponse(response) - }} - > - Challenge: -
- - -
-
- {signResponse && ( -
- Signature: -
-
{Json.stringify(signResponse.signature, null, 2)}
-
- Metadata: -
-
{Json.stringify(signResponse.metadata, null, 2)}
-
- )} - {signResponse && credential && ( -
-
-
-

Verify

-
{ - e.preventDefault() - - setVerified(undefined) - - const formData = new FormData(e.target as HTMLFormElement) - const challenge = formData.get('challenge') as Hex.Hex - const signature = Json.parse( - formData.get('signature') as string, - ) - const metadata = Json.parse(formData.get('webauthn') as string) - - const verified = WebAuthnP256.verify({ - challenge, - publicKey: credential.publicKey, - signature, - metadata, - }) - - setVerified(verified) - }} - > - Challenge: -
- -
-
- Signature: -
-