From 79d6dab1d86f8226542b1d3e7c6cebe119801049 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Fri, 8 May 2026 08:39:08 +1000
Subject: [PATCH 001/192] wip: v1
Amp-Thread-ID: https://ampcode.com/threads/T-019e0423-2129-734a-8c3f-314d3aab0bbd
---
.gitignore | 3 -
.npmrc | 4 -
contracts/generated.ts | 10 +-
examples/webauthn-p256/.gitignore | 24 -
examples/webauthn-p256/CHANGELOG.md | 43 -
examples/webauthn-p256/index.html | 13 -
examples/webauthn-p256/package.json | 21 -
examples/webauthn-p256/public/vite.svg | 1 -
examples/webauthn-p256/src/App.tsx | 143 --
examples/webauthn-p256/src/main.tsx | 9 -
examples/webauthn-p256/src/vite-env.d.ts | 1 -
examples/webauthn-p256/tsconfig.app.json | 24 -
examples/webauthn-p256/tsconfig.json | 7 -
examples/webauthn-p256/tsconfig.node.json | 22 -
examples/webauthn-p256/vite.config.ts | 7 -
package.json | 710 ++++++-
pnpm-lock.yaml | 1627 ++++++-----------
pnpm-workspace.yaml | 31 +-
scripts/build-mine-wasm.ts | 98 -
scripts/exports:update.ts | 103 ++
scripts/preconstruct.ts | 54 -
scripts/prepublish.ts | 44 -
scripts/utils/exports.ts | 96 -
.../{update-version.ts => version:update.ts} | 2 +-
site/package.json | 2 +-
site/pages/guides/json-rpc.md | 2 +-
src/core/_test/AbiParameters.bench.ts | 794 --------
src/core/_test/Address.bench.ts | 13 -
src/core/_test/Base58.bench.ts | 29 -
src/core/_test/BinaryStateTree.bench.ts | 18 -
src/core/_test/Hex.bench.ts | 62 -
src/core/_test/Kzg.test.ts | 2 +-
src/core/_test/Rlp.bench.ts | 252 ---
src/jsr.json | 2 +-
src/package.json | 56 -
src/tsconfig.json | 15 +
test/kzg.ts | 2 +-
test/tsconfig.json | 27 +
tsconfig.base.json | 50 +-
tsconfig.build.json | 16 -
tsconfig.json | 25 +-
41 files changed, 1415 insertions(+), 3049 deletions(-)
delete mode 100644 .npmrc
delete mode 100644 examples/webauthn-p256/.gitignore
delete mode 100644 examples/webauthn-p256/CHANGELOG.md
delete mode 100644 examples/webauthn-p256/index.html
delete mode 100644 examples/webauthn-p256/package.json
delete mode 100644 examples/webauthn-p256/public/vite.svg
delete mode 100644 examples/webauthn-p256/src/App.tsx
delete mode 100644 examples/webauthn-p256/src/main.tsx
delete mode 100644 examples/webauthn-p256/src/vite-env.d.ts
delete mode 100644 examples/webauthn-p256/tsconfig.app.json
delete mode 100644 examples/webauthn-p256/tsconfig.json
delete mode 100644 examples/webauthn-p256/tsconfig.node.json
delete mode 100644 examples/webauthn-p256/vite.config.ts
delete mode 100644 scripts/build-mine-wasm.ts
create mode 100644 scripts/exports:update.ts
delete mode 100644 scripts/preconstruct.ts
delete mode 100644 scripts/prepublish.ts
delete mode 100644 scripts/utils/exports.ts
rename scripts/{update-version.ts => version:update.ts} (89%)
delete mode 100644 src/core/_test/AbiParameters.bench.ts
delete mode 100644 src/core/_test/Address.bench.ts
delete mode 100644 src/core/_test/Base58.bench.ts
delete mode 100644 src/core/_test/BinaryStateTree.bench.ts
delete mode 100644 src/core/_test/Hex.bench.ts
delete mode 100644 src/core/_test/Rlp.bench.ts
delete mode 100644 src/package.json
create mode 100644 src/tsconfig.json
create mode 100644 test/tsconfig.json
delete mode 100644 tsconfig.build.json
diff --git a/.gitignore b/.gitignore
index 51093831..6d88c5b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,9 +4,6 @@
.env
.local
.pnpm-store
-_esm
-_cjs
-_types
dist
coverage
node_modules
diff --git a/.npmrc b/.npmrc
deleted file mode 100644
index 84cc0246..00000000
--- a/.npmrc
+++ /dev/null
@@ -1,4 +0,0 @@
-auto-install-peers=false
-link-workspace-packages=true
-provenance=false
-strict-peer-dependencies=false
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
-
-
- {credential && (
-
-
Credential ID:
-
- {credential.id}
-
-
-
Public Key:
-
-
{Json.stringify(credential.publicKey, null, 2)}
-
Public Key (serialized):
-
-
{PublicKey.toHex(credential.publicKey)}
-
- )}
-
-
-
Sign
-
-
-
- {signResponse && (
-
-
Signature:
-
-
{Json.stringify(signResponse.signature, null, 2)}
-
-
Metadata:
-
-
{Json.stringify(signResponse.metadata, null, 2)}
-
- )}
- {signResponse && credential && (
-
- )}
-
-
- )
-}
diff --git a/examples/webauthn-p256/src/main.tsx b/examples/webauthn-p256/src/main.tsx
deleted file mode 100644
index 5e7046ce..00000000
--- a/examples/webauthn-p256/src/main.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import { App } from './App.tsx'
-
-createRoot(document.getElementById('root')!).render(
-
-
- ,
-)
diff --git a/examples/webauthn-p256/src/vite-env.d.ts b/examples/webauthn-p256/src/vite-env.d.ts
deleted file mode 100644
index 11f02fe2..00000000
--- a/examples/webauthn-p256/src/vite-env.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-///
diff --git a/examples/webauthn-p256/tsconfig.app.json b/examples/webauthn-p256/tsconfig.app.json
deleted file mode 100644
index f0a23505..00000000
--- a/examples/webauthn-p256/tsconfig.app.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "compilerOptions": {
- "target": "ES2020",
- "useDefineForClassFields": true,
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
- "module": "ESNext",
- "skipLibCheck": true,
-
- /* Bundler mode */
- "moduleResolution": "bundler",
- "allowImportingTsExtensions": true,
- "isolatedModules": true,
- "moduleDetection": "force",
- "noEmit": true,
- "jsx": "react-jsx",
-
- /* Linting */
- "strict": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "noFallthroughCasesInSwitch": true
- },
- "include": ["src"]
-}
diff --git a/examples/webauthn-p256/tsconfig.json b/examples/webauthn-p256/tsconfig.json
deleted file mode 100644
index 1ffef600..00000000
--- a/examples/webauthn-p256/tsconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "files": [],
- "references": [
- { "path": "./tsconfig.app.json" },
- { "path": "./tsconfig.node.json" }
- ]
-}
diff --git a/examples/webauthn-p256/tsconfig.node.json b/examples/webauthn-p256/tsconfig.node.json
deleted file mode 100644
index 0d3d7144..00000000
--- a/examples/webauthn-p256/tsconfig.node.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "compilerOptions": {
- "target": "ES2022",
- "lib": ["ES2023"],
- "module": "ESNext",
- "skipLibCheck": true,
-
- /* Bundler mode */
- "moduleResolution": "bundler",
- "allowImportingTsExtensions": true,
- "isolatedModules": true,
- "moduleDetection": "force",
- "noEmit": true,
-
- /* Linting */
- "strict": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "noFallthroughCasesInSwitch": true
- },
- "include": ["vite.config.ts"]
-}
diff --git a/examples/webauthn-p256/vite.config.ts b/examples/webauthn-p256/vite.config.ts
deleted file mode 100644
index 36f7f4e1..00000000
--- a/examples/webauthn-p256/vite.config.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import react from '@vitejs/plugin-react'
-import { defineConfig } from 'vite'
-
-// https://vitejs.dev/config/
-export default defineConfig({
- plugins: [react()],
-})
diff --git a/package.json b/package.json
index 8c9a333d..25bcdd28 100644
--- a/package.json
+++ b/package.json
@@ -1,34 +1,25 @@
{
- "name": "ox",
"private": true,
- "type": "module",
"scripts": {
- "bench": "vitest -c ./test/vitest.config.ts bench",
- "bench:types": "TYPES=true vitest -c ./test/vitest.config.ts src/**/*.bench-d.ts",
- "build": "pnpm clean && pnpm build:cjs && pnpm build:esm && pnpm build:types",
- "build:esm": "tsc --project ./tsconfig.build.json --outDir ./src/_esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./src/_esm/package.json",
- "build:cjs": "tsc --project ./tsconfig.build.json --module commonjs --moduleResolution node10 --outDir ./src/_cjs --removeComments --verbatimModuleSyntax false && printf '{\"type\":\"commonjs\"}' > ./src/_cjs/package.json",
- "build:types": "tsc --project ./tsconfig.build.json --declarationDir ./src/_types --emitDeclarationOnly --declaration --declarationMap",
- "changeset:prepublish": "pnpm version:update && pnpm build && tsx scripts/prepublish.ts",
- "changeset:publish": "pnpm changeset:prepublish && changeset publish",
+ "build": "pnpm exports:update && zile",
+ "changeset:publish": "zile publish:prepare && changeset publish && zile publish:post",
"changeset:version": "changeset version && pnpm version:update && pnpm format",
"check": "biome check . --fix --unsafe",
"check:repo": "sherif",
- "check:tsdoc": "eslint src -c scripts/docgen/tsdoc.config.js --ignore-pattern 'src/_esm/**/*.js'",
- "check:types": "tsc --noEmit",
- "clean": "rimraf src/_types src/_esm src/_cjs ./tsconfig.build.tsbuildinfo src/tsconfig.build.tsbuildinfo",
- "contracts:build": "forge build --config-path ./contracts/foundry.toml && tsx contracts/scripts/generate-typed-artifacts.ts",
+ "check:tsdoc": "eslint src -c scripts/docgen/tsdoc.config.js",
+ "check:types": "tsc -b",
+ "contracts:build": "forge build --config-path ./contracts/foundry.toml && node --import tsx contracts/scripts/generate-typed-artifacts.ts",
"deps": "pnpx taze -r",
"deps:ci": "pnpx actions-up",
- "dev": "pnpm preconstruct",
+ "dev": "pnpm exports:update && zile dev",
"docs:dev": "pnpm --filter site dev",
- "docs:extract": "pnpm api-extractor run -c scripts/docgen/api-extractor.json && tsx scripts/docgen/build.ts",
- "docs:gen": "pnpm clean && pnpm build:types && pnpm docs:extract",
+ "docs:extract": "pnpm api-extractor run -c scripts/docgen/api-extractor.json && node --import tsx scripts/docgen/build.ts",
+ "docs:gen": "pnpm build && pnpm docs:extract",
"docs:build": "pnpm docs:gen && pnpm --filter site build",
+ "exports:update": "node --import tsx ./scripts/exports:update.ts",
"knip": "knip --production",
"format": "biome format --write",
- "postinstall": "git submodule update --init --recursive && pnpm contracts:build && pnpm preconstruct",
- "preconstruct": "tsx ./scripts/preconstruct.ts",
+ "postinstall": "git submodule update --init --recursive && pnpm contracts:build && pnpm dev",
"preinstall": "pnpx only-allow pnpm",
"prepare": "pnpm simple-git-hooks",
"size": "size-limit",
@@ -37,15 +28,13 @@
"test:types": "TYPES=true vitest -c ./test/vitest.config.ts",
"vectors": "bun test vectors/**/*.test.ts",
"vectors:generate": "bun vectors/generate.ts",
- "version:update": "tsx ./scripts/update-version.ts"
+ "version:update": "node --import tsx ./scripts/version:update.ts"
},
"devDependencies": {
"@ark/attest": "^0.16.0",
"@biomejs/biome": "^2.2.2",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.7",
- "@ethereumjs/rlp": "^5.0.2",
- "@ethereumjs/util": "^9.0.3",
"@microsoft/api-extractor": "^7.47.7",
"@microsoft/api-extractor-model": "^7.29.6",
"@microsoft/tsdoc": "^0.15.0",
@@ -61,13 +50,11 @@
"eslint": "^9.9.0",
"eslint-plugin-jsdoc": "^50.0.1",
"eslint-plugin-tsdoc": "^0.3.0",
- "ethers": "^6.13.2",
"fs-extra": "^11.2.0",
"knip": "^5.27.2",
- "micro-eth-signer": "^0.15.0",
+ "micro-eth-signer": "^0.18.1",
"playwright": "^1.58.2",
"prool": "~0.2.3",
- "rimraf": "^5.0.10",
"sherif": "^0.11.0",
"simple-git-hooks": "^2.11.1",
"size-limit": "^11.1.4",
@@ -77,12 +64,11 @@
"typescript": "^5.5.4",
"typescript-eslint": "^8.1.0",
"viem": "^2.45.0",
- "vite-tsconfig-paths": "^5.0.1",
"vitest": "^4.0.18",
"vocs": "^1.0.13",
- "web3": "^4.12.1"
+ "zile": "^0.0.25"
},
- "packageManager": "pnpm@10.15.0",
+ "packageManager": "pnpm@11.0.8",
"engines": {
"node": ">=22"
},
@@ -98,7 +84,6 @@
"site/**",
"test/**",
"vectors/**",
- "src/package.json",
"tsdoc.config.js"
],
"ignoreBinaries": [
@@ -117,41 +102,656 @@
"entry": [
"**/*.{bench,bench-d,test,test-d,spec}.?(c|m)[jt]s?(x)"
]
- },
- "workspaces": {
- "src": {
- "entry": [
- "index.ts!",
- "trusted-setups/index.ts!",
- "window/index.ts!"
- ]
- }
}
},
- "pnpm": {
- "overrides": {
- "viem>ox": "npm:ox@0.11.1",
- "@microsoft/api-extractor>typescript": "^5.5.4",
- "hono@<4.2.7": ">=4.2.7",
- "ws@>=8.0.0 <8.17.1": ">=8.17.1",
- "hono@<4.5.8": ">=4.5.8",
- "micromatch@<4.0.8": ">=4.0.8",
- "webpack@>=5.0.0-alpha.0 <5.94.0": ">=5.94.0",
- "rollup@>=4.0.0 <4.22.4": ">=4.22.4",
- "hono@<4.6.5": ">=4.6.5"
- },
- "patchedDependencies": {}
- },
"size-limit": [
{
"name": "import * from 'ox'",
- "path": "./src/_esm/index.js",
+ "path": "./dist/index.js",
"import": "*"
},
{
"name": "import { Hex } from 'ox'; console.log(Hex.assert)",
- "path": "./src/_esm/index.js",
+ "path": "./dist/index.js",
"import": "{ Hex.assert }"
}
- ]
+ ],
+ "[!start-pkg]": "",
+ "name": "ox",
+ "description": "Ethereum Standard Library",
+ "type": "module",
+ "version": "0.14.12",
+ "main": "./dist/index.js",
+ "sideEffects": false,
+ "license": "MIT",
+ "homepage": "https://wevm.dev",
+ "repository": "wevm/ox",
+ "authors": [
+ "awkweb",
+ "jxom"
+ ],
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "keywords": [
+ "ethereum",
+ "standard",
+ "library",
+ "typescript",
+ "evm"
+ ],
+ "files": [
+ "dist",
+ "src"
+ ],
+ "dependencies": {
+ "@adraffy/ens-normalize": "^1.11.0",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "1.9.1",
+ "@noble/hashes": "^1.8.0",
+ "@scure/bip32": "^1.7.0",
+ "@scure/bip39": "^1.6.0",
+ "abitype": "^1.2.3",
+ "eventemitter3": "5.0.1"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ },
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "src": "./src/index.ts",
+ "default": "./dist/index.js"
+ },
+ "./index.docs": {
+ "types": "./dist/index.docs.d.ts",
+ "src": "./src/index.docs.ts",
+ "default": "./dist/index.docs.js"
+ },
+ "./Abi": {
+ "types": "./dist/core/Abi.d.ts",
+ "src": "./src/core/Abi.ts",
+ "default": "./dist/core/Abi.js"
+ },
+ "./AbiConstructor": {
+ "types": "./dist/core/AbiConstructor.d.ts",
+ "src": "./src/core/AbiConstructor.ts",
+ "default": "./dist/core/AbiConstructor.js"
+ },
+ "./AbiError": {
+ "types": "./dist/core/AbiError.d.ts",
+ "src": "./src/core/AbiError.ts",
+ "default": "./dist/core/AbiError.js"
+ },
+ "./AbiEvent": {
+ "types": "./dist/core/AbiEvent.d.ts",
+ "src": "./src/core/AbiEvent.ts",
+ "default": "./dist/core/AbiEvent.js"
+ },
+ "./AbiFunction": {
+ "types": "./dist/core/AbiFunction.d.ts",
+ "src": "./src/core/AbiFunction.ts",
+ "default": "./dist/core/AbiFunction.js"
+ },
+ "./AbiItem": {
+ "types": "./dist/core/AbiItem.d.ts",
+ "src": "./src/core/AbiItem.ts",
+ "default": "./dist/core/AbiItem.js"
+ },
+ "./AbiParameters": {
+ "types": "./dist/core/AbiParameters.d.ts",
+ "src": "./src/core/AbiParameters.ts",
+ "default": "./dist/core/AbiParameters.js"
+ },
+ "./AccessList": {
+ "types": "./dist/core/AccessList.d.ts",
+ "src": "./src/core/AccessList.ts",
+ "default": "./dist/core/AccessList.js"
+ },
+ "./AccountProof": {
+ "types": "./dist/core/AccountProof.d.ts",
+ "src": "./src/core/AccountProof.ts",
+ "default": "./dist/core/AccountProof.js"
+ },
+ "./Address": {
+ "types": "./dist/core/Address.d.ts",
+ "src": "./src/core/Address.ts",
+ "default": "./dist/core/Address.js"
+ },
+ "./AesGcm": {
+ "types": "./dist/core/AesGcm.d.ts",
+ "src": "./src/core/AesGcm.ts",
+ "default": "./dist/core/AesGcm.js"
+ },
+ "./Authorization": {
+ "types": "./dist/core/Authorization.d.ts",
+ "src": "./src/core/Authorization.ts",
+ "default": "./dist/core/Authorization.js"
+ },
+ "./Base32": {
+ "types": "./dist/core/Base32.d.ts",
+ "src": "./src/core/Base32.ts",
+ "default": "./dist/core/Base32.js"
+ },
+ "./Base58": {
+ "types": "./dist/core/Base58.d.ts",
+ "src": "./src/core/Base58.ts",
+ "default": "./dist/core/Base58.js"
+ },
+ "./Base64": {
+ "types": "./dist/core/Base64.d.ts",
+ "src": "./src/core/Base64.ts",
+ "default": "./dist/core/Base64.js"
+ },
+ "./Bech32m": {
+ "types": "./dist/core/Bech32m.d.ts",
+ "src": "./src/core/Bech32m.ts",
+ "default": "./dist/core/Bech32m.js"
+ },
+ "./BinaryStateTree": {
+ "types": "./dist/core/BinaryStateTree.d.ts",
+ "src": "./src/core/BinaryStateTree.ts",
+ "default": "./dist/core/BinaryStateTree.js"
+ },
+ "./Blobs": {
+ "types": "./dist/core/Blobs.d.ts",
+ "src": "./src/core/Blobs.ts",
+ "default": "./dist/core/Blobs.js"
+ },
+ "./Block": {
+ "types": "./dist/core/Block.d.ts",
+ "src": "./src/core/Block.ts",
+ "default": "./dist/core/Block.js"
+ },
+ "./BlockOverrides": {
+ "types": "./dist/core/BlockOverrides.d.ts",
+ "src": "./src/core/BlockOverrides.ts",
+ "default": "./dist/core/BlockOverrides.js"
+ },
+ "./Bloom": {
+ "types": "./dist/core/Bloom.d.ts",
+ "src": "./src/core/Bloom.ts",
+ "default": "./dist/core/Bloom.js"
+ },
+ "./Bls": {
+ "types": "./dist/core/Bls.d.ts",
+ "src": "./src/core/Bls.ts",
+ "default": "./dist/core/Bls.js"
+ },
+ "./BlsPoint": {
+ "types": "./dist/core/BlsPoint.d.ts",
+ "src": "./src/core/BlsPoint.ts",
+ "default": "./dist/core/BlsPoint.js"
+ },
+ "./Bytes": {
+ "types": "./dist/core/Bytes.d.ts",
+ "src": "./src/core/Bytes.ts",
+ "default": "./dist/core/Bytes.js"
+ },
+ "./Caches": {
+ "types": "./dist/core/Caches.d.ts",
+ "src": "./src/core/Caches.ts",
+ "default": "./dist/core/Caches.js"
+ },
+ "./Cbor": {
+ "types": "./dist/core/Cbor.d.ts",
+ "src": "./src/core/Cbor.ts",
+ "default": "./dist/core/Cbor.js"
+ },
+ "./CompactSize": {
+ "types": "./dist/core/CompactSize.d.ts",
+ "src": "./src/core/CompactSize.ts",
+ "default": "./dist/core/CompactSize.js"
+ },
+ "./ContractAddress": {
+ "types": "./dist/core/ContractAddress.d.ts",
+ "src": "./src/core/ContractAddress.ts",
+ "default": "./dist/core/ContractAddress.js"
+ },
+ "./CoseKey": {
+ "types": "./dist/core/CoseKey.d.ts",
+ "src": "./src/core/CoseKey.ts",
+ "default": "./dist/core/CoseKey.js"
+ },
+ "./Ed25519": {
+ "types": "./dist/core/Ed25519.d.ts",
+ "src": "./src/core/Ed25519.ts",
+ "default": "./dist/core/Ed25519.js"
+ },
+ "./Ens": {
+ "types": "./dist/core/Ens.d.ts",
+ "src": "./src/core/Ens.ts",
+ "default": "./dist/core/Ens.js"
+ },
+ "./Errors": {
+ "types": "./dist/core/Errors.d.ts",
+ "src": "./src/core/Errors.ts",
+ "default": "./dist/core/Errors.js"
+ },
+ "./Fee": {
+ "types": "./dist/core/Fee.d.ts",
+ "src": "./src/core/Fee.ts",
+ "default": "./dist/core/Fee.js"
+ },
+ "./Filter": {
+ "types": "./dist/core/Filter.d.ts",
+ "src": "./src/core/Filter.ts",
+ "default": "./dist/core/Filter.js"
+ },
+ "./Hash": {
+ "types": "./dist/core/Hash.d.ts",
+ "src": "./src/core/Hash.ts",
+ "default": "./dist/core/Hash.js"
+ },
+ "./HdKey": {
+ "types": "./dist/core/HdKey.d.ts",
+ "src": "./src/core/HdKey.ts",
+ "default": "./dist/core/HdKey.js"
+ },
+ "./Hex": {
+ "types": "./dist/core/Hex.d.ts",
+ "src": "./src/core/Hex.ts",
+ "default": "./dist/core/Hex.js"
+ },
+ "./Json": {
+ "types": "./dist/core/Json.d.ts",
+ "src": "./src/core/Json.ts",
+ "default": "./dist/core/Json.js"
+ },
+ "./Keystore": {
+ "types": "./dist/core/Keystore.d.ts",
+ "src": "./src/core/Keystore.ts",
+ "default": "./dist/core/Keystore.js"
+ },
+ "./Kzg": {
+ "types": "./dist/core/Kzg.d.ts",
+ "src": "./src/core/Kzg.ts",
+ "default": "./dist/core/Kzg.js"
+ },
+ "./Log": {
+ "types": "./dist/core/Log.d.ts",
+ "src": "./src/core/Log.ts",
+ "default": "./dist/core/Log.js"
+ },
+ "./Mnemonic": {
+ "types": "./dist/core/Mnemonic.d.ts",
+ "src": "./src/core/Mnemonic.ts",
+ "default": "./dist/core/Mnemonic.js"
+ },
+ "./P256": {
+ "types": "./dist/core/P256.d.ts",
+ "src": "./src/core/P256.ts",
+ "default": "./dist/core/P256.js"
+ },
+ "./PersonalMessage": {
+ "types": "./dist/core/PersonalMessage.d.ts",
+ "src": "./src/core/PersonalMessage.ts",
+ "default": "./dist/core/PersonalMessage.js"
+ },
+ "./Provider": {
+ "types": "./dist/core/Provider.d.ts",
+ "src": "./src/core/Provider.ts",
+ "default": "./dist/core/Provider.js"
+ },
+ "./PublicKey": {
+ "types": "./dist/core/PublicKey.d.ts",
+ "src": "./src/core/PublicKey.ts",
+ "default": "./dist/core/PublicKey.js"
+ },
+ "./Rlp": {
+ "types": "./dist/core/Rlp.d.ts",
+ "src": "./src/core/Rlp.ts",
+ "default": "./dist/core/Rlp.js"
+ },
+ "./RpcRequest": {
+ "types": "./dist/core/RpcRequest.d.ts",
+ "src": "./src/core/RpcRequest.ts",
+ "default": "./dist/core/RpcRequest.js"
+ },
+ "./RpcResponse": {
+ "types": "./dist/core/RpcResponse.d.ts",
+ "src": "./src/core/RpcResponse.ts",
+ "default": "./dist/core/RpcResponse.js"
+ },
+ "./RpcSchema": {
+ "types": "./dist/core/RpcSchema.d.ts",
+ "src": "./src/core/RpcSchema.ts",
+ "default": "./dist/core/RpcSchema.js"
+ },
+ "./RpcTransport": {
+ "types": "./dist/core/RpcTransport.d.ts",
+ "src": "./src/core/RpcTransport.ts",
+ "default": "./dist/core/RpcTransport.js"
+ },
+ "./Secp256k1": {
+ "types": "./dist/core/Secp256k1.d.ts",
+ "src": "./src/core/Secp256k1.ts",
+ "default": "./dist/core/Secp256k1.js"
+ },
+ "./Signature": {
+ "types": "./dist/core/Signature.d.ts",
+ "src": "./src/core/Signature.ts",
+ "default": "./dist/core/Signature.js"
+ },
+ "./Siwe": {
+ "types": "./dist/core/Siwe.d.ts",
+ "src": "./src/core/Siwe.ts",
+ "default": "./dist/core/Siwe.js"
+ },
+ "./Solidity": {
+ "types": "./dist/core/Solidity.d.ts",
+ "src": "./src/core/Solidity.ts",
+ "default": "./dist/core/Solidity.js"
+ },
+ "./StateOverrides": {
+ "types": "./dist/core/StateOverrides.d.ts",
+ "src": "./src/core/StateOverrides.ts",
+ "default": "./dist/core/StateOverrides.js"
+ },
+ "./Transaction": {
+ "types": "./dist/core/Transaction.d.ts",
+ "src": "./src/core/Transaction.ts",
+ "default": "./dist/core/Transaction.js"
+ },
+ "./TransactionReceipt": {
+ "types": "./dist/core/TransactionReceipt.d.ts",
+ "src": "./src/core/TransactionReceipt.ts",
+ "default": "./dist/core/TransactionReceipt.js"
+ },
+ "./TransactionRequest": {
+ "types": "./dist/core/TransactionRequest.d.ts",
+ "src": "./src/core/TransactionRequest.ts",
+ "default": "./dist/core/TransactionRequest.js"
+ },
+ "./TxEnvelope": {
+ "types": "./dist/core/TxEnvelope.d.ts",
+ "src": "./src/core/TxEnvelope.ts",
+ "default": "./dist/core/TxEnvelope.js"
+ },
+ "./TxEnvelopeEip1559": {
+ "types": "./dist/core/TxEnvelopeEip1559.d.ts",
+ "src": "./src/core/TxEnvelopeEip1559.ts",
+ "default": "./dist/core/TxEnvelopeEip1559.js"
+ },
+ "./TxEnvelopeEip2930": {
+ "types": "./dist/core/TxEnvelopeEip2930.d.ts",
+ "src": "./src/core/TxEnvelopeEip2930.ts",
+ "default": "./dist/core/TxEnvelopeEip2930.js"
+ },
+ "./TxEnvelopeEip4844": {
+ "types": "./dist/core/TxEnvelopeEip4844.d.ts",
+ "src": "./src/core/TxEnvelopeEip4844.ts",
+ "default": "./dist/core/TxEnvelopeEip4844.js"
+ },
+ "./TxEnvelopeEip7702": {
+ "types": "./dist/core/TxEnvelopeEip7702.d.ts",
+ "src": "./src/core/TxEnvelopeEip7702.ts",
+ "default": "./dist/core/TxEnvelopeEip7702.js"
+ },
+ "./TxEnvelopeLegacy": {
+ "types": "./dist/core/TxEnvelopeLegacy.d.ts",
+ "src": "./src/core/TxEnvelopeLegacy.ts",
+ "default": "./dist/core/TxEnvelopeLegacy.js"
+ },
+ "./TypedData": {
+ "types": "./dist/core/TypedData.d.ts",
+ "src": "./src/core/TypedData.ts",
+ "default": "./dist/core/TypedData.js"
+ },
+ "./ValidatorData": {
+ "types": "./dist/core/ValidatorData.d.ts",
+ "src": "./src/core/ValidatorData.ts",
+ "default": "./dist/core/ValidatorData.js"
+ },
+ "./Value": {
+ "types": "./dist/core/Value.d.ts",
+ "src": "./src/core/Value.ts",
+ "default": "./dist/core/Value.js"
+ },
+ "./WebAuthnP256": {
+ "types": "./dist/core/WebAuthnP256.d.ts",
+ "src": "./src/core/WebAuthnP256.ts",
+ "default": "./dist/core/WebAuthnP256.js"
+ },
+ "./WebCryptoP256": {
+ "types": "./dist/core/WebCryptoP256.d.ts",
+ "src": "./src/core/WebCryptoP256.ts",
+ "default": "./dist/core/WebCryptoP256.js"
+ },
+ "./Withdrawal": {
+ "types": "./dist/core/Withdrawal.d.ts",
+ "src": "./src/core/Withdrawal.ts",
+ "default": "./dist/core/Withdrawal.js"
+ },
+ "./X25519": {
+ "types": "./dist/core/X25519.d.ts",
+ "src": "./src/core/X25519.ts",
+ "default": "./dist/core/X25519.js"
+ },
+ "./erc4337": {
+ "types": "./dist/erc4337/index.d.ts",
+ "src": "./src/erc4337/index.ts",
+ "default": "./dist/erc4337/index.js"
+ },
+ "./erc4337/EntryPoint": {
+ "types": "./dist/erc4337/EntryPoint.d.ts",
+ "src": "./src/erc4337/EntryPoint.ts",
+ "default": "./dist/erc4337/EntryPoint.js"
+ },
+ "./erc4337/RpcSchema": {
+ "types": "./dist/erc4337/RpcSchema.d.ts",
+ "src": "./src/erc4337/RpcSchema.ts",
+ "default": "./dist/erc4337/RpcSchema.js"
+ },
+ "./erc4337/UserOperation": {
+ "types": "./dist/erc4337/UserOperation.d.ts",
+ "src": "./src/erc4337/UserOperation.ts",
+ "default": "./dist/erc4337/UserOperation.js"
+ },
+ "./erc4337/UserOperationGas": {
+ "types": "./dist/erc4337/UserOperationGas.d.ts",
+ "src": "./src/erc4337/UserOperationGas.ts",
+ "default": "./dist/erc4337/UserOperationGas.js"
+ },
+ "./erc4337/UserOperationReceipt": {
+ "types": "./dist/erc4337/UserOperationReceipt.d.ts",
+ "src": "./src/erc4337/UserOperationReceipt.ts",
+ "default": "./dist/erc4337/UserOperationReceipt.js"
+ },
+ "./erc6492": {
+ "types": "./dist/erc6492/index.d.ts",
+ "src": "./src/erc6492/index.ts",
+ "default": "./dist/erc6492/index.js"
+ },
+ "./erc6492/SignatureErc6492": {
+ "types": "./dist/erc6492/SignatureErc6492.d.ts",
+ "src": "./src/erc6492/SignatureErc6492.ts",
+ "default": "./dist/erc6492/SignatureErc6492.js"
+ },
+ "./erc7821": {
+ "types": "./dist/erc7821/index.d.ts",
+ "src": "./src/erc7821/index.ts",
+ "default": "./dist/erc7821/index.js"
+ },
+ "./erc7821/Calls": {
+ "types": "./dist/erc7821/Calls.d.ts",
+ "src": "./src/erc7821/Calls.ts",
+ "default": "./dist/erc7821/Calls.js"
+ },
+ "./erc7821/Execute": {
+ "types": "./dist/erc7821/Execute.d.ts",
+ "src": "./src/erc7821/Execute.ts",
+ "default": "./dist/erc7821/Execute.js"
+ },
+ "./erc8010": {
+ "types": "./dist/erc8010/index.d.ts",
+ "src": "./src/erc8010/index.ts",
+ "default": "./dist/erc8010/index.js"
+ },
+ "./erc8010/SignatureErc8010": {
+ "types": "./dist/erc8010/SignatureErc8010.d.ts",
+ "src": "./src/erc8010/SignatureErc8010.ts",
+ "default": "./dist/erc8010/SignatureErc8010.js"
+ },
+ "./erc8021": {
+ "types": "./dist/erc8021/index.d.ts",
+ "src": "./src/erc8021/index.ts",
+ "default": "./dist/erc8021/index.js"
+ },
+ "./erc8021/Attribution": {
+ "types": "./dist/erc8021/Attribution.d.ts",
+ "src": "./src/erc8021/Attribution.ts",
+ "default": "./dist/erc8021/Attribution.js"
+ },
+ "./tempo": {
+ "types": "./dist/tempo/index.d.ts",
+ "src": "./src/tempo/index.ts",
+ "default": "./dist/tempo/index.js"
+ },
+ "./tempo/AuthorizationTempo": {
+ "types": "./dist/tempo/AuthorizationTempo.d.ts",
+ "src": "./src/tempo/AuthorizationTempo.ts",
+ "default": "./dist/tempo/AuthorizationTempo.js"
+ },
+ "./tempo/KeyAuthorization": {
+ "types": "./dist/tempo/KeyAuthorization.d.ts",
+ "src": "./src/tempo/KeyAuthorization.ts",
+ "default": "./dist/tempo/KeyAuthorization.js"
+ },
+ "./tempo/Period": {
+ "types": "./dist/tempo/Period.d.ts",
+ "src": "./src/tempo/Period.ts",
+ "default": "./dist/tempo/Period.js"
+ },
+ "./tempo/PoolId": {
+ "types": "./dist/tempo/PoolId.d.ts",
+ "src": "./src/tempo/PoolId.ts",
+ "default": "./dist/tempo/PoolId.js"
+ },
+ "./tempo/RpcSchemaTempo": {
+ "types": "./dist/tempo/RpcSchemaTempo.d.ts",
+ "src": "./src/tempo/RpcSchemaTempo.ts",
+ "default": "./dist/tempo/RpcSchemaTempo.js"
+ },
+ "./tempo/SignatureEnvelope": {
+ "types": "./dist/tempo/SignatureEnvelope.d.ts",
+ "src": "./src/tempo/SignatureEnvelope.ts",
+ "default": "./dist/tempo/SignatureEnvelope.js"
+ },
+ "./tempo/TempoAddress": {
+ "types": "./dist/tempo/TempoAddress.d.ts",
+ "src": "./src/tempo/TempoAddress.ts",
+ "default": "./dist/tempo/TempoAddress.js"
+ },
+ "./tempo/Tick": {
+ "types": "./dist/tempo/Tick.d.ts",
+ "src": "./src/tempo/Tick.ts",
+ "default": "./dist/tempo/Tick.js"
+ },
+ "./tempo/TokenId": {
+ "types": "./dist/tempo/TokenId.d.ts",
+ "src": "./src/tempo/TokenId.ts",
+ "default": "./dist/tempo/TokenId.js"
+ },
+ "./tempo/TokenRole": {
+ "types": "./dist/tempo/TokenRole.d.ts",
+ "src": "./src/tempo/TokenRole.ts",
+ "default": "./dist/tempo/TokenRole.js"
+ },
+ "./tempo/Transaction": {
+ "types": "./dist/tempo/Transaction.d.ts",
+ "src": "./src/tempo/Transaction.ts",
+ "default": "./dist/tempo/Transaction.js"
+ },
+ "./tempo/TransactionReceipt": {
+ "types": "./dist/tempo/TransactionReceipt.d.ts",
+ "src": "./src/tempo/TransactionReceipt.ts",
+ "default": "./dist/tempo/TransactionReceipt.js"
+ },
+ "./tempo/TransactionRequest": {
+ "types": "./dist/tempo/TransactionRequest.d.ts",
+ "src": "./src/tempo/TransactionRequest.ts",
+ "default": "./dist/tempo/TransactionRequest.js"
+ },
+ "./tempo/TxEnvelopeTempo": {
+ "types": "./dist/tempo/TxEnvelopeTempo.d.ts",
+ "src": "./src/tempo/TxEnvelopeTempo.ts",
+ "default": "./dist/tempo/TxEnvelopeTempo.js"
+ },
+ "./tempo/VirtualAddress": {
+ "types": "./dist/tempo/VirtualAddress.d.ts",
+ "src": "./src/tempo/VirtualAddress.ts",
+ "default": "./dist/tempo/VirtualAddress.js"
+ },
+ "./tempo/VirtualMaster": {
+ "types": "./dist/tempo/VirtualMaster.d.ts",
+ "src": "./src/tempo/VirtualMaster.ts",
+ "default": "./dist/tempo/VirtualMaster.js"
+ },
+ "./tempo/ZoneId": {
+ "types": "./dist/tempo/ZoneId.d.ts",
+ "src": "./src/tempo/ZoneId.ts",
+ "default": "./dist/tempo/ZoneId.js"
+ },
+ "./tempo/ZoneRpcAuthentication": {
+ "types": "./dist/tempo/ZoneRpcAuthentication.d.ts",
+ "src": "./src/tempo/ZoneRpcAuthentication.ts",
+ "default": "./dist/tempo/ZoneRpcAuthentication.js"
+ },
+ "./trusted-setups": {
+ "types": "./dist/trusted-setups/index.d.ts",
+ "src": "./src/trusted-setups/index.ts",
+ "default": "./dist/trusted-setups/index.js"
+ },
+ "./trusted-setups/Paths": {
+ "types": "./dist/trusted-setups/Paths.d.ts",
+ "src": "./src/trusted-setups/Paths.ts",
+ "default": "./dist/trusted-setups/Paths.js"
+ },
+ "./webauthn": {
+ "types": "./dist/webauthn/index.d.ts",
+ "src": "./src/webauthn/index.ts",
+ "default": "./dist/webauthn/index.js"
+ },
+ "./webauthn/Authentication": {
+ "types": "./dist/webauthn/Authentication.d.ts",
+ "src": "./src/webauthn/Authentication.ts",
+ "default": "./dist/webauthn/Authentication.js"
+ },
+ "./webauthn/Authenticator": {
+ "types": "./dist/webauthn/Authenticator.d.ts",
+ "src": "./src/webauthn/Authenticator.ts",
+ "default": "./dist/webauthn/Authenticator.js"
+ },
+ "./webauthn/Credential": {
+ "types": "./dist/webauthn/Credential.d.ts",
+ "src": "./src/webauthn/Credential.ts",
+ "default": "./dist/webauthn/Credential.js"
+ },
+ "./webauthn/Registration": {
+ "types": "./dist/webauthn/Registration.d.ts",
+ "src": "./src/webauthn/Registration.ts",
+ "default": "./dist/webauthn/Registration.js"
+ },
+ "./webauthn/Types": {
+ "types": "./dist/webauthn/Types.d.ts",
+ "src": "./src/webauthn/Types.ts",
+ "default": "./dist/webauthn/Types.js"
+ },
+ "./window": {
+ "types": "./dist/window/index.d.ts",
+ "src": "./src/window/index.ts",
+ "default": "./dist/window/index.js"
+ }
+ },
+ "module": "./dist/index.js",
+ "types": "./dist/index.d.ts"
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d7ab3e2a..b02cce8e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -18,6 +18,31 @@ overrides:
importers:
.:
+ dependencies:
+ '@adraffy/ens-normalize':
+ specifier: ^1.11.0
+ version: 1.11.1
+ '@noble/ciphers':
+ specifier: ^1.3.0
+ version: 1.3.0
+ '@noble/curves':
+ specifier: 1.9.1
+ version: 1.9.1
+ '@noble/hashes':
+ specifier: ^1.8.0
+ version: 1.8.0
+ '@scure/bip32':
+ specifier: ^1.7.0
+ version: 1.7.0
+ '@scure/bip39':
+ specifier: ^1.6.0
+ version: 1.6.0
+ abitype:
+ specifier: ^1.2.3
+ version: 1.2.3(typescript@5.5.4)(zod@3.23.8)
+ eventemitter3:
+ specifier: 5.0.1
+ version: 5.0.1
devDependencies:
'@ark/attest':
specifier: ^0.16.0
@@ -31,12 +56,6 @@ importers:
'@changesets/cli':
specifier: ^2.27.7
version: 2.27.7
- '@ethereumjs/rlp':
- specifier: ^5.0.2
- version: 5.0.2
- '@ethereumjs/util':
- specifier: ^9.0.3
- version: 9.0.3
'@microsoft/api-extractor':
specifier: ^7.47.7
version: 7.47.7(@types/node@22.5.4)
@@ -82,9 +101,6 @@ importers:
eslint-plugin-tsdoc:
specifier: ^0.3.0
version: 0.3.0
- ethers:
- specifier: ^6.13.2
- version: 6.13.2
fs-extra:
specifier: ^11.2.0
version: 11.3.0
@@ -92,17 +108,14 @@ importers:
specifier: ^5.27.2
version: 5.27.2(@types/node@22.5.4)(typescript@5.5.4)
micro-eth-signer:
- specifier: ^0.15.0
- version: 0.15.0
+ specifier: ^0.18.1
+ version: 0.18.1
playwright:
specifier: ^1.58.2
version: 1.58.2
prool:
specifier: ~0.2.3
version: 0.2.3(testcontainers@11.10.0)
- rimraf:
- specifier: ^5.0.10
- version: 5.0.10
sherif:
specifier: ^0.11.0
version: 0.11.0
@@ -130,62 +143,15 @@ importers:
viem:
specifier: ^2.45.0
version: 2.45.0(typescript@5.5.4)(zod@3.23.8)
- vite-tsconfig-paths:
- specifier: ^5.0.1
- version: 5.0.1(typescript@5.5.4)(vite@6.1.0(@types/node@22.5.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.31.5)(tsx@4.17.0)(yaml@2.5.0))
vitest:
specifier: ^4.0.18
version: 4.0.18(@types/node@22.5.4)(@vitest/browser-playwright@4.0.18)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.31.5)(tsx@4.17.0)(yaml@2.5.0)
vocs:
specifier: ^1.0.13
- version: 1.0.13(@types/node@22.5.4)(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.7)(terser@5.31.5)(tsx@4.17.0)(typescript@5.5.4)(yaml@2.5.0)
- web3:
- specifier: ^4.12.1
- version: 4.12.1(typescript@5.5.4)(zod@3.23.8)
-
- examples/mine-salt:
- dependencies:
- ox:
- specifier: workspace:*
- version: link:../../src
- devDependencies:
- typescript:
- specifier: ^5.5.3
- version: 5.5.4
- vite:
- specifier: ^5.4.1
- version: 5.4.10(@types/node@22.5.4)(lightningcss@1.29.1)(terser@5.31.5)
-
- examples/webauthn-p256:
- dependencies:
- ox:
- specifier: workspace:*
- version: link:../../src
- react:
- specifier: ^18.3.1
- version: 18.3.1
- react-dom:
- specifier: ^18.3.1
- version: 18.3.1(react@18.3.1)
- devDependencies:
- '@types/react':
- specifier: ^18.3.3
- version: 18.3.28
- '@types/react-dom':
- specifier: ^18.3.0
- version: 18.3.7(@types/react@18.3.28)
- '@vitejs/plugin-react':
- specifier: ^4.3.1
- version: 4.3.4(vite@5.4.10(@types/node@22.5.4)(lightningcss@1.29.1)(terser@5.31.5))
- globals:
- specifier: ^15.9.0
- version: 15.15.0
- typescript:
- specifier: ^5.5.3
- version: 5.5.4
- vite:
- specifier: ^5.4.1
- version: 5.4.10(@types/node@22.5.4)(lightningcss@1.29.1)(terser@5.31.5)
+ version: 1.0.13(@types/node@22.5.4)(@types/react@19.0.9)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.7)(terser@5.31.5)(tsx@4.17.0)(typescript@5.5.4)(yaml@2.5.0)
+ zile:
+ specifier: ^0.0.25
+ version: 0.0.25(typescript@5.5.4)
site:
devDependencies:
@@ -197,7 +163,7 @@ importers:
version: 7.0.1
ox:
specifier: workspace:*
- version: link:../src
+ version: link:..
react:
specifier: ^19
version: 19.0.0
@@ -206,43 +172,10 @@ importers:
version: 19.0.0(react@19.0.0)
vocs:
specifier: ^1.0.13
- version: 1.0.13(@types/node@22.5.4)(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.7)(terser@5.31.5)(tsx@4.17.0)(typescript@5.5.4)(yaml@2.5.0)
-
- src:
- dependencies:
- '@adraffy/ens-normalize':
- specifier: ^1.11.0
- version: 1.11.0
- '@noble/ciphers':
- specifier: ^1.3.0
- version: 1.3.0
- '@noble/curves':
- specifier: 1.9.1
- version: 1.9.1
- '@noble/hashes':
- specifier: ^1.8.0
- version: 1.8.0
- '@scure/bip32':
- specifier: ^1.7.0
- version: 1.7.0
- '@scure/bip39':
- specifier: ^1.6.0
- version: 1.6.0
- abitype:
- specifier: ^1.2.3
- version: 1.2.3(typescript@5.5.4)(zod@3.23.8)
- eventemitter3:
- specifier: 5.0.1
- version: 5.0.1
+ version: 1.0.13(@types/node@22.5.4)(@types/react@19.0.9)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.7)(terser@5.31.5)(tsx@4.17.0)(typescript@5.5.4)(yaml@2.5.0)
packages:
- '@adraffy/ens-normalize@1.10.1':
- resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==}
-
- '@adraffy/ens-normalize@1.11.0':
- resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==}
-
'@adraffy/ens-normalize@1.11.1':
resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==}
@@ -305,6 +238,10 @@ packages:
resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-string-parser@7.24.8':
+ resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-string-parser@7.25.9':
resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
engines: {node: '>=6.9.0'}
@@ -313,6 +250,10 @@ packages:
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-validator-identifier@7.24.7':
+ resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-validator-identifier@7.25.9':
resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
engines: {node: '>=6.9.0'}
@@ -329,6 +270,11 @@ packages:
resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==}
engines: {node: '>=6.9.0'}
+ '@babel/parser@7.25.3':
+ resolution: {integrity: sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
'@babel/parser@7.26.9':
resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==}
engines: {node: '>=6.0.0'}
@@ -369,6 +315,10 @@ packages:
resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==}
engines: {node: '>=6.9.0'}
+ '@babel/types@7.25.2':
+ resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==}
+ engines: {node: '>=6.9.0'}
+
'@babel/types@7.26.9':
resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==}
engines: {node: '>=6.9.0'}
@@ -519,11 +469,17 @@ packages:
'@clack/core@0.3.4':
resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==}
+ '@clack/core@1.2.0':
+ resolution: {integrity: sha512-qfxof/3T3t9DPU/Rj3OmcFyZInceqj/NVtO9rwIuJqCUgh32gwPjpFQQp/ben07qKlhpwq7GzfWpST4qdJ5Drg==}
+
'@clack/prompts@0.7.0':
resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==}
bundledDependencies:
- is-unicode-supported
+ '@clack/prompts@1.2.0':
+ resolution: {integrity: sha512-4jmztR9fMqPMjz6H/UZXj0zEmE43ha1euENwkckKKel4XpSfokExPo5AiVStdHSAlHekz4d0CA/r45Ok1E4D3w==}
+
'@emotion/hash@0.9.2':
resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
@@ -989,20 +945,6 @@ packages:
resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@ethereumjs/rlp@4.0.1':
- resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==}
- engines: {node: '>=14'}
- hasBin: true
-
- '@ethereumjs/rlp@5.0.2':
- resolution: {integrity: sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==}
- engines: {node: '>=18'}
- hasBin: true
-
- '@ethereumjs/util@9.0.3':
- resolution: {integrity: sha512-PmwzWDflky+7jlZIFqiGsBPap12tk9zK5SVH9YW2OEnDN7OEhCjUOMzbOqwuClrbkSIkM2ERivd7sXZ48Rh/vg==}
- engines: {node: '>=18'}
-
'@floating-ui/core@1.6.7':
resolution: {integrity: sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==}
@@ -1134,28 +1076,22 @@ packages:
resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==}
engines: {node: ^14.21.3 || >=16}
- '@noble/curves@1.2.0':
- resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==}
-
- '@noble/curves@1.4.2':
- resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==}
-
'@noble/curves@1.9.1':
resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==}
engines: {node: ^14.21.3 || >=16}
- '@noble/hashes@1.3.2':
- resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==}
- engines: {node: '>= 16'}
-
- '@noble/hashes@1.4.0':
- resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==}
- engines: {node: '>= 16'}
+ '@noble/curves@2.0.1':
+ resolution: {integrity: sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==}
+ engines: {node: '>= 20.19.0'}
'@noble/hashes@1.8.0':
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
engines: {node: ^14.21.3 || >=16}
+ '@noble/hashes@2.0.1':
+ resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==}
+ engines: {node: '>= 20.19.0'}
+
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -1930,51 +1866,101 @@ packages:
rollup:
optional: true
+ '@rollup/rollup-android-arm-eabi@4.27.2':
+ resolution: {integrity: sha512-Tj+j7Pyzd15wAdSJswvs5CJzJNV+qqSUcr/aCD+jpQSBtXvGnV0pnrjoc8zFTe9fcKCatkpFpOO7yAzpO998HA==}
+ cpu: [arm]
+ os: [android]
+
'@rollup/rollup-android-arm-eabi@4.34.7':
resolution: {integrity: sha512-l6CtzHYo8D2TQ3J7qJNpp3Q1Iye56ssIAtqbM2H8axxCEEwvN7o8Ze9PuIapbxFL3OHrJU2JBX6FIIVnP/rYyw==}
cpu: [arm]
os: [android]
+ '@rollup/rollup-android-arm64@4.27.2':
+ resolution: {integrity: sha512-xsPeJgh2ThBpUqlLgRfiVYBEf/P1nWlWvReG+aBWfNv3XEBpa6ZCmxSVnxJgLgkNz4IbxpLy64h2gCmAAQLneQ==}
+ cpu: [arm64]
+ os: [android]
+
'@rollup/rollup-android-arm64@4.34.7':
resolution: {integrity: sha512-KvyJpFUueUnSp53zhAa293QBYqwm94TgYTIfXyOTtidhm5V0LbLCJQRGkQClYiX3FXDQGSvPxOTD/6rPStMMDg==}
cpu: [arm64]
os: [android]
+ '@rollup/rollup-darwin-arm64@4.27.2':
+ resolution: {integrity: sha512-KnXU4m9MywuZFedL35Z3PuwiTSn/yqRIhrEA9j+7OSkji39NzVkgxuxTYg5F8ryGysq4iFADaU5osSizMXhU2A==}
+ cpu: [arm64]
+ os: [darwin]
+
'@rollup/rollup-darwin-arm64@4.34.7':
resolution: {integrity: sha512-jq87CjmgL9YIKvs8ybtIC98s/M3HdbqXhllcy9EdLV0yMg1DpxES2gr65nNy7ObNo/vZ/MrOTxt0bE5LinL6mA==}
cpu: [arm64]
os: [darwin]
+ '@rollup/rollup-darwin-x64@4.27.2':
+ resolution: {integrity: sha512-Hj77A3yTvUeCIx/Vi+4d4IbYhyTwtHj07lVzUgpUq9YpJSEiGJj4vXMKwzJ3w5zp5v3PFvpJNgc/J31smZey6g==}
+ cpu: [x64]
+ os: [darwin]
+
'@rollup/rollup-darwin-x64@4.34.7':
resolution: {integrity: sha512-rSI/m8OxBjsdnMMg0WEetu/w+LhLAcCDEiL66lmMX4R3oaml3eXz3Dxfvrxs1FbzPbJMaItQiksyMfv1hoIxnA==}
cpu: [x64]
os: [darwin]
+ '@rollup/rollup-freebsd-arm64@4.27.2':
+ resolution: {integrity: sha512-RjgKf5C3xbn8gxvCm5VgKZ4nn0pRAIe90J0/fdHUsgztd3+Zesb2lm2+r6uX4prV2eUByuxJNdt647/1KPRq5g==}
+ cpu: [arm64]
+ os: [freebsd]
+
'@rollup/rollup-freebsd-arm64@4.34.7':
resolution: {integrity: sha512-oIoJRy3ZrdsXpFuWDtzsOOa/E/RbRWXVokpVrNnkS7npz8GEG++E1gYbzhYxhxHbO2om1T26BZjVmdIoyN2WtA==}
cpu: [arm64]
os: [freebsd]
+ '@rollup/rollup-freebsd-x64@4.27.2':
+ resolution: {integrity: sha512-duq21FoXwQtuws+V9H6UZ+eCBc7fxSpMK1GQINKn3fAyd9DFYKPJNcUhdIKOrMFjLEJgQskoMoiuizMt+dl20g==}
+ cpu: [x64]
+ os: [freebsd]
+
'@rollup/rollup-freebsd-x64@4.34.7':
resolution: {integrity: sha512-X++QSLm4NZfZ3VXGVwyHdRf58IBbCu9ammgJxuWZYLX0du6kZvdNqPwrjvDfwmi6wFdvfZ/s6K7ia0E5kI7m8Q==}
cpu: [x64]
os: [freebsd]
+ '@rollup/rollup-linux-arm-gnueabihf@4.27.2':
+ resolution: {integrity: sha512-6npqOKEPRZkLrMcvyC/32OzJ2srdPzCylJjiTJT2c0bwwSGm7nz2F9mNQ1WrAqCBZROcQn91Fno+khFhVijmFA==}
+ cpu: [arm]
+ os: [linux]
+
'@rollup/rollup-linux-arm-gnueabihf@4.34.7':
resolution: {integrity: sha512-Z0TzhrsNqukTz3ISzrvyshQpFnFRfLunYiXxlCRvcrb3nvC5rVKI+ZXPFG/Aa4jhQa1gHgH3A0exHaRRN4VmdQ==}
cpu: [arm]
os: [linux]
+ '@rollup/rollup-linux-arm-musleabihf@4.27.2':
+ resolution: {integrity: sha512-V9Xg6eXtgBtHq2jnuQwM/jr2mwe2EycnopO8cbOvpzFuySCGtKlPCI3Hj9xup/pJK5Q0388qfZZy2DqV2J8ftw==}
+ cpu: [arm]
+ os: [linux]
+
'@rollup/rollup-linux-arm-musleabihf@4.34.7':
resolution: {integrity: sha512-nkznpyXekFAbvFBKBy4nNppSgneB1wwG1yx/hujN3wRnhnkrYVugMTCBXED4+Ni6thoWfQuHNYbFjgGH0MBXtw==}
cpu: [arm]
os: [linux]
+ '@rollup/rollup-linux-arm64-gnu@4.27.2':
+ resolution: {integrity: sha512-uCFX9gtZJoQl2xDTpRdseYuNqyKkuMDtH6zSrBTA28yTfKyjN9hQ2B04N5ynR8ILCoSDOrG/Eg+J2TtJ1e/CSA==}
+ cpu: [arm64]
+ os: [linux]
+
'@rollup/rollup-linux-arm64-gnu@4.34.7':
resolution: {integrity: sha512-KCjlUkcKs6PjOcxolqrXglBDcfCuUCTVlX5BgzgoJHw+1rWH1MCkETLkLe5iLLS9dP5gKC7mp3y6x8c1oGBUtA==}
cpu: [arm64]
os: [linux]
+ '@rollup/rollup-linux-arm64-musl@4.27.2':
+ resolution: {integrity: sha512-/PU9P+7Rkz8JFYDHIi+xzHabOu9qEWR07L5nWLIUsvserrxegZExKCi2jhMZRd0ATdboKylu/K5yAXbp7fYFvA==}
+ cpu: [arm64]
+ os: [linux]
+
'@rollup/rollup-linux-arm64-musl@4.34.7':
resolution: {integrity: sha512-uFLJFz6+utmpbR313TTx+NpPuAXbPz4BhTQzgaP0tozlLnGnQ6rCo6tLwaSa6b7l6gRErjLicXQ1iPiXzYotjw==}
cpu: [arm64]
@@ -1985,41 +1971,81 @@ packages:
cpu: [loong64]
os: [linux]
+ '@rollup/rollup-linux-powerpc64le-gnu@4.27.2':
+ resolution: {integrity: sha512-eCHmol/dT5odMYi/N0R0HC8V8QE40rEpkyje/ZAXJYNNoSfrObOvG/Mn+s1F/FJyB7co7UQZZf6FuWnN6a7f4g==}
+ cpu: [ppc64]
+ os: [linux]
+
'@rollup/rollup-linux-powerpc64le-gnu@4.34.7':
resolution: {integrity: sha512-vrDk9JDa/BFkxcS2PbWpr0C/LiiSLxFbNOBgfbW6P8TBe9PPHx9Wqbvx2xgNi1TOAyQHQJ7RZFqBiEohm79r0w==}
cpu: [ppc64]
os: [linux]
+ '@rollup/rollup-linux-riscv64-gnu@4.27.2':
+ resolution: {integrity: sha512-DEP3Njr9/ADDln3kNi76PXonLMSSMiCir0VHXxmGSHxCxDfQ70oWjHcJGfiBugzaqmYdTC7Y+8Int6qbnxPBIQ==}
+ cpu: [riscv64]
+ os: [linux]
+
'@rollup/rollup-linux-riscv64-gnu@4.34.7':
resolution: {integrity: sha512-rB+ejFyjtmSo+g/a4eovDD1lHWHVqizN8P0Hm0RElkINpS0XOdpaXloqM4FBkF9ZWEzg6bezymbpLmeMldfLTw==}
cpu: [riscv64]
os: [linux]
+ '@rollup/rollup-linux-s390x-gnu@4.27.2':
+ resolution: {integrity: sha512-NHGo5i6IE/PtEPh5m0yw5OmPMpesFnzMIS/lzvN5vknnC1sXM5Z/id5VgcNPgpD+wHmIcuYYgW+Q53v+9s96lQ==}
+ cpu: [s390x]
+ os: [linux]
+
'@rollup/rollup-linux-s390x-gnu@4.34.7':
resolution: {integrity: sha512-nNXNjo4As6dNqRn7OrsnHzwTgtypfRA3u3AKr0B3sOOo+HkedIbn8ZtFnB+4XyKJojIfqDKmbIzO1QydQ8c+Pw==}
cpu: [s390x]
os: [linux]
+ '@rollup/rollup-linux-x64-gnu@4.27.2':
+ resolution: {integrity: sha512-PaW2DY5Tan+IFvNJGHDmUrORadbe/Ceh8tQxi8cmdQVCCYsLoQo2cuaSj+AU+YRX8M4ivS2vJ9UGaxfuNN7gmg==}
+ cpu: [x64]
+ os: [linux]
+
'@rollup/rollup-linux-x64-gnu@4.34.7':
resolution: {integrity: sha512-9kPVf9ahnpOMSGlCxXGv980wXD0zRR3wyk8+33/MXQIpQEOpaNe7dEHm5LMfyRZRNt9lMEQuH0jUKj15MkM7QA==}
cpu: [x64]
os: [linux]
+ '@rollup/rollup-linux-x64-musl@4.27.2':
+ resolution: {integrity: sha512-dOlWEMg2gI91Qx5I/HYqOD6iqlJspxLcS4Zlg3vjk1srE67z5T2Uz91yg/qA8sY0XcwQrFzWWiZhMNERylLrpQ==}
+ cpu: [x64]
+ os: [linux]
+
'@rollup/rollup-linux-x64-musl@4.34.7':
resolution: {integrity: sha512-7wJPXRWTTPtTFDFezA8sle/1sdgxDjuMoRXEKtx97ViRxGGkVQYovem+Q8Pr/2HxiHp74SSRG+o6R0Yq0shPwQ==}
cpu: [x64]
os: [linux]
+ '@rollup/rollup-win32-arm64-msvc@4.27.2':
+ resolution: {integrity: sha512-euMIv/4x5Y2/ImlbGl88mwKNXDsvzbWUlT7DFky76z2keajCtcbAsN9LUdmk31hAoVmJJYSThgdA0EsPeTr1+w==}
+ cpu: [arm64]
+ os: [win32]
+
'@rollup/rollup-win32-arm64-msvc@4.34.7':
resolution: {integrity: sha512-MN7aaBC7mAjsiMEZcsJvwNsQVNZShgES/9SzWp1HC9Yjqb5OpexYnRjF7RmE4itbeesHMYYQiAtUAQaSKs2Rfw==}
cpu: [arm64]
os: [win32]
+ '@rollup/rollup-win32-ia32-msvc@4.27.2':
+ resolution: {integrity: sha512-RsnE6LQkUHlkC10RKngtHNLxb7scFykEbEwOFDjr3CeCMG+Rr+cKqlkKc2/wJ1u4u990urRHCbjz31x84PBrSQ==}
+ cpu: [ia32]
+ os: [win32]
+
'@rollup/rollup-win32-ia32-msvc@4.34.7':
resolution: {integrity: sha512-aeawEKYswsFu1LhDM9RIgToobquzdtSc4jSVqHV8uApz4FVvhFl/mKh92wc8WpFc6aYCothV/03UjY6y7yLgbg==}
cpu: [ia32]
os: [win32]
+ '@rollup/rollup-win32-x64-msvc@4.27.2':
+ resolution: {integrity: sha512-foJM5vv+z2KQmn7emYdDLyTbkoO5bkHZE1oth2tWbQNGW7mX32d46Hz6T0MqXdWS2vBZhaEtHqdy9WYwGfiliA==}
+ cpu: [x64]
+ os: [win32]
+
'@rollup/rollup-win32-x64-msvc@4.34.7':
resolution: {integrity: sha512-4ZedScpxxIrVO7otcZ8kCX1mZArtH2Wfj3uFCxRJ9NO80gg1XV0U/b2f/MKaGwj2X3QopHfoWiDQ917FRpwY3w==}
cpu: [x64]
@@ -2047,21 +2073,15 @@ packages:
'@rushstack/ts-command-line@4.22.6':
resolution: {integrity: sha512-QSRqHT/IfoC5nk9zn6+fgyqOPXHME0BfchII9EUPR19pocsNp/xSbeBCbD3PIR2Lg+Q5qk7OFqk1VhWPMdKHJg==}
- '@scure/base@1.1.9':
- resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==}
-
'@scure/base@1.2.5':
resolution: {integrity: sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw==}
- '@scure/bip32@1.4.0':
- resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==}
+ '@scure/base@2.0.0':
+ resolution: {integrity: sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==}
'@scure/bip32@1.7.0':
resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==}
- '@scure/bip39@1.3.0':
- resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==}
-
'@scure/bip39@1.6.0':
resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==}
@@ -2399,17 +2419,6 @@ packages:
'@types/node@22.5.4':
resolution: {integrity: sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==}
- '@types/prop-types@15.7.15':
- resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
-
- '@types/react-dom@18.3.7':
- resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==}
- peerDependencies:
- '@types/react': ^18.0.0
-
- '@types/react@18.3.28':
- resolution: {integrity: sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==}
-
'@types/react@19.0.9':
resolution: {integrity: sha512-FedNTYgmMwSZmD1Sru/W1gJKuiYCN/3SuBkmZkcxX+FpO5zL76B22A9YNfAKg4HQO3Neh/30AiynP6BELdU0qQ==}
@@ -2437,9 +2446,6 @@ packages:
'@types/ws@8.5.12':
resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==}
- '@types/ws@8.5.3':
- resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==}
-
'@types/yauzl@2.10.3':
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
@@ -2641,15 +2647,6 @@ packages:
'@xtuc/long@4.2.2':
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
- abitype@0.7.1:
- resolution: {integrity: sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ==}
- peerDependencies:
- typescript: '>=4.9.4'
- zod: ^3 >=3.19.1
- peerDependenciesMeta:
- zod:
- optional: true
-
abitype@1.2.3:
resolution: {integrity: sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==}
peerDependencies:
@@ -2685,9 +2682,6 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
- aes-js@4.0.0-beta.5:
- resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==}
-
agent-base@7.1.1:
resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==}
engines: {node: '>= 14'}
@@ -2809,10 +2803,6 @@ packages:
peerDependencies:
postcss: ^8.1.0
- available-typed-arrays@1.0.7:
- resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
- engines: {node: '>= 0.4'}
-
b4a@1.6.6:
resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==}
@@ -2966,10 +2956,6 @@ packages:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
- call-bind@1.0.7:
- resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
- engines: {node: '>= 0.4'}
-
callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
@@ -3178,9 +3164,6 @@ packages:
resolution: {integrity: sha512-/Nr9taHX1SxL5t72DLFPYujqD8d5PDk0T8bJ9Fb/m7ck1lP20PBxHzF5IYnHI0BeTpIuGk/MQoLfT6JKpY6xnw==}
hasBin: true
- cross-fetch@4.0.0:
- resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
-
cross-spawn@5.1.0:
resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==}
@@ -3207,9 +3190,6 @@ packages:
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
- csstype@3.2.3:
- resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
-
cytoscape-cose-bilkent@4.1.0:
resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==}
peerDependencies:
@@ -3444,10 +3424,6 @@ packages:
defaults@1.0.4:
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
- define-data-property@1.1.4:
- resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
- engines: {node: '>= 0.4'}
-
degenerator@5.0.1:
resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
engines: {node: '>= 14'}
@@ -3564,14 +3540,6 @@ packages:
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
engines: {node: '>=0.12'}
- es-define-property@1.0.0:
- resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
- engines: {node: '>= 0.4'}
-
- es-errors@1.3.0:
- resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
- engines: {node: '>= 0.4'}
-
es-module-lexer@1.7.0:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
@@ -3715,13 +3683,6 @@ packages:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
- ethereum-cryptography@2.2.1:
- resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==}
-
- ethers@6.13.2:
- resolution: {integrity: sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==}
- engines: {node: '>=14.0.0'}
-
eval@0.1.8:
resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==}
engines: {node: '>= 0.8'}
@@ -3797,6 +3758,15 @@ packages:
fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ fast-string-truncated-width@1.2.1:
+ resolution: {integrity: sha512-Q9acT/+Uu3GwGj+5w/zsGuQjh9O1TyywhIwAxHudtWrgF09nHOPrvTLhQevPbttcxjr/SNN7mJmfOw/B1bXgow==}
+
+ fast-string-width@1.1.0:
+ resolution: {integrity: sha512-O3fwIVIH5gKB38QNbdg+3760ZmGz0SZMgvwJbA1b2TGXceKE6A2cOlfogh1iw8lr049zPyd7YADHy+B7U4W9bQ==}
+
+ fast-wrap-ansi@0.1.6:
+ resolution: {integrity: sha512-HlUwET7a5gqjURj70D5jl7aC3Zmy4weA1SHUfM0JFI0Ptq987NH2TwbBFLoERhfwk+E+eaq4EK3jXoT+R3yp3w==}
+
fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
@@ -3858,9 +3828,6 @@ packages:
debug:
optional: true
- for-each@0.3.3:
- resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
-
foreground-child@3.3.0:
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
engines: {node: '>=14'}
@@ -3912,10 +3879,6 @@ packages:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
- get-intrinsic@1.2.4:
- resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
- engines: {node: '>= 0.4'}
-
get-nonce@1.0.1:
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
engines: {node: '>=6'}
@@ -3986,12 +3949,6 @@ packages:
resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==}
engines: {node: '>=18'}
- globrex@0.1.2:
- resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
-
- gopd@1.0.1:
- resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
-
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
@@ -4009,21 +3966,6 @@ packages:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
- has-property-descriptors@1.0.2:
- resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
-
- has-proto@1.0.3:
- resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
- engines: {node: '>= 0.4'}
-
- has-symbols@1.0.3:
- resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
- engines: {node: '>= 0.4'}
-
- has-tostringtag@1.0.2:
- resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
- engines: {node: '>= 0.4'}
-
hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
@@ -4180,18 +4122,10 @@ packages:
is-alphanumerical@2.0.1:
resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
- is-arguments@1.1.1:
- resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
- engines: {node: '>= 0.4'}
-
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
- is-callable@1.2.7:
- resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
- engines: {node: '>= 0.4'}
-
is-core-module@2.15.0:
resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==}
engines: {node: '>= 0.4'}
@@ -4207,10 +4141,6 @@ packages:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
- is-generator-function@1.0.10:
- resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==}
- engines: {node: '>= 0.4'}
-
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
@@ -4249,10 +4179,6 @@ packages:
resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==}
engines: {node: '>=4'}
- is-typed-array@1.1.13:
- resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==}
- engines: {node: '>= 0.4'}
-
is-unicode-supported@1.3.0:
resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
engines: {node: '>=12'}
@@ -4271,11 +4197,6 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
- isomorphic-ws@5.0.0:
- resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==}
- peerDependencies:
- ws: '>=8.17.1'
-
isows@1.0.7:
resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==}
peerDependencies:
@@ -4527,10 +4448,6 @@ packages:
longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
- loose-envify@1.4.0:
- resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
- hasBin: true
-
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
@@ -4651,11 +4568,13 @@ packages:
mermaid@11.10.1:
resolution: {integrity: sha512-0PdeADVWURz7VMAX0+MiMcgfxFKY4aweSGsjgFihe3XlMKNqmai/cugMrqTd3WNHM93V+K+AZL6Wu6tB5HmxRw==}
- micro-eth-signer@0.15.0:
- resolution: {integrity: sha512-VkKK698Odm0ef40ERC9FdcG6BHBL9vWhy+7xkLL1M0O3bcRBLi7FP7mr+4SdiPaP823Q+r6c8JdUtWdESSf06A==}
+ micro-eth-signer@0.18.1:
+ resolution: {integrity: sha512-vXKhCZxrytpl+dXR9JeaE41ZVFndi7wCKc1Jd22smOMAeDErvRcXaTxhYUf1yQxis4n2kIdv/pH7iuf+5/cj+Q==}
+ engines: {node: '>= 20.19.0'}
- micro-packed@0.7.3:
- resolution: {integrity: sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg==}
+ micro-packed@0.8.0:
+ resolution: {integrity: sha512-AKb8znIvg9sooythbXzyFeChEY0SkW0C6iXECpy/ls0e5BtwXO45J9wD9SLzBztnS4XmF/5kwZknsq+jyynd/A==}
+ engines: {node: '>= 20.19.0'}
micromark-core-commonmark@2.0.1:
resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==}
@@ -4866,6 +4785,11 @@ packages:
nan@2.24.0:
resolution: {integrity: sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==}
+ nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
nanoid@3.3.8:
resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -5159,13 +5083,13 @@ packages:
points-on-path@0.2.1:
resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==}
- possible-typed-array-names@1.0.0:
- resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
- engines: {node: '>= 0.4'}
-
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+ postcss@8.4.47:
+ resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
+ engines: {node: ^10 || ^12 || >=14}
+
postcss@8.5.2:
resolution: {integrity: sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==}
engines: {node: ^10 || ^12 || >=14}
@@ -5282,11 +5206,6 @@ packages:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'}
- react-dom@18.3.1:
- resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
- peerDependencies:
- react: ^18.3.1
-
react-dom@19.0.0:
resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==}
peerDependencies:
@@ -5345,10 +5264,6 @@ packages:
'@types/react':
optional: true
- react@18.3.1:
- resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
- engines: {node: '>=0.10.0'}
-
react@19.0.0:
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
engines: {node: '>=0.10.0'}
@@ -5470,6 +5385,11 @@ packages:
robust-predicates@3.0.2:
resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
+ rollup@4.27.2:
+ resolution: {integrity: sha512-KreA+PzWmk2yaFmZVwe6GB2uBD86nXl86OsDkt1bJS9p3vqWuEQ6HnJJ+j/mZi/q0920P99/MVRlB4L3crpF5w==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
rollup@4.34.7:
resolution: {integrity: sha512-8qhyN0oZ4x0H6wmBgfKxJtxM7qS98YJ0k0kNh5ECVtuchIJ7z9IVVvzpmtQyT10PXKMtBxYr1wQ5Apg8RS8kXQ==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -5493,9 +5413,6 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
- scheduler@0.23.2:
- resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
-
scheduler@0.25.0:
resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
@@ -5536,13 +5453,6 @@ packages:
set-cookie-parser@2.7.1:
resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
- set-function-length@1.2.2:
- resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
- engines: {node: '>= 0.4'}
-
- setimmediate@1.0.5:
- resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
-
setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
@@ -5903,6 +5813,10 @@ packages:
resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==}
engines: {node: '>=14.14'}
+ to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
@@ -5944,8 +5858,8 @@ packages:
ts-morph@24.0.0:
resolution: {integrity: sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw==}
- tsconfck@3.1.1:
- resolution: {integrity: sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ==}
+ tsconfck@3.1.6:
+ resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==}
engines: {node: ^18 || >=20}
hasBin: true
peerDependencies:
@@ -6098,9 +6012,6 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
- util@0.12.5:
- resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==}
-
uuid@10.0.0:
resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
hasBin: true
@@ -6135,14 +6046,6 @@ packages:
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
- vite-tsconfig-paths@5.0.1:
- resolution: {integrity: sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==}
- peerDependencies:
- vite: '*'
- peerDependenciesMeta:
- vite:
- optional: true
-
vite@5.4.10:
resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -6285,82 +6188,6 @@ packages:
web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
- web3-core@4.5.1:
- resolution: {integrity: sha512-mFMOO/IWdKsLL1o2whh3oJ0LCG9P3l5c4lpiMoVsVln3QXh/B0Gf8gW3aY8S+Ixm0OHyzFDXJVc2CodxqmI4Gw==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-errors@1.3.0:
- resolution: {integrity: sha512-j5JkAKCtuVMbY3F5PYXBqg1vWrtF4jcyyMY1rlw8a4PV67AkqlepjGgpzWJZd56Mt+TvHy6DA1F/3Id8LatDSQ==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-eth-abi@4.2.3:
- resolution: {integrity: sha512-rPVwTn0O1CzbtfXwEfIjUP0W5Y7u1OFjugwKpSqJzPQE6+REBg6OELjomTGZBu+GThxHnv0rp15SOxvqp+tyXA==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-eth-accounts@4.2.1:
- resolution: {integrity: sha512-aOlEZFzqAgKprKs7+DGArU4r9b+ILBjThpeq42aY7LAQcP+mSpsWcQgbIRK3r/n3OwTYZ3aLPk0Ih70O/LwnYA==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-eth-contract@4.7.0:
- resolution: {integrity: sha512-fdStoBOjFyMHwlyJmSUt/BTDL1ATwKGmG3zDXQ/zTKlkkW/F/074ut0Vry4GuwSBg9acMHc0ycOiZx9ZKjNHsw==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-eth-ens@4.4.0:
- resolution: {integrity: sha512-DeyVIS060hNV9g8dnTx92syqvgbvPricE3MerCxe/DquNZT3tD8aVgFfq65GATtpCgDDJffO2bVeHp3XBemnSQ==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-eth-iban@4.0.7:
- resolution: {integrity: sha512-8weKLa9KuKRzibC87vNLdkinpUE30gn0IGY027F8doeJdcPUfsa4IlBgNC4k4HLBembBB2CTU0Kr/HAOqMeYVQ==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-eth-personal@4.0.8:
- resolution: {integrity: sha512-sXeyLKJ7ddQdMxz1BZkAwImjqh7OmKxhXoBNF3isDmD4QDpMIwv/t237S3q4Z0sZQamPa/pHebJRWVuvP8jZdw==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-eth@4.8.2:
- resolution: {integrity: sha512-DLV/fIMG6gBp/B0gv0+G4FzxZ4YCDQsY3lzqqv7avwh3uU7/O27aifCUcFd7Ye+3ixTqCjAvLEl9wYSeyG3zQw==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-net@4.1.0:
- resolution: {integrity: sha512-WWmfvHVIXWEoBDWdgKNYKN8rAy6SgluZ0abyRyXOL3ESr7ym7pKWbfP4fjApIHlYTh8tNqkrdPfM4Dyi6CA0SA==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-providers-http@4.2.0:
- resolution: {integrity: sha512-IPMnDtHB7dVwaB7/mMxAZzyq7d5ezfO1+Vw0bNfAeIi7gaDlJiggp85SdyAfOgov8AMUA/dyiY72kQ0KmjXKvQ==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-providers-ipc@4.0.7:
- resolution: {integrity: sha512-YbNqY4zUvIaK2MHr1lQFE53/8t/ejHtJchrWn9zVbFMGXlTsOAbNoIoZWROrg1v+hCBvT2c9z8xt7e/+uz5p1g==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-providers-ws@4.0.8:
- resolution: {integrity: sha512-goJdgata7v4pyzHRsg9fSegUG4gVnHZSHODhNnn6J93ykHkBI1nz4fjlGpcQLUMi4jAMz6SHl9Ibzs2jj9xqPw==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-rpc-methods@1.3.0:
- resolution: {integrity: sha512-/CHmzGN+IYgdBOme7PdqzF+FNeMleefzqs0LVOduncSaqsppeOEoskLXb2anSpzmQAP3xZJPaTrkQPWSJMORig==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-rpc-providers@1.0.0-rc.2:
- resolution: {integrity: sha512-ocFIEXcBx/DYQ90HhVepTBUVnL9pGsZw8wyPb1ZINSenwYus9SvcFkjU1Hfvd/fXjuhAv2bUVch9vxvMx1mXAQ==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-types@1.7.0:
- resolution: {integrity: sha512-nhXxDJ7a5FesRw9UG5SZdP/C/3Q2EzHGnB39hkAV+YGXDMgwxBXFWebQLfEzZzuArfHnvC0sQqkIHNwSKcVjdA==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-utils@4.3.1:
- resolution: {integrity: sha512-kGwOk8FxOLJ9DQC68yqNQc7AzN+k9YDLaW+ZjlAXs3qORhf8zXk5SxWAAGLbLykMs3vTeB0FTb1Exut4JEYfFA==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3-validator@2.0.6:
- resolution: {integrity: sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==}
- engines: {node: '>=14', npm: '>=6.12.0'}
-
- web3@4.12.1:
- resolution: {integrity: sha512-zIFUPdgo2uG5Vbl7C4KrTv8dmWKN3sGnY/GundbiJzcaJZDxaCyu3a5HXAcgUM1VvvsVb1zaUQAFPceq05/q/Q==}
- engines: {node: '>=14.0.0', npm: '>=6.12.0'}
-
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@@ -6385,10 +6212,6 @@ packages:
resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==}
engines: {node: '>=8.15'}
- which-typed-array@1.1.15:
- resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==}
- engines: {node: '>= 0.4'}
-
which@1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
@@ -6418,20 +6241,8 @@ packages:
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
- ws@8.17.1:
- resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==}
- engines: {node: '>=10.0.0'}
- peerDependencies:
- bufferutil: ^4.0.1
- utf-8-validate: '>=5.0.2'
- peerDependenciesMeta:
- bufferutil:
- optional: true
- utf-8-validate:
- optional: true
-
- ws@8.18.3:
- resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
+ ws@8.18.3:
+ resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
@@ -6495,6 +6306,18 @@ packages:
resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==}
engines: {node: '>=18'}
+ zile@0.0.25:
+ resolution: {integrity: sha512-SftBTadMUaUGBoKHsDjGf26fPCuaps0wOmEcTihV2eQ8DzMs+vn1OebXVtNgPN9jAfG6Rh3mZ1Yci/qQPMIhbQ==}
+ hasBin: true
+ peerDependencies:
+ '@typescript/native-preview': '>=7.0.0'
+ typescript: '>=5'
+ peerDependenciesMeta:
+ '@typescript/native-preview':
+ optional: true
+ typescript:
+ optional: true
+
zip-stream@6.0.1:
resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
engines: {node: '>= 14'}
@@ -6516,10 +6339,6 @@ packages:
snapshots:
- '@adraffy/ens-normalize@1.10.1': {}
-
- '@adraffy/ens-normalize@1.11.0': {}
-
'@adraffy/ens-normalize@1.11.1': {}
'@ampproject/remapping@2.3.0':
@@ -6617,10 +6436,14 @@ snapshots:
'@babel/helper-plugin-utils@7.26.5': {}
+ '@babel/helper-string-parser@7.24.8': {}
+
'@babel/helper-string-parser@7.25.9': {}
'@babel/helper-string-parser@7.27.1': {}
+ '@babel/helper-validator-identifier@7.24.7': {}
+
'@babel/helper-validator-identifier@7.25.9': {}
'@babel/helper-validator-identifier@7.28.5': {}
@@ -6632,6 +6455,10 @@ snapshots:
'@babel/template': 7.26.9
'@babel/types': 7.28.5
+ '@babel/parser@7.25.3':
+ dependencies:
+ '@babel/types': 7.28.5
+
'@babel/parser@7.26.9':
dependencies:
'@babel/types': 7.28.5
@@ -6677,6 +6504,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/types@7.25.2':
+ dependencies:
+ '@babel/helper-string-parser': 7.24.8
+ '@babel/helper-validator-identifier': 7.24.7
+ to-fast-properties: 2.0.0
+
'@babel/types@7.26.9':
dependencies:
'@babel/helper-string-parser': 7.25.9
@@ -6921,12 +6754,24 @@ snapshots:
picocolors: 1.1.1
sisteransi: 1.0.5
+ '@clack/core@1.2.0':
+ dependencies:
+ fast-wrap-ansi: 0.1.6
+ sisteransi: 1.0.5
+
'@clack/prompts@0.7.0':
dependencies:
'@clack/core': 0.3.4
picocolors: 1.1.1
sisteransi: 1.0.5
+ '@clack/prompts@1.2.0':
+ dependencies:
+ '@clack/core': 1.2.0
+ fast-string-width: 1.1.0
+ fast-wrap-ansi: 0.1.6
+ sisteransi: 1.0.5
+
'@emotion/hash@0.9.2': {}
'@es-joy/jsdoccomment@0.46.0':
@@ -7184,15 +7029,6 @@ snapshots:
'@eslint/object-schema@2.1.4': {}
- '@ethereumjs/rlp@4.0.1': {}
-
- '@ethereumjs/rlp@5.0.2': {}
-
- '@ethereumjs/util@9.0.3':
- dependencies:
- '@ethereumjs/rlp': 5.0.2
- ethereum-cryptography: 2.2.1
-
'@floating-ui/core@1.6.7':
dependencies:
'@floating-ui/utils': 0.2.9
@@ -7400,24 +7236,18 @@ snapshots:
'@noble/ciphers@1.3.0': {}
- '@noble/curves@1.2.0':
- dependencies:
- '@noble/hashes': 1.3.2
-
- '@noble/curves@1.4.2':
- dependencies:
- '@noble/hashes': 1.4.0
-
'@noble/curves@1.9.1':
dependencies:
'@noble/hashes': 1.8.0
- '@noble/hashes@1.3.2': {}
-
- '@noble/hashes@1.4.0': {}
+ '@noble/curves@2.0.1':
+ dependencies:
+ '@noble/hashes': 2.0.1
'@noble/hashes@1.8.0': {}
+ '@noble/hashes@2.0.1': {}
+
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -7523,83 +7353,77 @@ snapshots:
'@radix-ui/primitive@1.1.1': {}
- '@radix-ui/react-accessible-icon@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-accessible-icon@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-visually-hidden': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-accordion@1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-accordion@1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-collapsible': 1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collapsible': 1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-alert-dialog@1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-alert-dialog@1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dialog': 1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dialog': 1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-arrow@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-arrow@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-aspect-ratio@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-aspect-ratio@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-avatar@1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-avatar@1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-checkbox@1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-checkbox@1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-size': 1.1.0(@types/react@19.0.9)(react@19.0.0)
@@ -7607,35 +7431,32 @@ snapshots:
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-collapsible@1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-collapsible@1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-collection@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-collection@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
'@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.9)(react@19.0.0)':
dependencies:
@@ -7643,19 +7464,18 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.9
- '@radix-ui/react-context-menu@2.2.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-context-menu@2.2.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-menu': 2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-menu': 2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
'@radix-ui/react-context@1.1.1(@types/react@19.0.9)(react@19.0.0)':
dependencies:
@@ -7663,18 +7483,18 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.9
- '@radix-ui/react-dialog@1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-dialog@1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-focus-scope': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
aria-hidden: 1.2.4
@@ -7683,7 +7503,6 @@ snapshots:
react-remove-scroll: 2.6.3(@types/react@19.0.9)(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
'@radix-ui/react-direction@1.1.0(@types/react@19.0.9)(react@19.0.0)':
dependencies:
@@ -7691,33 +7510,31 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.9
- '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-dismissable-layer@1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-dropdown-menu@2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-dropdown-menu@2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-menu': 2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-menu': 2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
'@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.9)(react@19.0.0)':
dependencies:
@@ -7725,47 +7542,44 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.9
- '@radix-ui/react-focus-scope@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-focus-scope@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-form@0.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-form@0.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-label': 2.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-label': 2.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-hover-card@1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-hover-card@1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-popper': 1.2.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
'@radix-ui/react-icons@1.3.2(react@19.0.0)':
dependencies:
@@ -7778,31 +7592,30 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.9
- '@radix-ui/react-label@2.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-label@2.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-menu@2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-menu@2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-focus-scope': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-popper': 1.2.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-roving-focus': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
aria-hidden: 1.2.4
@@ -7811,61 +7624,58 @@ snapshots:
react-remove-scroll: 2.6.3(@types/react@19.0.9)(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-menubar@1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-menubar@1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-menu': 2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-menu': 2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-roving-focus': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-navigation-menu@1.2.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-navigation-menu@1.2.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-visually-hidden': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-popover@1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-popover@1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-focus-scope': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-popper': 1.2.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
aria-hidden: 1.2.4
@@ -7874,15 +7684,14 @@ snapshots:
react-remove-scroll: 2.6.3(@types/react@19.0.9)(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-popper@1.2.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-popper@1.2.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-arrow': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-arrow': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
@@ -7892,19 +7701,17 @@ snapshots:
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-portal@1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-portal@1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-presence@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-presence@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
@@ -7912,36 +7719,33 @@ snapshots:
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-primitive@2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-primitive@2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-progress@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-progress@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-radio-group@1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-radio-group@1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-roving-focus': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-size': 1.1.0(@types/react@19.0.9)(react@19.0.0)
@@ -7949,89 +7753,84 @@ snapshots:
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-roving-focus@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-roving-focus@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-scroll-area@1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-scroll-area@1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/number': 1.1.0
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-select@2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-select@2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/number': 1.1.0
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-focus-scope': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-popper': 1.2.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-visually-hidden': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
aria-hidden: 1.2.4
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
react-remove-scroll: 2.6.3(@types/react@19.0.9)(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-separator@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-separator@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-slider@1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-slider@1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/number': 1.1.0
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.9)(react@19.0.0)
@@ -8040,7 +7839,6 @@ snapshots:
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
'@radix-ui/react-slot@1.1.2(@types/react@19.0.9)(react@19.0.0)':
dependencies:
@@ -8049,12 +7847,12 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.9
- '@radix-ui/react-switch@1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-switch@1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-size': 1.1.0(@types/react@19.0.9)(react@19.0.0)
@@ -8062,104 +7860,97 @@ snapshots:
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-tabs@1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-tabs@1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-roving-focus': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-toast@1.2.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-toast@1.2.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-visually-hidden': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-toggle-group@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-toggle-group@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-toggle': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-roving-focus': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-toggle': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-toggle@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-toggle@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-toolbar@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-toolbar@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-separator': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-toggle-group': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-roving-focus': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-separator': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-toggle-group': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
- '@radix-ui/react-tooltip@1.1.8(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-tooltip@1.1.8(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@radix-ui/primitive': 1.1.1
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-id': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-popper': 1.2.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-visually-hidden': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
'@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.9)(react@19.0.0)':
dependencies:
@@ -8207,14 +7998,13 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.9
- '@radix-ui/react-visually-hidden@1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+ '@radix-ui/react-visually-hidden@1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
'@radix-ui/rect@1.1.0': {}
@@ -8226,60 +8016,114 @@ snapshots:
optionalDependencies:
rollup: 4.34.7
+ '@rollup/rollup-android-arm-eabi@4.27.2':
+ optional: true
+
'@rollup/rollup-android-arm-eabi@4.34.7':
optional: true
+ '@rollup/rollup-android-arm64@4.27.2':
+ optional: true
+
'@rollup/rollup-android-arm64@4.34.7':
optional: true
+ '@rollup/rollup-darwin-arm64@4.27.2':
+ optional: true
+
'@rollup/rollup-darwin-arm64@4.34.7':
optional: true
+ '@rollup/rollup-darwin-x64@4.27.2':
+ optional: true
+
'@rollup/rollup-darwin-x64@4.34.7':
optional: true
+ '@rollup/rollup-freebsd-arm64@4.27.2':
+ optional: true
+
'@rollup/rollup-freebsd-arm64@4.34.7':
optional: true
+ '@rollup/rollup-freebsd-x64@4.27.2':
+ optional: true
+
'@rollup/rollup-freebsd-x64@4.34.7':
optional: true
+ '@rollup/rollup-linux-arm-gnueabihf@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-arm-gnueabihf@4.34.7':
optional: true
+ '@rollup/rollup-linux-arm-musleabihf@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-arm-musleabihf@4.34.7':
optional: true
+ '@rollup/rollup-linux-arm64-gnu@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-arm64-gnu@4.34.7':
optional: true
+ '@rollup/rollup-linux-arm64-musl@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-arm64-musl@4.34.7':
optional: true
'@rollup/rollup-linux-loongarch64-gnu@4.34.7':
optional: true
+ '@rollup/rollup-linux-powerpc64le-gnu@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-powerpc64le-gnu@4.34.7':
optional: true
+ '@rollup/rollup-linux-riscv64-gnu@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-riscv64-gnu@4.34.7':
optional: true
+ '@rollup/rollup-linux-s390x-gnu@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-s390x-gnu@4.34.7':
optional: true
+ '@rollup/rollup-linux-x64-gnu@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-x64-gnu@4.34.7':
optional: true
+ '@rollup/rollup-linux-x64-musl@4.27.2':
+ optional: true
+
'@rollup/rollup-linux-x64-musl@4.34.7':
optional: true
+ '@rollup/rollup-win32-arm64-msvc@4.27.2':
+ optional: true
+
'@rollup/rollup-win32-arm64-msvc@4.34.7':
optional: true
+ '@rollup/rollup-win32-ia32-msvc@4.27.2':
+ optional: true
+
'@rollup/rollup-win32-ia32-msvc@4.34.7':
optional: true
+ '@rollup/rollup-win32-x64-msvc@4.27.2':
+ optional: true
+
'@rollup/rollup-win32-x64-msvc@4.34.7':
optional: true
@@ -8317,15 +8161,9 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
- '@scure/base@1.1.9': {}
-
'@scure/base@1.2.5': {}
- '@scure/bip32@1.4.0':
- dependencies:
- '@noble/curves': 1.4.2
- '@noble/hashes': 1.4.0
- '@scure/base': 1.1.9
+ '@scure/base@2.0.0': {}
'@scure/bip32@1.7.0':
dependencies:
@@ -8333,11 +8171,6 @@ snapshots:
'@noble/hashes': 1.8.0
'@scure/base': 1.2.5
- '@scure/bip39@1.3.0':
- dependencies:
- '@noble/hashes': 1.4.0
- '@scure/base': 1.1.9
-
'@scure/bip39@1.6.0':
dependencies:
'@noble/hashes': 1.8.0
@@ -8528,8 +8361,8 @@ snapshots:
'@types/babel__core@7.20.5':
dependencies:
- '@babel/parser': 7.28.5
- '@babel/types': 7.28.5
+ '@babel/parser': 7.25.3
+ '@babel/types': 7.25.2
'@types/babel__generator': 7.6.8
'@types/babel__template': 7.4.4
'@types/babel__traverse': 7.20.6
@@ -8745,22 +8578,6 @@ snapshots:
dependencies:
undici-types: 6.19.8
- '@types/prop-types@15.7.15': {}
-
- '@types/react-dom@18.3.7(@types/react@18.3.28)':
- dependencies:
- '@types/react': 18.3.28
-
- '@types/react-dom@18.3.7(@types/react@19.0.9)':
- dependencies:
- '@types/react': 19.0.9
- optional: true
-
- '@types/react@18.3.28':
- dependencies:
- '@types/prop-types': 15.7.15
- csstype: 3.2.3
-
'@types/react@19.0.9':
dependencies:
csstype: 3.1.3
@@ -8791,10 +8608,6 @@ snapshots:
dependencies:
'@types/node': 22.5.4
- '@types/ws@8.5.3':
- dependencies:
- '@types/node': 22.5.4
-
'@types/yauzl@2.10.3':
dependencies:
'@types/node': 22.5.4
@@ -8981,17 +8794,6 @@ snapshots:
- supports-color
- terser
- '@vitejs/plugin-react@4.3.4(vite@5.4.10(@types/node@22.5.4)(lightningcss@1.29.1)(terser@5.31.5))':
- dependencies:
- '@babel/core': 7.26.9
- '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.9)
- '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.9)
- '@types/babel__core': 7.20.5
- react-refresh: 0.14.2
- vite: 5.4.10(@types/node@22.5.4)(lightningcss@1.29.1)(terser@5.31.5)
- transitivePeerDependencies:
- - supports-color
-
'@vitejs/plugin-react@4.3.4(vite@6.1.0(@types/node@22.5.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.31.5)(tsx@4.17.0)(yaml@2.5.0))':
dependencies:
'@babel/core': 7.26.9
@@ -9168,12 +8970,6 @@ snapshots:
'@xtuc/long@4.2.2': {}
- abitype@0.7.1(typescript@5.5.4)(zod@3.23.8):
- dependencies:
- typescript: 5.5.4
- optionalDependencies:
- zod: 3.23.8
-
abitype@1.2.3(typescript@5.5.4)(zod@3.23.8):
optionalDependencies:
typescript: 5.5.4
@@ -9197,8 +8993,6 @@ snapshots:
acorn@8.15.0: {}
- aes-js@4.0.0-beta.5: {}
-
agent-base@7.1.1:
dependencies:
debug: 4.4.0
@@ -9335,10 +9129,6 @@ snapshots:
postcss: 8.5.2
postcss-value-parser: 4.2.0
- available-typed-arrays@1.0.7:
- dependencies:
- possible-typed-array-names: 1.0.0
-
b4a@1.6.6: {}
bail@2.0.2: {}
@@ -9497,14 +9287,6 @@ snapshots:
cac@6.7.14: {}
- call-bind@1.0.7:
- dependencies:
- es-define-property: 1.0.0
- es-errors: 1.3.0
- function-bind: 1.1.2
- get-intrinsic: 1.2.4
- set-function-length: 1.2.2
-
callsites@3.1.0: {}
caniuse-lite@1.0.30001680: {}
@@ -9703,12 +9485,6 @@ snapshots:
fs-extra: 11.3.0
picocolors: 1.1.1
- cross-fetch@4.0.0:
- dependencies:
- node-fetch: 2.7.0
- transitivePeerDependencies:
- - encoding
-
cross-spawn@5.1.0:
dependencies:
lru-cache: 4.1.5
@@ -9735,8 +9511,6 @@ snapshots:
csstype@3.1.3: {}
- csstype@3.2.3: {}
-
cytoscape-cose-bilkent@4.1.0(cytoscape@3.33.1):
dependencies:
cose-base: 1.0.3
@@ -9964,12 +9738,6 @@ snapshots:
clone: 1.0.4
optional: true
- define-data-property@1.1.4:
- dependencies:
- es-define-property: 1.0.0
- es-errors: 1.3.0
- gopd: 1.0.1
-
degenerator@5.0.1:
dependencies:
ast-types: 0.13.4
@@ -10082,12 +9850,6 @@ snapshots:
entities@6.0.1: {}
- es-define-property@1.0.0:
- dependencies:
- get-intrinsic: 1.2.4
-
- es-errors@1.3.0: {}
-
es-module-lexer@1.7.0: {}
esbuild@0.21.5:
@@ -10338,26 +10100,6 @@ snapshots:
etag@1.8.1: {}
- ethereum-cryptography@2.2.1:
- dependencies:
- '@noble/curves': 1.4.2
- '@noble/hashes': 1.4.0
- '@scure/bip32': 1.4.0
- '@scure/bip39': 1.3.0
-
- ethers@6.13.2:
- dependencies:
- '@adraffy/ens-normalize': 1.10.1
- '@noble/curves': 1.2.0
- '@noble/hashes': 1.3.2
- '@types/node': 18.15.13
- aes-js: 4.0.0-beta.5
- tslib: 2.4.0
- ws: 8.17.1
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
-
eval@0.1.8:
dependencies:
'@types/node': 22.5.4
@@ -10455,6 +10197,16 @@ snapshots:
fast-levenshtein@2.0.6: {}
+ fast-string-truncated-width@1.2.1: {}
+
+ fast-string-width@1.1.0:
+ dependencies:
+ fast-string-truncated-width: 1.2.1
+
+ fast-wrap-ansi@0.1.6:
+ dependencies:
+ fast-string-width: 1.1.0
+
fastq@1.17.1:
dependencies:
reusify: 1.0.4
@@ -10513,10 +10265,6 @@ snapshots:
follow-redirects@1.15.6: {}
- for-each@0.3.3:
- dependencies:
- is-callable: 1.2.7
-
foreground-child@3.3.0:
dependencies:
cross-spawn: 7.0.6
@@ -10560,14 +10308,6 @@ snapshots:
get-caller-file@2.0.5: {}
- get-intrinsic@1.2.4:
- dependencies:
- es-errors: 1.3.0
- function-bind: 1.1.2
- has-proto: 1.0.3
- has-symbols: 1.0.3
- hasown: 2.0.2
-
get-nonce@1.0.1: {}
get-port@7.1.0: {}
@@ -10650,12 +10390,6 @@ snapshots:
slash: 5.1.0
unicorn-magic: 0.3.0
- globrex@0.1.2: {}
-
- gopd@1.0.1:
- dependencies:
- get-intrinsic: 1.2.4
-
graceful-fs@4.2.11: {}
graphemer@1.4.0: {}
@@ -10666,18 +10400,6 @@ snapshots:
has-flag@4.0.0: {}
- has-property-descriptors@1.0.2:
- dependencies:
- es-define-property: 1.0.0
-
- has-proto@1.0.3: {}
-
- has-symbols@1.0.3: {}
-
- has-tostringtag@1.0.2:
- dependencies:
- has-symbols: 1.0.3
-
hasown@2.0.2:
dependencies:
function-bind: 1.1.2
@@ -10930,17 +10652,10 @@ snapshots:
is-alphabetical: 2.0.1
is-decimal: 2.0.1
- is-arguments@1.1.1:
- dependencies:
- call-bind: 1.0.7
- has-tostringtag: 1.0.2
-
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
- is-callable@1.2.7: {}
-
is-core-module@2.15.0:
dependencies:
hasown: 2.0.2
@@ -10951,10 +10666,6 @@ snapshots:
is-fullwidth-code-point@3.0.0: {}
- is-generator-function@1.0.10:
- dependencies:
- has-tostringtag: 1.0.2
-
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
@@ -10981,10 +10692,6 @@ snapshots:
dependencies:
better-path-resolve: 1.0.0
- is-typed-array@1.1.13:
- dependencies:
- which-typed-array: 1.1.15
-
is-unicode-supported@1.3.0: {}
is-unicode-supported@2.0.0: {}
@@ -10995,10 +10702,6 @@ snapshots:
isexe@2.0.0: {}
- isomorphic-ws@5.0.0(ws@8.18.3):
- dependencies:
- ws: 8.18.3
-
isows@1.0.7(ws@8.18.3):
dependencies:
ws: 8.18.3
@@ -11227,10 +10930,6 @@ snapshots:
longest-streak@3.1.0: {}
- loose-envify@1.4.0:
- dependencies:
- js-tokens: 4.0.0
-
lru-cache@10.4.3: {}
lru-cache@4.1.5:
@@ -11502,15 +11201,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
- micro-eth-signer@0.15.0:
+ micro-eth-signer@0.18.1:
dependencies:
- '@noble/curves': 1.9.1
- '@noble/hashes': 1.8.0
- micro-packed: 0.7.3
+ '@noble/curves': 2.0.1
+ '@noble/hashes': 2.0.1
+ micro-packed: 0.8.0
- micro-packed@0.7.3:
+ micro-packed@0.8.0:
dependencies:
- '@scure/base': 1.2.5
+ '@scure/base': 2.0.0
micromark-core-commonmark@2.0.1:
dependencies:
@@ -11874,6 +11573,8 @@ snapshots:
nan@2.24.0:
optional: true
+ nanoid@3.3.7: {}
+
nanoid@3.3.8: {}
nanoid@5.0.7: {}
@@ -12150,10 +11851,14 @@ snapshots:
path-data-parser: 0.1.0
points-on-curve: 0.2.0
- possible-typed-array-names@1.0.0: {}
-
postcss-value-parser@4.2.0: {}
+ postcss@8.4.47:
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.1.0
+ source-map-js: 1.2.1
+
postcss@8.5.2:
dependencies:
nanoid: 3.3.8
@@ -12267,63 +11972,62 @@ snapshots:
queue-tick@1.0.1: {}
- radix-ui@1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
+ radix-ui@1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
'@radix-ui/primitive': 1.1.1
- '@radix-ui/react-accessible-icon': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-accordion': 1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-alert-dialog': 1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-aspect-ratio': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-avatar': 1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-checkbox': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-collapsible': 1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-accessible-icon': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-accordion': 1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-alert-dialog': 1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-aspect-ratio': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-avatar': 1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-checkbox': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collapsible': 1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-collection': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-context': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-context-menu': 2.2.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-dialog': 1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-context-menu': 2.2.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dialog': 1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-direction': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-dropdown-menu': 2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dismissable-layer': 1.1.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dropdown-menu': 2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-form': 0.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-hover-card': 1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-label': 2.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-menu': 2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-menubar': 1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-navigation-menu': 1.2.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-popover': 1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-popper': 1.2.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-portal': 1.1.4(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-progress': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-radio-group': 1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-scroll-area': 1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-select': 2.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-separator': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-slider': 1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-focus-scope': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-form': 0.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-hover-card': 1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-label': 2.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-menu': 2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-menubar': 1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-navigation-menu': 1.2.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-popover': 1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-popper': 1.2.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-portal': 1.1.4(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-presence': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-primitive': 2.0.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-progress': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-radio-group': 1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-roving-focus': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-scroll-area': 1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-select': 2.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-separator': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-slider': 1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-slot': 1.1.2(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-switch': 1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-tabs': 1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-toast': 1.2.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-toggle': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-toggle-group': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-toolbar': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-tooltip': 1.1.8(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-switch': 1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-tabs': 1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-toast': 1.2.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-toggle': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-toggle-group': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-toolbar': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-tooltip': 1.1.8(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.9)(react@19.0.0)
'@radix-ui/react-use-size': 1.1.0(@types/react@19.0.9)(react@19.0.0)
- '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-visually-hidden': 1.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
optionalDependencies:
'@types/react': 19.0.9
- '@types/react-dom': 18.3.7(@types/react@19.0.9)
randombytes@2.1.0:
dependencies:
@@ -12331,12 +12035,6 @@ snapshots:
range-parser@1.2.1: {}
- react-dom@18.3.1(react@18.3.1):
- dependencies:
- loose-envify: 1.4.0
- react: 18.3.1
- scheduler: 0.23.2
-
react-dom@19.0.0(react@19.0.0):
dependencies:
react: 19.0.0
@@ -12387,10 +12085,6 @@ snapshots:
optionalDependencies:
'@types/react': 19.0.9
- react@18.3.1:
- dependencies:
- loose-envify: 1.4.0
-
react@19.0.0: {}
read-yaml-file@1.1.0:
@@ -12579,6 +12273,30 @@ snapshots:
robust-predicates@3.0.2: {}
+ rollup@4.27.2:
+ dependencies:
+ '@types/estree': 1.0.6
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.27.2
+ '@rollup/rollup-android-arm64': 4.27.2
+ '@rollup/rollup-darwin-arm64': 4.27.2
+ '@rollup/rollup-darwin-x64': 4.27.2
+ '@rollup/rollup-freebsd-arm64': 4.27.2
+ '@rollup/rollup-freebsd-x64': 4.27.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.27.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.27.2
+ '@rollup/rollup-linux-arm64-gnu': 4.27.2
+ '@rollup/rollup-linux-arm64-musl': 4.27.2
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.27.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.27.2
+ '@rollup/rollup-linux-s390x-gnu': 4.27.2
+ '@rollup/rollup-linux-x64-gnu': 4.27.2
+ '@rollup/rollup-linux-x64-musl': 4.27.2
+ '@rollup/rollup-win32-arm64-msvc': 4.27.2
+ '@rollup/rollup-win32-ia32-msvc': 4.27.2
+ '@rollup/rollup-win32-x64-msvc': 4.27.2
+ fsevents: 2.3.3
+
rollup@4.34.7:
dependencies:
'@types/estree': 1.0.6
@@ -12623,10 +12341,6 @@ snapshots:
safer-buffer@2.1.2: {}
- scheduler@0.23.2:
- dependencies:
- loose-envify: 1.4.0
-
scheduler@0.25.0: {}
schema-utils@3.3.0:
@@ -12680,17 +12394,6 @@ snapshots:
set-cookie-parser@2.7.1: {}
- set-function-length@1.2.2:
- dependencies:
- define-data-property: 1.1.4
- es-errors: 1.3.0
- function-bind: 1.1.2
- get-intrinsic: 1.2.4
- gopd: 1.0.1
- has-property-descriptors: 1.0.2
-
- setimmediate@1.0.5: {}
-
setprototypeof@1.2.0: {}
shebang-command@1.2.0:
@@ -13081,6 +12784,8 @@ snapshots:
tmp@0.2.5: {}
+ to-fast-properties@2.0.0: {}
+
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
@@ -13110,7 +12815,7 @@ snapshots:
'@ts-morph/common': 0.25.0
code-block-writer: 13.0.3
- tsconfck@3.1.1(typescript@5.5.4):
+ tsconfck@3.1.6(typescript@5.5.4):
optionalDependencies:
typescript: 5.5.4
@@ -13257,14 +12962,6 @@ snapshots:
util-deprecate@1.0.2: {}
- util@0.12.5:
- dependencies:
- inherits: 2.0.4
- is-arguments: 1.1.1
- is-generator-function: 1.0.10
- is-typed-array: 1.1.13
- which-typed-array: 1.1.15
-
uuid@10.0.0: {}
uuid@11.1.0: {}
@@ -13322,22 +13019,11 @@ snapshots:
- supports-color
- terser
- vite-tsconfig-paths@5.0.1(typescript@5.5.4)(vite@6.1.0(@types/node@22.5.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.31.5)(tsx@4.17.0)(yaml@2.5.0)):
- dependencies:
- debug: 4.3.6
- globrex: 0.1.2
- tsconfck: 3.1.1(typescript@5.5.4)
- optionalDependencies:
- vite: 6.1.0(@types/node@22.5.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.31.5)(tsx@4.17.0)(yaml@2.5.0)
- transitivePeerDependencies:
- - supports-color
- - typescript
-
vite@5.4.10(@types/node@22.5.4)(lightningcss@1.29.1)(terser@5.31.5):
dependencies:
esbuild: 0.21.5
- postcss: 8.5.2
- rollup: 4.34.7
+ postcss: 8.4.47
+ rollup: 4.27.2
optionalDependencies:
'@types/node': 22.5.4
fsevents: 2.3.3
@@ -13396,7 +13082,7 @@ snapshots:
- tsx
- yaml
- vocs@1.0.13(@types/node@22.5.4)(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.7)(terser@5.31.5)(tsx@4.17.0)(typescript@5.5.4)(yaml@2.5.0):
+ vocs@1.0.13(@types/node@22.5.4)(@types/react@19.0.9)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.7)(terser@5.31.5)(tsx@4.17.0)(typescript@5.5.4)(yaml@2.5.0):
dependencies:
'@floating-ui/react': 0.27.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@hono/node-server': 1.13.8(hono@4.7.1)
@@ -13404,13 +13090,13 @@ snapshots:
'@mdx-js/rollup': 3.1.0(rollup@4.34.7)
'@noble/hashes': 1.8.0
'@radix-ui/colors': 3.0.0
- '@radix-ui/react-accordion': 1.2.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-dialog': 1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-accordion': 1.2.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-dialog': 1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@radix-ui/react-icons': 1.3.2(react@19.0.0)
- '@radix-ui/react-label': 2.1.2(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-navigation-menu': 1.2.5(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-popover': 1.1.6(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- '@radix-ui/react-tabs': 1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-label': 2.1.2(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-navigation-menu': 1.2.5(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-popover': 1.1.6(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ '@radix-ui/react-tabs': 1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@shikijs/rehype': 1.22.0
'@shikijs/transformers': 1.22.0
'@shikijs/twoslash': 1.22.0(typescript@5.5.4)
@@ -13445,7 +13131,7 @@ snapshots:
p-limit: 5.0.0
playwright: 1.58.2
postcss: 8.5.2
- radix-ui: 1.1.3(@types/react-dom@18.3.7(@types/react@19.0.9))(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ radix-ui: 1.1.3(@types/react@19.0.9)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
react-intersection-observer: 9.15.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -13516,231 +13202,6 @@ snapshots:
web-namespaces@2.0.1: {}
- web3-core@4.5.1:
- dependencies:
- web3-errors: 1.3.0
- web3-eth-accounts: 4.2.1
- web3-eth-iban: 4.0.7
- web3-providers-http: 4.2.0
- web3-providers-ws: 4.0.8
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
- optionalDependencies:
- web3-providers-ipc: 4.0.7
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - utf-8-validate
-
- web3-errors@1.3.0:
- dependencies:
- web3-types: 1.7.0
-
- web3-eth-abi@4.2.3(typescript@5.5.4)(zod@3.23.8):
- dependencies:
- abitype: 0.7.1(typescript@5.5.4)(zod@3.23.8)
- web3-errors: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
- transitivePeerDependencies:
- - typescript
- - zod
-
- web3-eth-accounts@4.2.1:
- dependencies:
- '@ethereumjs/rlp': 4.0.1
- crc-32: 1.2.2
- ethereum-cryptography: 2.2.1
- web3-errors: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
-
- web3-eth-contract@4.7.0(typescript@5.5.4)(zod@3.23.8):
- dependencies:
- '@ethereumjs/rlp': 5.0.2
- web3-core: 4.5.1
- web3-errors: 1.3.0
- web3-eth: 4.8.2(typescript@5.5.4)(zod@3.23.8)
- web3-eth-abi: 4.2.3(typescript@5.5.4)(zod@3.23.8)
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - typescript
- - utf-8-validate
- - zod
-
- web3-eth-ens@4.4.0(typescript@5.5.4)(zod@3.23.8):
- dependencies:
- '@adraffy/ens-normalize': 1.11.1
- web3-core: 4.5.1
- web3-errors: 1.3.0
- web3-eth: 4.8.2(typescript@5.5.4)(zod@3.23.8)
- web3-eth-contract: 4.7.0(typescript@5.5.4)(zod@3.23.8)
- web3-net: 4.1.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - typescript
- - utf-8-validate
- - zod
-
- web3-eth-iban@4.0.7:
- dependencies:
- web3-errors: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
-
- web3-eth-personal@4.0.8(typescript@5.5.4)(zod@3.23.8):
- dependencies:
- web3-core: 4.5.1
- web3-eth: 4.8.2(typescript@5.5.4)(zod@3.23.8)
- web3-rpc-methods: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - typescript
- - utf-8-validate
- - zod
-
- web3-eth@4.8.2(typescript@5.5.4)(zod@3.23.8):
- dependencies:
- setimmediate: 1.0.5
- web3-core: 4.5.1
- web3-errors: 1.3.0
- web3-eth-abi: 4.2.3(typescript@5.5.4)(zod@3.23.8)
- web3-eth-accounts: 4.2.1
- web3-net: 4.1.0
- web3-providers-ws: 4.0.8
- web3-rpc-methods: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - typescript
- - utf-8-validate
- - zod
-
- web3-net@4.1.0:
- dependencies:
- web3-core: 4.5.1
- web3-rpc-methods: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - utf-8-validate
-
- web3-providers-http@4.2.0:
- dependencies:
- cross-fetch: 4.0.0
- web3-errors: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- transitivePeerDependencies:
- - encoding
-
- web3-providers-ipc@4.0.7:
- dependencies:
- web3-errors: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- optional: true
-
- web3-providers-ws@4.0.8:
- dependencies:
- '@types/ws': 8.5.3
- isomorphic-ws: 5.0.0(ws@8.18.3)
- web3-errors: 1.3.0
- web3-types: 1.7.0
- web3-utils: 4.3.1
- ws: 8.18.3
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
-
- web3-rpc-methods@1.3.0:
- dependencies:
- web3-core: 4.5.1
- web3-types: 1.7.0
- web3-validator: 2.0.6
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - utf-8-validate
-
- web3-rpc-providers@1.0.0-rc.2:
- dependencies:
- web3-errors: 1.3.0
- web3-providers-http: 4.2.0
- web3-providers-ws: 4.0.8
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - utf-8-validate
-
- web3-types@1.7.0: {}
-
- web3-utils@4.3.1:
- dependencies:
- ethereum-cryptography: 2.2.1
- eventemitter3: 5.0.1
- web3-errors: 1.3.0
- web3-types: 1.7.0
- web3-validator: 2.0.6
-
- web3-validator@2.0.6:
- dependencies:
- ethereum-cryptography: 2.2.1
- util: 0.12.5
- web3-errors: 1.3.0
- web3-types: 1.7.0
- zod: 3.23.8
-
- web3@4.12.1(typescript@5.5.4)(zod@3.23.8):
- dependencies:
- web3-core: 4.5.1
- web3-errors: 1.3.0
- web3-eth: 4.8.2(typescript@5.5.4)(zod@3.23.8)
- web3-eth-abi: 4.2.3(typescript@5.5.4)(zod@3.23.8)
- web3-eth-accounts: 4.2.1
- web3-eth-contract: 4.7.0(typescript@5.5.4)(zod@3.23.8)
- web3-eth-ens: 4.4.0(typescript@5.5.4)(zod@3.23.8)
- web3-eth-iban: 4.0.7
- web3-eth-personal: 4.0.8(typescript@5.5.4)(zod@3.23.8)
- web3-net: 4.1.0
- web3-providers-http: 4.2.0
- web3-providers-ws: 4.0.8
- web3-rpc-methods: 1.3.0
- web3-rpc-providers: 1.0.0-rc.2
- web3-types: 1.7.0
- web3-utils: 4.3.1
- web3-validator: 2.0.6
- transitivePeerDependencies:
- - bufferutil
- - encoding
- - typescript
- - utf-8-validate
- - zod
-
webidl-conversions@3.0.1: {}
webpack-sources@3.2.3: {}
@@ -13785,14 +13246,6 @@ snapshots:
load-yaml-file: 0.2.0
path-exists: 4.0.0
- which-typed-array@1.1.15:
- dependencies:
- available-typed-arrays: 1.0.7
- call-bind: 1.0.7
- for-each: 0.3.3
- gopd: 1.0.1
- has-tostringtag: 1.0.2
-
which@1.3.1:
dependencies:
isexe: 2.0.0
@@ -13822,8 +13275,6 @@ snapshots:
wrappy@1.0.2: {}
- ws@8.17.1: {}
-
ws@8.18.3: {}
y18n@5.0.8: {}
@@ -13873,6 +13324,14 @@ snapshots:
yoctocolors@2.1.1: {}
+ zile@0.0.25(typescript@5.5.4):
+ dependencies:
+ '@clack/prompts': 1.2.0
+ cac: 6.7.14
+ tsconfck: 3.1.6(typescript@5.5.4)
+ optionalDependencies:
+ typescript: 5.5.4
+
zip-stream@6.0.1:
dependencies:
archiver-utils: 5.0.2
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 57bde497..148fb3bf 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,8 +1,35 @@
+allowBuilds:
+ bun: true
+ cpu-features: true
+ esbuild: true
+ protobufjs: true
+ simple-git-hooks: true
+ ssh2: true
+
+autoInstallPeers: false
+
+linkWorkspacePackages: true
+
minimumReleaseAge: 1440
minimumReleaseAgeExclude:
- abitype
+
+overrides:
+ viem>ox: npm:ox@0.11.1
+ '@microsoft/api-extractor>typescript': ^5.5.4
+ hono@<4.2.7: '>=4.2.7'
+ ws@>=8.0.0 <8.17.1: '>=8.17.1'
+ hono@<4.5.8: '>=4.5.8'
+ micromatch@<4.0.8: '>=4.0.8'
+ webpack@>=5.0.0-alpha.0 <5.94.0: '>=5.94.0'
+ rollup@>=4.0.0 <4.22.4: '>=4.22.4'
+ hono@<4.6.5: '>=4.6.5'
+
packages:
- - examples/*
- site
- - src
+
+provenance: false
+
+strictPeerDependencies: false
+
trustPolicy: no-downgrade
diff --git a/scripts/build-mine-wasm.ts b/scripts/build-mine-wasm.ts
deleted file mode 100644
index f80b2083..00000000
--- a/scripts/build-mine-wasm.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * Compiles src/tempo/internal/mine.c → WASM → base64 and writes mineWasm.ts.
- *
- * Requirements: LLVM clang with wasm32 target, wasm-opt (binaryen).
- *
- * Usage:
- * pnpm tsx scripts/build-mine-wasm.ts
- */
-
-import * as child_process from 'node:child_process'
-import * as fs from 'node:fs'
-import * as os from 'node:os'
-import * as path from 'node:path'
-
-const root = path.resolve(import.meta.dirname, '..')
-const sourceFile = path.join(root, 'src/tempo/internal/mine.c')
-const outputFile = path.join(root, 'src/tempo/internal/mine.wasm.ts')
-
-function findTool(name: string, candidates: string[]): string {
- for (const candidate of candidates) {
- try {
- child_process.execSync(`${candidate} --version`, { stdio: 'ignore' })
- return candidate
- } catch {}
- }
- throw new Error(`Cannot find ${name}. Tried: ${candidates.join(', ')}`)
-}
-
-const clang = findTool('clang (with wasm32 target)', [
- '/opt/homebrew/opt/llvm/bin/clang', // macOS Homebrew
- '/usr/local/opt/llvm/bin/clang', // macOS Intel Homebrew
- 'clang', // system PATH
-])
-
-const wasmOpt = findTool('wasm-opt (binaryen)', [
- 'wasm-opt',
- '/opt/homebrew/bin/wasm-opt',
- '/usr/local/bin/wasm-opt',
-])
-
-const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'mine-wasm-'))
-const rawWasm = path.join(tmp, 'mine.wasm')
-const optWasm = path.join(tmp, 'mine-opt.wasm')
-
-try {
- console.log(`Compiling ${sourceFile}...`)
- child_process.execSync(
- [
- clang,
- '--target=wasm32',
- '-O3 -flto',
- '-nostdlib -fno-builtin -ffreestanding',
- '-Wl,--no-entry -Wl,--strip-all -Wl,--initial-memory=131072',
- '-Wl,--export=mine',
- `-o ${rawWasm}`,
- sourceFile,
- ].join(' '),
- { stdio: 'inherit' },
- )
-
- console.log('Optimizing with wasm-opt -O4...')
- child_process.execSync(`${wasmOpt} -O4 ${rawWasm} -o ${optWasm}`, {
- stdio: 'inherit',
- })
-
- const binary = new Uint8Array(fs.readFileSync(optWasm))
- const base64 = Buffer.from(binary).toString('base64')
-
- console.log(
- `WASM binary: ${binary.length} bytes → ${base64.length} chars base64`,
- )
-
- fs.writeFileSync(
- outputFile,
- `// Embedded TIP-1022 WASM keccak256 salt miner (compiled from mine.c).
-//
-// Memory layout at offset 1024:
-// [0..19] address (20 bytes, set by JS)
-// [20..51] salt (32 bytes, set/read by JS, incremented in-place)
-// [52..83] hash out (32 bytes, written on match)
-//
-// Exported: mine(count: i32) -> i32 — returns 1 if found, 0 if not.
-//
-// Generated by: pnpm tsx scripts/build-mine-wasm.ts
-
-/** Base64-encoded WASM binary for the TIP-1022 salt miner. */
-export const wasmBase64 =
- '${base64}'
-
-/** Byte offset in WASM linear memory where mining I/O begins. */
-export const dataOffset = 1024
-`,
- )
-
- console.log(`Wrote ${outputFile}`)
-} finally {
- if (fs.existsSync(tmp)) fs.rmSync(tmp, { recursive: true })
-}
diff --git a/scripts/exports:update.ts b/scripts/exports:update.ts
new file mode 100644
index 00000000..1ce5cf38
--- /dev/null
+++ b/scripts/exports:update.ts
@@ -0,0 +1,103 @@
+import { readdirSync } from 'node:fs'
+import { join } from 'node:path'
+import fs from 'fs-extra'
+
+// Generates `package.json#exports` based on the contents of `./src`.
+//
+// Conventions:
+// - `./src/index.ts` → `.`
+// - `./src/index.docs.ts` → `./index.docs`
+// - `./src/core/.ts` → `./` (flattened)
+// - `./src//index.ts` → `./`
+// - `./src//.ts` → `.//`
+//
+// Files starting with `_`, `.`, or a lowercase letter are ignored, as are
+// `*.test.ts`, `*.test-d.ts`, `*.bench.ts`, `*.bench-d.ts`, and `*.snap-d.ts`.
+
+const srcPath = join(import.meta.dirname, '../src')
+const packageJsonPath = join(import.meta.dirname, '../package.json')
+
+const ignoredFiles = new Set(['version.ts'])
+const ignoredSuffixes = [
+ '.test.ts',
+ '.test-d.ts',
+ '.bench.ts',
+ '.bench-d.ts',
+ '.snap-d.ts',
+]
+
+function isExportable(file: string) {
+ if (ignoredFiles.has(file)) return false
+ if (file.startsWith('_') || file.startsWith('.')) return false
+ if (!file.endsWith('.ts')) return false
+ if (ignoredSuffixes.some((s) => file.endsWith(s))) return false
+ return true
+}
+
+function entry(key: string, srcPath: string) {
+ const distPath = srcPath.replace(/^\.\/src\//, './dist/').replace(/\.ts$/, '')
+ return [
+ key,
+ {
+ types: `${distPath}.d.ts`,
+ src: srcPath,
+ default: `${distPath}.js`,
+ },
+ ] as const
+}
+
+const exports: Array = []
+
+// Root: `./` and `./index.docs`
+exports.push(entry('.', './src/index.ts'))
+if (fs.existsSync(join(srcPath, 'index.docs.ts')))
+ exports.push(entry('./index.docs', './src/index.docs.ts'))
+
+// Subdirectories
+const dirs = readdirSync(srcPath, { withFileTypes: true })
+ .filter((d) => d.isDirectory() && !d.name.startsWith('_'))
+ .map((d) => d.name)
+ .sort()
+
+const subExports: Array = []
+
+for (const dir of dirs) {
+ const dirPath = join(srcPath, dir)
+ const files = readdirSync(dirPath).filter(isExportable).sort()
+
+ if (dir === 'core') {
+ // Flatten `core/.ts` → `./`
+ for (const file of files) {
+ const name = file.replace(/\.ts$/, '')
+ if (name === 'index') continue
+ exports.push(entry(`./${name}`, `./src/${dir}/${file}`))
+ }
+ continue
+ }
+
+ // `/index.ts` → `./`
+ if (files.includes('index.ts'))
+ subExports.push(entry(`./${dir}`, `./src/${dir}/index.ts`))
+
+ for (const file of files) {
+ const name = file.replace(/\.ts$/, '')
+ if (name === 'index') continue
+ subExports.push(entry(`./${dir}/${name}`, `./src/${dir}/${file}`))
+ }
+}
+
+// Sort root-level (post-core) entries alphabetically, then append subdir entries.
+const rootSorted = exports
+ .filter(([k]) => k !== '.' && k !== './index.docs')
+ .sort(([a], [b]) => a.localeCompare(b))
+const rootSpecial = exports.filter(
+ ([k]) => k === '.' || k === './index.docs',
+)
+
+const finalEntries = [...rootSpecial, ...rootSorted, ...subExports]
+
+const packageJson = fs.readJsonSync(packageJsonPath)
+packageJson.exports = Object.fromEntries(finalEntries)
+fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 })
+
+console.log(`Updated package.json#exports with ${finalEntries.length} entries.`)
diff --git a/scripts/preconstruct.ts b/scripts/preconstruct.ts
deleted file mode 100644
index 84db856f..00000000
--- a/scripts/preconstruct.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import { basename, dirname, resolve } from 'node:path'
-import fs from 'fs-extra'
-import { getExports } from './utils/exports.js'
-
-console.log('Setting up packages for development.')
-
-const packagePath = resolve(import.meta.dirname, '../src/package.json')
-const packageJson = fs.readJsonSync(packagePath)
-
-console.log(`${packageJson.name} — ${dirname(packagePath)}`)
-
-const dir = resolve(dirname(packagePath))
-
-// Empty dist directories
-fs.emptyDirSync(resolve(dir, '_esm'))
-
-const exports = getExports()
-
-// Link exports to dist locations
-for (const [key, distExports] of Object.entries(exports.dist ?? {})) {
- // Skip `package.json` exports
- if (/package\.json$/.test(key)) continue
-
- let entries: any
- if (typeof distExports === 'string')
- entries = [
- ['default', distExports],
- ['types', distExports.replace('.js', '.d.ts')],
- ]
- else entries = Object.entries(distExports as {})
-
- // Link exports to dist locations
- for (const [, value] of entries as [
- type: 'types' | 'default',
- value: string,
- ][]) {
- if (value.includes('_cjs')) continue
-
- const srcFilePath = resolve(dir, exports.src[key]!)
-
- const distDir = resolve(dir, dirname(value))
- const distFileName = basename(value)
- const distFilePath = resolve(distDir, distFileName)
-
- fs.mkdirSync(distDir, { recursive: true })
-
- // Symlink src to dist file
- try {
- fs.symlinkSync(srcFilePath, distFilePath, 'file')
- } catch {}
- }
-}
-
-console.log('Done.')
diff --git a/scripts/prepublish.ts b/scripts/prepublish.ts
deleted file mode 100644
index 01cc06ac..00000000
--- a/scripts/prepublish.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { join, relative, resolve } from 'node:path'
-import fs from 'fs-extra'
-import { getExports } from './utils/exports.js'
-
-const packageJsonPath = join(import.meta.dirname, '../src/package.json')
-const packageJson = fs.readJsonSync(packageJsonPath)
-
-const jsrJsonPath = join(import.meta.dirname, '../src/jsr.json')
-const jsrJson = fs.readJsonSync(jsrJsonPath)
-
-const exports = getExports({
- onEntry: ({ entryName, name, parentEntryName }) => {
- const modulePath = (dist?: string) => {
- let path = './'
- if (dist) path += `${dist}/`
- if (dist || (parentEntryName && parentEntryName !== 'core'))
- path += `${parentEntryName}/`
- if (dist || name !== 'index') path += name
- return path
- }
-
- try {
- fs.mkdirSync(resolve(import.meta.dirname, '../src', entryName))
- } catch {}
- fs.writeJsonSync(
- resolve(import.meta.dirname, '../src', entryName, 'package.json'),
- {
- type: 'module',
- types: relative(modulePath(), modulePath('_types')) + '.d.ts',
- main: relative(modulePath(), modulePath('_cjs')) + '.js',
- module: relative(modulePath(), modulePath('_esm')) + '.js',
- },
- { spaces: 2 },
- )
- },
-})
-
-packageJson.exports = exports.dist
-jsrJson.exports = exports.src
-
-delete packageJson.type
-
-fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 })
-fs.writeJsonSync(jsrJsonPath, jsrJson, { spaces: 2 })
diff --git a/scripts/utils/exports.ts b/scripts/utils/exports.ts
deleted file mode 100644
index 8b8ad279..00000000
--- a/scripts/utils/exports.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-import { matchesGlob, resolve } from 'node:path'
-import fs from 'fs-extra'
-
-const exclude = [
- '_types',
- '_esm',
- '_cjs',
- 'node_modules',
- 'jsr.json',
- 'tsdoc.json',
- 'version.ts',
-]
-
-export function getExports({
- onEntry,
-}: {
- onEntry?: (entry: {
- entryName: string
- name: string
- parentEntryName?: string | undefined
- }) => void
-} = {}) {
- const dist = {} as Record<
- string,
- string | { types: string; default: string; import: string }
- >
- const src = {} as Record
-
- const entries = fs
- .readdirSync(resolve(import.meta.dirname, '../../src'), {
- withFileTypes: true,
- })
- .filter((entry) => !exclude.some((x) => matchesGlob(entry.name, x)))
-
- for (const parentEntry of entries) {
- if (!parentEntry.isDirectory()) {
- if (parentEntry.name.endsWith('test.ts')) continue
- if (
- !parentEntry.name.endsWith('.ts') &&
- !parentEntry.name.endsWith('.json')
- )
- continue
-
- const name = parentEntry.name.replace(/\.ts$/, '')
- const entryName = `.${name === 'index' ? '' : `/${name}`}`
-
- if (!parentEntry.name.endsWith('.ts')) {
- dist[entryName] = entryName
- src[entryName] = entryName
- } else {
- dist[entryName] = {
- types: `./_types/${name}.d.ts`,
- import: `./_esm/${name}.js`,
- default: `./_cjs/${name}.js`,
- }
- src[entryName] = `./${name}.ts`
-
- if (name === 'index') continue
-
- onEntry?.({ entryName, name })
- }
-
- continue
- }
-
- const entries = fs.readdirSync(
- resolve(parentEntry.parentPath, parentEntry.name),
- {
- withFileTypes: true,
- },
- )
- for (const entry of entries) {
- if (entry.name.endsWith('test.ts')) continue
- if (entry.isDirectory()) continue
-
- const isIndex = entry.name === 'index.ts'
- const name = entry.name.replace(/\.ts$/, '')
-
- if (!/^[A-Z]/.test(name) && name !== 'index') continue
-
- const entryName = `.${parentEntry.name === 'core' ? '' : `/${parentEntry.name}`}${isIndex ? '' : `/${name}`}`
-
- dist[entryName] = {
- types: `./_types/${parentEntry.name}/${name}.d.ts`,
- import: `./_esm/${parentEntry.name}/${name}.js`,
- default: `./_cjs/${parentEntry.name}/${name}.js`,
- }
- src[entryName] = `./${parentEntry.name}/${name}.ts`
-
- if (entryName !== '.')
- onEntry?.({ entryName, name, parentEntryName: parentEntry.name })
- }
- }
-
- return { dist, src }
-}
diff --git a/scripts/update-version.ts b/scripts/version:update.ts
similarity index 89%
rename from scripts/update-version.ts
rename to scripts/version:update.ts
index 9abb3faf..06f5430f 100644
--- a/scripts/update-version.ts
+++ b/scripts/version:update.ts
@@ -3,7 +3,7 @@ import fs from 'fs-extra'
// Writes the current package.json version to `./src/errors/version.ts`.
const versionFilePath = join(import.meta.dirname, '../src/version.ts')
-const packageJsonPath = join(import.meta.dirname, '../src/package.json')
+const packageJsonPath = join(import.meta.dirname, '../package.json')
const packageJson = fs.readJsonSync(packageJsonPath)
fs.writeFileSync(
diff --git a/site/package.json b/site/package.json
index 1d10f60e..4ec07fcc 100644
--- a/site/package.json
+++ b/site/package.json
@@ -15,5 +15,5 @@
"react-dom": "^19",
"vocs": "^1.0.13"
},
- "packageManager": "pnpm@10.15.0"
+ "packageManager": "pnpm@11.0.8"
}
diff --git a/site/pages/guides/json-rpc.md b/site/pages/guides/json-rpc.md
index 25dfac5c..5ad02d08 100644
--- a/site/pages/guides/json-rpc.md
+++ b/site/pages/guides/json-rpc.md
@@ -194,5 +194,5 @@ async function handleRequest(request: RpcRequest.RpcRequest) {
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [RpcRequest](/api/RpcRequest) | Utility types & functions for working with [JSON-RPC 2.0 Requests](https://www.jsonrpc.org/specification#request_object) and Ethereum JSON-RPC methods as defined on the [Ethereum API specification](https://github.com/ethereum/execution-apis) |
| [RpcResponse](/api/RpcResponse) | Utility types & functions for working with [JSON-RPC 2.0 Responses](https://www.jsonrpc.org/specification#response_object) |
-| [RpcSchema](/api/RpcSchema/) | Utility types for working with Ethereum JSON-RPC namespaces & schemas. |
+| [RpcSchema](/api/RpcSchema) | Utility types for working with Ethereum JSON-RPC namespaces & schemas. |
| [RpcTransport](/api/RpcTransport) | Utility functions for working with JSON-RPC Transports. |
diff --git a/src/core/_test/AbiParameters.bench.ts b/src/core/_test/AbiParameters.bench.ts
deleted file mode 100644
index 6b09ea43..00000000
--- a/src/core/_test/AbiParameters.bench.ts
+++ /dev/null
@@ -1,794 +0,0 @@
-import { AbiCoder } from 'ethers'
-import { AbiItem } from 'ox'
-import { bench, describe } from 'vitest'
-import { Web3 } from 'web3'
-
-import { seaportContractConfig } from '../../../test/constants/abis.js'
-import { address } from '../../../test/constants/addresses.js'
-import { decode, encode } from '../AbiParameters.js'
-
-const fulfillAdvancedOrder = AbiItem.fromAbi(
- seaportContractConfig.abi,
- 'fulfillAdvancedOrder',
-)
-
-describe('ABI Decode (static struct)', () => {
- bench('ox: `Abi.decodeParameters`', () => {
- decode(
- fulfillAdvancedOrder.inputs,
- '0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006a0511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000001caab5c3b30000000000000000000000000000000000000000000000000000001caab5c3b3511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a00000000000000000000000000000000000000000000000000000000498f3973511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a0000000000000000000000000000000000000000000000000000000000010f2c0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000005414d89a8bf7e99d732bc52f3e6a3ef461c0c07800000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000034fb5b7000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000001e0f30000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000000312312300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003123123000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004cf000000000000000000000000000000000000000000000000000000000000109200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- )
- })
-
- bench('ethers: `AbiCoder.decode`', () => {
- const coder = new AbiCoder()
- coder.decode(
- fulfillAdvancedOrder.inputs as any,
- '0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006a0511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000001caab5c3b30000000000000000000000000000000000000000000000000000001caab5c3b3511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a00000000000000000000000000000000000000000000000000000000498f3973511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a0000000000000000000000000000000000000000000000000000000000010f2c0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000005414d89a8bf7e99d732bc52f3e6a3ef461c0c07800000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000034fb5b7000000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000001e0f30000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001a4000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000000312312300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003123123000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004cf000000000000000000000000000000000000000000000000000000000000109200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- )
- })
-})
-
-const web3 = new Web3()
-
-describe('ABI Encode', () => {
- bench('ox: `encodeAbi`', () => {
- encode(
- [
- {
- components: [
- {
- components: [
- {
- name: 'x',
- type: 'uint256',
- },
- {
- name: 'y',
- type: 'bool',
- },
- {
- name: 'z',
- type: 'address',
- },
- ],
- name: 'foo',
- type: 'tuple',
- },
- {
- components: [
- {
- name: 'x',
- type: 'uint256',
- },
- {
- name: 'y',
- type: 'bool',
- },
- {
- name: 'z',
- type: 'address',
- },
- ],
- name: 'baz',
- type: 'tuple',
- },
- {
- name: 'x',
- type: 'uint8[2]',
- },
- ],
- name: 'barOut',
- type: 'tuple',
- },
- ],
- [
- {
- foo: {
- x: 420n,
- y: true,
- z: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
- },
- baz: {
- x: 69n,
- y: false,
- z: '0xc961145a54C96E3aE9bAA048c4F4D6b04C13916b',
- },
- x: [1, 2],
- },
- ],
- )
- })
-
- bench('ethers: `AbiCoder.encode`', () => {
- const coder = new AbiCoder()
- coder.encode(
- [
- {
- components: [
- {
- components: [
- {
- name: 'x',
- type: 'uint256',
- },
- {
- name: 'y',
- type: 'bool',
- },
- {
- name: 'z',
- type: 'address',
- },
- ],
- name: 'foo',
- type: 'tuple',
- },
- {
- components: [
- {
- name: 'x',
- type: 'uint256',
- },
- {
- name: 'y',
- type: 'bool',
- },
- {
- name: 'z',
- type: 'address',
- },
- ],
- name: 'baz',
- type: 'tuple',
- },
- {
- name: 'x',
- type: 'uint8[2]',
- },
- ],
- name: 'barOut',
- type: 'tuple',
- },
- ] as any,
- [
- {
- foo: {
- x: 420n,
- y: true,
- z: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
- },
- baz: {
- x: 69n,
- y: false,
- z: '0xc961145a54C96E3aE9bAA048c4F4D6b04C13916b',
- },
- x: [1, 2],
- },
- ],
- )
- })
-
- bench('web3: `encodeParameters`', () => {
- web3.eth.abi.encodeParameters(
- [
- {
- components: [
- {
- components: [
- {
- name: 'x',
- type: 'uint256',
- },
- {
- name: 'y',
- type: 'bool',
- },
- {
- name: 'z',
- type: 'address',
- },
- ],
- name: 'foo',
- type: 'tuple',
- },
- {
- components: [
- {
- name: 'x',
- type: 'uint256',
- },
- {
- name: 'y',
- type: 'bool',
- },
- {
- name: 'z',
- type: 'address',
- },
- ],
- name: 'baz',
- type: 'tuple',
- },
- {
- name: 'x',
- type: 'uint8[2]',
- },
- ],
- name: 'barOut',
- type: 'tuple',
- },
- ],
- [
- {
- foo: {
- x: 420n,
- y: true,
- z: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC',
- },
- baz: {
- x: 69n,
- y: false,
- z: '0xc961145a54C96E3aE9bAA048c4F4D6b04C13916b',
- },
- x: [1, 2],
- },
- ],
- )
- })
-})
-
-describe('Seaport function', () => {
- bench('ox: `encodeAbi`', () => {
- encode(
- [
- {
- components: [
- { name: 'offerer', type: 'address' },
- { name: 'zone', type: 'address' },
- {
- components: [
- {
- name: 'itemType',
- type: 'uint8',
- },
- { name: 'token', type: 'address' },
- {
- name: 'identifierOrCriteria',
- type: 'uint256',
- },
- {
- name: 'startAmount',
- type: 'uint256',
- },
- { name: 'endAmount', type: 'uint256' },
- ],
-
- name: 'offer',
- type: 'tuple[]',
- },
- {
- components: [
- {
- name: 'itemType',
- type: 'uint8',
- },
- { name: 'token', type: 'address' },
- {
- name: 'identifierOrCriteria',
- type: 'uint256',
- },
- {
- name: 'startAmount',
- type: 'uint256',
- },
- { name: 'endAmount', type: 'uint256' },
- {
- name: 'recipient',
- type: 'address',
- },
- ],
-
- name: 'consideration',
- type: 'tuple[]',
- },
- {
- name: 'orderType',
- type: 'uint8',
- },
- { name: 'startTime', type: 'uint256' },
- { name: 'endTime', type: 'uint256' },
- { name: 'zoneHash', type: 'bytes32' },
- { name: 'salt', type: 'uint256' },
- { name: 'conduitKey', type: 'bytes32' },
- { name: 'counter', type: 'uint256' },
- ],
-
- name: 'orders',
- type: 'tuple[]',
- },
- ],
- [
- [
- {
- conduitKey:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- consideration: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- recipient: address.vitalik,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 141n,
- identifierOrCriteria: 55n,
- itemType: 16,
- recipient: address.vitalik,
- startAmount: 15n,
- token: address.burn,
- },
- ],
- counter: 1234123123n,
- endTime: 123123123123n,
- offer: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 11n,
- identifierOrCriteria: 515n,
- itemType: 10,
- startAmount: 6n,
- token: address.usdcHolder,
- },
- {
- endAmount: 123123n,
- identifierOrCriteria: 55555511n,
- itemType: 10,
- startAmount: 111n,
- token: address.vitalik,
- },
- ],
- offerer: address.vitalik,
- orderType: 10,
- salt: 1234123123n,
- startTime: 123123123123n,
- zone: address.vitalik,
- zoneHash:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- },
- {
- conduitKey:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- consideration: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- recipient: address.vitalik,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 141n,
- identifierOrCriteria: 55n,
- itemType: 16,
- recipient: address.vitalik,
- startAmount: 15n,
- token: address.burn,
- },
- ],
- counter: 1234123123n,
- endTime: 123123123123n,
- offer: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 11n,
- identifierOrCriteria: 515n,
- itemType: 10,
- startAmount: 6n,
- token: address.usdcHolder,
- },
- {
- endAmount: 123123n,
- identifierOrCriteria: 55555511n,
- itemType: 10,
- startAmount: 111n,
- token: address.vitalik,
- },
- ],
- offerer: address.vitalik,
- orderType: 10,
- salt: 1234123123n,
- startTime: 123123123123n,
- zone: address.vitalik,
- zoneHash:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- },
- ],
- ],
- )
- })
-
- bench('ethers: `AbiCoder.encode`', () => {
- const coder = new AbiCoder()
- coder.encode(
- [
- {
- components: [
- { name: 'offerer', type: 'address' },
- { name: 'zone', type: 'address' },
- {
- components: [
- {
- name: 'itemType',
- type: 'uint8',
- },
- { name: 'token', type: 'address' },
- {
- name: 'identifierOrCriteria',
- type: 'uint256',
- },
- {
- name: 'startAmount',
- type: 'uint256',
- },
- { name: 'endAmount', type: 'uint256' },
- ],
-
- name: 'offer',
- type: 'tuple[]',
- },
- {
- components: [
- {
- name: 'itemType',
- type: 'uint8',
- },
- { name: 'token', type: 'address' },
- {
- name: 'identifierOrCriteria',
- type: 'uint256',
- },
- {
- name: 'startAmount',
- type: 'uint256',
- },
- { name: 'endAmount', type: 'uint256' },
- {
- name: 'recipient',
- type: 'address',
- },
- ],
-
- name: 'consideration',
- type: 'tuple[]',
- },
- {
- name: 'orderType',
- type: 'uint8',
- },
- { name: 'startTime', type: 'uint256' },
- { name: 'endTime', type: 'uint256' },
- { name: 'zoneHash', type: 'bytes32' },
- { name: 'salt', type: 'uint256' },
- { name: 'conduitKey', type: 'bytes32' },
- { name: 'counter', type: 'uint256' },
- ],
-
- name: 'orders',
- type: 'tuple[]',
- },
- ] as any,
- [
- [
- {
- conduitKey:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- consideration: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- recipient: address.vitalik,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 141n,
- identifierOrCriteria: 55n,
- itemType: 16,
- recipient: address.vitalik,
- startAmount: 15n,
- token: address.burn,
- },
- ],
- counter: 1234123123n,
- endTime: 123123123123n,
- offer: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 11n,
- identifierOrCriteria: 515n,
- itemType: 10,
- startAmount: 6n,
- token: address.usdcHolder,
- },
- {
- endAmount: 123123n,
- identifierOrCriteria: 55555511n,
- itemType: 10,
- startAmount: 111n,
- token: address.vitalik,
- },
- ],
- offerer: address.vitalik,
- orderType: 10,
- salt: 1234123123n,
- startTime: 123123123123n,
- zone: address.vitalik,
- zoneHash:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- },
- {
- conduitKey:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- consideration: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- recipient: address.vitalik,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 141n,
- identifierOrCriteria: 55n,
- itemType: 16,
- recipient: address.vitalik,
- startAmount: 15n,
- token: address.burn,
- },
- ],
- counter: 1234123123n,
- endTime: 123123123123n,
- offer: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 11n,
- identifierOrCriteria: 515n,
- itemType: 10,
- startAmount: 6n,
- token: address.usdcHolder,
- },
- {
- endAmount: 123123n,
- identifierOrCriteria: 55555511n,
- itemType: 10,
- startAmount: 111n,
- token: address.vitalik,
- },
- ],
- offerer: address.vitalik,
- orderType: 10,
- salt: 1234123123n,
- startTime: 123123123123n,
- zone: address.vitalik,
- zoneHash:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- },
- ],
- ],
- )
- })
-
- bench('web3: `encodeParameters`', () => {
- web3.eth.abi.encodeParameters(
- [
- {
- components: [
- { name: 'offerer', type: 'address' },
- { name: 'zone', type: 'address' },
- {
- components: [
- {
- name: 'itemType',
- type: 'uint8',
- },
- { name: 'token', type: 'address' },
- {
- name: 'identifierOrCriteria',
- type: 'uint256',
- },
- {
- name: 'startAmount',
- type: 'uint256',
- },
- { name: 'endAmount', type: 'uint256' },
- ],
-
- name: 'offer',
- type: 'tuple[]',
- },
- {
- components: [
- {
- name: 'itemType',
- type: 'uint8',
- },
- { name: 'token', type: 'address' },
- {
- name: 'identifierOrCriteria',
- type: 'uint256',
- },
- {
- name: 'startAmount',
- type: 'uint256',
- },
- { name: 'endAmount', type: 'uint256' },
- {
- name: 'recipient',
- type: 'address',
- },
- ],
-
- name: 'consideration',
- type: 'tuple[]',
- },
- {
- name: 'orderType',
- type: 'uint8',
- },
- { name: 'startTime', type: 'uint256' },
- { name: 'endTime', type: 'uint256' },
- { name: 'zoneHash', type: 'bytes32' },
- { name: 'salt', type: 'uint256' },
- { name: 'conduitKey', type: 'bytes32' },
- { name: 'counter', type: 'uint256' },
- ],
-
- name: 'orders',
- type: 'tuple[]',
- },
- ],
- [
- [
- {
- conduitKey:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- consideration: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- recipient: address.vitalik,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 141n,
- identifierOrCriteria: 55n,
- itemType: 16,
- recipient: address.vitalik,
- startAmount: 15n,
- token: address.burn,
- },
- ],
- counter: 1234123123n,
- endTime: 123123123123n,
- offer: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 11n,
- identifierOrCriteria: 515n,
- itemType: 10,
- startAmount: 6n,
- token: address.usdcHolder,
- },
- {
- endAmount: 123123n,
- identifierOrCriteria: 55555511n,
- itemType: 10,
- startAmount: 111n,
- token: address.vitalik,
- },
- ],
- offerer: address.vitalik,
- orderType: 10,
- salt: 1234123123n,
- startTime: 123123123123n,
- zone: address.vitalik,
- zoneHash:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- },
- {
- conduitKey:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- consideration: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- recipient: address.vitalik,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 141n,
- identifierOrCriteria: 55n,
- itemType: 16,
- recipient: address.vitalik,
- startAmount: 15n,
- token: address.burn,
- },
- ],
- counter: 1234123123n,
- endTime: 123123123123n,
- offer: [
- {
- endAmount: 420n,
- identifierOrCriteria: 69n,
- itemType: 10,
- startAmount: 6n,
- token: address.burn,
- },
- {
- endAmount: 11n,
- identifierOrCriteria: 515n,
- itemType: 10,
- startAmount: 6n,
- token: address.usdcHolder,
- },
- {
- endAmount: 123123n,
- identifierOrCriteria: 55555511n,
- itemType: 10,
- startAmount: 111n,
- token: address.vitalik,
- },
- ],
- offerer: address.vitalik,
- orderType: 10,
- salt: 1234123123n,
- startTime: 123123123123n,
- zone: address.vitalik,
- zoneHash:
- '0x511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511aaa511a',
- },
- ],
- ],
- )
- })
-})
diff --git a/src/core/_test/Address.bench.ts b/src/core/_test/Address.bench.ts
deleted file mode 100644
index 3b7325a3..00000000
--- a/src/core/_test/Address.bench.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as ethers from 'ethers'
-import { Address } from 'ox'
-import { bench, describe } from 'vitest'
-
-describe('Address', () => {
- bench('ox: `Address.from`', () => {
- Address.from('0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC')
- })
-
- bench('ethers: `getAddress`', () => {
- ethers.getAddress('0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC')
- })
-})
diff --git a/src/core/_test/Base58.bench.ts b/src/core/_test/Base58.bench.ts
deleted file mode 100644
index 4f17eead..00000000
--- a/src/core/_test/Base58.bench.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { encodeBase58 } from 'ethers'
-import { Hex } from 'ox'
-import { bench, describe } from 'vitest'
-import { fromBytes, fromHex } from '../Base58.js'
-
-const bytes = new Uint8Array([
- 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
-])
-const hex = Hex.from(bytes)
-
-describe('base58 encode (bytes)', () => {
- bench('ethers', () => {
- encodeBase58(bytes)
- })
-
- bench('ox', () => {
- fromBytes(bytes)
- })
-})
-
-describe('base58 encode (hex)', () => {
- bench('ethers', () => {
- encodeBase58(hex)
- })
-
- bench('ox', () => {
- fromHex(hex)
- })
-})
diff --git a/src/core/_test/BinaryStateTree.bench.ts b/src/core/_test/BinaryStateTree.bench.ts
deleted file mode 100644
index 8fa3a9e5..00000000
--- a/src/core/_test/BinaryStateTree.bench.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { bench } from 'vitest'
-import * as BinaryStateTree from '../BinaryStateTree.js'
-import * as Bytes from '../Bytes.js'
-import type * as Hex from '../Hex.js'
-
-bench('default', () => {
- const tree = BinaryStateTree.create()
- for (let i = 0; i < 1 << 8; i++) {
- const key = Bytes.fromHex(
- ('0x' + i.toString(16).padStart(2, '0') + '00'.repeat(31)) as Hex.Hex,
- )
- BinaryStateTree.insert(
- tree,
- key,
- Bytes.fromHex(('0x' + 'FF'.repeat(32)) as Hex.Hex),
- )
- }
-})
diff --git a/src/core/_test/Hex.bench.ts b/src/core/_test/Hex.bench.ts
deleted file mode 100644
index 54cc3c01..00000000
--- a/src/core/_test/Hex.bench.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { bytesToHex as bytesToHex_ethjs } from '@ethereumjs/util'
-import * as ethers from 'ethers'
-import { bench, describe } from 'vitest'
-import { Bytes } from '../../index.js'
-import * as Hex from '../Hex.js'
-
-// TODO: random hex
-describe('concat (hex)', () => {
- bench('ox', () => {
- Hex.concat(
- '0xdeadbeefdeadbeefdeadbeef',
- '0xdeadbeefdeadbeefdeadbeef',
- '0xdeadbeefdeadbeefdeadbeef',
- '0xdeadbeefdeadbeefdeadbeef',
- )
- })
-
- bench('ethers', () => {
- ethers.concat([
- '0xdeadbeefdeadbeefdeadbeef',
- '0xdeadbeefdeadbeefdeadbeef',
- '0xdeadbeefdeadbeefdeadbeef',
- '0xdeadbeefdeadbeefdeadbeef',
- ])
- })
-})
-
-describe('number to hex', () => {
- bench('ox: `Hex.fromNumber`', () => {
- Hex.fromNumber(52)
- })
-
- bench('ethers: `hexlify`', () => {
- ethers.toBeHex(52)
- })
-})
-
-describe('string to hex', () => {
- bench('ox: `Hex.fromString`', () => {
- Hex.fromString('Hello world.')
- })
-
- bench('ethers: `hexlify`', () => {
- ethers.hexlify(ethers.toUtf8Bytes('Hello world.'))
- })
-})
-
-describe('bytes to hex', () => {
- const bytes = Bytes.random(1024)
-
- bench('ox: `Hex.fromBytes`', () => {
- Hex.fromBytes(bytes)
- })
-
- bench('ethers: `bytesToHex`', () => {
- ethers.hexlify(new Uint8Array(bytes))
- })
-
- bench('@ethereumjs/util: `bytesToHex`', () => {
- bytesToHex_ethjs(bytes)
- })
-})
diff --git a/src/core/_test/Kzg.test.ts b/src/core/_test/Kzg.test.ts
index 01d9b170..d6907f81 100644
--- a/src/core/_test/Kzg.test.ts
+++ b/src/core/_test/Kzg.test.ts
@@ -1,7 +1,7 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { trustedSetup as fastSetup } from '@paulmillr/trusted-setups/fast-kzg.js'
-import { KZG } from 'micro-eth-signer/kzg.js'
+import { KZG } from 'micro-eth-signer/advanced/kzg.js'
import { Bytes, Hex, Kzg } from 'ox'
import { describe, expect, test } from 'vitest'
diff --git a/src/core/_test/Rlp.bench.ts b/src/core/_test/Rlp.bench.ts
deleted file mode 100644
index 4eca25e7..00000000
--- a/src/core/_test/Rlp.bench.ts
+++ /dev/null
@@ -1,252 +0,0 @@
-import { RLP } from '@ethereumjs/rlp'
-import * as ethers from 'ethers'
-import { Rlp } from 'ox'
-import { bench, describe } from 'vitest'
-
-const generateBytes = (length: number) => {
- const bytes = new Uint8Array(length)
- for (let i = 0; i < length; i++) bytes[i] = i
- return bytes
-}
-
-const generateList = (length: number) => {
- const bytes = []
- for (let i = 0; i < length; i++) bytes[i] = generateBytes(i)
- return bytes
-}
-
-describe('Rlp.to', () => {
- describe('rlp: prefix === 0xb8', () => {
- const bytes = Rlp.fromBytes(generateBytes(255))
-
- bench('ox: `Rlp.toBytes`', () => {
- Rlp.toBytes(bytes)
- })
-
- bench('ethers: `decodeRlp`', () => {
- ethers.decodeRlp(bytes as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.decode`', () => {
- RLP.decode(bytes)
- })
- })
-
- describe('rlp: prefix === 0xb9', () => {
- const bytes = Rlp.fromBytes(generateBytes(65_535))
-
- bench('ox: `Rlp.toBytes`', () => {
- Rlp.toBytes(bytes)
- })
-
- bench('ethers: `decodeRlp`', () => {
- ethers.decodeRlp(bytes as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.decode`', () => {
- RLP.decode(bytes)
- })
- })
-
- describe('rlp: prefix === 0xba', () => {
- const bytes = Rlp.fromBytes(generateBytes(16_777_215))
-
- bench('ox: `Rlp.toBytes`', () => {
- Rlp.toBytes(bytes)
- })
-
- bench.skip('ethers: `decodeRlp`', () => {
- ethers.decodeRlp(bytes as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.decode`', () => {
- RLP.decode(bytes)
- })
- })
-
- describe('rlp list: prefix === 0xf8', () => {
- const list = Rlp.fromBytes(generateList(60))
-
- bench('ox: `Rlp.toBytes`', () => {
- Rlp.toBytes(list)
- })
-
- bench('ethers: `decodeRlp`', () => {
- ethers.decodeRlp(list as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.decode`', () => {
- RLP.decode(list)
- })
- })
-
- describe('rlp list: prefix === 0xf8 (recursive)', () => {
- const list = Rlp.fromBytes([
- generateList(4),
- [generateList(8), [generateList(3), generateBytes(1)]],
- [
- generateList(10),
- [
- generateList(5),
- generateBytes(2),
- [generateList(10), [generateList(20)]],
- ],
- ],
- ])
-
- bench('ox: `Rlp.toBytes`', () => {
- Rlp.toBytes(list)
- })
-
- bench('ethers: `decodeRlp`', () => {
- ethers.decodeRlp(list as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.decode`', () => {
- RLP.decode(list)
- })
- })
-
- describe('rlp: tx (2048kB - prefix: 0xfa)', () => {
- const list = Rlp.fromBytes([
- generateBytes(1),
- generateBytes(4),
- generateBytes(8),
- generateBytes(8),
- generateBytes(4),
- generateBytes(20),
- generateBytes(8),
- generateBytes(2_048_000),
- ])
-
- bench('ox: `Rlp.toBytes`', () => {
- Rlp.toBytes(list)
- })
-
- bench('ethers: `decodeRlp`', () => {
- ethers.decodeRlp(list as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.decode`', () => {
- RLP.decode(list, true)
- })
- })
-})
-
-describe('Rlp.from', () => {
- describe('rlp: prefix === 0xb8', () => {
- const bytes = generateBytes(255)
-
- bench('ox: `Rlp.fromBytes`', () => {
- Rlp.fromBytes(bytes)
- })
-
- bench('ethers: `encodeRlp`', () => {
- ethers.encodeRlp(bytes as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.encode`', () => {
- RLP.encode(bytes as any)
- })
- })
-
- describe('rlp: prefix === 0xb9', () => {
- const bytes = generateBytes(65_535)
-
- bench('ox: `Rlp.fromBytes`', () => {
- Rlp.fromBytes(bytes)
- })
-
- bench('ethers: `encodeRlp`', () => {
- ethers.encodeRlp(bytes as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.encode`', () => {
- RLP.encode(bytes as any)
- })
- })
-
- describe('rlp: prefix === 0xba', () => {
- const bytes = generateBytes(16_777_215)
-
- bench('ox: `Rlp.fromBytes`', () => {
- Rlp.fromBytes(bytes)
- })
-
- bench.skip('ethers: `encodeRlp`', () => {
- ethers.encodeRlp(bytes as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.encode`', () => {
- RLP.encode(bytes as any)
- })
- })
-
- describe('rlp list: prefix === 0xf8', () => {
- const list = generateList(60)
-
- bench('ox: `Rlp.fromBytes`', () => {
- Rlp.fromBytes(list)
- })
-
- bench('ethers: `encodeRlp`', () => {
- ethers.encodeRlp(list as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.encode`', () => {
- RLP.encode(list as any)
- })
- })
-
- describe('rlp list: prefix === 0xf8 (recursive)', () => {
- const list = [
- generateList(4),
- [generateList(8), [generateList(3), generateBytes(1)]],
- [
- generateList(10),
- [
- generateList(5),
- generateBytes(2),
- [generateList(10), [generateList(20)]],
- ],
- ],
- ]
-
- bench('ox: `Rlp.fromBytes`', () => {
- Rlp.fromBytes(list)
- })
-
- bench('ethers: `encodeRlp`', () => {
- ethers.encodeRlp(list as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.encode`', () => {
- RLP.encode(list as any)
- })
- })
-
- describe.skip('rlp: tx (2048kB - prefix: 0xfa)', () => {
- const list = [
- generateBytes(1),
- generateBytes(4),
- generateBytes(8),
- generateBytes(8),
- generateBytes(4),
- generateBytes(20),
- generateBytes(8),
- generateBytes(2_048_000),
- ]
-
- bench('ox: `Rlp.fromBytes`', () => {
- Rlp.fromBytes(list)
- })
-
- bench('ethers: `encodeRlp`', () => {
- ethers.encodeRlp(list as any)
- })
-
- bench('@ethereumjs/rlp: `RLP.encode`', () => {
- RLP.encode(list as any)
- })
- })
-})
diff --git a/src/jsr.json b/src/jsr.json
index c72108b4..538b803c 100644
--- a/src/jsr.json
+++ b/src/jsr.json
@@ -1,6 +1,6 @@
{
"name": "@wevm/ox",
- "version": "0.14.20",
+ "version": "0.14.13",
"publish": {
"include": ["LICENSE", "README.md", "CHANGELOG.md", "**/*.ts"],
"exclude": [
diff --git a/src/package.json b/src/package.json
deleted file mode 100644
index d4adfb9b..00000000
--- a/src/package.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "name": "ox",
- "description": "Ethereum Standard Library",
- "version": "0.14.20",
- "type": "module",
- "main": "./_cjs/index.js",
- "module": "./_esm/index.js",
- "types": "./_types/index.d.ts",
- "typings": "./_types/index.d.ts",
- "sideEffects": false,
- "files": [
- "*",
- "!**/_test/**",
- "!**/*.tsbuildinfo",
- "!tsconfig.build.json",
- "!jsr.json"
- ],
- "dependencies": {
- "@adraffy/ens-normalize": "^1.11.0",
- "@noble/ciphers": "^1.3.0",
- "@noble/curves": "1.9.1",
- "@noble/hashes": "^1.8.0",
- "@scure/bip32": "^1.7.0",
- "@scure/bip39": "^1.6.0",
- "abitype": "^1.2.3",
- "eventemitter3": "5.0.1"
- },
- "peerDependencies": {
- "typescript": ">=5.4.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- },
- "license": "MIT",
- "homepage": "https://wevm.dev",
- "repository": "wevm/ox",
- "authors": [
- "awkweb",
- "jxom"
- ],
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/wevm"
- }
- ],
- "keywords": [
- "ethereum",
- "standard",
- "library",
- "typescript",
- "evm"
- ]
-}
diff --git a/src/tsconfig.json b/src/tsconfig.json
new file mode 100644
index 00000000..8ee3ee02
--- /dev/null
+++ b/src/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "types": ["node"]
+ },
+ "include": ["./**/*.ts"],
+ "exclude": [
+ "./**/*.test.ts",
+ "./**/*.test-d.ts",
+ "./**/*.bench.ts",
+ "./**/*.bench-d.ts",
+ "./**/*.snap-d.ts",
+ "./**/*.browser.test.ts"
+ ]
+}
diff --git a/test/kzg.ts b/test/kzg.ts
index 6cece0a6..60f41735 100644
--- a/test/kzg.ts
+++ b/test/kzg.ts
@@ -1,7 +1,7 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { trustedSetup as fastSetup } from '@paulmillr/trusted-setups/fast-kzg.js'
-import { KZG } from 'micro-eth-signer/kzg.js'
+import { KZG } from 'micro-eth-signer/advanced/kzg.js'
import { Bytes, Hex, Kzg } from 'ox'
const k = new KZG(fastSetup)
diff --git a/test/tsconfig.json b/test/tsconfig.json
new file mode 100644
index 00000000..4cb92276
--- /dev/null
+++ b/test/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "types": ["node", "vitest/importMeta"],
+ "paths": {
+ "ox": ["../src/index.ts"],
+ "ox/erc4337": ["../src/erc4337/index.ts"],
+ "ox/erc6492": ["../src/erc6492/index.ts"],
+ "ox/erc7821": ["../src/erc7821/index.ts"],
+ "ox/erc8010": ["../src/erc8010/index.ts"],
+ "ox/erc8021": ["../src/erc8021/index.ts"],
+ "ox/tempo": ["../src/tempo/index.ts"],
+ "ox/trusted-setups": ["../src/trusted-setups/index.ts"],
+ "ox/webauthn": ["../src/webauthn/index.ts"],
+ "ox/window": ["../src/window/index.ts"]
+ }
+ },
+ "include": [
+ "./**/*.ts",
+ "../src/**/*.test.ts",
+ "../src/**/*.test-d.ts",
+ "../src/**/*.bench.ts",
+ "../src/**/*.bench-d.ts",
+ "../src/**/*.snap-d.ts",
+ "../src/**/*.browser.test.ts"
+ ]
+}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 091cb5ed..4a71dc73 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -1,42 +1,44 @@
{
- // This tsconfig file contains the shared config for the build (tsconfig.build.json) and type checking (tsconfig.json) config.
- "include": [],
"compilerOptions": {
- // Incremental builds
- // NOTE: Enabling incremental builds speeds up `tsc`. Keep in mind though that it does not reliably bust the cache when the `tsconfig.json` file changes.
- "incremental": true,
+ // Module system
+ "module": "nodenext",
+ "moduleResolution": "nodenext",
+ "moduleDetection": "force",
+ "target": "esnext",
+ "lib": [
+ "ES2022", // By using ES2022 we get access to the `.cause` property on `Error` instances.
+ "DOM" // We are adding `DOM` here to get the `fetch`, etc. types. This should be removed once these types are available via DefinitelyTyped.
+ ],
+
+ // Emit
+ "noEmit": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
// Type checking
"strict": true,
- "useDefineForClassFields": true, // Not enabled by default in `strict` mode unless we bump `target` to ES2022.
- "noFallthroughCasesInSwitch": true, // Not enabled by default in `strict` mode.
- "noImplicitReturns": true, // Not enabled by default in `strict` mode.
"noUncheckedIndexedAccess": true,
- "useUnknownInCatchVariables": true, // TODO: This would normally be enabled in `strict` mode but would require some adjustments to the codebase.
- "noImplicitOverride": true, // Not enabled by default in `strict` mode.
- "noUnusedLocals": true, // Not enabled by default in `strict` mode.
- "noUnusedParameters": true, // Not enabled by default in `strict` mode.
"exactOptionalPropertyTypes": true,
-
- // JavaScript support
- "allowJs": false,
- "checkJs": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitReturns": true,
+ "noImplicitOverride": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "useDefineForClassFields": true,
+ "useUnknownInCatchVariables": true,
// Interop constraints
"esModuleInterop": false,
"allowSyntheticDefaultImports": false,
"forceConsistentCasingInFileNames": true,
"verbatimModuleSyntax": true,
+ "isolatedModules": true,
"importHelpers": true, // This is only used for build validation. Since we do not have `tslib` installed, this will fail if we accidentally make use of anything that'd require injection of helpers.
- // Language and environment
- "moduleResolution": "nodenext",
- "module": "nodenext",
- "target": "ES2021", // Setting this to `ES2021` enables native support for `Node v16+`: https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping.
- "lib": [
- "ES2022", // By using ES2022 we get access to the `.cause` property on `Error` instances.
- "DOM" // We are adding `DOM` here to get the `fetch`, etc. types. This should be removed once these types are available via DefinitelyTyped.
- ],
+ // JavaScript support
+ "allowJs": false,
+ "checkJs": false,
// Skip type checking for node modules
"skipLibCheck": true
diff --git a/tsconfig.build.json b/tsconfig.build.json
deleted file mode 100644
index d3c59392..00000000
--- a/tsconfig.build.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- // This file is used to compile the for cjs and esm (see package.json build scripts). It should exclude all test files.
- "extends": "./tsconfig.base.json",
- "include": ["src"],
- "exclude": [
- "src/**/*.bench.ts",
- "src/**/*.bench-d.ts",
- "src/**/*.snap-d.ts",
- "src/**/*.test.ts",
- "src/**/*.test-d.ts"
- ],
- "compilerOptions": {
- "sourceMap": true,
- "rootDir": "./src"
- }
-}
diff --git a/tsconfig.json b/tsconfig.json
index 69707244..b14b9ccc 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,22 +1,9 @@
{
- // This configuration is used for local development and type checking.
- "extends": "./tsconfig.base.json",
- "include": ["contracts", "scripts", "src", "test", "vectors", "contracts/scripts/generateTypedArtifacts.ts"],
- "exclude": ["src/_types"],
"compilerOptions": {
- "baseUrl": ".",
- "paths": {
- "~test/*": ["./test/*"],
- "ox": ["src/index.ts"],
- "ox/erc4337": ["src/erc4337/index.ts"],
- "ox/erc6492": ["src/erc6492/index.ts"],
- "ox/erc7821": ["src/erc7821/index.ts"],
- "ox/erc8010": ["src/erc8010/index.ts"],
- "ox/erc8021": ["src/erc8021/index.ts"],
- "ox/tempo": ["src/tempo/index.ts"],
- "ox/trusted-setups": ["src/trusted-setups/index.ts"],
- "ox/webauthn": ["src/webauthn/index.ts"],
- "ox/window": ["src/window/index.ts"]
- }
- }
+ "module": "nodenext",
+ "moduleResolution": "nodenext",
+ "strict": true
+ },
+ "files": [],
+ "references": [{ "path": "./src" }, { "path": "./test" }]
}
From e3a8c0f0eaa0458bb294fda675d99988983b71bf Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Fri, 8 May 2026 08:40:32 +1000
Subject: [PATCH 002/192] chore: format exports:update.ts
Amp-Thread-ID: https://ampcode.com/threads/T-019e0423-2129-734a-8c3f-314d3aab0bbd
---
scripts/exports:update.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/scripts/exports:update.ts b/scripts/exports:update.ts
index 1ce5cf38..dbaeb186 100644
--- a/scripts/exports:update.ts
+++ b/scripts/exports:update.ts
@@ -90,9 +90,7 @@ for (const dir of dirs) {
const rootSorted = exports
.filter(([k]) => k !== '.' && k !== './index.docs')
.sort(([a], [b]) => a.localeCompare(b))
-const rootSpecial = exports.filter(
- ([k]) => k === '.' || k === './index.docs',
-)
+const rootSpecial = exports.filter(([k]) => k === '.' || k === './index.docs')
const finalEntries = [...rootSpecial, ...rootSorted, ...subExports]
From be3841e8a64f1dc9acfef8cec9d6fba14181b9d6 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Fri, 8 May 2026 14:58:17 +1000
Subject: [PATCH 003/192] chore: upgrade noble and scure deps to v2
Bumps @noble/ciphers, @noble/curves, @noble/hashes, @scure/bip32,
and @scure/bip39 to v2 and refactors crypto wrappers to the new APIs
(Uint8Array signatures, Point.fromBytes, Signature.fromBytes/toBytes,
bls.longSignatures, randomSecretKey, .js import extensions).
Adds an internal helper for converting between ox's { r, s, yParity }
Signature shape and noble's compact/recovered byte layouts. Restores
ImportMeta.env types for tests now that vitest v4 dropped them.
Amp-Thread-ID: https://ampcode.com/threads/T-019e05c5-ba3e-711e-8ea5-532440226027
---
package.json | 10 +--
pnpm-lock.yaml | 93 ++++++++++++++++++++++---
src/core/BinaryStateTree.ts | 2 +-
src/core/Bls.ts | 53 +++++++-------
src/core/BlsPoint.ts | 16 ++---
src/core/Bytes.ts | 2 +-
src/core/Ed25519.ts | 13 ++--
src/core/Hash.ts | 8 +--
src/core/Hex.ts | 2 +-
src/core/Keystore.ts | 8 +--
src/core/P256.ts | 75 +++++++++-----------
src/core/Secp256k1.ts | 69 +++++++++---------
src/core/Signature.ts | 11 +--
src/core/WebCryptoP256.ts | 9 ++-
src/core/X25519.ts | 4 +-
src/core/_test/Ed25519.test-d.ts | 2 +-
src/core/_test/X25519.test-d.ts | 2 +-
src/core/_test/X25519.test.ts | 2 +-
src/core/internal/mnemonic/wordlists.ts | 20 +++---
src/core/internal/signature.ts | 45 ++++++++++++
src/core/internal/webauthn.ts | 8 ++-
src/tempo/VirtualMaster.ts | 2 +-
test/env.d.ts | 12 ++++
23 files changed, 288 insertions(+), 180 deletions(-)
create mode 100644 src/core/internal/signature.ts
create mode 100644 test/env.d.ts
diff --git a/package.json b/package.json
index 25bcdd28..2729a7e2 100644
--- a/package.json
+++ b/package.json
@@ -149,11 +149,11 @@
],
"dependencies": {
"@adraffy/ens-normalize": "^1.11.0",
- "@noble/ciphers": "^1.3.0",
- "@noble/curves": "1.9.1",
- "@noble/hashes": "^1.8.0",
- "@scure/bip32": "^1.7.0",
- "@scure/bip39": "^1.6.0",
+ "@noble/ciphers": "^2.2.0",
+ "@noble/curves": "^2.2.0",
+ "@noble/hashes": "^2.2.0",
+ "@scure/bip32": "^2.0.0",
+ "@scure/bip39": "^2.0.0",
"abitype": "^1.2.3",
"eventemitter3": "5.0.1"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b02cce8e..be042d30 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -23,20 +23,20 @@ importers:
specifier: ^1.11.0
version: 1.11.1
'@noble/ciphers':
- specifier: ^1.3.0
- version: 1.3.0
+ specifier: ^2.2.0
+ version: 2.2.0
'@noble/curves':
- specifier: 1.9.1
- version: 1.9.1
+ specifier: ^2.2.0
+ version: 2.2.0
'@noble/hashes':
- specifier: ^1.8.0
- version: 1.8.0
+ specifier: ^2.2.0
+ version: 2.2.0
'@scure/bip32':
- specifier: ^1.7.0
- version: 1.7.0
+ specifier: ^2.0.0
+ version: 2.2.0
'@scure/bip39':
- specifier: ^1.6.0
- version: 1.6.0
+ specifier: ^2.0.0
+ version: 2.2.0
abitype:
specifier: ^1.2.3
version: 1.2.3(typescript@5.5.4)(zod@3.23.8)
@@ -356,24 +356,28 @@ packages:
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@biomejs/cli-linux-arm64@2.2.2':
resolution: {integrity: sha512-JfrK3gdmWWTh2J5tq/rcWCOsImVyzUnOS2fkjhiYKCQ+v8PqM+du5cfB7G1kXas+7KQeKSWALv18iQqdtIMvzw==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@biomejs/cli-linux-x64-musl@2.2.2':
resolution: {integrity: sha512-ZCLXcZvjZKSiRY/cFANKg+z6Fhsf9MHOzj+NrDQcM+LbqYRT97LyCLWy2AS+W2vP+i89RyRM+kbGpUzbRTYWig==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@biomejs/cli-linux-x64@2.2.2':
resolution: {integrity: sha512-Ogb+77edO5LEP/xbNicACOWVLt8mgC+E1wmpUakr+O4nKwLt9vXe74YNuT3T1dUBxC/SnrVmlzZFC7kQJEfquQ==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@biomejs/cli-win32-arm64@2.2.2':
resolution: {integrity: sha512-wBe2wItayw1zvtXysmHJQoQqXlTzHSpQRyPpJKiNIR21HzH/CrZRDFic1C1jDdp+zAPtqhNExa0owKMbNwW9cQ==}
@@ -1076,6 +1080,10 @@ packages:
resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==}
engines: {node: ^14.21.3 || >=16}
+ '@noble/ciphers@2.2.0':
+ resolution: {integrity: sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA==}
+ engines: {node: '>= 20.19.0'}
+
'@noble/curves@1.9.1':
resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==}
engines: {node: ^14.21.3 || >=16}
@@ -1084,6 +1092,10 @@ packages:
resolution: {integrity: sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==}
engines: {node: '>= 20.19.0'}
+ '@noble/curves@2.2.0':
+ resolution: {integrity: sha512-T/BoHgFXirb0ENSPBquzX0rcjXeM6Lo892a2jlYJkqk83LqZx0l1Of7DzlKJ6jkpvMrkHSnAcgb5JegL8SeIkQ==}
+ engines: {node: '>= 20.19.0'}
+
'@noble/hashes@1.8.0':
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
engines: {node: ^14.21.3 || >=16}
@@ -1092,6 +1104,10 @@ packages:
resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==}
engines: {node: '>= 20.19.0'}
+ '@noble/hashes@2.2.0':
+ resolution: {integrity: sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==}
+ engines: {node: '>= 20.19.0'}
+
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -1930,96 +1946,115 @@ packages:
resolution: {integrity: sha512-6npqOKEPRZkLrMcvyC/32OzJ2srdPzCylJjiTJT2c0bwwSGm7nz2F9mNQ1WrAqCBZROcQn91Fno+khFhVijmFA==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm-gnueabihf@4.34.7':
resolution: {integrity: sha512-Z0TzhrsNqukTz3ISzrvyshQpFnFRfLunYiXxlCRvcrb3nvC5rVKI+ZXPFG/Aa4jhQa1gHgH3A0exHaRRN4VmdQ==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.27.2':
resolution: {integrity: sha512-V9Xg6eXtgBtHq2jnuQwM/jr2mwe2EycnopO8cbOvpzFuySCGtKlPCI3Hj9xup/pJK5Q0388qfZZy2DqV2J8ftw==}
cpu: [arm]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm-musleabihf@4.34.7':
resolution: {integrity: sha512-nkznpyXekFAbvFBKBy4nNppSgneB1wwG1yx/hujN3wRnhnkrYVugMTCBXED4+Ni6thoWfQuHNYbFjgGH0MBXtw==}
cpu: [arm]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.27.2':
resolution: {integrity: sha512-uCFX9gtZJoQl2xDTpRdseYuNqyKkuMDtH6zSrBTA28yTfKyjN9hQ2B04N5ynR8ILCoSDOrG/Eg+J2TtJ1e/CSA==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm64-gnu@4.34.7':
resolution: {integrity: sha512-KCjlUkcKs6PjOcxolqrXglBDcfCuUCTVlX5BgzgoJHw+1rWH1MCkETLkLe5iLLS9dP5gKC7mp3y6x8c1oGBUtA==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.27.2':
resolution: {integrity: sha512-/PU9P+7Rkz8JFYDHIi+xzHabOu9qEWR07L5nWLIUsvserrxegZExKCi2jhMZRd0ATdboKylu/K5yAXbp7fYFvA==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm64-musl@4.34.7':
resolution: {integrity: sha512-uFLJFz6+utmpbR313TTx+NpPuAXbPz4BhTQzgaP0tozlLnGnQ6rCo6tLwaSa6b7l6gRErjLicXQ1iPiXzYotjw==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-loongarch64-gnu@4.34.7':
resolution: {integrity: sha512-ws8pc68UcJJqCpneDFepnwlsMUFoWvPbWXT/XUrJ7rWUL9vLoIN3GAasgG+nCvq8xrE3pIrd+qLX/jotcLy0Qw==}
cpu: [loong64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-powerpc64le-gnu@4.27.2':
resolution: {integrity: sha512-eCHmol/dT5odMYi/N0R0HC8V8QE40rEpkyje/ZAXJYNNoSfrObOvG/Mn+s1F/FJyB7co7UQZZf6FuWnN6a7f4g==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-powerpc64le-gnu@4.34.7':
resolution: {integrity: sha512-vrDk9JDa/BFkxcS2PbWpr0C/LiiSLxFbNOBgfbW6P8TBe9PPHx9Wqbvx2xgNi1TOAyQHQJ7RZFqBiEohm79r0w==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.27.2':
resolution: {integrity: sha512-DEP3Njr9/ADDln3kNi76PXonLMSSMiCir0VHXxmGSHxCxDfQ70oWjHcJGfiBugzaqmYdTC7Y+8Int6qbnxPBIQ==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.34.7':
resolution: {integrity: sha512-rB+ejFyjtmSo+g/a4eovDD1lHWHVqizN8P0Hm0RElkINpS0XOdpaXloqM4FBkF9ZWEzg6bezymbpLmeMldfLTw==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.27.2':
resolution: {integrity: sha512-NHGo5i6IE/PtEPh5m0yw5OmPMpesFnzMIS/lzvN5vknnC1sXM5Z/id5VgcNPgpD+wHmIcuYYgW+Q53v+9s96lQ==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.34.7':
resolution: {integrity: sha512-nNXNjo4As6dNqRn7OrsnHzwTgtypfRA3u3AKr0B3sOOo+HkedIbn8ZtFnB+4XyKJojIfqDKmbIzO1QydQ8c+Pw==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.27.2':
resolution: {integrity: sha512-PaW2DY5Tan+IFvNJGHDmUrORadbe/Ceh8tQxi8cmdQVCCYsLoQo2cuaSj+AU+YRX8M4ivS2vJ9UGaxfuNN7gmg==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.34.7':
resolution: {integrity: sha512-9kPVf9ahnpOMSGlCxXGv980wXD0zRR3wyk8+33/MXQIpQEOpaNe7dEHm5LMfyRZRNt9lMEQuH0jUKj15MkM7QA==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.27.2':
resolution: {integrity: sha512-dOlWEMg2gI91Qx5I/HYqOD6iqlJspxLcS4Zlg3vjk1srE67z5T2Uz91yg/qA8sY0XcwQrFzWWiZhMNERylLrpQ==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-x64-musl@4.34.7':
resolution: {integrity: sha512-7wJPXRWTTPtTFDFezA8sle/1sdgxDjuMoRXEKtx97ViRxGGkVQYovem+Q8Pr/2HxiHp74SSRG+o6R0Yq0shPwQ==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-win32-arm64-msvc@4.27.2':
resolution: {integrity: sha512-euMIv/4x5Y2/ImlbGl88mwKNXDsvzbWUlT7DFky76z2keajCtcbAsN9LUdmk31hAoVmJJYSThgdA0EsPeTr1+w==}
@@ -2079,12 +2114,21 @@ packages:
'@scure/base@2.0.0':
resolution: {integrity: sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==}
+ '@scure/base@2.2.0':
+ resolution: {integrity: sha512-b8XEupJibegiXV+tDUseI8oLQc8ei3d/4Jkb2RpbHh3MfE054ov3uIz2dhFkB3FI8iwYkEh0gGCApkrYggkPNg==}
+
'@scure/bip32@1.7.0':
resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==}
+ '@scure/bip32@2.2.0':
+ resolution: {integrity: sha512-zFr7t2F+a9+5tB7QbarF2HQNYrgjCNaoLAupZdKkrFMYMozJf5zqH2WJCQibMzm1qQ0QogrxVGO3qXfQDYMaQg==}
+
'@scure/bip39@1.6.0':
resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==}
+ '@scure/bip39@2.2.0':
+ resolution: {integrity: sha512-T/Bj/YvYMNkIPq6EENO6/rcs2e7qTNuyoUXf0KBFDmp0ZDu0H2X4Lq6yC3i0c8PcWkov5EbW+yQZZbdMmk154A==}
+
'@sec-ant/readable-stream@0.4.1':
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
@@ -2193,24 +2237,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.0.7':
resolution: {integrity: sha512-WHYs3cpPEJb/ccyT20NOzopYQkl7JKncNBUbb77YFlwlXMVJLLV3nrXQKhr7DmZxz2ZXqjyUwsj2rdzd9stYdw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.0.7':
resolution: {integrity: sha512-7bP1UyuX9kFxbOwkeIJhBZNevKYPXB6xZI37v09fqi6rqRJR8elybwjMUHm54GVP+UTtJ14ueB1K54Dy1tIO6w==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.0.7':
resolution: {integrity: sha512-gBQIV8nL/LuhARNGeroqzXymMzzW5wQzqlteVqOVoqwEfpHOP3GMird5pGFbnpY+NP0fOlsZGrxxOPQ4W/84bQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@tailwindcss/oxide-win32-arm64-msvc@4.0.7':
resolution: {integrity: sha512-aH530NFfx0kpQpvYMfWoeG03zGnRCMVlQG8do/5XeahYydz+6SIBxA1tl/cyITSJyWZHyVt6GVNkXeAD30v0Xg==}
@@ -4364,24 +4412,28 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-arm64-musl@1.29.1:
resolution: {integrity: sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
lightningcss-linux-x64-gnu@1.29.1:
resolution: {integrity: sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-x64-musl@1.29.1:
resolution: {integrity: sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [musl]
lightningcss-win32-arm64-msvc@1.29.1:
resolution: {integrity: sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==}
@@ -7236,6 +7288,8 @@ snapshots:
'@noble/ciphers@1.3.0': {}
+ '@noble/ciphers@2.2.0': {}
+
'@noble/curves@1.9.1':
dependencies:
'@noble/hashes': 1.8.0
@@ -7244,10 +7298,16 @@ snapshots:
dependencies:
'@noble/hashes': 2.0.1
+ '@noble/curves@2.2.0':
+ dependencies:
+ '@noble/hashes': 2.2.0
+
'@noble/hashes@1.8.0': {}
'@noble/hashes@2.0.1': {}
+ '@noble/hashes@2.2.0': {}
+
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -8165,17 +8225,30 @@ snapshots:
'@scure/base@2.0.0': {}
+ '@scure/base@2.2.0': {}
+
'@scure/bip32@1.7.0':
dependencies:
'@noble/curves': 1.9.1
'@noble/hashes': 1.8.0
'@scure/base': 1.2.5
+ '@scure/bip32@2.2.0':
+ dependencies:
+ '@noble/curves': 2.2.0
+ '@noble/hashes': 2.2.0
+ '@scure/base': 2.2.0
+
'@scure/bip39@1.6.0':
dependencies:
'@noble/hashes': 1.8.0
'@scure/base': 1.2.5
+ '@scure/bip39@2.2.0':
+ dependencies:
+ '@noble/hashes': 2.2.0
+ '@scure/base': 2.2.0
+
'@sec-ant/readable-stream@0.4.1': {}
'@shikijs/core@1.22.0':
diff --git a/src/core/BinaryStateTree.ts b/src/core/BinaryStateTree.ts
index e3440568..11d3f417 100644
--- a/src/core/BinaryStateTree.ts
+++ b/src/core/BinaryStateTree.ts
@@ -1,4 +1,4 @@
-import { blake3 } from '@noble/hashes/blake3'
+import { blake3 } from '@noble/hashes/blake3.js'
import * as Bytes from './Bytes.js'
import type { OneOf } from './internal/types.js'
diff --git a/src/core/Bls.ts b/src/core/Bls.ts
index a69f06d4..fd4af020 100644
--- a/src/core/Bls.ts
+++ b/src/core/Bls.ts
@@ -1,5 +1,4 @@
-import type { ProjPointType } from '@noble/curves/abstract/weierstrass'
-import { bls12_381 as bls } from '@noble/curves/bls12-381'
+import { bls12_381 as bls } from '@noble/curves/bls12-381.js'
import type * as BlsPoint from './BlsPoint.js'
import * as Bytes from './Bytes.js'
@@ -56,13 +55,13 @@ export function aggregate(
const group = typeof points[0]?.x === 'bigint' ? bls.G1 : bls.G2
const point = points.reduce(
(acc, point) =>
- acc.add(new (group as any).ProjectivePoint(point.x, point.y, point.z)),
- group.ProjectivePoint.ZERO,
+ acc.add(new (group as any).Point(point.x, point.y, point.z)),
+ group.Point.ZERO,
)
return {
- x: point.px,
- y: point.py,
- z: point.pz,
+ x: point.X,
+ y: point.Y,
+ z: point.Z,
}
}
@@ -330,10 +329,10 @@ export function getPublicKey(
export function getPublicKey(options: getPublicKey.Options): BlsPoint.BlsPoint {
const { privateKey, size = 'short-key:long-sig' } = options
const group = size === 'short-key:long-sig' ? bls.G1 : bls.G2
- const { px, py, pz } = group.ProjectivePoint.fromPrivateKey(
- Hex.from(privateKey).slice(2),
+ const point = group.Point.BASE.multiply(
+ group.Point.Fn.fromBytes(Bytes.from(privateKey)),
)
- return { x: px, y: py, z: pz }
+ return { x: point.X, y: point.Y, z: point.Z }
}
export declare namespace getPublicKey {
@@ -373,7 +372,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = bls.utils.randomPrivateKey()
+ const bytes = bls.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
@@ -470,13 +469,13 @@ export function sign(options: sign.Options): BlsPoint.BlsPoint {
const privateKeyGroup = size === 'short-key:long-sig' ? bls.G1 : bls.G2
const signature = payloadPoint.multiply(
- privateKeyGroup.normPrivateKeyToScalar(privateKey.slice(2)),
- ) as ProjPointType
+ privateKeyGroup.Point.Fn.fromBytes(Bytes.from(privateKey)),
+ )
return {
- x: signature.px,
- y: signature.py,
- z: signature.pz,
+ x: signature.X,
+ y: signature.Y,
+ z: signature.Z,
}
}
@@ -571,33 +570,29 @@ export function verify(options: verify.Options): boolean {
const payloadPoint = group.hashToCurve(
Bytes.from(payload),
suite ? { DST: Bytes.fromString(suite) } : undefined,
- ) as ProjPointType
+ )
const shortSigPairing = () =>
bls.pairingBatch([
{
- g1: payloadPoint,
- g2: new bls.G2.ProjectivePoint(publicKey.x, publicKey.y, publicKey.z),
+ g1: payloadPoint as InstanceType,
+ g2: new bls.G2.Point(publicKey.x, publicKey.y, publicKey.z),
},
{
- g1: new bls.G1.ProjectivePoint(signature.x, signature.y, signature.z),
- g2: bls.G2.ProjectivePoint.BASE.negate(),
+ g1: new bls.G1.Point(signature.x, signature.y, signature.z),
+ g2: bls.G2.Point.BASE.negate(),
},
])
const longSigPairing = () =>
bls.pairingBatch([
{
- g1: new bls.G1.ProjectivePoint(
- publicKey.x,
- publicKey.y,
- publicKey.z,
- ).negate(),
- g2: payloadPoint,
+ g1: new bls.G1.Point(publicKey.x, publicKey.y, publicKey.z).negate(),
+ g2: payloadPoint as InstanceType,
},
{
- g1: bls.G1.ProjectivePoint.BASE,
- g2: new bls.G2.ProjectivePoint(signature.x, signature.y, signature.z),
+ g1: bls.G1.Point.BASE,
+ g2: new bls.G2.Point(signature.x, signature.y, signature.z),
},
])
diff --git a/src/core/BlsPoint.ts b/src/core/BlsPoint.ts
index 97a47874..e3e549d4 100644
--- a/src/core/BlsPoint.ts
+++ b/src/core/BlsPoint.ts
@@ -1,4 +1,4 @@
-import { bls12_381 as bls } from '@noble/curves/bls12-381'
+import { bls12_381 as bls } from '@noble/curves/bls12-381.js'
import type * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
@@ -61,11 +61,7 @@ export function toBytes(
point: point,
): point extends G1 ? G1Bytes : G2Bytes {
const group = typeof point.z === 'bigint' ? bls.G1 : bls.G2
- return new (group as any).ProjectivePoint(
- point.x,
- point.y,
- point.z,
- ).toRawBytes()
+ return new (group as any).Point(point.x, point.y, point.z).toBytes()
}
export declare namespace toBytes {
@@ -155,11 +151,11 @@ export function fromBytes(
// eslint-disable-next-line jsdoc/require-jsdoc
export function fromBytes(bytes: Bytes.Bytes): BlsPoint {
const group = bytes.length === 48 ? bls.G1 : bls.G2
- const point = group.ProjectivePoint.fromHex(bytes)
+ const point = group.Point.fromBytes(bytes)
return {
- x: point.px,
- y: point.py,
- z: point.pz,
+ x: point.X,
+ y: point.Y,
+ z: point.Z,
}
}
diff --git a/src/core/Bytes.ts b/src/core/Bytes.ts
index 97500413..2cb15e27 100644
--- a/src/core/Bytes.ts
+++ b/src/core/Bytes.ts
@@ -1,4 +1,4 @@
-import { equalBytes } from '@noble/curves/abstract/utils'
+import { equalBytes } from '@noble/curves/utils.js'
import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import * as internal from './internal/bytes.js'
diff --git a/src/core/Ed25519.ts b/src/core/Ed25519.ts
index 7fc69443..38c86d05 100644
--- a/src/core/Ed25519.ts
+++ b/src/core/Ed25519.ts
@@ -1,8 +1,4 @@
-import {
- ed25519,
- edwardsToMontgomeryPriv,
- edwardsToMontgomeryPub,
-} from '@noble/curves/ed25519'
+import { ed25519 } from '@noble/curves/ed25519.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
@@ -124,7 +120,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = ed25519.utils.randomPrivateKey()
+ const bytes = ed25519.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
@@ -263,7 +259,7 @@ export function toX25519PublicKey(
): toX25519PublicKey.ReturnType {
const { as = 'Hex', publicKey } = options
const publicKeyBytes = Bytes.from(publicKey)
- const x25519PublicKeyBytes = edwardsToMontgomeryPub(publicKeyBytes)
+ const x25519PublicKeyBytes = ed25519.utils.toMontgomery(publicKeyBytes)
if (as === 'Hex') return Hex.fromBytes(x25519PublicKeyBytes) as never
return x25519PublicKeyBytes as never
}
@@ -312,7 +308,8 @@ export function toX25519PrivateKey(
): toX25519PrivateKey.ReturnType {
const { as = 'Hex', privateKey } = options
const privateKeyBytes = Bytes.from(privateKey)
- const x25519PrivateKeyBytes = edwardsToMontgomeryPriv(privateKeyBytes)
+ const x25519PrivateKeyBytes =
+ ed25519.utils.toMontgomerySecret(privateKeyBytes)
if (as === 'Hex') return Hex.fromBytes(x25519PrivateKeyBytes) as never
return x25519PrivateKeyBytes as never
}
diff --git a/src/core/Hash.ts b/src/core/Hash.ts
index 4c16cb04..e0a62a4a 100644
--- a/src/core/Hash.ts
+++ b/src/core/Hash.ts
@@ -1,7 +1,7 @@
-import { hmac } from '@noble/hashes/hmac'
-import { ripemd160 as noble_ripemd160 } from '@noble/hashes/ripemd160'
-import { keccak_256 as noble_keccak256 } from '@noble/hashes/sha3'
-import { sha256 as noble_sha256 } from '@noble/hashes/sha256'
+import { hmac } from '@noble/hashes/hmac.js'
+import { ripemd160 as noble_ripemd160 } from '@noble/hashes/legacy.js'
+import { sha256 as noble_sha256 } from '@noble/hashes/sha2.js'
+import { keccak_256 as noble_keccak256 } from '@noble/hashes/sha3.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
diff --git a/src/core/Hex.ts b/src/core/Hex.ts
index fcf6e853..23af4e63 100644
--- a/src/core/Hex.ts
+++ b/src/core/Hex.ts
@@ -1,4 +1,4 @@
-import { equalBytes } from '@noble/curves/abstract/utils'
+import { equalBytes } from '@noble/curves/utils.js'
import * as Bytes from './Bytes.js'
import * as Errors from './Errors.js'
import * as internal_bytes from './internal/bytes.js'
diff --git a/src/core/Keystore.ts b/src/core/Keystore.ts
index e4b05f27..f419e4d6 100644
--- a/src/core/Keystore.ts
+++ b/src/core/Keystore.ts
@@ -1,13 +1,13 @@
-import { ctr } from '@noble/ciphers/aes'
+import { ctr } from '@noble/ciphers/aes.js'
import {
pbkdf2 as pbkdf2_noble,
pbkdf2Async as pbkdf2Async_noble,
-} from '@noble/hashes/pbkdf2'
+} from '@noble/hashes/pbkdf2.js'
import {
scrypt as scrypt_noble,
scryptAsync as scryptAsync_noble,
-} from '@noble/hashes/scrypt'
-import { sha256 } from '@noble/hashes/sha2'
+} from '@noble/hashes/scrypt.js'
+import { sha256 } from '@noble/hashes/sha2.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
diff --git a/src/core/P256.ts b/src/core/P256.ts
index 9a98b79a..62681cdf 100644
--- a/src/core/P256.ts
+++ b/src/core/P256.ts
@@ -1,13 +1,18 @@
-import { secp256r1 } from '@noble/curves/p256'
+import { p256 as noble_p256 } from '@noble/curves/nist.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import * as Entropy from './internal/entropy.js'
+import {
+ fromRecoveredBytes,
+ toCompactBytes,
+ toRecoveredBytes,
+} from './internal/signature.js'
import * as PublicKey from './PublicKey.js'
import type * as Signature from './Signature.js'
/** Re-export of noble/curves P256 utilities. */
-export const noble = secp256r1
+export const noble = noble_p256
/**
* Creates a new P256 ECDSA key pair consisting of a private key and its corresponding public key.
@@ -74,12 +79,8 @@ export function getPublicKey(
options: getPublicKey.Options,
): PublicKey.PublicKey {
const { privateKey } = options
- const point = secp256r1.ProjectivePoint.fromPrivateKey(
- typeof privateKey === 'string'
- ? privateKey.slice(2)
- : Hex.fromBytes(privateKey).slice(2),
- )
- return PublicKey.from(point)
+ const bytes = noble_p256.getPublicKey(Bytes.from(privateKey), false)
+ return PublicKey.fromBytes(bytes)
}
export declare namespace getPublicKey {
@@ -116,17 +117,11 @@ export function getSharedSecret(
options: getSharedSecret.Options,
): getSharedSecret.ReturnType {
const { as = 'Hex', privateKey, publicKey } = options
- const point = secp256r1.ProjectivePoint.fromHex(
- PublicKey.toHex(publicKey).slice(2),
- )
- const privateKeyHex =
- typeof privateKey === 'string'
- ? privateKey.slice(2)
- : Hex.fromBytes(privateKey).slice(2)
- const sharedPoint = point.multiply(
- secp256r1.utils.normPrivateKeyToScalar(privateKeyHex),
+ const sharedSecret = noble_p256.getSharedSecret(
+ Bytes.from(privateKey),
+ PublicKey.toBytes(publicKey),
+ true, // compressed
)
- const sharedSecret = sharedPoint.toRawBytes(true) // compressed format
if (as === 'Hex') return Hex.fromBytes(sharedSecret) as never
return sharedSecret as never
}
@@ -175,7 +170,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = secp256r1.utils.randomPrivateKey()
+ const bytes = noble_p256.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
@@ -218,15 +213,12 @@ export function recoverPublicKey(
options: recoverPublicKey.Options,
): PublicKey.PublicKey {
const { payload, signature } = options
- const { r, s, yParity } = signature
- const signature_ = new secp256r1.Signature(
- BigInt(r),
- BigInt(s),
- ).addRecoveryBit(yParity)
- const payload_ =
- payload instanceof Uint8Array ? Hex.fromBytes(payload) : payload
- const point = signature_.recoverPublicKey(payload_.substring(2))
- return PublicKey.from(point)
+ const sigBytes = toRecoveredBytes(signature)
+ const point = noble_p256.Signature.fromBytes(
+ sigBytes,
+ 'recovered',
+ ).recoverPublicKey(Bytes.from(payload))
+ return PublicKey.fromBytes(point.toBytes(false))
}
export declare namespace recoverPublicKey {
@@ -266,23 +258,20 @@ export function sign(options: sign.Options): Signature.Signature {
payload,
privateKey,
} = options
- const { r, s, recovery } = secp256r1.sign(
- payload instanceof Uint8Array ? payload : Bytes.fromHex(payload),
- privateKey instanceof Uint8Array ? privateKey : Bytes.fromHex(privateKey),
+ const sigBytes = noble_p256.sign(
+ Bytes.from(payload),
+ Bytes.from(privateKey),
{
extraEntropy:
typeof extraEntropy === 'boolean'
? extraEntropy
- : Hex.from(extraEntropy).slice(2),
+ : Bytes.from(extraEntropy),
lowS: true,
- ...(hash ? { prehash: true } : {}),
+ prehash: hash === true,
+ format: 'recovered',
},
)
- return {
- r,
- s,
- yParity: recovery,
- }
+ return fromRecoveredBytes(sigBytes)
}
export declare namespace sign {
@@ -332,11 +321,11 @@ export declare namespace sign {
*/
export function verify(options: verify.Options): boolean {
const { hash, payload, publicKey, signature } = options
- return secp256r1.verify(
- signature,
- payload instanceof Uint8Array ? payload : Bytes.fromHex(payload),
- PublicKey.toHex(publicKey).substring(2),
- { lowS: true, ...(hash ? { prehash: true } : {}) },
+ return noble_p256.verify(
+ toCompactBytes(signature),
+ Bytes.from(payload),
+ PublicKey.toBytes(publicKey),
+ { lowS: true, prehash: hash === true },
)
}
diff --git a/src/core/Secp256k1.ts b/src/core/Secp256k1.ts
index b3de84be..4763605c 100644
--- a/src/core/Secp256k1.ts
+++ b/src/core/Secp256k1.ts
@@ -1,9 +1,14 @@
-import { secp256k1 } from '@noble/curves/secp256k1'
+import { secp256k1 } from '@noble/curves/secp256k1.js'
import * as Address from './Address.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import * as Entropy from './internal/entropy.js'
+import {
+ fromRecoveredBytes,
+ toCompactBytes,
+ toRecoveredBytes,
+} from './internal/signature.js'
import type { OneOf } from './internal/types.js'
import * as PublicKey from './PublicKey.js'
import type * as Signature from './Signature.js'
@@ -76,10 +81,8 @@ export function getPublicKey(
options: getPublicKey.Options,
): PublicKey.PublicKey {
const { privateKey } = options
- const point = secp256k1.ProjectivePoint.fromPrivateKey(
- Hex.from(privateKey).slice(2),
- )
- return PublicKey.from(point)
+ const bytes = secp256k1.getPublicKey(Bytes.from(privateKey), false)
+ return PublicKey.fromBytes(bytes)
}
export declare namespace getPublicKey {
@@ -119,13 +122,11 @@ export function getSharedSecret(
options: getSharedSecret.Options,
): getSharedSecret.ReturnType {
const { as = 'Hex', privateKey, publicKey } = options
- const point = secp256k1.ProjectivePoint.fromHex(
- PublicKey.toHex(publicKey).slice(2),
- )
- const sharedPoint = point.multiply(
- secp256k1.utils.normPrivateKeyToScalar(Hex.from(privateKey).slice(2)),
+ const sharedSecret = secp256k1.getSharedSecret(
+ Bytes.from(privateKey),
+ PublicKey.toBytes(publicKey),
+ true, // compressed
)
- const sharedSecret = sharedPoint.toRawBytes(true) // compressed format
if (as === 'Hex') return Hex.fromBytes(sharedSecret) as never
return sharedSecret as never
}
@@ -175,7 +176,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = secp256k1.utils.randomPrivateKey()
+ const bytes = secp256k1.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
@@ -258,13 +259,12 @@ export function recoverPublicKey(
options: recoverPublicKey.Options,
): PublicKey.PublicKey {
const { payload, signature } = options
- const { r, s, yParity } = signature
- const signature_ = new secp256k1.Signature(
- BigInt(r),
- BigInt(s),
- ).addRecoveryBit(yParity)
- const point = signature_.recoverPublicKey(Hex.from(payload).substring(2))
- return PublicKey.from(point)
+ const sigBytes = toRecoveredBytes(signature)
+ const point = secp256k1.Signature.fromBytes(
+ sigBytes,
+ 'recovered',
+ ).recoverPublicKey(Bytes.from(payload))
+ return PublicKey.fromBytes(point.toBytes(false))
}
export declare namespace recoverPublicKey {
@@ -304,23 +304,16 @@ export function sign(options: sign.Options): Signature.Signature {
payload,
privateKey,
} = options
- const { r, s, recovery } = secp256k1.sign(
- Bytes.from(payload),
- Bytes.from(privateKey),
- {
- extraEntropy:
- typeof extraEntropy === 'boolean'
- ? extraEntropy
- : Hex.from(extraEntropy).slice(2),
- lowS: true,
- ...(hash ? { prehash: true } : {}),
- },
- )
- return {
- r,
- s,
- yParity: recovery,
- }
+ const sigBytes = secp256k1.sign(Bytes.from(payload), Bytes.from(privateKey), {
+ extraEntropy:
+ typeof extraEntropy === 'boolean'
+ ? extraEntropy
+ : Bytes.from(extraEntropy),
+ lowS: true,
+ prehash: hash === true,
+ format: 'recovered',
+ })
+ return fromRecoveredBytes(sigBytes)
}
export declare namespace sign {
@@ -390,10 +383,10 @@ export function verify(options: verify.Options): boolean {
if (address)
return Address.isEqual(address, recoverAddress({ payload, signature }))
return secp256k1.verify(
- signature,
+ toCompactBytes(signature),
Bytes.from(payload),
PublicKey.toBytes(publicKey),
- ...(hash ? [{ prehash: true, lowS: true }] : []),
+ { lowS: true, prehash: hash === true },
)
}
diff --git a/src/core/Signature.ts b/src/core/Signature.ts
index 250d376f..d8e0edf7 100644
--- a/src/core/Signature.ts
+++ b/src/core/Signature.ts
@@ -1,4 +1,4 @@
-import { secp256k1 } from '@noble/curves/secp256k1'
+import { secp256k1 } from '@noble/curves/secp256k1.js'
import * as Bytes from './Bytes.js'
import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
@@ -360,7 +360,10 @@ export declare namespace fromDerBytes {
* @returns The {@link ox#Signature.Signature}.
*/
export function fromDerHex(signature: Hex.Hex): Signature {
- const { r, s } = secp256k1.Signature.fromDER(Hex.from(signature).slice(2))
+ const { r, s } = secp256k1.Signature.fromHex(
+ Hex.from(signature).slice(2),
+ 'der',
+ )
return { r, s }
}
@@ -562,7 +565,7 @@ export declare namespace toHex {
*/
export function toDerBytes(signature: Signature): Bytes.Bytes {
const sig = new secp256k1.Signature(signature.r, signature.s)
- return sig.toDERRawBytes()
+ return sig.toBytes('der')
}
export declare namespace toDerBytes {
@@ -590,7 +593,7 @@ export declare namespace toDerBytes {
*/
export function toDerHex(signature: Signature): Hex.Hex {
const sig = new secp256k1.Signature(signature.r, signature.s)
- return `0x${sig.toDERHex()}`
+ return `0x${sig.toHex('der')}`
}
export declare namespace toDerHex {
diff --git a/src/core/WebCryptoP256.ts b/src/core/WebCryptoP256.ts
index f43f5830..10dd4670 100644
--- a/src/core/WebCryptoP256.ts
+++ b/src/core/WebCryptoP256.ts
@@ -1,4 +1,4 @@
-import { p256 } from '@noble/curves/p256'
+import { p256 } from '@noble/curves/nist.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
@@ -6,6 +6,9 @@ import type { Compute } from './internal/types.js'
import * as PublicKey from './PublicKey.js'
import type * as Signature from './Signature.js'
+/** secp256r1 / P-256 curve order. */
+const N = p256.Point.CURVE().n
+
/**
* Generates an ECDSA P256 key pair that includes:
*
@@ -245,7 +248,7 @@ export async function sign(
const signature_bytes = Bytes.fromArray(new Uint8Array(signature))
const r = Bytes.toBigInt(Bytes.slice(signature_bytes, 0, 32))
let s = Bytes.toBigInt(Bytes.slice(signature_bytes, 32, 64))
- if (s > p256.CURVE.n / 2n) s = p256.CURVE.n - s
+ if (s > N / 2n) s = N - s
return { r, s }
}
@@ -286,7 +289,7 @@ export async function verify(options: verify.Options): Promise {
const { lowS = true, payload, signature } = options
// Reject high-S signatures if lowS is enabled.
- if (lowS && signature.s > p256.CURVE.n / 2n) return false
+ if (lowS && signature.s > N / 2n) return false
const publicKey = await globalThis.crypto.subtle.importKey(
'raw',
diff --git a/src/core/X25519.ts b/src/core/X25519.ts
index e8be7845..b0c5a93b 100644
--- a/src/core/X25519.ts
+++ b/src/core/X25519.ts
@@ -1,4 +1,4 @@
-import { x25519 } from '@noble/curves/ed25519'
+import { x25519 } from '@noble/curves/ed25519.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
@@ -180,7 +180,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = x25519.utils.randomPrivateKey()
+ const bytes = x25519.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
diff --git a/src/core/_test/Ed25519.test-d.ts b/src/core/_test/Ed25519.test-d.ts
index 804959aa..e0c4a281 100644
--- a/src/core/_test/Ed25519.test-d.ts
+++ b/src/core/_test/Ed25519.test-d.ts
@@ -150,6 +150,6 @@ test('verify', () => {
test('noble export', () => {
expectTypeOf(Ed25519.noble).toMatchTypeOf<
- typeof import('@noble/curves/ed25519').ed25519
+ typeof import('@noble/curves/ed25519.js').ed25519
>()
})
diff --git a/src/core/_test/X25519.test-d.ts b/src/core/_test/X25519.test-d.ts
index 9b6f7ddb..6976294c 100644
--- a/src/core/_test/X25519.test-d.ts
+++ b/src/core/_test/X25519.test-d.ts
@@ -127,6 +127,6 @@ test('randomPrivateKey', () => {
test('noble export', () => {
expectTypeOf(X25519.noble).toMatchTypeOf<
- typeof import('@noble/curves/ed25519').x25519
+ typeof import('@noble/curves/ed25519.js').x25519
>()
})
diff --git a/src/core/_test/X25519.test.ts b/src/core/_test/X25519.test.ts
index 92ca3274..5a18211e 100644
--- a/src/core/_test/X25519.test.ts
+++ b/src/core/_test/X25519.test.ts
@@ -8,7 +8,7 @@ describe('noble', () => {
expect(X25519.noble).toBeDefined()
expect(typeof X25519.noble.getPublicKey).toBe('function')
expect(typeof X25519.noble.getSharedSecret).toBe('function')
- expect(typeof X25519.noble.utils.randomPrivateKey).toBe('function')
+ expect(typeof X25519.noble.utils.randomSecretKey).toBe('function')
})
})
diff --git a/src/core/internal/mnemonic/wordlists.ts b/src/core/internal/mnemonic/wordlists.ts
index aef60660..f699b541 100644
--- a/src/core/internal/mnemonic/wordlists.ts
+++ b/src/core/internal/mnemonic/wordlists.ts
@@ -1,10 +1,10 @@
-export { wordlist as czech } from '@scure/bip39/wordlists/czech'
-export { wordlist as english } from '@scure/bip39/wordlists/english'
-export { wordlist as french } from '@scure/bip39/wordlists/french'
-export { wordlist as italian } from '@scure/bip39/wordlists/italian'
-export { wordlist as japanese } from '@scure/bip39/wordlists/japanese'
-export { wordlist as korean } from '@scure/bip39/wordlists/korean'
-export { wordlist as portuguese } from '@scure/bip39/wordlists/portuguese'
-export { wordlist as simplifiedChinese } from '@scure/bip39/wordlists/simplified-chinese'
-export { wordlist as spanish } from '@scure/bip39/wordlists/spanish'
-export { wordlist as traditionalChinese } from '@scure/bip39/wordlists/traditional-chinese'
+export { wordlist as czech } from '@scure/bip39/wordlists/czech.js'
+export { wordlist as english } from '@scure/bip39/wordlists/english.js'
+export { wordlist as french } from '@scure/bip39/wordlists/french.js'
+export { wordlist as italian } from '@scure/bip39/wordlists/italian.js'
+export { wordlist as japanese } from '@scure/bip39/wordlists/japanese.js'
+export { wordlist as korean } from '@scure/bip39/wordlists/korean.js'
+export { wordlist as portuguese } from '@scure/bip39/wordlists/portuguese.js'
+export { wordlist as simplifiedChinese } from '@scure/bip39/wordlists/simplified-chinese.js'
+export { wordlist as spanish } from '@scure/bip39/wordlists/spanish.js'
+export { wordlist as traditionalChinese } from '@scure/bip39/wordlists/traditional-chinese.js'
diff --git a/src/core/internal/signature.ts b/src/core/internal/signature.ts
new file mode 100644
index 00000000..d725c2f1
--- /dev/null
+++ b/src/core/internal/signature.ts
@@ -0,0 +1,45 @@
+import * as Bytes from '../Bytes.js'
+import type * as Signature from '../Signature.js'
+
+/**
+ * Encodes an ox `Signature` as a 64-byte compact noble signature
+ * (`r ++ s`, big-endian).
+ *
+ * @internal
+ */
+export function toCompactBytes(
+ signature: Signature.Signature,
+): Uint8Array {
+ const bytes = new Uint8Array(64)
+ bytes.set(Bytes.fromNumber(signature.r, { size: 32 }), 0)
+ bytes.set(Bytes.fromNumber(signature.s, { size: 32 }), 32)
+ return bytes
+}
+
+/**
+ * Encodes an ox `Signature` as a 65-byte recoverable noble signature
+ * (`recovery ++ r ++ s`, big-endian).
+ *
+ * @internal
+ */
+export function toRecoveredBytes(signature: Signature.Signature): Uint8Array {
+ const bytes = new Uint8Array(65)
+ bytes[0] = signature.yParity
+ bytes.set(Bytes.fromNumber(signature.r, { size: 32 }), 1)
+ bytes.set(Bytes.fromNumber(signature.s, { size: 32 }), 33)
+ return bytes
+}
+
+/**
+ * Decodes a 65-byte recoverable noble signature (`recovery ++ r ++ s`)
+ * into an ox `Signature`.
+ *
+ * @internal
+ */
+export function fromRecoveredBytes(bytes: Uint8Array): Signature.Signature {
+ return {
+ r: Bytes.toBigInt(bytes.subarray(1, 33)),
+ s: Bytes.toBigInt(bytes.subarray(33, 65)),
+ yParity: bytes[0]!,
+ }
+}
diff --git a/src/core/internal/webauthn.ts b/src/core/internal/webauthn.ts
index b3378c55..5f3f2b1c 100644
--- a/src/core/internal/webauthn.ts
+++ b/src/core/internal/webauthn.ts
@@ -1,4 +1,4 @@
-import { p256 } from '@noble/curves/p256'
+import { p256 } from '@noble/curves/nist.js'
import * as Registration from '../../webauthn/Registration.js'
import type * as Errors from '../Errors.js'
import * as PublicKey from '../PublicKey.js'
@@ -9,8 +9,10 @@ import * as PublicKey from '../PublicKey.js'
* @internal
*/
export function parseAsn1Signature(bytes: Uint8Array) {
- const sig = p256.Signature.fromDER(bytes).normalizeS()
- return { r: sig.r, s: sig.s }
+ const sig = p256.Signature.fromBytes(bytes, 'der')
+ const n = p256.Point.CURVE().n
+ const s = sig.hasHighS() ? n - sig.s : sig.s
+ return { r: sig.r, s }
}
/**
diff --git a/src/tempo/VirtualMaster.ts b/src/tempo/VirtualMaster.ts
index 40e713d6..5e8d96a4 100644
--- a/src/tempo/VirtualMaster.ts
+++ b/src/tempo/VirtualMaster.ts
@@ -1,4 +1,4 @@
-import { keccak_256 } from '@noble/hashes/sha3'
+import { keccak_256 } from '@noble/hashes/sha3.js'
import * as Address from '../core/Address.js'
import * as Bytes from '../core/Bytes.js'
import * as Errors from '../core/Errors.js'
diff --git a/test/env.d.ts b/test/env.d.ts
new file mode 100644
index 00000000..9c156e87
--- /dev/null
+++ b/test/env.d.ts
@@ -0,0 +1,12 @@
+interface ImportMetaEnv {
+ readonly VITE_TEMPO_ENV?: string
+ readonly VITE_TEMPO_TAG?: string
+ readonly VITE_TEMPO_LOG?: string
+ readonly VITE_TEMPO_HTTP_LOG?: string
+ readonly VITE_TEMPO_CREDENTIALS?: string
+ readonly VITEST_POOL_ID?: string
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv
+}
From cfe481169c24db1e1381dbd3287e78f1caa26510 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Fri, 8 May 2026 15:03:26 +1000
Subject: [PATCH 004/192] chore: changeset for noble v2 upgrade
Amp-Thread-ID: https://ampcode.com/threads/T-019e05c5-ba3e-711e-8ea5-532440226027
---
.changeset/upgrade-noble-v2.md | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 .changeset/upgrade-noble-v2.md
diff --git a/.changeset/upgrade-noble-v2.md b/.changeset/upgrade-noble-v2.md
new file mode 100644
index 00000000..43cff596
--- /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.
From ad13d3369e705bc4bfd1ee59693c95c920e3fdf5 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Fri, 8 May 2026 15:25:39 +1000
Subject: [PATCH 005/192] chore: upgrade noble and scure deps to v2
Bumps @noble/ciphers, @noble/curves, @noble/hashes, @scure/bip32,
and @scure/bip39 to v2 and refactors crypto wrappers to the new APIs
(Uint8Array signatures, Point.fromBytes, Signature.fromBytes/toBytes,
bls.longSignatures, randomSecretKey, .js import extensions).
Adds an internal helper for converting between ox's { r, s, yParity }
Signature shape and noble's compact/recovered byte layouts. Restores
ImportMeta.env types for tests now that vitest v4 dropped them.
Amp-Thread-ID: https://ampcode.com/threads/T-019e05c5-ba3e-711e-8ea5-532440226027
---
.changeset/upgrade-noble-v2.md | 10 +++
package.json | 10 +--
pnpm-lock.yaml | 93 ++++++++++++++++++++++---
src/core/BinaryStateTree.ts | 2 +-
src/core/Bls.ts | 53 +++++++-------
src/core/BlsPoint.ts | 16 ++---
src/core/Bytes.ts | 2 +-
src/core/Ed25519.ts | 13 ++--
src/core/Hash.ts | 8 +--
src/core/Hex.ts | 2 +-
src/core/Keystore.ts | 8 +--
src/core/P256.ts | 75 +++++++++-----------
src/core/Secp256k1.ts | 69 +++++++++---------
src/core/Signature.ts | 11 +--
src/core/WebCryptoP256.ts | 9 ++-
src/core/X25519.ts | 4 +-
src/core/_test/Ed25519.test-d.ts | 2 +-
src/core/_test/X25519.test-d.ts | 2 +-
src/core/_test/X25519.test.ts | 2 +-
src/core/internal/mnemonic/wordlists.ts | 20 +++---
src/core/internal/signature.ts | 45 ++++++++++++
src/core/internal/webauthn.ts | 8 ++-
src/tempo/VirtualMaster.ts | 2 +-
test/env.d.ts | 12 ++++
24 files changed, 298 insertions(+), 180 deletions(-)
create mode 100644 .changeset/upgrade-noble-v2.md
create mode 100644 src/core/internal/signature.ts
create mode 100644 test/env.d.ts
diff --git a/.changeset/upgrade-noble-v2.md b/.changeset/upgrade-noble-v2.md
new file mode 100644
index 00000000..43cff596
--- /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/package.json b/package.json
index 25bcdd28..2729a7e2 100644
--- a/package.json
+++ b/package.json
@@ -149,11 +149,11 @@
],
"dependencies": {
"@adraffy/ens-normalize": "^1.11.0",
- "@noble/ciphers": "^1.3.0",
- "@noble/curves": "1.9.1",
- "@noble/hashes": "^1.8.0",
- "@scure/bip32": "^1.7.0",
- "@scure/bip39": "^1.6.0",
+ "@noble/ciphers": "^2.2.0",
+ "@noble/curves": "^2.2.0",
+ "@noble/hashes": "^2.2.0",
+ "@scure/bip32": "^2.0.0",
+ "@scure/bip39": "^2.0.0",
"abitype": "^1.2.3",
"eventemitter3": "5.0.1"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b02cce8e..be042d30 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -23,20 +23,20 @@ importers:
specifier: ^1.11.0
version: 1.11.1
'@noble/ciphers':
- specifier: ^1.3.0
- version: 1.3.0
+ specifier: ^2.2.0
+ version: 2.2.0
'@noble/curves':
- specifier: 1.9.1
- version: 1.9.1
+ specifier: ^2.2.0
+ version: 2.2.0
'@noble/hashes':
- specifier: ^1.8.0
- version: 1.8.0
+ specifier: ^2.2.0
+ version: 2.2.0
'@scure/bip32':
- specifier: ^1.7.0
- version: 1.7.0
+ specifier: ^2.0.0
+ version: 2.2.0
'@scure/bip39':
- specifier: ^1.6.0
- version: 1.6.0
+ specifier: ^2.0.0
+ version: 2.2.0
abitype:
specifier: ^1.2.3
version: 1.2.3(typescript@5.5.4)(zod@3.23.8)
@@ -356,24 +356,28 @@ packages:
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@biomejs/cli-linux-arm64@2.2.2':
resolution: {integrity: sha512-JfrK3gdmWWTh2J5tq/rcWCOsImVyzUnOS2fkjhiYKCQ+v8PqM+du5cfB7G1kXas+7KQeKSWALv18iQqdtIMvzw==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@biomejs/cli-linux-x64-musl@2.2.2':
resolution: {integrity: sha512-ZCLXcZvjZKSiRY/cFANKg+z6Fhsf9MHOzj+NrDQcM+LbqYRT97LyCLWy2AS+W2vP+i89RyRM+kbGpUzbRTYWig==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@biomejs/cli-linux-x64@2.2.2':
resolution: {integrity: sha512-Ogb+77edO5LEP/xbNicACOWVLt8mgC+E1wmpUakr+O4nKwLt9vXe74YNuT3T1dUBxC/SnrVmlzZFC7kQJEfquQ==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@biomejs/cli-win32-arm64@2.2.2':
resolution: {integrity: sha512-wBe2wItayw1zvtXysmHJQoQqXlTzHSpQRyPpJKiNIR21HzH/CrZRDFic1C1jDdp+zAPtqhNExa0owKMbNwW9cQ==}
@@ -1076,6 +1080,10 @@ packages:
resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==}
engines: {node: ^14.21.3 || >=16}
+ '@noble/ciphers@2.2.0':
+ resolution: {integrity: sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA==}
+ engines: {node: '>= 20.19.0'}
+
'@noble/curves@1.9.1':
resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==}
engines: {node: ^14.21.3 || >=16}
@@ -1084,6 +1092,10 @@ packages:
resolution: {integrity: sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==}
engines: {node: '>= 20.19.0'}
+ '@noble/curves@2.2.0':
+ resolution: {integrity: sha512-T/BoHgFXirb0ENSPBquzX0rcjXeM6Lo892a2jlYJkqk83LqZx0l1Of7DzlKJ6jkpvMrkHSnAcgb5JegL8SeIkQ==}
+ engines: {node: '>= 20.19.0'}
+
'@noble/hashes@1.8.0':
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
engines: {node: ^14.21.3 || >=16}
@@ -1092,6 +1104,10 @@ packages:
resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==}
engines: {node: '>= 20.19.0'}
+ '@noble/hashes@2.2.0':
+ resolution: {integrity: sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==}
+ engines: {node: '>= 20.19.0'}
+
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -1930,96 +1946,115 @@ packages:
resolution: {integrity: sha512-6npqOKEPRZkLrMcvyC/32OzJ2srdPzCylJjiTJT2c0bwwSGm7nz2F9mNQ1WrAqCBZROcQn91Fno+khFhVijmFA==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm-gnueabihf@4.34.7':
resolution: {integrity: sha512-Z0TzhrsNqukTz3ISzrvyshQpFnFRfLunYiXxlCRvcrb3nvC5rVKI+ZXPFG/Aa4jhQa1gHgH3A0exHaRRN4VmdQ==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.27.2':
resolution: {integrity: sha512-V9Xg6eXtgBtHq2jnuQwM/jr2mwe2EycnopO8cbOvpzFuySCGtKlPCI3Hj9xup/pJK5Q0388qfZZy2DqV2J8ftw==}
cpu: [arm]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm-musleabihf@4.34.7':
resolution: {integrity: sha512-nkznpyXekFAbvFBKBy4nNppSgneB1wwG1yx/hujN3wRnhnkrYVugMTCBXED4+Ni6thoWfQuHNYbFjgGH0MBXtw==}
cpu: [arm]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.27.2':
resolution: {integrity: sha512-uCFX9gtZJoQl2xDTpRdseYuNqyKkuMDtH6zSrBTA28yTfKyjN9hQ2B04N5ynR8ILCoSDOrG/Eg+J2TtJ1e/CSA==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm64-gnu@4.34.7':
resolution: {integrity: sha512-KCjlUkcKs6PjOcxolqrXglBDcfCuUCTVlX5BgzgoJHw+1rWH1MCkETLkLe5iLLS9dP5gKC7mp3y6x8c1oGBUtA==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.27.2':
resolution: {integrity: sha512-/PU9P+7Rkz8JFYDHIi+xzHabOu9qEWR07L5nWLIUsvserrxegZExKCi2jhMZRd0ATdboKylu/K5yAXbp7fYFvA==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm64-musl@4.34.7':
resolution: {integrity: sha512-uFLJFz6+utmpbR313TTx+NpPuAXbPz4BhTQzgaP0tozlLnGnQ6rCo6tLwaSa6b7l6gRErjLicXQ1iPiXzYotjw==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-loongarch64-gnu@4.34.7':
resolution: {integrity: sha512-ws8pc68UcJJqCpneDFepnwlsMUFoWvPbWXT/XUrJ7rWUL9vLoIN3GAasgG+nCvq8xrE3pIrd+qLX/jotcLy0Qw==}
cpu: [loong64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-powerpc64le-gnu@4.27.2':
resolution: {integrity: sha512-eCHmol/dT5odMYi/N0R0HC8V8QE40rEpkyje/ZAXJYNNoSfrObOvG/Mn+s1F/FJyB7co7UQZZf6FuWnN6a7f4g==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-powerpc64le-gnu@4.34.7':
resolution: {integrity: sha512-vrDk9JDa/BFkxcS2PbWpr0C/LiiSLxFbNOBgfbW6P8TBe9PPHx9Wqbvx2xgNi1TOAyQHQJ7RZFqBiEohm79r0w==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.27.2':
resolution: {integrity: sha512-DEP3Njr9/ADDln3kNi76PXonLMSSMiCir0VHXxmGSHxCxDfQ70oWjHcJGfiBugzaqmYdTC7Y+8Int6qbnxPBIQ==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.34.7':
resolution: {integrity: sha512-rB+ejFyjtmSo+g/a4eovDD1lHWHVqizN8P0Hm0RElkINpS0XOdpaXloqM4FBkF9ZWEzg6bezymbpLmeMldfLTw==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.27.2':
resolution: {integrity: sha512-NHGo5i6IE/PtEPh5m0yw5OmPMpesFnzMIS/lzvN5vknnC1sXM5Z/id5VgcNPgpD+wHmIcuYYgW+Q53v+9s96lQ==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.34.7':
resolution: {integrity: sha512-nNXNjo4As6dNqRn7OrsnHzwTgtypfRA3u3AKr0B3sOOo+HkedIbn8ZtFnB+4XyKJojIfqDKmbIzO1QydQ8c+Pw==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.27.2':
resolution: {integrity: sha512-PaW2DY5Tan+IFvNJGHDmUrORadbe/Ceh8tQxi8cmdQVCCYsLoQo2cuaSj+AU+YRX8M4ivS2vJ9UGaxfuNN7gmg==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.34.7':
resolution: {integrity: sha512-9kPVf9ahnpOMSGlCxXGv980wXD0zRR3wyk8+33/MXQIpQEOpaNe7dEHm5LMfyRZRNt9lMEQuH0jUKj15MkM7QA==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.27.2':
resolution: {integrity: sha512-dOlWEMg2gI91Qx5I/HYqOD6iqlJspxLcS4Zlg3vjk1srE67z5T2Uz91yg/qA8sY0XcwQrFzWWiZhMNERylLrpQ==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-x64-musl@4.34.7':
resolution: {integrity: sha512-7wJPXRWTTPtTFDFezA8sle/1sdgxDjuMoRXEKtx97ViRxGGkVQYovem+Q8Pr/2HxiHp74SSRG+o6R0Yq0shPwQ==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-win32-arm64-msvc@4.27.2':
resolution: {integrity: sha512-euMIv/4x5Y2/ImlbGl88mwKNXDsvzbWUlT7DFky76z2keajCtcbAsN9LUdmk31hAoVmJJYSThgdA0EsPeTr1+w==}
@@ -2079,12 +2114,21 @@ packages:
'@scure/base@2.0.0':
resolution: {integrity: sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w==}
+ '@scure/base@2.2.0':
+ resolution: {integrity: sha512-b8XEupJibegiXV+tDUseI8oLQc8ei3d/4Jkb2RpbHh3MfE054ov3uIz2dhFkB3FI8iwYkEh0gGCApkrYggkPNg==}
+
'@scure/bip32@1.7.0':
resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==}
+ '@scure/bip32@2.2.0':
+ resolution: {integrity: sha512-zFr7t2F+a9+5tB7QbarF2HQNYrgjCNaoLAupZdKkrFMYMozJf5zqH2WJCQibMzm1qQ0QogrxVGO3qXfQDYMaQg==}
+
'@scure/bip39@1.6.0':
resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==}
+ '@scure/bip39@2.2.0':
+ resolution: {integrity: sha512-T/Bj/YvYMNkIPq6EENO6/rcs2e7qTNuyoUXf0KBFDmp0ZDu0H2X4Lq6yC3i0c8PcWkov5EbW+yQZZbdMmk154A==}
+
'@sec-ant/readable-stream@0.4.1':
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
@@ -2193,24 +2237,28 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.0.7':
resolution: {integrity: sha512-WHYs3cpPEJb/ccyT20NOzopYQkl7JKncNBUbb77YFlwlXMVJLLV3nrXQKhr7DmZxz2ZXqjyUwsj2rdzd9stYdw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.0.7':
resolution: {integrity: sha512-7bP1UyuX9kFxbOwkeIJhBZNevKYPXB6xZI37v09fqi6rqRJR8elybwjMUHm54GVP+UTtJ14ueB1K54Dy1tIO6w==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.0.7':
resolution: {integrity: sha512-gBQIV8nL/LuhARNGeroqzXymMzzW5wQzqlteVqOVoqwEfpHOP3GMird5pGFbnpY+NP0fOlsZGrxxOPQ4W/84bQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@tailwindcss/oxide-win32-arm64-msvc@4.0.7':
resolution: {integrity: sha512-aH530NFfx0kpQpvYMfWoeG03zGnRCMVlQG8do/5XeahYydz+6SIBxA1tl/cyITSJyWZHyVt6GVNkXeAD30v0Xg==}
@@ -4364,24 +4412,28 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-arm64-musl@1.29.1:
resolution: {integrity: sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
lightningcss-linux-x64-gnu@1.29.1:
resolution: {integrity: sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
lightningcss-linux-x64-musl@1.29.1:
resolution: {integrity: sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ libc: [musl]
lightningcss-win32-arm64-msvc@1.29.1:
resolution: {integrity: sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==}
@@ -7236,6 +7288,8 @@ snapshots:
'@noble/ciphers@1.3.0': {}
+ '@noble/ciphers@2.2.0': {}
+
'@noble/curves@1.9.1':
dependencies:
'@noble/hashes': 1.8.0
@@ -7244,10 +7298,16 @@ snapshots:
dependencies:
'@noble/hashes': 2.0.1
+ '@noble/curves@2.2.0':
+ dependencies:
+ '@noble/hashes': 2.2.0
+
'@noble/hashes@1.8.0': {}
'@noble/hashes@2.0.1': {}
+ '@noble/hashes@2.2.0': {}
+
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -8165,17 +8225,30 @@ snapshots:
'@scure/base@2.0.0': {}
+ '@scure/base@2.2.0': {}
+
'@scure/bip32@1.7.0':
dependencies:
'@noble/curves': 1.9.1
'@noble/hashes': 1.8.0
'@scure/base': 1.2.5
+ '@scure/bip32@2.2.0':
+ dependencies:
+ '@noble/curves': 2.2.0
+ '@noble/hashes': 2.2.0
+ '@scure/base': 2.2.0
+
'@scure/bip39@1.6.0':
dependencies:
'@noble/hashes': 1.8.0
'@scure/base': 1.2.5
+ '@scure/bip39@2.2.0':
+ dependencies:
+ '@noble/hashes': 2.2.0
+ '@scure/base': 2.2.0
+
'@sec-ant/readable-stream@0.4.1': {}
'@shikijs/core@1.22.0':
diff --git a/src/core/BinaryStateTree.ts b/src/core/BinaryStateTree.ts
index e3440568..11d3f417 100644
--- a/src/core/BinaryStateTree.ts
+++ b/src/core/BinaryStateTree.ts
@@ -1,4 +1,4 @@
-import { blake3 } from '@noble/hashes/blake3'
+import { blake3 } from '@noble/hashes/blake3.js'
import * as Bytes from './Bytes.js'
import type { OneOf } from './internal/types.js'
diff --git a/src/core/Bls.ts b/src/core/Bls.ts
index a69f06d4..fd4af020 100644
--- a/src/core/Bls.ts
+++ b/src/core/Bls.ts
@@ -1,5 +1,4 @@
-import type { ProjPointType } from '@noble/curves/abstract/weierstrass'
-import { bls12_381 as bls } from '@noble/curves/bls12-381'
+import { bls12_381 as bls } from '@noble/curves/bls12-381.js'
import type * as BlsPoint from './BlsPoint.js'
import * as Bytes from './Bytes.js'
@@ -56,13 +55,13 @@ export function aggregate(
const group = typeof points[0]?.x === 'bigint' ? bls.G1 : bls.G2
const point = points.reduce(
(acc, point) =>
- acc.add(new (group as any).ProjectivePoint(point.x, point.y, point.z)),
- group.ProjectivePoint.ZERO,
+ acc.add(new (group as any).Point(point.x, point.y, point.z)),
+ group.Point.ZERO,
)
return {
- x: point.px,
- y: point.py,
- z: point.pz,
+ x: point.X,
+ y: point.Y,
+ z: point.Z,
}
}
@@ -330,10 +329,10 @@ export function getPublicKey(
export function getPublicKey(options: getPublicKey.Options): BlsPoint.BlsPoint {
const { privateKey, size = 'short-key:long-sig' } = options
const group = size === 'short-key:long-sig' ? bls.G1 : bls.G2
- const { px, py, pz } = group.ProjectivePoint.fromPrivateKey(
- Hex.from(privateKey).slice(2),
+ const point = group.Point.BASE.multiply(
+ group.Point.Fn.fromBytes(Bytes.from(privateKey)),
)
- return { x: px, y: py, z: pz }
+ return { x: point.X, y: point.Y, z: point.Z }
}
export declare namespace getPublicKey {
@@ -373,7 +372,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = bls.utils.randomPrivateKey()
+ const bytes = bls.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
@@ -470,13 +469,13 @@ export function sign(options: sign.Options): BlsPoint.BlsPoint {
const privateKeyGroup = size === 'short-key:long-sig' ? bls.G1 : bls.G2
const signature = payloadPoint.multiply(
- privateKeyGroup.normPrivateKeyToScalar(privateKey.slice(2)),
- ) as ProjPointType
+ privateKeyGroup.Point.Fn.fromBytes(Bytes.from(privateKey)),
+ )
return {
- x: signature.px,
- y: signature.py,
- z: signature.pz,
+ x: signature.X,
+ y: signature.Y,
+ z: signature.Z,
}
}
@@ -571,33 +570,29 @@ export function verify(options: verify.Options): boolean {
const payloadPoint = group.hashToCurve(
Bytes.from(payload),
suite ? { DST: Bytes.fromString(suite) } : undefined,
- ) as ProjPointType
+ )
const shortSigPairing = () =>
bls.pairingBatch([
{
- g1: payloadPoint,
- g2: new bls.G2.ProjectivePoint(publicKey.x, publicKey.y, publicKey.z),
+ g1: payloadPoint as InstanceType,
+ g2: new bls.G2.Point(publicKey.x, publicKey.y, publicKey.z),
},
{
- g1: new bls.G1.ProjectivePoint(signature.x, signature.y, signature.z),
- g2: bls.G2.ProjectivePoint.BASE.negate(),
+ g1: new bls.G1.Point(signature.x, signature.y, signature.z),
+ g2: bls.G2.Point.BASE.negate(),
},
])
const longSigPairing = () =>
bls.pairingBatch([
{
- g1: new bls.G1.ProjectivePoint(
- publicKey.x,
- publicKey.y,
- publicKey.z,
- ).negate(),
- g2: payloadPoint,
+ g1: new bls.G1.Point(publicKey.x, publicKey.y, publicKey.z).negate(),
+ g2: payloadPoint as InstanceType,
},
{
- g1: bls.G1.ProjectivePoint.BASE,
- g2: new bls.G2.ProjectivePoint(signature.x, signature.y, signature.z),
+ g1: bls.G1.Point.BASE,
+ g2: new bls.G2.Point(signature.x, signature.y, signature.z),
},
])
diff --git a/src/core/BlsPoint.ts b/src/core/BlsPoint.ts
index 97a47874..e3e549d4 100644
--- a/src/core/BlsPoint.ts
+++ b/src/core/BlsPoint.ts
@@ -1,4 +1,4 @@
-import { bls12_381 as bls } from '@noble/curves/bls12-381'
+import { bls12_381 as bls } from '@noble/curves/bls12-381.js'
import type * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
@@ -61,11 +61,7 @@ export function toBytes(
point: point,
): point extends G1 ? G1Bytes : G2Bytes {
const group = typeof point.z === 'bigint' ? bls.G1 : bls.G2
- return new (group as any).ProjectivePoint(
- point.x,
- point.y,
- point.z,
- ).toRawBytes()
+ return new (group as any).Point(point.x, point.y, point.z).toBytes()
}
export declare namespace toBytes {
@@ -155,11 +151,11 @@ export function fromBytes(
// eslint-disable-next-line jsdoc/require-jsdoc
export function fromBytes(bytes: Bytes.Bytes): BlsPoint {
const group = bytes.length === 48 ? bls.G1 : bls.G2
- const point = group.ProjectivePoint.fromHex(bytes)
+ const point = group.Point.fromBytes(bytes)
return {
- x: point.px,
- y: point.py,
- z: point.pz,
+ x: point.X,
+ y: point.Y,
+ z: point.Z,
}
}
diff --git a/src/core/Bytes.ts b/src/core/Bytes.ts
index 97500413..2cb15e27 100644
--- a/src/core/Bytes.ts
+++ b/src/core/Bytes.ts
@@ -1,4 +1,4 @@
-import { equalBytes } from '@noble/curves/abstract/utils'
+import { equalBytes } from '@noble/curves/utils.js'
import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import * as internal from './internal/bytes.js'
diff --git a/src/core/Ed25519.ts b/src/core/Ed25519.ts
index 7fc69443..38c86d05 100644
--- a/src/core/Ed25519.ts
+++ b/src/core/Ed25519.ts
@@ -1,8 +1,4 @@
-import {
- ed25519,
- edwardsToMontgomeryPriv,
- edwardsToMontgomeryPub,
-} from '@noble/curves/ed25519'
+import { ed25519 } from '@noble/curves/ed25519.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
@@ -124,7 +120,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = ed25519.utils.randomPrivateKey()
+ const bytes = ed25519.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
@@ -263,7 +259,7 @@ export function toX25519PublicKey(
): toX25519PublicKey.ReturnType {
const { as = 'Hex', publicKey } = options
const publicKeyBytes = Bytes.from(publicKey)
- const x25519PublicKeyBytes = edwardsToMontgomeryPub(publicKeyBytes)
+ const x25519PublicKeyBytes = ed25519.utils.toMontgomery(publicKeyBytes)
if (as === 'Hex') return Hex.fromBytes(x25519PublicKeyBytes) as never
return x25519PublicKeyBytes as never
}
@@ -312,7 +308,8 @@ export function toX25519PrivateKey(
): toX25519PrivateKey.ReturnType {
const { as = 'Hex', privateKey } = options
const privateKeyBytes = Bytes.from(privateKey)
- const x25519PrivateKeyBytes = edwardsToMontgomeryPriv(privateKeyBytes)
+ const x25519PrivateKeyBytes =
+ ed25519.utils.toMontgomerySecret(privateKeyBytes)
if (as === 'Hex') return Hex.fromBytes(x25519PrivateKeyBytes) as never
return x25519PrivateKeyBytes as never
}
diff --git a/src/core/Hash.ts b/src/core/Hash.ts
index 4c16cb04..e0a62a4a 100644
--- a/src/core/Hash.ts
+++ b/src/core/Hash.ts
@@ -1,7 +1,7 @@
-import { hmac } from '@noble/hashes/hmac'
-import { ripemd160 as noble_ripemd160 } from '@noble/hashes/ripemd160'
-import { keccak_256 as noble_keccak256 } from '@noble/hashes/sha3'
-import { sha256 as noble_sha256 } from '@noble/hashes/sha256'
+import { hmac } from '@noble/hashes/hmac.js'
+import { ripemd160 as noble_ripemd160 } from '@noble/hashes/legacy.js'
+import { sha256 as noble_sha256 } from '@noble/hashes/sha2.js'
+import { keccak_256 as noble_keccak256 } from '@noble/hashes/sha3.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
diff --git a/src/core/Hex.ts b/src/core/Hex.ts
index fcf6e853..23af4e63 100644
--- a/src/core/Hex.ts
+++ b/src/core/Hex.ts
@@ -1,4 +1,4 @@
-import { equalBytes } from '@noble/curves/abstract/utils'
+import { equalBytes } from '@noble/curves/utils.js'
import * as Bytes from './Bytes.js'
import * as Errors from './Errors.js'
import * as internal_bytes from './internal/bytes.js'
diff --git a/src/core/Keystore.ts b/src/core/Keystore.ts
index e4b05f27..f419e4d6 100644
--- a/src/core/Keystore.ts
+++ b/src/core/Keystore.ts
@@ -1,13 +1,13 @@
-import { ctr } from '@noble/ciphers/aes'
+import { ctr } from '@noble/ciphers/aes.js'
import {
pbkdf2 as pbkdf2_noble,
pbkdf2Async as pbkdf2Async_noble,
-} from '@noble/hashes/pbkdf2'
+} from '@noble/hashes/pbkdf2.js'
import {
scrypt as scrypt_noble,
scryptAsync as scryptAsync_noble,
-} from '@noble/hashes/scrypt'
-import { sha256 } from '@noble/hashes/sha2'
+} from '@noble/hashes/scrypt.js'
+import { sha256 } from '@noble/hashes/sha2.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
diff --git a/src/core/P256.ts b/src/core/P256.ts
index 9a98b79a..62681cdf 100644
--- a/src/core/P256.ts
+++ b/src/core/P256.ts
@@ -1,13 +1,18 @@
-import { secp256r1 } from '@noble/curves/p256'
+import { p256 as noble_p256 } from '@noble/curves/nist.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import * as Entropy from './internal/entropy.js'
+import {
+ fromRecoveredBytes,
+ toCompactBytes,
+ toRecoveredBytes,
+} from './internal/signature.js'
import * as PublicKey from './PublicKey.js'
import type * as Signature from './Signature.js'
/** Re-export of noble/curves P256 utilities. */
-export const noble = secp256r1
+export const noble = noble_p256
/**
* Creates a new P256 ECDSA key pair consisting of a private key and its corresponding public key.
@@ -74,12 +79,8 @@ export function getPublicKey(
options: getPublicKey.Options,
): PublicKey.PublicKey {
const { privateKey } = options
- const point = secp256r1.ProjectivePoint.fromPrivateKey(
- typeof privateKey === 'string'
- ? privateKey.slice(2)
- : Hex.fromBytes(privateKey).slice(2),
- )
- return PublicKey.from(point)
+ const bytes = noble_p256.getPublicKey(Bytes.from(privateKey), false)
+ return PublicKey.fromBytes(bytes)
}
export declare namespace getPublicKey {
@@ -116,17 +117,11 @@ export function getSharedSecret(
options: getSharedSecret.Options,
): getSharedSecret.ReturnType {
const { as = 'Hex', privateKey, publicKey } = options
- const point = secp256r1.ProjectivePoint.fromHex(
- PublicKey.toHex(publicKey).slice(2),
- )
- const privateKeyHex =
- typeof privateKey === 'string'
- ? privateKey.slice(2)
- : Hex.fromBytes(privateKey).slice(2)
- const sharedPoint = point.multiply(
- secp256r1.utils.normPrivateKeyToScalar(privateKeyHex),
+ const sharedSecret = noble_p256.getSharedSecret(
+ Bytes.from(privateKey),
+ PublicKey.toBytes(publicKey),
+ true, // compressed
)
- const sharedSecret = sharedPoint.toRawBytes(true) // compressed format
if (as === 'Hex') return Hex.fromBytes(sharedSecret) as never
return sharedSecret as never
}
@@ -175,7 +170,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = secp256r1.utils.randomPrivateKey()
+ const bytes = noble_p256.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
@@ -218,15 +213,12 @@ export function recoverPublicKey(
options: recoverPublicKey.Options,
): PublicKey.PublicKey {
const { payload, signature } = options
- const { r, s, yParity } = signature
- const signature_ = new secp256r1.Signature(
- BigInt(r),
- BigInt(s),
- ).addRecoveryBit(yParity)
- const payload_ =
- payload instanceof Uint8Array ? Hex.fromBytes(payload) : payload
- const point = signature_.recoverPublicKey(payload_.substring(2))
- return PublicKey.from(point)
+ const sigBytes = toRecoveredBytes(signature)
+ const point = noble_p256.Signature.fromBytes(
+ sigBytes,
+ 'recovered',
+ ).recoverPublicKey(Bytes.from(payload))
+ return PublicKey.fromBytes(point.toBytes(false))
}
export declare namespace recoverPublicKey {
@@ -266,23 +258,20 @@ export function sign(options: sign.Options): Signature.Signature {
payload,
privateKey,
} = options
- const { r, s, recovery } = secp256r1.sign(
- payload instanceof Uint8Array ? payload : Bytes.fromHex(payload),
- privateKey instanceof Uint8Array ? privateKey : Bytes.fromHex(privateKey),
+ const sigBytes = noble_p256.sign(
+ Bytes.from(payload),
+ Bytes.from(privateKey),
{
extraEntropy:
typeof extraEntropy === 'boolean'
? extraEntropy
- : Hex.from(extraEntropy).slice(2),
+ : Bytes.from(extraEntropy),
lowS: true,
- ...(hash ? { prehash: true } : {}),
+ prehash: hash === true,
+ format: 'recovered',
},
)
- return {
- r,
- s,
- yParity: recovery,
- }
+ return fromRecoveredBytes(sigBytes)
}
export declare namespace sign {
@@ -332,11 +321,11 @@ export declare namespace sign {
*/
export function verify(options: verify.Options): boolean {
const { hash, payload, publicKey, signature } = options
- return secp256r1.verify(
- signature,
- payload instanceof Uint8Array ? payload : Bytes.fromHex(payload),
- PublicKey.toHex(publicKey).substring(2),
- { lowS: true, ...(hash ? { prehash: true } : {}) },
+ return noble_p256.verify(
+ toCompactBytes(signature),
+ Bytes.from(payload),
+ PublicKey.toBytes(publicKey),
+ { lowS: true, prehash: hash === true },
)
}
diff --git a/src/core/Secp256k1.ts b/src/core/Secp256k1.ts
index b3de84be..4763605c 100644
--- a/src/core/Secp256k1.ts
+++ b/src/core/Secp256k1.ts
@@ -1,9 +1,14 @@
-import { secp256k1 } from '@noble/curves/secp256k1'
+import { secp256k1 } from '@noble/curves/secp256k1.js'
import * as Address from './Address.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import * as Entropy from './internal/entropy.js'
+import {
+ fromRecoveredBytes,
+ toCompactBytes,
+ toRecoveredBytes,
+} from './internal/signature.js'
import type { OneOf } from './internal/types.js'
import * as PublicKey from './PublicKey.js'
import type * as Signature from './Signature.js'
@@ -76,10 +81,8 @@ export function getPublicKey(
options: getPublicKey.Options,
): PublicKey.PublicKey {
const { privateKey } = options
- const point = secp256k1.ProjectivePoint.fromPrivateKey(
- Hex.from(privateKey).slice(2),
- )
- return PublicKey.from(point)
+ const bytes = secp256k1.getPublicKey(Bytes.from(privateKey), false)
+ return PublicKey.fromBytes(bytes)
}
export declare namespace getPublicKey {
@@ -119,13 +122,11 @@ export function getSharedSecret(
options: getSharedSecret.Options,
): getSharedSecret.ReturnType {
const { as = 'Hex', privateKey, publicKey } = options
- const point = secp256k1.ProjectivePoint.fromHex(
- PublicKey.toHex(publicKey).slice(2),
- )
- const sharedPoint = point.multiply(
- secp256k1.utils.normPrivateKeyToScalar(Hex.from(privateKey).slice(2)),
+ const sharedSecret = secp256k1.getSharedSecret(
+ Bytes.from(privateKey),
+ PublicKey.toBytes(publicKey),
+ true, // compressed
)
- const sharedSecret = sharedPoint.toRawBytes(true) // compressed format
if (as === 'Hex') return Hex.fromBytes(sharedSecret) as never
return sharedSecret as never
}
@@ -175,7 +176,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = secp256k1.utils.randomPrivateKey()
+ const bytes = secp256k1.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
@@ -258,13 +259,12 @@ export function recoverPublicKey(
options: recoverPublicKey.Options,
): PublicKey.PublicKey {
const { payload, signature } = options
- const { r, s, yParity } = signature
- const signature_ = new secp256k1.Signature(
- BigInt(r),
- BigInt(s),
- ).addRecoveryBit(yParity)
- const point = signature_.recoverPublicKey(Hex.from(payload).substring(2))
- return PublicKey.from(point)
+ const sigBytes = toRecoveredBytes(signature)
+ const point = secp256k1.Signature.fromBytes(
+ sigBytes,
+ 'recovered',
+ ).recoverPublicKey(Bytes.from(payload))
+ return PublicKey.fromBytes(point.toBytes(false))
}
export declare namespace recoverPublicKey {
@@ -304,23 +304,16 @@ export function sign(options: sign.Options): Signature.Signature {
payload,
privateKey,
} = options
- const { r, s, recovery } = secp256k1.sign(
- Bytes.from(payload),
- Bytes.from(privateKey),
- {
- extraEntropy:
- typeof extraEntropy === 'boolean'
- ? extraEntropy
- : Hex.from(extraEntropy).slice(2),
- lowS: true,
- ...(hash ? { prehash: true } : {}),
- },
- )
- return {
- r,
- s,
- yParity: recovery,
- }
+ const sigBytes = secp256k1.sign(Bytes.from(payload), Bytes.from(privateKey), {
+ extraEntropy:
+ typeof extraEntropy === 'boolean'
+ ? extraEntropy
+ : Bytes.from(extraEntropy),
+ lowS: true,
+ prehash: hash === true,
+ format: 'recovered',
+ })
+ return fromRecoveredBytes(sigBytes)
}
export declare namespace sign {
@@ -390,10 +383,10 @@ export function verify(options: verify.Options): boolean {
if (address)
return Address.isEqual(address, recoverAddress({ payload, signature }))
return secp256k1.verify(
- signature,
+ toCompactBytes(signature),
Bytes.from(payload),
PublicKey.toBytes(publicKey),
- ...(hash ? [{ prehash: true, lowS: true }] : []),
+ { lowS: true, prehash: hash === true },
)
}
diff --git a/src/core/Signature.ts b/src/core/Signature.ts
index 250d376f..d8e0edf7 100644
--- a/src/core/Signature.ts
+++ b/src/core/Signature.ts
@@ -1,4 +1,4 @@
-import { secp256k1 } from '@noble/curves/secp256k1'
+import { secp256k1 } from '@noble/curves/secp256k1.js'
import * as Bytes from './Bytes.js'
import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
@@ -360,7 +360,10 @@ export declare namespace fromDerBytes {
* @returns The {@link ox#Signature.Signature}.
*/
export function fromDerHex(signature: Hex.Hex): Signature {
- const { r, s } = secp256k1.Signature.fromDER(Hex.from(signature).slice(2))
+ const { r, s } = secp256k1.Signature.fromHex(
+ Hex.from(signature).slice(2),
+ 'der',
+ )
return { r, s }
}
@@ -562,7 +565,7 @@ export declare namespace toHex {
*/
export function toDerBytes(signature: Signature): Bytes.Bytes {
const sig = new secp256k1.Signature(signature.r, signature.s)
- return sig.toDERRawBytes()
+ return sig.toBytes('der')
}
export declare namespace toDerBytes {
@@ -590,7 +593,7 @@ export declare namespace toDerBytes {
*/
export function toDerHex(signature: Signature): Hex.Hex {
const sig = new secp256k1.Signature(signature.r, signature.s)
- return `0x${sig.toDERHex()}`
+ return `0x${sig.toHex('der')}`
}
export declare namespace toDerHex {
diff --git a/src/core/WebCryptoP256.ts b/src/core/WebCryptoP256.ts
index f43f5830..10dd4670 100644
--- a/src/core/WebCryptoP256.ts
+++ b/src/core/WebCryptoP256.ts
@@ -1,4 +1,4 @@
-import { p256 } from '@noble/curves/p256'
+import { p256 } from '@noble/curves/nist.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
@@ -6,6 +6,9 @@ import type { Compute } from './internal/types.js'
import * as PublicKey from './PublicKey.js'
import type * as Signature from './Signature.js'
+/** secp256r1 / P-256 curve order. */
+const N = p256.Point.CURVE().n
+
/**
* Generates an ECDSA P256 key pair that includes:
*
@@ -245,7 +248,7 @@ export async function sign(
const signature_bytes = Bytes.fromArray(new Uint8Array(signature))
const r = Bytes.toBigInt(Bytes.slice(signature_bytes, 0, 32))
let s = Bytes.toBigInt(Bytes.slice(signature_bytes, 32, 64))
- if (s > p256.CURVE.n / 2n) s = p256.CURVE.n - s
+ if (s > N / 2n) s = N - s
return { r, s }
}
@@ -286,7 +289,7 @@ export async function verify(options: verify.Options): Promise {
const { lowS = true, payload, signature } = options
// Reject high-S signatures if lowS is enabled.
- if (lowS && signature.s > p256.CURVE.n / 2n) return false
+ if (lowS && signature.s > N / 2n) return false
const publicKey = await globalThis.crypto.subtle.importKey(
'raw',
diff --git a/src/core/X25519.ts b/src/core/X25519.ts
index e8be7845..b0c5a93b 100644
--- a/src/core/X25519.ts
+++ b/src/core/X25519.ts
@@ -1,4 +1,4 @@
-import { x25519 } from '@noble/curves/ed25519'
+import { x25519 } from '@noble/curves/ed25519.js'
import * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
@@ -180,7 +180,7 @@ export function randomPrivateKey(
options: randomPrivateKey.Options = {},
): randomPrivateKey.ReturnType {
const { as = 'Hex' } = options
- const bytes = x25519.utils.randomPrivateKey()
+ const bytes = x25519.utils.randomSecretKey()
if (as === 'Hex') return Hex.fromBytes(bytes) as never
return bytes as never
}
diff --git a/src/core/_test/Ed25519.test-d.ts b/src/core/_test/Ed25519.test-d.ts
index 804959aa..e0c4a281 100644
--- a/src/core/_test/Ed25519.test-d.ts
+++ b/src/core/_test/Ed25519.test-d.ts
@@ -150,6 +150,6 @@ test('verify', () => {
test('noble export', () => {
expectTypeOf(Ed25519.noble).toMatchTypeOf<
- typeof import('@noble/curves/ed25519').ed25519
+ typeof import('@noble/curves/ed25519.js').ed25519
>()
})
diff --git a/src/core/_test/X25519.test-d.ts b/src/core/_test/X25519.test-d.ts
index 9b6f7ddb..6976294c 100644
--- a/src/core/_test/X25519.test-d.ts
+++ b/src/core/_test/X25519.test-d.ts
@@ -127,6 +127,6 @@ test('randomPrivateKey', () => {
test('noble export', () => {
expectTypeOf(X25519.noble).toMatchTypeOf<
- typeof import('@noble/curves/ed25519').x25519
+ typeof import('@noble/curves/ed25519.js').x25519
>()
})
diff --git a/src/core/_test/X25519.test.ts b/src/core/_test/X25519.test.ts
index 92ca3274..5a18211e 100644
--- a/src/core/_test/X25519.test.ts
+++ b/src/core/_test/X25519.test.ts
@@ -8,7 +8,7 @@ describe('noble', () => {
expect(X25519.noble).toBeDefined()
expect(typeof X25519.noble.getPublicKey).toBe('function')
expect(typeof X25519.noble.getSharedSecret).toBe('function')
- expect(typeof X25519.noble.utils.randomPrivateKey).toBe('function')
+ expect(typeof X25519.noble.utils.randomSecretKey).toBe('function')
})
})
diff --git a/src/core/internal/mnemonic/wordlists.ts b/src/core/internal/mnemonic/wordlists.ts
index aef60660..f699b541 100644
--- a/src/core/internal/mnemonic/wordlists.ts
+++ b/src/core/internal/mnemonic/wordlists.ts
@@ -1,10 +1,10 @@
-export { wordlist as czech } from '@scure/bip39/wordlists/czech'
-export { wordlist as english } from '@scure/bip39/wordlists/english'
-export { wordlist as french } from '@scure/bip39/wordlists/french'
-export { wordlist as italian } from '@scure/bip39/wordlists/italian'
-export { wordlist as japanese } from '@scure/bip39/wordlists/japanese'
-export { wordlist as korean } from '@scure/bip39/wordlists/korean'
-export { wordlist as portuguese } from '@scure/bip39/wordlists/portuguese'
-export { wordlist as simplifiedChinese } from '@scure/bip39/wordlists/simplified-chinese'
-export { wordlist as spanish } from '@scure/bip39/wordlists/spanish'
-export { wordlist as traditionalChinese } from '@scure/bip39/wordlists/traditional-chinese'
+export { wordlist as czech } from '@scure/bip39/wordlists/czech.js'
+export { wordlist as english } from '@scure/bip39/wordlists/english.js'
+export { wordlist as french } from '@scure/bip39/wordlists/french.js'
+export { wordlist as italian } from '@scure/bip39/wordlists/italian.js'
+export { wordlist as japanese } from '@scure/bip39/wordlists/japanese.js'
+export { wordlist as korean } from '@scure/bip39/wordlists/korean.js'
+export { wordlist as portuguese } from '@scure/bip39/wordlists/portuguese.js'
+export { wordlist as simplifiedChinese } from '@scure/bip39/wordlists/simplified-chinese.js'
+export { wordlist as spanish } from '@scure/bip39/wordlists/spanish.js'
+export { wordlist as traditionalChinese } from '@scure/bip39/wordlists/traditional-chinese.js'
diff --git a/src/core/internal/signature.ts b/src/core/internal/signature.ts
new file mode 100644
index 00000000..d725c2f1
--- /dev/null
+++ b/src/core/internal/signature.ts
@@ -0,0 +1,45 @@
+import * as Bytes from '../Bytes.js'
+import type * as Signature from '../Signature.js'
+
+/**
+ * Encodes an ox `Signature` as a 64-byte compact noble signature
+ * (`r ++ s`, big-endian).
+ *
+ * @internal
+ */
+export function toCompactBytes(
+ signature: Signature.Signature,
+): Uint8Array {
+ const bytes = new Uint8Array(64)
+ bytes.set(Bytes.fromNumber(signature.r, { size: 32 }), 0)
+ bytes.set(Bytes.fromNumber(signature.s, { size: 32 }), 32)
+ return bytes
+}
+
+/**
+ * Encodes an ox `Signature` as a 65-byte recoverable noble signature
+ * (`recovery ++ r ++ s`, big-endian).
+ *
+ * @internal
+ */
+export function toRecoveredBytes(signature: Signature.Signature): Uint8Array {
+ const bytes = new Uint8Array(65)
+ bytes[0] = signature.yParity
+ bytes.set(Bytes.fromNumber(signature.r, { size: 32 }), 1)
+ bytes.set(Bytes.fromNumber(signature.s, { size: 32 }), 33)
+ return bytes
+}
+
+/**
+ * Decodes a 65-byte recoverable noble signature (`recovery ++ r ++ s`)
+ * into an ox `Signature`.
+ *
+ * @internal
+ */
+export function fromRecoveredBytes(bytes: Uint8Array): Signature.Signature {
+ return {
+ r: Bytes.toBigInt(bytes.subarray(1, 33)),
+ s: Bytes.toBigInt(bytes.subarray(33, 65)),
+ yParity: bytes[0]!,
+ }
+}
diff --git a/src/core/internal/webauthn.ts b/src/core/internal/webauthn.ts
index b3378c55..5f3f2b1c 100644
--- a/src/core/internal/webauthn.ts
+++ b/src/core/internal/webauthn.ts
@@ -1,4 +1,4 @@
-import { p256 } from '@noble/curves/p256'
+import { p256 } from '@noble/curves/nist.js'
import * as Registration from '../../webauthn/Registration.js'
import type * as Errors from '../Errors.js'
import * as PublicKey from '../PublicKey.js'
@@ -9,8 +9,10 @@ import * as PublicKey from '../PublicKey.js'
* @internal
*/
export function parseAsn1Signature(bytes: Uint8Array) {
- const sig = p256.Signature.fromDER(bytes).normalizeS()
- return { r: sig.r, s: sig.s }
+ const sig = p256.Signature.fromBytes(bytes, 'der')
+ const n = p256.Point.CURVE().n
+ const s = sig.hasHighS() ? n - sig.s : sig.s
+ return { r: sig.r, s }
}
/**
diff --git a/src/tempo/VirtualMaster.ts b/src/tempo/VirtualMaster.ts
index 40e713d6..5e8d96a4 100644
--- a/src/tempo/VirtualMaster.ts
+++ b/src/tempo/VirtualMaster.ts
@@ -1,4 +1,4 @@
-import { keccak_256 } from '@noble/hashes/sha3'
+import { keccak_256 } from '@noble/hashes/sha3.js'
import * as Address from '../core/Address.js'
import * as Bytes from '../core/Bytes.js'
import * as Errors from '../core/Errors.js'
diff --git a/test/env.d.ts b/test/env.d.ts
new file mode 100644
index 00000000..9c156e87
--- /dev/null
+++ b/test/env.d.ts
@@ -0,0 +1,12 @@
+interface ImportMetaEnv {
+ readonly VITE_TEMPO_ENV?: string
+ readonly VITE_TEMPO_TAG?: string
+ readonly VITE_TEMPO_LOG?: string
+ readonly VITE_TEMPO_HTTP_LOG?: string
+ readonly VITE_TEMPO_CREDENTIALS?: string
+ readonly VITEST_POOL_ID?: string
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv
+}
From 47b13461576770eb4f4283862309831259739325 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Fri, 8 May 2026 15:41:45 +1000
Subject: [PATCH 006/192] fix: include blockTimestamp on transactions
The tempo node returns a blockTimestamp on transaction responses; add
it to the core Transaction type, parse it in fromRpc, and serialize it
in toRpc. Updates the tempo e2e tests to assert it on transactions
returned via Transaction.fromRpc.
Amp-Thread-ID: https://ampcode.com/threads/T-019e05c5-ba3e-711e-8ea5-532440226027
---
src/core/Transaction.ts | 6 ++++++
src/tempo/e2e.test.ts | 14 ++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/src/core/Transaction.ts b/src/core/Transaction.ts
index 87508d93..ff5ab9dc 100644
--- a/src/core/Transaction.ts
+++ b/src/core/Transaction.ts
@@ -49,6 +49,8 @@ export type Base<
blockHash: pending extends true ? null : Hex.Hex
/** Number of block containing this transaction or `null` if pending */
blockNumber: pending extends true ? null : bigintType
+ /** Timestamp (in seconds) of the block containing this transaction, or `null` if pending. */
+ blockTimestamp?: (pending extends true ? null : bigintType) | undefined
/** Chain ID that this transaction is valid on. */
chainId: numberType
/** @alias `input` Added for TransactionEnvelope - Transaction compatibility. */
@@ -289,6 +291,8 @@ export function fromRpc<
transaction_.blockNumber = transaction.blockNumber
? BigInt(transaction.blockNumber)
: null
+ if (transaction.blockTimestamp)
+ transaction_.blockTimestamp = BigInt(transaction.blockTimestamp)
transaction_.data = transaction.input
transaction_.gas = BigInt(transaction.gas ?? 0n)
transaction_.nonce = BigInt(transaction.nonce ?? 0n)
@@ -371,6 +375,8 @@ export function toRpc(
typeof transaction.blockNumber === 'bigint'
? Hex.fromNumber(transaction.blockNumber)
: null
+ if (typeof transaction.blockTimestamp === 'bigint')
+ rpc.blockTimestamp = Hex.fromNumber(transaction.blockTimestamp)
rpc.from = transaction.from
rpc.gas = Hex.fromNumber(transaction.gas ?? 0n)
rpc.hash = transaction.hash
diff --git a/src/tempo/e2e.test.ts b/src/tempo/e2e.test.ts
index 1ba617a1..22153e0c 100644
--- a/src/tempo/e2e.test.ts
+++ b/src/tempo/e2e.test.ts
@@ -79,6 +79,7 @@ test('behavior: default (secp256k1)', async () => {
const {
blockNumber,
blockHash,
+ blockTimestamp,
chainId,
hash,
feeToken: _,
@@ -94,6 +95,7 @@ test('behavior: default (secp256k1)', async () => {
expect(blockNumber).toBeDefined()
expect(blockHash).toBeDefined()
+ expect(blockTimestamp).toBeDefined()
expect(chainId).toBe(chainId)
expect(hash).toBe(receipt.transactionHash)
expect(from).toBe(address)
@@ -288,6 +290,7 @@ test('behavior: default (p256)', async () => {
const {
blockNumber,
blockHash,
+ blockTimestamp,
chainId,
feeToken: _,
from,
@@ -303,6 +306,7 @@ test('behavior: default (p256)', async () => {
expect(blockNumber).toBeDefined()
expect(blockHash).toBeDefined()
+ expect(blockTimestamp).toBeDefined()
expect(chainId).toBe(chainId)
expect(from).toBe(address)
expect(hash).toBe(receipt.transactionHash)
@@ -429,6 +433,7 @@ test('behavior: default (p256 - webcrypto)', async () => {
const {
blockNumber,
blockHash,
+ blockTimestamp,
chainId,
feeToken: _,
from,
@@ -444,6 +449,7 @@ test('behavior: default (p256 - webcrypto)', async () => {
expect(blockNumber).toBeDefined()
expect(blockHash).toBeDefined()
+ expect(blockTimestamp).toBeDefined()
expect(chainId).toBeDefined()
expect(from).toBeDefined()
expect(hash).toBe(receipt.transactionHash)
@@ -577,6 +583,7 @@ test('behavior: default (webauthn)', async () => {
const {
blockNumber,
blockHash,
+ blockTimestamp,
chainId,
feeToken: _,
from,
@@ -592,6 +599,7 @@ test('behavior: default (webauthn)', async () => {
expect(blockNumber).toBeDefined()
expect(blockHash).toBeDefined()
+ expect(blockTimestamp).toBeDefined()
expect(chainId).toBe(chainId)
expect(from).toBeDefined()
expect(hash).toBe(receipt.transactionHash)
@@ -956,6 +964,7 @@ describe('behavior: keyAuthorization', () => {
const {
blockNumber,
blockHash,
+ blockTimestamp,
chainId: _,
gasPrice,
hash,
@@ -971,6 +980,7 @@ describe('behavior: keyAuthorization', () => {
expect(blockNumber).toBeDefined()
expect(blockHash).toBeDefined()
+ expect(blockTimestamp).toBeDefined()
expect(gasPrice).toBeDefined()
expect(maxFeePerGas).toBeDefined()
expect(maxPriorityFeePerGas).toBeDefined()
@@ -1173,6 +1183,7 @@ describe('behavior: keyAuthorization', () => {
const {
blockNumber,
blockHash,
+ blockTimestamp,
chainId: _,
gasPrice,
hash,
@@ -1188,6 +1199,7 @@ describe('behavior: keyAuthorization', () => {
expect(blockNumber).toBeDefined()
expect(blockHash).toBeDefined()
+ expect(blockTimestamp).toBeDefined()
expect(gasPrice).toBeDefined()
expect(hash).toBe(receipt.transactionHash)
expect(from).toBe(root.address)
@@ -1392,6 +1404,7 @@ describe('behavior: keyAuthorization', () => {
const {
blockNumber,
blockHash,
+ blockTimestamp,
chainId: _,
gasPrice,
hash,
@@ -1407,6 +1420,7 @@ describe('behavior: keyAuthorization', () => {
expect(blockNumber).toBeDefined()
expect(blockHash).toBeDefined()
+ expect(blockTimestamp).toBeDefined()
expect(gasPrice).toBeDefined()
expect(hash).toBe(receipt.transactionHash)
expect(from).toBe(root.address)
From 395180fbf920fdce00bf58ae5b54bd654fefcd0f Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 09:56:55 +1000
Subject: [PATCH 007/192] chore: switch to zile publish helpers and ignore
tasks/
Amp-Thread-ID: https://ampcode.com/threads/T-019e1976-9c6f-745e-87d8-d00af1fe5aaf
---
.github/workflows/prerelease.yml | 2 +-
.github/workflows/snapshot.yml | 3 ++-
.gitignore | 1 +
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml
index 3747fe93..82db807c 100644
--- a/.github/workflows/prerelease.yml
+++ b/.github/workflows/prerelease.yml
@@ -17,5 +17,5 @@ jobs:
- name: Prepublish
run: |
cd src && pnpm version prerelease --preid $(git rev-parse --short=7 HEAD) && cd ..
- pnpm changeset:prepublish
+ pnpm exec zile publish:prepare
pnpx pkg-pr-new publish --pnpm --compact './src'
diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml
index 64941836..7457053f 100644
--- a/.github/workflows/snapshot.yml
+++ b/.github/workflows/snapshot.yml
@@ -30,6 +30,7 @@ jobs:
npm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN"
pnpm clean
pnpm changeset version --no-git-tag --snapshot $snapshot
- pnpm changeset:prepublish
+ pnpm exec zile publish:prepare
pnpm changeset publish --no-git-tag --snapshot $snapshot --tag $snapshot
+ pnpm exec zile publish:post
diff --git a/.gitignore b/.gitignore
index 6d88c5b3..1468886a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
dist
coverage
node_modules
+tasks
tsconfig.*.tsbuildinfo
tsconfig.tsbuildinfo
tsdoc.d.tson
From bad595c72073c36136de929df951194f148667ce Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:04:17 +1000
Subject: [PATCH 008/192] fix(mnemonic): return Bytes by default from
toPrivateKey to match declared type
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a57e8955ff21
---
.../wave-0-address-keys-mnemonic-default.md | 5 ++
src/core/Mnemonic.ts | 6 +--
src/core/_test/Mnemonic.test.ts | 49 ++++++++++++++++++-
3 files changed, 55 insertions(+), 5 deletions(-)
create mode 100644 .changeset/wave-0-address-keys-mnemonic-default.md
diff --git a/.changeset/wave-0-address-keys-mnemonic-default.md b/.changeset/wave-0-address-keys-mnemonic-default.md
new file mode 100644
index 00000000..c515bb0a
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Mnemonic.ts b/src/core/Mnemonic.ts
index 90240664..7d9ca1ce 100644
--- a/src/core/Mnemonic.ts
+++ b/src/core/Mnemonic.ts
@@ -138,10 +138,10 @@ export function toPrivateKey(
mnemonic: string,
options: toPrivateKey.Options = {},
): toPrivateKey.ReturnType {
- const { path = HdKey.path(), passphrase } = options
+ const { as = 'Bytes', path = HdKey.path(), passphrase } = options
const hdKey = toHdKey(mnemonic, { passphrase }).derive(path)
- if (options.as === 'Bytes') return Bytes.from(hdKey.privateKey) as never
- return hdKey.privateKey as never
+ if (as === 'Hex') return hdKey.privateKey as never
+ return Bytes.from(hdKey.privateKey) as never
}
export declare namespace toPrivateKey {
diff --git a/src/core/_test/Mnemonic.test.ts b/src/core/_test/Mnemonic.test.ts
index 8c2354a6..2ce658f1 100644
--- a/src/core/_test/Mnemonic.test.ts
+++ b/src/core/_test/Mnemonic.test.ts
@@ -47,11 +47,46 @@ describe('toPrivateKey', () => {
'test test test test test test test test test test test junk',
)
expect(privateKey).toMatchInlineSnapshot(
- `"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"`,
+ `
+ Uint8Array [
+ 172,
+ 9,
+ 116,
+ 190,
+ 195,
+ 154,
+ 23,
+ 227,
+ 107,
+ 164,
+ 166,
+ 180,
+ 210,
+ 56,
+ 255,
+ 148,
+ 75,
+ 172,
+ 180,
+ 120,
+ 203,
+ 237,
+ 94,
+ 252,
+ 174,
+ 120,
+ 77,
+ 123,
+ 244,
+ 242,
+ 255,
+ 128,
+ ]
+ `,
)
})
- test('options: as: bytes', () => {
+ test('options: as: Bytes', () => {
const privateKey = Mnemonic.toPrivateKey(
'test test test test test test test test test test test junk',
{ as: 'Bytes' },
@@ -95,6 +130,16 @@ describe('toPrivateKey', () => {
`,
)
})
+
+ test('options: as: Hex', () => {
+ const privateKey = Mnemonic.toPrivateKey(
+ 'test test test test test test test test test test test junk',
+ { as: 'Hex' },
+ )
+ expect(privateKey).toMatchInlineSnapshot(
+ `"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"`,
+ )
+ })
})
describe('toSeed', () => {
From 8c0ea670fafe21eee761a38e3bd2a7bf177a8a64 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:04:46 +1000
Subject: [PATCH 009/192] fix(keystore): use pbkdf2Async in toKeyAsync to avoid
blocking the main thread
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a57e8955ff21
---
.changeset/wave-0-address-keys-keystore-async-pbkdf2.md | 5 +++++
src/core/Keystore.ts | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
create mode 100644 .changeset/wave-0-address-keys-keystore-async-pbkdf2.md
diff --git a/.changeset/wave-0-address-keys-keystore-async-pbkdf2.md b/.changeset/wave-0-address-keys-keystore-async-pbkdf2.md
new file mode 100644
index 00000000..941ee210
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Keystore.ts b/src/core/Keystore.ts
index f419e4d6..7ceb9a4c 100644
--- a/src/core/Keystore.ts
+++ b/src/core/Keystore.ts
@@ -500,7 +500,7 @@ export async function toKeyAsync(
password,
})
case 'pbkdf2':
- return await pbkdf2({
+ return await pbkdf2Async({
iv: Bytes.from(`0x${iv}`),
iterations: c,
password,
From bc094642239a6098d54f5938661c1a53876b9ff7 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:06:21 +1000
Subject: [PATCH 010/192] fix(tempo): make PoolId.from order-independent
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b992045f9165
---
.changeset/wave-0-tempo-poolid-canonical.md | 5 +++++
src/tempo/PoolId.test.ts | 25 +++++++++++++++++++++
src/tempo/PoolId.ts | 8 +++----
3 files changed, 34 insertions(+), 4 deletions(-)
create mode 100644 .changeset/wave-0-tempo-poolid-canonical.md
diff --git a/.changeset/wave-0-tempo-poolid-canonical.md b/.changeset/wave-0-tempo-poolid-canonical.md
new file mode 100644
index 00000000..196462c2
--- /dev/null
+++ b/.changeset/wave-0-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/src/tempo/PoolId.test.ts b/src/tempo/PoolId.test.ts
index 4297dbe0..9cc8b769 100644
--- a/src/tempo/PoolId.test.ts
+++ b/src/tempo/PoolId.test.ts
@@ -40,3 +40,28 @@ test('from', () => {
})
expect(poolId5).toBe(poolId1)
})
+
+test('order-independent', () => {
+ const poolId1 = PoolId.from({
+ userToken: 0n,
+ validatorToken: 1n,
+ })
+ const poolId2 = PoolId.from({
+ userToken: 1n,
+ validatorToken: 0n,
+ })
+ expect(poolId2).toBe(poolId1)
+
+ const poolId3 = PoolId.from({
+ userToken: '0x20c0000000000000000000000000000000000001',
+ validatorToken: '0x20c0000000000000000000000000000000000000',
+ })
+ expect(poolId3).toBe(poolId1)
+
+ // Mixed inputs (token id + address) in swapped order.
+ const poolId4 = PoolId.from({
+ userToken: '0x20c0000000000000000000000000000000000001',
+ validatorToken: 0n,
+ })
+ expect(poolId4).toBe(poolId1)
+})
diff --git a/src/tempo/PoolId.ts b/src/tempo/PoolId.ts
index fad3b58a..5ffdbb16 100644
--- a/src/tempo/PoolId.ts
+++ b/src/tempo/PoolId.ts
@@ -25,11 +25,11 @@ import * as TokenId from './TokenId.js'
* @returns The pool ID.
*/
export function from(value: from.Value): Hex.Hex {
+ const a = TokenId.toAddress(value.userToken)
+ const b = TokenId.toAddress(value.validatorToken)
+ const [left, right] = a.toLowerCase() < b.toLowerCase() ? [a, b] : [b, a]
return Hash.keccak256(
- Hex.concat(
- Hex.padLeft(TokenId.toAddress(value.userToken), 32),
- Hex.padLeft(TokenId.toAddress(value.validatorToken), 32),
- ),
+ Hex.concat(Hex.padLeft(left, 32), Hex.padLeft(right, 32)),
)
}
From 2b048142abdc081052ac4cc5f129ae72475eadb9 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:07:23 +1000
Subject: [PATCH 011/192] fix(tempo): generate 192-bit nonceKey when 'random'
is requested
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b992045f9165
---
.changeset/wave-0-tempo-noncekey-random.md | 5 +++++
src/tempo/TransactionRequest.test.ts | 15 +++++++++++++++
src/tempo/TransactionRequest.ts | 2 +-
3 files changed, 21 insertions(+), 1 deletion(-)
create mode 100644 .changeset/wave-0-tempo-noncekey-random.md
diff --git a/.changeset/wave-0-tempo-noncekey-random.md b/.changeset/wave-0-tempo-noncekey-random.md
new file mode 100644
index 00000000..face65ef
--- /dev/null
+++ b/.changeset/wave-0-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/src/tempo/TransactionRequest.test.ts b/src/tempo/TransactionRequest.test.ts
index 6002127c..07d31966 100644
--- a/src/tempo/TransactionRequest.test.ts
+++ b/src/tempo/TransactionRequest.test.ts
@@ -122,6 +122,21 @@ describe('toRpc', () => {
}
`)
})
+
+ test("behavior: nonceKey 'random' generates a 192-bit value", () => {
+ const request = TransactionRequest.toRpc({
+ calls: [
+ {
+ data: '0xdeadbeef',
+ to: '0xcafebabecafebabecafebabecafebabecafebabe',
+ },
+ ],
+ feeToken: '0x20c0000000000000000000000000000000000000',
+ nonceKey: 'random',
+ })
+ // 24 bytes = 48 hex chars + '0x' prefix.
+ expect(request.nonceKey).toMatch(/^0x[0-9a-f]{48}$/)
+ })
})
describe('roundtrip', () => {
diff --git a/src/tempo/TransactionRequest.ts b/src/tempo/TransactionRequest.ts
index eefbbfb1..ffa54a0a 100644
--- a/src/tempo/TransactionRequest.ts
+++ b/src/tempo/TransactionRequest.ts
@@ -210,7 +210,7 @@ export function toRpc(request: TransactionRequest): Rpc {
request_rpc.validAfter = Hex.fromNumber(request.validAfter)
const nonceKey = (() => {
- if (request.nonceKey === 'random') return Hex.random(6)
+ if (request.nonceKey === 'random') return Hex.random(24)
if (typeof request.nonceKey === 'bigint')
return Hex.fromNumber(request.nonceKey)
return undefined
From b38dbd408c3c6185b1b78b4b7cf60df5b439e4a2 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:09:01 +1000
Subject: [PATCH 012/192] fix(keystore): honor caller-provided p and r in
scryptAsync
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a57e8955ff21
---
...0-address-keys-keystore-scrypt-async-pr.md | 5 ++
src/core/Keystore.ts | 5 +-
src/core/_test/Keystore.test.ts | 37 +++++++++++++-
src/erc4337/UserOperation.ts | 11 ++++-
src/erc4337/UserOperationGas.ts | 7 +++
src/erc6492/SignatureErc6492.ts | 36 ++++++++++++--
src/erc7821/Execute.ts | 31 ++++++------
src/erc8010/SignatureErc8010.ts | 49 ++++++++++++++++---
8 files changed, 145 insertions(+), 36 deletions(-)
create mode 100644 .changeset/wave-0-address-keys-keystore-scrypt-async-pr.md
diff --git a/.changeset/wave-0-address-keys-keystore-scrypt-async-pr.md b/.changeset/wave-0-address-keys-keystore-scrypt-async-pr.md
new file mode 100644
index 00000000..df6e6720
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Keystore.ts b/src/core/Keystore.ts
index 7ceb9a4c..b1dce77b 100644
--- a/src/core/Keystore.ts
+++ b/src/core/Keystore.ts
@@ -367,10 +367,7 @@ export declare namespace scrypt {
* @returns Scrypt key.
*/
export async function scryptAsync(options: scrypt.Options) {
- const { iv, n = 262_144, password } = options
-
- const p = 8
- const r = 1
+ const { iv, n = 262_144, password, p = 8, r = 1 } = options
const salt = options.salt ? Bytes.from(options.salt) : Bytes.random(32)
const key = Bytes.toHex(
diff --git a/src/core/_test/Keystore.test.ts b/src/core/_test/Keystore.test.ts
index 50f64b50..210c37cd 100644
--- a/src/core/_test/Keystore.test.ts
+++ b/src/core/_test/Keystore.test.ts
@@ -480,7 +480,42 @@ describe.skip('scrypt', () => {
})
})
-describe.skip('scryptAsync', () => {
+describe('scryptAsync', () => {
+ test('behavior: respects p and r options', async () => {
+ const [, opts] = await Keystore.scryptAsync({
+ salt: '0xab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19',
+ password: 'testpassword',
+ n: 1024,
+ p: 1,
+ r: 8,
+ })
+ expect(opts.kdfparams.p).toBe(1)
+ expect(opts.kdfparams.r).toBe(8)
+ expect(opts.kdfparams.n).toBe(1024)
+ })
+
+ test('behavior: matches sync scrypt for identical params', async () => {
+ const [keySync] = Keystore.scrypt({
+ iv: '0x83dbcc02d8ccb40e466191a123791e0e',
+ salt: '0xab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19',
+ password: 'testpassword',
+ n: 1024,
+ p: 2,
+ r: 4,
+ })
+ const [keyAsync] = await Keystore.scryptAsync({
+ iv: '0x83dbcc02d8ccb40e466191a123791e0e',
+ salt: '0xab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19',
+ password: 'testpassword',
+ n: 1024,
+ p: 2,
+ r: 4,
+ })
+ expect(keyAsync()).toEqual(keySync())
+ })
+})
+
+describe.skip('scryptAsync legacy snapshot', () => {
test('default', async () => {
const [key, opts] = await Keystore.scryptAsync({
salt: '0xab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19',
diff --git a/src/erc4337/UserOperation.ts b/src/erc4337/UserOperation.ts
index 2da71604..813ee519 100644
--- a/src/erc4337/UserOperation.ts
+++ b/src/erc4337/UserOperation.ts
@@ -1,6 +1,6 @@
import * as AbiParameters from '../core/AbiParameters.js'
import type * as Address from '../core/Address.js'
-import type * as Authorization from '../core/Authorization.js'
+import * as Authorization from '../core/Authorization.js'
import type * as Errors from '../core/Errors.js'
import * as Hash from '../core/Hash.js'
import * as Hex from '../core/Hex.js'
@@ -718,7 +718,7 @@ export declare namespace toPacked {
* @param packed - The packed user operation to transform.
* @returns The structured user operation.
*/
-export function fromPacked(packed: Packed): UserOperation<'0.7' | '0.8', true> {
+export function fromPacked(packed: Packed): UserOperation<'0.7', true> {
const {
accountGasLimits,
callData,
@@ -857,6 +857,13 @@ export function toRpc(userOperation: UserOperation): Rpc {
)
if (userOperation.signature) rpc.signature = userOperation.signature
+ const authorization = (userOperation as UserOperation<'0.8', true>)
+ .authorization
+ if (authorization)
+ (rpc as Rpc<'0.8'>).authorization = Authorization.toRpc(
+ authorization as Authorization.Signed,
+ ) as Rpc<'0.8'>['authorization']
+
return rpc
}
diff --git a/src/erc4337/UserOperationGas.ts b/src/erc4337/UserOperationGas.ts
index b20211b2..806598f3 100644
--- a/src/erc4337/UserOperationGas.ts
+++ b/src/erc4337/UserOperationGas.ts
@@ -9,6 +9,7 @@ export type UserOperationGas<
> = OneOf<
| (entryPointVersion extends '0.6' ? V06 : never)
| (entryPointVersion extends '0.7' ? V07 : never)
+ | (entryPointVersion extends '0.8' ? V08 : never)
>
/** RPC User Operation Gas on EntryPoint 0.6 */
@@ -38,6 +39,12 @@ export type V07 = {
/** RPC User Operation Gas on EntryPoint 0.7 */
export type RpcV07 = V07
+/** Type for User Operation Gas on EntryPoint 0.8 */
+export type V08 = V07
+
+/** RPC User Operation Gas on EntryPoint 0.8 */
+export type RpcV08 = V08
+
/**
* Converts an {@link ox#UserOperationGas.Rpc} to an {@link ox#UserOperationGas.UserOperationGas}.
*
diff --git a/src/erc6492/SignatureErc6492.ts b/src/erc6492/SignatureErc6492.ts
index 230ae268..d87bf3fd 100644
--- a/src/erc6492/SignatureErc6492.ts
+++ b/src/erc6492/SignatureErc6492.ts
@@ -91,16 +91,29 @@ export const universalSignatureValidatorAbi = [
* // @error: InvalidWrappedSignatureError: Value `0xdeadbeef` is an invalid ERC-6492 wrapped signature.
* ```
*
- * @param wrapped - The wrapped signature to assert.
+ * @param value - The value to assert.
*/
-export function assert(wrapped: Wrapped) {
- if (Hex.slice(wrapped, -32) !== magicBytes)
- throw new InvalidWrappedSignatureError(wrapped)
+export function assert(value: Unwrapped | Wrapped) {
+ if (typeof value === 'string') {
+ if (Hex.slice(value, -32) !== magicBytes)
+ throw new InvalidWrappedSignatureError(value)
+ return
+ }
+ if (value === null || typeof value !== 'object')
+ throw new InvalidUnwrappedSignatureError(value as never)
+ const { data, signature, to } = value as Unwrapped
+ if (
+ typeof to !== 'string' ||
+ typeof data !== 'string' ||
+ typeof signature !== 'string'
+ )
+ throw new InvalidUnwrappedSignatureError(value as Unwrapped)
}
export declare namespace assert {
type ErrorType =
| InvalidWrappedSignatureError
+ | InvalidUnwrappedSignatureError
| Hex.slice.ErrorType
| Errors.GlobalErrorType
}
@@ -137,6 +150,7 @@ export declare namespace assert {
*/
export function from(wrapped: Unwrapped | Wrapped): Unwrapped {
if (typeof wrapped === 'string') return unwrap(wrapped)
+ assert(wrapped)
return wrapped
}
@@ -166,9 +180,10 @@ export declare namespace from {
export function unwrap(wrapped: Wrapped): Unwrapped {
assert(wrapped)
+ const body = Hex.slice(wrapped, 0, -32)
const [to, data, signature] = AbiParameters.decode(
AbiParameters.from('address, bytes, bytes'),
- wrapped,
+ body,
)
return { data, signature, to }
@@ -261,3 +276,14 @@ export class InvalidWrappedSignatureError extends Errors.BaseError {
super(`Value \`${wrapped}\` is an invalid ERC-6492 wrapped signature.`)
}
}
+
+/** Thrown when an ERC-6492 unwrapped signature object is malformed. */
+export class InvalidUnwrappedSignatureError extends Errors.BaseError {
+ override readonly name = 'SignatureErc6492.InvalidUnwrappedSignatureError'
+
+ constructor(value: Unwrapped) {
+ super(
+ `Value \`${JSON.stringify(value)}\` is an invalid ERC-6492 unwrapped signature.`,
+ )
+ }
+}
diff --git a/src/erc7821/Execute.ts b/src/erc7821/Execute.ts
index defd12be..89ab624b 100644
--- a/src/erc7821/Execute.ts
+++ b/src/erc7821/Execute.ts
@@ -1,5 +1,5 @@
import * as AbiFunction from '../core/AbiFunction.js'
-import type * as Hex from '../core/Hex.js'
+import * as Hex from '../core/Hex.js'
import { AbiParameters } from '../index.js'
import * as Calls from './Calls.js'
@@ -91,22 +91,19 @@ export function decodeBatchOfBatchesData(
) as readonly [Hex.Hex[]]
return encodedBatches.map((encodedBatch) => {
- // Try decoding with opData first
- try {
- const decoded = Calls.decode(encodedBatch, { opData: true })
- if (decoded.opData) {
- return {
- calls: decoded.calls,
- opData: decoded.opData,
- }
- }
- // If opData is undefined, return without it
- return { calls: decoded.calls }
- } catch {
- // If decoding with opData fails, decode without it
- const decoded = Calls.decode(encodedBatch, { opData: false })
- return { calls: decoded.calls }
- }
+ // Structurally detect whether the batch was encoded with opData by
+ // inspecting the first ABI head word (the offset to the first dynamic
+ // param). For a single dynamic param tuple `(Call[] calls)` the head
+ // is one word, so the offset is 0x20. For a two dynamic param tuple
+ // `(Call[] calls, bytes opData)` the head is two words, so the offset
+ // is 0x40.
+ const firstHead = Hex.toBigInt(Hex.slice(encodedBatch, 0, 32))
+ const withOpData = firstHead === 64n
+
+ const decoded = Calls.decode(encodedBatch, { opData: withOpData })
+ if (withOpData && decoded.opData)
+ return { calls: decoded.calls, opData: decoded.opData }
+ return { calls: decoded.calls }
})
}
diff --git a/src/erc8010/SignatureErc8010.ts b/src/erc8010/SignatureErc8010.ts
index d20f3c9f..4a23593d 100644
--- a/src/erc8010/SignatureErc8010.ts
+++ b/src/erc8010/SignatureErc8010.ts
@@ -49,12 +49,26 @@ export function assert(value: Unwrapped | Wrapped) {
if (typeof value === 'string') {
if (Hex.slice(value, -32) !== magicBytes)
throw new InvalidWrappedSignatureError(value)
- } else Signature.assert(value.authorization)
+ return
+ }
+ if (value === null || typeof value !== 'object')
+ throw new InvalidUnwrappedSignatureError(value as never)
+ const { authorization, data, signature, to } = value as Unwrapped
+ if (typeof signature !== 'string')
+ throw new InvalidUnwrappedSignatureError(value as Unwrapped)
+ if (data !== undefined && typeof data !== 'string')
+ throw new InvalidUnwrappedSignatureError(value as Unwrapped)
+ if (to !== undefined && typeof to !== 'string')
+ throw new InvalidUnwrappedSignatureError(value as Unwrapped)
+ if (authorization === null || typeof authorization !== 'object')
+ throw new InvalidUnwrappedSignatureError(value as Unwrapped)
+ Signature.assert(authorization)
}
export declare namespace assert {
type ErrorType =
| InvalidWrappedSignatureError
+ | InvalidUnwrappedSignatureError
| Hex.slice.ErrorType
| Errors.GlobalErrorType
}
@@ -91,6 +105,7 @@ export declare namespace assert {
*/
export function from(value: Unwrapped | Wrapped): Unwrapped {
if (typeof value === 'string') return unwrap(value)
+ assert(value)
return value
}
@@ -114,7 +129,12 @@ export declare namespace from {
export function unwrap(wrapped: Wrapped): Unwrapped {
assert(wrapped)
- const suffixLength = Hex.toNumber(Hex.slice(wrapped, -64, -32))
+ const suffixLengthBig = Hex.toBigInt(Hex.slice(wrapped, -64, -32))
+ const wrappedSize = Hex.size(wrapped)
+ // Suffix + length word + magic bytes must fit inside the wrapped value.
+ if (suffixLengthBig < 0n || suffixLengthBig > BigInt(wrappedSize - 64))
+ throw new InvalidWrappedSignatureError(wrapped)
+ const suffixLength = Number(suffixLengthBig)
const suffix = Hex.slice(wrapped, -suffixLength - 64, -64)
const signature = Hex.slice(wrapped, 0, -suffixLength - 64)
@@ -169,10 +189,12 @@ export function wrap(value: Unwrapped): Wrapped {
assert(value)
- const self = Secp256k1.recoverAddress({
- payload: Authorization.getSignPayload(value.authorization),
- signature: Signature.from(value.authorization),
- })
+ const to =
+ value.to ??
+ Secp256k1.recoverAddress({
+ payload: Authorization.getSignPayload(value.authorization),
+ signature: Signature.from(value.authorization),
+ })
const suffix = AbiParameters.encode(suffixParameters, [
{
@@ -180,7 +202,7 @@ export function wrap(value: Unwrapped): Wrapped {
delegation: value.authorization.address,
chainId: BigInt(value.authorization.chainId),
},
- value.to ?? self,
+ to,
data ?? '0x',
])
const suffixLength = Hex.fromNumber(Hex.size(suffix), { size: 32 })
@@ -226,3 +248,16 @@ export class InvalidWrappedSignatureError extends Errors.BaseError {
super(`Value \`${wrapped}\` is an invalid ERC-8010 wrapped signature.`)
}
}
+
+/** Thrown when an ERC-8010 unwrapped signature object is malformed. */
+export class InvalidUnwrappedSignatureError extends Errors.BaseError {
+ override readonly name = 'SignatureErc8010.InvalidUnwrappedSignatureError'
+
+ constructor(value: Unwrapped) {
+ super(
+ `Value \`${JSON.stringify(value, (_, v) =>
+ typeof v === 'bigint' ? v.toString() : v,
+ )}\` is an invalid ERC-8010 unwrapped signature.`,
+ )
+ }
+}
From c624edeaecb5af4f75777b652d4a08f1c9dbd8eb Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:09:50 +1000
Subject: [PATCH 013/192] fix(abi): honor anonymous flag in AbiEvent
encode/decode
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-9d2614e4f981
---
.changeset/wave-0-abi-anonymous-events.md | 5 ++++
src/core/AbiEvent.ts | 30 ++++++++++++++---------
src/core/_test/AbiEvent.test.ts | 27 ++++++++++++++++++++
3 files changed, 51 insertions(+), 11 deletions(-)
create mode 100644 .changeset/wave-0-abi-anonymous-events.md
diff --git a/.changeset/wave-0-abi-anonymous-events.md b/.changeset/wave-0-abi-anonymous-events.md
new file mode 100644
index 00000000..48851f39
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/AbiEvent.ts b/src/core/AbiEvent.ts
index 54389d9a..d4457ec4 100644
--- a/src/core/AbiEvent.ts
+++ b/src/core/AbiEvent.ts
@@ -365,15 +365,19 @@ export function decode(
const { data, topics } = log
- const [selector_, ...argTopics] = topics
+ const isAnonymous = abiEvent.anonymous === true
+ const argTopics = isAnonymous ? [...topics] : topics.slice(1)
- const selector = getSelector(abiEvent)
- if (selector_ !== selector)
- throw new SelectorTopicMismatchError({
- abiEvent,
- actual: selector_,
- expected: selector,
- })
+ if (!isAnonymous) {
+ const selector_ = topics[0]
+ const selector = getSelector(abiEvent)
+ if (selector_ !== selector)
+ throw new SelectorTopicMismatchError({
+ abiEvent,
+ actual: selector_,
+ expected: selector,
+ })
+ }
const { inputs } = abiEvent
const isUnnamed = inputs?.every((x) => !('name' in x && x.name))
@@ -680,6 +684,8 @@ export function encode(
}
}
+ if (abiEvent.anonymous === true) return { topics }
+
const selector = (() => {
if (abiEvent.hash) return abiEvent.hash
return getSelector(abiEvent)
@@ -705,9 +711,11 @@ export declare namespace encode {
: [readonly unknown[] | Record] | []
type ReturnType = {
- topics: Compute<
- [selector: Hex.Hex, ...(Hex.Hex | readonly Hex.Hex[] | null)[]]
- >
+ topics:
+ | Compute<
+ [selector: Hex.Hex, ...(Hex.Hex | readonly Hex.Hex[] | null)[]]
+ >
+ | readonly (Hex.Hex | readonly Hex.Hex[] | null)[]
}
type ErrorType =
diff --git a/src/core/_test/AbiEvent.test.ts b/src/core/_test/AbiEvent.test.ts
index 23cb9248..4d1ee94f 100644
--- a/src/core/_test/AbiEvent.test.ts
+++ b/src/core/_test/AbiEvent.test.ts
@@ -537,6 +537,33 @@ describe('decode', () => {
}
`)
})
+
+ test('behavior: anonymous event', () => {
+ const abiEvent = AbiEvent.from({
+ type: 'event',
+ name: 'Transfer',
+ anonymous: true,
+ inputs: [
+ { name: 'from', type: 'address', indexed: true },
+ { name: 'to', type: 'address', indexed: true },
+ { name: 'value', type: 'uint256', indexed: false },
+ ],
+ })
+ const decoded = AbiEvent.decode(abiEvent, {
+ data: '0x0000000000000000000000000000000000000000000000000000000000000001',
+ topics: [
+ '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ac',
+ '0x000000000000000000000000a5cc3c03994db5b0d9a5eedd10cabab0813678ad',
+ ],
+ })
+ expect(decoded).toMatchInlineSnapshot(`
+ {
+ "from": "0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac",
+ "to": "0xa5cc3c03994db5b0d9a5eedd10cabab0813678ad",
+ "value": 1n,
+ }
+ `)
+ })
})
describe('encode', () => {
From f8d4595c0c8bcafd919b17b1af0b0e22f1e42e90 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:10:26 +1000
Subject: [PATCH 014/192] fix(crypto): pad WebCryptoP256.verify r/s to 32 bytes
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-99b84f570f29
---
...-anchor-crypto-webcrypto-verify-padding.md | 5 +++
src/core/Provider.ts | 25 ++++++---------
src/core/RpcResponse.ts | 26 ++++++++++++----
src/core/RpcTransport.ts | 31 ++++++++++++++++---
src/core/WebCryptoP256.ts | 5 ++-
src/core/_test/WebCryptoP256.test.ts | 17 ++++++++++
src/core/internal/promise.ts | 7 +++--
7 files changed, 87 insertions(+), 29 deletions(-)
create mode 100644 .changeset/wave-0-anchor-crypto-webcrypto-verify-padding.md
diff --git a/.changeset/wave-0-anchor-crypto-webcrypto-verify-padding.md b/.changeset/wave-0-anchor-crypto-webcrypto-verify-padding.md
new file mode 100644
index 00000000..323ec6ab
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Provider.ts b/src/core/Provider.ts
index 2786b819..fe43fedb 100644
--- a/src/core/Provider.ts
+++ b/src/core/Provider.ts
@@ -480,23 +480,16 @@ export function from<
// eslint-disable-next-line jsdoc/require-jsdoc
export function from(provider: any, _options: Options = {}): Provider {
if (!provider) throw new IsUndefinedError()
- return {
- ...provider,
- async request(args) {
- try {
- const result = await provider.request(args)
- if (
- result &&
- typeof result === 'object' &&
- 'jsonrpc' in (result as { jsonrpc?: unknown })
- )
- return RpcResponse.parse(result) as never
- return result
- } catch (error) {
- throw parseError(error)
- }
- },
+ const wrapped = Object.create(Object.getPrototypeOf(provider))
+ Object.defineProperties(wrapped, Object.getOwnPropertyDescriptors(provider))
+ wrapped.request = async (args: any) => {
+ try {
+ return await provider.request(args)
+ } catch (error) {
+ throw parseError(error)
+ }
}
+ return wrapped
}
export declare namespace from {
diff --git a/src/core/RpcResponse.ts b/src/core/RpcResponse.ts
index d6529bf1..a8050a62 100644
--- a/src/core/RpcResponse.ts
+++ b/src/core/RpcResponse.ts
@@ -76,11 +76,15 @@ export function from<
// eslint-disable-next-line jsdoc/require-jsdoc
export function from(response: RpcResponse, options: any = {}): RpcResponse {
const { request } = options
- return {
- ...response,
- id: response.id ?? request?.id,
- jsonrpc: response.jsonrpc ?? request.jsonrpc,
- }
+ if (request)
+ return {
+ ...response,
+ id: response.id ?? request.id,
+ jsonrpc: response.jsonrpc ?? request.jsonrpc,
+ }
+ if (response.id === undefined || response.jsonrpc === undefined)
+ throw new ParseError({ message: 'Invalid JSON-RPC response.' })
+ return response
}
export declare namespace from {
@@ -214,7 +218,15 @@ export function parse<
raw
> {
const { raw = false } = options
- const response_ = response as RpcResponse
+ const response_ = response as RpcResponse | null | undefined
+ if (
+ !response_ ||
+ typeof response_ !== 'object' ||
+ response_.jsonrpc !== '2.0' ||
+ response_.id === undefined ||
+ (!('result' in response_) && !('error' in response_))
+ )
+ throw new ParseError({ message: 'Invalid JSON-RPC response.' })
if (raw) return response as never
if (response_.error) throw parseError(response_.error)
return response_.result as never
@@ -285,6 +297,8 @@ export function parseError(
): parseError.ReturnType {
const error_ = error as Error | ErrorObject
+ if (error_ instanceof BaseError) return error_ as never
+
if (error_ instanceof Error && !('code' in error_))
return new InternalError({
cause: error_,
diff --git a/src/core/RpcTransport.ts b/src/core/RpcTransport.ts
index 1af1ad3b..8b751ba2 100644
--- a/src/core/RpcTransport.ts
+++ b/src/core/RpcTransport.ts
@@ -97,6 +97,17 @@ export function fromHttp<
const response = await promise.withTimeout(
({ signal }) => {
+ const externalSignal = fetchOptions?.signal
+ const timeoutSignal = timeout > 0 ? signal : null
+ const signals = [externalSignal, timeoutSignal].filter(
+ (s): s is AbortSignal => Boolean(s),
+ )
+ const composedSignal =
+ signals.length === 0
+ ? null
+ : signals.length === 1
+ ? signals[0]!
+ : AbortSignal.any(signals)
const init: RequestInit = {
...fetchOptions,
body,
@@ -105,7 +116,7 @@ export function fromHttp<
...fetchOptions?.headers,
},
method: fetchOptions?.method ?? 'POST',
- signal: fetchOptions?.signal ?? (timeout > 0 ? signal : null),
+ signal: composedSignal,
}
const request = new Request(url, init)
return fetchFn(request)
@@ -122,8 +133,13 @@ export function fromHttp<
)
return response.json()
return response.text().then((data) => {
+ if (data === '') {
+ if (response.ok)
+ throw new MalformedResponseError({ response: data })
+ return { error: undefined }
+ }
try {
- return JSON.parse(data || '{}')
+ return JSON.parse(data)
} catch (_err) {
if (response.ok)
throw new MalformedResponseError({
@@ -134,13 +150,20 @@ export function fromHttp<
})
})()
- if (!response.ok)
+ if (!response.ok) {
+ const error = (data as { error?: unknown })?.error
throw new HttpError({
body,
- details: JSON.stringify(data.error) ?? response.statusText,
+ details:
+ typeof error === 'string'
+ ? error
+ : error
+ ? JSON.stringify(error)
+ : response.statusText,
response,
url,
})
+ }
return data as never
},
diff --git a/src/core/WebCryptoP256.ts b/src/core/WebCryptoP256.ts
index 10dd4670..c193ecd9 100644
--- a/src/core/WebCryptoP256.ts
+++ b/src/core/WebCryptoP256.ts
@@ -305,7 +305,10 @@ export async function verify(options: verify.Options): Promise {
hash: 'SHA-256',
},
publicKey,
- Bytes.concat(Bytes.fromNumber(signature.r), Bytes.fromNumber(signature.s)),
+ Bytes.concat(
+ Bytes.fromNumber(signature.r, { size: 32 }),
+ Bytes.fromNumber(signature.s, { size: 32 }),
+ ),
Bytes.from(payload),
)
}
diff --git a/src/core/_test/WebCryptoP256.test.ts b/src/core/_test/WebCryptoP256.test.ts
index ddd84042..638d1267 100644
--- a/src/core/_test/WebCryptoP256.test.ts
+++ b/src/core/_test/WebCryptoP256.test.ts
@@ -192,6 +192,23 @@ describe('verify', () => {
await WebCryptoP256.verify({ publicKey, payload, signature: { r, s } }),
).toBe(true)
})
+
+ test('behavior: signature with leading-zero r/s is verified', async () => {
+ // Sign repeatedly until we hit a signature whose r or s value has its
+ // most-significant byte equal to zero. With variable-width number
+ // encoding such signatures fail to verify; with fixed-width 32-byte
+ // encoding (the regression fix) they verify correctly.
+ const payload = '0xdeadbeef'
+ for (let i = 0; i < 256; i++) {
+ const signature = await WebCryptoP256.sign({ payload, privateKey })
+ if (signature.r >> 248n === 0n || signature.s >> 248n === 0n) {
+ expect(
+ await WebCryptoP256.verify({ publicKey, payload, signature }),
+ ).toBe(true)
+ return
+ }
+ }
+ })
})
test('exports', () => {
diff --git a/src/core/internal/promise.ts b/src/core/internal/promise.ts
index 79598c37..2592a490 100644
--- a/src/core/internal/promise.ts
+++ b/src/core/internal/promise.ts
@@ -9,10 +9,12 @@ export function withTimeout(
return new Promise((resolve, reject) => {
;(async () => {
let timeoutId: any
+ let timedOut = false
try {
const controller = new AbortController()
if (timeout > 0)
timeoutId = setTimeout(() => {
+ timedOut = true
if (signal) {
controller.abort()
} else {
@@ -21,8 +23,9 @@ export function withTimeout(
}, timeout) as any
resolve(await fn({ signal: controller.signal }))
} catch (err) {
- if ((err as Error)?.name === 'AbortError') reject(errorInstance)
- reject(err)
+ if (timedOut || (err as Error)?.name === 'AbortError')
+ reject(errorInstance)
+ else reject(err)
} finally {
clearTimeout(timeoutId)
}
From 2b32e0ca27c5a1fc77d6f158a82ed2fc1112b97d Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:10:47 +1000
Subject: [PATCH 015/192] fix(tempo): normalize AuthorizationTempo.from
signature option through SignatureEnvelope.from
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b992045f9165
---
.changeset/wave-0-tempo-authorization-signature-normalize.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/wave-0-tempo-authorization-signature-normalize.md
diff --git a/.changeset/wave-0-tempo-authorization-signature-normalize.md b/.changeset/wave-0-tempo-authorization-signature-normalize.md
new file mode 100644
index 00000000..a0539a7c
--- /dev/null
+++ b/.changeset/wave-0-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.
From 51c0cc807f495718295751cb70e1667e90665e70 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:11:20 +1000
Subject: [PATCH 016/192] fix(publickey): reject malformed shape when
compressed option is set
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-99b84f570f29
---
.../wave-0-abi-constructor-bytecode-prefix.md | 5 +++
.../wave-0-anchor-publickey-assert-shape.md | 5 +++
src/core/PublicKey.ts | 36 ++++++++++++----
src/core/_test/PublicKey.test.ts | 42 +++++++++++++++++++
4 files changed, 80 insertions(+), 8 deletions(-)
create mode 100644 .changeset/wave-0-abi-constructor-bytecode-prefix.md
create mode 100644 .changeset/wave-0-anchor-publickey-assert-shape.md
diff --git a/.changeset/wave-0-abi-constructor-bytecode-prefix.md b/.changeset/wave-0-abi-constructor-bytecode-prefix.md
new file mode 100644
index 00000000..981f24bc
--- /dev/null
+++ b/.changeset/wave-0-abi-constructor-bytecode-prefix.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Fixed `AbiConstructor.decode` to assert that `data` begins with the provided `bytecode` and throw a new `BytecodeMismatchError` instead of silently returning garbage when the prefix does not match.
diff --git a/.changeset/wave-0-anchor-publickey-assert-shape.md b/.changeset/wave-0-anchor-publickey-assert-shape.md
new file mode 100644
index 00000000..bf938b56
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/PublicKey.ts b/src/core/PublicKey.ts
index 4f315683..d829f252 100644
--- a/src/core/PublicKey.ts
+++ b/src/core/PublicKey.ts
@@ -49,11 +49,34 @@ export function assert(
const { compressed } = options
const { prefix, x, y } = publicKey
+ // Explicit `compressed: false` -- require uncompressed shape.
+ if (compressed === false) {
+ if (typeof x !== 'bigint' || typeof y !== 'bigint')
+ throw new InvalidError({ publicKey })
+ if (prefix !== 4)
+ throw new InvalidPrefixError({
+ prefix,
+ cause: new InvalidUncompressedPrefixError(),
+ })
+ return
+ }
+
+ // Explicit `compressed: true` -- require compressed shape.
+ if (compressed === true) {
+ if (typeof x !== 'bigint' || typeof y !== 'undefined')
+ throw new InvalidError({ publicKey })
+ if (prefix !== 3 && prefix !== 2)
+ throw new InvalidPrefixError({
+ prefix,
+ cause: new InvalidCompressedPrefixError(),
+ })
+ return
+ }
+
+ // No explicit `compressed` option -- infer from shape.
+
// Uncompressed
- if (
- compressed === false ||
- (typeof x === 'bigint' && typeof y === 'bigint')
- ) {
+ if (typeof x === 'bigint' && typeof y === 'bigint') {
if (prefix !== 4)
throw new InvalidPrefixError({
prefix,
@@ -63,10 +86,7 @@ export function assert(
}
// Compressed
- if (
- compressed === true ||
- (typeof x === 'bigint' && typeof y === 'undefined')
- ) {
+ if (typeof x === 'bigint' && typeof y === 'undefined') {
if (prefix !== 3 && prefix !== 2)
throw new InvalidPrefixError({
prefix,
diff --git a/src/core/_test/PublicKey.test.ts b/src/core/_test/PublicKey.test.ts
index cf0756f7..bdb85864 100644
--- a/src/core/_test/PublicKey.test.ts
+++ b/src/core/_test/PublicKey.test.ts
@@ -83,6 +83,48 @@ describe('PublicKey.assert', () => {
`,
)
})
+
+ test('behavior: rejects missing x/y when compressed: false is set', () => {
+ expect(() =>
+ PublicKey.assert({ prefix: 4 }, { compressed: false }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [PublicKey.InvalidError: Value \`{"prefix":4}\` is not a valid public key.
+
+ Public key must contain:
+ - an \`x\` and \`prefix\` value (compressed)
+ - an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
+ `)
+ expect(() =>
+ PublicKey.assert({ prefix: 4, x: 1n }, { compressed: false }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [PublicKey.InvalidError: Value \`{"prefix":4,"x":"1#__bigint"}\` is not a valid public key.
+
+ Public key must contain:
+ - an \`x\` and \`prefix\` value (compressed)
+ - an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
+ `)
+ })
+
+ test('behavior: rejects missing x or extra y when compressed: true is set', () => {
+ expect(() =>
+ PublicKey.assert({ prefix: 2 }, { compressed: true }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [PublicKey.InvalidError: Value \`{"prefix":2}\` is not a valid public key.
+
+ Public key must contain:
+ - an \`x\` and \`prefix\` value (compressed)
+ - an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
+ `)
+ expect(() =>
+ PublicKey.assert({ prefix: 2, x: 1n, y: 1n }, { compressed: true }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [PublicKey.InvalidError: Value \`{"prefix":2,"x":"1#__bigint","y":"1#__bigint"}\` is not a valid public key.
+
+ Public key must contain:
+ - an \`x\` and \`prefix\` value (compressed)
+ - an \`x\`, \`y\`, and \`prefix\` value (uncompressed)]
+ `)
+ })
})
describe('PublicKey.compress', () => {
From 08dae9a52fbc21e14d5ba8c83a0748417c0d2fe8 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:12:06 +1000
Subject: [PATCH 017/192] fix(tempo): apply AuthorizationTempo.from signature
normalization
Implementation for the changeset added in 2b32e0c (the source change was lost in a concurrent stash on the previous commit).
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b992045f9165
---
src/core/AbiConstructor.ts | 33 ++++++++++++++++++++++++++-
src/core/_test/AbiConstructor.test.ts | 14 ++++++++++++
2 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/src/core/AbiConstructor.ts b/src/core/AbiConstructor.ts
index 697913e8..468ba849 100644
--- a/src/core/AbiConstructor.ts
+++ b/src/core/AbiConstructor.ts
@@ -91,7 +91,12 @@ export function decode(
const { bytecode } = options
if (abiConstructor.inputs?.length === 0) return undefined
- const data = options.data.replace(bytecode, '0x') as Hex.Hex
+ if (!options.data.startsWith(bytecode))
+ throw new BytecodeMismatchError({
+ bytecode,
+ data: options.data,
+ })
+ const data = ('0x' + options.data.slice(bytecode.length)) as Hex.Hex
return AbiParameters.decode(abiConstructor.inputs, data)
}
@@ -475,3 +480,29 @@ export declare namespace fromAbi {
type ErrorType = AbiItem.NotFoundError | Errors.GlobalErrorType
}
+
+/**
+ * Throws when the provided `data` does not begin with the provided `bytecode`.
+ *
+ * @example
+ * ```ts twoslash
+ * import { AbiConstructor } from 'ox'
+ *
+ * AbiConstructor.decode(
+ * AbiConstructor.from('constructor(address)'),
+ * { bytecode: '0x6080...', data: '0xdeadbeef' },
+ * )
+ * // @error: AbiConstructor.BytecodeMismatchError: Provided `data` does not start with the provided `bytecode`.
+ * ```
+ */
+export class BytecodeMismatchError extends Errors.BaseError {
+ override readonly name = 'AbiConstructor.BytecodeMismatchError'
+ constructor({ bytecode, data }: { bytecode: Hex.Hex; data: Hex.Hex }) {
+ super('Provided `data` does not start with the provided `bytecode`.', {
+ metaMessages: [
+ `Bytecode: ${bytecode.slice(0, 18)}${bytecode.length > 18 ? '...' : ''}`,
+ `Data: ${data.slice(0, 18)}${data.length > 18 ? '...' : ''}`,
+ ],
+ })
+ }
+}
diff --git a/src/core/_test/AbiConstructor.test.ts b/src/core/_test/AbiConstructor.test.ts
index 17b9f019..8167813f 100644
--- a/src/core/_test/AbiConstructor.test.ts
+++ b/src/core/_test/AbiConstructor.test.ts
@@ -120,6 +120,20 @@ describe('decode', () => {
]
`)
})
+
+ test('error: bytecode does not match data prefix', () => {
+ const abiConstructor = AbiConstructor.from(
+ 'constructor(address, uint256)',
+ )
+ expect(() =>
+ AbiConstructor.decode(abiConstructor, {
+ bytecode: '0x6080604052deadbeef',
+ data: '0xcafebabe000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000007b',
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(
+ `[AbiConstructor.BytecodeMismatchError: Provided \`data\` does not start with the provided \`bytecode\`.]`,
+ )
+ })
})
describe('encode', () => {
From f05efd24a9f3b8146fa77e013e2f4561eb63a179 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:12:37 +1000
Subject: [PATCH 018/192] fix(publickey): validate SEC1 prefix in
fromHex/fromBytes
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-99b84f570f29
---
...ave-0-anchor-publickey-fromhex-validate.md | 5 ++
src/core/PublicKey.ts | 51 +++++++++++--------
src/core/_test/PublicKey.test.ts | 38 ++++++++++++++
3 files changed, 73 insertions(+), 21 deletions(-)
create mode 100644 .changeset/wave-0-anchor-publickey-fromhex-validate.md
diff --git a/.changeset/wave-0-anchor-publickey-fromhex-validate.md b/.changeset/wave-0-anchor-publickey-fromhex-validate.md
new file mode 100644
index 00000000..3eb2393a
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/PublicKey.ts b/src/core/PublicKey.ts
index d829f252..2ae7b39f 100644
--- a/src/core/PublicKey.ts
+++ b/src/core/PublicKey.ts
@@ -302,37 +302,46 @@ export function fromHex(publicKey: Hex.Hex): PublicKey {
)
throw new InvalidSerializedSizeError({ publicKey })
- if (publicKey.length === 130) {
- const x = BigInt(Hex.slice(publicKey, 0, 32))
- const y = BigInt(Hex.slice(publicKey, 32, 64))
- return {
- prefix: 4,
- x,
- y,
- } as never
- }
+ const result = (() => {
+ if (publicKey.length === 130) {
+ const x = BigInt(Hex.slice(publicKey, 0, 32))
+ const y = BigInt(Hex.slice(publicKey, 32, 64))
+ return {
+ prefix: 4,
+ x,
+ y,
+ }
+ }
+
+ if (publicKey.length === 132) {
+ const prefix = Number(Hex.slice(publicKey, 0, 1))
+ const x = BigInt(Hex.slice(publicKey, 1, 33))
+ const y = BigInt(Hex.slice(publicKey, 33, 65))
+ return {
+ prefix,
+ x,
+ y,
+ }
+ }
- if (publicKey.length === 132) {
const prefix = Number(Hex.slice(publicKey, 0, 1))
const x = BigInt(Hex.slice(publicKey, 1, 33))
- const y = BigInt(Hex.slice(publicKey, 33, 65))
return {
prefix,
x,
- y,
- } as never
- }
+ }
+ })()
- const prefix = Number(Hex.slice(publicKey, 0, 1))
- const x = BigInt(Hex.slice(publicKey, 1, 33))
- return {
- prefix,
- x,
- } as never
+ assert(result)
+ return result as never
}
export declare namespace fromHex {
- type ErrorType = Hex.slice.ErrorType | Errors.GlobalErrorType
+ type ErrorType =
+ | assert.ErrorType
+ | Hex.slice.ErrorType
+ | InvalidSerializedSizeError
+ | Errors.GlobalErrorType
}
/**
diff --git a/src/core/_test/PublicKey.test.ts b/src/core/_test/PublicKey.test.ts
index bdb85864..2b5f1c9e 100644
--- a/src/core/_test/PublicKey.test.ts
+++ b/src/core/_test/PublicKey.test.ts
@@ -210,6 +210,32 @@ describe('PublicKey.fromHex', () => {
Received 63 bytes.]
`)
})
+
+ test('error: invalid uncompressed prefix', () => {
+ // 65-byte serialized with prefix 5 (invalid for uncompressed).
+ expect(() =>
+ PublicKey.fromHex(
+ '0x058318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
+ ),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [PublicKey.InvalidPrefixError: Prefix "5" is invalid.
+
+ Details: Prefix must be 4 for uncompressed public keys.]
+ `)
+ })
+
+ test('error: invalid compressed prefix', () => {
+ // 33-byte serialized with prefix 5 (invalid for compressed).
+ expect(() =>
+ PublicKey.fromHex(
+ '0x058318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75',
+ ),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [PublicKey.InvalidPrefixError: Prefix "5" is invalid.
+
+ Details: Prefix must be 2 or 3 for compressed public keys.]
+ `)
+ })
})
describe('PublicKey.fromBytes', () => {
@@ -226,6 +252,18 @@ describe('PublicKey.fromBytes', () => {
}
`)
})
+
+ test('error: invalid prefix', () => {
+ const serialized = Bytes.fromHex(
+ '0x058318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
+ )
+ expect(() => PublicKey.fromBytes(serialized))
+ .toThrowErrorMatchingInlineSnapshot(`
+ [PublicKey.InvalidPrefixError: Prefix "5" is invalid.
+
+ Details: Prefix must be 4 for uncompressed public keys.]
+ `)
+ })
})
describe('PublicKey.from', () => {
From feb35d968086bc788a11087bbf066bc4f4168ba2 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:12:40 +1000
Subject: [PATCH 019/192] fix(value): validate decimals and use string-carry
rounding in from()
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b2649a371d7f
---
.../wave-0-block-state-value-validation.md | 5 ++
src/core/Value.ts | 90 +++++++++++++++----
src/core/_test/Value.test.ts | 59 ++++++++++++
3 files changed, 136 insertions(+), 18 deletions(-)
create mode 100644 .changeset/wave-0-block-state-value-validation.md
diff --git a/.changeset/wave-0-block-state-value-validation.md b/.changeset/wave-0-block-state-value-validation.md
new file mode 100644
index 00000000..d4c0a052
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Value.ts b/src/core/Value.ts
index 048c3e6c..a16b9547 100644
--- a/src/core/Value.ts
+++ b/src/core/Value.ts
@@ -25,6 +25,9 @@ export const exponents = {
* @returns The string representation of the Value.
*/
export function format(value: bigint, decimals = 0) {
+ if (!Number.isInteger(decimals) || decimals < 0)
+ throw new InvalidDecimalsError({ decimals })
+
let display = value.toString()
const negative = display.startsWith('-')
@@ -111,40 +114,51 @@ export declare namespace formatGwei {
* @returns The `bigint` representation of the Value.
*/
export function from(value: string, decimals = 0) {
- if (!/^(-?)([0-9]*)\.?([0-9]*)$/.test(value))
+ if (!Number.isInteger(decimals) || decimals < 0)
+ throw new InvalidDecimalsError({ decimals })
+
+ // Require at least one digit overall. Rejects '', '.', '-', '-.' which
+ // the previous regex accepted (and which then either produced garbage or
+ // threw a raw `SyntaxError` from `BigInt('')`).
+ if (!/^-?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)$/.test(value))
throw new InvalidDecimalNumberError({ value })
let [integer = '', fraction = '0'] = value.split('.')
const negative = integer.startsWith('-')
if (negative) integer = integer.slice(1)
+ if (integer === '') integer = '0'
// trim trailing zeros.
fraction = fraction.replace(/(0+)$/, '')
// round off if the fraction is larger than the number of decimals.
if (decimals === 0) {
- if (Math.round(Number(`.${fraction}`)) === 1)
+ // Round half-away-from-zero by inspecting the first fractional digit.
+ if (fraction.length > 0 && Number.parseInt(fraction[0]!, 10) >= 5)
integer = `${BigInt(integer) + 1n}`
fraction = ''
} else if (fraction.length > decimals) {
- const [left, unit, right] = [
- fraction.slice(0, decimals - 1),
- fraction.slice(decimals - 1, decimals),
- fraction.slice(decimals),
- ]
-
- const rounded = Math.round(Number(`${unit}.${right}`))
- if (rounded > 9)
- fraction = `${BigInt(left) + BigInt(1)}0`.padStart(left.length + 1, '0')
- else fraction = `${left}${rounded}`
-
- if (fraction.length > decimals) {
- fraction = fraction.slice(1)
- integer = `${BigInt(integer) + 1n}`
- }
+ const left = fraction.slice(0, decimals)
+ const roundDigit = Number.parseInt(
+ fraction.slice(decimals, decimals + 1)!,
+ 10,
+ )
- fraction = fraction.slice(0, decimals)
+ if (roundDigit >= 5) {
+ // Carry through the truncated fraction digits into the integer part
+ // without converting to a JS Number (avoids float precision loss).
+ const carried = carry(left)
+ if (carried.length > decimals) {
+ // Carry overflowed into the integer part.
+ fraction = carried.slice(1)
+ integer = `${BigInt(integer) + 1n}`
+ } else {
+ fraction = carried
+ }
+ } else {
+ fraction = left
+ }
} else {
fraction = fraction.padEnd(decimals, '0')
}
@@ -152,6 +166,28 @@ export function from(value: string, decimals = 0) {
return BigInt(`${negative ? '-' : ''}${integer}${fraction}`)
}
+/**
+ * Adds 1 to a digit string with carry, returning a string of the same length
+ * unless the carry overflows past the most-significant digit (in which case
+ * the returned string is one digit longer).
+ *
+ * @internal
+ */
+function carry(digits: string): string {
+ const out = digits.split('')
+ let i = out.length - 1
+ while (i >= 0) {
+ const d = Number.parseInt(out[i]!, 10) + 1
+ if (d < 10) {
+ out[i] = String(d)
+ return out.join('')
+ }
+ out[i] = '0'
+ i--
+ }
+ return `1${out.join('')}`
+}
+
export declare namespace from {
type ErrorType = Errors.GlobalErrorType
}
@@ -222,3 +258,21 @@ export class InvalidDecimalNumberError extends Errors.BaseError {
super(`Value \`${value}\` is not a valid decimal number.`)
}
}
+
+/**
+ * Thrown when the `decimals` argument is not a non-negative integer.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Value } from 'ox'
+ *
+ * Value.from('1', -1)
+ * // @error: Value.InvalidDecimalsError: `decimals` must be a non-negative integer. Got `-1`.
+ * ```
+ */
+export class InvalidDecimalsError extends Errors.BaseError {
+ override readonly name = 'Value.InvalidDecimalsError'
+ constructor({ decimals }: { decimals: number }) {
+ super(`\`decimals\` must be a non-negative integer. Got \`${decimals}\`.`)
+ }
+}
diff --git a/src/core/_test/Value.test.ts b/src/core/_test/Value.test.ts
index 45e7cad5..df71114e 100644
--- a/src/core/_test/Value.test.ts
+++ b/src/core/_test/Value.test.ts
@@ -418,6 +418,64 @@ describe('from', () => {
'[Value.InvalidDecimalNumberError: Value `0o50` is not a valid decimal number.]',
)
})
+
+ test('error: requires at least one digit', () => {
+ expect(() => Value.from('', 0)).toThrowErrorMatchingInlineSnapshot(
+ '[Value.InvalidDecimalNumberError: Value `` is not a valid decimal number.]',
+ )
+ expect(() => Value.from('.', 0)).toThrowErrorMatchingInlineSnapshot(
+ '[Value.InvalidDecimalNumberError: Value `.` is not a valid decimal number.]',
+ )
+ expect(() => Value.from('-', 0)).toThrowErrorMatchingInlineSnapshot(
+ '[Value.InvalidDecimalNumberError: Value `-` is not a valid decimal number.]',
+ )
+ expect(() => Value.from('-.', 0)).toThrowErrorMatchingInlineSnapshot(
+ '[Value.InvalidDecimalNumberError: Value `-.` is not a valid decimal number.]',
+ )
+ })
+
+ test('behavior: leading-decimal numbers', () => {
+ expect(Value.from('.5', 0)).toMatchInlineSnapshot('1n')
+ expect(Value.from('.5', 1)).toMatchInlineSnapshot('5n')
+ expect(Value.from('-.5', 1)).toMatchInlineSnapshot('-5n')
+ })
+
+ test('error: invalid decimals', () => {
+ expect(() => Value.from('1', -1)).toThrowErrorMatchingInlineSnapshot(
+ '[Value.InvalidDecimalsError: `decimals` must be a non-negative integer. Got `-1`.]',
+ )
+ expect(() => Value.from('1', 1.5)).toThrowErrorMatchingInlineSnapshot(
+ '[Value.InvalidDecimalsError: `decimals` must be a non-negative integer. Got `1.5`.]',
+ )
+ expect(() =>
+ Value.from('1', Number.NaN),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[Value.InvalidDecimalsError: `decimals` must be a non-negative integer. Got `NaN`.]',
+ )
+ })
+
+ test('behavior: precise rounding for long fractions', () => {
+ // The carry-based rounding path uses no float arithmetic, so very long
+ // fractions round at the boundary digit without precision loss.
+ expect(
+ Value.from(
+ '1.000000000000000005000000000000000000000000000000000000000000000000000001',
+ 18,
+ ),
+ ).toMatchInlineSnapshot('1000000000000000005n')
+ expect(
+ Value.from(
+ '1.000000000000000004999999999999999999999999999999999999999999999999999999',
+ 18,
+ ),
+ ).toMatchInlineSnapshot('1000000000000000005n')
+ expect(
+ Value.from(
+ '1.000000000000000004499999999999999999999999999999999999999999999999999999',
+ 18,
+ ),
+ ).toMatchInlineSnapshot('1000000000000000004n')
+ })
})
describe('fromEther', () => {
@@ -651,6 +709,7 @@ test('exports', () => {
"fromEther",
"fromGwei",
"InvalidDecimalNumberError",
+ "InvalidDecimalsError",
]
`)
})
From 8b50bd31017d18c61d2159f244c69f80113a2bd5 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:13:11 +1000
Subject: [PATCH 020/192] fix(abi): assert AbiConstructor.decode bytecode
prefix
---
src/core/AbiConstructor.ts | 2 +-
src/core/_test/AbiConstructor.test.ts | 4 +---
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/core/AbiConstructor.ts b/src/core/AbiConstructor.ts
index 468ba849..f62acf7f 100644
--- a/src/core/AbiConstructor.ts
+++ b/src/core/AbiConstructor.ts
@@ -2,7 +2,7 @@ import * as abitype from 'abitype'
import type * as Abi from './Abi.js'
import * as AbiItem from './AbiItem.js'
import * as AbiParameters from './AbiParameters.js'
-import type * as Errors from './Errors.js'
+import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import type * as internal from './internal/abiConstructor.js'
import type { IsNarrowable } from './internal/types.js'
diff --git a/src/core/_test/AbiConstructor.test.ts b/src/core/_test/AbiConstructor.test.ts
index 8167813f..b226fe93 100644
--- a/src/core/_test/AbiConstructor.test.ts
+++ b/src/core/_test/AbiConstructor.test.ts
@@ -122,9 +122,7 @@ describe('decode', () => {
})
test('error: bytecode does not match data prefix', () => {
- const abiConstructor = AbiConstructor.from(
- 'constructor(address, uint256)',
- )
+ const abiConstructor = AbiConstructor.from('constructor(address, uint256)')
expect(() =>
AbiConstructor.decode(abiConstructor, {
bytecode: '0x6080604052deadbeef',
From 14af5bc59f3a63dfd588f80a2ed3498bcf984375 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:13:36 +1000
Subject: [PATCH 021/192] fix(bls): validate input shape in Bls.aggregate
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-99b84f570f29
---
.../wave-0-crypto-bls-aggregate-validate.md | 5 ++
src/core/Base32.ts | 9 +++
src/core/Base58.ts | 2 +-
src/core/Base64.ts | 62 +++++++++++++++++--
src/core/Bls.ts | 22 ++++++-
src/core/CompactSize.ts | 42 +++++++++++--
src/core/Hex.ts | 12 +++-
src/core/Json.ts | 25 ++++++--
src/core/_test/Bls.test.ts | 24 +++++++
9 files changed, 182 insertions(+), 21 deletions(-)
create mode 100644 .changeset/wave-0-crypto-bls-aggregate-validate.md
diff --git a/.changeset/wave-0-crypto-bls-aggregate-validate.md b/.changeset/wave-0-crypto-bls-aggregate-validate.md
new file mode 100644
index 00000000..e96f12b3
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Base32.ts b/src/core/Base32.ts
index 4c3778b9..de8e9857 100644
--- a/src/core/Base32.ts
+++ b/src/core/Base32.ts
@@ -132,3 +132,12 @@ export class InvalidCharacterError extends Errors.BaseError {
super(`Invalid bech32 base32 character: "${character}".`)
}
}
+
+/** Thrown when a Base32 string contains non-canonical (non-zero) trailing bits. */
+export class InvalidPaddingError extends Errors.BaseError {
+ override readonly name = 'Base32.InvalidPaddingError'
+
+ constructor() {
+ super('Non-canonical trailing bits in Base32 input.')
+ }
+}
diff --git a/src/core/Base58.ts b/src/core/Base58.ts
index 34a07226..171bd01f 100644
--- a/src/core/Base58.ts
+++ b/src/core/Base58.ts
@@ -1,5 +1,5 @@
import * as Bytes from './Bytes.js'
-import type * as Errors from './Errors.js'
+import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import * as internal from './internal/base58.js'
diff --git a/src/core/Base64.ts b/src/core/Base64.ts
index b7cbf95c..e3bf0980 100644
--- a/src/core/Base64.ts
+++ b/src/core/Base64.ts
@@ -1,5 +1,5 @@
import * as Bytes from './Bytes.js'
-import type * as Errors from './Errors.js'
+import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
const encoder = /*#__PURE__*/ new TextEncoder()
@@ -238,14 +238,33 @@ export declare namespace fromString {
* @returns The Base64 decoded {@link ox#Bytes.Bytes}.
*/
export function toBytes(value: string): Bytes.Bytes {
- const base64 = value.replace(/=+$/, '')
+ // Strip trailing '=' padding (only at the very end).
+ let body = value
+ let pad = 0
+ while (body.length > 0 && body.charCodeAt(body.length - 1) === 61 /* '=' */) {
+ body = body.slice(0, -1)
+ pad++
+ }
+
+ const size = body.length
+ // Reject impossible lengths and excessive padding.
+ if (size % 4 === 1) throw new InvalidLengthError({ length: value.length })
+ if (pad > 2) throw new InvalidPaddingError({ padding: pad })
- const size = base64.length
+ // Validate characters: every char must be in the standard or URL-safe alphabet,
+ // and '=' may not appear in the body (only stripped trailing padding).
+ for (let i = 0; i < size; i++) {
+ const code = body.charCodeAt(i)
+ if (code === 61 /* '=' */)
+ throw new InvalidCharacterError({ character: '=' })
+ if (characterToInteger[code] === undefined)
+ throw new InvalidCharacterError({ character: body[i]! })
+ }
const decoded = new Uint8Array(size + 3)
- encoder.encodeInto(base64 + '===', decoded)
+ encoder.encodeInto(body + '===', decoded)
- for (let i = 0, j = 0; i < base64.length; i += 4, j += 3) {
+ for (let i = 0, j = 0; i < size; i += 4, j += 3) {
const x =
(characterToInteger[decoded[i]!]! << 18) +
(characterToInteger[decoded[i + 1]!]! << 12) +
@@ -261,7 +280,11 @@ export function toBytes(value: string): Bytes.Bytes {
}
export declare namespace toBytes {
- type ErrorType = Errors.GlobalErrorType
+ type ErrorType =
+ | InvalidCharacterError
+ | InvalidLengthError
+ | InvalidPaddingError
+ | Errors.GlobalErrorType
}
/**
@@ -307,3 +330,30 @@ export function toString(value: string): string {
export declare namespace toString {
type ErrorType = toBytes.ErrorType | Errors.GlobalErrorType
}
+
+/** Thrown when a Base64 string contains an invalid character. */
+export class InvalidCharacterError extends Errors.BaseError {
+ override readonly name = 'Base64.InvalidCharacterError'
+
+ constructor({ character }: { character: string }) {
+ super(`Invalid Base64 character: "${character}".`)
+ }
+}
+
+/** Thrown when a Base64 string has an impossible length. */
+export class InvalidLengthError extends Errors.BaseError {
+ override readonly name = 'Base64.InvalidLengthError'
+
+ constructor({ length }: { length: number }) {
+ super(`Invalid Base64 input length \`${length}\`.`)
+ }
+}
+
+/** Thrown when a Base64 string contains too many trailing `=` padding characters. */
+export class InvalidPaddingError extends Errors.BaseError {
+ override readonly name = 'Base64.InvalidPaddingError'
+
+ constructor({ padding }: { padding: number }) {
+ super(`Invalid Base64 padding length \`${padding}\` (must be 0, 1, or 2).`)
+ }
+}
diff --git a/src/core/Bls.ts b/src/core/Bls.ts
index fd4af020..d9f63ad4 100644
--- a/src/core/Bls.ts
+++ b/src/core/Bls.ts
@@ -2,7 +2,7 @@ import { bls12_381 as bls } from '@noble/curves/bls12-381.js'
import type * as BlsPoint from './BlsPoint.js'
import * as Bytes from './Bytes.js'
-import type * as Errors from './Errors.js'
+import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import type { OneOf } from './internal/types.js'
@@ -52,7 +52,25 @@ export function aggregate(
export function aggregate(
points: readonly BlsPoint.BlsPoint[],
): BlsPoint.BlsPoint {
- const group = typeof points[0]?.x === 'bigint' ? bls.G1 : bls.G2
+ if (points.length === 0)
+ throw new Errors.BaseError(
+ 'Bls.aggregate expects a non-empty array of points.',
+ )
+
+ const first = points[0]!
+
+ // Fast path: a single point aggregates to itself.
+ if (points.length === 1) return first
+
+ const isG1 = typeof first.x === 'bigint'
+ for (let i = 1; i < points.length; i++) {
+ if ((typeof points[i]!.x === 'bigint') !== isG1)
+ throw new Errors.BaseError(
+ 'Bls.aggregate expects all points to be from the same group (G1 or G2).',
+ )
+ }
+
+ const group = isG1 ? bls.G1 : bls.G2
const point = points.reduce(
(acc, point) =>
acc.add(new (group as any).Point(point.x, point.y, point.z)),
diff --git a/src/core/CompactSize.ts b/src/core/CompactSize.ts
index dcf0d90d..d3832e8d 100644
--- a/src/core/CompactSize.ts
+++ b/src/core/CompactSize.ts
@@ -27,6 +27,8 @@ import * as Hex from './Hex.js'
* @returns The CompactSize-encoded bytes.
*/
export function toBytes(value: bigint | number): Bytes.Bytes {
+ if (typeof value === 'number' && !Number.isSafeInteger(value))
+ throw new InvalidValueError({ value })
const n = BigInt(value)
if (n < 0n) throw new NegativeValueError({ value: n })
if (n <= 252n) return new Uint8Array([Number(n)])
@@ -52,7 +54,10 @@ export function toBytes(value: bigint | number): Bytes.Bytes {
}
export declare namespace toBytes {
- type ErrorType = NegativeValueError | Errors.GlobalErrorType
+ type ErrorType =
+ | InvalidValueError
+ | NegativeValueError
+ | Errors.GlobalErrorType
}
/**
@@ -100,17 +105,23 @@ export function fromBytes(data: Bytes.Bytes): fromBytes.ReturnType {
if (first === 0xfd) {
if (data.length < 3)
throw new InsufficientBytesError({ expected: 3, actual: data.length })
- return { value: BigInt(view.getUint16(1, true)), size: 3 }
+ const value = view.getUint16(1, true)
+ if (value < 0xfd) throw new NonMinimalEncodingError()
+ return { value: BigInt(value), size: 3 }
}
if (first === 0xfe) {
if (data.length < 5)
throw new InsufficientBytesError({ expected: 5, actual: data.length })
- return { value: BigInt(view.getUint32(1, true)), size: 5 }
+ const value = view.getUint32(1, true)
+ if (value <= 0xffff) throw new NonMinimalEncodingError()
+ return { value: BigInt(value), size: 5 }
}
if (data.length < 9)
throw new InsufficientBytesError({ expected: 9, actual: data.length })
+ const value = view.getBigUint64(1, true)
+ if (value <= 0xffffffffn) throw new NonMinimalEncodingError()
return {
- value: view.getBigUint64(1, true),
+ value,
size: 9,
}
}
@@ -123,7 +134,10 @@ export declare namespace fromBytes {
size: number
}
- type ErrorType = InsufficientBytesError | Errors.GlobalErrorType
+ type ErrorType =
+ | InsufficientBytesError
+ | NonMinimalEncodingError
+ | Errors.GlobalErrorType
}
/**
@@ -167,3 +181,21 @@ export class InsufficientBytesError extends Errors.BaseError {
)
}
}
+
+/** Thrown when a CompactSize input is not a safe integer. */
+export class InvalidValueError extends Errors.BaseError {
+ override readonly name = 'CompactSize.InvalidValueError'
+
+ constructor({ value }: { value: number }) {
+ super(`CompactSize value \`${value}\` must be a safe integer or a bigint.`)
+ }
+}
+
+/** Thrown when a CompactSize value is encoded non-minimally. */
+export class NonMinimalEncodingError extends Errors.BaseError {
+ override readonly name = 'CompactSize.NonMinimalEncodingError'
+
+ constructor() {
+ super('CompactSize value is encoded non-minimally.')
+ }
+}
diff --git a/src/core/Hex.ts b/src/core/Hex.ts
index 23af4e63..a3323b5f 100644
--- a/src/core/Hex.ts
+++ b/src/core/Hex.ts
@@ -665,8 +665,16 @@ export declare namespace toBytes {
*/
export function toNumber(hex: Hex, options: toNumber.Options = {}): number {
const { signed, size } = options
- if (!signed && !size) return Number(hex)
- return Number(toBigInt(hex, options))
+ const value = !signed && !size ? Number(hex) : Number(toBigInt(hex, options))
+ if (!Number.isSafeInteger(value))
+ throw new IntegerOutOfRangeError({
+ max: `${Number.MAX_SAFE_INTEGER}`,
+ min: signed ? `${Number.MIN_SAFE_INTEGER}` : '0',
+ signed,
+ size,
+ value: `${value}`,
+ })
+ return value
}
export declare namespace toNumber {
diff --git a/src/core/Json.ts b/src/core/Json.ts
index 4749802b..7a976df0 100644
--- a/src/core/Json.ts
+++ b/src/core/Json.ts
@@ -30,6 +30,15 @@ const bigIntSuffix = '#__bigint'
* @returns The canonical JSON string.
*/
export function canonicalize(value: unknown): string {
+ const result = canonicalizeInner(value)
+ if (result === undefined)
+ throw new TypeError(
+ `Cannot canonicalize value of type \`${typeof value}\`.`,
+ )
+ return result
+}
+
+function canonicalizeInner(value: unknown): string | undefined {
if (value === null || typeof value === 'boolean' || typeof value === 'string')
return JSON.stringify(value)
if (typeof value === 'number') {
@@ -39,20 +48,26 @@ export function canonicalize(value: unknown): string {
}
if (typeof value === 'bigint')
throw new TypeError('Cannot canonicalize bigint')
- if (Array.isArray(value))
- return `[${value.map((item) => canonicalize(item)).join(',')}]`
+ if (Array.isArray(value)) {
+ const items = value.map((item) => {
+ const v = canonicalizeInner(item)
+ // Per JSON.stringify semantics, unsupported array slots become `null`.
+ return v === undefined ? 'null' : v
+ })
+ return `[${items.join(',')}]`
+ }
if (typeof value === 'object') {
const entries = Object.keys(value as Record)
.sort()
.reduce((acc, key) => {
const v = (value as Record)[key]
- if (v !== undefined)
- acc.push(`${JSON.stringify(key)}:${canonicalize(v)}`)
+ const inner = canonicalizeInner(v)
+ if (inner !== undefined) acc.push(`${JSON.stringify(key)}:${inner}`)
return acc
}, [])
return `{${entries.join(',')}}`
}
- return undefined as never
+ return undefined
}
export declare namespace canonicalize {
diff --git a/src/core/_test/Bls.test.ts b/src/core/_test/Bls.test.ts
index 84cc2578..be7d1a52 100644
--- a/src/core/_test/Bls.test.ts
+++ b/src/core/_test/Bls.test.ts
@@ -52,6 +52,30 @@ describe('aggregate', () => {
})
expect(valid).toBe(true)
})
+
+ test('error: empty array', () => {
+ expect(() => Bls.aggregate([])).toThrowErrorMatchingInlineSnapshot(
+ `[BaseError: Bls.aggregate expects a non-empty array of points.]`,
+ )
+ })
+
+ test('behavior: single-element array fast-returns the input', () => {
+ const publicKey = Bls.getPublicKey({ privateKey })
+ expect(Bls.aggregate([publicKey])).toBe(publicKey)
+ })
+
+ test('error: mixed groups', () => {
+ const g1 = Bls.getPublicKey({ privateKey })
+ const g2 = Bls.getPublicKey({
+ privateKey,
+ size: 'long-key:short-sig',
+ })
+ expect(() =>
+ Bls.aggregate([g1, g2 as any]),
+ ).toThrowErrorMatchingInlineSnapshot(
+ `[BaseError: Bls.aggregate expects all points to be from the same group (G1 or G2).]`,
+ )
+ })
})
describe('createKeyPair', () => {
From 1bd3e52cfe6a62b513b19a6c86cd7af45b82f5ea Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:14:00 +1000
Subject: [PATCH 022/192] fix(tempo): validate envelope-type prefix in
TxEnvelopeTempo.deserialize
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b992045f9165
---
.../wave-0-tempo-txenvelope-validate-prefix.md | 5 +++++
src/tempo/TxEnvelopeTempo.test.ts | 13 +++++++++++++
src/tempo/TxEnvelopeTempo.ts | 7 +++++++
3 files changed, 25 insertions(+)
create mode 100644 .changeset/wave-0-tempo-txenvelope-validate-prefix.md
diff --git a/.changeset/wave-0-tempo-txenvelope-validate-prefix.md b/.changeset/wave-0-tempo-txenvelope-validate-prefix.md
new file mode 100644
index 00000000..931dc1d1
--- /dev/null
+++ b/.changeset/wave-0-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/src/tempo/TxEnvelopeTempo.test.ts b/src/tempo/TxEnvelopeTempo.test.ts
index d78337f7..9b8fe01d 100644
--- a/src/tempo/TxEnvelopeTempo.test.ts
+++ b/src/tempo/TxEnvelopeTempo.test.ts
@@ -628,6 +628,19 @@ describe('deserialize', () => {
)
})
+ test('invalid transaction (wrong prefix byte)', () => {
+ // EIP-1559 prefix byte (0x02) instead of Tempo's 0x76.
+ expect(() =>
+ TxEnvelopeTempo.deserialize(
+ `0x02${Rlp.fromHex([]).slice(2)}` as TxEnvelopeTempo.Serialized,
+ ),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [TransactionEnvelope.InvalidSerializedError: Invalid serialized transaction of type "tempo" was provided.
+
+ Serialized Transaction: "0x02c0"]
+ `)
+ })
+
test('invalid transaction (too many fields with signature)', () => {
expect(() =>
TxEnvelopeTempo.deserialize(
diff --git a/src/tempo/TxEnvelopeTempo.ts b/src/tempo/TxEnvelopeTempo.ts
index 6312b110..22121ead 100644
--- a/src/tempo/TxEnvelopeTempo.ts
+++ b/src/tempo/TxEnvelopeTempo.ts
@@ -254,6 +254,13 @@ export declare namespace assert {
* @returns Deserialized Transaction Envelope.
*/
export function deserialize(serialized: Serialized): Compute {
+ if (Hex.slice(serialized, 0, 1) !== serializedType)
+ throw new TransactionEnvelope.InvalidSerializedError({
+ attributes: {},
+ serialized,
+ type,
+ })
+
const transactionArray = Rlp.toHex(Hex.slice(serialized, 1))
const [
From 302110c8040014af362959a168366333bb1aa568 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:14:07 +1000
Subject: [PATCH 023/192] fix(webauthn): decode clientDataJSON as UTF-8 in
Authentication.sign
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-bc30fc2dfd83
---
...ave-0-webauthn-authentication-sign-utf8.md | 5 ++
src/core/TransactionRequest.ts | 4 --
src/webauthn/Authentication.ts | 2 +-
src/webauthn/_test/Authentication.test.ts | 71 +++++++++++++++++++
4 files changed, 77 insertions(+), 5 deletions(-)
create mode 100644 .changeset/wave-0-webauthn-authentication-sign-utf8.md
diff --git a/.changeset/wave-0-webauthn-authentication-sign-utf8.md b/.changeset/wave-0-webauthn-authentication-sign-utf8.md
new file mode 100644
index 00000000..b022a409
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/TransactionRequest.ts b/src/core/TransactionRequest.ts
index 7705f64e..d390aa24 100644
--- a/src/core/TransactionRequest.ts
+++ b/src/core/TransactionRequest.ts
@@ -182,10 +182,6 @@ export function toRpc(request: TransactionRequest): Rpc {
request_rpc.maxPriorityFeePerGas = Hex.fromNumber(
request.maxPriorityFeePerGas,
)
- if (typeof request.maxPriorityFeePerGas !== 'undefined')
- request_rpc.maxPriorityFeePerGas = Hex.fromNumber(
- request.maxPriorityFeePerGas,
- )
if (typeof request.nonce !== 'undefined')
request_rpc.nonce = Hex.fromNumber(request.nonce)
if (typeof request.to !== 'undefined') request_rpc.to = request.to
diff --git a/src/webauthn/Authentication.ts b/src/webauthn/Authentication.ts
index 82af7562..c4792dbc 100644
--- a/src/webauthn/Authentication.ts
+++ b/src/webauthn/Authentication.ts
@@ -501,7 +501,7 @@ export async function sign(options: sign.Options): Promise {
const signatureBytes = new Uint8Array(response.signature)
const id = credential.id
- const clientDataJSON = String.fromCharCode(...clientDataJSONBytes)
+ const clientDataJSON = Bytes.toString(clientDataJSONBytes)
const challengeIndex = clientDataJSON.indexOf('"challenge"')
const typeIndex = clientDataJSON.indexOf('"type"')
diff --git a/src/webauthn/_test/Authentication.test.ts b/src/webauthn/_test/Authentication.test.ts
index a985cb74..600d5ade 100644
--- a/src/webauthn/_test/Authentication.test.ts
+++ b/src/webauthn/_test/Authentication.test.ts
@@ -1,4 +1,5 @@
import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'
+import * as Bytes from '../../core/Bytes.js'
import * as P256 from '../../core/P256.js'
import * as PublicKey from '../../core/PublicKey.js'
import * as Signature from '../../core/Signature.js'
@@ -824,6 +825,76 @@ describe('sign', () => {
`)
})
+ test('behavior: non-ASCII clientDataJSON decodes as UTF-8', async () => {
+ const clientDataJSON = `{"type":"webauthn.get","challenge":"9jEFijuhEWrM4SOW-tChJbUEHEP44VcjcJ-Bqo1fTM8","origin":"http://localhost:5173","crossOrigin":false,"note":"🚀 héllo"}`
+ const clientDataJSONBytes = Bytes.fromString(clientDataJSON)
+
+ const response = await Authentication.sign({
+ getFn() {
+ return Promise.resolve({
+ id: 'm1-bMPuAqpWhCxHZQZTT6e-lSPntQbh3opIoGe7g4Qs',
+ response: {
+ authenticatorData: new Uint8Array([
+ 73, 150, 13, 229, 136, 14, 140, 104, 116, 52, 23, 15, 100, 118,
+ 96, 91, 143, 228, 174, 185, 162, 134, 50, 199, 153, 92, 243, 186,
+ 131, 29, 151, 99, 5, 0, 0, 0, 0,
+ ]),
+ clientDataJSON: clientDataJSONBytes,
+ signature: new Uint8Array([
+ 48, 70, 2, 33, 0, 146, 61, 150, 57, 188, 182, 119, 250, 23, 162,
+ 103, 56, 232, 200, 162, 77, 88, 37, 145, 151, 40, 59, 42, 63, 46,
+ 225, 53, 221, 74, 128, 13, 165, 2, 33, 0, 128, 39, 38, 71, 180,
+ 153, 30, 232, 243, 94, 159, 66, 42, 246, 56, 195, 195, 139, 40,
+ 163, 26, 34, 125, 244, 171, 166, 7, 178, 169, 246, 142, 198,
+ ]),
+ },
+ } as any)
+ },
+ challenge:
+ '0xf631058a3ba1116acce12396fad0a125b5041c43f8e15723709f81aa8d5f4ccf',
+ })
+
+ expect(response.metadata.clientDataJSON).toBe(clientDataJSON)
+ expect(response.metadata.challengeIndex).toBe(
+ clientDataJSON.indexOf('"challenge"'),
+ )
+ expect(response.metadata.typeIndex).toBe(clientDataJSON.indexOf('"type"'))
+ })
+
+ test('behavior: large clientDataJSON does not throw', async () => {
+ const extra = 'x'.repeat(200_000)
+ const clientDataJSON = `{"type":"webauthn.get","challenge":"9jEFijuhEWrM4SOW-tChJbUEHEP44VcjcJ-Bqo1fTM8","origin":"http://localhost:5173","crossOrigin":false,"note":"${extra}"}`
+ const clientDataJSONBytes = Bytes.fromString(clientDataJSON)
+
+ const response = await Authentication.sign({
+ getFn() {
+ return Promise.resolve({
+ id: 'm1-bMPuAqpWhCxHZQZTT6e-lSPntQbh3opIoGe7g4Qs',
+ response: {
+ authenticatorData: new Uint8Array([
+ 73, 150, 13, 229, 136, 14, 140, 104, 116, 52, 23, 15, 100, 118,
+ 96, 91, 143, 228, 174, 185, 162, 134, 50, 199, 153, 92, 243, 186,
+ 131, 29, 151, 99, 5, 0, 0, 0, 0,
+ ]),
+ clientDataJSON: clientDataJSONBytes,
+ signature: new Uint8Array([
+ 48, 70, 2, 33, 0, 146, 61, 150, 57, 188, 182, 119, 250, 23, 162,
+ 103, 56, 232, 200, 162, 77, 88, 37, 145, 151, 40, 59, 42, 63, 46,
+ 225, 53, 221, 74, 128, 13, 165, 2, 33, 0, 128, 39, 38, 71, 180,
+ 153, 30, 232, 243, 94, 159, 66, 42, 246, 56, 195, 195, 139, 40,
+ 163, 26, 34, 125, 244, 171, 166, 7, 178, 169, 246, 142, 198,
+ ]),
+ },
+ } as any)
+ },
+ challenge:
+ '0xf631058a3ba1116acce12396fad0a125b5041c43f8e15723709f81aa8d5f4ccf',
+ })
+
+ expect(response.metadata.clientDataJSON).toBe(clientDataJSON)
+ expect(response.metadata.clientDataJSON.length).toBe(clientDataJSON.length)
+ })
+
test('error: null credential', async () => {
await expect(() =>
Authentication.sign({
From d00fdaf898b96606788c60dc8adf901b2eaf7809 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:14:10 +1000
Subject: [PATCH 024/192] fix(transactions): remove duplicate
maxPriorityFeePerGas assignment in TransactionRequest.toRpc
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a8a740d3ed8f
---
...ave-0-transactions-transaction-request-duplicate-field.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/wave-0-transactions-transaction-request-duplicate-field.md
diff --git a/.changeset/wave-0-transactions-transaction-request-duplicate-field.md b/.changeset/wave-0-transactions-transaction-request-duplicate-field.md
new file mode 100644
index 00000000..9e97ed46
--- /dev/null
+++ b/.changeset/wave-0-transactions-transaction-request-duplicate-field.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Removed duplicate `maxPriorityFeePerGas` assignment in `TransactionRequest.toRpc`.
From 9c6707dbd2954f8cdb18206b0371a9908945e9d3 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:14:13 +1000
Subject: [PATCH 025/192] fix(blspoint): honor group argument and assert byte
length in fromBytes
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-99b84f570f29
---
.../wave-0-crypto-blspoint-frombytes-group.md | 5 +++++
src/core/BlsPoint.ts | 16 +++++++++++----
src/core/_test/BlsPoint.test.ts | 20 +++++++++++++++++++
3 files changed, 37 insertions(+), 4 deletions(-)
create mode 100644 .changeset/wave-0-crypto-blspoint-frombytes-group.md
diff --git a/.changeset/wave-0-crypto-blspoint-frombytes-group.md b/.changeset/wave-0-crypto-blspoint-frombytes-group.md
new file mode 100644
index 00000000..4a709262
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/BlsPoint.ts b/src/core/BlsPoint.ts
index e3e549d4..909799a5 100644
--- a/src/core/BlsPoint.ts
+++ b/src/core/BlsPoint.ts
@@ -1,7 +1,7 @@
import { bls12_381 as bls } from '@noble/curves/bls12-381.js'
import type * as Bytes from './Bytes.js'
-import type * as Errors from './Errors.js'
+import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import type { Branded, Compute } from './internal/types.js'
@@ -149,9 +149,17 @@ export function fromBytes(
group: group,
): group extends 'G1' ? G1 : G2
// eslint-disable-next-line jsdoc/require-jsdoc
-export function fromBytes(bytes: Bytes.Bytes): BlsPoint {
- const group = bytes.length === 48 ? bls.G1 : bls.G2
- const point = group.Point.fromBytes(bytes)
+export function fromBytes(
+ bytes: Bytes.Bytes,
+ group: 'G1' | 'G2',
+): BlsPoint {
+ const expectedLength = group === 'G1' ? 48 : 96
+ if (bytes.length !== expectedLength)
+ throw new Errors.BaseError(
+ `Expected ${expectedLength} bytes for a ${group} point, received ${bytes.length}.`,
+ )
+ const Group = group === 'G1' ? bls.G1 : bls.G2
+ const point = Group.Point.fromBytes(bytes)
return {
x: point.X,
y: point.Y,
diff --git a/src/core/_test/BlsPoint.test.ts b/src/core/_test/BlsPoint.test.ts
index 01490146..8f189116 100644
--- a/src/core/_test/BlsPoint.test.ts
+++ b/src/core/_test/BlsPoint.test.ts
@@ -19,6 +19,26 @@ describe('fromBytes', () => {
const publicKeyHex = BlsPoint.toBytes(publicKey)
expect(BlsPoint.fromBytes(publicKeyHex, 'G2')).toEqual(publicKey)
})
+
+ test('error: wrong byte length for G1', () => {
+ const g2Bytes = BlsPoint.toBytes(
+ Bls.getPublicKey({ privateKey, size: 'long-key:short-sig' }),
+ )
+ expect(() =>
+ BlsPoint.fromBytes(g2Bytes, 'G1'),
+ ).toThrowErrorMatchingInlineSnapshot(
+ `[BaseError: Expected 48 bytes for a G1 point, received 96.]`,
+ )
+ })
+
+ test('error: wrong byte length for G2', () => {
+ const g1Bytes = BlsPoint.toBytes(Bls.getPublicKey({ privateKey }))
+ expect(() =>
+ BlsPoint.fromBytes(g1Bytes, 'G2'),
+ ).toThrowErrorMatchingInlineSnapshot(
+ `[BaseError: Expected 96 bytes for a G2 point, received 48.]`,
+ )
+ })
})
describe('fromHex', () => {
From 726d02f3d2eafa85ebefcf1e70628de00609cce0 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:14:36 +1000
Subject: [PATCH 026/192] fix(keystore): reject trivially weak PBKDF2 and
scrypt parameters
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a57e8955ff21
---
...-0-address-keys-keystore-kdf-validation.md | 5 +
...block-state-typed-data-array-validation.md | 5 +
src/core/TypedData.ts | 161 +++++++++++++-----
src/core/_test/TypedData.test.ts | 72 ++++++++
4 files changed, 201 insertions(+), 42 deletions(-)
create mode 100644 .changeset/wave-0-address-keys-keystore-kdf-validation.md
create mode 100644 .changeset/wave-0-block-state-typed-data-array-validation.md
diff --git a/.changeset/wave-0-address-keys-keystore-kdf-validation.md b/.changeset/wave-0-address-keys-keystore-kdf-validation.md
new file mode 100644
index 00000000..f519103f
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-block-state-typed-data-array-validation.md b/.changeset/wave-0-block-state-typed-data-array-validation.md
new file mode 100644
index 00000000..98f5afd9
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/TypedData.ts b/src/core/TypedData.ts
index 5862649a..df9a1ff8 100644
--- a/src/core/TypedData.ts
+++ b/src/core/TypedData.ts
@@ -106,53 +106,75 @@ export function assert<
const { domain, message, primaryType, types } =
value as unknown as assert.Value
+ const validateValue = (type: string, value: unknown, name: string) => {
+ // Array types: validate length (if fixed) and recurse into each element.
+ const arrayMatch = type.match(Solidity.arrayRegex)
+ if (arrayMatch) {
+ const [, elementType, lengthStr] = arrayMatch
+ if (!Array.isArray(value))
+ throw new InvalidArrayError({ name, type, value })
+ if (lengthStr) {
+ const expected = Number.parseInt(lengthStr, 10)
+ if (value.length !== expected)
+ throw new InvalidArrayLengthError({
+ name,
+ type,
+ expectedLength: expected,
+ givenLength: value.length,
+ })
+ }
+ for (const element of value) validateValue(elementType!, element, name)
+ return
+ }
+
+ const integerMatch = type.match(Solidity.integerRegex)
+ if (
+ integerMatch &&
+ (typeof value === 'number' || typeof value === 'bigint')
+ ) {
+ const [, base, size_] = integerMatch
+ // If number cannot be cast to a sized hex value, it is out of range
+ // and will throw.
+ Hex.fromNumber(value, {
+ signed: base === 'int',
+ size: Number.parseInt(size_ ?? '', 10) / 8,
+ })
+ }
+
+ if (
+ type === 'address' &&
+ typeof value === 'string' &&
+ !Address.validate(value)
+ )
+ throw new Address.InvalidAddressError({
+ address: value,
+ cause: new Address.InvalidInputError(),
+ })
+
+ const bytesMatch = type.match(Solidity.bytesRegex)
+ if (bytesMatch) {
+ const [, size] = bytesMatch
+ if (size && Hex.size(value as Hex.Hex) !== Number.parseInt(size, 10))
+ throw new BytesSizeMismatchError({
+ expectedSize: Number.parseInt(size, 10),
+ givenSize: Hex.size(value as Hex.Hex),
+ })
+ }
+
+ const struct = types[type]
+ if (struct) {
+ validateReference(type)
+ validateData(struct, value as Record)
+ }
+ }
+
const validateData = (
struct: readonly Parameter[],
data: Record,
) => {
for (const param of struct) {
const { name, type } = param
- const value = data[name]
-
- const integerMatch = type.match(Solidity.integerRegex)
- if (
- integerMatch &&
- (typeof value === 'number' || typeof value === 'bigint')
- ) {
- const [, base, size_] = integerMatch
- // If number cannot be cast to a sized hex value, it is out of range
- // and will throw.
- Hex.fromNumber(value, {
- signed: base === 'int',
- size: Number.parseInt(size_ ?? '', 10) / 8,
- })
- }
-
- if (
- type === 'address' &&
- typeof value === 'string' &&
- !Address.validate(value)
- )
- throw new Address.InvalidAddressError({
- address: value,
- cause: new Address.InvalidInputError(),
- })
-
- const bytesMatch = type.match(Solidity.bytesRegex)
- if (bytesMatch) {
- const [, size] = bytesMatch
- if (size && Hex.size(value as Hex.Hex) !== Number.parseInt(size, 10))
- throw new BytesSizeMismatchError({
- expectedSize: Number.parseInt(size, 10),
- givenSize: Hex.size(value as Hex.Hex),
- })
- }
-
- const struct = types[type]
- if (struct) {
- validateReference(type)
- validateData(struct, value as Record)
- }
+ validateValue(type, data[name], name)
}
}
@@ -178,6 +200,8 @@ export declare namespace assert {
type ErrorType =
| Address.InvalidAddressError
| BytesSizeMismatchError
+ | InvalidArrayError
+ | InvalidArrayLengthError
| InvalidPrimaryTypeError
| Hex.fromNumber.ErrorType
| Hex.size.ErrorType
@@ -757,6 +781,42 @@ export class InvalidStructTypeError extends Errors.BaseError {
}
}
+/** Thrown when an array-typed value is not an array. */
+export class InvalidArrayError extends Errors.BaseError {
+ override readonly name = 'TypedData.InvalidArrayError'
+
+ constructor({
+ name,
+ type,
+ value,
+ }: { name: string; type: string; value: unknown }) {
+ super(
+ `Value for field \`${name}\` of type \`${type}\` is not an array. Got \`${typeof value}\`.`,
+ )
+ }
+}
+
+/** Thrown when a fixed-length array does not match its declared length. */
+export class InvalidArrayLengthError extends Errors.BaseError {
+ override readonly name = 'TypedData.InvalidArrayLengthError'
+
+ constructor({
+ name,
+ type,
+ expectedLength,
+ givenLength,
+ }: {
+ name: string
+ type: string
+ expectedLength: number
+ givenLength: number
+ }) {
+ super(
+ `Expected fixed-length array \`${type}\` for field \`${name}\` to have ${expectedLength} elements, got ${givenLength}.`,
+ )
+ }
+}
+
/** @internal */
export function encodeData(value: {
data: Record
@@ -837,7 +897,22 @@ export function encodeField(properties: {
]
if (type.lastIndexOf(']') === type.length - 1) {
- const parsedType = type.slice(0, type.lastIndexOf('['))
+ const arrayMatch = type.match(Solidity.arrayRegex)
+ const parsedType = arrayMatch
+ ? arrayMatch[1]!
+ : type.slice(0, type.lastIndexOf('['))
+ const fixedLength = arrayMatch?.[2]
+ ? Number.parseInt(arrayMatch[2], 10)
+ : undefined
+ if (!Array.isArray(value))
+ throw new InvalidArrayError({ name, type, value })
+ if (fixedLength !== undefined && value.length !== fixedLength)
+ throw new InvalidArrayLengthError({
+ name,
+ type,
+ expectedLength: fixedLength,
+ givenLength: value.length,
+ })
const typeValuePairs = (value as [AbiParameters.Parameter, any][]).map(
(item) =>
encodeField({
@@ -867,6 +942,8 @@ export declare namespace encodeField {
| AbiParameters.encode.ErrorType
| Hash.keccak256.ErrorType
| Bytes.fromString.ErrorType
+ | InvalidArrayError
+ | InvalidArrayLengthError
| Errors.GlobalErrorType
}
diff --git a/src/core/_test/TypedData.test.ts b/src/core/_test/TypedData.test.ts
index 566e4d36..a08c1cd2 100644
--- a/src/core/_test/TypedData.test.ts
+++ b/src/core/_test/TypedData.test.ts
@@ -428,6 +428,76 @@ describe('assert', () => {
Struct type must not be a Solidity type.]
`)
})
+
+ test('fixed-array length mismatch', () => {
+ expect(() =>
+ TypedData.assert({
+ types: {
+ Foo: [{ name: 'addresses', type: 'address[2]' }],
+ },
+ primaryType: 'Foo',
+ message: {
+ addresses: ['0x0000000000000000000000000000000000000001'],
+ },
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[TypedData.InvalidArrayLengthError: Expected fixed-length array `address[2]` for field `addresses` to have 2 elements, got 1.]',
+ )
+ })
+
+ test('non-array value for array type', () => {
+ expect(() =>
+ TypedData.assert({
+ types: {
+ Person: [
+ { name: 'name', type: 'string' },
+ { name: 'wallet', type: 'address' },
+ ],
+ Foo: [{ name: 'people', type: 'Person[]' }],
+ },
+ primaryType: 'Foo',
+ message: {
+ people: 'oops' as any,
+ },
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[TypedData.InvalidArrayError: Value for field `people` of type `Person[]` is not an array. Got `string`.]',
+ )
+ })
+
+ test('invalid array element', () => {
+ expect(() =>
+ TypedData.assert({
+ types: {
+ Foo: [{ name: 'addresses', type: 'address[]' }],
+ },
+ primaryType: 'Foo',
+ message: {
+ addresses: ['0xnot-an-address'],
+ },
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [Address.InvalidAddressError: Address "0xnot-an-address" is invalid.
+
+ Details: Address is not a 20 byte (40 hexadecimal character) value.]
+ `)
+ })
+
+ test('uint array element overflow', () => {
+ expect(() =>
+ TypedData.assert({
+ types: {
+ Foo: [{ name: 'amounts', type: 'uint8[]' }],
+ },
+ primaryType: 'Foo',
+ message: {
+ amounts: [256n],
+ },
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [Hex.IntegerOutOfRangeError: Number \`256n\` is not in safe 8-bit unsigned integer range (\`0n\` to \`255n\`)]
+ `)
+ })
})
describe('domainSeparator', () => {
@@ -1489,6 +1559,8 @@ test('exports', () => {
"InvalidDomainError",
"InvalidPrimaryTypeError",
"InvalidStructTypeError",
+ "InvalidArrayError",
+ "InvalidArrayLengthError",
"encodeData",
"hashType",
"encodeField",
From e94c7ed91c7ac2b08125202cf7ec7f0decbe8fa6 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:14:50 +1000
Subject: [PATCH 027/192] fix(webauthn): honor hash option in
Authentication.getSignPayload
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-bc30fc2dfd83
---
...uthn-authentication-getsignpayload-hash.md | 5 +++
src/webauthn/Authentication.ts | 4 +-
src/webauthn/_test/Authentication.test.ts | 42 +++++++++++++++++++
3 files changed, 50 insertions(+), 1 deletion(-)
create mode 100644 .changeset/wave-0-webauthn-authentication-getsignpayload-hash.md
diff --git a/.changeset/wave-0-webauthn-authentication-getsignpayload-hash.md b/.changeset/wave-0-webauthn-authentication-getsignpayload-hash.md
new file mode 100644
index 00000000..fb019040
--- /dev/null
+++ b/.changeset/wave-0-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/src/webauthn/Authentication.ts b/src/webauthn/Authentication.ts
index c4792dbc..f9a32ff3 100644
--- a/src/webauthn/Authentication.ts
+++ b/src/webauthn/Authentication.ts
@@ -258,6 +258,7 @@ export function getSignPayload(
crossOrigin,
extraClientData,
flag,
+ hash = false,
origin,
rpId,
signCount,
@@ -288,7 +289,8 @@ export function getSignPayload(
userVerificationRequired: userVerification === 'required',
}
- const payload = Hex.concat(authenticatorData, clientDataJSONHash)
+ const concatenated = Hex.concat(authenticatorData, clientDataJSONHash)
+ const payload = hash ? Hash.sha256(concatenated) : concatenated
return { metadata, payload }
}
diff --git a/src/webauthn/_test/Authentication.test.ts b/src/webauthn/_test/Authentication.test.ts
index 600d5ade..b1c3fb9e 100644
--- a/src/webauthn/_test/Authentication.test.ts
+++ b/src/webauthn/_test/Authentication.test.ts
@@ -1,5 +1,6 @@
import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'
import * as Bytes from '../../core/Bytes.js'
+import * as Hash from '../../core/Hash.js'
import * as P256 from '../../core/P256.js'
import * as PublicKey from '../../core/PublicKey.js'
import * as Signature from '../../core/Signature.js'
@@ -443,6 +444,47 @@ describe('getSignPayload', () => {
)
})
+ test('options: hash', () => {
+ const data = {
+ challenge:
+ '0xf631058a3ba1116acce12396fad0a125b5041c43f8e15723709f81aa8d5f4ccf',
+ origin: 'http://localhost:5173',
+ rpId: 'foo',
+ } as const
+ const { payload: unhashed } = Authentication.getSignPayload(data)
+ const { payload: hashed } = Authentication.getSignPayload({
+ ...data,
+ hash: true,
+ })
+ expect(hashed).toBe(Hash.sha256(unhashed))
+ })
+
+ test('options: hash + verify roundtrip', () => {
+ const { privateKey, publicKey } = P256.createKeyPair()
+
+ const challenge =
+ '0xf631058a3ba1116acce12396fad0a125b5041c43f8e15723709f81aa8d5f4ccf' as const
+
+ const { metadata, payload } = Authentication.getSignPayload({
+ challenge,
+ origin: 'http://localhost:5173',
+ rpId: 'localhost',
+ hash: true,
+ })
+
+ // payload is already hashed, so do not re-hash on sign
+ const signature = P256.sign({ payload, privateKey })
+
+ expect(
+ Authentication.verify({
+ challenge,
+ publicKey,
+ signature,
+ metadata,
+ }),
+ ).toBeTruthy()
+ })
+
test('options: signCount', () => {
const payload = Authentication.getSignPayload({
challenge:
From 62233c469ed63a09a5d8ee3a690af8900bfa80bc Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:15:21 +1000
Subject: [PATCH 028/192] fix(tempo): emit `calls[].input` from
Transaction.toRpc to match TempoRpc schema
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b992045f9165
---
.changeset/wave-0-tempo-transaction-rpc-input.md | 5 +++++
src/tempo/Transaction.test.ts | 6 +++---
src/tempo/Transaction.ts | 2 +-
3 files changed, 9 insertions(+), 4 deletions(-)
create mode 100644 .changeset/wave-0-tempo-transaction-rpc-input.md
diff --git a/.changeset/wave-0-tempo-transaction-rpc-input.md b/.changeset/wave-0-tempo-transaction-rpc-input.md
new file mode 100644
index 00000000..758e792c
--- /dev/null
+++ b/.changeset/wave-0-tempo-transaction-rpc-input.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Fixed `tempo.Transaction.toRpc` to emit each call's data as `input` to match the `TempoRpc` schema and round-trip with `tempo.Transaction.fromRpc`.
diff --git a/src/tempo/Transaction.test.ts b/src/tempo/Transaction.test.ts
index 4923f070..6cb319ec 100644
--- a/src/tempo/Transaction.test.ts
+++ b/src/tempo/Transaction.test.ts
@@ -304,7 +304,7 @@ describe('toRpc', () => {
"blockNumber": "0x12f296f",
"calls": [
{
- "data": "0xdeadbeef",
+ "input": "0xdeadbeef",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"value": "0x9b6e64a8ec60000",
},
@@ -380,7 +380,7 @@ describe('toRpc', () => {
"blockNumber": "0x12f296f",
"calls": [
{
- "data": "0xdeadbeef",
+ "input": "0xdeadbeef",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"value": "0x9b6e64a8ec60000",
},
@@ -476,7 +476,7 @@ describe('toRpc', () => {
"blockNumber": "0x12f296f",
"calls": [
{
- "data": "0xdeadbeef",
+ "input": "0xdeadbeef",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"value": "0x9b6e64a8ec60000",
},
diff --git a/src/tempo/Transaction.ts b/src/tempo/Transaction.ts
index e8f417d1..5de7cd10 100644
--- a/src/tempo/Transaction.ts
+++ b/src/tempo/Transaction.ts
@@ -307,7 +307,7 @@ export function toRpc(
rpc.calls = transaction.calls.map((call) => ({
to: call.to,
value: call.value ? Hex.fromNumber(call.value) : undefined,
- data: call.data,
+ input: call.data,
}))
if (transaction.feeToken) rpc.feeToken = transaction.feeToken
if (transaction.keyAuthorization)
From c5c6a203c169f6be30a6fc5500908f6a686506b4 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:15:48 +1000
Subject: [PATCH 029/192] fix(webauthn): document Registration.verify
attestation default as 'none'
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-bc30fc2dfd83
---
...istration-verify-attestation-default-docs.md | 5 +++++
src/webauthn/Registration.ts | 6 +++---
src/webauthn/_test/Registration.test.ts | 17 +++++++++++++++++
3 files changed, 25 insertions(+), 3 deletions(-)
create mode 100644 .changeset/wave-0-webauthn-registration-verify-attestation-default-docs.md
diff --git a/.changeset/wave-0-webauthn-registration-verify-attestation-default-docs.md b/.changeset/wave-0-webauthn-registration-verify-attestation-default-docs.md
new file mode 100644
index 00000000..c821b30f
--- /dev/null
+++ b/.changeset/wave-0-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/src/webauthn/Registration.ts b/src/webauthn/Registration.ts
index 4df1031b..99570e32 100644
--- a/src/webauthn/Registration.ts
+++ b/src/webauthn/Registration.ts
@@ -760,10 +760,10 @@ export declare namespace verify {
type Options = {
/**
* Attestation verification mode.
- * - `'required'` (default): attestation signature must be present and valid (`packed` self-attestation).
- * - `'none'`: accept `fmt: "none"` attestation (no cryptographic binding of authData to clientDataJSON).
+ * - `'none'` (default): accept `fmt: "none"` attestation (no cryptographic binding of authData to clientDataJSON).
+ * - `'required'`: attestation signature must be present and valid (`packed` self-attestation).
*
- * @default 'required'
+ * @default 'none'
*/
attestation?: 'required' | 'none' | undefined
/** The credential response from `Registration.create()`. */
diff --git a/src/webauthn/_test/Registration.test.ts b/src/webauthn/_test/Registration.test.ts
index 89527a54..cf4738b4 100644
--- a/src/webauthn/_test/Registration.test.ts
+++ b/src/webauthn/_test/Registration.test.ts
@@ -984,6 +984,23 @@ describe('verify', () => {
).toThrow('Credential ID mismatch')
})
+ test('default attestation is "none" (matches getOptions default)', async () => {
+ const { credential, challenge, origin, rpId } = await mockCreateCredential({
+ fmt: 'none',
+ })
+
+ // No `attestation` option; runtime default must be 'none' so that
+ // unattested ('fmt: "none"') credentials are accepted by default.
+ const result = Registration.verify({
+ credential,
+ challenge,
+ origin,
+ rpId,
+ })
+
+ expect(result.credential.id).toBe(credential.id)
+ })
+
test('error: fmt none rejected when attestation is required', async () => {
const { credential, challenge, origin, rpId } = await mockCreateCredential({
fmt: 'none',
From ded65ec2d84b7f11713c0a6577f882c18f16444a Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:15:50 +1000
Subject: [PATCH 030/192] test(abi): update AbiConstructor snapshots for
BytecodeMismatchError
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-9d2614e4f981
---
src/core/_test/AbiConstructor.test.ts | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/core/_test/AbiConstructor.test.ts b/src/core/_test/AbiConstructor.test.ts
index b226fe93..0956728d 100644
--- a/src/core/_test/AbiConstructor.test.ts
+++ b/src/core/_test/AbiConstructor.test.ts
@@ -128,9 +128,12 @@ describe('decode', () => {
bytecode: '0x6080604052deadbeef',
data: '0xcafebabe000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045000000000000000000000000000000000000000000000000000000000000007b',
}),
- ).toThrowErrorMatchingInlineSnapshot(
- `[AbiConstructor.BytecodeMismatchError: Provided \`data\` does not start with the provided \`bytecode\`.]`,
- )
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [AbiConstructor.BytecodeMismatchError: Provided \`data\` does not start with the provided \`bytecode\`.
+
+ Bytecode: 0x6080604052deadbe...
+ Data: 0xcafebabe00000000...]
+ `)
})
})
@@ -326,6 +329,7 @@ test('exports', () => {
"format",
"from",
"fromAbi",
+ "BytecodeMismatchError",
]
`)
})
From 58f78e843915db31e2bdbef0222763ff5423f850 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:16:07 +1000
Subject: [PATCH 031/192] fix(keystore): apply KDF parameter validation to
pbkdf2/scrypt entry points
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a57e8955ff21
---
src/core/Keystore.ts | 26 +++++++++++++++
src/core/_test/Keystore.test.ts | 58 +++++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+)
diff --git a/src/core/Keystore.ts b/src/core/Keystore.ts
index b1dce77b..8a61ea7f 100644
--- a/src/core/Keystore.ts
+++ b/src/core/Keystore.ts
@@ -231,6 +231,7 @@ export declare namespace encrypt {
*/
export function pbkdf2(options: pbkdf2.Options) {
const { iv, iterations = 262_144, password } = options
+ assertPbkdf2Iterations(iterations)
const salt = options.salt ? Bytes.from(options.salt) : Bytes.random(32)
const key = Bytes.toHex(
@@ -277,6 +278,7 @@ export declare namespace pbkdf2 {
*/
export async function pbkdf2Async(options: pbkdf2.Options) {
const { iv, iterations = 262_144, password } = options
+ assertPbkdf2Iterations(iterations)
const salt = options.salt ? Bytes.from(options.salt) : Bytes.random(32)
const key = Bytes.toHex(
@@ -317,6 +319,7 @@ export declare namespace pbkdf2Async {
*/
export function scrypt(options: scrypt.Options) {
const { iv, n = 262_144, password, p = 8, r = 1 } = options
+ assertScryptParams(n, r, p)
const salt = options.salt ? Bytes.from(options.salt) : Bytes.random(32)
const key = Bytes.toHex(
@@ -368,6 +371,7 @@ export declare namespace scrypt {
*/
export async function scryptAsync(options: scrypt.Options) {
const { iv, n = 262_144, password, p = 8, r = 1 } = options
+ assertScryptParams(n, r, p)
const salt = options.salt ? Bytes.from(options.salt) : Bytes.random(32)
const key = Bytes.toHex(
@@ -520,6 +524,28 @@ export declare namespace toKeyAsync {
///////////////////////////////////////////////////////////////////////////
+/** @internal */
+// biome-ignore lint/correctness/noUnusedVariables: called above
+function assertPbkdf2Iterations(iterations: number) {
+ if (!Number.isInteger(iterations) || iterations < 1_000)
+ throw new Error(
+ `Keystore: PBKDF2 iterations must be an integer >= 1000, got ${iterations}.`,
+ )
+}
+
+/** @internal */
+// biome-ignore lint/correctness/noUnusedVariables: called above
+function assertScryptParams(n: number, r: number, p: number) {
+ if (!Number.isInteger(n) || n < 1_024 || (n & (n - 1)) !== 0)
+ throw new Error(
+ `Keystore: scrypt n must be a power of two >= 1024, got ${n}.`,
+ )
+ if (!Number.isInteger(r) || r <= 0)
+ throw new Error(`Keystore: scrypt r must be a positive integer, got ${r}.`)
+ if (!Number.isInteger(p) || p <= 0)
+ throw new Error(`Keystore: scrypt p must be a positive integer, got ${p}.`)
+}
+
/** @internal */
// biome-ignore lint/correctness/noUnusedVariables: _
function defineKey<
diff --git a/src/core/_test/Keystore.test.ts b/src/core/_test/Keystore.test.ts
index 210c37cd..843b3a95 100644
--- a/src/core/_test/Keystore.test.ts
+++ b/src/core/_test/Keystore.test.ts
@@ -426,6 +426,64 @@ describe('pbkdf2Async', () => {
})
})
+describe('validation', () => {
+ test('pbkdf2 rejects iterations < 1000', () => {
+ expect(() =>
+ Keystore.pbkdf2({ password: 'x', iterations: 1 }),
+ ).toThrowError(
+ 'Keystore: PBKDF2 iterations must be an integer >= 1000, got 1.',
+ )
+ })
+
+ test('pbkdf2 rejects non-integer iterations', () => {
+ expect(() =>
+ Keystore.pbkdf2({ password: 'x', iterations: 1.5 }),
+ ).toThrowError(
+ 'Keystore: PBKDF2 iterations must be an integer >= 1000, got 1.5.',
+ )
+ })
+
+ test('pbkdf2Async rejects iterations < 1000', async () => {
+ await expect(
+ Keystore.pbkdf2Async({ password: 'x', iterations: 1 }),
+ ).rejects.toThrowError(
+ 'Keystore: PBKDF2 iterations must be an integer >= 1000, got 1.',
+ )
+ })
+
+ test('scrypt rejects n < 1024', () => {
+ expect(() => Keystore.scrypt({ password: 'x', n: 2 })).toThrowError(
+ 'Keystore: scrypt n must be a power of two >= 1024, got 2.',
+ )
+ })
+
+ test('scrypt rejects n that is not a power of two', () => {
+ expect(() => Keystore.scrypt({ password: 'x', n: 1500 })).toThrowError(
+ 'Keystore: scrypt n must be a power of two >= 1024, got 1500.',
+ )
+ })
+
+ test('scrypt rejects r <= 0', () => {
+ expect(() =>
+ Keystore.scrypt({ password: 'x', n: 1024, r: 0 }),
+ ).toThrowError('Keystore: scrypt r must be a positive integer, got 0.')
+ })
+
+ test('scrypt rejects p <= 0', () => {
+ expect(() =>
+ Keystore.scrypt({ password: 'x', n: 1024, p: 0 }),
+ ).toThrowError('Keystore: scrypt p must be a positive integer, got 0.')
+ })
+
+ test('scryptAsync rejects n that is not a power of two', async () => {
+ await expect(
+ Keystore.scryptAsync({ password: 'x', n: 1500 }),
+ ).rejects.toThrowError(
+ 'Keystore: scrypt n must be a power of two >= 1024, got 1500.',
+ )
+ })
+})
+
describe.skip('scrypt', () => {
test('default', async () => {
const [key, opts] = Keystore.scrypt({
From 4b587b1105367c832a480d3224cb08232ade20cb Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:16:15 +1000
Subject: [PATCH 032/192] fix(transactions): clone caller input in
TransactionRequest.fromRpc to avoid mutation
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a8a740d3ed8f
---
...ctions-transaction-request-fromrpc-no-mutate.md | 5 +++++
src/core/CoseKey.ts | 11 ++++++++++-
src/core/TransactionRequest.ts | 2 +-
src/core/_test/TransactionRequest.test.ts | 14 ++++++++++++++
4 files changed, 30 insertions(+), 2 deletions(-)
create mode 100644 .changeset/wave-0-transactions-transaction-request-fromrpc-no-mutate.md
diff --git a/.changeset/wave-0-transactions-transaction-request-fromrpc-no-mutate.md b/.changeset/wave-0-transactions-transaction-request-fromrpc-no-mutate.md
new file mode 100644
index 00000000..bd113ae8
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/CoseKey.ts b/src/core/CoseKey.ts
index 907903ee..e1726403 100644
--- a/src/core/CoseKey.ts
+++ b/src/core/CoseKey.ts
@@ -66,10 +66,19 @@ export declare namespace fromPublicKey {
export function toPublicKey(coseKey: Hex.Hex): PublicKey.PublicKey {
const decoded = Cbor.decode>(coseKey)
+ // Validate COSE_Key header per RFC 9053 (kty=2 EC2, alg=-7 ES256, crv=1 P-256).
+ if (decoded['1'] !== 2 || decoded['3'] !== -7 || decoded['-1'] !== 1)
+ throw new InvalidCoseKeyError()
+
const x = decoded['-2']
const y = decoded['-3']
- if (!(x instanceof Uint8Array) || !(y instanceof Uint8Array))
+ if (
+ !(x instanceof Uint8Array) ||
+ x.length !== 32 ||
+ !(y instanceof Uint8Array) ||
+ y.length !== 32
+ )
throw new InvalidCoseKeyError()
return PublicKey.from(new Uint8Array([0x04, ...x, ...y]))
diff --git a/src/core/TransactionRequest.ts b/src/core/TransactionRequest.ts
index d390aa24..53c0a752 100644
--- a/src/core/TransactionRequest.ts
+++ b/src/core/TransactionRequest.ts
@@ -70,7 +70,7 @@ export type Rpc = TransactionRequest
* @returns A transaction request.
*/
export function fromRpc(request: Rpc): TransactionRequest {
- const request_ = request as TransactionRequest
+ const request_ = { ...request } as TransactionRequest
if (typeof request.authorizationList !== 'undefined')
request_.authorizationList = Authorization.fromRpcList(
diff --git a/src/core/_test/TransactionRequest.test.ts b/src/core/_test/TransactionRequest.test.ts
index cc62f3f4..811de6d6 100644
--- a/src/core/_test/TransactionRequest.test.ts
+++ b/src/core/_test/TransactionRequest.test.ts
@@ -196,6 +196,20 @@ describe('fromRpc', () => {
input: '0xdeadbeef',
})
})
+
+ test('behavior: does not mutate input', () => {
+ const rpc = {
+ chainId: '0x1',
+ gas: '0x5208',
+ gasPrice: '0x2540be400',
+ nonce: '0x1',
+ to: '0x0000000000000000000000000000000000000000',
+ value: '0xde0b6b3a7640000',
+ } as const
+ const snapshot = { ...rpc }
+ TransactionRequest.fromRpc(rpc)
+ expect(rpc).toEqual(snapshot)
+ })
})
test('exports', () => {
From 952a17636e043a32f86d4c0a295a005db82bf6d7 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:16:26 +1000
Subject: [PATCH 033/192] fix(tempo): apply AuthorizationTempo.from signature
normalization (retry)
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b992045f9165
---
src/tempo/AuthorizationTempo.test.ts | 34 +++++++++++++++++++++++++---
src/tempo/AuthorizationTempo.ts | 5 +++-
2 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/src/tempo/AuthorizationTempo.test.ts b/src/tempo/AuthorizationTempo.test.ts
index cee642ac..cf774b6a 100644
--- a/src/tempo/AuthorizationTempo.test.ts
+++ b/src/tempo/AuthorizationTempo.test.ts
@@ -125,15 +125,43 @@ describe('from', () => {
"chainId": 1,
"nonce": 40n,
"signature": {
- "r": 74666311849961653398815470296948700361392062371901161364182304079113687952627n,
- "s": 24912990662134805731506157958890440652926649106845286943280690489391727501383n,
- "yParity": 1,
+ "signature": {
+ "r": 74666311849961653398815470296948700361392062371901161364182304079113687952627n,
+ "s": 24912990662134805731506157958890440652926649106845286943280690489391727501383n,
+ "yParity": 1,
+ },
+ "type": "secp256k1",
},
}
`,
)
})
+ test('options: serialized signature is normalized into an envelope', () => {
+ const authorization = AuthorizationTempo.from({
+ address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
+ chainId: 1,
+ nonce: 40n,
+ })
+ const signature = Secp256k1.sign({
+ payload: AuthorizationTempo.getSignPayload(authorization),
+ privateKey: testPrivateKey,
+ })
+ const serialized = SignatureEnvelope.serialize(
+ SignatureEnvelope.from(signature),
+ )
+
+ const authorization_signed = AuthorizationTempo.from(authorization, {
+ signature: serialized,
+ })
+
+ // The signature should be a normalized envelope object, not a raw string.
+ expect(typeof authorization_signed.signature).toBe('object')
+ expect(authorization_signed.signature).toMatchObject({
+ type: 'secp256k1',
+ })
+ })
+
test('options: signature (secp256k1)', () => {
const authorization = AuthorizationTempo.from({
address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c',
diff --git a/src/tempo/AuthorizationTempo.ts b/src/tempo/AuthorizationTempo.ts
index ebd87062..a8ace06b 100644
--- a/src/tempo/AuthorizationTempo.ts
+++ b/src/tempo/AuthorizationTempo.ts
@@ -261,7 +261,10 @@ export function from<
),
}
if (options.signature) {
- return { ...resolved, signature: options.signature } as never
+ return {
+ ...resolved,
+ signature: SignatureEnvelope.from(options.signature),
+ } as never
}
return resolved as never
}
From b896c488d8ae523f81e32f646e657592f99a4f4c Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:16:43 +1000
Subject: [PATCH 034/192] fix(abi): wrap PositionOutOfBoundsError as
DataSizeTooSmallError in AbiParameters.decode
---
.../wave-0-abi-parameters-data-size-bound.md | 5 ++
.../wave-0-crypto-cosekey-validate-header.md | 5 ++
src/core/AbiParameters.ts | 26 +++++++---
src/core/_test/AbiParameters.decode.test.ts | 9 ++--
src/core/_test/CoseKey.test.ts | 52 ++++++++++++++++++-
5 files changed, 85 insertions(+), 12 deletions(-)
create mode 100644 .changeset/wave-0-abi-parameters-data-size-bound.md
create mode 100644 .changeset/wave-0-crypto-cosekey-validate-header.md
diff --git a/.changeset/wave-0-abi-parameters-data-size-bound.md b/.changeset/wave-0-abi-parameters-data-size-bound.md
new file mode 100644
index 00000000..7e4af13d
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-crypto-cosekey-validate-header.md b/.changeset/wave-0-crypto-cosekey-validate-header.md
new file mode 100644
index 00000000..113fc481
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/AbiParameters.ts b/src/core/AbiParameters.ts
index b5782fe3..d3341c7f 100644
--- a/src/core/AbiParameters.ts
+++ b/src/core/AbiParameters.ts
@@ -96,14 +96,24 @@ export function decode(
const values: any = as === 'Array' ? [] : {}
for (let i = 0; i < parameters.length; ++i) {
const param = parameters[i] as Parameter
- cursor.setPosition(consumed)
- const [data, consumed_] = internal.decodeParameter(cursor, param, {
- checksumAddress,
- staticPosition: 0,
- })
- consumed += consumed_
- if (as === 'Array') values.push(data)
- else values[param.name ?? i] = data
+ try {
+ cursor.setPosition(consumed)
+ const [data_, consumed_] = internal.decodeParameter(cursor, param, {
+ checksumAddress,
+ staticPosition: 0,
+ })
+ consumed += consumed_
+ if (as === 'Array') values.push(data_)
+ else values[param.name ?? i] = data_
+ } catch (err) {
+ if (err instanceof Cursor.PositionOutOfBoundsError)
+ throw new DataSizeTooSmallError({
+ data: typeof data === 'string' ? data : Hex.fromBytes(data),
+ parameters: parameters as readonly Parameter[],
+ size: Bytes.size(bytes),
+ })
+ throw err
+ }
}
return values
}
diff --git a/src/core/_test/AbiParameters.decode.test.ts b/src/core/_test/AbiParameters.decode.test.ts
index 6d30d5ad..a9aa83b7 100644
--- a/src/core/_test/AbiParameters.decode.test.ts
+++ b/src/core/_test/AbiParameters.decode.test.ts
@@ -1525,9 +1525,12 @@ test('data size too small', () => {
[{ type: 'uint256' }, { type: 'uint256' }],
'0x0000000000000000000000000000000000000000000000000000000000010f2c',
),
- ).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `32` is out of bounds (`0 < position < 32`).]',
- )
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [AbiParameters.DataSizeTooSmallError: Data size of 32 bytes is too small for given parameters.
+
+ Params: (uint256, uint256)
+ Data: 0x0000000000000000000000000000000000000000000000000000000000010f2c (32 bytes)]
+ `)
})
test('invalid type', () => {
diff --git a/src/core/_test/CoseKey.test.ts b/src/core/_test/CoseKey.test.ts
index 54c224e1..826b5bac 100644
--- a/src/core/_test/CoseKey.test.ts
+++ b/src/core/_test/CoseKey.test.ts
@@ -1,4 +1,4 @@
-import { CoseKey, P256, PublicKey } from 'ox'
+import { Cbor, CoseKey, P256, PublicKey } from 'ox'
import { describe, expect, test } from 'vitest'
describe('fromPublicKey', () => {
@@ -54,4 +54,54 @@ describe('errors', () => {
CoseKey.InvalidCoseKeyError,
)
})
+
+ function makeCoseKey(overrides: {
+ kty?: number
+ alg?: number
+ crv?: number
+ x?: Uint8Array
+ y?: Uint8Array
+ }) {
+ const x = overrides.x ?? new Uint8Array(32).fill(0xaa)
+ const y = overrides.y ?? new Uint8Array(32).fill(0xbb)
+ return Cbor.encode(
+ new Map([
+ [1, overrides.kty ?? 2],
+ [3, overrides.alg ?? -7],
+ [-1, overrides.crv ?? 1],
+ [-2, x],
+ [-3, y],
+ ]),
+ )
+ }
+
+ test('rejects wrong kty', () => {
+ expect(() => CoseKey.toPublicKey(makeCoseKey({ kty: 1 }))).toThrow(
+ CoseKey.InvalidCoseKeyError,
+ )
+ })
+
+ test('rejects wrong alg', () => {
+ expect(() => CoseKey.toPublicKey(makeCoseKey({ alg: -8 }))).toThrow(
+ CoseKey.InvalidCoseKeyError,
+ )
+ })
+
+ test('rejects wrong crv', () => {
+ expect(() => CoseKey.toPublicKey(makeCoseKey({ crv: 2 }))).toThrow(
+ CoseKey.InvalidCoseKeyError,
+ )
+ })
+
+ test('rejects wrong x coordinate length', () => {
+ expect(() =>
+ CoseKey.toPublicKey(makeCoseKey({ x: new Uint8Array(31).fill(0xaa) })),
+ ).toThrow(CoseKey.InvalidCoseKeyError)
+ })
+
+ test('rejects wrong y coordinate length', () => {
+ expect(() =>
+ CoseKey.toPublicKey(makeCoseKey({ y: new Uint8Array(33).fill(0xbb) })),
+ ).toThrow(CoseKey.InvalidCoseKeyError)
+ })
})
From 135469c75693ceb5329ae14000584bcec3b8f603 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:17:39 +1000
Subject: [PATCH 035/192] fix(authorization): return List instead of TupleList
from fromTupleList type
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a8a740d3ed8f
---
...0-transactions-authorization-fromtuplelist-return-type.md | 5 +++++
src/core/Authorization.ts | 2 +-
src/core/_test/Authorization.test.ts | 1 +
3 files changed, 7 insertions(+), 1 deletion(-)
create mode 100644 .changeset/wave-0-transactions-authorization-fromtuplelist-return-type.md
diff --git a/.changeset/wave-0-transactions-authorization-fromtuplelist-return-type.md b/.changeset/wave-0-transactions-authorization-fromtuplelist-return-type.md
new file mode 100644
index 00000000..d3fdae66
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Authorization.ts b/src/core/Authorization.ts
index 0f6f581d..33409d1e 100644
--- a/src/core/Authorization.ts
+++ b/src/core/Authorization.ts
@@ -353,7 +353,7 @@ export function fromTupleList(
export declare namespace fromTupleList {
type ReturnType = Compute<
- TupleList ? true : false>
+ List ? true : false>
>
type ErrorType = Errors.GlobalErrorType
diff --git a/src/core/_test/Authorization.test.ts b/src/core/_test/Authorization.test.ts
index a749c0e6..43af4b46 100644
--- a/src/core/_test/Authorization.test.ts
+++ b/src/core/_test/Authorization.test.ts
@@ -260,6 +260,7 @@ describe('fromTupleList', () => {
['0x03', '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', '0x14'],
] as const satisfies Authorization.TupleList
const authorization = Authorization.fromTupleList(tupleList)
+ expectTypeOf(authorization).toMatchTypeOf>()
expect(authorization).toMatchInlineSnapshot(`
[
{
From 4e0d154286a9cabc68b0ad16f07f6f7359ef33ca Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:17:58 +1000
Subject: [PATCH 036/192] fix(webauthn): reject invalid AT/ED flag structures
in Authentication.verify
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-bc30fc2dfd83
---
...authn-authentication-verify-at-ed-flags.md | 5 +
src/core/Base58.ts | 20 +++-
src/core/Bytes.ts | 16 ++-
src/core/Cbor.ts | 9 +-
src/core/Hex.ts | 4 +-
src/core/Rlp.ts | 10 +-
src/core/internal/base58.ts | 23 +++--
src/core/internal/bytes.ts | 26 ++---
src/core/internal/hex.ts | 28 +++---
src/webauthn/_test/Authentication.test.ts | 97 +++++++++++++++++++
10 files changed, 167 insertions(+), 71 deletions(-)
create mode 100644 .changeset/wave-0-webauthn-authentication-verify-at-ed-flags.md
diff --git a/.changeset/wave-0-webauthn-authentication-verify-at-ed-flags.md b/.changeset/wave-0-webauthn-authentication-verify-at-ed-flags.md
new file mode 100644
index 00000000..4051de59
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Base58.ts b/src/core/Base58.ts
index 171bd01f..b8e12726 100644
--- a/src/core/Base58.ts
+++ b/src/core/Base58.ts
@@ -106,6 +106,8 @@ export declare namespace toBytes {
* @returns The decoded hex string.
*/
export function toHex(value: string): Hex.Hex {
+ if (value.length === 0) return '0x'
+
let integer = BigInt(0)
let pad = 0
let checkPad = true
@@ -119,18 +121,19 @@ export function toHex(value: string): Hex.Hex {
// check for invalid characters
if (typeof internal.alphabetToInteger[char] !== 'bigint')
- throw new Error('invalid base58 character: ' + char)
+ throw new InvalidCharacterError({ character: char })
integer = integer * 58n
integer = integer + internal.alphabetToInteger[char]!
}
- if (!pad) return `0x${integer.toString(16)}` as Hex.Hex
- return `0x${'0'.repeat(pad * 2)}${integer.toString(16)}` as Hex.Hex
+ let body = integer === 0n ? '' : integer.toString(16)
+ if ((body.length & 1) !== 0) body = `0${body}`
+ return `0x${'00'.repeat(pad)}${body}` as Hex.Hex
}
export declare namespace toHex {
- type ErrorType = Errors.GlobalErrorType
+ type ErrorType = InvalidCharacterError | Errors.GlobalErrorType
}
/**
@@ -154,3 +157,12 @@ export function toString(value: string): string {
export declare namespace toString {
type ErrorType = Errors.GlobalErrorType
}
+
+/** Thrown when a Base58 string contains an invalid character. */
+export class InvalidCharacterError extends Errors.BaseError {
+ override readonly name = 'Base58.InvalidCharacterError'
+
+ constructor({ character }: { character: string }) {
+ super(`Invalid Base58 character: "${character}".`)
+ }
+}
diff --git a/src/core/Bytes.ts b/src/core/Bytes.ts
index 2cb15e27..f6016658 100644
--- a/src/core/Bytes.ts
+++ b/src/core/Bytes.ts
@@ -212,16 +212,24 @@ export declare namespace fromBoolean {
export function fromHex(value: Hex.Hex, options: fromHex.Options = {}): Bytes {
const { size } = options
+ if (
+ typeof value !== 'string' ||
+ value.length < 2 ||
+ value.charCodeAt(0) !== 48 /* '0' */ ||
+ value.charCodeAt(1) !== 120 /* 'x' */
+ )
+ throw new Hex.InvalidHexValueError(value)
+
let hex = value
if (size) {
internal_hex.assertSize(value, size)
hex = Hex.padRight(value, size)
}
- let hexString = hex.slice(2) as string
- if (hexString.length % 2) hexString = `0${hexString}`
+ const hexString = hex.slice(2)
+ if ((hexString.length & 1) !== 0) throw new Hex.InvalidLengthError(hex)
- const length = hexString.length / 2
+ const length = hexString.length >> 1
const bytes = new Uint8Array(length)
for (let index = 0, j = 0; index < length; index++) {
const nibbleLeft = internal.charCodeToBase16(hexString.charCodeAt(j++))
@@ -245,6 +253,8 @@ export declare namespace fromHex {
type ErrorType =
| internal_hex.assertSize.ErrorType
| Hex.padRight.ErrorType
+ | Hex.InvalidHexValueError
+ | Hex.InvalidLengthError
| Errors.GlobalErrorType
}
diff --git a/src/core/Cbor.ts b/src/core/Cbor.ts
index 43436e0b..b9b72199 100644
--- a/src/core/Cbor.ts
+++ b/src/core/Cbor.ts
@@ -83,14 +83,7 @@ export declare namespace encode {
* @returns The decoded value.
*/
export function decode(data: Hex.Hex | Bytes.Bytes): type {
- const bytes = (() => {
- if (typeof data === 'string') {
- if (data.length > 3 && data.length % 2 !== 0)
- throw new Hex.InvalidLengthError(data)
- return Bytes.fromHex(data)
- }
- return data
- })()
+ const bytes = typeof data === 'string' ? Bytes.fromHex(data) : data
const cursor = Cursor.create(bytes)
diff --git a/src/core/Hex.ts b/src/core/Hex.ts
index a3323b5f..80c8a5e9 100644
--- a/src/core/Hex.ts
+++ b/src/core/Hex.ts
@@ -35,7 +35,6 @@ export function assert(
options: assert.Options = {},
): asserts value is Hex {
const { strict = false } = options
- if (!value) throw new InvalidHexTypeError(value)
if (typeof value !== 'string') throw new InvalidHexTypeError(value)
if (strict) {
if (!/^0x[0-9a-fA-F]*$/.test(value)) throw new InvalidHexValueError(value)
@@ -109,7 +108,8 @@ export declare namespace concat {
export function from(value: Hex | Bytes.Bytes | readonly number[]): Hex {
if (value instanceof Uint8Array) return fromBytes(value)
if (Array.isArray(value)) return fromBytes(new Uint8Array(value))
- return value as never
+ assert(value)
+ return value
}
export declare namespace from {
diff --git a/src/core/Rlp.ts b/src/core/Rlp.ts
index 92a1f85f..5aad2dc7 100644
--- a/src/core/Rlp.ts
+++ b/src/core/Rlp.ts
@@ -59,14 +59,8 @@ export function to<
>(value: value, to: to | 'Hex' | 'Bytes'): to.ReturnType {
const to_ = to ?? (typeof value === 'string' ? 'Hex' : 'Bytes')
- const bytes = (() => {
- if (typeof value === 'string') {
- if (value.length > 3 && value.length % 2 !== 0)
- throw new Hex.InvalidLengthError(value)
- return Bytes.fromHex(value)
- }
- return value as Bytes.Bytes
- })()
+ const bytes =
+ typeof value === 'string' ? Bytes.fromHex(value) : (value as Bytes.Bytes)
const cursor = Cursor.create(bytes, {
recursiveReadLimit: Number.POSITIVE_INFINITY,
diff --git a/src/core/internal/base58.ts b/src/core/internal/base58.ts
index c9dc818a..776c2719 100644
--- a/src/core/internal/base58.ts
+++ b/src/core/internal/base58.ts
@@ -72,13 +72,17 @@ export const alphabetToInteger = /* __PURE__ */ Object.freeze<
/** @internal */
export function from(value: Hex.Hex | Bytes.Bytes) {
- let bytes = Bytes.from(value)
+ const bytes = Bytes.from(value)
- let integer = (() => {
- let hex = value
- if (value instanceof Uint8Array) hex = Hex.fromBytes(bytes)
- return BigInt(hex as string)
- })()
+ if (bytes.length === 0) return ''
+
+ let pad = 0
+ while (pad < bytes.length && bytes[pad] === 0) pad++
+
+ let integer =
+ value instanceof Uint8Array
+ ? BigInt(Hex.fromBytes(bytes))
+ : BigInt(value as string)
let result = ''
while (integer > 0n) {
@@ -87,12 +91,7 @@ export function from(value: Hex.Hex | Bytes.Bytes) {
result = integerToAlphabet[remainder] + result
}
- while (bytes.length > 1 && bytes[0] === 0) {
- result = '1' + result
- bytes = bytes.slice(1)
- }
-
- return result
+ return '1'.repeat(pad) + result
}
/** @internal */
diff --git a/src/core/internal/bytes.ts b/src/core/internal/bytes.ts
index f7f33a29..241c6db7 100644
--- a/src/core/internal/bytes.ts
+++ b/src/core/internal/bytes.ts
@@ -97,11 +97,7 @@ export function pad(bytes: Bytes.Bytes, options: pad.Options = {}) {
type: 'Bytes',
})
const paddedBytes = new Uint8Array(size)
- for (let i = 0; i < size; i++) {
- const padEnd = dir === 'right'
- paddedBytes[padEnd ? i : size - i - 1] =
- bytes[padEnd ? i : bytes.length - i - 1]!
- }
+ paddedBytes.set(bytes, dir === 'right' ? 0 : size - bytes.length)
return paddedBytes
}
@@ -124,20 +120,14 @@ export function trim(
): trim.ReturnType {
const { dir = 'left' } = options
- let data = value
-
- let sliceLength = 0
- for (let i = 0; i < data.length - 1; i++) {
- if (data[dir === 'left' ? i : data.length - i - 1]!.toString() === '0')
- sliceLength++
- else break
- }
- data =
- dir === 'left'
- ? data.slice(sliceLength)
- : data.slice(0, data.length - sliceLength)
+ let start = 0
+ let end = value.length
+ if (dir === 'left') while (start < end && value[start] === 0) start++
+ else while (end > start && value[end - 1] === 0) end--
- return data as trim.ReturnType
+ return (
+ start === 0 && end === value.length ? value : value.slice(start, end)
+ ) as trim.ReturnType
}
/** @internal */
diff --git a/src/core/internal/hex.ts b/src/core/internal/hex.ts
index 5e971474..645b9c9a 100644
--- a/src/core/internal/hex.ts
+++ b/src/core/internal/hex.ts
@@ -94,22 +94,18 @@ export function trim(
): trim.ReturnType {
const { dir = 'left' } = options
- let data = value.replace('0x', '')
-
- let sliceLength = 0
- for (let i = 0; i < data.length - 1; i++) {
- if (data[dir === 'left' ? i : data.length - i - 1]!.toString() === '0')
- sliceLength++
- else break
- }
- data =
- dir === 'left'
- ? data.slice(sliceLength)
- : data.slice(0, data.length - sliceLength)
-
- if (data === '0') return '0x'
- if (dir === 'right' && data.length % 2 === 1) return `0x${data}0`
- return `0x${data}` as trim.ReturnType
+ const data = value.slice(2)
+
+ let start = 0
+ let end = data.length
+ if (dir === 'left')
+ while (start < end && data.charCodeAt(start) === 48 /* '0' */) start++
+ else while (end > start && data.charCodeAt(end - 1) === 48 /* '0' */) end--
+
+ if (start >= end) return '0x'
+ if (dir === 'right' && (end - start) % 2 === 1)
+ return `0x${data.slice(start, end)}0` as trim.ReturnType
+ return `0x${data.slice(start, end)}` as trim.ReturnType
}
/** @internal */
diff --git a/src/webauthn/_test/Authentication.test.ts b/src/webauthn/_test/Authentication.test.ts
index b1c3fb9e..934c966b 100644
--- a/src/webauthn/_test/Authentication.test.ts
+++ b/src/webauthn/_test/Authentication.test.ts
@@ -1771,4 +1771,101 @@ describe('verify', () => {
}),
).toBeFalsy()
})
+
+ test('behavior: AT flag set on assertion is rejected', () => {
+ const publicKey = PublicKey.from({
+ prefix: 4,
+ x: 15325272481743543470187210372131079389379804084126119117911265853867256769440n,
+ y: 74947999673872536163854436677160946007685903587557427331495653571111132132212n,
+ })
+ const signature = Signature.from({
+ r: 10330677067519063752777069525326520293658884904426299601620960859195372963151n,
+ s: 47017859265388077754498411591757867926785106410894171160067329762716841868244n,
+ })
+ // Original flag byte was 0x05; flip the AT bit (0x40) to make 0x45.
+ const metadata = {
+ authenticatorData:
+ '0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97634500000000',
+ challengeIndex: 23,
+ clientDataJSON:
+ '{"type":"webauthn.get","challenge":"9jEFijuhEWrM4SOW-tChJbUEHEP44VcjcJ-Bqo1fTM8","origin":"http://localhost:5173","crossOrigin":false}',
+ typeIndex: 1,
+ userVerificationRequired: true,
+ } as const
+
+ expect(
+ Authentication.verify({
+ metadata,
+ challenge:
+ '0xf631058a3ba1116acce12396fad0a125b5041c43f8e15723709f81aa8d5f4ccf',
+ publicKey,
+ signature,
+ }),
+ ).toBeFalsy()
+ })
+
+ test('behavior: ED flag set with no extension bytes is rejected', () => {
+ const publicKey = PublicKey.from({
+ prefix: 4,
+ x: 15325272481743543470187210372131079389379804084126119117911265853867256769440n,
+ y: 74947999673872536163854436677160946007685903587557427331495653571111132132212n,
+ })
+ const signature = Signature.from({
+ r: 10330677067519063752777069525326520293658884904426299601620960859195372963151n,
+ s: 47017859265388077754498411591757867926785106410894171160067329762716841868244n,
+ })
+ // Flag byte 0x85 = UP | UV | ED, but no trailing CBOR map.
+ const metadata = {
+ authenticatorData:
+ '0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97638500000000',
+ challengeIndex: 23,
+ clientDataJSON:
+ '{"type":"webauthn.get","challenge":"9jEFijuhEWrM4SOW-tChJbUEHEP44VcjcJ-Bqo1fTM8","origin":"http://localhost:5173","crossOrigin":false}',
+ typeIndex: 1,
+ userVerificationRequired: true,
+ } as const
+
+ expect(
+ Authentication.verify({
+ metadata,
+ challenge:
+ '0xf631058a3ba1116acce12396fad0a125b5041c43f8e15723709f81aa8d5f4ccf',
+ publicKey,
+ signature,
+ }),
+ ).toBeFalsy()
+ })
+
+ test('behavior: ED flag set with malformed CBOR extension is rejected', () => {
+ const publicKey = PublicKey.from({
+ prefix: 4,
+ x: 15325272481743543470187210372131079389379804084126119117911265853867256769440n,
+ y: 74947999673872536163854436677160946007685903587557427331495653571111132132212n,
+ })
+ const signature = Signature.from({
+ r: 10330677067519063752777069525326520293658884904426299601620960859195372963151n,
+ s: 47017859265388077754498411591757867926785106410894171160067329762716841868244n,
+ })
+ // Flag byte 0x85 = UP | UV | ED, with an obviously malformed trailing
+ // extension (0xff is reserved/break in CBOR and not a valid top-level item).
+ const metadata = {
+ authenticatorData:
+ '0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97638500000000ff',
+ challengeIndex: 23,
+ clientDataJSON:
+ '{"type":"webauthn.get","challenge":"9jEFijuhEWrM4SOW-tChJbUEHEP44VcjcJ-Bqo1fTM8","origin":"http://localhost:5173","crossOrigin":false}',
+ typeIndex: 1,
+ userVerificationRequired: true,
+ } as const
+
+ expect(
+ Authentication.verify({
+ metadata,
+ challenge:
+ '0xf631058a3ba1116acce12396fad0a125b5041c43f8e15723709f81aa8d5f4ccf',
+ publicKey,
+ signature,
+ }),
+ ).toBeFalsy()
+ })
})
From a67a329cc09f71894f09eb27fa1f5be7fe2704c5 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:18:20 +1000
Subject: [PATCH 037/192] fix(transactions): validate storage keys strictly in
AccessList.fromTupleList
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a8a740d3ed8f
---
...nsactions-access-list-strict-storage-keys.md | 5 +++++
src/core/AccessList.ts | 11 +++++++----
src/core/_test/AccessList.test.ts | 17 +++++++++++++----
3 files changed, 25 insertions(+), 8 deletions(-)
create mode 100644 .changeset/wave-0-transactions-access-list-strict-storage-keys.md
diff --git a/.changeset/wave-0-transactions-access-list-strict-storage-keys.md b/.changeset/wave-0-transactions-access-list-strict-storage-keys.md
new file mode 100644
index 00000000..4a9b28fa
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/AccessList.ts b/src/core/AccessList.ts
index 8fc6adba..68dcb3c2 100644
--- a/src/core/AccessList.ts
+++ b/src/core/AccessList.ts
@@ -1,6 +1,5 @@
import * as Address from './Address.js'
import * as Errors from './Errors.js'
-import * as Hash from './Hash.js'
import * as Hex from './Hex.js'
import type { Compute, Mutable } from './internal/types.js'
@@ -54,11 +53,15 @@ export function fromTupleList(accessList: Tuple): AccessList {
if (address) Address.assert(address, { strict: false })
+ for (let j = 0; j < storageKeys.length; j++)
+ if (Hex.size(storageKeys[j]!) !== 32)
+ throw new InvalidStorageKeySizeError({
+ storageKey: storageKeys[j]!,
+ })
+
list.push({
address: address,
- storageKeys: storageKeys.map((key) =>
- Hash.validate(key) ? key : Hex.trimLeft(key),
- ),
+ storageKeys,
})
}
return list
diff --git a/src/core/_test/AccessList.test.ts b/src/core/_test/AccessList.test.ts
index beccfae0..074ea065 100644
--- a/src/core/_test/AccessList.test.ts
+++ b/src/core/_test/AccessList.test.ts
@@ -8,8 +8,6 @@ describe('fromTupleList', () => {
[
'0x1234512345123451234512345123451234512345',
[
- '0x1234512345123451234512345123451234512345',
- '0x0000512345123451234512345123451234512345',
'0x1234512345123451234512345123451234512345123451234512345123423232',
],
],
@@ -19,14 +17,25 @@ describe('fromTupleList', () => {
{
"address": "0x1234512345123451234512345123451234512345",
"storageKeys": [
- "0x1234512345123451234512345123451234512345",
- "0x512345123451234512345123451234512345",
"0x1234512345123451234512345123451234512345123451234512345123423232",
],
},
]
`)
})
+
+ test('error: invalid storage key size', () => {
+ expect(() =>
+ AccessList.fromTupleList([
+ [
+ '0x1234512345123451234512345123451234512345',
+ ['0x1234512345123451234512345123451234512345'],
+ ],
+ ]),
+ ).toThrowErrorMatchingInlineSnapshot(
+ `[AccessList.InvalidStorageKeySizeError: Size for storage key "0x1234512345123451234512345123451234512345" is invalid. Expected 32 bytes. Got 20 bytes.]`,
+ )
+ })
})
describe('toTupleList', () => {
From 62a09afd64f183f88659bd5783a1c2f1869feae4 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:19:29 +1000
Subject: [PATCH 038/192] fix(webauthn): reject invalid AT/ED flag structures
in Authentication.verify (impl)
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-bc30fc2dfd83
---
...c4337-user-operation-from-packed-typing.md | 5 +
.../wave-0-erc4337-user-operation-gas-v08.md | 5 +
...rc4337-user-operation-v08-authorization.md | 5 +
...wave-0-erc6492-strip-magic-and-validate.md | 5 +
...-0-erc7821-execute-structural-detection.md | 5 +
...ve-0-erc8010-assert-suffix-and-recovery.md | 5 +
...ve-0-promise-with-timeout-single-reject.md | 5 +
.changeset/wave-0-provider-from-prototype.md | 5 +
.../wave-0-provider-from-strict-eip1193.md | 5 +
.../wave-0-rpc-response-from-validation.md | 5 +
...ave-0-rpc-response-parse-error-preserve.md | 5 +
.../wave-0-rpc-response-parse-validation.md | 5 +
.changeset/wave-0-rpc-transport-empty-body.md | 5 +
...wave-0-rpc-transport-http-error-details.md | 5 +
.../wave-0-rpc-transport-signal-compose.md | 5 +
src/core/AbiParameters.ts | 27 ++++-
src/core/WebCryptoP256.ts | 20 +++-
src/core/_test/AbiParameters.test.ts | 24 +++++
src/core/_test/Kzg.test.ts | 33 ++++++
src/core/_test/Provider.test.ts | 102 +++++++++++++-----
src/core/_test/RpcResponse.test.ts | 52 +++++++++
src/core/_test/RpcTransport.test.ts | 35 +++++-
src/core/_test/internal/promise.test.ts | 26 +++++
src/erc4337/UserOperation.ts | 4 +
src/erc4337/_test/UserOperation.test.ts | 57 ++++++++++
src/erc4337/_test/UserOperationGas.test.ts | 21 ++++
src/erc6492/_test/SignatureErc6492.test.ts | 43 ++++++++
src/erc8010/_test/SignatureErc8010.test.ts | 62 +++++++++++
src/webauthn/Authentication.ts | 16 +++
29 files changed, 558 insertions(+), 39 deletions(-)
create mode 100644 .changeset/wave-0-erc4337-user-operation-from-packed-typing.md
create mode 100644 .changeset/wave-0-erc4337-user-operation-gas-v08.md
create mode 100644 .changeset/wave-0-erc4337-user-operation-v08-authorization.md
create mode 100644 .changeset/wave-0-erc6492-strip-magic-and-validate.md
create mode 100644 .changeset/wave-0-erc7821-execute-structural-detection.md
create mode 100644 .changeset/wave-0-erc8010-assert-suffix-and-recovery.md
create mode 100644 .changeset/wave-0-promise-with-timeout-single-reject.md
create mode 100644 .changeset/wave-0-provider-from-prototype.md
create mode 100644 .changeset/wave-0-provider-from-strict-eip1193.md
create mode 100644 .changeset/wave-0-rpc-response-from-validation.md
create mode 100644 .changeset/wave-0-rpc-response-parse-error-preserve.md
create mode 100644 .changeset/wave-0-rpc-response-parse-validation.md
create mode 100644 .changeset/wave-0-rpc-transport-empty-body.md
create mode 100644 .changeset/wave-0-rpc-transport-http-error-details.md
create mode 100644 .changeset/wave-0-rpc-transport-signal-compose.md
diff --git a/.changeset/wave-0-erc4337-user-operation-from-packed-typing.md b/.changeset/wave-0-erc4337-user-operation-from-packed-typing.md
new file mode 100644
index 00000000..83ab4f05
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-erc4337-user-operation-gas-v08.md b/.changeset/wave-0-erc4337-user-operation-gas-v08.md
new file mode 100644
index 00000000..9fc9bc86
--- /dev/null
+++ b/.changeset/wave-0-erc4337-user-operation-gas-v08.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Added v0.8 EntryPoint support to `UserOperationGas` (and `RpcSchema.Bundler` via inheritance) by introducing `V08` and `RpcV08` aliases over the v0.7 gas shape.
diff --git a/.changeset/wave-0-erc4337-user-operation-v08-authorization.md b/.changeset/wave-0-erc4337-user-operation-v08-authorization.md
new file mode 100644
index 00000000..97a78f08
--- /dev/null
+++ b/.changeset/wave-0-erc4337-user-operation-v08-authorization.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Fixed `UserOperation.fromRpc` and `UserOperation.toRpc` to parse and serialize the v0.8 `authorization` field instead of dropping it.
diff --git a/.changeset/wave-0-erc6492-strip-magic-and-validate.md b/.changeset/wave-0-erc6492-strip-magic-and-validate.md
new file mode 100644
index 00000000..47dfb0ac
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-erc7821-execute-structural-detection.md b/.changeset/wave-0-erc7821-execute-structural-detection.md
new file mode 100644
index 00000000..5f7133c2
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-erc8010-assert-suffix-and-recovery.md b/.changeset/wave-0-erc8010-assert-suffix-and-recovery.md
new file mode 100644
index 00000000..151a8883
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-promise-with-timeout-single-reject.md b/.changeset/wave-0-promise-with-timeout-single-reject.md
new file mode 100644
index 00000000..c6497085
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-provider-from-prototype.md b/.changeset/wave-0-provider-from-prototype.md
new file mode 100644
index 00000000..da79a10a
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-provider-from-strict-eip1193.md b/.changeset/wave-0-provider-from-strict-eip1193.md
new file mode 100644
index 00000000..ea88e6bc
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-rpc-response-from-validation.md b/.changeset/wave-0-rpc-response-from-validation.md
new file mode 100644
index 00000000..c8c8036c
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-rpc-response-parse-error-preserve.md b/.changeset/wave-0-rpc-response-parse-error-preserve.md
new file mode 100644
index 00000000..57a3ed80
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-rpc-response-parse-validation.md b/.changeset/wave-0-rpc-response-parse-validation.md
new file mode 100644
index 00000000..34f15162
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-rpc-transport-empty-body.md b/.changeset/wave-0-rpc-transport-empty-body.md
new file mode 100644
index 00000000..5ec42a57
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-rpc-transport-http-error-details.md b/.changeset/wave-0-rpc-transport-http-error-details.md
new file mode 100644
index 00000000..f34af06a
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-rpc-transport-signal-compose.md b/.changeset/wave-0-rpc-transport-signal-compose.md
new file mode 100644
index 00000000..0e654e81
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/AbiParameters.ts b/src/core/AbiParameters.ts
index d3341c7f..e25790ba 100644
--- a/src/core/AbiParameters.ts
+++ b/src/core/AbiParameters.ts
@@ -296,8 +296,20 @@ export namespace encodePacked {
isArray ? 32 : 0,
) as Address.Address
}
- if (type === 'string') return Hex.fromString(value as string)
- if (type === 'bytes') return value as Hex.Hex
+ if (type === 'string') {
+ const hex = Hex.fromString(value as string)
+ if (!isArray) return hex
+ const byteSize = (hex.length - 2) / 2
+ const paddedSize = Math.ceil(byteSize / 32) * 32 || 32
+ return Hex.padRight(hex, paddedSize)
+ }
+ if (type === 'bytes') {
+ const hex = value as Hex.Hex
+ if (!isArray) return hex
+ const byteSize = (hex.length - 2) / 2
+ const paddedSize = Math.ceil(byteSize / 32) * 32 || 32
+ return Hex.padRight(hex, paddedSize)
+ }
if (type === 'bool')
return Hex.padLeft(Hex.fromBoolean(value as boolean), isArray ? 32 : 1)
@@ -324,7 +336,16 @@ export namespace encodePacked {
const arrayMatch = (type as string).match(Solidity.arrayRegex)
if (arrayMatch && Array.isArray(value)) {
- const [_type, childType] = arrayMatch
+ const [_type, childType, lengthMatch] = arrayMatch
+ if (lengthMatch) {
+ const declaredLength = Number.parseInt(lengthMatch, 10)
+ if (value.length !== declaredLength)
+ throw new ArrayLengthMismatchError({
+ expectedLength: declaredLength,
+ givenLength: value.length,
+ type: type as string,
+ })
+ }
const data: Hex.Hex[] = []
for (let i = 0; i < value.length; i++) {
data.push(encode(childType, value[i], true))
diff --git a/src/core/WebCryptoP256.ts b/src/core/WebCryptoP256.ts
index c193ecd9..4deab9df 100644
--- a/src/core/WebCryptoP256.ts
+++ b/src/core/WebCryptoP256.ts
@@ -1,6 +1,6 @@
import { p256 } from '@noble/curves/nist.js'
import * as Bytes from './Bytes.js'
-import type * as Errors from './Errors.js'
+import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import type { Compute } from './internal/types.js'
import * as PublicKey from './PublicKey.js'
@@ -157,9 +157,7 @@ export async function getSharedSecret(
const { as = 'Hex', privateKey, publicKey } = options
if (privateKey.algorithm.name === 'ECDSA') {
- throw new Error(
- 'privateKey is not compatible with ECDH. please use `createKeyPairECDH` to create an ECDH key.',
- )
+ throw new InvalidPrivateKeyAlgorithmError()
}
const publicKeyCrypto = await globalThis.crypto.subtle.importKey(
@@ -327,3 +325,17 @@ export declare namespace verify {
type ErrorType = Errors.GlobalErrorType
}
+
+/**
+ * Thrown when an ECDSA private key is supplied to {@link ox#WebCryptoP256.(getSharedSecret:function)}.
+ * Only ECDH private keys are valid for shared secret derivation.
+ */
+export class InvalidPrivateKeyAlgorithmError extends Errors.BaseError {
+ override readonly name = 'WebCryptoP256.InvalidPrivateKeyAlgorithmError'
+
+ constructor() {
+ super(
+ 'privateKey is not compatible with ECDH. Please use `createKeyPairECDH` to create an ECDH key.',
+ )
+ }
+}
diff --git a/src/core/_test/AbiParameters.test.ts b/src/core/_test/AbiParameters.test.ts
index 97ba9792..3f3af379 100644
--- a/src/core/_test/AbiParameters.test.ts
+++ b/src/core/_test/AbiParameters.test.ts
@@ -252,6 +252,30 @@ describe('encodePacked', () => {
'[AbiParameters.InvalidTypeError: Type `function` is not a valid ABI Type.]',
)
})
+
+ test('error: fixed-array length mismatch', () => {
+ expect(() =>
+ AbiParameters.encodePacked(['uint256[2]'], [[1n, 2n, 3n]]),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[AbiParameters.ArrayLengthMismatchError: Array length mismatch for type `uint256[2]`. Expected: `2`. Given: `3`.]',
+ )
+ })
+
+ test('behavior: pads string[] elements to 32 bytes', () => {
+ expect(
+ AbiParameters.encodePacked(['string[]'], [['hi', 'bye']]),
+ ).toMatchInlineSnapshot(
+ `"0x68690000000000000000000000000000000000000000000000000000000000006279650000000000000000000000000000000000000000000000000000000000"`,
+ )
+ })
+
+ test('behavior: pads bytes[] elements to 32 bytes', () => {
+ expect(
+ AbiParameters.encodePacked(['bytes[]'], [['0xdead', '0xbeef']]),
+ ).toMatchInlineSnapshot(
+ `"0xdead000000000000000000000000000000000000000000000000000000000000beef000000000000000000000000000000000000000000000000000000000000"`,
+ )
+ })
})
describe('from', () => {
diff --git a/src/core/_test/Kzg.test.ts b/src/core/_test/Kzg.test.ts
index d6907f81..9404ee83 100644
--- a/src/core/_test/Kzg.test.ts
+++ b/src/core/_test/Kzg.test.ts
@@ -100,3 +100,36 @@ test('exports', () => {
]
`)
})
+
+test('from: preserves `this` binding for method-style implementations', () => {
+ // Stateful implementation whose methods rely on `this` -- a destructured
+ // wrapper would lose the binding and throw.
+ class StatefulKzg {
+ suffix: Uint8Array
+ constructor(suffix: Uint8Array) {
+ this.suffix = suffix
+ }
+ blobToKzgCommitment(blob: Uint8Array): Uint8Array {
+ return new Uint8Array([...blob.slice(0, 1), ...this.suffix])
+ }
+ computeBlobKzgProof(
+ blob: Uint8Array,
+ commitment: Uint8Array,
+ ): Uint8Array {
+ return new Uint8Array([
+ ...blob.slice(0, 1),
+ ...commitment.slice(0, 1),
+ ...this.suffix,
+ ])
+ }
+ }
+ const stateful = new StatefulKzg(new Uint8Array([0xab, 0xcd]))
+ const kzg = Kzg.from(stateful)
+ expect(() => kzg.blobToKzgCommitment(new Uint8Array([0x11]))).not.toThrow()
+ expect(kzg.blobToKzgCommitment(new Uint8Array([0x11]))).toEqual(
+ new Uint8Array([0x11, 0xab, 0xcd]),
+ )
+ expect(
+ kzg.computeBlobKzgProof(new Uint8Array([0x11]), new Uint8Array([0x22])),
+ ).toEqual(new Uint8Array([0x11, 0x22, 0xab, 0xcd]))
+})
diff --git a/src/core/_test/Provider.test.ts b/src/core/_test/Provider.test.ts
index e00169c4..bf65df10 100644
--- a/src/core/_test/Provider.test.ts
+++ b/src/core/_test/Provider.test.ts
@@ -155,6 +155,48 @@ describe('Provider.from', () => {
off('accountsChanged')
})
+ test('behavior: preserves prototype methods and accessors', async () => {
+ class CustomProvider {
+ _calls: string[] = []
+ get isCustom() {
+ return true
+ }
+ async request(args: any) {
+ this._calls.push(args.method)
+ return '0x1'
+ }
+ }
+
+ const original = new CustomProvider()
+ const provider = Provider.from(original) as Provider.Provider & {
+ isCustom: boolean
+ _calls: string[]
+ }
+
+ expect(provider.isCustom).toBe(true)
+ expect(await provider.request({ method: 'eth_blockNumber' })).toBe('0x1')
+ expect(original._calls).toEqual(['eth_blockNumber'])
+ })
+
+ test('behavior: does not parse JSON-RPC envelope success payloads', async () => {
+ // EIP-1193 `request` resolves with the method result, not a JSON-RPC
+ // envelope. If a provider returns an envelope-shaped object as the
+ // method result, Provider.from should pass it through verbatim.
+ const envelopeShapedResult = {
+ jsonrpc: '2.0',
+ id: 0,
+ result: '0x1',
+ }
+ const provider = Provider.from({
+ async request(_) {
+ return envelopeShapedResult
+ },
+ })
+
+ const result = await provider.request({ method: 'eth_blockNumber' })
+ expect(result).toEqual(envelopeShapedResult)
+ })
+
test('behavior: UnauthorizedError', async () => {
const provider = Provider.from({
async request(_) {
@@ -174,14 +216,14 @@ describe('Provider.from', () => {
test('behavior: UnauthorizedError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.UnauthorizedError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -213,14 +255,14 @@ describe('Provider.from', () => {
test('behavior: UserRejectedRequestError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.UserRejectedRequestError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -252,14 +294,14 @@ describe('Provider.from', () => {
test('behavior: UnsupportedMethodError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.UnsupportedMethodError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -291,14 +333,14 @@ describe('Provider.from', () => {
test('behavior: DisconnectedError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.DisconnectedError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -330,14 +372,14 @@ describe('Provider.from', () => {
test('behavior: ChainDisconnectedError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.ChainDisconnectedError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -369,14 +411,14 @@ describe('Provider.from', () => {
test('behavior: SwitchChainError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.SwitchChainError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -408,14 +450,14 @@ describe('Provider.from', () => {
test('behavior: UnsupportedNonOptionalCapabilityError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.UnsupportedNonOptionalCapabilityError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -447,14 +489,14 @@ describe('Provider.from', () => {
test('behavior: UnsupportedChainIdError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.UnsupportedChainIdError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -486,14 +528,14 @@ describe('Provider.from', () => {
test('behavior: DuplicateIdError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.DuplicateIdError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -525,14 +567,14 @@ describe('Provider.from', () => {
test('behavior: UnknownBundleIdError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.UnknownBundleIdError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -564,14 +606,14 @@ describe('Provider.from', () => {
test('behavior: BundleTooLargeError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.BundleTooLargeError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -603,14 +645,14 @@ describe('Provider.from', () => {
test('behavior: AtomicReadyWalletRejectedUpgradeError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.AtomicReadyWalletRejectedUpgradeError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -642,14 +684,14 @@ describe('Provider.from', () => {
test('behavior: AtomicityNotSupportedError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: Provider.AtomicityNotSupportedError.code,
message: 'foo',
},
- }
+ })
},
})
@@ -715,14 +757,14 @@ describe('Provider.from', () => {
test('behavior: BaseError (raw)', async () => {
const provider = Provider.from({
async request(_) {
- return {
+ return RpcResponse.parse({
jsonrpc: '2.0',
id: 0,
error: {
code: 1000,
message: 'foo',
},
- }
+ })
},
})
@@ -746,7 +788,9 @@ describe('Provider.from', () => {
headers: {
'Content-Type': 'application/json',
},
- }).then((res) => res.json())
+ })
+ .then((res) => res.json())
+ .then(RpcResponse.parse)
},
})
diff --git a/src/core/_test/RpcResponse.test.ts b/src/core/_test/RpcResponse.test.ts
index e469b940..bc94b843 100644
--- a/src/core/_test/RpcResponse.test.ts
+++ b/src/core/_test/RpcResponse.test.ts
@@ -37,6 +37,22 @@ describe('from', () => {
}
`)
})
+
+ test('behavior: missing request and missing jsonrpc throws ParseError', () => {
+ expect(() =>
+ RpcResponse.from({ id: 0, result: '0x1' } as never),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[RpcResponse.ParseError: Invalid JSON-RPC response.]',
+ )
+ })
+
+ test('behavior: missing request and missing id throws ParseError', () => {
+ expect(() =>
+ RpcResponse.from({ jsonrpc: '2.0', result: '0x1' } as never),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[RpcResponse.ParseError: Invalid JSON-RPC response.]',
+ )
+ })
})
describe('parse', () => {
@@ -355,6 +371,36 @@ describe('parse', () => {
}),
).toThrowErrorMatchingInlineSnapshot('[RpcResponse.InternalError: oh no]')
})
+
+ test('behavior: rejects empty object envelope', () => {
+ expect(() => RpcResponse.parse({})).toThrowErrorMatchingInlineSnapshot(
+ '[RpcResponse.ParseError: Invalid JSON-RPC response.]',
+ )
+ })
+
+ test('behavior: rejects null envelope', () => {
+ expect(() =>
+ RpcResponse.parse(null as never),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[RpcResponse.ParseError: Invalid JSON-RPC response.]',
+ )
+ })
+
+ test('behavior: rejects envelope without result or error', () => {
+ expect(() =>
+ RpcResponse.parse({ jsonrpc: '2.0', id: 0 } as never),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[RpcResponse.ParseError: Invalid JSON-RPC response.]',
+ )
+ })
+
+ test('behavior: rejects envelope with wrong jsonrpc', () => {
+ expect(() =>
+ RpcResponse.parse({ jsonrpc: '1.0', id: 0, result: '0x1' } as never),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[RpcResponse.ParseError: Invalid JSON-RPC response.]',
+ )
+ })
})
describe('parseError', () => {
@@ -483,6 +529,12 @@ describe('parseError', () => {
expect(message).toBe('foo')
expect(error).toMatchInlineSnapshot('[RpcResponse.InternalError: foo]')
})
+
+ test('behavior: preserves existing BaseError instance', () => {
+ const original = new RpcResponse.InvalidInputError({ message: 'foo' })
+ const error = RpcResponse.parseError(original)
+ expect(error).toBe(original)
+ })
})
test('InvalidInputError', () => {
diff --git a/src/core/_test/RpcTransport.test.ts b/src/core/_test/RpcTransport.test.ts
index 0ad9b3c2..03fdbfa0 100644
--- a/src/core/_test/RpcTransport.test.ts
+++ b/src/core/_test/RpcTransport.test.ts
@@ -157,9 +157,13 @@ describe('fromHttp', () => {
const transport = RpcTransport.fromHttp(server.url)
- const blockNumber = await transport.request({ method: 'eth_accounts' })
+ await expect(() =>
+ transport.request({ method: 'eth_accounts' }),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
+ [RpcTransport.MalformedResponseError: HTTP Response could not be parsed as JSON.
- expect(blockNumber).toMatchInlineSnapshot('undefined')
+ Response: ]
+ `)
})
test('behavior: http error', async () => {
@@ -200,7 +204,7 @@ describe('fromHttp', () => {
URL: https://oxlib.sh/rpc
Body: "{\\"id\\":0,\\"method\\":\\"eth_accounts\\",\\"jsonrpc\\":\\"2.0\\"}"
- Details: "bad"]
+ Details: bad]
`)
})
@@ -219,6 +223,31 @@ describe('fromHttp', () => {
Response: bad]
`)
})
+
+ test('behavior: timeout still fires when caller supplies signal', async () => {
+ // Regression: previously fetchOptions.signal would replace the timeout
+ // signal, so the timeout could never abort the request.
+ const server = await createHttpServer(async (_, res) => {
+ await setTimeout(200)
+ res.end(JSON.stringify({ id: 0, jsonrpc: '2.0', result: 'wagmi' }))
+ })
+
+ const controller = new AbortController()
+ const transport = RpcTransport.fromHttp(server.url, {
+ timeout: 50,
+ fetchOptions: {
+ signal: controller.signal,
+ },
+ })
+
+ await expect(() =>
+ transport.request({ method: 'eth_accounts' }),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
+ '[Promise.TimeoutError: Operation timed out.]',
+ )
+
+ server.close()
+ })
})
test('exports', () => {
diff --git a/src/core/_test/internal/promise.test.ts b/src/core/_test/internal/promise.test.ts
index 0e0ffcb5..cf6014b6 100644
--- a/src/core/_test/internal/promise.test.ts
+++ b/src/core/_test/internal/promise.test.ts
@@ -35,4 +35,30 @@ describe('withTimeout', () => {
server.close()
})
+
+ test('behavior: does not double-reject on inner error', async () => {
+ // Regression: the catch path used to call reject() twice when fn threw
+ // a non-AbortError. The unhandled rejection would crash the process.
+ const innerError = new Error('inner failure')
+ let unhandled: unknown
+ const onUnhandled = (reason: unknown) => {
+ unhandled = reason
+ }
+ process.on('unhandledRejection', onUnhandled)
+ try {
+ await expect(() =>
+ withTimeout(
+ async () => {
+ throw innerError
+ },
+ { timeout: 1000 },
+ ),
+ ).rejects.toBe(innerError)
+ // Allow microtasks to flush so a stray reject would surface.
+ await new Promise((resolve) => setImmediate(resolve))
+ expect(unhandled).toBe(undefined)
+ } finally {
+ process.off('unhandledRejection', onUnhandled)
+ }
+ })
})
diff --git a/src/erc4337/UserOperation.ts b/src/erc4337/UserOperation.ts
index 813ee519..6d7e8cc9 100644
--- a/src/erc4337/UserOperation.ts
+++ b/src/erc4337/UserOperation.ts
@@ -330,6 +330,7 @@ export declare namespace from {
* @returns An instantiated {@link ox#UserOperation.UserOperation}.
*/
export function fromRpc(rpc: Rpc): UserOperation {
+ const authorization = (rpc as Rpc<'0.8'>).authorization
return {
...rpc,
callGasLimit: BigInt(rpc.callGasLimit),
@@ -344,6 +345,9 @@ export function fromRpc(rpc: Rpc): UserOperation {
...(rpc.paymasterVerificationGasLimit && {
paymasterVerificationGasLimit: BigInt(rpc.paymasterVerificationGasLimit),
}),
+ ...(authorization && {
+ authorization: Authorization.fromRpc(authorization as Authorization.Rpc),
+ }),
} as UserOperation
}
diff --git a/src/erc4337/_test/UserOperation.test.ts b/src/erc4337/_test/UserOperation.test.ts
index cb0720d8..d4f2a43e 100644
--- a/src/erc4337/_test/UserOperation.test.ts
+++ b/src/erc4337/_test/UserOperation.test.ts
@@ -1443,3 +1443,60 @@ describe('toTypedData', () => {
})
})
})
+
+describe('v0.8 authorization round-trip', () => {
+ const userOperation = {
+ authorization: {
+ address: '0x1234567890123456789012345678901234567890',
+ chainId: 1,
+ nonce: 0n,
+ yParity: 0,
+ r: 1n,
+ s: 2n,
+ },
+ callData: '0xdeadbeef',
+ callGasLimit: 300_000n,
+ maxFeePerGas: 100_000n,
+ maxPriorityFeePerGas: 100_000n,
+ nonce: 0n,
+ preVerificationGas: 100_000n,
+ sender: '0x1234567890123456789012345678901234567890',
+ signature: '0x',
+ verificationGasLimit: 100_000n,
+ } as const satisfies UserOperation.UserOperation<'0.8', true>
+
+ test('toRpc serializes authorization', () => {
+ const rpc = UserOperation.toRpc(userOperation) as UserOperation.Rpc<'0.8'>
+ expect(rpc.authorization).toMatchInlineSnapshot(`
+ {
+ "address": "0x1234567890123456789012345678901234567890",
+ "chainId": "0x1",
+ "nonce": "0x0",
+ "r": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "s": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "yParity": "0x0",
+ }
+ `)
+ })
+
+ test('fromRpc parses authorization', () => {
+ const rpc = UserOperation.toRpc(userOperation) as UserOperation.Rpc<'0.8'>
+ const parsed = UserOperation.fromRpc(rpc) as UserOperation.UserOperation<
+ '0.8',
+ true
+ >
+ expect(parsed.authorization).toEqual(userOperation.authorization)
+ })
+
+ test('round-trip preserves authorization', () => {
+ const rpc = UserOperation.toRpc(userOperation)
+ const parsed = UserOperation.fromRpc(rpc)
+ expect(parsed).toEqual(userOperation)
+ })
+
+ test('toRpc omits authorization when absent', () => {
+ const { authorization: _omit, ...rest } = userOperation
+ const rpc = UserOperation.toRpc(rest)
+ expect('authorization' in rpc).toBe(false)
+ })
+})
diff --git a/src/erc4337/_test/UserOperationGas.test.ts b/src/erc4337/_test/UserOperationGas.test.ts
index 259fc215..d8c9a5bb 100644
--- a/src/erc4337/_test/UserOperationGas.test.ts
+++ b/src/erc4337/_test/UserOperationGas.test.ts
@@ -72,3 +72,24 @@ describe('toRpc', () => {
`)
})
})
+
+describe('v0.8', () => {
+ test('round-trips matching v0.7 shape', () => {
+ const v08 = {
+ callGasLimit: 300_000n,
+ paymasterPostOpGasLimit: 100_000n,
+ paymasterVerificationGasLimit: 100_000n,
+ preVerificationGas: 100_000n,
+ verificationGasLimit: 100_000n,
+ } as const satisfies UserOperationGas.UserOperationGas<'0.8'>
+
+ const rpc = UserOperationGas.toRpc(
+ v08,
+ ) as UserOperationGas.Rpc<'0.8'>
+ const parsed = UserOperationGas.fromRpc(
+ rpc,
+ ) as UserOperationGas.UserOperationGas<'0.8'>
+
+ expect(parsed).toEqual(v08)
+ })
+})
diff --git a/src/erc6492/_test/SignatureErc6492.test.ts b/src/erc6492/_test/SignatureErc6492.test.ts
index 0bc09ca2..7016a235 100644
--- a/src/erc6492/_test/SignatureErc6492.test.ts
+++ b/src/erc6492/_test/SignatureErc6492.test.ts
@@ -116,3 +116,46 @@ describe('validate', () => {
expect(SignatureErc6492.validate('0xdeadbeef')).toBe(false)
})
})
+
+describe('unwrap: strips trailing magic bytes', () => {
+ test('round-trip with long signature payload', () => {
+ const args = {
+ data: '0xdeadbeef',
+ signature: `0x${'ab'.repeat(96)}`,
+ to: '0xcafebabecafebabecafebabecafebabecafebabe',
+ } as const
+
+ const wrapped = SignatureErc6492.wrap(args)
+ expect(wrapped.endsWith(SignatureErc6492.magicBytes.slice(2))).toBe(true)
+ const unwrapped = SignatureErc6492.unwrap(wrapped)
+ expect(unwrapped).toEqual(args)
+ })
+})
+
+describe('from: validates object inputs', () => {
+ test('throws on malformed object', () => {
+ expect(() =>
+ // @ts-expect-error
+ SignatureErc6492.from({ data: '0xdeadbeef', signature: '0x00' }),
+ ).toThrow(SignatureErc6492.InvalidUnwrappedSignatureError)
+
+ expect(() =>
+ // @ts-expect-error
+ SignatureErc6492.from({}),
+ ).toThrow(SignatureErc6492.InvalidUnwrappedSignatureError)
+
+ expect(() =>
+ // @ts-expect-error
+ SignatureErc6492.from(null),
+ ).toThrow(SignatureErc6492.InvalidUnwrappedSignatureError)
+ })
+
+ test('accepts valid object', () => {
+ const args = {
+ data: '0xdeadbeef',
+ signature: '0x00',
+ to: '0xcafebabecafebabecafebabecafebabecafebabe',
+ } as const
+ expect(SignatureErc6492.from(args)).toEqual(args)
+ })
+})
diff --git a/src/erc8010/_test/SignatureErc8010.test.ts b/src/erc8010/_test/SignatureErc8010.test.ts
index d010b8fb..659d97bc 100644
--- a/src/erc8010/_test/SignatureErc8010.test.ts
+++ b/src/erc8010/_test/SignatureErc8010.test.ts
@@ -147,3 +147,65 @@ describe('validate', () => {
expect(SignatureErc8010.validate('0xdeadbeef')).toBe(false)
})
})
+
+describe('assert: validates unwrapped objects', () => {
+ test('throws on malformed object', () => {
+ expect(() =>
+ // @ts-expect-error
+ SignatureErc8010.assert(null),
+ ).toThrow(SignatureErc8010.InvalidUnwrappedSignatureError)
+
+ expect(() =>
+ // @ts-expect-error
+ SignatureErc8010.assert({ authorization, data: '0xdeadbeef' }),
+ ).toThrow(SignatureErc8010.InvalidUnwrappedSignatureError)
+
+ expect(() =>
+ SignatureErc8010.assert({
+ // @ts-expect-error
+ authorization: null,
+ signature,
+ }),
+ ).toThrow(SignatureErc8010.InvalidUnwrappedSignatureError)
+ })
+})
+
+describe('wrap: skips recovery when `to` is provided', () => {
+ test('uses caller-supplied `to` verbatim', () => {
+ const customTo = '0xcafebabecafebabecafebabecafebabecafebabe' as const
+ const wrapped = SignatureErc8010.wrap({
+ authorization,
+ data: '0xdeadbeef',
+ signature,
+ to: customTo,
+ })
+ const unwrapped = SignatureErc8010.unwrap(wrapped)
+ expect(unwrapped.to).toBe(customTo)
+ })
+
+ test('still recovers when `to` is absent', () => {
+ const wrapped = SignatureErc8010.wrap({
+ authorization,
+ data: '0xdeadbeef',
+ signature,
+ })
+ const unwrapped = SignatureErc8010.unwrap(wrapped)
+ expect(unwrapped.to).toBe(accounts[0].address)
+ })
+})
+
+describe('unwrap: rejects oversized suffix length', () => {
+ test('throws InvalidWrappedSignatureError on out-of-range suffix length', () => {
+ // Construct a malicious wrapped value: short signature + impossibly large
+ // suffix length word + magic bytes. The naive Number(hex) parse used to
+ // produce a valid slice; the safe parse must reject.
+ const shortSig = `0x${'00'.repeat(8)}`
+ const huge = `0x${'ff'.repeat(32)}`
+ const malicious = (shortSig +
+ huge.slice(2) +
+ SignatureErc8010.magicBytes.slice(2)) as `0x${string}`
+ expect(() => SignatureErc8010.unwrap(malicious)).toThrow(
+ SignatureErc8010.InvalidWrappedSignatureError,
+ )
+ })
+})
diff --git a/src/webauthn/Authentication.ts b/src/webauthn/Authentication.ts
index f9a32ff3..9d9edef2 100644
--- a/src/webauthn/Authentication.ts
+++ b/src/webauthn/Authentication.ts
@@ -1,5 +1,6 @@
import * as Base64 from '../core/Base64.js'
import * as Bytes from '../core/Bytes.js'
+import * as Cbor from '../core/Cbor.js'
import * as Errors from '../core/Errors.js'
import * as Hash from '../core/Hash.js'
import * as Hex from '../core/Hex.js'
@@ -625,6 +626,21 @@ export function verify(options: verify.Options): boolean {
// the BS bit is not set.
if ((flag & 0x08) !== 0x08 && (flag & 0x10) === 0x10) return false
+ // Authentication assertions must not carry attested credential data
+ // (AT bit). If AT is set, the structure is invalid for an assertion.
+ if ((flag & 0x40) === 0x40) return false
+
+ // If the ED bit is set, trailing extension bytes must be a valid CBOR
+ // map. Reject malformed extensions.
+ if ((flag & 0x80) === 0x80) {
+ if (authenticatorDataBytes.length <= 37) return false
+ try {
+ Cbor.decode(authenticatorDataBytes.slice(37))
+ } catch {
+ return false
+ }
+ }
+
// Parse clientDataJSON for validation.
const clientData = JSON.parse(clientDataJSON)
From 2043ea0ede7f8af8b071637e066ccfeac62f9c91 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:19:32 +1000
Subject: [PATCH 039/192] fix(abi): validate fixed-array length and pad
string[]/bytes[] in AbiParameters.encodePacked
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-9d2614e4f981
---
.changeset/wave-0-abi-parameters-encode-packed.md | 5 +++++
src/erc4337/_test/UserOperationGas.test.ts | 4 +---
2 files changed, 6 insertions(+), 3 deletions(-)
create mode 100644 .changeset/wave-0-abi-parameters-encode-packed.md
diff --git a/.changeset/wave-0-abi-parameters-encode-packed.md b/.changeset/wave-0-abi-parameters-encode-packed.md
new file mode 100644
index 00000000..30ef590f
--- /dev/null
+++ b/.changeset/wave-0-abi-parameters-encode-packed.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Fixed `AbiParameters.encodePacked` to validate fixed-array lengths and to right-pad `string[]` and `bytes[]` elements to a 32-byte boundary, matching the Solidity packed-encoding specification.
diff --git a/src/erc4337/_test/UserOperationGas.test.ts b/src/erc4337/_test/UserOperationGas.test.ts
index d8c9a5bb..78de74e9 100644
--- a/src/erc4337/_test/UserOperationGas.test.ts
+++ b/src/erc4337/_test/UserOperationGas.test.ts
@@ -83,9 +83,7 @@ describe('v0.8', () => {
verificationGasLimit: 100_000n,
} as const satisfies UserOperationGas.UserOperationGas<'0.8'>
- const rpc = UserOperationGas.toRpc(
- v08,
- ) as UserOperationGas.Rpc<'0.8'>
+ const rpc = UserOperationGas.toRpc(v08) as UserOperationGas.Rpc<'0.8'>
const parsed = UserOperationGas.fromRpc(
rpc,
) as UserOperationGas.UserOperationGas<'0.8'>
From 708e094ba6b14ebd92e31798ac93102a62a9c5b4 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:19:42 +1000
Subject: [PATCH 040/192] fix(transactions): preserve transactionIndex 0 in
Transaction.toRpc
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-a8a740d3ed8f
---
...-transaction-rpc-transaction-index-zero.md | 5 ++++
src/core/Transaction.ts | 7 +++---
src/core/_test/Transaction.test.ts | 24 +++++++++++++++++++
src/core/_test/WebCryptoP256.test.ts | 3 ++-
4 files changed, 35 insertions(+), 4 deletions(-)
create mode 100644 .changeset/wave-0-transactions-transaction-rpc-transaction-index-zero.md
diff --git a/.changeset/wave-0-transactions-transaction-rpc-transaction-index-zero.md b/.changeset/wave-0-transactions-transaction-rpc-transaction-index-zero.md
new file mode 100644
index 00000000..ef92710c
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Transaction.ts b/src/core/Transaction.ts
index ff5ab9dc..b8d667a8 100644
--- a/src/core/Transaction.ts
+++ b/src/core/Transaction.ts
@@ -383,9 +383,10 @@ export function toRpc(
rpc.input = transaction.input
rpc.nonce = Hex.fromNumber(transaction.nonce ?? 0n)
rpc.to = transaction.to
- rpc.transactionIndex = transaction.transactionIndex
- ? Hex.fromNumber(transaction.transactionIndex)
- : null
+ rpc.transactionIndex =
+ typeof transaction.transactionIndex === 'number'
+ ? Hex.fromNumber(transaction.transactionIndex)
+ : null
rpc.type = (toRpcType as any)[transaction.type] ?? transaction.type
rpc.value = Hex.fromNumber(transaction.value ?? 0n)
diff --git a/src/core/_test/Transaction.test.ts b/src/core/_test/Transaction.test.ts
index 86ece602..eb907946 100644
--- a/src/core/_test/Transaction.test.ts
+++ b/src/core/_test/Transaction.test.ts
@@ -1224,6 +1224,30 @@ describe('toRpc', () => {
}
`)
})
+
+ test('behavior: transactionIndex 0', () => {
+ const rpc = Transaction.toRpc({
+ blockHash:
+ '0xc350d807505fb835650f0013632c5515592987ba169bbc6626d9fc54d91f0f0b',
+ blockNumber: 19868015n,
+ chainId: 1,
+ from: '0x814e5e0e31016b9a7f138c76b7e7b2bb5c1ab6a6',
+ gas: 21000n,
+ gasPrice: 1n,
+ hash: '0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0',
+ input: '0x',
+ nonce: 0n,
+ r: 1n,
+ s: 2n,
+ to: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad',
+ transactionIndex: 0,
+ type: 'legacy',
+ v: 27,
+ value: 0n,
+ yParity: 0,
+ })
+ expect(rpc.transactionIndex).toBe('0x0')
+ })
})
describe('eip1559', () => {
diff --git a/src/core/_test/WebCryptoP256.test.ts b/src/core/_test/WebCryptoP256.test.ts
index 638d1267..cd04547d 100644
--- a/src/core/_test/WebCryptoP256.test.ts
+++ b/src/core/_test/WebCryptoP256.test.ts
@@ -155,7 +155,7 @@ describe('getSharedSecret', () => {
publicKey: publicKeyB,
}),
).rejects.toThrowErrorMatchingInlineSnapshot(
- '[Error: privateKey is not compatible with ECDH. please use `createKeyPairECDH` to create an ECDH key.]',
+ '[WebCryptoP256.InvalidPrivateKeyAlgorithmError: privateKey is not compatible with ECDH. Please use `createKeyPairECDH` to create an ECDH key.]',
)
})
@@ -219,6 +219,7 @@ test('exports', () => {
"getSharedSecret",
"sign",
"verify",
+ "InvalidPrivateKeyAlgorithmError",
]
`)
})
From f2daa75125d94ed6e6d11097db78d91e19396077 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:20:23 +1000
Subject: [PATCH 041/192] fix(abi): always hash indexed string/bytes topics to
hex in AbiEvent
---
...ave-0-abi-event-hex-topic-normalization.md | 5 ++++
src/core/AbiEvent.ts | 24 +++++++++++++------
src/core/P256.ts | 5 ++--
src/core/Secp256k1.ts | 5 ++--
src/core/WebCryptoP256.ts | 9 +++++--
5 files changed, 35 insertions(+), 13 deletions(-)
create mode 100644 .changeset/wave-0-abi-event-hex-topic-normalization.md
diff --git a/.changeset/wave-0-abi-event-hex-topic-normalization.md b/.changeset/wave-0-abi-event-hex-topic-normalization.md
new file mode 100644
index 00000000..36d42035
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/AbiEvent.ts b/src/core/AbiEvent.ts
index d4457ec4..89ee8585 100644
--- a/src/core/AbiEvent.ts
+++ b/src/core/AbiEvent.ts
@@ -137,8 +137,14 @@ export function assertArgs(
if (input.type === 'address')
return Address.isEqual(value as Address.Address, arg as Address.Address)
if (input.type === 'string')
- return Hash.keccak256(Bytes.fromString(value as string)) === arg
- if (input.type === 'bytes') return Hash.keccak256(value as Hex.Hex) === arg
+ return (
+ Hash.keccak256(Bytes.fromString(value as string), { as: 'Hex' }) === arg
+ )
+ if (input.type === 'bytes') {
+ const hex =
+ typeof value === 'string' ? (value as Hex.Hex) : Hex.fromBytes(value as Bytes.Bytes)
+ return Hash.keccak256(hex, { as: 'Hex' }) === arg
+ }
return value === arg
}
@@ -664,8 +670,14 @@ export function encode(
if (args_.length > 0) {
const encode = (param: abitype.AbiParameter, value: unknown) => {
if (param.type === 'string')
- return Hash.keccak256(Hex.fromString(value as string))
- if (param.type === 'bytes') return Hash.keccak256(value as Hex.Hex)
+ return Hash.keccak256(Hex.fromString(value as string), { as: 'Hex' })
+ if (param.type === 'bytes') {
+ const hex =
+ typeof value === 'string'
+ ? (value as Hex.Hex)
+ : Hex.fromBytes(value as Bytes.Bytes)
+ return Hash.keccak256(hex, { as: 'Hex' })
+ }
if (param.type === 'tuple' || param.type.match(/^(.*)\[(\d+)?\]$/))
throw new FilterTypeNotSupportedError(param.type)
return AbiParameters.encode([param], [value])
@@ -712,9 +724,7 @@ export declare namespace encode {
type ReturnType = {
topics:
- | Compute<
- [selector: Hex.Hex, ...(Hex.Hex | readonly Hex.Hex[] | null)[]]
- >
+ | Compute<[selector: Hex.Hex, ...(Hex.Hex | readonly Hex.Hex[] | null)[]]>
| readonly (Hex.Hex | readonly Hex.Hex[] | null)[]
}
diff --git a/src/core/P256.ts b/src/core/P256.ts
index 62681cdf..4014be88 100644
--- a/src/core/P256.ts
+++ b/src/core/P256.ts
@@ -277,8 +277,9 @@ export function sign(options: sign.Options): Signature.Signature {
export declare namespace sign {
type Options = {
/**
- * Extra entropy to add to the signing process. Setting to `false` will disable it.
- * @default true
+ * Extra entropy to add to the signing process. Setting to `true` enables hedged
+ * (RFC 6979 + extra randomness) signing.
+ * @default false
*/
extraEntropy?: boolean | Hex.Hex | Bytes.Bytes | undefined
/**
diff --git a/src/core/Secp256k1.ts b/src/core/Secp256k1.ts
index 4763605c..c245fef5 100644
--- a/src/core/Secp256k1.ts
+++ b/src/core/Secp256k1.ts
@@ -319,8 +319,9 @@ export function sign(options: sign.Options): Signature.Signature {
export declare namespace sign {
type Options = {
/**
- * Extra entropy to add to the signing process. Setting to `false` will disable it.
- * @default true
+ * Extra entropy to add to the signing process. Setting to `true` enables hedged
+ * (RFC 6979 + extra randomness) signing.
+ * @default false
*/
extraEntropy?: boolean | Hex.Hex | Bytes.Bytes | undefined
/**
diff --git a/src/core/WebCryptoP256.ts b/src/core/WebCryptoP256.ts
index 4deab9df..52a57a6a 100644
--- a/src/core/WebCryptoP256.ts
+++ b/src/core/WebCryptoP256.ts
@@ -14,7 +14,7 @@ const N = p256.Point.CURVE().n
*
* - a `privateKey` of type [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
*
- * - a `publicKey` of type {@link ox#Hex.Hex} or {@link ox#Bytes.Bytes}
+ * - a `publicKey` of type {@link ox#PublicKey.PublicKey}
*
* @example
* ```ts twoslash
@@ -212,6 +212,11 @@ export declare namespace getSharedSecret {
/**
* Signs a payload with the provided `CryptoKey` private key and returns a P256 signature.
*
+ * @remarks
+ * Web Crypto may emit ECDSA signatures with `s` in the upper half of the curve
+ * order. ox always normalizes the result to a low-S signature so it round-trips
+ * with {@link ox#WebCryptoP256.(verify:function)} and other ox ECDSA verifiers.
+ *
* @example
* ```ts twoslash
* import { WebCryptoP256 } from 'ox'
@@ -229,7 +234,7 @@ export declare namespace getSharedSecret {
* ```
*
* @param options - Options for signing the payload.
- * @returns The P256 ECDSA {@link ox#Signature.Signature}.
+ * @returns The P256 ECDSA {@link ox#Signature.Signature} (always low-S normalized).
*/
export async function sign(
options: sign.Options,
From 9fdaeee4057531238c8856f5385ee1010105a741 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:20:31 +1000
Subject: [PATCH 042/192] fix(block): throw MissingFieldError on required
fields in fromRpc and preserve totalDifficulty as undefined
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b2649a371d7f
---
...ock-state-block-fromrpc-required-fields.md | 5 ++
src/core/Block.ts | 34 ++++++--
src/core/_test/Block.test.ts | 83 +++++++++----------
3 files changed, 71 insertions(+), 51 deletions(-)
create mode 100644 .changeset/wave-0-block-state-block-fromrpc-required-fields.md
diff --git a/.changeset/wave-0-block-state-block-fromrpc-required-fields.md b/.changeset/wave-0-block-state-block-fromrpc-required-fields.md
new file mode 100644
index 00000000..ff78a4fb
--- /dev/null
+++ b/.changeset/wave-0-block-state-block-fromrpc-required-fields.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Made `Block.fromRpc` throw `Block.MissingFieldError` when a required Block field is absent and preserved `totalDifficulty` as `undefined` instead of silently coercing missing required fields and the optional `totalDifficulty` to `0n`.
diff --git a/src/core/Block.ts b/src/core/Block.ts
index d4011a24..aea9c65d 100644
--- a/src/core/Block.ts
+++ b/src/core/Block.ts
@@ -1,5 +1,5 @@
import type * as Address from './Address.js'
-import type * as Errors from './Errors.js'
+import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import type { Compute, OneOf } from './internal/types.js'
import * as Transaction from './Transaction.js'
@@ -299,13 +299,17 @@ export function fromRpc<
excessBlobGas: block.excessBlobGas
? BigInt(block.excessBlobGas)
: undefined,
- gasLimit: BigInt(block.gasLimit ?? 0n),
- gasUsed: BigInt(block.gasUsed ?? 0n),
+ gasLimit: requiredBigInt(block.gasLimit, 'gasLimit'),
+ gasUsed: requiredBigInt(block.gasUsed, 'gasUsed'),
number: block.number ? BigInt(block.number) : null,
- size: BigInt(block.size ?? 0n),
+ size: requiredBigInt(block.size, 'size'),
stateRoot: block.stateRoot,
- timestamp: BigInt(block.timestamp ?? 0n),
- totalDifficulty: BigInt(block.totalDifficulty ?? 0n),
+ timestamp: requiredBigInt(block.timestamp, 'timestamp'),
+ totalDifficulty:
+ typeof block.totalDifficulty !== 'undefined' &&
+ block.totalDifficulty !== null
+ ? BigInt(block.totalDifficulty)
+ : undefined,
transactions,
withdrawals: block.withdrawals?.map(Withdrawal.fromRpc),
} as Block as never
@@ -320,5 +324,21 @@ export declare namespace fromRpc {
includeTransactions?: includeTransactions | boolean | undefined
}
- type ErrorType = Errors.GlobalErrorType
+ type ErrorType = MissingFieldError | Errors.GlobalErrorType
+}
+
+/** Thrown when a required Block field is missing in an RPC response. */
+export class MissingFieldError extends Errors.BaseError {
+ override readonly name = 'Block.MissingFieldError'
+
+ constructor({ field }: { field: string }) {
+ super(`Required Block field \`${field}\` is missing.`)
+ }
+}
+
+/** @internal */
+function requiredBigInt(value: Hex.Hex | bigint | undefined, field: string) {
+ if (typeof value === 'undefined' || value === null)
+ throw new MissingFieldError({ field })
+ return BigInt(value)
}
diff --git a/src/core/_test/Block.test.ts b/src/core/_test/Block.test.ts
index e82b207e..b1d155bd 100644
--- a/src/core/_test/Block.test.ts
+++ b/src/core/_test/Block.test.ts
@@ -83,70 +83,64 @@ describe('fromRpc', () => {
expect(block).toBeNull()
})
- test('behavior: nullish values', () => {
- // @ts-expect-error
+ test('behavior: missing required field throws', () => {
+ expect(() =>
+ // @ts-expect-error
+ Block.fromRpc({
+ extraData: '0x',
+ hash: '0xebc3644804e4040c0a74c5a5bbbc6b46a71a5d4010fe0c92ebb2fdf4a43ea5dd',
+ logsBloom: '0x',
+ miner: '0x0000000000000000000000000000000000000000',
+ mixHash:
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
+ nonce: '0x0000000000000000',
+ parentHash:
+ '0xe55516ad8029e53cd32087f14653d851401b05245abb1b2d6ed4ddcc597ac5a6',
+ receiptsRoot:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ sha3Uncles:
+ '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
+ stateRoot:
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
+ transactions: [],
+ transactionsRoot:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ uncles: [],
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[Block.MissingFieldError: Required Block field `gasLimit` is missing.]',
+ )
+ })
+
+ test('behavior: optional totalDifficulty preserved as undefined', () => {
const block = Block.fromRpc({
+ // @ts-expect-error totalDifficulty is omitted on purpose
extraData: '0x',
+ gasLimit: '0x1c9c347',
+ gasUsed: '0x0',
hash: '0xebc3644804e4040c0a74c5a5bbbc6b46a71a5d4010fe0c92ebb2fdf4a43ea5dd',
- logsBloom:
- '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ logsBloom: '0x',
miner: '0x0000000000000000000000000000000000000000',
mixHash:
'0x0000000000000000000000000000000000000000000000000000000000000000',
nonce: '0x0000000000000000',
+ number: '0xec6fc6',
parentHash:
'0xe55516ad8029e53cd32087f14653d851401b05245abb1b2d6ed4ddcc597ac5a6',
receiptsRoot:
'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
- sealFields: [
- '0x0000000000000000000000000000000000000000000000000000000000000000',
- '0x0000000000000000',
- ],
sha3Uncles:
'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
+ size: '0x208',
stateRoot:
'0x0000000000000000000000000000000000000000000000000000000000000000',
+ timestamp: '0x63198f6f',
transactions: [],
transactionsRoot:
'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
uncles: [],
- withdrawals: [],
- withdrawalsRoot:
- '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
})
- expect(block).toMatchInlineSnapshot(`
- {
- "baseFeePerGas": undefined,
- "blobGasUsed": undefined,
- "difficulty": undefined,
- "excessBlobGas": undefined,
- "extraData": "0x",
- "gasLimit": 0n,
- "gasUsed": 0n,
- "hash": "0xebc3644804e4040c0a74c5a5bbbc6b46a71a5d4010fe0c92ebb2fdf4a43ea5dd",
- "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "miner": "0x0000000000000000000000000000000000000000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0000000000000000",
- "number": null,
- "parentHash": "0xe55516ad8029e53cd32087f14653d851401b05245abb1b2d6ed4ddcc597ac5a6",
- "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "sealFields": [
- "0x0000000000000000000000000000000000000000000000000000000000000000",
- "0x0000000000000000",
- ],
- "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": 0n,
- "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "timestamp": 0n,
- "totalDifficulty": 0n,
- "transactions": [],
- "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- "uncles": [],
- "withdrawals": [],
- "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
- }
- `)
+ expect(block?.totalDifficulty).toBeUndefined()
})
test('behavior: network', async () => {
@@ -672,6 +666,7 @@ test('exports', () => {
[
"toRpc",
"fromRpc",
+ "MissingFieldError",
]
`)
})
From c2d18486abec1649ff255b04d39fb9e3d368a1e7 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:20:59 +1000
Subject: [PATCH 043/192] fix(kzg): preserve receiver semantics in Kzg.from
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-99b84f570f29
---
.changeset/wave-0-crypto-kzg-from-receiver.md | 5 +++++
src/core/Kzg.ts | 6 +++---
src/core/_test/Kzg.test.ts | 5 +----
3 files changed, 9 insertions(+), 7 deletions(-)
create mode 100644 .changeset/wave-0-crypto-kzg-from-receiver.md
diff --git a/.changeset/wave-0-crypto-kzg-from-receiver.md b/.changeset/wave-0-crypto-kzg-from-receiver.md
new file mode 100644
index 00000000..c77a2e0d
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Kzg.ts b/src/core/Kzg.ts
index 14c533fd..28926875 100644
--- a/src/core/Kzg.ts
+++ b/src/core/Kzg.ts
@@ -36,10 +36,10 @@ export type Kzg = {
* @returns The KZG interface object.
*/
export function from(value: Kzg): Kzg {
- const { blobToKzgCommitment, computeBlobKzgProof } = value
return {
- blobToKzgCommitment,
- computeBlobKzgProof,
+ blobToKzgCommitment: (blob) => value.blobToKzgCommitment(blob),
+ computeBlobKzgProof: (blob, commitment) =>
+ value.computeBlobKzgProof(blob, commitment),
}
}
diff --git a/src/core/_test/Kzg.test.ts b/src/core/_test/Kzg.test.ts
index 9404ee83..deb6d6a8 100644
--- a/src/core/_test/Kzg.test.ts
+++ b/src/core/_test/Kzg.test.ts
@@ -112,10 +112,7 @@ test('from: preserves `this` binding for method-style implementations', () => {
blobToKzgCommitment(blob: Uint8Array): Uint8Array {
return new Uint8Array([...blob.slice(0, 1), ...this.suffix])
}
- computeBlobKzgProof(
- blob: Uint8Array,
- commitment: Uint8Array,
- ): Uint8Array {
+ computeBlobKzgProof(blob: Uint8Array, commitment: Uint8Array): Uint8Array {
return new Uint8Array([
...blob.slice(0, 1),
...commitment.slice(0, 1),
From 362490b9886f57c538aca329134b8792b939ed7e Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:21:05 +1000
Subject: [PATCH 044/192] fix(abi): throw on selector-only calldata, fast event
partition, reject trailing signature garbage
---
.../wave-0-abi-event-decode-fast-partition.md | 5 ++++
...e-0-abi-function-selector-only-calldata.md | 5 ++++
...wave-0-abi-normalize-signature-trailing.md | 5 ++++
src/core/AbiEvent.ts | 23 +++++++++++++++----
src/core/AbiFunction.ts | 6 +++++
src/core/internal/abiItem.ts | 10 ++++++++
6 files changed, 50 insertions(+), 4 deletions(-)
create mode 100644 .changeset/wave-0-abi-event-decode-fast-partition.md
create mode 100644 .changeset/wave-0-abi-function-selector-only-calldata.md
create mode 100644 .changeset/wave-0-abi-normalize-signature-trailing.md
diff --git a/.changeset/wave-0-abi-event-decode-fast-partition.md b/.changeset/wave-0-abi-event-decode-fast-partition.md
new file mode 100644
index 00000000..2819a79c
--- /dev/null
+++ b/.changeset/wave-0-abi-event-decode-fast-partition.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Fixed `AbiEvent.decode` to partition `indexed` and non-`indexed` inputs in a single pass and to look up each non-indexed input's original position via a precomputed index map instead of `inputs.indexOf(...)`.
diff --git a/.changeset/wave-0-abi-function-selector-only-calldata.md b/.changeset/wave-0-abi-function-selector-only-calldata.md
new file mode 100644
index 00000000..f8f8ba6d
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-abi-normalize-signature-trailing.md b/.changeset/wave-0-abi-normalize-signature-trailing.md
new file mode 100644
index 00000000..783963e2
--- /dev/null
+++ b/.changeset/wave-0-abi-normalize-signature-trailing.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Fixed `internal.normalizeSignature` to reject trailing characters after the closing parenthesis of an ABI item signature instead of silently truncating them.
diff --git a/src/core/AbiEvent.ts b/src/core/AbiEvent.ts
index 89ee8585..a2825b5a 100644
--- a/src/core/AbiEvent.ts
+++ b/src/core/AbiEvent.ts
@@ -142,7 +142,9 @@ export function assertArgs(
)
if (input.type === 'bytes') {
const hex =
- typeof value === 'string' ? (value as Hex.Hex) : Hex.fromBytes(value as Bytes.Bytes)
+ typeof value === 'string'
+ ? (value as Hex.Hex)
+ : Hex.fromBytes(value as Bytes.Bytes)
return Hash.keccak256(hex, { as: 'Hex' }) === arg
}
return value === arg
@@ -390,8 +392,22 @@ export function decode(
let args: any = isUnnamed ? [] : {}
+ // Single-pass partition: keep both the input and its original index so we
+ // don't have to call `inputs.indexOf(...)` per non-indexed entry below
+ // (which is O(n^2) on event width).
+ const indexedInputs: abitype.AbiEventParameter[] = []
+ const nonIndexedInputs: abitype.AbiEventParameter[] = []
+ const nonIndexedOriginalIndex: number[] = []
+ for (let i = 0; i < inputs.length; i++) {
+ const input = inputs[i]!
+ if ('indexed' in input && input.indexed) indexedInputs.push(input)
+ else {
+ nonIndexedInputs.push(input)
+ nonIndexedOriginalIndex.push(i)
+ }
+ }
+
// Decode topics (indexed args).
- const indexedInputs = inputs.filter((x) => 'indexed' in x && x.indexed)
for (let i = 0; i < indexedInputs.length; i++) {
const param = indexedInputs[i]!
const topic = argTopics[i]
@@ -414,7 +430,6 @@ export function decode(
}
// Decode data (non-indexed args).
- const nonIndexedInputs = inputs.filter((x) => !('indexed' in x && x.indexed))
if (nonIndexedInputs.length > 0) {
if (data && data !== '0x') {
try {
@@ -423,7 +438,7 @@ export function decode(
if (isUnnamed) args = [...args, ...decodedData]
else {
for (let i = 0; i < nonIndexedInputs.length; i++) {
- const index = inputs.indexOf(nonIndexedInputs[i]!)
+ const index = nonIndexedOriginalIndex[i]!
args[nonIndexedInputs[i]!.name! || index] = decodedData[i]
}
}
diff --git a/src/core/AbiFunction.ts b/src/core/AbiFunction.ts
index cc3dca5e..46c99cbd 100644
--- a/src/core/AbiFunction.ts
+++ b/src/core/AbiFunction.ts
@@ -163,6 +163,12 @@ export function decodeData(
? fromAbi([abiFunction, ...overloads], data as never)
: abiFunction
+ if (item.inputs.length > 0 && Hex.size(data) <= 4)
+ throw new AbiParameters.DataSizeTooSmallError({
+ data,
+ parameters: item.inputs as never,
+ size: Math.max(0, Hex.size(data) - 4),
+ })
if (Hex.size(data) <= 4) return undefined
return AbiParameters.decode(item.inputs, Hex.slice(data, 4))
}
diff --git a/src/core/internal/abiItem.ts b/src/core/internal/abiItem.ts
index 23043ee4..2bf5c782 100644
--- a/src/core/internal/abiItem.ts
+++ b/src/core/internal/abiItem.ts
@@ -480,6 +480,16 @@ export function normalizeSignature(signature: string): string {
if (!valid) throw new Errors.BaseError('Unable to normalize signature.')
+ // Reject trailing characters after the closing paren of the top-level
+ // parameter list. The loop above breaks at the first `)` at level 0,
+ // so any remaining non-whitespace input means the signature is malformed.
+ for (let j = i + 1; j < signature.length; j++) {
+ if (signature[j] !== ' ')
+ throw new Errors.BaseError(
+ `Unable to normalize signature: trailing characters after closing parenthesis: ${signature.slice(j)}`,
+ )
+ }
+
return result
}
From c2ed87d40536f26a3ff91f8e2cd9895215803ca3 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:21:33 +1000
Subject: [PATCH 045/192] fix(abi): hoist normalizeSignature loop counter to
allow trailing-garbage check
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-9d2614e4f981
---
src/core/internal/abiItem.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/core/internal/abiItem.ts b/src/core/internal/abiItem.ts
index 2bf5c782..4650fc9d 100644
--- a/src/core/internal/abiItem.ts
+++ b/src/core/internal/abiItem.ts
@@ -433,8 +433,9 @@ export function normalizeSignature(signature: string): string {
let level = 0
let result = ''
let valid = false
+ let i = 0
- for (let i = 0; i < signature.length; i++) {
+ for (; i < signature.length; i++) {
const char = signature[i]!
// If the character is a separator, we want to reactivate.
From 742fbc9d0fe378d65f0f20cbee1dbe1a1ab77e4f Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:21:34 +1000
Subject: [PATCH 046/192] fix(crypto): typed getSharedSecret error and JSDoc
corrections
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-99b84f570f29
---
.changeset/wave-0-crypto-extra-entropy-default-doc.md | 5 +++++
.changeset/wave-0-crypto-webcrypto-doc-corrections.md | 5 +++++
.../wave-0-crypto-webcrypto-shared-secret-typed-error.md | 5 +++++
3 files changed, 15 insertions(+)
create mode 100644 .changeset/wave-0-crypto-extra-entropy-default-doc.md
create mode 100644 .changeset/wave-0-crypto-webcrypto-doc-corrections.md
create mode 100644 .changeset/wave-0-crypto-webcrypto-shared-secret-typed-error.md
diff --git a/.changeset/wave-0-crypto-extra-entropy-default-doc.md b/.changeset/wave-0-crypto-extra-entropy-default-doc.md
new file mode 100644
index 00000000..4b841a99
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-crypto-webcrypto-doc-corrections.md b/.changeset/wave-0-crypto-webcrypto-doc-corrections.md
new file mode 100644
index 00000000..d9036203
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-crypto-webcrypto-shared-secret-typed-error.md b/.changeset/wave-0-crypto-webcrypto-shared-secret-typed-error.md
new file mode 100644
index 00000000..2b9d4470
--- /dev/null
+++ b/.changeset/wave-0-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`.
From 6f985408a1728a6e8f36a73a309694c0745a35cd Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:23:06 +1000
Subject: [PATCH 047/192] fix(abi): drop string[]/bytes[] padding change to
keep parity with viem
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-9d2614e4f981
---
.../wave-0-abi-parameters-encode-packed.md | 2 +-
src/core/AbiParameters.ts | 16 ++--------------
src/core/_test/AbiParameters.test.ts | 16 ----------------
3 files changed, 3 insertions(+), 31 deletions(-)
diff --git a/.changeset/wave-0-abi-parameters-encode-packed.md b/.changeset/wave-0-abi-parameters-encode-packed.md
index 30ef590f..823d114e 100644
--- a/.changeset/wave-0-abi-parameters-encode-packed.md
+++ b/.changeset/wave-0-abi-parameters-encode-packed.md
@@ -2,4 +2,4 @@
"ox": patch
---
-Fixed `AbiParameters.encodePacked` to validate fixed-array lengths and to right-pad `string[]` and `bytes[]` elements to a 32-byte boundary, matching the Solidity packed-encoding specification.
+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/src/core/AbiParameters.ts b/src/core/AbiParameters.ts
index e25790ba..2f769f07 100644
--- a/src/core/AbiParameters.ts
+++ b/src/core/AbiParameters.ts
@@ -296,20 +296,8 @@ export namespace encodePacked {
isArray ? 32 : 0,
) as Address.Address
}
- if (type === 'string') {
- const hex = Hex.fromString(value as string)
- if (!isArray) return hex
- const byteSize = (hex.length - 2) / 2
- const paddedSize = Math.ceil(byteSize / 32) * 32 || 32
- return Hex.padRight(hex, paddedSize)
- }
- if (type === 'bytes') {
- const hex = value as Hex.Hex
- if (!isArray) return hex
- const byteSize = (hex.length - 2) / 2
- const paddedSize = Math.ceil(byteSize / 32) * 32 || 32
- return Hex.padRight(hex, paddedSize)
- }
+ if (type === 'string') return Hex.fromString(value as string)
+ if (type === 'bytes') return value as Hex.Hex
if (type === 'bool')
return Hex.padLeft(Hex.fromBoolean(value as boolean), isArray ? 32 : 1)
diff --git a/src/core/_test/AbiParameters.test.ts b/src/core/_test/AbiParameters.test.ts
index 3f3af379..ff11d40c 100644
--- a/src/core/_test/AbiParameters.test.ts
+++ b/src/core/_test/AbiParameters.test.ts
@@ -260,22 +260,6 @@ describe('encodePacked', () => {
'[AbiParameters.ArrayLengthMismatchError: Array length mismatch for type `uint256[2]`. Expected: `2`. Given: `3`.]',
)
})
-
- test('behavior: pads string[] elements to 32 bytes', () => {
- expect(
- AbiParameters.encodePacked(['string[]'], [['hi', 'bye']]),
- ).toMatchInlineSnapshot(
- `"0x68690000000000000000000000000000000000000000000000000000000000006279650000000000000000000000000000000000000000000000000000000000"`,
- )
- })
-
- test('behavior: pads bytes[] elements to 32 bytes', () => {
- expect(
- AbiParameters.encodePacked(['bytes[]'], [['0xdead', '0xbeef']]),
- ).toMatchInlineSnapshot(
- `"0xdead000000000000000000000000000000000000000000000000000000000000beef000000000000000000000000000000000000000000000000000000000000"`,
- )
- })
})
describe('from', () => {
From 8ce5e7b419dc2839c19b21e7f82ced15e07f0a9d Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:23:29 +1000
Subject: [PATCH 048/192] fix(filter): preserve explicit address: null and
topics: null in toRpc
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b2649a371d7f
---
...ve-0-block-state-filter-torpc-address-null.md | 5 +++++
src/core/Filter.ts | 4 ++--
src/core/_test/Filter.test.ts | 16 ++++++++++++++++
3 files changed, 23 insertions(+), 2 deletions(-)
create mode 100644 .changeset/wave-0-block-state-filter-torpc-address-null.md
diff --git a/.changeset/wave-0-block-state-filter-torpc-address-null.md b/.changeset/wave-0-block-state-filter-torpc-address-null.md
new file mode 100644
index 00000000..206ec0df
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Filter.ts b/src/core/Filter.ts
index 672b0d72..1dd3829c 100644
--- a/src/core/Filter.ts
+++ b/src/core/Filter.ts
@@ -112,8 +112,8 @@ export declare namespace fromRpc {
export function toRpc(filter: Filter): Rpc {
const { address, topics, fromBlock, toBlock } = filter
return {
- ...(address && { address }),
- ...(topics && { topics }),
+ ...(typeof address !== 'undefined' ? { address } : {}),
+ ...(typeof topics !== 'undefined' ? { topics } : {}),
...(typeof fromBlock !== 'undefined'
? {
fromBlock:
diff --git a/src/core/_test/Filter.test.ts b/src/core/_test/Filter.test.ts
index 10ae6261..a877bc5d 100644
--- a/src/core/_test/Filter.test.ts
+++ b/src/core/_test/Filter.test.ts
@@ -121,6 +121,22 @@ describe('toRpc', () => {
`)
}
})
+
+ test('behavior: preserves explicit `address: null`', () => {
+ const filter = Filter.toRpc({
+ address: null,
+ })
+ expect(filter).toMatchInlineSnapshot(`
+ {
+ "address": null,
+ }
+ `)
+ })
+
+ test('behavior: omits absent `address`', () => {
+ const filter = Filter.toRpc({})
+ expect(filter).toMatchInlineSnapshot('{}')
+ })
})
test('exports', () => {
From fd27456003c22e7e5c15ffdb89f9baa31c33025b Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:23:34 +1000
Subject: [PATCH 049/192] fix(validator-data): assert validator address in
encode
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b2649a371d7f
---
...0-block-state-validator-data-validate-address.md | 5 +++++
src/core/ValidatorData.ts | 4 +++-
src/core/_test/ValidatorData.test.ts | 13 +++++++++++++
3 files changed, 21 insertions(+), 1 deletion(-)
create mode 100644 .changeset/wave-0-block-state-validator-data-validate-address.md
diff --git a/.changeset/wave-0-block-state-validator-data-validate-address.md b/.changeset/wave-0-block-state-validator-data-validate-address.md
new file mode 100644
index 00000000..a9240908
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/ValidatorData.ts b/src/core/ValidatorData.ts
index f9443d46..24a105ee 100644
--- a/src/core/ValidatorData.ts
+++ b/src/core/ValidatorData.ts
@@ -1,4 +1,4 @@
-import type * as Address from './Address.js'
+import * as Address from './Address.js'
import type * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
@@ -24,6 +24,7 @@ import * as Hex from './Hex.js'
*/
export function encode(value: encode.Value): Hex.Hex {
const { data, validator } = value
+ Address.assert(validator, { strict: false })
return Hex.concat(
// Validator Data Format: `0x19 ‖ 0x00 ‖ ‖ `
'0x19',
@@ -40,6 +41,7 @@ export declare namespace encode {
}
type ErrorType =
+ | Address.assert.ErrorType
| Hex.concat.ErrorType
| Hex.from.ErrorType
| Errors.GlobalErrorType
diff --git a/src/core/_test/ValidatorData.test.ts b/src/core/_test/ValidatorData.test.ts
index 1f53696f..ee084a34 100644
--- a/src/core/_test/ValidatorData.test.ts
+++ b/src/core/_test/ValidatorData.test.ts
@@ -21,6 +21,19 @@ describe('encode', () => {
`"0x1900d8da6bf26964af9d7eed9e03e53415d37aa9604568656c6c6f20776f726c64"`,
)
})
+
+ test('error: invalid validator address', () => {
+ expect(() =>
+ ValidatorData.encode({
+ data: Hex.fromString('hello world'),
+ validator: '0xnope' as never,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(`
+ [Address.InvalidAddressError: Address "0xnope" is invalid.
+
+ Details: Address is not a 20 byte (40 hexadecimal character) value.]
+ `)
+ })
})
describe('getSignPayload', () => {
From 916fd9cf1e54eb2843337189bbb2550b8d07a4ed Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:23:38 +1000
Subject: [PATCH 050/192] fix(bloom): validate bloom length in contains
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b2649a371d7f
---
...ck-state-bloom-contains-validate-length.md | 5 +++++
src/core/Bloom.ts | 16 +++++++++++++-
src/core/_test/Bloom.test.ts | 22 +++++++++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 .changeset/wave-0-block-state-bloom-contains-validate-length.md
diff --git a/.changeset/wave-0-block-state-bloom-contains-validate-length.md b/.changeset/wave-0-block-state-bloom-contains-validate-length.md
new file mode 100644
index 00000000..31b6b7ce
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Bloom.ts b/src/core/Bloom.ts
index 8d4c8b85..6a5f9b41 100644
--- a/src/core/Bloom.ts
+++ b/src/core/Bloom.ts
@@ -1,5 +1,5 @@
import * as Bytes from './Bytes.js'
-import type * as Errors from './Errors.js'
+import * as Errors from './Errors.js'
import * as Hash from './Hash.js'
import * as Hex from './Hex.js'
@@ -25,6 +25,8 @@ export function contains(
bloom: Hex.Hex,
input: Hex.Hex | Bytes.Bytes,
): boolean {
+ if (!validate(bloom)) throw new InvalidBloomError({ bloom })
+
const filter = Bytes.fromHex(bloom)
const hash = Hash.keccak256(input, { as: 'Bytes' })
@@ -41,6 +43,7 @@ export declare namespace contains {
type ErrorType =
| Bytes.fromHex.ErrorType
| Hash.keccak256.ErrorType
+ | InvalidBloomError
| Errors.GlobalErrorType
}
@@ -71,3 +74,14 @@ export declare namespace validate {
| Hex.size.ErrorType
| Errors.GlobalErrorType
}
+
+/** Thrown when a value is not a valid bloom filter. */
+export class InvalidBloomError extends Errors.BaseError {
+ override readonly name = 'Bloom.InvalidBloomError'
+
+ constructor({ bloom }: { bloom: string }) {
+ super(
+ `Value \`${bloom}\` is not a valid bloom filter (must be a 256-byte hex string).`,
+ )
+ }
+}
diff --git a/src/core/_test/Bloom.test.ts b/src/core/_test/Bloom.test.ts
index 5afb8fa6..81963fd5 100644
--- a/src/core/_test/Bloom.test.ts
+++ b/src/core/_test/Bloom.test.ts
@@ -34,6 +34,28 @@ describe('contains', () => {
),
).toBeTruthy()
})
+
+ test('error: rejects bloom of incorrect length', () => {
+ expect(() =>
+ Bloom.contains(
+ '0xdeadbeef',
+ '0xef2d6d194084c2de36e0dabfce45d046b37d1106',
+ ),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[Bloom.InvalidBloomError: Value `0xdeadbeef` is not a valid bloom filter (must be a 256-byte hex string).]',
+ )
+ })
+
+ test('error: rejects non-hex bloom', () => {
+ expect(() =>
+ Bloom.contains(
+ 'not-a-hex' as never,
+ '0xef2d6d194084c2de36e0dabfce45d046b37d1106',
+ ),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[Bloom.InvalidBloomError: Value `not-a-hex` is not a valid bloom filter (must be a 256-byte hex string).]',
+ )
+ })
})
describe('validate', () => {
From 028c57b80b39a1f8dcf461dc2bb09ade6fba6b0f Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:24:49 +1000
Subject: [PATCH 051/192] fix(abi): revert normalizeSignature trailing-garbage
check (clashes with valid Solidity modifiers)
---
.../wave-0-abi-normalize-signature-trailing.md | 5 -----
src/core/internal/abiItem.ts | 13 +------------
2 files changed, 1 insertion(+), 17 deletions(-)
delete mode 100644 .changeset/wave-0-abi-normalize-signature-trailing.md
diff --git a/.changeset/wave-0-abi-normalize-signature-trailing.md b/.changeset/wave-0-abi-normalize-signature-trailing.md
deleted file mode 100644
index 783963e2..00000000
--- a/.changeset/wave-0-abi-normalize-signature-trailing.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"ox": patch
----
-
-Fixed `internal.normalizeSignature` to reject trailing characters after the closing parenthesis of an ABI item signature instead of silently truncating them.
diff --git a/src/core/internal/abiItem.ts b/src/core/internal/abiItem.ts
index 4650fc9d..23043ee4 100644
--- a/src/core/internal/abiItem.ts
+++ b/src/core/internal/abiItem.ts
@@ -433,9 +433,8 @@ export function normalizeSignature(signature: string): string {
let level = 0
let result = ''
let valid = false
- let i = 0
- for (; i < signature.length; i++) {
+ for (let i = 0; i < signature.length; i++) {
const char = signature[i]!
// If the character is a separator, we want to reactivate.
@@ -481,16 +480,6 @@ export function normalizeSignature(signature: string): string {
if (!valid) throw new Errors.BaseError('Unable to normalize signature.')
- // Reject trailing characters after the closing paren of the top-level
- // parameter list. The loop above breaks at the first `)` at level 0,
- // so any remaining non-whitespace input means the signature is malformed.
- for (let j = i + 1; j < signature.length; j++) {
- if (signature[j] !== ' ')
- throw new Errors.BaseError(
- `Unable to normalize signature: trailing characters after closing parenthesis: ${signature.slice(j)}`,
- )
- }
-
return result
}
From 8426949ee2f4c1d55e3f59ce37b104f4dae83a85 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:25:06 +1000
Subject: [PATCH 052/192] fix(types): satisfy strict types in block-state
regression tests
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-b2649a371d7f
---
src/core/_test/Block.test.ts | 1 -
src/core/_test/TypedData.test.ts | 4 ++--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/core/_test/Block.test.ts b/src/core/_test/Block.test.ts
index b1d155bd..7bcdda39 100644
--- a/src/core/_test/Block.test.ts
+++ b/src/core/_test/Block.test.ts
@@ -114,7 +114,6 @@ describe('fromRpc', () => {
test('behavior: optional totalDifficulty preserved as undefined', () => {
const block = Block.fromRpc({
- // @ts-expect-error totalDifficulty is omitted on purpose
extraData: '0x',
gasLimit: '0x1c9c347',
gasUsed: '0x0',
diff --git a/src/core/_test/TypedData.test.ts b/src/core/_test/TypedData.test.ts
index a08c1cd2..4e169c9c 100644
--- a/src/core/_test/TypedData.test.ts
+++ b/src/core/_test/TypedData.test.ts
@@ -437,7 +437,7 @@ describe('assert', () => {
},
primaryType: 'Foo',
message: {
- addresses: ['0x0000000000000000000000000000000000000001'],
+ addresses: ['0x0000000000000000000000000000000000000001'] as any,
},
}),
).toThrowErrorMatchingInlineSnapshot(
@@ -491,7 +491,7 @@ describe('assert', () => {
},
primaryType: 'Foo',
message: {
- amounts: [256n],
+ amounts: [256n] as any,
},
}),
).toThrowErrorMatchingInlineSnapshot(`
From 65141bb3c7eee9aa50263df6878aa4c16677f643 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:25:34 +1000
Subject: [PATCH 053/192] test(abi): update decode snapshots after wrapping
PositionOutOfBoundsError
Amp-Thread-ID: https://ampcode.com/threads/T-019e197d-5765-7569-9e8b-9d2614e4f981
---
src/core/_test/AbiParameters.decode.test.ts | 77 ++++++++++++++++++---
1 file changed, 66 insertions(+), 11 deletions(-)
diff --git a/src/core/_test/AbiParameters.decode.test.ts b/src/core/_test/AbiParameters.decode.test.ts
index a9aa83b7..cb6eaecf 100644
--- a/src/core/_test/AbiParameters.decode.test.ts
+++ b/src/core/_test/AbiParameters.decode.test.ts
@@ -1589,12 +1589,22 @@ test('zst', () => {
expect(() =>
AbiParameters.decode([{ type: 'uint256[0][4294967295]' }], payload),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `64` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: (uint256[0][4294967295])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode([{ type: 'uint32[0][4294967295]' }], payload),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `64` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: (uint32[0][4294967295])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode(
@@ -1602,27 +1612,52 @@ test('zst', () => {
payload,
),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `95` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: (uint256[4294967295][4294967295])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode([{ type: 'uint32[4294967295][4294967295]' }], payload),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `95` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: (uint32[4294967295][4294967295])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode([{ type: 'uint256[0][]' }], payload),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `64` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: (uint256[0][])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode([{ type: 'uint256[0][]' }], payload),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `64` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: (uint256[0][])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode([{ type: 'tuple[]', components: [] }], payload),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `64` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: (()[])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode(
@@ -1630,7 +1665,12 @@ test('zst', () => {
payload,
),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `64` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: ((())[])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode(
@@ -1638,7 +1678,12 @@ test('zst', () => {
payload,
),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `64` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: ((uint32[0])[])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode(
@@ -1651,7 +1696,12 @@ test('zst', () => {
payload,
),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `64` is out of bounds (`0 < position < 64`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 64 bytes is too small for given parameters.
+
+ Params: (((uint32[0]))[])
+ Data: 0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF (64 bytes)]
+ `,
)
})
@@ -1704,7 +1754,12 @@ test('recursive', () => {
expect(() =>
AbiParameters.decode(AbiParameters.from(arr10), p2),
).toThrowErrorMatchingInlineSnapshot(
- '[Cursor.PositionOutOfBoundsError: Position `327744` is out of bounds (`0 < position < 327744`).]',
+ `
+ [AbiParameters.DataSizeTooSmallError: Data size of 327744 bytes is too small for given parameters.
+
+ Params: (uint256[][][][][][][][][][])
+ Data: 0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000460000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000058000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005e00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000072000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000760000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007e00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008e00000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000092000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000960000000000000000000000000000000000000000000000000000000000000098000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000009e00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000de00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000108000000000000000000000000000000000000000000000000000000000000010a000000000000000000000000000000000000000000000000000000000000010c000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000112000000000000000000000000000000000000000000000000000000000000011400000000000000000000000000000000000000000000000000000000000001160000000000000000000000000000000000000000000000000000000000000118000000000000000000000000000000000000000000000000000000000000011a000000000000000000000000000000000000000000000000000000000000011c000000000000000000000000000000000000000000000000000000000000011e00000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000122000000000000000000000000000000000000000000000000000000000000012400000000000000000000000000000000000000000000000000000000000001260000000000000000000000000000000000000000000000000000000000000128000000000000000000000000000000000000000000000000000000000000012a000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000012e00000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000132000000000000000000000000000000000000000000000000000000000000013400000000000000000000000000000000000000000000000000000000000001360000000000000000000000000000000000000000000000000000000000000138000000000000000000000000000000000000000000000000000000000000013a000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000013e00000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000142000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001460000000000000000000000000000000000000000000000000000000000000148000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014e00000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000152000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001560000000000000000000000000000000000000000000000000000000000000158000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015e00000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001660000000000000000000000000000000000000000000000000000000000000168000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016e00000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000172000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001760000000000000000000000000000000000000000000000000000000000000178000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017e00000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000182000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001860000000000000000000000000000000000000000000000000000000000000188000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018e00000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000192000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001960000000000000000000000000000000000000000000000000000000000000198000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019e00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000202000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002060000000000000000000000000000000000000000000000000000000000000208000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020e00000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000212000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002160000000000000000000000000000000000000000000000000000000000000218000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021e00000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000222000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002260000000000000000000000000000000000000000000000000000000000000228000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022e00000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000232000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002360000000000000000000000000000000000000000000000000000000000000238000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023e00000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000242000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002460000000000000000000000000000000000000000000000000000000000000248000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024e00000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000252000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002560000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025e00000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000262000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002660000000000000000000000000000000000000000000000000000000000000268000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026e00000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000272000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002760000000000000000000000000000000000000000000000000000000000000278000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027e00000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000282000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002860000000000000000000000000000000000000000000000000000000000000288000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028e00000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000292000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002960000000000000000000000000000000000000000000000000000000000000298000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029e00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000302000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003060000000000000000000000000000000000000000000000000000000000000308000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030e00000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000312000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003160000000000000000000000000000000000000000000000000000000000000318000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031e00000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000322000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003260000000000000000000000000000000000000000000000000000000000000328000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032e00000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000332000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003360000000000000000000000000000000000000000000000000000000000000338000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033e00000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003460000000000000000000000000000000000000000000000000000000000000348000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034e00000000000000000000000000000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000352000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003560000000000000000000000000000000000000000000000000000000000000358000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035e00000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000362000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003660000000000000000000000000000000000000000000000000000000000000368000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036e00000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000372000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003760000000000000000000000000000000000000000000000000000000000000378000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037e00000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000382000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003860000000000000000000000000000000000000000000000000000000000000388000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038e00000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000392000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003960000000000000000000000000000000000000000000000000000000000000398000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039e00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003be00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fe00000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004060000000000000000000000000000000000000000000000000000000000000408000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040e00000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000412000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004160000000000000000000000000000000000000000000000000000000000000418000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041e00000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000000000000000000000422000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004260000000000000000000000000000000000000000000000000000000000000428000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042e00000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000432000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004360000000000000000000000000000000000000000000000000000000000000438000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043e00000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000442000000000000000000000000000000000000000000000000000000000000044400000000000000000000000000000000000000000000000000000000000004460000000000000000000000000000000000000000000000000000000000000448000000000000000000000000000000000000000000000000000000000000044a000000000000000000000000000000000000000000000000000000000000044c000000000000000000000000000000000000000000000000000000000000044e00000000000000000000000000000000000000000000000000000000000004500000000000000000000000000000000000000000000000000000000000000452000000000000000000000000000000000000000000000000000000000000045400000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000458000000000000000000000000000000000000000000000000000000000000045a000000000000000000000000000000000000000000000000000000000000045c000000000000000000000000000000000000000000000000000000000000045e00000000000000000000000000000000000000000000000000000000000004600000000000000000000000000000000000000000000000000000000000000462000000000000000000000000000000000000000000000000000000000000046400000000000000000000000000000000000000000000000000000000000004660000000000000000000000000000000000000000000000000000000000000468000000000000000000000000000000000000000000000000000000000000046a000000000000000000000000000000000000000000000000000000000000046c000000000000000000000000000000000000000000000000000000000000046e00000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000472000000000000000000000000000000000000000000000000000000000000047400000000000000000000000000000000000000000000000000000000000004760000000000000000000000000000000000000000000000000000000000000478000000000000000000000000000000000000000000000000000000000000047a000000000000000000000000000000000000000000000000000000000000047c000000000000000000000000000000000000000000000000000000000000047e00000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000482000000000000000000000000000000000000000000000000000000000000048400000000000000000000000000000000000000000000000000000000000004860000000000000000000000000000000000000000000000000000000000000488000000000000000000000000000000000000000000000000000000000000048a000000000000000000000000000000000000000000000000000000000000048c000000000000000000000000000000000000000000000000000000000000048e00000000000000000000000000000000000000000000000000000000000004900000000000000000000000000000000000000000000000000000000000000492000000000000000000000000000000000000000000000000000000000000049400000000000000000000000000000000000000000000000000000000000004960000000000000000000000000000000000000000000000000000000000000498000000000000000000000000000000000000000000000000000000000000049a000000000000000000000000000000000000000000000000000000000000049c000000000000000000000000000000000000000000000000000000000000049e00000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004a200000000000000000000000000000000000000000000000000000000000004a400000000000000000000000000000000000000000000000000000000000004a600000000000000000000000000000000000000000000000000000000000004a800000000000000000000000000000000000000000000000000000000000004aa00000000000000000000000000000000000000000000000000000000000004ac00000000000000000000000000000000000000000000000000000000000004ae00000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000004b200000000000000000000000000000000000000000000000000000000000004b400000000000000000000000000000000000000000000000000000000000004b600000000000000000000000000000000000000000000000000000000000004b800000000000000000000000000000000000000000000000000000000000004ba00000000000000000000000000000000000000000000000000000000000004bc00000000000000000000000000000000000000000000000000000000000004be00000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c200000000000000000000000000000000000000000000000000000000000004c400000000000000000000000000000000000000000000000000000000000004c600000000000000000000000000000000000000000000000000000000000004c800000000000000000000000000000000000000000000000000000000000004ca00000000000000000000000000000000000000000000000000000000000004cc00000000000000000000000000000000000000000000000000000000000004ce00000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000004d200000000000000000000000000000000000000000000000000000000000004d400000000000000000000000000000000000000000000000000000000000004d600000000000000000000000000000000000000000000000000000000000004d800000000000000000000000000000000000000000000000000000000000004da00000000000000000000000000000000000000000000000000000000000004dc00000000000000000000000000000000000000000000000000000000000004de00000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004e200000000000000000000000000000000000000000000000000000000000004e400000000000000000000000000000000000000000000000000000000000004e600000000000000000000000000000000000000000000000000000000000004e800000000000000000000000000000000000000000000000000000000000004ea00000000000000000000000000000000000000000000000000000000000004ec00000000000000000000000000000000000000000000000000000000000004ee00000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000004f200000000000000000000000000000000000000000000000000000000000004f400000000000000000000000000000000000000000000000000000000000004f600000000000000000000000000000000000000000000000000000000000004f800000000000000000000000000000000000000000000000000000000000004fa00000000000000000000000000000000000000000000000000000000000004fc00000000000000000000000000000000000000000000000000000000000004fe00000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000502000000000000000000000000000000000000000000000000000000000000050400000000000000000000000000000000000000000000000000000000000005060000000000000000000000000000000000000000000000000000000000000508000000000000000000000000000000000000000000000000000000000000050a000000000000000000000000000000000000000000000000000000000000050c000000000000000000000000000000000000000000000000000000000000050e00000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000512000000000000000000000000000000000000000000000000000000000000051400000000000000000000000000000000000000000000000000000000000005160000000000000000000000000000000000000000000000000000000000000518000000000000000000000000000000000000000000000000000000000000051a000000000000000000000000000000000000000000000000000000000000051c000000000000000000000000000000000000000000000000000000000000051e00000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000522000000000000000000000000000000000000000000000000000000000000052400000000000000000000000000000000000000000000000000000000000005260000000000000000000000000000000000000000000000000000000000000528000000000000000000000000000000000000000000000000000000000000052a000000000000000000000000000000000000000000000000000000000000052c000000000000000000000000000000000000000000000000000000000000052e00000000000000000000000000000000000000000000000000000000000005300000000000000000000000000000000000000000000000000000000000000532000000000000000000000000000000000000000000000000000000000000053400000000000000000000000000000000000000000000000000000000000005360000000000000000000000000000000000000000000000000000000000000538000000000000000000000000000000000000000000000000000000000000053a000000000000000000000000000000000000000000000000000000000000053c000000000000000000000000000000000000000000000000000000000000053e00000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054400000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000054a000000000000000000000000000000000000000000000000000000000000054c000000000000000000000000000000000000000000000000000000000000054e00000000000000000000000000000000000000000000000000000000000005500000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055400000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000055a000000000000000000000000000000000000000000000000000000000000055c000000000000000000000000000000000000000000000000000000000000055e00000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056400000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000056a000000000000000000000000000000000000000000000000000000000000056c000000000000000000000000000000000000000000000000000000000000056e00000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057400000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000057a000000000000000000000000000000000000000000000000000000000000057c000000000000000000000000000000000000000000000000000000000000057e00000000000000000000000000000000000000000000000000000000000005800000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058400000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000058a000000000000000000000000000000000000000000000000000000000000058c000000000000000000000000000000000000000000000000000000000000058e00000000000000000000000000000000000000000000000000000000000005900000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059400000000000000000000000000000000000000000000000000000000000005960000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000059a000000000000000000000000000000000000000000000000000000000000059c000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000060a000000000000000000000000000000000000000000000000000000000000060c000000000000000000000000000000000000000000000000000000000000060e00000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061400000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000061a000000000000000000000000000000000000000000000000000000000000061c000000000000000000000000000000000000000000000000000000000000061e00000000000000000000000000000000000000000000000000000000000006200000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062400000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000062a000000000000000000000000000000000000000000000000000000000000062c000000000000000000000000000000000000000000000000000000000000062e00000000000000000000000000000000000000000000000000000000000006300000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063400000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000063a000000000000000000000000000000000000000000000000000000000000063c000000000000000000000000000000000000000000000000000000000000063e00000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064400000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000064a000000000000000000000000000000000000000000000000000000000000064c000000000000000000000000000000000000000000000000000000000000064e00000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065400000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000065a000000000000000000000000000000000000000000000000000000000000065c000000000000000000000000000000000000000000000000000000000000065e00000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066400000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000066a000000000000000000000000000000000000000000000000000000000000066c000000000000000000000000000000000000000000000000000000000000066e00000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067400000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000067a000000000000000000000000000000000000000000000000000000000000067c000000000000000000000000000000000000000000000000000000000000067e00000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068400000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000068a000000000000000000000000000000000000000000000000000000000000068c000000000000000000000000000000000000000000000000000000000000068e00000000000000000000000000000000000000000000000000000000000006900000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069400000000000000000000000000000000000000000000000000000000000006960000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000069a000000000000000000000000000000000000000000000000000000000000069c000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000070a000000000000000000000000000000000000000000000000000000000000070c000000000000000000000000000000000000000000000000000000000000070e00000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071400000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000071a000000000000000000000000000000000000000000000000000000000000071c000000000000000000000000000000000000000000000000000000000000071e00000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072400000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000072a000000000000000000000000000000000000000000000000000000000000072c000000000000000000000000000000000000000000000000000000000000072e00000000000000000000000000000000000000000000000000000000000007300000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073400000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000073a000000000000000000000000000000000000000000000000000000000000073c000000000000000000000000000000000000000000000000000000000000073e00000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000742000000000000000000000000000000000000000000000000000000000000074400000000000000000000000000000000000000000000000000000000000007460000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000074a000000000000000000000000000000000000000000000000000000000000074c000000000000000000000000000000000000000000000000000000000000074e00000000000000000000000000000000000000000000000000000000000007500000000000000000000000000000000000000000000000000000000000000752000000000000000000000000000000000000000000000000000000000000075400000000000000000000000000000000000000000000000000000000000007560000000000000000000000000000000000000000000000000000000000000758000000000000000000000000000000000000000000000000000000000000075a000000000000000000000000000000000000000000000000000000000000075c000000000000000000000000000000000000000000000000000000000000075e00000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000000000000000000000000000000000000762000000000000000000000000000000000000000000000000000000000000076400000000000000000000000000000000000000000000000000000000000007660000000000000000000000000000000000000000000000000000000000000768000000000000000000000000000000000000000000000000000000000000076a000000000000000000000000000000000000000000000000000000000000076c000000000000000000000000000000000000000000000000000000000000076e00000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000772000000000000000000000000000000000000000000000000000000000000077400000000000000000000000000000000000000000000000000000000000007760000000000000000000000000000000000000000000000000000000000000778000000000000000000000000000000000000000000000000000000000000077a000000000000000000000000000000000000000000000000000000000000077c000000000000000000000000000000000000000000000000000000000000077e00000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000782000000000000000000000000000000000000000000000000000000000000078400000000000000000000000000000000000000000000000000000000000007860000000000000000000000000000000000000000000000000000000000000788000000000000000000000000000000000000000000000000000000000000078a000000000000000000000000000000000000000000000000000000000000078c000000000000000000000000000000000000000000000000000000000000078e00000000000000000000000000000000000000000000000000000000000007900000000000000000000000000000000000000000000000000000000000000792000000000000000000000000000000000000000000000000000000000000079400000000000000000000000000000000000000000000000000000000000007960000000000000000000000000000000000000000000000000000000000000798000000000000000000000000000000000000000000000000000000000000079a000000000000000000000000000000000000000000000000000000000000079c000000000000000000000000000000000000000000000000000000000000079e00000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000007a200000000000000000000000000000000000000000000000000000000000007a400000000000000000000000000000000000000000000000000000000000007a600000000000000000000000000000000000000000000000000000000000007a800000000000000000000000000000000000000000000000000000000000007aa00000000000000000000000000000000000000000000000000000000000007ac00000000000000000000000000000000000000000000000000000000000007ae00000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007b200000000000000000000000000000000000000000000000000000000000007b400000000000000000000000000000000000000000000000000000000000007b600000000000000000000000000000000000000000000000000000000000007b800000000000000000000000000000000000000000000000000000000000007ba00000000000000000000000000000000000000000000000000000000000007bc00000000000000000000000000000000000000000000000000000000000007be00000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007c200000000000000000000000000000000000000000000000000000000000007c400000000000000000000000000000000000000000000000000000000000007c600000000000000000000000000000000000000000000000000000000000007c800000000000000000000000000000000000000000000000000000000000007ca00000000000000000000000000000000000000000000000000000000000007cc00000000000000000000000000000000000000000000000000000000000007ce00000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000007d200000000000000000000000000000000000000000000000000000000000007d400000000000000000000000000000000000000000000000000000000000007d600000000000000000000000000000000000000000000000000000000000007d800000000000000000000000000000000000000000000000000000000000007da00000000000000000000000000000000000000000000000000000000000007dc00000000000000000000000000000000000000000000000000000000000007de00000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000007e200000000000000000000000000000000000000000000000000000000000007e400000000000000000000000000000000000000000000000000000000000007e600000000000000000000000000000000000000000000000000000000000007e800000000000000000000000000000000000000000000000000000000000007ea00000000000000000000000000000000000000000000000000000000000007ec00000000000000000000000000000000000000000000000000000000000007ee00000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000007f200000000000000000000000000000000000000000000000000000000000007f400000000000000000000000000000000000000000000000000000000000007f600000000000000000000000000000000000000000000000000000000000007f800000000000000000000000000000000000000000000000000000000000007fa00000000000000000000000000000000000000000000000000000000000007fc00000000000000000000000000000000000000000000000000000000000007fe00000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000802000000000000000000000000000000000000000000000000000000000000080400000000000000000000000000000000000000000000000000000000000008060000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000080a000000000000000000000000000000000000000000000000000000000000080c000000000000000000000000000000000000000000000000000000000000080e00000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000812000000000000000000000000000000000000000000000000000000000000081400000000000000000000000000000000000000000000000000000000000008160000000000000000000000000000000000000000000000000000000000000818000000000000000000000000000000000000000000000000000000000000081a000000000000000000000000000000000000000000000000000000000000081c000000000000000000000000000000000000000000000000000000000000081e00000000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000822000000000000000000000000000000000000000000000000000000000000082400000000000000000000000000000000000000000000000000000000000008260000000000000000000000000000000000000000000000000000000000000828000000000000000000000000000000000000000000000000000000000000082a000000000000000000000000000000000000000000000000000000000000082c000000000000000000000000000000000000000000000000000000000000082e00000000000000000000000000000000000000000000000000000000000008300000000000000000000000000000000000000000000000000000000000000832000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000008360000000000000000000000000000000000000000000000000000000000000838000000000000000000000000000000000000000000000000000000000000083a000000000000000000000000000000000000000000000000000000000000083c000000000000000000000000000000000000000000000000000000000000083e00000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000842000000000000000000000000000000000000000000000000000000000000084400000000000000000000000000000000000000000000000000000000000008460000000000000000000000000000000000000000000000000000000000000848000000000000000000000000000000000000000000000000000000000000084a000000000000000000000000000000000000000000000000000000000000084c000000000000000000000000000000000000000000000000000000000000084e00000000000000000000000000000000000000000000000000000000000008500000000000000000000000000000000000000000000000000000000000000852000000000000000000000000000000000000000000000000000000000000085400000000000000000000000000000000000000000000000000000000000008560000000000000000000000000000000000000000000000000000000000000858000000000000000000000000000000000000000000000000000000000000085a000000000000000000000000000000000000000000000000000000000000085c000000000000000000000000000000000000000000000000000000000000085e00000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000862000000000000000000000000000000000000000000000000000000000000086400000000000000000000000000000000000000000000000000000000000008660000000000000000000000000000000000000000000000000000000000000868000000000000000000000000000000000000000000000000000000000000086a000000000000000000000000000000000000000000000000000000000000086c000000000000000000000000000000000000000000000000000000000000086e00000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000872000000000000000000000000000000000000000000000000000000000000087400000000000000000000000000000000000000000000000000000000000008760000000000000000000000000000000000000000000000000000000000000878000000000000000000000000000000000000000000000000000000000000087a000000000000000000000000000000000000000000000000000000000000087c000000000000000000000000000000000000000000000000000000000000087e00000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000882000000000000000000000000000000000000000000000000000000000000088400000000000000000000000000000000000000000000000000000000000008860000000000000000000000000000000000000000000000000000000000000888000000000000000000000000000000000000000000000000000000000000088a000000000000000000000000000000000000000000000000000000000000088c000000000000000000000000000000000000000000000000000000000000088e00000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000892000000000000000000000000000000000000000000000000000000000000089400000000000000000000000000000000000000000000000000000000000008960000000000000000000000000000000000000000000000000000000000000898000000000000000000000000000000000000000000000000000000000000089a000000000000000000000000000000000000000000000000000000000000089c000000000000000000000000000000000000000000000000000000000000089e00000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000008a200000000000000000000000000000000000000000000000000000000000008a400000000000000000000000000000000000000000000000000000000000008a600000000000000000000000000000000000000000000000000000000000008a800000000000000000000000000000000000000000000000000000000000008aa00000000000000000000000000000000000000000000000000000000000008ac00000000000000000000000000000000000000000000000000000000000008ae00000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000008b200000000000000000000000000000000000000000000000000000000000008b400000000000000000000000000000000000000000000000000000000000008b600000000000000000000000000000000000000000000000000000000000008b800000000000000000000000000000000000000000000000000000000000008ba00000000000000000000000000000000000000000000000000000000000008bc00000000000000000000000000000000000000000000000000000000000008be00000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008c200000000000000000000000000000000000000000000000000000000000008c400000000000000000000000000000000000000000000000000000000000008c600000000000000000000000000000000000000000000000000000000000008c800000000000000000000000000000000000000000000000000000000000008ca00000000000000000000000000000000000000000000000000000000000008cc00000000000000000000000000000000000000000000000000000000000008ce00000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008d200000000000000000000000000000000000000000000000000000000000008d400000000000000000000000000000000000000000000000000000000000008d600000000000000000000000000000000000000000000000000000000000008d800000000000000000000000000000000000000000000000000000000000008da00000000000000000000000000000000000000000000000000000000000008dc00000000000000000000000000000000000000000000000000000000000008de00000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000008e200000000000000000000000000000000000000000000000000000000000008e400000000000000000000000000000000000000000000000000000000000008e600000000000000000000000000000000000000000000000000000000000008e800000000000000000000000000000000000000000000000000000000000008ea00000000000000000000000000000000000000000000000000000000000008ec00000000000000000000000000000000000000000000000000000000000008ee00000000000000000000000000000000000000000000000000000000000008f000000000000000000000000000000000000000000000000000000000000008f200000000000000000000000000000000000000000000000000000000000008f400000000000000000000000000000000000000000000000000000000000008f600000000000000000000000000000000000000000000000000000000000008f800000000000000000000000000000000000000000000000000000000000008fa00000000000000000000000000000000000000000000000000000000000008fc00000000000000000000000000000000000000000000000000000000000008fe00000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000902000000000000000000000000000000000000000000000000000000000000090400000000000000000000000000000000000000000000000000000000000009060000000000000000000000000000000000000000000000000000000000000908000000000000000000000000000000000000000000000000000000000000090a000000000000000000000000000000000000000000000000000000000000090c000000000000000000000000000000000000000000000000000000000000090e00000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000912000000000000000000000000000000000000000000000000000000000000091400000000000000000000000000000000000000000000000000000000000009160000000000000000000000000000000000000000000000000000000000000918000000000000000000000000000000000000000000000000000000000000091a000000000000000000000000000000000000000000000000000000000000091c000000000000000000000000000000000000000000000000000000000000091e00000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000922000000000000000000000000000000000000000000000000000000000000092400000000000000000000000000000000000000000000000000000000000009260000000000000000000000000000000000000000000000000000000000000928000000000000000000000000000000000000000000000000000000000000092a000000000000000000000000000000000000000000000000000000000000092c000000000000000000000000000000000000000000000000000000000000092e00000000000000000000000000000000000000000000000000000000000009300000000000000000000000000000000000000000000000000000000000000932000000000000000000000000000000000000000000000000000000000000093400000000000000000000000000000000000000000000000000000000000009360000000000000000000000000000000000000000000000000000000000000938000000000000000000000000000000000000000000000000000000000000093a000000000000000000000000000000000000000000000000000000000000093c000000000000000000000000000000000000000000000000000000000000093e00000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000942000000000000000000000000000000000000000000000000000000000000094400000000000000000000000000000000000000000000000000000000000009460000000000000000000000000000000000000000000000000000000000000948000000000000000000000000000000000000000000000000000000000000094a000000000000000000000000000000000000000000000000000000000000094c000000000000000000000000000000000000000000000000000000000000094e00000000000000000000000000000000000000000000000000000000000009500000000000000000000000000000000000000000000000000000000000000952000000000000000000000000000000000000000000000000000000000000095400000000000000000000000000000000000000000000000000000000000009560000000000000000000000000000000000000000000000000000000000000958000000000000000000000000000000000000000000000000000000000000095a000000000000000000000000000000000000000000000000000000000000095c000000000000000000000000000000000000000000000000000000000000095e00000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000962000000000000000000000000000000000000000000000000000000000000096400000000000000000000000000000000000000000000000000000000000009660000000000000000000000000000000000000000000000000000000000000968000000000000000000000000000000000000000000000000000000000000096a000000000000000000000000000000000000000000000000000000000000096c000000000000000000000000000000000000000000000000000000000000096e00000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000972000000000000000000000000000000000000000000000000000000000000097400000000000000000000000000000000000000000000000000000000000009760000000000000000000000000000000000000000000000000000000000000978000000000000000000000000000000000000000000000000000000000000097a000000000000000000000000000000000000000000000000000000000000097c000000000000000000000000000000000000000000000000000000000000097e00000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000982000000000000000000000000000000000000000000000000000000000000098400000000000000000000000000000000000000000000000000000000000009860000000000000000000000000000000000000000000000000000000000000988000000000000000000000000000000000000000000000000000000000000098a000000000000000000000000000000000000000000000000000000000000098c000000000000000000000000000000000000000000000000000000000000098e00000000000000000000000000000000000000000000000000000000000009900000000000000000000000000000000000000000000000000000000000000992000000000000000000000000000000000000000000000000000000000000099400000000000000000000000000000000000000000000000000000000000009960000000000000000000000000000000000000000000000000000000000000998000000000000000000000000000000000000000000000000000000000000099a000000000000000000000000000000000000000000000000000000000000099c000000000000000000000000000000000000000000000000000000000000099e00000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000009a200000000000000000000000000000000000000000000000000000000000009a400000000000000000000000000000000000000000000000000000000000009a600000000000000000000000000000000000000000000000000000000000009a800000000000000000000000000000000000000000000000000000000000009aa00000000000000000000000000000000000000000000000000000000000009ac00000000000000000000000000000000000000000000000000000000000009ae00000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000009b200000000000000000000000000000000000000000000000000000000000009b400000000000000000000000000000000000000000000000000000000000009b600000000000000000000000000000000000000000000000000000000000009b800000000000000000000000000000000000000000000000000000000000009ba00000000000000000000000000000000000000000000000000000000000009bc00000000000000000000000000000000000000000000000000000000000009be00000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000009c200000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000009c600000000000000000000000000000000000000000000000000000000000009c800000000000000000000000000000000000000000000000000000000000009ca00000000000000000000000000000000000000000000000000000000000009cc00000000000000000000000000000000000000000000000000000000000009ce00000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000009d200000000000000000000000000000000000000000000000000000000000009d400000000000000000000000000000000000000000000000000000000000009d600000000000000000000000000000000000000000000000000000000000009d800000000000000000000000000000000000000000000000000000000000009da00000000000000000000000000000000000000000000000000000000000009dc00000000000000000000000000000000000000000000000000000000000009de00000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000009e200000000000000000000000000000000000000000000000000000000000009e400000000000000000000000000000000000000000000000000000000000009e600000000000000000000000000000000000000000000000000000000000009e800000000000000000000000000000000000000000000000000000000000009ea00000000000000000000000000000000000000000000000000000000000009ec00000000000000000000000000000000000000000000000000000000000009ee00000000000000000000000000000000000000000000000000000000000009f000000000000000000000000000000000000000000000000000000000000009f200000000000000000000000000000000000000000000000000000000000009f400000000000000000000000000000000000000000000000000000000000009f600000000000000000000000000000000000000000000000000000000000009f800000000000000000000000000000000000000000000000000000000000009fa00000000000000000000000000000000000000000000000000000000000009fc00000000000000000000000000000000000000000000000000000000000009fe0000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a020000000000000000000000000000000000000000000000000000000000000a040000000000000000000000000000000000000000000000000000000000000a060000000000000000000000000000000000000000000000000000000000000a080000000000000000000000000000000000000000000000000000000000000a0a0000000000000000000000000000000000000000000000000000000000000a0c0000000000000000000000000000000000000000000000000000000000000a0e0000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000a120000000000000000000000000000000000000000000000000000000000000a140000000000000000000000000000000000000000000000000000000000000a160000000000000000000000000000000000000000000000000000000000000a180000000000000000000000000000000000000000000000000000000000000a1a0000000000000000000000000000000000000000000000000000000000000a1c0000000000000000000000000000000000000000000000000000000000000a1e0000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000a220000000000000000000000000000000000000000000000000000000000000a240000000000000000000000000000000000000000000000000000000000000a260000000000000000000000000000000000000000000000000000000000000a280000000000000000000000000000000000000000000000000000000000000a2a0000000000000000000000000000000000000000000000000000000000000a2c0000000000000000000000000000000000000000000000000000000000000a2e0000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000a320000000000000000000000000000000000000000000000000000000000000a340000000000000000000000000000000000000000000000000000000000000a360000000000000000000000000000000000000000000000000000000000000a380000000000000000000000000000000000000000000000000000000000000a3a0000000000000000000000000000000000000000000000000000000000000a3c0000000000000000000000000000000000000000000000000000000000000a3e0000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000a420000000000000000000000000000000000000000000000000000000000000a440000000000000000000000000000000000000000000000000000000000000a460000000000000000000000000000000000000000000000000000000000000a480000000000000000000000000000000000000000000000000000000000000a4a0000000000000000000000000000000000000000000000000000000000000a4c0000000000000000000000000000000000000000000000000000000000000a4e0000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000a520000000000000000000000000000000000000000000000000000000000000a540000000000000000000000000000000000000000000000000000000000000a560000000000000000000000000000000000000000000000000000000000000a580000000000000000000000000000000000000000000000000000000000000a5a0000000000000000000000000000000000000000000000000000000000000a5c0000000000000000000000000000000000000000000000000000000000000a5e0000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000a620000000000000000000000000000000000000000000000000000000000000a640000000000000000000000000000000000000000000000000000000000000a660000000000000000000000000000000000000000000000000000000000000a680000000000000000000000000000000000000000000000000000000000000a6a0000000000000000000000000000000000000000000000000000000000000a6c0000000000000000000000000000000000000000000000000000000000000a6e0000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000a720000000000000000000000000000000000000000000000000000000000000a740000000000000000000000000000000000000000000000000000000000000a760000000000000000000000000000000000000000000000000000000000000a780000000000000000000000000000000000000000000000000000000000000a7a0000000000000000000000000000000000000000000000000000000000000a7c0000000000000000000000000000000000000000000000000000000000000a7e0000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000a820000000000000000000000000000000000000000000000000000000000000a840000000000000000000000000000000000000000000000000000000000000a860000000000000000000000000000000000000000000000000000000000000a880000000000000000000000000000000000000000000000000000000000000a8a0000000000000000000000000000000000000000000000000000000000000a8c0000000000000000000000000000000000000000000000000000000000000a8e0000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000a920000000000000000000000000000000000000000000000000000000000000a940000000000000000000000000000000000000000000000000000000000000a960000000000000000000000000000000000000000000000000000000000000a980000000000000000000000000000000000000000000000000000000000000a9a0000000000000000000000000000000000000000000000000000000000000a9c0000000000000000000000000000000000000000000000000000000000000a9e0000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000aa20000000000000000000000000000000000000000000000000000000000000aa40000000000000000000000000000000000000000000000000000000000000aa60000000000000000000000000000000000000000000000000000000000000aa80000000000000000000000000000000000000000000000000000000000000aaa0000000000000000000000000000000000000000000000000000000000000aac0000000000000000000000000000000000000000000000000000000000000aae0000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000ab20000000000000000000000000000000000000000000000000000000000000ab40000000000000000000000000000000000000000000000000000000000000ab60000000000000000000000000000000000000000000000000000000000000ab80000000000000000000000000000000000000000000000000000000000000aba0000000000000000000000000000000000000000000000000000000000000abc0000000000000000000000000000000000000000000000000000000000000abe0000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000ac20000000000000000000000000000000000000000000000000000000000000ac40000000000000000000000000000000000000000000000000000000000000ac60000000000000000000000000000000000000000000000000000000000000ac80000000000000000000000000000000000000000000000000000000000000aca0000000000000000000000000000000000000000000000000000000000000acc0000000000000000000000000000000000000000000000000000000000000ace0000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000ad20000000000000000000000000000000000000000000000000000000000000ad40000000000000000000000000000000000000000000000000000000000000ad60000000000000000000000000000000000000000000000000000000000000ad80000000000000000000000000000000000000000000000000000000000000ada0000000000000000000000000000000000000000000000000000000000000adc0000000000000000000000000000000000000000000000000000000000000ade0000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000ae20000000000000000000000000000000000000000000000000000000000000ae40000000000000000000000000000000000000000000000000000000000000ae60000000000000000000000000000000000000000000000000000000000000ae80000000000000000000000000000000000000000000000000000000000000aea0000000000000000000000000000000000000000000000000000000000000aec0000000000000000000000000000000000000000000000000000000000000aee0000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000af20000000000000000000000000000000000000000000000000000000000000af40000000000000000000000000000000000000000000000000000000000000af60000000000000000000000000000000000000000000000000000000000000af80000000000000000000000000000000000000000000000000000000000000afa0000000000000000000000000000000000000000000000000000000000000afc0000000000000000000000000000000000000000000000000000000000000afe0000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000b020000000000000000000000000000000000000000000000000000000000000b040000000000000000000000000000000000000000000000000000000000000b060000000000000000000000000000000000000000000000000000000000000b080000000000000000000000000000000000000000000000000000000000000b0a0000000000000000000000000000000000000000000000000000000000000b0c0000000000000000000000000000000000000000000000000000000000000b0e0000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000b120000000000000000000000000000000000000000000000000000000000000b140000000000000000000000000000000000000000000000000000000000000b160000000000000000000000000000000000000000000000000000000000000b180000000000000000000000000000000000000000000000000000000000000b1a0000000000000000000000000000000000000000000000000000000000000b1c0000000000000000000000000000000000000000000000000000000000000b1e0000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000b220000000000000000000000000000000000000000000000000000000000000b240000000000000000000000000000000000000000000000000000000000000b260000000000000000000000000000000000000000000000000000000000000b280000000000000000000000000000000000000000000000000000000000000b2a0000000000000000000000000000000000000000000000000000000000000b2c0000000000000000000000000000000000000000000000000000000000000b2e0000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000b320000000000000000000000000000000000000000000000000000000000000b340000000000000000000000000000000000000000000000000000000000000b360000000000000000000000000000000000000000000000000000000000000b380000000000000000000000000000000000000000000000000000000000000b3a0000000000000000000000000000000000000000000000000000000000000b3c0000000000000000000000000000000000000000000000000000000000000b3e0000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000b420000000000000000000000000000000000000000000000000000000000000b440000000000000000000000000000000000000000000000000000000000000b460000000000000000000000000000000000000000000000000000000000000b480000000000000000000000000000000000000000000000000000000000000b4a0000000000000000000000000000000000000000000000000000000000000b4c0000000000000000000000000000000000000000000000000000000000000b4e0000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000b520000000000000000000000000000000000000000000000000000000000000b540000000000000000000000000000000000000000000000000000000000000b560000000000000000000000000000000000000000000000000000000000000b580000000000000000000000000000000000000000000000000000000000000b5a0000000000000000000000000000000000000000000000000000000000000b5c0000000000000000000000000000000000000000000000000000000000000b5e0000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000b620000000000000000000000000000000000000000000000000000000000000b640000000000000000000000000000000000000000000000000000000000000b660000000000000000000000000000000000000000000000000000000000000b680000000000000000000000000000000000000000000000000000000000000b6a0000000000000000000000000000000000000000000000000000000000000b6c0000000000000000000000000000000000000000000000000000000000000b6e0000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000b720000000000000000000000000000000000000000000000000000000000000b740000000000000000000000000000000000000000000000000000000000000b760000000000000000000000000000000000000000000000000000000000000b780000000000000000000000000000000000000000000000000000000000000b7a0000000000000000000000000000000000000000000000000000000000000b7c0000000000000000000000000000000000000000000000000000000000000b7e0000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000b820000000000000000000000000000000000000000000000000000000000000b840000000000000000000000000000000000000000000000000000000000000b860000000000000000000000000000000000000000000000000000000000000b880000000000000000000000000000000000000000000000000000000000000b8a0000000000000000000000000000000000000000000000000000000000000b8c0000000000000000000000000000000000000000000000000000000000000b8e0000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000b920000000000000000000000000000000000000000000000000000000000000b940000000000000000000000000000000000000000000000000000000000000b960000000000000000000000000000000000000000000000000000000000000b980000000000000000000000000000000000000000000000000000000000000b9a0000000000000000000000000000000000000000000000000000000000000b9c0000000000000000000000000000000000000000000000000000000000000b9e0000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000ba20000000000000000000000000000000000000000000000000000000000000ba40000000000000000000000000000000000000000000000000000000000000ba60000000000000000000000000000000000000000000000000000000000000ba80000000000000000000000000000000000000000000000000000000000000baa0000000000000000000000000000000000000000000000000000000000000bac0000000000000000000000000000000000000000000000000000000000000bae0000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000bb20000000000000000000000000000000000000000000000000000000000000bb40000000000000000000000000000000000000000000000000000000000000bb60000000000000000000000000000000000000000000000000000000000000bb80000000000000000000000000000000000000000000000000000000000000bba0000000000000000000000000000000000000000000000000000000000000bbc0000000000000000000000000000000000000000000000000000000000000bbe0000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000bc20000000000000000000000000000000000000000000000000000000000000bc40000000000000000000000000000000000000000000000000000000000000bc60000000000000000000000000000000000000000000000000000000000000bc80000000000000000000000000000000000000000000000000000000000000bca0000000000000000000000000000000000000000000000000000000000000bcc0000000000000000000000000000000000000000000000000000000000000bce0000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000bd20000000000000000000000000000000000000000000000000000000000000bd40000000000000000000000000000000000000000000000000000000000000bd60000000000000000000000000000000000000000000000000000000000000bd80000000000000000000000000000000000000000000000000000000000000bda0000000000000000000000000000000000000000000000000000000000000bdc0000000000000000000000000000000000000000000000000000000000000bde0000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000be20000000000000000000000000000000000000000000000000000000000000be40000000000000000000000000000000000000000000000000000000000000be60000000000000000000000000000000000000000000000000000000000000be80000000000000000000000000000000000000000000000000000000000000bea0000000000000000000000000000000000000000000000000000000000000bec0000000000000000000000000000000000000000000000000000000000000bee0000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000bf20000000000000000000000000000000000000000000000000000000000000bf40000000000000000000000000000000000000000000000000000000000000bf60000000000000000000000000000000000000000000000000000000000000bf80000000000000000000000000000000000000000000000000000000000000bfa0000000000000000000000000000000000000000000000000000000000000bfc0000000000000000000000000000000000000000000000000000000000000bfe0000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c020000000000000000000000000000000000000000000000000000000000000c040000000000000000000000000000000000000000000000000000000000000c060000000000000000000000000000000000000000000000000000000000000c080000000000000000000000000000000000000000000000000000000000000c0a0000000000000000000000000000000000000000000000000000000000000c0c0000000000000000000000000000000000000000000000000000000000000c0e0000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c120000000000000000000000000000000000000000000000000000000000000c140000000000000000000000000000000000000000000000000000000000000c160000000000000000000000000000000000000000000000000000000000000c180000000000000000000000000000000000000000000000000000000000000c1a0000000000000000000000000000000000000000000000000000000000000c1c0000000000000000000000000000000000000000000000000000000000000c1e0000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c220000000000000000000000000000000000000000000000000000000000000c240000000000000000000000000000000000000000000000000000000000000c260000000000000000000000000000000000000000000000000000000000000c280000000000000000000000000000000000000000000000000000000000000c2a0000000000000000000000000000000000000000000000000000000000000c2c0000000000000000000000000000000000000000000000000000000000000c2e0000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000c320000000000000000000000000000000000000000000000000000000000000c340000000000000000000000000000000000000000000000000000000000000c360000000000000000000000000000000000000000000000000000000000000c380000000000000000000000000000000000000000000000000000000000000c3a0000000000000000000000000000000000000000000000000000000000000c3c0000000000000000000000000000000000000000000000000000000000000c3e0000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000c420000000000000000000000000000000000000000000000000000000000000c440000000000000000000000000000000000000000000000000000000000000c460000000000000000000000000000000000000000000000000000000000000c480000000000000000000000000000000000000000000000000000000000000c4a0000000000000000000000000000000000000000000000000000000000000c4c0000000000000000000000000000000000000000000000000000000000000c4e0000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000c520000000000000000000000000000000000000000000000000000000000000c540000000000000000000000000000000000000000000000000000000000000c560000000000000000000000000000000000000000000000000000000000000c580000000000000000000000000000000000000000000000000000000000000c5a0000000000000000000000000000000000000000000000000000000000000c5c0000000000000000000000000000000000000000000000000000000000000c5e0000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000c620000000000000000000000000000000000000000000000000000000000000c640000000000000000000000000000000000000000000000000000000000000c660000000000000000000000000000000000000000000000000000000000000c680000000000000000000000000000000000000000000000000000000000000c6a0000000000000000000000000000000000000000000000000000000000000c6c0000000000000000000000000000000000000000000000000000000000000c6e0000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000c720000000000000000000000000000000000000000000000000000000000000c740000000000000000000000000000000000000000000000000000000000000c760000000000000000000000000000000000000000000000000000000000000c780000000000000000000000000000000000000000000000000000000000000c7a0000000000000000000000000000000000000000000000000000000000000c7c0000000000000000000000000000000000000000000000000000000000000c7e0000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000c820000000000000000000000000000000000000000000000000000000000000c840000000000000000000000000000000000000000000000000000000000000c860000000000000000000000000000000000000000000000000000000000000c880000000000000000000000000000000000000000000000000000000000000c8a0000000000000000000000000000000000000000000000000000000000000c8c0000000000000000000000000000000000000000000000000000000000000c8e0000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000c920000000000000000000000000000000000000000000000000000000000000c940000000000000000000000000000000000000000000000000000000000000c960000000000000000000000000000000000000000000000000000000000000c980000000000000000000000000000000000000000000000000000000000000c9a0000000000000000000000000000000000000000000000000000000000000c9c0000000000000000000000000000000000000000000000000000000000000c9e0000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000ca20000000000000000000000000000000000000000000000000000000000000ca40000000000000000000000000000000000000000000000000000000000000ca60000000000000000000000000000000000000000000000000000000000000ca80000000000000000000000000000000000000000000000000000000000000caa0000000000000000000000000000000000000000000000000000000000000cac0000000000000000000000000000000000000000000000000000000000000cae0000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000cb20000000000000000000000000000000000000000000000000000000000000cb40000000000000000000000000000000000000000000000000000000000000cb60000000000000000000000000000000000000000000000000000000000000cb80000000000000000000000000000000000000000000000000000000000000cba0000000000000000000000000000000000000000000000000000000000000cbc0000000000000000000000000000000000000000000000000000000000000cbe0000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000cc20000000000000000000000000000000000000000000000000000000000000cc40000000000000000000000000000000000000000000000000000000000000cc60000000000000000000000000000000000000000000000000000000000000cc80000000000000000000000000000000000000000000000000000000000000cca0000000000000000000000000000000000000000000000000000000000000ccc0000000000000000000000000000000000000000000000000000000000000cce0000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000cd20000000000000000000000000000000000000000000000000000000000000cd40000000000000000000000000000000000000000000000000000000000000cd60000000000000000000000000000000000000000000000000000000000000cd80000000000000000000000000000000000000000000000000000000000000cda0000000000000000000000000000000000000000000000000000000000000cdc0000000000000000000000000000000000000000000000000000000000000cde0000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000ce20000000000000000000000000000000000000000000000000000000000000ce40000000000000000000000000000000000000000000000000000000000000ce60000000000000000000000000000000000000000000000000000000000000ce80000000000000000000000000000000000000000000000000000000000000cea0000000000000000000000000000000000000000000000000000000000000cec0000000000000000000000000000000000000000000000000000000000000cee0000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000cf20000000000000000000000000000000000000000000000000000000000000cf40000000000000000000000000000000000000000000000000000000000000cf60000000000000000000000000000000000000000000000000000000000000cf80000000000000000000000000000000000000000000000000000000000000cfa0000000000000000000000000000000000000000000000000000000000000cfc0000000000000000000000000000000000000000000000000000000000000cfe0000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d020000000000000000000000000000000000000000000000000000000000000d040000000000000000000000000000000000000000000000000000000000000d060000000000000000000000000000000000000000000000000000000000000d080000000000000000000000000000000000000000000000000000000000000d0a0000000000000000000000000000000000000000000000000000000000000d0c0000000000000000000000000000000000000000000000000000000000000d0e0000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000d120000000000000000000000000000000000000000000000000000000000000d140000000000000000000000000000000000000000000000000000000000000d160000000000000000000000000000000000000000000000000000000000000d180000000000000000000000000000000000000000000000000000000000000d1a0000000000000000000000000000000000000000000000000000000000000d1c0000000000000000000000000000000000000000000000000000000000000d1e0000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000d220000000000000000000000000000000000000000000000000000000000000d240000000000000000000000000000000000000000000000000000000000000d260000000000000000000000000000000000000000000000000000000000000d280000000000000000000000000000000000000000000000000000000000000d2a0000000000000000000000000000000000000000000000000000000000000d2c0000000000000000000000000000000000000000000000000000000000000d2e0000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000d320000000000000000000000000000000000000000000000000000000000000d340000000000000000000000000000000000000000000000000000000000000d360000000000000000000000000000000000000000000000000000000000000d380000000000000000000000000000000000000000000000000000000000000d3a0000000000000000000000000000000000000000000000000000000000000d3c0000000000000000000000000000000000000000000000000000000000000d3e0000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000d420000000000000000000000000000000000000000000000000000000000000d440000000000000000000000000000000000000000000000000000000000000d460000000000000000000000000000000000000000000000000000000000000d480000000000000000000000000000000000000000000000000000000000000d4a0000000000000000000000000000000000000000000000000000000000000d4c0000000000000000000000000000000000000000000000000000000000000d4e0000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000d520000000000000000000000000000000000000000000000000000000000000d540000000000000000000000000000000000000000000000000000000000000d560000000000000000000000000000000000000000000000000000000000000d580000000000000000000000000000000000000000000000000000000000000d5a0000000000000000000000000000000000000000000000000000000000000d5c0000000000000000000000000000000000000000000000000000000000000d5e0000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000d620000000000000000000000000000000000000000000000000000000000000d640000000000000000000000000000000000000000000000000000000000000d660000000000000000000000000000000000000000000000000000000000000d680000000000000000000000000000000000000000000000000000000000000d6a0000000000000000000000000000000000000000000000000000000000000d6c0000000000000000000000000000000000000000000000000000000000000d6e0000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000d720000000000000000000000000000000000000000000000000000000000000d740000000000000000000000000000000000000000000000000000000000000d760000000000000000000000000000000000000000000000000000000000000d780000000000000000000000000000000000000000000000000000000000000d7a0000000000000000000000000000000000000000000000000000000000000d7c0000000000000000000000000000000000000000000000000000000000000d7e0000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000d820000000000000000000000000000000000000000000000000000000000000d840000000000000000000000000000000000000000000000000000000000000d860000000000000000000000000000000000000000000000000000000000000d880000000000000000000000000000000000000000000000000000000000000d8a0000000000000000000000000000000000000000000000000000000000000d8c0000000000000000000000000000000000000000000000000000000000000d8e0000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000d920000000000000000000000000000000000000000000000000000000000000d940000000000000000000000000000000000000000000000000000000000000d960000000000000000000000000000000000000000000000000000000000000d980000000000000000000000000000000000000000000000000000000000000d9a0000000000000000000000000000000000000000000000000000000000000d9c0000000000000000000000000000000000000000000000000000000000000d9e0000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000da20000000000000000000000000000000000000000000000000000000000000da40000000000000000000000000000000000000000000000000000000000000da60000000000000000000000000000000000000000000000000000000000000da80000000000000000000000000000000000000000000000000000000000000daa0000000000000000000000000000000000000000000000000000000000000dac0000000000000000000000000000000000000000000000000000000000000dae0000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000db20000000000000000000000000000000000000000000000000000000000000db40000000000000000000000000000000000000000000000000000000000000db60000000000000000000000000000000000000000000000000000000000000db80000000000000000000000000000000000000000000000000000000000000dba0000000000000000000000000000000000000000000000000000000000000dbc0000000000000000000000000000000000000000000000000000000000000dbe0000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000dc20000000000000000000000000000000000000000000000000000000000000dc40000000000000000000000000000000000000000000000000000000000000dc60000000000000000000000000000000000000000000000000000000000000dc80000000000000000000000000000000000000000000000000000000000000dca0000000000000000000000000000000000000000000000000000000000000dcc0000000000000000000000000000000000000000000000000000000000000dce0000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000dd20000000000000000000000000000000000000000000000000000000000000dd40000000000000000000000000000000000000000000000000000000000000dd60000000000000000000000000000000000000000000000000000000000000dd80000000000000000000000000000000000000000000000000000000000000dda0000000000000000000000000000000000000000000000000000000000000ddc0000000000000000000000000000000000000000000000000000000000000dde0000000000000000000000000000000000000000000000000000000000000de00000000000000000000000000000000000000000000000000000000000000de20000000000000000000000000000000000000000000000000000000000000de40000000000000000000000000000000000000000000000000000000000000de60000000000000000000000000000000000000000000000000000000000000de80000000000000000000000000000000000000000000000000000000000000dea0000000000000000000000000000000000000000000000000000000000000dec0000000000000000000000000000000000000000000000000000000000000dee0000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000df20000000000000000000000000000000000000000000000000000000000000df40000000000000000000000000000000000000000000000000000000000000df60000000000000000000000000000000000000000000000000000000000000df80000000000000000000000000000000000000000000000000000000000000dfa0000000000000000000000000000000000000000000000000000000000000dfc0000000000000000000000000000000000000000000000000000000000000dfe0000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000e020000000000000000000000000000000000000000000000000000000000000e040000000000000000000000000000000000000000000000000000000000000e060000000000000000000000000000000000000000000000000000000000000e080000000000000000000000000000000000000000000000000000000000000e0a0000000000000000000000000000000000000000000000000000000000000e0c0000000000000000000000000000000000000000000000000000000000000e0e0000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000e120000000000000000000000000000000000000000000000000000000000000e140000000000000000000000000000000000000000000000000000000000000e160000000000000000000000000000000000000000000000000000000000000e180000000000000000000000000000000000000000000000000000000000000e1a0000000000000000000000000000000000000000000000000000000000000e1c0000000000000000000000000000000000000000000000000000000000000e1e0000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000e220000000000000000000000000000000000000000000000000000000000000e240000000000000000000000000000000000000000000000000000000000000e260000000000000000000000000000000000000000000000000000000000000e280000000000000000000000000000000000000000000000000000000000000e2a0000000000000000000000000000000000000000000000000000000000000e2c0000000000000000000000000000000000000000000000000000000000000e2e0000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000e320000000000000000000000000000000000000000000000000000000000000e340000000000000000000000000000000000000000000000000000000000000e360000000000000000000000000000000000000000000000000000000000000e380000000000000000000000000000000000000000000000000000000000000e3a0000000000000000000000000000000000000000000000000000000000000e3c0000000000000000000000000000000000000000000000000000000000000e3e0000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000e420000000000000000000000000000000000000000000000000000000000000e440000000000000000000000000000000000000000000000000000000000000e460000000000000000000000000000000000000000000000000000000000000e480000000000000000000000000000000000000000000000000000000000000e4a0000000000000000000000000000000000000000000000000000000000000e4c0000000000000000000000000000000000000000000000000000000000000e4e0000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000e520000000000000000000000000000000000000000000000000000000000000e540000000000000000000000000000000000000000000000000000000000000e560000000000000000000000000000000000000000000000000000000000000e580000000000000000000000000000000000000000000000000000000000000e5a0000000000000000000000000000000000000000000000000000000000000e5c0000000000000000000000000000000000000000000000000000000000000e5e0000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000e620000000000000000000000000000000000000000000000000000000000000e640000000000000000000000000000000000000000000000000000000000000e660000000000000000000000000000000000000000000000000000000000000e680000000000000000000000000000000000000000000000000000000000000e6a0000000000000000000000000000000000000000000000000000000000000e6c0000000000000000000000000000000000000000000000000000000000000e6e0000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000e720000000000000000000000000000000000000000000000000000000000000e740000000000000000000000000000000000000000000000000000000000000e760000000000000000000000000000000000000000000000000000000000000e780000000000000000000000000000000000000000000000000000000000000e7a0000000000000000000000000000000000000000000000000000000000000e7c0000000000000000000000000000000000000000000000000000000000000e7e0000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000e820000000000000000000000000000000000000000000000000000000000000e840000000000000000000000000000000000000000000000000000000000000e860000000000000000000000000000000000000000000000000000000000000e880000000000000000000000000000000000000000000000000000000000000e8a0000000000000000000000000000000000000000000000000000000000000e8c0000000000000000000000000000000000000000000000000000000000000e8e0000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000e920000000000000000000000000000000000000000000000000000000000000e940000000000000000000000000000000000000000000000000000000000000e960000000000000000000000000000000000000000000000000000000000000e980000000000000000000000000000000000000000000000000000000000000e9a0000000000000000000000000000000000000000000000000000000000000e9c0000000000000000000000000000000000000000000000000000000000000e9e0000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000ea20000000000000000000000000000000000000000000000000000000000000ea40000000000000000000000000000000000000000000000000000000000000ea60000000000000000000000000000000000000000000000000000000000000ea80000000000000000000000000000000000000000000000000000000000000eaa0000000000000000000000000000000000000000000000000000000000000eac0000000000000000000000000000000000000000000000000000000000000eae0000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000eb20000000000000000000000000000000000000000000000000000000000000eb40000000000000000000000000000000000000000000000000000000000000eb60000000000000000000000000000000000000000000000000000000000000eb80000000000000000000000000000000000000000000000000000000000000eba0000000000000000000000000000000000000000000000000000000000000ebc0000000000000000000000000000000000000000000000000000000000000ebe0000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000ec20000000000000000000000000000000000000000000000000000000000000ec40000000000000000000000000000000000000000000000000000000000000ec60000000000000000000000000000000000000000000000000000000000000ec80000000000000000000000000000000000000000000000000000000000000eca0000000000000000000000000000000000000000000000000000000000000ecc0000000000000000000000000000000000000000000000000000000000000ece0000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000ed20000000000000000000000000000000000000000000000000000000000000ed40000000000000000000000000000000000000000000000000000000000000ed60000000000000000000000000000000000000000000000000000000000000ed80000000000000000000000000000000000000000000000000000000000000eda0000000000000000000000000000000000000000000000000000000000000edc0000000000000000000000000000000000000000000000000000000000000ede0000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000ee20000000000000000000000000000000000000000000000000000000000000ee40000000000000000000000000000000000000000000000000000000000000ee60000000000000000000000000000000000000000000000000000000000000ee80000000000000000000000000000000000000000000000000000000000000eea0000000000000000000000000000000000000000000000000000000000000eec0000000000000000000000000000000000000000000000000000000000000eee0000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000ef20000000000000000000000000000000000000000000000000000000000000ef40000000000000000000000000000000000000000000000000000000000000ef60000000000000000000000000000000000000000000000000000000000000ef80000000000000000000000000000000000000000000000000000000000000efa0000000000000000000000000000000000000000000000000000000000000efc0000000000000000000000000000000000000000000000000000000000000efe0000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000f020000000000000000000000000000000000000000000000000000000000000f040000000000000000000000000000000000000000000000000000000000000f060000000000000000000000000000000000000000000000000000000000000f080000000000000000000000000000000000000000000000000000000000000f0a0000000000000000000000000000000000000000000000000000000000000f0c0000000000000000000000000000000000000000000000000000000000000f0e0000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000f120000000000000000000000000000000000000000000000000000000000000f140000000000000000000000000000000000000000000000000000000000000f160000000000000000000000000000000000000000000000000000000000000f180000000000000000000000000000000000000000000000000000000000000f1a0000000000000000000000000000000000000000000000000000000000000f1c0000000000000000000000000000000000000000000000000000000000000f1e0000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000f220000000000000000000000000000000000000000000000000000000000000f240000000000000000000000000000000000000000000000000000000000000f260000000000000000000000000000000000000000000000000000000000000f280000000000000000000000000000000000000000000000000000000000000f2a0000000000000000000000000000000000000000000000000000000000000f2c0000000000000000000000000000000000000000000000000000000000000f2e0000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000f320000000000000000000000000000000000000000000000000000000000000f340000000000000000000000000000000000000000000000000000000000000f360000000000000000000000000000000000000000000000000000000000000f380000000000000000000000000000000000000000000000000000000000000f3a0000000000000000000000000000000000000000000000000000000000000f3c0000000000000000000000000000000000000000000000000000000000000f3e0000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000f420000000000000000000000000000000000000000000000000000000000000f440000000000000000000000000000000000000000000000000000000000000f460000000000000000000000000000000000000000000000000000000000000f480000000000000000000000000000000000000000000000000000000000000f4a0000000000000000000000000000000000000000000000000000000000000f4c0000000000000000000000000000000000000000000000000000000000000f4e0000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000f520000000000000000000000000000000000000000000000000000000000000f540000000000000000000000000000000000000000000000000000000000000f560000000000000000000000000000000000000000000000000000000000000f580000000000000000000000000000000000000000000000000000000000000f5a0000000000000000000000000000000000000000000000000000000000000f5c0000000000000000000000000000000000000000000000000000000000000f5e0000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000f620000000000000000000000000000000000000000000000000000000000000f640000000000000000000000000000000000000000000000000000000000000f660000000000000000000000000000000000000000000000000000000000000f680000000000000000000000000000000000000000000000000000000000000f6a0000000000000000000000000000000000000000000000000000000000000f6c0000000000000000000000000000000000000000000000000000000000000f6e0000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000f720000000000000000000000000000000000000000000000000000000000000f740000000000000000000000000000000000000000000000000000000000000f760000000000000000000000000000000000000000000000000000000000000f780000000000000000000000000000000000000000000000000000000000000f7a0000000000000000000000000000000000000000000000000000000000000f7c0000000000000000000000000000000000000000000000000000000000000f7e0000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000f820000000000000000000000000000000000000000000000000000000000000f840000000000000000000000000000000000000000000000000000000000000f860000000000000000000000000000000000000000000000000000000000000f880000000000000000000000000000000000000000000000000000000000000f8a0000000000000000000000000000000000000000000000000000000000000f8c0000000000000000000000000000000000000000000000000000000000000f8e0000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000f920000000000000000000000000000000000000000000000000000000000000f940000000000000000000000000000000000000000000000000000000000000f960000000000000000000000000000000000000000000000000000000000000f980000000000000000000000000000000000000000000000000000000000000f9a0000000000000000000000000000000000000000000000000000000000000f9c0000000000000000000000000000000000000000000000000000000000000f9e0000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000fa20000000000000000000000000000000000000000000000000000000000000fa40000000000000000000000000000000000000000000000000000000000000fa60000000000000000000000000000000000000000000000000000000000000fa80000000000000000000000000000000000000000000000000000000000000faa0000000000000000000000000000000000000000000000000000000000000fac0000000000000000000000000000000000000000000000000000000000000fae0000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000fb20000000000000000000000000000000000000000000000000000000000000fb40000000000000000000000000000000000000000000000000000000000000fb60000000000000000000000000000000000000000000000000000000000000fb80000000000000000000000000000000000000000000000000000000000000fba0000000000000000000000000000000000000000000000000000000000000fbc0000000000000000000000000000000000000000000000000000000000000fbe0000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000fc20000000000000000000000000000000000000000000000000000000000000fc40000000000000000000000000000000000000000000000000000000000000fc60000000000000000000000000000000000000000000000000000000000000fc80000000000000000000000000000000000000000000000000000000000000fca0000000000000000000000000000000000000000000000000000000000000fcc0000000000000000000000000000000000000000000000000000000000000fce0000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000fd20000000000000000000000000000000000000000000000000000000000000fd40000000000000000000000000000000000000000000000000000000000000fd60000000000000000000000000000000000000000000000000000000000000fd80000000000000000000000000000000000000000000000000000000000000fda0000000000000000000000000000000000000000000000000000000000000fdc0000000000000000000000000000000000000000000000000000000000000fde0000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000fe20000000000000000000000000000000000000000000000000000000000000fe40000000000000000000000000000000000000000000000000000000000000fe60000000000000000000000000000000000000000000000000000000000000fe80000000000000000000000000000000000000000000000000000000000000fea0000000000000000000000000000000000000000000000000000000000000fec0000000000000000000000000000000000000000000000000000000000000fee0000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000ff20000000000000000000000000000000000000000000000000000000000000ff40000000000000000000000000000000000000000000000000000000000000ff60000000000000000000000000000000000000000000000000000000000000ff80000000000000000000000000000000000000000000000000000000000000ffa0000000000000000000000000000000000000000000000000000000000000ffc0000000000000000000000000000000000000000000000000000000000000ffe00000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001002000000000000000000000000000000000000000000000000000000000000100400000000000000000000000000000000000000000000000000000000000010060000000000000000000000000000000000000000000000000000000000001008000000000000000000000000000000000000000000000000000000000000100a000000000000000000000000000000000000000000000000000000000000100c000000000000000000000000000000000000000000000000000000000000100e00000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001012000000000000000000000000000000000000000000000000000000000000101400000000000000000000000000000000000000000000000000000000000010160000000000000000000000000000000000000000000000000000000000001018000000000000000000000000000000000000000000000000000000000000101a000000000000000000000000000000000000000000000000000000000000101c000000000000000000000000000000000000000000000000000000000000101e00000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000001022000000000000000000000000000000000000000000000000000000000000102400000000000000000000000000000000000000000000000000000000000010260000000000000000000000000000000000000000000000000000000000001028000000000000000000000000000000000000000000000000000000000000102a000000000000000000000000000000000000000000000000000000000000102c000000000000000000000000000000000000000000000000000000000000102e00000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000000000000000000000000000000001032000000000000000000000000000000000000000000000000000000000000103400000000000000000000000000000000000000000000000000000000000010360000000000000000000000000000000000000000000000000000000000001038000000000000000000000000000000000000000000000000000000000000103a000000000000000000000000000000000000000000000000000000000000103c000000000000000000000000000000000000000000000000000000000000103e00000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001042000000000000000000000000000000000000000000000000000000000000104400000000000000000000000000000000000000000000000000000000000010460000000000000000000000000000000000000000000000000000000000001048000000000000000000000000000000000000000000000000000000000000104a000000000000000000000000000000000000000000000000000000000000104c000000000000000000000000000000000000000000000000000000000000104e00000000000000000000000000000000000000000000000000000000000010500000000000000000000000000000000000000000000000000000000000001052000000000000000000000000000000000000000000000000000000000000105400000000000000000000000000000000000000000000000000000000000010560000000000000000000000000000000000000000000000000000000000001058000000000000000000000000000000000000000000000000000000000000105a000000000000000000000000000000000000000000000000000000000000105c000000000000000000000000000000000000000000000000000000000000105e00000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000001062000000000000000000000000000000000000000000000000000000000000106400000000000000000000000000000000000000000000000000000000000010660000000000000000000000000000000000000000000000000000000000001068000000000000000000000000000000000000000000000000000000000000106a000000000000000000000000000000000000000000000000000000000000106c000000000000000000000000000000000000000000000000000000000000106e00000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001072000000000000000000000000000000000000000000000000000000000000107400000000000000000000000000000000000000000000000000000000000010760000000000000000000000000000000000000000000000000000000000001078000000000000000000000000000000000000000000000000000000000000107a000000000000000000000000000000000000000000000000000000000000107c000000000000000000000000000000000000000000000000000000000000107e00000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000000000000000000000000000001082000000000000000000000000000000000000000000000000000000000000108400000000000000000000000000000000000000000000000000000000000010860000000000000000000000000000000000000000000000000000000000001088000000000000000000000000000000000000000000000000000000000000108a000000000000000000000000000000000000000000000000000000000000108c000000000000000000000000000000000000000000000000000000000000108e00000000000000000000000000000000000000000000000000000000000010900000000000000000000000000000000000000000000000000000000000001092000000000000000000000000000000000000000000000000000000000000109400000000000000000000000000000000000000000000000000000000000010960000000000000000000000000000000000000000000000000000000000001098000000000000000000000000000000000000000000000000000000000000109a000000000000000000000000000000000000000000000000000000000000109c000000000000000000000000000000000000000000000000000000000000109e00000000000000000000000000000000000000000000000000000000000010a000000000000000000000000000000000000000000000000000000000000010a200000000000000000000000000000000000000000000000000000000000010a400000000000000000000000000000000000000000000000000000000000010a600000000000000000000000000000000000000000000000000000000000010a800000000000000000000000000000000000000000000000000000000000010aa00000000000000000000000000000000000000000000000000000000000010ac00000000000000000000000000000000000000000000000000000000000010ae00000000000000000000000000000000000000000000000000000000000010b000000000000000000000000000000000000000000000000000000000000010b200000000000000000000000000000000000000000000000000000000000010b400000000000000000000000000000000000000000000000000000000000010b600000000000000000000000000000000000000000000000000000000000010b800000000000000000000000000000000000000000000000000000000000010ba00000000000000000000000000000000000000000000000000000000000010bc00000000000000000000000000000000000000000000000000000000000010be00000000000000000000000000000000000000000000000000000000000010c000000000000000000000000000000000000000000000000000000000000010c200000000000000000000000000000000000000000000000000000000000010c400000000000000000000000000000000000000000000000000000000000010c600000000000000000000000000000000000000000000000000000000000010c800000000000000000000000000000000000000000000000000000000000010ca00000000000000000000000000000000000000000000000000000000000010cc00000000000000000000000000000000000000000000000000000000000010ce00000000000000000000000000000000000000000000000000000000000010d000000000000000000000000000000000000000000000000000000000000010d200000000000000000000000000000000000000000000000000000000000010d400000000000000000000000000000000000000000000000000000000000010d600000000000000000000000000000000000000000000000000000000000010d800000000000000000000000000000000000000000000000000000000000010da00000000000000000000000000000000000000000000000000000000000010dc00000000000000000000000000000000000000000000000000000000000010de00000000000000000000000000000000000000000000000000000000000010e000000000000000000000000000000000000000000000000000000000000010e200000000000000000000000000000000000000000000000000000000000010e400000000000000000000000000000000000000000000000000000000000010e600000000000000000000000000000000000000000000000000000000000010e800000000000000000000000000000000000000000000000000000000000010ea00000000000000000000000000000000000000000000000000000000000010ec00000000000000000000000000000000000000000000000000000000000010ee00000000000000000000000000000000000000000000000000000000000010f000000000000000000000000000000000000000000000000000000000000010f200000000000000000000000000000000000000000000000000000000000010f400000000000000000000000000000000000000000000000000000000000010f600000000000000000000000000000000000000000000000000000000000010f800000000000000000000000000000000000000000000000000000000000010fa00000000000000000000000000000000000000000000000000000000000010fc00000000000000000000000000000000000000000000000000000000000010fe00000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001102000000000000000000000000000000000000000000000000000000000000110400000000000000000000000000000000000000000000000000000000000011060000000000000000000000000000000000000000000000000000000000001108000000000000000000000000000000000000000000000000000000000000110a000000000000000000000000000000000000000000000000000000000000110c000000000000000000000000000000000000000000000000000000000000110e00000000000000000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000000000000000001112000000000000000000000000000000000000000000000000000000000000111400000000000000000000000000000000000000000000000000000000000011160000000000000000000000000000000000000000000000000000000000001118000000000000000000000000000000000000000000000000000000000000111a000000000000000000000000000000000000000000000000000000000000111c000000000000000000000000000000000000000000000000000000000000111e00000000000000000000000000000000000000000000000000000000000011200000000000000000000000000000000000000000000000000000000000001122000000000000000000000000000000000000000000000000000000000000112400000000000000000000000000000000000000000000000000000000000011260000000000000000000000000000000000000000000000000000000000001128000000000000000000000000000000000000000000000000000000000000112a000000000000000000000000000000000000000000000000000000000000112c000000000000000000000000000000000000000000000000000000000000112e00000000000000000000000000000000000000000000000000000000000011300000000000000000000000000000000000000000000000000000000000001132000000000000000000000000000000000000000000000000000000000000113400000000000000000000000000000000000000000000000000000000000011360000000000000000000000000000000000000000000000000000000000001138000000000000000000000000000000000000000000000000000000000000113a000000000000000000000000000000000000000000000000000000000000113c000000000000000000000000000000000000000000000000000000000000113e00000000000000000000000000000000000000000000000000000000000011400000000000000000000000000000000000000000000000000000000000001142000000000000000000000000000000000000000000000000000000000000114400000000000000000000000000000000000000000000000000000000000011460000000000000000000000000000000000000000000000000000000000001148000000000000000000000000000000000000000000000000000000000000114a000000000000000000000000000000000000000000000000000000000000114c000000000000000000000000000000000000000000000000000000000000114e00000000000000000000000000000000000000000000000000000000000011500000000000000000000000000000000000000000000000000000000000001152000000000000000000000000000000000000000000000000000000000000115400000000000000000000000000000000000000000000000000000000000011560000000000000000000000000000000000000000000000000000000000001158000000000000000000000000000000000000000000000000000000000000115a000000000000000000000000000000000000000000000000000000000000115c000000000000000000000000000000000000000000000000000000000000115e00000000000000000000000000000000000000000000000000000000000011600000000000000000000000000000000000000000000000000000000000001162000000000000000000000000000000000000000000000000000000000000116400000000000000000000000000000000000000000000000000000000000011660000000000000000000000000000000000000000000000000000000000001168000000000000000000000000000000000000000000000000000000000000116a000000000000000000000000000000000000000000000000000000000000116c000000000000000000000000000000000000000000000000000000000000116e00000000000000000000000000000000000000000000000000000000000011700000000000000000000000000000000000000000000000000000000000001172000000000000000000000000000000000000000000000000000000000000117400000000000000000000000000000000000000000000000000000000000011760000000000000000000000000000000000000000000000000000000000001178000000000000000000000000000000000000000000000000000000000000117a000000000000000000000000000000000000000000000000000000000000117c000000000000000000000000000000000000000000000000000000000000117e00000000000000000000000000000000000000000000000000000000000011800000000000000000000000000000000000000000000000000000000000001182000000000000000000000000000000000000000000000000000000000000118400000000000000000000000000000000000000000000000000000000000011860000000000000000000000000000000000000000000000000000000000001188000000000000000000000000000000000000000000000000000000000000118a000000000000000000000000000000000000000000000000000000000000118c000000000000000000000000000000000000000000000000000000000000118e00000000000000000000000000000000000000000000000000000000000011900000000000000000000000000000000000000000000000000000000000001192000000000000000000000000000000000000000000000000000000000000119400000000000000000000000000000000000000000000000000000000000011960000000000000000000000000000000000000000000000000000000000001198000000000000000000000000000000000000000000000000000000000000119a000000000000000000000000000000000000000000000000000000000000119c000000000000000000000000000000000000000000000000000000000000119e00000000000000000000000000000000000000000000000000000000000011a000000000000000000000000000000000000000000000000000000000000011a200000000000000000000000000000000000000000000000000000000000011a400000000000000000000000000000000000000000000000000000000000011a600000000000000000000000000000000000000000000000000000000000011a800000000000000000000000000000000000000000000000000000000000011aa00000000000000000000000000000000000000000000000000000000000011ac00000000000000000000000000000000000000000000000000000000000011ae00000000000000000000000000000000000000000000000000000000000011b000000000000000000000000000000000000000000000000000000000000011b200000000000000000000000000000000000000000000000000000000000011b400000000000000000000000000000000000000000000000000000000000011b600000000000000000000000000000000000000000000000000000000000011b800000000000000000000000000000000000000000000000000000000000011ba00000000000000000000000000000000000000000000000000000000000011bc00000000000000000000000000000000000000000000000000000000000011be00000000000000000000000000000000000000000000000000000000000011c000000000000000000000000000000000000000000000000000000000000011c200000000000000000000000000000000000000000000000000000000000011c400000000000000000000000000000000000000000000000000000000000011c600000000000000000000000000000000000000000000000000000000000011c800000000000000000000000000000000000000000000000000000000000011ca00000000000000000000000000000000000000000000000000000000000011cc00000000000000000000000000000000000000000000000000000000000011ce00000000000000000000000000000000000000000000000000000000000011d000000000000000000000000000000000000000000000000000000000000011d200000000000000000000000000000000000000000000000000000000000011d400000000000000000000000000000000000000000000000000000000000011d600000000000000000000000000000000000000000000000000000000000011d800000000000000000000000000000000000000000000000000000000000011da00000000000000000000000000000000000000000000000000000000000011dc00000000000000000000000000000000000000000000000000000000000011de00000000000000000000000000000000000000000000000000000000000011e000000000000000000000000000000000000000000000000000000000000011e200000000000000000000000000000000000000000000000000000000000011e400000000000000000000000000000000000000000000000000000000000011e600000000000000000000000000000000000000000000000000000000000011e800000000000000000000000000000000000000000000000000000000000011ea00000000000000000000000000000000000000000000000000000000000011ec00000000000000000000000000000000000000000000000000000000000011ee00000000000000000000000000000000000000000000000000000000000011f000000000000000000000000000000000000000000000000000000000000011f200000000000000000000000000000000000000000000000000000000000011f400000000000000000000000000000000000000000000000000000000000011f600000000000000000000000000000000000000000000000000000000000011f800000000000000000000000000000000000000000000000000000000000011fa00000000000000000000000000000000000000000000000000000000000011fc00000000000000000000000000000000000000000000000000000000000011fe00000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001202000000000000000000000000000000000000000000000000000000000000120400000000000000000000000000000000000000000000000000000000000012060000000000000000000000000000000000000000000000000000000000001208000000000000000000000000000000000000000000000000000000000000120a000000000000000000000000000000000000000000000000000000000000120c000000000000000000000000000000000000000000000000000000000000120e00000000000000000000000000000000000000000000000000000000000012100000000000000000000000000000000000000000000000000000000000001212000000000000000000000000000000000000000000000000000000000000121400000000000000000000000000000000000000000000000000000000000012160000000000000000000000000000000000000000000000000000000000001218000000000000000000000000000000000000000000000000000000000000121a000000000000000000000000000000000000000000000000000000000000121c000000000000000000000000000000000000000000000000000000000000121e00000000000000000000000000000000000000000000000000000000000012200000000000000000000000000000000000000000000000000000000000001222000000000000000000000000000000000000000000000000000000000000122400000000000000000000000000000000000000000000000000000000000012260000000000000000000000000000000000000000000000000000000000001228000000000000000000000000000000000000000000000000000000000000122a000000000000000000000000000000000000000000000000000000000000122c000000000000000000000000000000000000000000000000000000000000122e00000000000000000000000000000000000000000000000000000000000012300000000000000000000000000000000000000000000000000000000000001232000000000000000000000000000000000000000000000000000000000000123400000000000000000000000000000000000000000000000000000000000012360000000000000000000000000000000000000000000000000000000000001238000000000000000000000000000000000000000000000000000000000000123a000000000000000000000000000000000000000000000000000000000000123c000000000000000000000000000000000000000000000000000000000000123e00000000000000000000000000000000000000000000000000000000000012400000000000000000000000000000000000000000000000000000000000001242000000000000000000000000000000000000000000000000000000000000124400000000000000000000000000000000000000000000000000000000000012460000000000000000000000000000000000000000000000000000000000001248000000000000000000000000000000000000000000000000000000000000124a000000000000000000000000000000000000000000000000000000000000124c000000000000000000000000000000000000000000000000000000000000124e00000000000000000000000000000000000000000000000000000000000012500000000000000000000000000000000000000000000000000000000000001252000000000000000000000000000000000000000000000000000000000000125400000000000000000000000000000000000000000000000000000000000012560000000000000000000000000000000000000000000000000000000000001258000000000000000000000000000000000000000000000000000000000000125a000000000000000000000000000000000000000000000000000000000000125c000000000000000000000000000000000000000000000000000000000000125e00000000000000000000000000000000000000000000000000000000000012600000000000000000000000000000000000000000000000000000000000001262000000000000000000000000000000000000000000000000000000000000126400000000000000000000000000000000000000000000000000000000000012660000000000000000000000000000000000000000000000000000000000001268000000000000000000000000000000000000000000000000000000000000126a000000000000000000000000000000000000000000000000000000000000126c000000000000000000000000000000000000000000000000000000000000126e00000000000000000000000000000000000000000000000000000000000012700000000000000000000000000000000000000000000000000000000000001272000000000000000000000000000000000000000000000000000000000000127400000000000000000000000000000000000000000000000000000000000012760000000000000000000000000000000000000000000000000000000000001278000000000000000000000000000000000000000000000000000000000000127a000000000000000000000000000000000000000000000000000000000000127c000000000000000000000000000000000000000000000000000000000000127e00000000000000000000000000000000000000000000000000000000000012800000000000000000000000000000000000000000000000000000000000001282000000000000000000000000000000000000000000000000000000000000128400000000000000000000000000000000000000000000000000000000000012860000000000000000000000000000000000000000000000000000000000001288000000000000000000000000000000000000000000000000000000000000128a000000000000000000000000000000000000000000000000000000000000128c000000000000000000000000000000000000000000000000000000000000128e00000000000000000000000000000000000000000000000000000000000012900000000000000000000000000000000000000000000000000000000000001292000000000000000000000000000000000000000000000000000000000000129400000000000000000000000000000000000000000000000000000000000012960000000000000000000000000000000000000000000000000000000000001298000000000000000000000000000000000000000000000000000000000000129a000000000000000000000000000000000000000000000000000000000000129c000000000000000000000000000000000000000000000000000000000000129e00000000000000000000000000000000000000000000000000000000000012a000000000000000000000000000000000000000000000000000000000000012a200000000000000000000000000000000000000000000000000000000000012a400000000000000000000000000000000000000000000000000000000000012a600000000000000000000000000000000000000000000000000000000000012a800000000000000000000000000000000000000000000000000000000000012aa00000000000000000000000000000000000000000000000000000000000012ac00000000000000000000000000000000000000000000000000000000000012ae00000000000000000000000000000000000000000000000000000000000012b000000000000000000000000000000000000000000000000000000000000012b200000000000000000000000000000000000000000000000000000000000012b400000000000000000000000000000000000000000000000000000000000012b600000000000000000000000000000000000000000000000000000000000012b800000000000000000000000000000000000000000000000000000000000012ba00000000000000000000000000000000000000000000000000000000000012bc00000000000000000000000000000000000000000000000000000000000012be00000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000012c200000000000000000000000000000000000000000000000000000000000012c400000000000000000000000000000000000000000000000000000000000012c600000000000000000000000000000000000000000000000000000000000012c800000000000000000000000000000000000000000000000000000000000012ca00000000000000000000000000000000000000000000000000000000000012cc00000000000000000000000000000000000000000000000000000000000012ce00000000000000000000000000000000000000000000000000000000000012d000000000000000000000000000000000000000000000000000000000000012d200000000000000000000000000000000000000000000000000000000000012d400000000000000000000000000000000000000000000000000000000000012d600000000000000000000000000000000000000000000000000000000000012d800000000000000000000000000000000000000000000000000000000000012da00000000000000000000000000000000000000000000000000000000000012dc00000000000000000000000000000000000000000000000000000000000012de00000000000000000000000000000000000000000000000000000000000012e000000000000000000000000000000000000000000000000000000000000012e200000000000000000000000000000000000000000000000000000000000012e400000000000000000000000000000000000000000000000000000000000012e600000000000000000000000000000000000000000000000000000000000012e800000000000000000000000000000000000000000000000000000000000012ea00000000000000000000000000000000000000000000000000000000000012ec00000000000000000000000000000000000000000000000000000000000012ee00000000000000000000000000000000000000000000000000000000000012f000000000000000000000000000000000000000000000000000000000000012f200000000000000000000000000000000000000000000000000000000000012f400000000000000000000000000000000000000000000000000000000000012f600000000000000000000000000000000000000000000000000000000000012f800000000000000000000000000000000000000000000000000000000000012fa00000000000000000000000000000000000000000000000000000000000012fc00000000000000000000000000000000000000000000000000000000000012fe00000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001302000000000000000000000000000000000000000000000000000000000000130400000000000000000000000000000000000000000000000000000000000013060000000000000000000000000000000000000000000000000000000000001308000000000000000000000000000000000000000000000000000000000000130a000000000000000000000000000000000000000000000000000000000000130c000000000000000000000000000000000000000000000000000000000000130e00000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000001312000000000000000000000000000000000000000000000000000000000000131400000000000000000000000000000000000000000000000000000000000013160000000000000000000000000000000000000000000000000000000000001318000000000000000000000000000000000000000000000000000000000000131a000000000000000000000000000000000000000000000000000000000000131c000000000000000000000000000000000000000000000000000000000000131e00000000000000000000000000000000000000000000000000000000000013200000000000000000000000000000000000000000000000000000000000001322000000000000000000000000000000000000000000000000000000000000132400000000000000000000000000000000000000000000000000000000000013260000000000000000000000000000000000000000000000000000000000001328000000000000000000000000000000000000000000000000000000000000132a000000000000000000000000000000000000000000000000000000000000132c000000000000000000000000000000000000000000000000000000000000132e00000000000000000000000000000000000000000000000000000000000013300000000000000000000000000000000000000000000000000000000000001332000000000000000000000000000000000000000000000000000000000000133400000000000000000000000000000000000000000000000000000000000013360000000000000000000000000000000000000000000000000000000000001338000000000000000000000000000000000000000000000000000000000000133a000000000000000000000000000000000000000000000000000000000000133c000000000000000000000000000000000000000000000000000000000000133e00000000000000000000000000000000000000000000000000000000000013400000000000000000000000000000000000000000000000000000000000001342000000000000000000000000000000000000000000000000000000000000134400000000000000000000000000000000000000000000000000000000000013460000000000000000000000000000000000000000000000000000000000001348000000000000000000000000000000000000000000000000000000000000134a000000000000000000000000000000000000000000000000000000000000134c000000000000000000000000000000000000000000000000000000000000134e00000000000000000000000000000000000000000000000000000000000013500000000000000000000000000000000000000000000000000000000000001352000000000000000000000000000000000000000000000000000000000000135400000000000000000000000000000000000000000000000000000000000013560000000000000000000000000000000000000000000000000000000000001358000000000000000000000000000000000000000000000000000000000000135a000000000000000000000000000000000000000000000000000000000000135c000000000000000000000000000000000000000000000000000000000000135e00000000000000000000000000000000000000000000000000000000000013600000000000000000000000000000000000000000000000000000000000001362000000000000000000000000000000000000000000000000000000000000136400000000000000000000000000000000000000000000000000000000000013660000000000000000000000000000000000000000000000000000000000001368000000000000000000000000000000000000000000000000000000000000136a000000000000000000000000000000000000000000000000000000000000136c000000000000000000000000000000000000000000000000000000000000136e00000000000000000000000000000000000000000000000000000000000013700000000000000000000000000000000000000000000000000000000000001372000000000000000000000000000000000000000000000000000000000000137400000000000000000000000000000000000000000000000000000000000013760000000000000000000000000000000000000000000000000000000000001378000000000000000000000000000000000000000000000000000000000000137a000000000000000000000000000000000000000000000000000000000000137c000000000000000000000000000000000000000000000000000000000000137e00000000000000000000000000000000000000000000000000000000000013800000000000000000000000000000000000000000000000000000000000001382000000000000000000000000000000000000000000000000000000000000138400000000000000000000000000000000000000000000000000000000000013860000000000000000000000000000000000000000000000000000000000001388000000000000000000000000000000000000000000000000000000000000138a000000000000000000000000000000000000000000000000000000000000138c000000000000000000000000000000000000000000000000000000000000138e00000000000000000000000000000000000000000000000000000000000013900000000000000000000000000000000000000000000000000000000000001392000000000000000000000000000000000000000000000000000000000000139400000000000000000000000000000000000000000000000000000000000013960000000000000000000000000000000000000000000000000000000000001398000000000000000000000000000000000000000000000000000000000000139a000000000000000000000000000000000000000000000000000000000000139c000000000000000000000000000000000000000000000000000000000000139e00000000000000000000000000000000000000000000000000000000000013a000000000000000000000000000000000000000000000000000000000000013a200000000000000000000000000000000000000000000000000000000000013a400000000000000000000000000000000000000000000000000000000000013a600000000000000000000000000000000000000000000000000000000000013a800000000000000000000000000000000000000000000000000000000000013aa00000000000000000000000000000000000000000000000000000000000013ac00000000000000000000000000000000000000000000000000000000000013ae00000000000000000000000000000000000000000000000000000000000013b000000000000000000000000000000000000000000000000000000000000013b200000000000000000000000000000000000000000000000000000000000013b400000000000000000000000000000000000000000000000000000000000013b600000000000000000000000000000000000000000000000000000000000013b800000000000000000000000000000000000000000000000000000000000013ba00000000000000000000000000000000000000000000000000000000000013bc00000000000000000000000000000000000000000000000000000000000013be00000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000013c200000000000000000000000000000000000000000000000000000000000013c400000000000000000000000000000000000000000000000000000000000013c600000000000000000000000000000000000000000000000000000000000013c800000000000000000000000000000000000000000000000000000000000013ca00000000000000000000000000000000000000000000000000000000000013cc00000000000000000000000000000000000000000000000000000000000013ce00000000000000000000000000000000000000000000000000000000000013d000000000000000000000000000000000000000000000000000000000000013d200000000000000000000000000000000000000000000000000000000000013d400000000000000000000000000000000000000000000000000000000000013d600000000000000000000000000000000000000000000000000000000000013d800000000000000000000000000000000000000000000000000000000000013da00000000000000000000000000000000000000000000000000000000000013dc00000000000000000000000000000000000000000000000000000000000013de00000000000000000000000000000000000000000000000000000000000013e000000000000000000000000000000000000000000000000000000000000013e200000000000000000000000000000000000000000000000000000000000013e400000000000000000000000000000000000000000000000000000000000013e600000000000000000000000000000000000000000000000000000000000013e800000000000000000000000000000000000000000000000000000000000013ea00000000000000000000000000000000000000000000000000000000000013ec00000000000000000000000000000000000000000000000000000000000013ee00000000000000000000000000000000000000000000000000000000000013f000000000000000000000000000000000000000000000000000000000000013f200000000000000000000000000000000000000000000000000000000000013f400000000000000000000000000000000000000000000000000000000000013f600000000000000000000000000000000000000000000000000000000000013f800000000000000000000000000000000000000000000000000000000000013fa00000000000000000000000000000000000000000000000000000000000013fc00000000000000000000000000000000000000000000000000000000000013fe00000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001402000000000000000000000000000000000000000000000000000000000000140400000000000000000000000000000000000000000000000000000000000014060000000000000000000000000000000000000000000000000000000000001408000000000000000000000000000000000000000000000000000000000000140a000000000000000000000000000000000000000000000000000000000000140c000000000000000000000000000000000000000000000000000000000000140e00000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001412000000000000000000000000000000000000000000000000000000000000141400000000000000000000000000000000000000000000000000000000000014160000000000000000000000000000000000000000000000000000000000001418000000000000000000000000000000000000000000000000000000000000141a000000000000000000000000000000000000000000000000000000000000141c000000000000000000000000000000000000000000000000000000000000141e00000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000001422000000000000000000000000000000000000000000000000000000000000142400000000000000000000000000000000000000000000000000000000000014260000000000000000000000000000000000000000000000000000000000001428000000000000000000000000000000000000000000000000000000000000142a000000000000000000000000000000000000000000000000000000000000142c000000000000000000000000000000000000000000000000000000000000142e00000000000000000000000000000000000000000000000000000000000014300000000000000000000000000000000000000000000000000000000000001432000000000000000000000000000000000000000000000000000000000000143400000000000000000000000000000000000000000000000000000000000014360000000000000000000000000000000000000000000000000000000000001438000000000000000000000000000000000000000000000000000000000000143a000000000000000000000000000000000000000000000000000000000000143c000000000000000000000000000000000000000000000000000000000000143e00000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001442000000000000000000000000000000000000000000000000000000000000144400000000000000000000000000000000000000000000000000000000000014460000000000000000000000000000000000000000000000000000000000001448000000000000000000000000000000000000000000000000000000000000144a000000000000000000000000000000000000000000000000000000000000144c000000000000000000000000000000000000000000000000000000000000144e00000000000000000000000000000000000000000000000000000000000014500000000000000000000000000000000000000000000000000000000000001452000000000000000000000000000000000000000000000000000000000000145400000000000000000000000000000000000000000000000000000000000014560000000000000000000000000000000000000000000000000000000000001458000000000000000000000000000000000000000000000000000000000000145a000000000000000000000000000000000000000000000000000000000000145c000000000000000000000000000000000000000000000000000000000000145e00000000000000000000000000000000000000000000000000000000000014600000000000000000000000000000000000000000000000000000000000001462000000000000000000000000000000000000000000000000000000000000146400000000000000000000000000000000000000000000000000000000000014660000000000000000000000000000000000000000000000000000000000001468000000000000000000000000000000000000000000000000000000000000146a000000000000000000000000000000000000000000000000000000000000146c000000000000000000000000000000000000000000000000000000000000146e00000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001472000000000000000000000000000000000000000000000000000000000000147400000000000000000000000000000000000000000000000000000000000014760000000000000000000000000000000000000000000000000000000000001478000000000000000000000000000000000000000000000000000000000000147a000000000000000000000000000000000000000000000000000000000000147c000000000000000000000000000000000000000000000000000000000000147e00000000000000000000000000000000000000000000000000000000000014800000000000000000000000000000000000000000000000000000000000001482000000000000000000000000000000000000000000000000000000000000148400000000000000000000000000000000000000000000000000000000000014860000000000000000000000000000000000000000000000000000000000001488000000000000000000000000000000000000000000000000000000000000148a000000000000000000000000000000000000000000000000000000000000148c000000000000000000000000000000000000000000000000000000000000148e00000000000000000000000000000000000000000000000000000000000014900000000000000000000000000000000000000000000000000000000000001492000000000000000000000000000000000000000000000000000000000000149400000000000000000000000000000000000000000000000000000000000014960000000000000000000000000000000000000000000000000000000000001498000000000000000000000000000000000000000000000000000000000000149a000000000000000000000000000000000000000000000000000000000000149c000000000000000000000000000000000000000000000000000000000000149e00000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014a200000000000000000000000000000000000000000000000000000000000014a400000000000000000000000000000000000000000000000000000000000014a600000000000000000000000000000000000000000000000000000000000014a800000000000000000000000000000000000000000000000000000000000014aa00000000000000000000000000000000000000000000000000000000000014ac00000000000000000000000000000000000000000000000000000000000014ae00000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014b200000000000000000000000000000000000000000000000000000000000014b400000000000000000000000000000000000000000000000000000000000014b600000000000000000000000000000000000000000000000000000000000014b800000000000000000000000000000000000000000000000000000000000014ba00000000000000000000000000000000000000000000000000000000000014bc00000000000000000000000000000000000000000000000000000000000014be00000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014c200000000000000000000000000000000000000000000000000000000000014c400000000000000000000000000000000000000000000000000000000000014c600000000000000000000000000000000000000000000000000000000000014c800000000000000000000000000000000000000000000000000000000000014ca00000000000000000000000000000000000000000000000000000000000014cc00000000000000000000000000000000000000000000000000000000000014ce00000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014d200000000000000000000000000000000000000000000000000000000000014d400000000000000000000000000000000000000000000000000000000000014d600000000000000000000000000000000000000000000000000000000000014d800000000000000000000000000000000000000000000000000000000000014da00000000000000000000000000000000000000000000000000000000000014dc00000000000000000000000000000000000000000000000000000000000014de00000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014e200000000000000000000000000000000000000000000000000000000000014e400000000000000000000000000000000000000000000000000000000000014e600000000000000000000000000000000000000000000000000000000000014e800000000000000000000000000000000000000000000000000000000000014ea00000000000000000000000000000000000000000000000000000000000014ec00000000000000000000000000000000000000000000000000000000000014ee00000000000000000000000000000000000000000000000000000000000014f000000000000000000000000000000000000000000000000000000000000014f200000000000000000000000000000000000000000000000000000000000014f400000000000000000000000000000000000000000000000000000000000014f600000000000000000000000000000000000000000000000000000000000014f800000000000000000000000000000000000000000000000000000000000014fa00000000000000000000000000000000000000000000000000000000000014fc00000000000000000000000000000000000000000000000000000000000014fe00000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000001502000000000000000000000000000000000000000000000000000000000000150400000000000000000000000000000000000000000000000000000000000015060000000000000000000000000000000000000000000000000000000000001508000000000000000000000000000000000000000000000000000000000000150a000000000000000000000000000000000000000000000000000000000000150c000000000000000000000000000000000000000000000000000000000000150e00000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001512000000000000000000000000000000000000000000000000000000000000151400000000000000000000000000000000000000000000000000000000000015160000000000000000000000000000000000000000000000000000000000001518000000000000000000000000000000000000000000000000000000000000151a000000000000000000000000000000000000000000000000000000000000151c000000000000000000000000000000000000000000000000000000000000151e00000000000000000000000000000000000000000000000000000000000015200000000000000000000000000000000000000000000000000000000000001522000000000000000000000000000000000000000000000000000000000000152400000000000000000000000000000000000000000000000000000000000015260000000000000000000000000000000000000000000000000000000000001528000000000000000000000000000000000000000000000000000000000000152a000000000000000000000000000000000000000000000000000000000000152c000000000000000000000000000000000000000000000000000000000000152e00000000000000000000000000000000000000000000000000000000000015300000000000000000000000000000000000000000000000000000000000001532000000000000000000000000000000000000000000000000000000000000153400000000000000000000000000000000000000000000000000000000000015360000000000000000000000000000000000000000000000000000000000001538000000000000000000000000000000000000000000000000000000000000153a000000000000000000000000000000000000000000000000000000000000153c000000000000000000000000000000000000000000000000000000000000153e00000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001542000000000000000000000000000000000000000000000000000000000000154400000000000000000000000000000000000000000000000000000000000015460000000000000000000000000000000000000000000000000000000000001548000000000000000000000000000000000000000000000000000000000000154a000000000000000000000000000000000000000000000000000000000000154c000000000000000000000000000000000000000000000000000000000000154e00000000000000000000000000000000000000000000000000000000000015500000000000000000000000000000000000000000000000000000000000001552000000000000000000000000000000000000000000000000000000000000155400000000000000000000000000000000000000000000000000000000000015560000000000000000000000000000000000000000000000000000000000001558000000000000000000000000000000000000000000000000000000000000155a000000000000000000000000000000000000000000000000000000000000155c000000000000000000000000000000000000000000000000000000000000155e00000000000000000000000000000000000000000000000000000000000015600000000000000000000000000000000000000000000000000000000000001562000000000000000000000000000000000000000000000000000000000000156400000000000000000000000000000000000000000000000000000000000015660000000000000000000000000000000000000000000000000000000000001568000000000000000000000000000000000000000000000000000000000000156a000000000000000000000000000000000000000000000000000000000000156c000000000000000000000000000000000000000000000000000000000000156e00000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001572000000000000000000000000000000000000000000000000000000000000157400000000000000000000000000000000000000000000000000000000000015760000000000000000000000000000000000000000000000000000000000001578000000000000000000000000000000000000000000000000000000000000157a000000000000000000000000000000000000000000000000000000000000157c000000000000000000000000000000000000000000000000000000000000157e00000000000000000000000000000000000000000000000000000000000015800000000000000000000000000000000000000000000000000000000000001582000000000000000000000000000000000000000000000000000000000000158400000000000000000000000000000000000000000000000000000000000015860000000000000000000000000000000000000000000000000000000000001588000000000000000000000000000000000000000000000000000000000000158a000000000000000000000000000000000000000000000000000000000000158c000000000000000000000000000000000000000000000000000000000000158e00000000000000000000000000000000000000000000000000000000000015900000000000000000000000000000000000000000000000000000000000001592000000000000000000000000000000000000000000000000000000000000159400000000000000000000000000000000000000000000000000000000000015960000000000000000000000000000000000000000000000000000000000001598000000000000000000000000000000000000000000000000000000000000159a000000000000000000000000000000000000000000000000000000000000159c000000000000000000000000000000000000000000000000000000000000159e00000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015a200000000000000000000000000000000000000000000000000000000000015a400000000000000000000000000000000000000000000000000000000000015a600000000000000000000000000000000000000000000000000000000000015a800000000000000000000000000000000000000000000000000000000000015aa00000000000000000000000000000000000000000000000000000000000015ac00000000000000000000000000000000000000000000000000000000000015ae00000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015b200000000000000000000000000000000000000000000000000000000000015b400000000000000000000000000000000000000000000000000000000000015b600000000000000000000000000000000000000000000000000000000000015b800000000000000000000000000000000000000000000000000000000000015ba00000000000000000000000000000000000000000000000000000000000015bc00000000000000000000000000000000000000000000000000000000000015be00000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015c200000000000000000000000000000000000000000000000000000000000015c400000000000000000000000000000000000000000000000000000000000015c600000000000000000000000000000000000000000000000000000000000015c800000000000000000000000000000000000000000000000000000000000015ca00000000000000000000000000000000000000000000000000000000000015cc00000000000000000000000000000000000000000000000000000000000015ce00000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015d200000000000000000000000000000000000000000000000000000000000015d400000000000000000000000000000000000000000000000000000000000015d600000000000000000000000000000000000000000000000000000000000015d800000000000000000000000000000000000000000000000000000000000015da00000000000000000000000000000000000000000000000000000000000015dc00000000000000000000000000000000000000000000000000000000000015de00000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015e200000000000000000000000000000000000000000000000000000000000015e400000000000000000000000000000000000000000000000000000000000015e600000000000000000000000000000000000000000000000000000000000015e800000000000000000000000000000000000000000000000000000000000015ea00000000000000000000000000000000000000000000000000000000000015ec00000000000000000000000000000000000000000000000000000000000015ee00000000000000000000000000000000000000000000000000000000000015f000000000000000000000000000000000000000000000000000000000000015f200000000000000000000000000000000000000000000000000000000000015f400000000000000000000000000000000000000000000000000000000000015f600000000000000000000000000000000000000000000000000000000000015f800000000000000000000000000000000000000000000000000000000000015fa00000000000000000000000000000000000000000000000000000000000015fc00000000000000000000000000000000000000000000000000000000000015fe00000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001602000000000000000000000000000000000000000000000000000000000000160400000000000000000000000000000000000000000000000000000000000016060000000000000000000000000000000000000000000000000000000000001608000000000000000000000000000000000000000000000000000000000000160a000000000000000000000000000000000000000000000000000000000000160c000000000000000000000000000000000000000000000000000000000000160e00000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001612000000000000000000000000000000000000000000000000000000000000161400000000000000000000000000000000000000000000000000000000000016160000000000000000000000000000000000000000000000000000000000001618000000000000000000000000000000000000000000000000000000000000161a000000000000000000000000000000000000000000000000000000000000161c000000000000000000000000000000000000000000000000000000000000161e00000000000000000000000000000000000000000000000000000000000016200000000000000000000000000000000000000000000000000000000000001622000000000000000000000000000000000000000000000000000000000000162400000000000000000000000000000000000000000000000000000000000016260000000000000000000000000000000000000000000000000000000000001628000000000000000000000000000000000000000000000000000000000000162a000000000000000000000000000000000000000000000000000000000000162c000000000000000000000000000000000000000000000000000000000000162e00000000000000000000000000000000000000000000000000000000000016300000000000000000000000000000000000000000000000000000000000001632000000000000000000000000000000000000000000000000000000000000163400000000000000000000000000000000000000000000000000000000000016360000000000000000000000000000000000000000000000000000000000001638000000000000000000000000000000000000000000000000000000000000163a000000000000000000000000000000000000000000000000000000000000163c000000000000000000000000000000000000000000000000000000000000163e00000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001642000000000000000000000000000000000000000000000000000000000000164400000000000000000000000000000000000000000000000000000000000016460000000000000000000000000000000000000000000000000000000000001648000000000000000000000000000000000000000000000000000000000000164a000000000000000000000000000000000000000000000000000000000000164c000000000000000000000000000000000000000000000000000000000000164e00000000000000000000000000000000000000000000000000000000000016500000000000000000000000000000000000000000000000000000000000001652000000000000000000000000000000000000000000000000000000000000165400000000000000000000000000000000000000000000000000000000000016560000000000000000000000000000000000000000000000000000000000001658000000000000000000000000000000000000000000000000000000000000165a000000000000000000000000000000000000000000000000000000000000165c000000000000000000000000000000000000000000000000000000000000165e00000000000000000000000000000000000000000000000000000000000016600000000000000000000000000000000000000000000000000000000000001662000000000000000000000000000000000000000000000000000000000000166400000000000000000000000000000000000000000000000000000000000016660000000000000000000000000000000000000000000000000000000000001668000000000000000000000000000000000000000000000000000000000000166a000000000000000000000000000000000000000000000000000000000000166c000000000000000000000000000000000000000000000000000000000000166e00000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001672000000000000000000000000000000000000000000000000000000000000167400000000000000000000000000000000000000000000000000000000000016760000000000000000000000000000000000000000000000000000000000001678000000000000000000000000000000000000000000000000000000000000167a000000000000000000000000000000000000000000000000000000000000167c000000000000000000000000000000000000000000000000000000000000167e00000000000000000000000000000000000000000000000000000000000016800000000000000000000000000000000000000000000000000000000000001682000000000000000000000000000000000000000000000000000000000000168400000000000000000000000000000000000000000000000000000000000016860000000000000000000000000000000000000000000000000000000000001688000000000000000000000000000000000000000000000000000000000000168a000000000000000000000000000000000000000000000000000000000000168c000000000000000000000000000000000000000000000000000000000000168e00000000000000000000000000000000000000000000000000000000000016900000000000000000000000000000000000000000000000000000000000001692000000000000000000000000000000000000000000000000000000000000169400000000000000000000000000000000000000000000000000000000000016960000000000000000000000000000000000000000000000000000000000001698000000000000000000000000000000000000000000000000000000000000169a000000000000000000000000000000000000000000000000000000000000169c000000000000000000000000000000000000000000000000000000000000169e00000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016a200000000000000000000000000000000000000000000000000000000000016a400000000000000000000000000000000000000000000000000000000000016a600000000000000000000000000000000000000000000000000000000000016a800000000000000000000000000000000000000000000000000000000000016aa00000000000000000000000000000000000000000000000000000000000016ac00000000000000000000000000000000000000000000000000000000000016ae00000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016b200000000000000000000000000000000000000000000000000000000000016b400000000000000000000000000000000000000000000000000000000000016b600000000000000000000000000000000000000000000000000000000000016b800000000000000000000000000000000000000000000000000000000000016ba00000000000000000000000000000000000000000000000000000000000016bc00000000000000000000000000000000000000000000000000000000000016be00000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016c200000000000000000000000000000000000000000000000000000000000016c400000000000000000000000000000000000000000000000000000000000016c600000000000000000000000000000000000000000000000000000000000016c800000000000000000000000000000000000000000000000000000000000016ca00000000000000000000000000000000000000000000000000000000000016cc00000000000000000000000000000000000000000000000000000000000016ce00000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016d200000000000000000000000000000000000000000000000000000000000016d400000000000000000000000000000000000000000000000000000000000016d600000000000000000000000000000000000000000000000000000000000016d800000000000000000000000000000000000000000000000000000000000016da00000000000000000000000000000000000000000000000000000000000016dc00000000000000000000000000000000000000000000000000000000000016de00000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016e200000000000000000000000000000000000000000000000000000000000016e400000000000000000000000000000000000000000000000000000000000016e600000000000000000000000000000000000000000000000000000000000016e800000000000000000000000000000000000000000000000000000000000016ea00000000000000000000000000000000000000000000000000000000000016ec00000000000000000000000000000000000000000000000000000000000016ee00000000000000000000000000000000000000000000000000000000000016f000000000000000000000000000000000000000000000000000000000000016f200000000000000000000000000000000000000000000000000000000000016f400000000000000000000000000000000000000000000000000000000000016f600000000000000000000000000000000000000000000000000000000000016f800000000000000000000000000000000000000000000000000000000000016fa00000000000000000000000000000000000000000000000000000000000016fc00000000000000000000000000000000000000000000000000000000000016fe00000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000001702000000000000000000000000000000000000000000000000000000000000170400000000000000000000000000000000000000000000000000000000000017060000000000000000000000000000000000000000000000000000000000001708000000000000000000000000000000000000000000000000000000000000170a000000000000000000000000000000000000000000000000000000000000170c000000000000000000000000000000000000000000000000000000000000170e00000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001712000000000000000000000000000000000000000000000000000000000000171400000000000000000000000000000000000000000000000000000000000017160000000000000000000000000000000000000000000000000000000000001718000000000000000000000000000000000000000000000000000000000000171a000000000000000000000000000000000000000000000000000000000000171c000000000000000000000000000000000000000000000000000000000000171e00000000000000000000000000000000000000000000000000000000000017200000000000000000000000000000000000000000000000000000000000001722000000000000000000000000000000000000000000000000000000000000172400000000000000000000000000000000000000000000000000000000000017260000000000000000000000000000000000000000000000000000000000001728000000000000000000000000000000000000000000000000000000000000172a000000000000000000000000000000000000000000000000000000000000172c000000000000000000000000000000000000000000000000000000000000172e00000000000000000000000000000000000000000000000000000000000017300000000000000000000000000000000000000000000000000000000000001732000000000000000000000000000000000000000000000000000000000000173400000000000000000000000000000000000000000000000000000000000017360000000000000000000000000000000000000000000000000000000000001738000000000000000000000000000000000000000000000000000000000000173a000000000000000000000000000000000000000000000000000000000000173c000000000000000000000000000000000000000000000000000000000000173e00000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001742000000000000000000000000000000000000000000000000000000000000174400000000000000000000000000000000000000000000000000000000000017460000000000000000000000000000000000000000000000000000000000001748000000000000000000000000000000000000000000000000000000000000174a000000000000000000000000000000000000000000000000000000000000174c000000000000000000000000000000000000000000000000000000000000174e00000000000000000000000000000000000000000000000000000000000017500000000000000000000000000000000000000000000000000000000000001752000000000000000000000000000000000000000000000000000000000000175400000000000000000000000000000000000000000000000000000000000017560000000000000000000000000000000000000000000000000000000000001758000000000000000000000000000000000000000000000000000000000000175a000000000000000000000000000000000000000000000000000000000000175c000000000000000000000000000000000000000000000000000000000000175e00000000000000000000000000000000000000000000000000000000000017600000000000000000000000000000000000000000000000000000000000001762000000000000000000000000000000000000000000000000000000000000176400000000000000000000000000000000000000000000000000000000000017660000000000000000000000000000000000000000000000000000000000001768000000000000000000000000000000000000000000000000000000000000176a000000000000000000000000000000000000000000000000000000000000176c000000000000000000000000000000000000000000000000000000000000176e00000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001772000000000000000000000000000000000000000000000000000000000000177400000000000000000000000000000000000000000000000000000000000017760000000000000000000000000000000000000000000000000000000000001778000000000000000000000000000000000000000000000000000000000000177a000000000000000000000000000000000000000000000000000000000000177c000000000000000000000000000000000000000000000000000000000000177e00000000000000000000000000000000000000000000000000000000000017800000000000000000000000000000000000000000000000000000000000001782000000000000000000000000000000000000000000000000000000000000178400000000000000000000000000000000000000000000000000000000000017860000000000000000000000000000000000000000000000000000000000001788000000000000000000000000000000000000000000000000000000000000178a000000000000000000000000000000000000000000000000000000000000178c000000000000000000000000000000000000000000000000000000000000178e00000000000000000000000000000000000000000000000000000000000017900000000000000000000000000000000000000000000000000000000000001792000000000000000000000000000000000000000000000000000000000000179400000000000000000000000000000000000000000000000000000000000017960000000000000000000000000000000000000000000000000000000000001798000000000000000000000000000000000000000000000000000000000000179a000000000000000000000000000000000000000000000000000000000000179c000000000000000000000000000000000000000000000000000000000000179e00000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017a200000000000000000000000000000000000000000000000000000000000017a400000000000000000000000000000000000000000000000000000000000017a600000000000000000000000000000000000000000000000000000000000017a800000000000000000000000000000000000000000000000000000000000017aa00000000000000000000000000000000000000000000000000000000000017ac00000000000000000000000000000000000000000000000000000000000017ae00000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017b200000000000000000000000000000000000000000000000000000000000017b400000000000000000000000000000000000000000000000000000000000017b600000000000000000000000000000000000000000000000000000000000017b800000000000000000000000000000000000000000000000000000000000017ba00000000000000000000000000000000000000000000000000000000000017bc00000000000000000000000000000000000000000000000000000000000017be00000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017c200000000000000000000000000000000000000000000000000000000000017c400000000000000000000000000000000000000000000000000000000000017c600000000000000000000000000000000000000000000000000000000000017c800000000000000000000000000000000000000000000000000000000000017ca00000000000000000000000000000000000000000000000000000000000017cc00000000000000000000000000000000000000000000000000000000000017ce00000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017d200000000000000000000000000000000000000000000000000000000000017d400000000000000000000000000000000000000000000000000000000000017d600000000000000000000000000000000000000000000000000000000000017d800000000000000000000000000000000000000000000000000000000000017da00000000000000000000000000000000000000000000000000000000000017dc00000000000000000000000000000000000000000000000000000000000017de00000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017e200000000000000000000000000000000000000000000000000000000000017e400000000000000000000000000000000000000000000000000000000000017e600000000000000000000000000000000000000000000000000000000000017e800000000000000000000000000000000000000000000000000000000000017ea00000000000000000000000000000000000000000000000000000000000017ec00000000000000000000000000000000000000000000000000000000000017ee00000000000000000000000000000000000000000000000000000000000017f000000000000000000000000000000000000000000000000000000000000017f200000000000000000000000000000000000000000000000000000000000017f400000000000000000000000000000000000000000000000000000000000017f600000000000000000000000000000000000000000000000000000000000017f800000000000000000000000000000000000000000000000000000000000017fa00000000000000000000000000000000000000000000000000000000000017fc00000000000000000000000000000000000000000000000000000000000017fe00000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001802000000000000000000000000000000000000000000000000000000000000180400000000000000000000000000000000000000000000000000000000000018060000000000000000000000000000000000000000000000000000000000001808000000000000000000000000000000000000000000000000000000000000180a000000000000000000000000000000000000000000000000000000000000180c000000000000000000000000000000000000000000000000000000000000180e00000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001812000000000000000000000000000000000000000000000000000000000000181400000000000000000000000000000000000000000000000000000000000018160000000000000000000000000000000000000000000000000000000000001818000000000000000000000000000000000000000000000000000000000000181a000000000000000000000000000000000000000000000000000000000000181c000000000000000000000000000000000000000000000000000000000000181e00000000000000000000000000000000000000000000000000000000000018200000000000000000000000000000000000000000000000000000000000001822000000000000000000000000000000000000000000000000000000000000182400000000000000000000000000000000000000000000000000000000000018260000000000000000000000000000000000000000000000000000000000001828000000000000000000000000000000000000000000000000000000000000182a000000000000000000000000000000000000000000000000000000000000182c000000000000000000000000000000000000000000000000000000000000182e00000000000000000000000000000000000000000000000000000000000018300000000000000000000000000000000000000000000000000000000000001832000000000000000000000000000000000000000000000000000000000000183400000000000000000000000000000000000000000000000000000000000018360000000000000000000000000000000000000000000000000000000000001838000000000000000000000000000000000000000000000000000000000000183a000000000000000000000000000000000000000000000000000000000000183c000000000000000000000000000000000000000000000000000000000000183e00000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001842000000000000000000000000000000000000000000000000000000000000184400000000000000000000000000000000000000000000000000000000000018460000000000000000000000000000000000000000000000000000000000001848000000000000000000000000000000000000000000000000000000000000184a000000000000000000000000000000000000000000000000000000000000184c000000000000000000000000000000000000000000000000000000000000184e00000000000000000000000000000000000000000000000000000000000018500000000000000000000000000000000000000000000000000000000000001852000000000000000000000000000000000000000000000000000000000000185400000000000000000000000000000000000000000000000000000000000018560000000000000000000000000000000000000000000000000000000000001858000000000000000000000000000000000000000000000000000000000000185a000000000000000000000000000000000000000000000000000000000000185c000000000000000000000000000000000000000000000000000000000000185e00000000000000000000000000000000000000000000000000000000000018600000000000000000000000000000000000000000000000000000000000001862000000000000000000000000000000000000000000000000000000000000186400000000000000000000000000000000000000000000000000000000000018660000000000000000000000000000000000000000000000000000000000001868000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186c000000000000000000000000000000000000000000000000000000000000186e00000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001872000000000000000000000000000000000000000000000000000000000000187400000000000000000000000000000000000000000000000000000000000018760000000000000000000000000000000000000000000000000000000000001878000000000000000000000000000000000000000000000000000000000000187a000000000000000000000000000000000000000000000000000000000000187c000000000000000000000000000000000000000000000000000000000000187e00000000000000000000000000000000000000000000000000000000000018800000000000000000000000000000000000000000000000000000000000001882000000000000000000000000000000000000000000000000000000000000188400000000000000000000000000000000000000000000000000000000000018860000000000000000000000000000000000000000000000000000000000001888000000000000000000000000000000000000000000000000000000000000188a000000000000000000000000000000000000000000000000000000000000188c000000000000000000000000000000000000000000000000000000000000188e00000000000000000000000000000000000000000000000000000000000018900000000000000000000000000000000000000000000000000000000000001892000000000000000000000000000000000000000000000000000000000000189400000000000000000000000000000000000000000000000000000000000018960000000000000000000000000000000000000000000000000000000000001898000000000000000000000000000000000000000000000000000000000000189a000000000000000000000000000000000000000000000000000000000000189c000000000000000000000000000000000000000000000000000000000000189e00000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018a200000000000000000000000000000000000000000000000000000000000018a400000000000000000000000000000000000000000000000000000000000018a600000000000000000000000000000000000000000000000000000000000018a800000000000000000000000000000000000000000000000000000000000018aa00000000000000000000000000000000000000000000000000000000000018ac00000000000000000000000000000000000000000000000000000000000018ae00000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018b200000000000000000000000000000000000000000000000000000000000018b400000000000000000000000000000000000000000000000000000000000018b600000000000000000000000000000000000000000000000000000000000018b800000000000000000000000000000000000000000000000000000000000018ba00000000000000000000000000000000000000000000000000000000000018bc00000000000000000000000000000000000000000000000000000000000018be00000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018c200000000000000000000000000000000000000000000000000000000000018c400000000000000000000000000000000000000000000000000000000000018c600000000000000000000000000000000000000000000000000000000000018c800000000000000000000000000000000000000000000000000000000000018ca00000000000000000000000000000000000000000000000000000000000018cc00000000000000000000000000000000000000000000000000000000000018ce00000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018d200000000000000000000000000000000000000000000000000000000000018d400000000000000000000000000000000000000000000000000000000000018d600000000000000000000000000000000000000000000000000000000000018d800000000000000000000000000000000000000000000000000000000000018da00000000000000000000000000000000000000000000000000000000000018dc00000000000000000000000000000000000000000000000000000000000018de00000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018e200000000000000000000000000000000000000000000000000000000000018e400000000000000000000000000000000000000000000000000000000000018e600000000000000000000000000000000000000000000000000000000000018e800000000000000000000000000000000000000000000000000000000000018ea00000000000000000000000000000000000000000000000000000000000018ec00000000000000000000000000000000000000000000000000000000000018ee00000000000000000000000000000000000000000000000000000000000018f000000000000000000000000000000000000000000000000000000000000018f200000000000000000000000000000000000000000000000000000000000018f400000000000000000000000000000000000000000000000000000000000018f600000000000000000000000000000000000000000000000000000000000018f800000000000000000000000000000000000000000000000000000000000018fa00000000000000000000000000000000000000000000000000000000000018fc00000000000000000000000000000000000000000000000000000000000018fe00000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001902000000000000000000000000000000000000000000000000000000000000190400000000000000000000000000000000000000000000000000000000000019060000000000000000000000000000000000000000000000000000000000001908000000000000000000000000000000000000000000000000000000000000190a000000000000000000000000000000000000000000000000000000000000190c000000000000000000000000000000000000000000000000000000000000190e00000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001912000000000000000000000000000000000000000000000000000000000000191400000000000000000000000000000000000000000000000000000000000019160000000000000000000000000000000000000000000000000000000000001918000000000000000000000000000000000000000000000000000000000000191a000000000000000000000000000000000000000000000000000000000000191c000000000000000000000000000000000000000000000000000000000000191e00000000000000000000000000000000000000000000000000000000000019200000000000000000000000000000000000000000000000000000000000001922000000000000000000000000000000000000000000000000000000000000192400000000000000000000000000000000000000000000000000000000000019260000000000000000000000000000000000000000000000000000000000001928000000000000000000000000000000000000000000000000000000000000192a000000000000000000000000000000000000000000000000000000000000192c000000000000000000000000000000000000000000000000000000000000192e00000000000000000000000000000000000000000000000000000000000019300000000000000000000000000000000000000000000000000000000000001932000000000000000000000000000000000000000000000000000000000000193400000000000000000000000000000000000000000000000000000000000019360000000000000000000000000000000000000000000000000000000000001938000000000000000000000000000000000000000000000000000000000000193a000000000000000000000000000000000000000000000000000000000000193c000000000000000000000000000000000000000000000000000000000000193e00000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001942000000000000000000000000000000000000000000000000000000000000194400000000000000000000000000000000000000000000000000000000000019460000000000000000000000000000000000000000000000000000000000001948000000000000000000000000000000000000000000000000000000000000194a000000000000000000000000000000000000000000000000000000000000194c000000000000000000000000000000000000000000000000000000000000194e00000000000000000000000000000000000000000000000000000000000019500000000000000000000000000000000000000000000000000000000000001952000000000000000000000000000000000000000000000000000000000000195400000000000000000000000000000000000000000000000000000000000019560000000000000000000000000000000000000000000000000000000000001958000000000000000000000000000000000000000000000000000000000000195a000000000000000000000000000000000000000000000000000000000000195c000000000000000000000000000000000000000000000000000000000000195e00000000000000000000000000000000000000000000000000000000000019600000000000000000000000000000000000000000000000000000000000001962000000000000000000000000000000000000000000000000000000000000196400000000000000000000000000000000000000000000000000000000000019660000000000000000000000000000000000000000000000000000000000001968000000000000000000000000000000000000000000000000000000000000196a000000000000000000000000000000000000000000000000000000000000196c000000000000000000000000000000000000000000000000000000000000196e00000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001972000000000000000000000000000000000000000000000000000000000000197400000000000000000000000000000000000000000000000000000000000019760000000000000000000000000000000000000000000000000000000000001978000000000000000000000000000000000000000000000000000000000000197a000000000000000000000000000000000000000000000000000000000000197c000000000000000000000000000000000000000000000000000000000000197e00000000000000000000000000000000000000000000000000000000000019800000000000000000000000000000000000000000000000000000000000001982000000000000000000000000000000000000000000000000000000000000198400000000000000000000000000000000000000000000000000000000000019860000000000000000000000000000000000000000000000000000000000001988000000000000000000000000000000000000000000000000000000000000198a000000000000000000000000000000000000000000000000000000000000198c000000000000000000000000000000000000000000000000000000000000198e00000000000000000000000000000000000000000000000000000000000019900000000000000000000000000000000000000000000000000000000000001992000000000000000000000000000000000000000000000000000000000000199400000000000000000000000000000000000000000000000000000000000019960000000000000000000000000000000000000000000000000000000000001998000000000000000000000000000000000000000000000000000000000000199a000000000000000000000000000000000000000000000000000000000000199c000000000000000000000000000000000000000000000000000000000000199e00000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019a200000000000000000000000000000000000000000000000000000000000019a400000000000000000000000000000000000000000000000000000000000019a600000000000000000000000000000000000000000000000000000000000019a800000000000000000000000000000000000000000000000000000000000019aa00000000000000000000000000000000000000000000000000000000000019ac00000000000000000000000000000000000000000000000000000000000019ae00000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019b200000000000000000000000000000000000000000000000000000000000019b400000000000000000000000000000000000000000000000000000000000019b600000000000000000000000000000000000000000000000000000000000019b800000000000000000000000000000000000000000000000000000000000019ba00000000000000000000000000000000000000000000000000000000000019bc00000000000000000000000000000000000000000000000000000000000019be00000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019c200000000000000000000000000000000000000000000000000000000000019c400000000000000000000000000000000000000000000000000000000000019c600000000000000000000000000000000000000000000000000000000000019c800000000000000000000000000000000000000000000000000000000000019ca00000000000000000000000000000000000000000000000000000000000019cc00000000000000000000000000000000000000000000000000000000000019ce00000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019d200000000000000000000000000000000000000000000000000000000000019d400000000000000000000000000000000000000000000000000000000000019d600000000000000000000000000000000000000000000000000000000000019d800000000000000000000000000000000000000000000000000000000000019da00000000000000000000000000000000000000000000000000000000000019dc00000000000000000000000000000000000000000000000000000000000019de00000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019e200000000000000000000000000000000000000000000000000000000000019e400000000000000000000000000000000000000000000000000000000000019e600000000000000000000000000000000000000000000000000000000000019e800000000000000000000000000000000000000000000000000000000000019ea00000000000000000000000000000000000000000000000000000000000019ec00000000000000000000000000000000000000000000000000000000000019ee00000000000000000000000000000000000000000000000000000000000019f000000000000000000000000000000000000000000000000000000000000019f200000000000000000000000000000000000000000000000000000000000019f400000000000000000000000000000000000000000000000000000000000019f600000000000000000000000000000000000000000000000000000000000019f800000000000000000000000000000000000000000000000000000000000019fa00000000000000000000000000000000000000000000000000000000000019fc00000000000000000000000000000000000000000000000000000000000019fe0000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a020000000000000000000000000000000000000000000000000000000000001a040000000000000000000000000000000000000000000000000000000000001a060000000000000000000000000000000000000000000000000000000000001a080000000000000000000000000000000000000000000000000000000000001a0a0000000000000000000000000000000000000000000000000000000000001a0c0000000000000000000000000000000000000000000000000000000000001a0e0000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a120000000000000000000000000000000000000000000000000000000000001a140000000000000000000000000000000000000000000000000000000000001a160000000000000000000000000000000000000000000000000000000000001a180000000000000000000000000000000000000000000000000000000000001a1a0000000000000000000000000000000000000000000000000000000000001a1c0000000000000000000000000000000000000000000000000000000000001a1e0000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a220000000000000000000000000000000000000000000000000000000000001a240000000000000000000000000000000000000000000000000000000000001a260000000000000000000000000000000000000000000000000000000000001a280000000000000000000000000000000000000000000000000000000000001a2a0000000000000000000000000000000000000000000000000000000000001a2c0000000000000000000000000000000000000000000000000000000000001a2e0000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a320000000000000000000000000000000000000000000000000000000000001a340000000000000000000000000000000000000000000000000000000000001a360000000000000000000000000000000000000000000000000000000000001a380000000000000000000000000000000000000000000000000000000000001a3a0000000000000000000000000000000000000000000000000000000000001a3c0000000000000000000000000000000000000000000000000000000000001a3e0000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a420000000000000000000000000000000000000000000000000000000000001a440000000000000000000000000000000000000000000000000000000000001a460000000000000000000000000000000000000000000000000000000000001a480000000000000000000000000000000000000000000000000000000000001a4a0000000000000000000000000000000000000000000000000000000000001a4c0000000000000000000000000000000000000000000000000000000000001a4e0000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a520000000000000000000000000000000000000000000000000000000000001a540000000000000000000000000000000000000000000000000000000000001a560000000000000000000000000000000000000000000000000000000000001a580000000000000000000000000000000000000000000000000000000000001a5a0000000000000000000000000000000000000000000000000000000000001a5c0000000000000000000000000000000000000000000000000000000000001a5e0000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a620000000000000000000000000000000000000000000000000000000000001a640000000000000000000000000000000000000000000000000000000000001a660000000000000000000000000000000000000000000000000000000000001a680000000000000000000000000000000000000000000000000000000000001a6a0000000000000000000000000000000000000000000000000000000000001a6c0000000000000000000000000000000000000000000000000000000000001a6e0000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a720000000000000000000000000000000000000000000000000000000000001a740000000000000000000000000000000000000000000000000000000000001a760000000000000000000000000000000000000000000000000000000000001a780000000000000000000000000000000000000000000000000000000000001a7a0000000000000000000000000000000000000000000000000000000000001a7c0000000000000000000000000000000000000000000000000000000000001a7e0000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a820000000000000000000000000000000000000000000000000000000000001a840000000000000000000000000000000000000000000000000000000000001a860000000000000000000000000000000000000000000000000000000000001a880000000000000000000000000000000000000000000000000000000000001a8a0000000000000000000000000000000000000000000000000000000000001a8c0000000000000000000000000000000000000000000000000000000000001a8e0000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001a920000000000000000000000000000000000000000000000000000000000001a940000000000000000000000000000000000000000000000000000000000001a960000000000000000000000000000000000000000000000000000000000001a980000000000000000000000000000000000000000000000000000000000001a9a0000000000000000000000000000000000000000000000000000000000001a9c0000000000000000000000000000000000000000000000000000000000001a9e0000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001aa20000000000000000000000000000000000000000000000000000000000001aa40000000000000000000000000000000000000000000000000000000000001aa60000000000000000000000000000000000000000000000000000000000001aa80000000000000000000000000000000000000000000000000000000000001aaa0000000000000000000000000000000000000000000000000000000000001aac0000000000000000000000000000000000000000000000000000000000001aae0000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ab20000000000000000000000000000000000000000000000000000000000001ab40000000000000000000000000000000000000000000000000000000000001ab60000000000000000000000000000000000000000000000000000000000001ab80000000000000000000000000000000000000000000000000000000000001aba0000000000000000000000000000000000000000000000000000000000001abc0000000000000000000000000000000000000000000000000000000000001abe0000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ac20000000000000000000000000000000000000000000000000000000000001ac40000000000000000000000000000000000000000000000000000000000001ac60000000000000000000000000000000000000000000000000000000000001ac80000000000000000000000000000000000000000000000000000000000001aca0000000000000000000000000000000000000000000000000000000000001acc0000000000000000000000000000000000000000000000000000000000001ace0000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ad20000000000000000000000000000000000000000000000000000000000001ad40000000000000000000000000000000000000000000000000000000000001ad60000000000000000000000000000000000000000000000000000000000001ad80000000000000000000000000000000000000000000000000000000000001ada0000000000000000000000000000000000000000000000000000000000001adc0000000000000000000000000000000000000000000000000000000000001ade0000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001ae20000000000000000000000000000000000000000000000000000000000001ae40000000000000000000000000000000000000000000000000000000000001ae60000000000000000000000000000000000000000000000000000000000001ae80000000000000000000000000000000000000000000000000000000000001aea0000000000000000000000000000000000000000000000000000000000001aec0000000000000000000000000000000000000000000000000000000000001aee0000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001af20000000000000000000000000000000000000000000000000000000000001af40000000000000000000000000000000000000000000000000000000000001af60000000000000000000000000000000000000000000000000000000000001af80000000000000000000000000000000000000000000000000000000000001afa0000000000000000000000000000000000000000000000000000000000001afc0000000000000000000000000000000000000000000000000000000000001afe0000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b020000000000000000000000000000000000000000000000000000000000001b040000000000000000000000000000000000000000000000000000000000001b060000000000000000000000000000000000000000000000000000000000001b080000000000000000000000000000000000000000000000000000000000001b0a0000000000000000000000000000000000000000000000000000000000001b0c0000000000000000000000000000000000000000000000000000000000001b0e0000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b120000000000000000000000000000000000000000000000000000000000001b140000000000000000000000000000000000000000000000000000000000001b160000000000000000000000000000000000000000000000000000000000001b180000000000000000000000000000000000000000000000000000000000001b1a0000000000000000000000000000000000000000000000000000000000001b1c0000000000000000000000000000000000000000000000000000000000001b1e0000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b220000000000000000000000000000000000000000000000000000000000001b240000000000000000000000000000000000000000000000000000000000001b260000000000000000000000000000000000000000000000000000000000001b280000000000000000000000000000000000000000000000000000000000001b2a0000000000000000000000000000000000000000000000000000000000001b2c0000000000000000000000000000000000000000000000000000000000001b2e0000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b320000000000000000000000000000000000000000000000000000000000001b340000000000000000000000000000000000000000000000000000000000001b360000000000000000000000000000000000000000000000000000000000001b380000000000000000000000000000000000000000000000000000000000001b3a0000000000000000000000000000000000000000000000000000000000001b3c0000000000000000000000000000000000000000000000000000000000001b3e0000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b420000000000000000000000000000000000000000000000000000000000001b440000000000000000000000000000000000000000000000000000000000001b460000000000000000000000000000000000000000000000000000000000001b480000000000000000000000000000000000000000000000000000000000001b4a0000000000000000000000000000000000000000000000000000000000001b4c0000000000000000000000000000000000000000000000000000000000001b4e0000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b520000000000000000000000000000000000000000000000000000000000001b540000000000000000000000000000000000000000000000000000000000001b560000000000000000000000000000000000000000000000000000000000001b580000000000000000000000000000000000000000000000000000000000001b5a0000000000000000000000000000000000000000000000000000000000001b5c0000000000000000000000000000000000000000000000000000000000001b5e0000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b620000000000000000000000000000000000000000000000000000000000001b640000000000000000000000000000000000000000000000000000000000001b660000000000000000000000000000000000000000000000000000000000001b680000000000000000000000000000000000000000000000000000000000001b6a0000000000000000000000000000000000000000000000000000000000001b6c0000000000000000000000000000000000000000000000000000000000001b6e0000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b720000000000000000000000000000000000000000000000000000000000001b740000000000000000000000000000000000000000000000000000000000001b760000000000000000000000000000000000000000000000000000000000001b780000000000000000000000000000000000000000000000000000000000001b7a0000000000000000000000000000000000000000000000000000000000001b7c0000000000000000000000000000000000000000000000000000000000001b7e0000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b820000000000000000000000000000000000000000000000000000000000001b840000000000000000000000000000000000000000000000000000000000001b860000000000000000000000000000000000000000000000000000000000001b880000000000000000000000000000000000000000000000000000000000001b8a0000000000000000000000000000000000000000000000000000000000001b8c0000000000000000000000000000000000000000000000000000000000001b8e0000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001b920000000000000000000000000000000000000000000000000000000000001b940000000000000000000000000000000000000000000000000000000000001b960000000000000000000000000000000000000000000000000000000000001b980000000000000000000000000000000000000000000000000000000000001b9a0000000000000000000000000000000000000000000000000000000000001b9c0000000000000000000000000000000000000000000000000000000000001b9e0000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001ba20000000000000000000000000000000000000000000000000000000000001ba40000000000000000000000000000000000000000000000000000000000001ba60000000000000000000000000000000000000000000000000000000000001ba80000000000000000000000000000000000000000000000000000000000001baa0000000000000000000000000000000000000000000000000000000000001bac0000000000000000000000000000000000000000000000000000000000001bae0000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bb20000000000000000000000000000000000000000000000000000000000001bb40000000000000000000000000000000000000000000000000000000000001bb60000000000000000000000000000000000000000000000000000000000001bb80000000000000000000000000000000000000000000000000000000000001bba0000000000000000000000000000000000000000000000000000000000001bbc0000000000000000000000000000000000000000000000000000000000001bbe0000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bc20000000000000000000000000000000000000000000000000000000000001bc40000000000000000000000000000000000000000000000000000000000001bc60000000000000000000000000000000000000000000000000000000000001bc80000000000000000000000000000000000000000000000000000000000001bca0000000000000000000000000000000000000000000000000000000000001bcc0000000000000000000000000000000000000000000000000000000000001bce0000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001bd20000000000000000000000000000000000000000000000000000000000001bd40000000000000000000000000000000000000000000000000000000000001bd60000000000000000000000000000000000000000000000000000000000001bd80000000000000000000000000000000000000000000000000000000000001bda0000000000000000000000000000000000000000000000000000000000001bdc0000000000000000000000000000000000000000000000000000000000001bde0000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001be20000000000000000000000000000000000000000000000000000000000001be40000000000000000000000000000000000000000000000000000000000001be60000000000000000000000000000000000000000000000000000000000001be80000000000000000000000000000000000000000000000000000000000001bea0000000000000000000000000000000000000000000000000000000000001bec0000000000000000000000000000000000000000000000000000000000001bee0000000000000000000000000000000000000000000000000000000000001bf00000000000000000000000000000000000000000000000000000000000001bf20000000000000000000000000000000000000000000000000000000000001bf40000000000000000000000000000000000000000000000000000000000001bf60000000000000000000000000000000000000000000000000000000000001bf80000000000000000000000000000000000000000000000000000000000001bfa0000000000000000000000000000000000000000000000000000000000001bfc0000000000000000000000000000000000000000000000000000000000001bfe0000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c020000000000000000000000000000000000000000000000000000000000001c040000000000000000000000000000000000000000000000000000000000001c060000000000000000000000000000000000000000000000000000000000001c080000000000000000000000000000000000000000000000000000000000001c0a0000000000000000000000000000000000000000000000000000000000001c0c0000000000000000000000000000000000000000000000000000000000001c0e0000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c120000000000000000000000000000000000000000000000000000000000001c140000000000000000000000000000000000000000000000000000000000001c160000000000000000000000000000000000000000000000000000000000001c180000000000000000000000000000000000000000000000000000000000001c1a0000000000000000000000000000000000000000000000000000000000001c1c0000000000000000000000000000000000000000000000000000000000001c1e0000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c220000000000000000000000000000000000000000000000000000000000001c240000000000000000000000000000000000000000000000000000000000001c260000000000000000000000000000000000000000000000000000000000001c280000000000000000000000000000000000000000000000000000000000001c2a0000000000000000000000000000000000000000000000000000000000001c2c0000000000000000000000000000000000000000000000000000000000001c2e0000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c320000000000000000000000000000000000000000000000000000000000001c340000000000000000000000000000000000000000000000000000000000001c360000000000000000000000000000000000000000000000000000000000001c380000000000000000000000000000000000000000000000000000000000001c3a0000000000000000000000000000000000000000000000000000000000001c3c0000000000000000000000000000000000000000000000000000000000001c3e0000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c420000000000000000000000000000000000000000000000000000000000001c440000000000000000000000000000000000000000000000000000000000001c460000000000000000000000000000000000000000000000000000000000001c480000000000000000000000000000000000000000000000000000000000001c4a0000000000000000000000000000000000000000000000000000000000001c4c0000000000000000000000000000000000000000000000000000000000001c4e0000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c520000000000000000000000000000000000000000000000000000000000001c540000000000000000000000000000000000000000000000000000000000001c560000000000000000000000000000000000000000000000000000000000001c580000000000000000000000000000000000000000000000000000000000001c5a0000000000000000000000000000000000000000000000000000000000001c5c0000000000000000000000000000000000000000000000000000000000001c5e0000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c620000000000000000000000000000000000000000000000000000000000001c640000000000000000000000000000000000000000000000000000000000001c660000000000000000000000000000000000000000000000000000000000001c680000000000000000000000000000000000000000000000000000000000001c6a0000000000000000000000000000000000000000000000000000000000001c6c0000000000000000000000000000000000000000000000000000000000001c6e0000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c720000000000000000000000000000000000000000000000000000000000001c740000000000000000000000000000000000000000000000000000000000001c760000000000000000000000000000000000000000000000000000000000001c780000000000000000000000000000000000000000000000000000000000001c7a0000000000000000000000000000000000000000000000000000000000001c7c0000000000000000000000000000000000000000000000000000000000001c7e0000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c820000000000000000000000000000000000000000000000000000000000001c840000000000000000000000000000000000000000000000000000000000001c860000000000000000000000000000000000000000000000000000000000001c880000000000000000000000000000000000000000000000000000000000001c8a0000000000000000000000000000000000000000000000000000000000001c8c0000000000000000000000000000000000000000000000000000000000001c8e0000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001c920000000000000000000000000000000000000000000000000000000000001c940000000000000000000000000000000000000000000000000000000000001c960000000000000000000000000000000000000000000000000000000000001c980000000000000000000000000000000000000000000000000000000000001c9a0000000000000000000000000000000000000000000000000000000000001c9c0000000000000000000000000000000000000000000000000000000000001c9e0000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001ca20000000000000000000000000000000000000000000000000000000000001ca40000000000000000000000000000000000000000000000000000000000001ca60000000000000000000000000000000000000000000000000000000000001ca80000000000000000000000000000000000000000000000000000000000001caa0000000000000000000000000000000000000000000000000000000000001cac0000000000000000000000000000000000000000000000000000000000001cae0000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cb20000000000000000000000000000000000000000000000000000000000001cb40000000000000000000000000000000000000000000000000000000000001cb60000000000000000000000000000000000000000000000000000000000001cb80000000000000000000000000000000000000000000000000000000000001cba0000000000000000000000000000000000000000000000000000000000001cbc0000000000000000000000000000000000000000000000000000000000001cbe0000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cc20000000000000000000000000000000000000000000000000000000000001cc40000000000000000000000000000000000000000000000000000000000001cc60000000000000000000000000000000000000000000000000000000000001cc80000000000000000000000000000000000000000000000000000000000001cca0000000000000000000000000000000000000000000000000000000000001ccc0000000000000000000000000000000000000000000000000000000000001cce0000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001cd20000000000000000000000000000000000000000000000000000000000001cd40000000000000000000000000000000000000000000000000000000000001cd60000000000000000000000000000000000000000000000000000000000001cd80000000000000000000000000000000000000000000000000000000000001cda0000000000000000000000000000000000000000000000000000000000001cdc0000000000000000000000000000000000000000000000000000000000001cde0000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001ce20000000000000000000000000000000000000000000000000000000000001ce40000000000000000000000000000000000000000000000000000000000001ce60000000000000000000000000000000000000000000000000000000000001ce80000000000000000000000000000000000000000000000000000000000001cea0000000000000000000000000000000000000000000000000000000000001cec0000000000000000000000000000000000000000000000000000000000001cee0000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001cf20000000000000000000000000000000000000000000000000000000000001cf40000000000000000000000000000000000000000000000000000000000001cf60000000000000000000000000000000000000000000000000000000000001cf80000000000000000000000000000000000000000000000000000000000001cfa0000000000000000000000000000000000000000000000000000000000001cfc0000000000000000000000000000000000000000000000000000000000001cfe0000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d020000000000000000000000000000000000000000000000000000000000001d040000000000000000000000000000000000000000000000000000000000001d060000000000000000000000000000000000000000000000000000000000001d080000000000000000000000000000000000000000000000000000000000001d0a0000000000000000000000000000000000000000000000000000000000001d0c0000000000000000000000000000000000000000000000000000000000001d0e0000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d120000000000000000000000000000000000000000000000000000000000001d140000000000000000000000000000000000000000000000000000000000001d160000000000000000000000000000000000000000000000000000000000001d180000000000000000000000000000000000000000000000000000000000001d1a0000000000000000000000000000000000000000000000000000000000001d1c0000000000000000000000000000000000000000000000000000000000001d1e0000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d220000000000000000000000000000000000000000000000000000000000001d240000000000000000000000000000000000000000000000000000000000001d260000000000000000000000000000000000000000000000000000000000001d280000000000000000000000000000000000000000000000000000000000001d2a0000000000000000000000000000000000000000000000000000000000001d2c0000000000000000000000000000000000000000000000000000000000001d2e0000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d320000000000000000000000000000000000000000000000000000000000001d340000000000000000000000000000000000000000000000000000000000001d360000000000000000000000000000000000000000000000000000000000001d380000000000000000000000000000000000000000000000000000000000001d3a0000000000000000000000000000000000000000000000000000000000001d3c0000000000000000000000000000000000000000000000000000000000001d3e0000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d420000000000000000000000000000000000000000000000000000000000001d440000000000000000000000000000000000000000000000000000000000001d460000000000000000000000000000000000000000000000000000000000001d480000000000000000000000000000000000000000000000000000000000001d4a0000000000000000000000000000000000000000000000000000000000001d4c0000000000000000000000000000000000000000000000000000000000001d4e0000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d520000000000000000000000000000000000000000000000000000000000001d540000000000000000000000000000000000000000000000000000000000001d560000000000000000000000000000000000000000000000000000000000001d580000000000000000000000000000000000000000000000000000000000001d5a0000000000000000000000000000000000000000000000000000000000001d5c0000000000000000000000000000000000000000000000000000000000001d5e0000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d620000000000000000000000000000000000000000000000000000000000001d640000000000000000000000000000000000000000000000000000000000001d660000000000000000000000000000000000000000000000000000000000001d680000000000000000000000000000000000000000000000000000000000001d6a0000000000000000000000000000000000000000000000000000000000001d6c0000000000000000000000000000000000000000000000000000000000001d6e0000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d720000000000000000000000000000000000000000000000000000000000001d740000000000000000000000000000000000000000000000000000000000001d760000000000000000000000000000000000000000000000000000000000001d780000000000000000000000000000000000000000000000000000000000001d7a0000000000000000000000000000000000000000000000000000000000001d7c0000000000000000000000000000000000000000000000000000000000001d7e0000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d820000000000000000000000000000000000000000000000000000000000001d840000000000000000000000000000000000000000000000000000000000001d860000000000000000000000000000000000000000000000000000000000001d880000000000000000000000000000000000000000000000000000000000001d8a0000000000000000000000000000000000000000000000000000000000001d8c0000000000000000000000000000000000000000000000000000000000001d8e0000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001d920000000000000000000000000000000000000000000000000000000000001d940000000000000000000000000000000000000000000000000000000000001d960000000000000000000000000000000000000000000000000000000000001d980000000000000000000000000000000000000000000000000000000000001d9a0000000000000000000000000000000000000000000000000000000000001d9c0000000000000000000000000000000000000000000000000000000000001d9e0000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001da20000000000000000000000000000000000000000000000000000000000001da40000000000000000000000000000000000000000000000000000000000001da60000000000000000000000000000000000000000000000000000000000001da80000000000000000000000000000000000000000000000000000000000001daa0000000000000000000000000000000000000000000000000000000000001dac0000000000000000000000000000000000000000000000000000000000001dae0000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001db20000000000000000000000000000000000000000000000000000000000001db40000000000000000000000000000000000000000000000000000000000001db60000000000000000000000000000000000000000000000000000000000001db80000000000000000000000000000000000000000000000000000000000001dba0000000000000000000000000000000000000000000000000000000000001dbc0000000000000000000000000000000000000000000000000000000000001dbe0000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dc20000000000000000000000000000000000000000000000000000000000001dc40000000000000000000000000000000000000000000000000000000000001dc60000000000000000000000000000000000000000000000000000000000001dc80000000000000000000000000000000000000000000000000000000000001dca0000000000000000000000000000000000000000000000000000000000001dcc0000000000000000000000000000000000000000000000000000000000001dce0000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001dd20000000000000000000000000000000000000000000000000000000000001dd40000000000000000000000000000000000000000000000000000000000001dd60000000000000000000000000000000000000000000000000000000000001dd80000000000000000000000000000000000000000000000000000000000001dda0000000000000000000000000000000000000000000000000000000000001ddc0000000000000000000000000000000000000000000000000000000000001dde0000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001de20000000000000000000000000000000000000000000000000000000000001de40000000000000000000000000000000000000000000000000000000000001de60000000000000000000000000000000000000000000000000000000000001de80000000000000000000000000000000000000000000000000000000000001dea0000000000000000000000000000000000000000000000000000000000001dec0000000000000000000000000000000000000000000000000000000000001dee0000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001df20000000000000000000000000000000000000000000000000000000000001df40000000000000000000000000000000000000000000000000000000000001df60000000000000000000000000000000000000000000000000000000000001df80000000000000000000000000000000000000000000000000000000000001dfa0000000000000000000000000000000000000000000000000000000000001dfc0000000000000000000000000000000000000000000000000000000000001dfe0000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e020000000000000000000000000000000000000000000000000000000000001e040000000000000000000000000000000000000000000000000000000000001e060000000000000000000000000000000000000000000000000000000000001e080000000000000000000000000000000000000000000000000000000000001e0a0000000000000000000000000000000000000000000000000000000000001e0c0000000000000000000000000000000000000000000000000000000000001e0e0000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e120000000000000000000000000000000000000000000000000000000000001e140000000000000000000000000000000000000000000000000000000000001e160000000000000000000000000000000000000000000000000000000000001e180000000000000000000000000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000001e1c0000000000000000000000000000000000000000000000000000000000001e1e0000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e220000000000000000000000000000000000000000000000000000000000001e240000000000000000000000000000000000000000000000000000000000001e260000000000000000000000000000000000000000000000000000000000001e280000000000000000000000000000000000000000000000000000000000001e2a0000000000000000000000000000000000000000000000000000000000001e2c0000000000000000000000000000000000000000000000000000000000001e2e0000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e320000000000000000000000000000000000000000000000000000000000001e340000000000000000000000000000000000000000000000000000000000001e360000000000000000000000000000000000000000000000000000000000001e380000000000000000000000000000000000000000000000000000000000001e3a0000000000000000000000000000000000000000000000000000000000001e3c0000000000000000000000000000000000000000000000000000000000001e3e0000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e420000000000000000000000000000000000000000000000000000000000001e440000000000000000000000000000000000000000000000000000000000001e460000000000000000000000000000000000000000000000000000000000001e480000000000000000000000000000000000000000000000000000000000001e4a0000000000000000000000000000000000000000000000000000000000001e4c0000000000000000000000000000000000000000000000000000000000001e4e0000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e520000000000000000000000000000000000000000000000000000000000001e540000000000000000000000000000000000000000000000000000000000001e560000000000000000000000000000000000000000000000000000000000001e580000000000000000000000000000000000000000000000000000000000001e5a0000000000000000000000000000000000000000000000000000000000001e5c0000000000000000000000000000000000000000000000000000000000001e5e0000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e620000000000000000000000000000000000000000000000000000000000001e640000000000000000000000000000000000000000000000000000000000001e660000000000000000000000000000000000000000000000000000000000001e680000000000000000000000000000000000000000000000000000000000001e6a0000000000000000000000000000000000000000000000000000000000001e6c0000000000000000000000000000000000000000000000000000000000001e6e0000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e720000000000000000000000000000000000000000000000000000000000001e740000000000000000000000000000000000000000000000000000000000001e760000000000000000000000000000000000000000000000000000000000001e780000000000000000000000000000000000000000000000000000000000001e7a0000000000000000000000000000000000000000000000000000000000001e7c0000000000000000000000000000000000000000000000000000000000001e7e0000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e820000000000000000000000000000000000000000000000000000000000001e840000000000000000000000000000000000000000000000000000000000001e860000000000000000000000000000000000000000000000000000000000001e880000000000000000000000000000000000000000000000000000000000001e8a0000000000000000000000000000000000000000000000000000000000001e8c0000000000000000000000000000000000000000000000000000000000001e8e0000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001e920000000000000000000000000000000000000000000000000000000000001e940000000000000000000000000000000000000000000000000000000000001e960000000000000000000000000000000000000000000000000000000000001e980000000000000000000000000000000000000000000000000000000000001e9a0000000000000000000000000000000000000000000000000000000000001e9c0000000000000000000000000000000000000000000000000000000000001e9e0000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001ea20000000000000000000000000000000000000000000000000000000000001ea40000000000000000000000000000000000000000000000000000000000001ea60000000000000000000000000000000000000000000000000000000000001ea80000000000000000000000000000000000000000000000000000000000001eaa0000000000000000000000000000000000000000000000000000000000001eac0000000000000000000000000000000000000000000000000000000000001eae0000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001eb20000000000000000000000000000000000000000000000000000000000001eb40000000000000000000000000000000000000000000000000000000000001eb60000000000000000000000000000000000000000000000000000000000001eb80000000000000000000000000000000000000000000000000000000000001eba0000000000000000000000000000000000000000000000000000000000001ebc0000000000000000000000000000000000000000000000000000000000001ebe0000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ec20000000000000000000000000000000000000000000000000000000000001ec40000000000000000000000000000000000000000000000000000000000001ec60000000000000000000000000000000000000000000000000000000000001ec80000000000000000000000000000000000000000000000000000000000001eca0000000000000000000000000000000000000000000000000000000000001ecc0000000000000000000000000000000000000000000000000000000000001ece0000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ed20000000000000000000000000000000000000000000000000000000000001ed40000000000000000000000000000000000000000000000000000000000001ed60000000000000000000000000000000000000000000000000000000000001ed80000000000000000000000000000000000000000000000000000000000001eda0000000000000000000000000000000000000000000000000000000000001edc0000000000000000000000000000000000000000000000000000000000001ede0000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ee20000000000000000000000000000000000000000000000000000000000001ee40000000000000000000000000000000000000000000000000000000000001ee60000000000000000000000000000000000000000000000000000000000001ee80000000000000000000000000000000000000000000000000000000000001eea0000000000000000000000000000000000000000000000000000000000001eec0000000000000000000000000000000000000000000000000000000000001eee0000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001ef20000000000000000000000000000000000000000000000000000000000001ef40000000000000000000000000000000000000000000000000000000000001ef60000000000000000000000000000000000000000000000000000000000001ef80000000000000000000000000000000000000000000000000000000000001efa0000000000000000000000000000000000000000000000000000000000001efc0000000000000000000000000000000000000000000000000000000000001efe0000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f020000000000000000000000000000000000000000000000000000000000001f040000000000000000000000000000000000000000000000000000000000001f060000000000000000000000000000000000000000000000000000000000001f080000000000000000000000000000000000000000000000000000000000001f0a0000000000000000000000000000000000000000000000000000000000001f0c0000000000000000000000000000000000000000000000000000000000001f0e0000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f120000000000000000000000000000000000000000000000000000000000001f140000000000000000000000000000000000000000000000000000000000001f160000000000000000000000000000000000000000000000000000000000001f180000000000000000000000000000000000000000000000000000000000001f1a0000000000000000000000000000000000000000000000000000000000001f1c0000000000000000000000000000000000000000000000000000000000001f1e0000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f220000000000000000000000000000000000000000000000000000000000001f240000000000000000000000000000000000000000000000000000000000001f260000000000000000000000000000000000000000000000000000000000001f280000000000000000000000000000000000000000000000000000000000001f2a0000000000000000000000000000000000000000000000000000000000001f2c0000000000000000000000000000000000000000000000000000000000001f2e0000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f320000000000000000000000000000000000000000000000000000000000001f340000000000000000000000000000000000000000000000000000000000001f360000000000000000000000000000000000000000000000000000000000001f380000000000000000000000000000000000000000000000000000000000001f3a0000000000000000000000000000000000000000000000000000000000001f3c0000000000000000000000000000000000000000000000000000000000001f3e0000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f420000000000000000000000000000000000000000000000000000000000001f440000000000000000000000000000000000000000000000000000000000001f460000000000000000000000000000000000000000000000000000000000001f480000000000000000000000000000000000000000000000000000000000001f4a0000000000000000000000000000000000000000000000000000000000001f4c0000000000000000000000000000000000000000000000000000000000001f4e0000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f520000000000000000000000000000000000000000000000000000000000001f540000000000000000000000000000000000000000000000000000000000001f560000000000000000000000000000000000000000000000000000000000001f580000000000000000000000000000000000000000000000000000000000001f5a0000000000000000000000000000000000000000000000000000000000001f5c0000000000000000000000000000000000000000000000000000000000001f5e0000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f620000000000000000000000000000000000000000000000000000000000001f640000000000000000000000000000000000000000000000000000000000001f660000000000000000000000000000000000000000000000000000000000001f680000000000000000000000000000000000000000000000000000000000001f6a0000000000000000000000000000000000000000000000000000000000001f6c0000000000000000000000000000000000000000000000000000000000001f6e0000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f720000000000000000000000000000000000000000000000000000000000001f740000000000000000000000000000000000000000000000000000000000001f760000000000000000000000000000000000000000000000000000000000001f780000000000000000000000000000000000000000000000000000000000001f7a0000000000000000000000000000000000000000000000000000000000001f7c0000000000000000000000000000000000000000000000000000000000001f7e0000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f820000000000000000000000000000000000000000000000000000000000001f840000000000000000000000000000000000000000000000000000000000001f860000000000000000000000000000000000000000000000000000000000001f880000000000000000000000000000000000000000000000000000000000001f8a0000000000000000000000000000000000000000000000000000000000001f8c0000000000000000000000000000000000000000000000000000000000001f8e0000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001f920000000000000000000000000000000000000000000000000000000000001f940000000000000000000000000000000000000000000000000000000000001f960000000000000000000000000000000000000000000000000000000000001f980000000000000000000000000000000000000000000000000000000000001f9a0000000000000000000000000000000000000000000000000000000000001f9c0000000000000000000000000000000000000000000000000000000000001f9e0000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fa20000000000000000000000000000000000000000000000000000000000001fa40000000000000000000000000000000000000000000000000000000000001fa60000000000000000000000000000000000000000000000000000000000001fa80000000000000000000000000000000000000000000000000000000000001faa0000000000000000000000000000000000000000000000000000000000001fac0000000000000000000000000000000000000000000000000000000000001fae0000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fb20000000000000000000000000000000000000000000000000000000000001fb40000000000000000000000000000000000000000000000000000000000001fb60000000000000000000000000000000000000000000000000000000000001fb80000000000000000000000000000000000000000000000000000000000001fba0000000000000000000000000000000000000000000000000000000000001fbc0000000000000000000000000000000000000000000000000000000000001fbe0000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fc20000000000000000000000000000000000000000000000000000000000001fc40000000000000000000000000000000000000000000000000000000000001fc60000000000000000000000000000000000000000000000000000000000001fc80000000000000000000000000000000000000000000000000000000000001fca0000000000000000000000000000000000000000000000000000000000001fcc0000000000000000000000000000000000000000000000000000000000001fce0000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fd20000000000000000000000000000000000000000000000000000000000001fd40000000000000000000000000000000000000000000000000000000000001fd60000000000000000000000000000000000000000000000000000000000001fd80000000000000000000000000000000000000000000000000000000000001fda0000000000000000000000000000000000000000000000000000000000001fdc0000000000000000000000000000000000000000000000000000000000001fde0000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001fe20000000000000000000000000000000000000000000000000000000000001fe40000000000000000000000000000000000000000000000000000000000001fe60000000000000000000000000000000000000000000000000000000000001fe80000000000000000000000000000000000000000000000000000000000001fea0000000000000000000000000000000000000000000000000000000000001fec0000000000000000000000000000000000000000000000000000000000001fee0000000000000000000000000000000000000000000000000000000000001ff00000000000000000000000000000000000000000000000000000000000001ff20000000000000000000000000000000000000000000000000000000000001ff40000000000000000000000000000000000000000000000000000000000001ff60000000000000000000000000000000000000000000000000000000000001ff80000000000000000000000000000000000000000000000000000000000001ffa0000000000000000000000000000000000000000000000000000000000001ffc0000000000000000000000000000000000000000000000000000000000001ffe00000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000200400000000000000000000000000000000000000000000000000000000000020060000000000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000200a000000000000000000000000000000000000000000000000000000000000200c000000000000000000000000000000000000000000000000000000000000200e00000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002012000000000000000000000000000000000000000000000000000000000000201400000000000000000000000000000000000000000000000000000000000020160000000000000000000000000000000000000000000000000000000000002018000000000000000000000000000000000000000000000000000000000000201a000000000000000000000000000000000000000000000000000000000000201c000000000000000000000000000000000000000000000000000000000000201e00000000000000000000000000000000000000000000000000000000000020200000000000000000000000000000000000000000000000000000000000002022000000000000000000000000000000000000000000000000000000000000202400000000000000000000000000000000000000000000000000000000000020260000000000000000000000000000000000000000000000000000000000002028000000000000000000000000000000000000000000000000000000000000202a000000000000000000000000000000000000000000000000000000000000202c000000000000000000000000000000000000000000000000000000000000202e00000000000000000000000000000000000000000000000000000000000020300000000000000000000000000000000000000000000000000000000000002032000000000000000000000000000000000000000000000000000000000000203400000000000000000000000000000000000000000000000000000000000020360000000000000000000000000000000000000000000000000000000000002038000000000000000000000000000000000000000000000000000000000000203a000000000000000000000000000000000000000000000000000000000000203c000000000000000000000000000000000000000000000000000000000000203e00000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002042000000000000000000000000000000000000000000000000000000000000204400000000000000000000000000000000000000000000000000000000000020460000000000000000000000000000000000000000000000000000000000002048000000000000000000000000000000000000000000000000000000000000204a000000000000000000000000000000000000000000000000000000000000204c000000000000000000000000000000000000000000000000000000000000204e00000000000000000000000000000000000000000000000000000000000020500000000000000000000000000000000000000000000000000000000000002052000000000000000000000000000000000000000000000000000000000000205400000000000000000000000000000000000000000000000000000000000020560000000000000000000000000000000000000000000000000000000000002058000000000000000000000000000000000000000000000000000000000000205a000000000000000000000000000000000000000000000000000000000000205c000000000000000000000000000000000000000000000000000000000000205e00000000000000000000000000000000000000000000000000000000000020600000000000000000000000000000000000000000000000000000000000002062000000000000000000000000000000000000000000000000000000000000206400000000000000000000000000000000000000000000000000000000000020660000000000000000000000000000000000000000000000000000000000002068000000000000000000000000000000000000000000000000000000000000206a000000000000000000000000000000000000000000000000000000000000206c000000000000000000000000000000000000000000000000000000000000206e00000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002072000000000000000000000000000000000000000000000000000000000000207400000000000000000000000000000000000000000000000000000000000020760000000000000000000000000000000000000000000000000000000000002078000000000000000000000000000000000000000000000000000000000000207a000000000000000000000000000000000000000000000000000000000000207c000000000000000000000000000000000000000000000000000000000000207e00000000000000000000000000000000000000000000000000000000000020800000000000000000000000000000000000000000000000000000000000002082000000000000000000000000000000000000000000000000000000000000208400000000000000000000000000000000000000000000000000000000000020860000000000000000000000000000000000000000000000000000000000002088000000000000000000000000000000000000000000000000000000000000208a000000000000000000000000000000000000000000000000000000000000208c000000000000000000000000000000000000000000000000000000000000208e00000000000000000000000000000000000000000000000000000000000020900000000000000000000000000000000000000000000000000000000000002092000000000000000000000000000000000000000000000000000000000000209400000000000000000000000000000000000000000000000000000000000020960000000000000000000000000000000000000000000000000000000000002098000000000000000000000000000000000000000000000000000000000000209a000000000000000000000000000000000000000000000000000000000000209c000000000000000000000000000000000000000000000000000000000000209e00000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020a200000000000000000000000000000000000000000000000000000000000020a400000000000000000000000000000000000000000000000000000000000020a600000000000000000000000000000000000000000000000000000000000020a800000000000000000000000000000000000000000000000000000000000020aa00000000000000000000000000000000000000000000000000000000000020ac00000000000000000000000000000000000000000000000000000000000020ae00000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020b200000000000000000000000000000000000000000000000000000000000020b400000000000000000000000000000000000000000000000000000000000020b600000000000000000000000000000000000000000000000000000000000020b800000000000000000000000000000000000000000000000000000000000020ba00000000000000000000000000000000000000000000000000000000000020bc00000000000000000000000000000000000000000000000000000000000020be00000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020c200000000000000000000000000000000000000000000000000000000000020c400000000000000000000000000000000000000000000000000000000000020c600000000000000000000000000000000000000000000000000000000000020c800000000000000000000000000000000000000000000000000000000000020ca00000000000000000000000000000000000000000000000000000000000020cc00000000000000000000000000000000000000000000000000000000000020ce00000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020d200000000000000000000000000000000000000000000000000000000000020d400000000000000000000000000000000000000000000000000000000000020d600000000000000000000000000000000000000000000000000000000000020d800000000000000000000000000000000000000000000000000000000000020da00000000000000000000000000000000000000000000000000000000000020dc00000000000000000000000000000000000000000000000000000000000020de00000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020e200000000000000000000000000000000000000000000000000000000000020e400000000000000000000000000000000000000000000000000000000000020e600000000000000000000000000000000000000000000000000000000000020e800000000000000000000000000000000000000000000000000000000000020ea00000000000000000000000000000000000000000000000000000000000020ec00000000000000000000000000000000000000000000000000000000000020ee00000000000000000000000000000000000000000000000000000000000020f000000000000000000000000000000000000000000000000000000000000020f200000000000000000000000000000000000000000000000000000000000020f400000000000000000000000000000000000000000000000000000000000020f600000000000000000000000000000000000000000000000000000000000020f800000000000000000000000000000000000000000000000000000000000020fa00000000000000000000000000000000000000000000000000000000000020fc00000000000000000000000000000000000000000000000000000000000020fe00000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002102000000000000000000000000000000000000000000000000000000000000210400000000000000000000000000000000000000000000000000000000000021060000000000000000000000000000000000000000000000000000000000002108000000000000000000000000000000000000000000000000000000000000210a000000000000000000000000000000000000000000000000000000000000210c000000000000000000000000000000000000000000000000000000000000210e00000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002112000000000000000000000000000000000000000000000000000000000000211400000000000000000000000000000000000000000000000000000000000021160000000000000000000000000000000000000000000000000000000000002118000000000000000000000000000000000000000000000000000000000000211a000000000000000000000000000000000000000000000000000000000000211c000000000000000000000000000000000000000000000000000000000000211e00000000000000000000000000000000000000000000000000000000000021200000000000000000000000000000000000000000000000000000000000002122000000000000000000000000000000000000000000000000000000000000212400000000000000000000000000000000000000000000000000000000000021260000000000000000000000000000000000000000000000000000000000002128000000000000000000000000000000000000000000000000000000000000212a000000000000000000000000000000000000000000000000000000000000212c000000000000000000000000000000000000000000000000000000000000212e00000000000000000000000000000000000000000000000000000000000021300000000000000000000000000000000000000000000000000000000000002132000000000000000000000000000000000000000000000000000000000000213400000000000000000000000000000000000000000000000000000000000021360000000000000000000000000000000000000000000000000000000000002138000000000000000000000000000000000000000000000000000000000000213a000000000000000000000000000000000000000000000000000000000000213c000000000000000000000000000000000000000000000000000000000000213e00000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002142000000000000000000000000000000000000000000000000000000000000214400000000000000000000000000000000000000000000000000000000000021460000000000000000000000000000000000000000000000000000000000002148000000000000000000000000000000000000000000000000000000000000214a000000000000000000000000000000000000000000000000000000000000214c000000000000000000000000000000000000000000000000000000000000214e00000000000000000000000000000000000000000000000000000000000021500000000000000000000000000000000000000000000000000000000000002152000000000000000000000000000000000000000000000000000000000000215400000000000000000000000000000000000000000000000000000000000021560000000000000000000000000000000000000000000000000000000000002158000000000000000000000000000000000000000000000000000000000000215a000000000000000000000000000000000000000000000000000000000000215c000000000000000000000000000000000000000000000000000000000000215e00000000000000000000000000000000000000000000000000000000000021600000000000000000000000000000000000000000000000000000000000002162000000000000000000000000000000000000000000000000000000000000216400000000000000000000000000000000000000000000000000000000000021660000000000000000000000000000000000000000000000000000000000002168000000000000000000000000000000000000000000000000000000000000216a000000000000000000000000000000000000000000000000000000000000216c000000000000000000000000000000000000000000000000000000000000216e00000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002172000000000000000000000000000000000000000000000000000000000000217400000000000000000000000000000000000000000000000000000000000021760000000000000000000000000000000000000000000000000000000000002178000000000000000000000000000000000000000000000000000000000000217a000000000000000000000000000000000000000000000000000000000000217c000000000000000000000000000000000000000000000000000000000000217e00000000000000000000000000000000000000000000000000000000000021800000000000000000000000000000000000000000000000000000000000002182000000000000000000000000000000000000000000000000000000000000218400000000000000000000000000000000000000000000000000000000000021860000000000000000000000000000000000000000000000000000000000002188000000000000000000000000000000000000000000000000000000000000218a000000000000000000000000000000000000000000000000000000000000218c000000000000000000000000000000000000000000000000000000000000218e00000000000000000000000000000000000000000000000000000000000021900000000000000000000000000000000000000000000000000000000000002192000000000000000000000000000000000000000000000000000000000000219400000000000000000000000000000000000000000000000000000000000021960000000000000000000000000000000000000000000000000000000000002198000000000000000000000000000000000000000000000000000000000000219a000000000000000000000000000000000000000000000000000000000000219c000000000000000000000000000000000000000000000000000000000000219e00000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021a200000000000000000000000000000000000000000000000000000000000021a400000000000000000000000000000000000000000000000000000000000021a600000000000000000000000000000000000000000000000000000000000021a800000000000000000000000000000000000000000000000000000000000021aa00000000000000000000000000000000000000000000000000000000000021ac00000000000000000000000000000000000000000000000000000000000021ae00000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021b200000000000000000000000000000000000000000000000000000000000021b400000000000000000000000000000000000000000000000000000000000021b600000000000000000000000000000000000000000000000000000000000021b800000000000000000000000000000000000000000000000000000000000021ba00000000000000000000000000000000000000000000000000000000000021bc00000000000000000000000000000000000000000000000000000000000021be00000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021c200000000000000000000000000000000000000000000000000000000000021c400000000000000000000000000000000000000000000000000000000000021c600000000000000000000000000000000000000000000000000000000000021c800000000000000000000000000000000000000000000000000000000000021ca00000000000000000000000000000000000000000000000000000000000021cc00000000000000000000000000000000000000000000000000000000000021ce00000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021d200000000000000000000000000000000000000000000000000000000000021d400000000000000000000000000000000000000000000000000000000000021d600000000000000000000000000000000000000000000000000000000000021d800000000000000000000000000000000000000000000000000000000000021da00000000000000000000000000000000000000000000000000000000000021dc00000000000000000000000000000000000000000000000000000000000021de00000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021e200000000000000000000000000000000000000000000000000000000000021e400000000000000000000000000000000000000000000000000000000000021e600000000000000000000000000000000000000000000000000000000000021e800000000000000000000000000000000000000000000000000000000000021ea00000000000000000000000000000000000000000000000000000000000021ec00000000000000000000000000000000000000000000000000000000000021ee00000000000000000000000000000000000000000000000000000000000021f000000000000000000000000000000000000000000000000000000000000021f200000000000000000000000000000000000000000000000000000000000021f400000000000000000000000000000000000000000000000000000000000021f600000000000000000000000000000000000000000000000000000000000021f800000000000000000000000000000000000000000000000000000000000021fa00000000000000000000000000000000000000000000000000000000000021fc00000000000000000000000000000000000000000000000000000000000021fe00000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002202000000000000000000000000000000000000000000000000000000000000220400000000000000000000000000000000000000000000000000000000000022060000000000000000000000000000000000000000000000000000000000002208000000000000000000000000000000000000000000000000000000000000220a000000000000000000000000000000000000000000000000000000000000220c000000000000000000000000000000000000000000000000000000000000220e00000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002212000000000000000000000000000000000000000000000000000000000000221400000000000000000000000000000000000000000000000000000000000022160000000000000000000000000000000000000000000000000000000000002218000000000000000000000000000000000000000000000000000000000000221a000000000000000000000000000000000000000000000000000000000000221c000000000000000000000000000000000000000000000000000000000000221e00000000000000000000000000000000000000000000000000000000000022200000000000000000000000000000000000000000000000000000000000002222000000000000000000000000000000000000000000000000000000000000222400000000000000000000000000000000000000000000000000000000000022260000000000000000000000000000000000000000000000000000000000002228000000000000000000000000000000000000000000000000000000000000222a000000000000000000000000000000000000000000000000000000000000222c000000000000000000000000000000000000000000000000000000000000222e00000000000000000000000000000000000000000000000000000000000022300000000000000000000000000000000000000000000000000000000000002232000000000000000000000000000000000000000000000000000000000000223400000000000000000000000000000000000000000000000000000000000022360000000000000000000000000000000000000000000000000000000000002238000000000000000000000000000000000000000000000000000000000000223a000000000000000000000000000000000000000000000000000000000000223c000000000000000000000000000000000000000000000000000000000000223e00000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002242000000000000000000000000000000000000000000000000000000000000224400000000000000000000000000000000000000000000000000000000000022460000000000000000000000000000000000000000000000000000000000002248000000000000000000000000000000000000000000000000000000000000224a000000000000000000000000000000000000000000000000000000000000224c000000000000000000000000000000000000000000000000000000000000224e00000000000000000000000000000000000000000000000000000000000022500000000000000000000000000000000000000000000000000000000000002252000000000000000000000000000000000000000000000000000000000000225400000000000000000000000000000000000000000000000000000000000022560000000000000000000000000000000000000000000000000000000000002258000000000000000000000000000000000000000000000000000000000000225a000000000000000000000000000000000000000000000000000000000000225c000000000000000000000000000000000000000000000000000000000000225e00000000000000000000000000000000000000000000000000000000000022600000000000000000000000000000000000000000000000000000000000002262000000000000000000000000000000000000000000000000000000000000226400000000000000000000000000000000000000000000000000000000000022660000000000000000000000000000000000000000000000000000000000002268000000000000000000000000000000000000000000000000000000000000226a000000000000000000000000000000000000000000000000000000000000226c000000000000000000000000000000000000000000000000000000000000226e00000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002272000000000000000000000000000000000000000000000000000000000000227400000000000000000000000000000000000000000000000000000000000022760000000000000000000000000000000000000000000000000000000000002278000000000000000000000000000000000000000000000000000000000000227a000000000000000000000000000000000000000000000000000000000000227c000000000000000000000000000000000000000000000000000000000000227e00000000000000000000000000000000000000000000000000000000000022800000000000000000000000000000000000000000000000000000000000002282000000000000000000000000000000000000000000000000000000000000228400000000000000000000000000000000000000000000000000000000000022860000000000000000000000000000000000000000000000000000000000002288000000000000000000000000000000000000000000000000000000000000228a000000000000000000000000000000000000000000000000000000000000228c000000000000000000000000000000000000000000000000000000000000228e00000000000000000000000000000000000000000000000000000000000022900000000000000000000000000000000000000000000000000000000000002292000000000000000000000000000000000000000000000000000000000000229400000000000000000000000000000000000000000000000000000000000022960000000000000000000000000000000000000000000000000000000000002298000000000000000000000000000000000000000000000000000000000000229a000000000000000000000000000000000000000000000000000000000000229c000000000000000000000000000000000000000000000000000000000000229e00000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022a200000000000000000000000000000000000000000000000000000000000022a400000000000000000000000000000000000000000000000000000000000022a600000000000000000000000000000000000000000000000000000000000022a800000000000000000000000000000000000000000000000000000000000022aa00000000000000000000000000000000000000000000000000000000000022ac00000000000000000000000000000000000000000000000000000000000022ae00000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022b200000000000000000000000000000000000000000000000000000000000022b400000000000000000000000000000000000000000000000000000000000022b600000000000000000000000000000000000000000000000000000000000022b800000000000000000000000000000000000000000000000000000000000022ba00000000000000000000000000000000000000000000000000000000000022bc00000000000000000000000000000000000000000000000000000000000022be00000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022c200000000000000000000000000000000000000000000000000000000000022c400000000000000000000000000000000000000000000000000000000000022c600000000000000000000000000000000000000000000000000000000000022c800000000000000000000000000000000000000000000000000000000000022ca00000000000000000000000000000000000000000000000000000000000022cc00000000000000000000000000000000000000000000000000000000000022ce00000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022d200000000000000000000000000000000000000000000000000000000000022d400000000000000000000000000000000000000000000000000000000000022d600000000000000000000000000000000000000000000000000000000000022d800000000000000000000000000000000000000000000000000000000000022da00000000000000000000000000000000000000000000000000000000000022dc00000000000000000000000000000000000000000000000000000000000022de00000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022e200000000000000000000000000000000000000000000000000000000000022e400000000000000000000000000000000000000000000000000000000000022e600000000000000000000000000000000000000000000000000000000000022e800000000000000000000000000000000000000000000000000000000000022ea00000000000000000000000000000000000000000000000000000000000022ec00000000000000000000000000000000000000000000000000000000000022ee00000000000000000000000000000000000000000000000000000000000022f000000000000000000000000000000000000000000000000000000000000022f200000000000000000000000000000000000000000000000000000000000022f400000000000000000000000000000000000000000000000000000000000022f600000000000000000000000000000000000000000000000000000000000022f800000000000000000000000000000000000000000000000000000000000022fa00000000000000000000000000000000000000000000000000000000000022fc00000000000000000000000000000000000000000000000000000000000022fe00000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000002302000000000000000000000000000000000000000000000000000000000000230400000000000000000000000000000000000000000000000000000000000023060000000000000000000000000000000000000000000000000000000000002308000000000000000000000000000000000000000000000000000000000000230a000000000000000000000000000000000000000000000000000000000000230c000000000000000000000000000000000000000000000000000000000000230e00000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002312000000000000000000000000000000000000000000000000000000000000231400000000000000000000000000000000000000000000000000000000000023160000000000000000000000000000000000000000000000000000000000002318000000000000000000000000000000000000000000000000000000000000231a000000000000000000000000000000000000000000000000000000000000231c000000000000000000000000000000000000000000000000000000000000231e00000000000000000000000000000000000000000000000000000000000023200000000000000000000000000000000000000000000000000000000000002322000000000000000000000000000000000000000000000000000000000000232400000000000000000000000000000000000000000000000000000000000023260000000000000000000000000000000000000000000000000000000000002328000000000000000000000000000000000000000000000000000000000000232a000000000000000000000000000000000000000000000000000000000000232c000000000000000000000000000000000000000000000000000000000000232e00000000000000000000000000000000000000000000000000000000000023300000000000000000000000000000000000000000000000000000000000002332000000000000000000000000000000000000000000000000000000000000233400000000000000000000000000000000000000000000000000000000000023360000000000000000000000000000000000000000000000000000000000002338000000000000000000000000000000000000000000000000000000000000233a000000000000000000000000000000000000000000000000000000000000233c000000000000000000000000000000000000000000000000000000000000233e00000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002342000000000000000000000000000000000000000000000000000000000000234400000000000000000000000000000000000000000000000000000000000023460000000000000000000000000000000000000000000000000000000000002348000000000000000000000000000000000000000000000000000000000000234a000000000000000000000000000000000000000000000000000000000000234c000000000000000000000000000000000000000000000000000000000000234e00000000000000000000000000000000000000000000000000000000000023500000000000000000000000000000000000000000000000000000000000002352000000000000000000000000000000000000000000000000000000000000235400000000000000000000000000000000000000000000000000000000000023560000000000000000000000000000000000000000000000000000000000002358000000000000000000000000000000000000000000000000000000000000235a000000000000000000000000000000000000000000000000000000000000235c000000000000000000000000000000000000000000000000000000000000235e00000000000000000000000000000000000000000000000000000000000023600000000000000000000000000000000000000000000000000000000000002362000000000000000000000000000000000000000000000000000000000000236400000000000000000000000000000000000000000000000000000000000023660000000000000000000000000000000000000000000000000000000000002368000000000000000000000000000000000000000000000000000000000000236a000000000000000000000000000000000000000000000000000000000000236c000000000000000000000000000000000000000000000000000000000000236e00000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002372000000000000000000000000000000000000000000000000000000000000237400000000000000000000000000000000000000000000000000000000000023760000000000000000000000000000000000000000000000000000000000002378000000000000000000000000000000000000000000000000000000000000237a000000000000000000000000000000000000000000000000000000000000237c000000000000000000000000000000000000000000000000000000000000237e00000000000000000000000000000000000000000000000000000000000023800000000000000000000000000000000000000000000000000000000000002382000000000000000000000000000000000000000000000000000000000000238400000000000000000000000000000000000000000000000000000000000023860000000000000000000000000000000000000000000000000000000000002388000000000000000000000000000000000000000000000000000000000000238a000000000000000000000000000000000000000000000000000000000000238c000000000000000000000000000000000000000000000000000000000000238e00000000000000000000000000000000000000000000000000000000000023900000000000000000000000000000000000000000000000000000000000002392000000000000000000000000000000000000000000000000000000000000239400000000000000000000000000000000000000000000000000000000000023960000000000000000000000000000000000000000000000000000000000002398000000000000000000000000000000000000000000000000000000000000239a000000000000000000000000000000000000000000000000000000000000239c000000000000000000000000000000000000000000000000000000000000239e00000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023a200000000000000000000000000000000000000000000000000000000000023a400000000000000000000000000000000000000000000000000000000000023a600000000000000000000000000000000000000000000000000000000000023a800000000000000000000000000000000000000000000000000000000000023aa00000000000000000000000000000000000000000000000000000000000023ac00000000000000000000000000000000000000000000000000000000000023ae00000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023b200000000000000000000000000000000000000000000000000000000000023b400000000000000000000000000000000000000000000000000000000000023b600000000000000000000000000000000000000000000000000000000000023b800000000000000000000000000000000000000000000000000000000000023ba00000000000000000000000000000000000000000000000000000000000023bc00000000000000000000000000000000000000000000000000000000000023be00000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023c200000000000000000000000000000000000000000000000000000000000023c400000000000000000000000000000000000000000000000000000000000023c600000000000000000000000000000000000000000000000000000000000023c800000000000000000000000000000000000000000000000000000000000023ca00000000000000000000000000000000000000000000000000000000000023cc00000000000000000000000000000000000000000000000000000000000023ce00000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023d200000000000000000000000000000000000000000000000000000000000023d400000000000000000000000000000000000000000000000000000000000023d600000000000000000000000000000000000000000000000000000000000023d800000000000000000000000000000000000000000000000000000000000023da00000000000000000000000000000000000000000000000000000000000023dc00000000000000000000000000000000000000000000000000000000000023de00000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023e200000000000000000000000000000000000000000000000000000000000023e400000000000000000000000000000000000000000000000000000000000023e600000000000000000000000000000000000000000000000000000000000023e800000000000000000000000000000000000000000000000000000000000023ea00000000000000000000000000000000000000000000000000000000000023ec00000000000000000000000000000000000000000000000000000000000023ee00000000000000000000000000000000000000000000000000000000000023f000000000000000000000000000000000000000000000000000000000000023f200000000000000000000000000000000000000000000000000000000000023f400000000000000000000000000000000000000000000000000000000000023f600000000000000000000000000000000000000000000000000000000000023f800000000000000000000000000000000000000000000000000000000000023fa00000000000000000000000000000000000000000000000000000000000023fc00000000000000000000000000000000000000000000000000000000000023fe00000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002402000000000000000000000000000000000000000000000000000000000000240400000000000000000000000000000000000000000000000000000000000024060000000000000000000000000000000000000000000000000000000000002408000000000000000000000000000000000000000000000000000000000000240a000000000000000000000000000000000000000000000000000000000000240c000000000000000000000000000000000000000000000000000000000000240e00000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002412000000000000000000000000000000000000000000000000000000000000241400000000000000000000000000000000000000000000000000000000000024160000000000000000000000000000000000000000000000000000000000002418000000000000000000000000000000000000000000000000000000000000241a000000000000000000000000000000000000000000000000000000000000241c000000000000000000000000000000000000000000000000000000000000241e00000000000000000000000000000000000000000000000000000000000024200000000000000000000000000000000000000000000000000000000000002422000000000000000000000000000000000000000000000000000000000000242400000000000000000000000000000000000000000000000000000000000024260000000000000000000000000000000000000000000000000000000000002428000000000000000000000000000000000000000000000000000000000000242a000000000000000000000000000000000000000000000000000000000000242c000000000000000000000000000000000000000000000000000000000000242e00000000000000000000000000000000000000000000000000000000000024300000000000000000000000000000000000000000000000000000000000002432000000000000000000000000000000000000000000000000000000000000243400000000000000000000000000000000000000000000000000000000000024360000000000000000000000000000000000000000000000000000000000002438000000000000000000000000000000000000000000000000000000000000243a000000000000000000000000000000000000000000000000000000000000243c000000000000000000000000000000000000000000000000000000000000243e00000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002442000000000000000000000000000000000000000000000000000000000000244400000000000000000000000000000000000000000000000000000000000024460000000000000000000000000000000000000000000000000000000000002448000000000000000000000000000000000000000000000000000000000000244a000000000000000000000000000000000000000000000000000000000000244c000000000000000000000000000000000000000000000000000000000000244e00000000000000000000000000000000000000000000000000000000000024500000000000000000000000000000000000000000000000000000000000002452000000000000000000000000000000000000000000000000000000000000245400000000000000000000000000000000000000000000000000000000000024560000000000000000000000000000000000000000000000000000000000002458000000000000000000000000000000000000000000000000000000000000245a000000000000000000000000000000000000000000000000000000000000245c000000000000000000000000000000000000000000000000000000000000245e00000000000000000000000000000000000000000000000000000000000024600000000000000000000000000000000000000000000000000000000000002462000000000000000000000000000000000000000000000000000000000000246400000000000000000000000000000000000000000000000000000000000024660000000000000000000000000000000000000000000000000000000000002468000000000000000000000000000000000000000000000000000000000000246a000000000000000000000000000000000000000000000000000000000000246c000000000000000000000000000000000000000000000000000000000000246e00000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002472000000000000000000000000000000000000000000000000000000000000247400000000000000000000000000000000000000000000000000000000000024760000000000000000000000000000000000000000000000000000000000002478000000000000000000000000000000000000000000000000000000000000247a000000000000000000000000000000000000000000000000000000000000247c000000000000000000000000000000000000000000000000000000000000247e00000000000000000000000000000000000000000000000000000000000024800000000000000000000000000000000000000000000000000000000000002482000000000000000000000000000000000000000000000000000000000000248400000000000000000000000000000000000000000000000000000000000024860000000000000000000000000000000000000000000000000000000000002488000000000000000000000000000000000000000000000000000000000000248a000000000000000000000000000000000000000000000000000000000000248c000000000000000000000000000000000000000000000000000000000000248e00000000000000000000000000000000000000000000000000000000000024900000000000000000000000000000000000000000000000000000000000002492000000000000000000000000000000000000000000000000000000000000249400000000000000000000000000000000000000000000000000000000000024960000000000000000000000000000000000000000000000000000000000002498000000000000000000000000000000000000000000000000000000000000249a000000000000000000000000000000000000000000000000000000000000249c000000000000000000000000000000000000000000000000000000000000249e00000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024a200000000000000000000000000000000000000000000000000000000000024a400000000000000000000000000000000000000000000000000000000000024a600000000000000000000000000000000000000000000000000000000000024a800000000000000000000000000000000000000000000000000000000000024aa00000000000000000000000000000000000000000000000000000000000024ac00000000000000000000000000000000000000000000000000000000000024ae00000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024b200000000000000000000000000000000000000000000000000000000000024b400000000000000000000000000000000000000000000000000000000000024b600000000000000000000000000000000000000000000000000000000000024b800000000000000000000000000000000000000000000000000000000000024ba00000000000000000000000000000000000000000000000000000000000024bc00000000000000000000000000000000000000000000000000000000000024be00000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024c200000000000000000000000000000000000000000000000000000000000024c400000000000000000000000000000000000000000000000000000000000024c600000000000000000000000000000000000000000000000000000000000024c800000000000000000000000000000000000000000000000000000000000024ca00000000000000000000000000000000000000000000000000000000000024cc00000000000000000000000000000000000000000000000000000000000024ce00000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024d200000000000000000000000000000000000000000000000000000000000024d400000000000000000000000000000000000000000000000000000000000024d600000000000000000000000000000000000000000000000000000000000024d800000000000000000000000000000000000000000000000000000000000024da00000000000000000000000000000000000000000000000000000000000024dc00000000000000000000000000000000000000000000000000000000000024de00000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024e200000000000000000000000000000000000000000000000000000000000024e400000000000000000000000000000000000000000000000000000000000024e600000000000000000000000000000000000000000000000000000000000024e800000000000000000000000000000000000000000000000000000000000024ea00000000000000000000000000000000000000000000000000000000000024ec00000000000000000000000000000000000000000000000000000000000024ee00000000000000000000000000000000000000000000000000000000000024f000000000000000000000000000000000000000000000000000000000000024f200000000000000000000000000000000000000000000000000000000000024f400000000000000000000000000000000000000000000000000000000000024f600000000000000000000000000000000000000000000000000000000000024f800000000000000000000000000000000000000000000000000000000000024fa00000000000000000000000000000000000000000000000000000000000024fc00000000000000000000000000000000000000000000000000000000000024fe00000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000002502000000000000000000000000000000000000000000000000000000000000250400000000000000000000000000000000000000000000000000000000000025060000000000000000000000000000000000000000000000000000000000002508000000000000000000000000000000000000000000000000000000000000250a000000000000000000000000000000000000000000000000000000000000250c000000000000000000000000000000000000000000000000000000000000250e00000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002512000000000000000000000000000000000000000000000000000000000000251400000000000000000000000000000000000000000000000000000000000025160000000000000000000000000000000000000000000000000000000000002518000000000000000000000000000000000000000000000000000000000000251a000000000000000000000000000000000000000000000000000000000000251c000000000000000000000000000000000000000000000000000000000000251e00000000000000000000000000000000000000000000000000000000000025200000000000000000000000000000000000000000000000000000000000002522000000000000000000000000000000000000000000000000000000000000252400000000000000000000000000000000000000000000000000000000000025260000000000000000000000000000000000000000000000000000000000002528000000000000000000000000000000000000000000000000000000000000252a000000000000000000000000000000000000000000000000000000000000252c000000000000000000000000000000000000000000000000000000000000252e00000000000000000000000000000000000000000000000000000000000025300000000000000000000000000000000000000000000000000000000000002532000000000000000000000000000000000000000000000000000000000000253400000000000000000000000000000000000000000000000000000000000025360000000000000000000000000000000000000000000000000000000000002538000000000000000000000000000000000000000000000000000000000000253a000000000000000000000000000000000000000000000000000000000000253c000000000000000000000000000000000000000000000000000000000000253e00000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002542000000000000000000000000000000000000000000000000000000000000254400000000000000000000000000000000000000000000000000000000000025460000000000000000000000000000000000000000000000000000000000002548000000000000000000000000000000000000000000000000000000000000254a000000000000000000000000000000000000000000000000000000000000254c000000000000000000000000000000000000000000000000000000000000254e00000000000000000000000000000000000000000000000000000000000025500000000000000000000000000000000000000000000000000000000000002552000000000000000000000000000000000000000000000000000000000000255400000000000000000000000000000000000000000000000000000000000025560000000000000000000000000000000000000000000000000000000000002558000000000000000000000000000000000000000000000000000000000000255a000000000000000000000000000000000000000000000000000000000000255c000000000000000000000000000000000000000000000000000000000000255e00000000000000000000000000000000000000000000000000000000000025600000000000000000000000000000000000000000000000000000000000002562000000000000000000000000000000000000000000000000000000000000256400000000000000000000000000000000000000000000000000000000000025660000000000000000000000000000000000000000000000000000000000002568000000000000000000000000000000000000000000000000000000000000256a000000000000000000000000000000000000000000000000000000000000256c000000000000000000000000000000000000000000000000000000000000256e00000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002572000000000000000000000000000000000000000000000000000000000000257400000000000000000000000000000000000000000000000000000000000025760000000000000000000000000000000000000000000000000000000000002578000000000000000000000000000000000000000000000000000000000000257a000000000000000000000000000000000000000000000000000000000000257c000000000000000000000000000000000000000000000000000000000000257e00000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000000000000000002582000000000000000000000000000000000000000000000000000000000000258400000000000000000000000000000000000000000000000000000000000025860000000000000000000000000000000000000000000000000000000000002588000000000000000000000000000000000000000000000000000000000000258a000000000000000000000000000000000000000000000000000000000000258c000000000000000000000000000000000000000000000000000000000000258e00000000000000000000000000000000000000000000000000000000000025900000000000000000000000000000000000000000000000000000000000002592000000000000000000000000000000000000000000000000000000000000259400000000000000000000000000000000000000000000000000000000000025960000000000000000000000000000000000000000000000000000000000002598000000000000000000000000000000000000000000000000000000000000259a000000000000000000000000000000000000000000000000000000000000259c000000000000000000000000000000000000000000000000000000000000259e00000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025a200000000000000000000000000000000000000000000000000000000000025a400000000000000000000000000000000000000000000000000000000000025a600000000000000000000000000000000000000000000000000000000000025a800000000000000000000000000000000000000000000000000000000000025aa00000000000000000000000000000000000000000000000000000000000025ac00000000000000000000000000000000000000000000000000000000000025ae00000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025b200000000000000000000000000000000000000000000000000000000000025b400000000000000000000000000000000000000000000000000000000000025b600000000000000000000000000000000000000000000000000000000000025b800000000000000000000000000000000000000000000000000000000000025ba00000000000000000000000000000000000000000000000000000000000025bc00000000000000000000000000000000000000000000000000000000000025be00000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025c200000000000000000000000000000000000000000000000000000000000025c400000000000000000000000000000000000000000000000000000000000025c600000000000000000000000000000000000000000000000000000000000025c800000000000000000000000000000000000000000000000000000000000025ca00000000000000000000000000000000000000000000000000000000000025cc00000000000000000000000000000000000000000000000000000000000025ce00000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025d200000000000000000000000000000000000000000000000000000000000025d400000000000000000000000000000000000000000000000000000000000025d600000000000000000000000000000000000000000000000000000000000025d800000000000000000000000000000000000000000000000000000000000025da00000000000000000000000000000000000000000000000000000000000025dc00000000000000000000000000000000000000000000000000000000000025de00000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025e200000000000000000000000000000000000000000000000000000000000025e400000000000000000000000000000000000000000000000000000000000025e600000000000000000000000000000000000000000000000000000000000025e800000000000000000000000000000000000000000000000000000000000025ea00000000000000000000000000000000000000000000000000000000000025ec00000000000000000000000000000000000000000000000000000000000025ee00000000000000000000000000000000000000000000000000000000000025f000000000000000000000000000000000000000000000000000000000000025f200000000000000000000000000000000000000000000000000000000000025f400000000000000000000000000000000000000000000000000000000000025f600000000000000000000000000000000000000000000000000000000000025f800000000000000000000000000000000000000000000000000000000000025fa00000000000000000000000000000000000000000000000000000000000025fc00000000000000000000000000000000000000000000000000000000000025fe00000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002602000000000000000000000000000000000000000000000000000000000000260400000000000000000000000000000000000000000000000000000000000026060000000000000000000000000000000000000000000000000000000000002608000000000000000000000000000000000000000000000000000000000000260a000000000000000000000000000000000000000000000000000000000000260c000000000000000000000000000000000000000000000000000000000000260e00000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002612000000000000000000000000000000000000000000000000000000000000261400000000000000000000000000000000000000000000000000000000000026160000000000000000000000000000000000000000000000000000000000002618000000000000000000000000000000000000000000000000000000000000261a000000000000000000000000000000000000000000000000000000000000261c000000000000000000000000000000000000000000000000000000000000261e00000000000000000000000000000000000000000000000000000000000026200000000000000000000000000000000000000000000000000000000000002622000000000000000000000000000000000000000000000000000000000000262400000000000000000000000000000000000000000000000000000000000026260000000000000000000000000000000000000000000000000000000000002628000000000000000000000000000000000000000000000000000000000000262a000000000000000000000000000000000000000000000000000000000000262c000000000000000000000000000000000000000000000000000000000000262e00000000000000000000000000000000000000000000000000000000000026300000000000000000000000000000000000000000000000000000000000002632000000000000000000000000000000000000000000000000000000000000263400000000000000000000000000000000000000000000000000000000000026360000000000000000000000000000000000000000000000000000000000002638000000000000000000000000000000000000000000000000000000000000263a000000000000000000000000000000000000000000000000000000000000263c000000000000000000000000000000000000000000000000000000000000263e00000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002642000000000000000000000000000000000000000000000000000000000000264400000000000000000000000000000000000000000000000000000000000026460000000000000000000000000000000000000000000000000000000000002648000000000000000000000000000000000000000000000000000000000000264a000000000000000000000000000000000000000000000000000000000000264c000000000000000000000000000000000000000000000000000000000000264e00000000000000000000000000000000000000000000000000000000000026500000000000000000000000000000000000000000000000000000000000002652000000000000000000000000000000000000000000000000000000000000265400000000000000000000000000000000000000000000000000000000000026560000000000000000000000000000000000000000000000000000000000002658000000000000000000000000000000000000000000000000000000000000265a000000000000000000000000000000000000000000000000000000000000265c000000000000000000000000000000000000000000000000000000000000265e00000000000000000000000000000000000000000000000000000000000026600000000000000000000000000000000000000000000000000000000000002662000000000000000000000000000000000000000000000000000000000000266400000000000000000000000000000000000000000000000000000000000026660000000000000000000000000000000000000000000000000000000000002668000000000000000000000000000000000000000000000000000000000000266a000000000000000000000000000000000000000000000000000000000000266c000000000000000000000000000000000000000000000000000000000000266e00000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002672000000000000000000000000000000000000000000000000000000000000267400000000000000000000000000000000000000000000000000000000000026760000000000000000000000000000000000000000000000000000000000002678000000000000000000000000000000000000000000000000000000000000267a000000000000000000000000000000000000000000000000000000000000267c000000000000000000000000000000000000000000000000000000000000267e00000000000000000000000000000000000000000000000000000000000026800000000000000000000000000000000000000000000000000000000000002682000000000000000000000000000000000000000000000000000000000000268400000000000000000000000000000000000000000000000000000000000026860000000000000000000000000000000000000000000000000000000000002688000000000000000000000000000000000000000000000000000000000000268a000000000000000000000000000000000000000000000000000000000000268c000000000000000000000000000000000000000000000000000000000000268e00000000000000000000000000000000000000000000000000000000000026900000000000000000000000000000000000000000000000000000000000002692000000000000000000000000000000000000000000000000000000000000269400000000000000000000000000000000000000000000000000000000000026960000000000000000000000000000000000000000000000000000000000002698000000000000000000000000000000000000000000000000000000000000269a000000000000000000000000000000000000000000000000000000000000269c000000000000000000000000000000000000000000000000000000000000269e00000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026a200000000000000000000000000000000000000000000000000000000000026a400000000000000000000000000000000000000000000000000000000000026a600000000000000000000000000000000000000000000000000000000000026a800000000000000000000000000000000000000000000000000000000000026aa00000000000000000000000000000000000000000000000000000000000026ac00000000000000000000000000000000000000000000000000000000000026ae00000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026b200000000000000000000000000000000000000000000000000000000000026b400000000000000000000000000000000000000000000000000000000000026b600000000000000000000000000000000000000000000000000000000000026b800000000000000000000000000000000000000000000000000000000000026ba00000000000000000000000000000000000000000000000000000000000026bc00000000000000000000000000000000000000000000000000000000000026be00000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026c200000000000000000000000000000000000000000000000000000000000026c400000000000000000000000000000000000000000000000000000000000026c600000000000000000000000000000000000000000000000000000000000026c800000000000000000000000000000000000000000000000000000000000026ca00000000000000000000000000000000000000000000000000000000000026cc00000000000000000000000000000000000000000000000000000000000026ce00000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026d200000000000000000000000000000000000000000000000000000000000026d400000000000000000000000000000000000000000000000000000000000026d600000000000000000000000000000000000000000000000000000000000026d800000000000000000000000000000000000000000000000000000000000026da00000000000000000000000000000000000000000000000000000000000026dc00000000000000000000000000000000000000000000000000000000000026de00000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026e200000000000000000000000000000000000000000000000000000000000026e400000000000000000000000000000000000000000000000000000000000026e600000000000000000000000000000000000000000000000000000000000026e800000000000000000000000000000000000000000000000000000000000026ea00000000000000000000000000000000000000000000000000000000000026ec00000000000000000000000000000000000000000000000000000000000026ee00000000000000000000000000000000000000000000000000000000000026f000000000000000000000000000000000000000000000000000000000000026f200000000000000000000000000000000000000000000000000000000000026f400000000000000000000000000000000000000000000000000000000000026f600000000000000000000000000000000000000000000000000000000000026f800000000000000000000000000000000000000000000000000000000000026fa00000000000000000000000000000000000000000000000000000000000026fc00000000000000000000000000000000000000000000000000000000000026fe00000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000002702000000000000000000000000000000000000000000000000000000000000270400000000000000000000000000000000000000000000000000000000000027060000000000000000000000000000000000000000000000000000000000002708000000000000000000000000000000000000000000000000000000000000270a000000000000000000000000000000000000000000000000000000000000270c000000000000000000000000000000000000000000000000000000000000270e00000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002712000000000000000000000000000000000000000000000000000000000000271400000000000000000000000000000000000000000000000000000000000027160000000000000000000000000000000000000000000000000000000000002718000000000000000000000000000000000000000000000000000000000000271a000000000000000000000000000000000000000000000000000000000000271c000000000000000000000000000000000000000000000000000000000000271e00000000000000000000000000000000000000000000000000000000000027200000000000000000000000000000000000000000000000000000000000002722000000000000000000000000000000000000000000000000000000000000272400000000000000000000000000000000000000000000000000000000000027260000000000000000000000000000000000000000000000000000000000002728000000000000000000000000000000000000000000000000000000000000272a000000000000000000000000000000000000000000000000000000000000272c000000000000000000000000000000000000000000000000000000000000272e00000000000000000000000000000000000000000000000000000000000027300000000000000000000000000000000000000000000000000000000000002732000000000000000000000000000000000000000000000000000000000000273400000000000000000000000000000000000000000000000000000000000027360000000000000000000000000000000000000000000000000000000000002738000000000000000000000000000000000000000000000000000000000000273a000000000000000000000000000000000000000000000000000000000000273c000000000000000000000000000000000000000000000000000000000000273e00000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002742000000000000000000000000000000000000000000000000000000000000274400000000000000000000000000000000000000000000000000000000000027460000000000000000000000000000000000000000000000000000000000002748000000000000000000000000000000000000000000000000000000000000274a000000000000000000000000000000000000000000000000000000000000274c000000000000000000000000000000000000000000000000000000000000274e00000000000000000000000000000000000000000000000000000000000027500000000000000000000000000000000000000000000000000000000000002752000000000000000000000000000000000000000000000000000000000000275400000000000000000000000000000000000000000000000000000000000027560000000000000000000000000000000000000000000000000000000000002758000000000000000000000000000000000000000000000000000000000000275a000000000000000000000000000000000000000000000000000000000000275c000000000000000000000000000000000000000000000000000000000000275e00000000000000000000000000000000000000000000000000000000000027600000000000000000000000000000000000000000000000000000000000002762000000000000000000000000000000000000000000000000000000000000276400000000000000000000000000000000000000000000000000000000000027660000000000000000000000000000000000000000000000000000000000002768000000000000000000000000000000000000000000000000000000000000276a000000000000000000000000000000000000000000000000000000000000276c000000000000000000000000000000000000000000000000000000000000276e00000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002772000000000000000000000000000000000000000000000000000000000000277400000000000000000000000000000000000000000000000000000000000027760000000000000000000000000000000000000000000000000000000000002778000000000000000000000000000000000000000000000000000000000000277a000000000000000000000000000000000000000000000000000000000000277c000000000000000000000000000000000000000000000000000000000000277e00000000000000000000000000000000000000000000000000000000000027800000000000000000000000000000000000000000000000000000000000002782000000000000000000000000000000000000000000000000000000000000278400000000000000000000000000000000000000000000000000000000000027860000000000000000000000000000000000000000000000000000000000002788000000000000000000000000000000000000000000000000000000000000278a000000000000000000000000000000000000000000000000000000000000278c000000000000000000000000000000000000000000000000000000000000278e00000000000000000000000000000000000000000000000000000000000027900000000000000000000000000000000000000000000000000000000000002792000000000000000000000000000000000000000000000000000000000000279400000000000000000000000000000000000000000000000000000000000027960000000000000000000000000000000000000000000000000000000000002798000000000000000000000000000000000000000000000000000000000000279a000000000000000000000000000000000000000000000000000000000000279c000000000000000000000000000000000000000000000000000000000000279e00000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027a200000000000000000000000000000000000000000000000000000000000027a400000000000000000000000000000000000000000000000000000000000027a600000000000000000000000000000000000000000000000000000000000027a800000000000000000000000000000000000000000000000000000000000027aa00000000000000000000000000000000000000000000000000000000000027ac00000000000000000000000000000000000000000000000000000000000027ae00000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027b200000000000000000000000000000000000000000000000000000000000027b400000000000000000000000000000000000000000000000000000000000027b600000000000000000000000000000000000000000000000000000000000027b800000000000000000000000000000000000000000000000000000000000027ba00000000000000000000000000000000000000000000000000000000000027bc00000000000000000000000000000000000000000000000000000000000027be00000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027c200000000000000000000000000000000000000000000000000000000000027c400000000000000000000000000000000000000000000000000000000000027c600000000000000000000000000000000000000000000000000000000000027c800000000000000000000000000000000000000000000000000000000000027ca00000000000000000000000000000000000000000000000000000000000027cc00000000000000000000000000000000000000000000000000000000000027ce00000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027d200000000000000000000000000000000000000000000000000000000000027d400000000000000000000000000000000000000000000000000000000000027d600000000000000000000000000000000000000000000000000000000000027d800000000000000000000000000000000000000000000000000000000000027da00000000000000000000000000000000000000000000000000000000000027dc00000000000000000000000000000000000000000000000000000000000027de00000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027e200000000000000000000000000000000000000000000000000000000000027e400000000000000000000000000000000000000000000000000000000000027e600000000000000000000000000000000000000000000000000000000000027e800000000000000000000000000000000000000000000000000000000000027ea00000000000000000000000000000000000000000000000000000000000027ec00000000000000000000000000000000000000000000000000000000000027ee00000000000000000000000000000000000000000000000000000000000027f000000000000000000000000000000000000000000000000000000000000027f200000000000000000000000000000000000000000000000000000000000027f400000000000000000000000000000000000000000000000000000000000027f600000000000000000000000000000000000000000000000000000000000027f800000000000000000000000000000000000000000000000000000000000027fa00000000000000000000000000000000000000000000000000000000000027fc00000000000000000000000000000000000000000000000000000000000027fe00000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002802000000000000000000000000000000000000000000000000000000000000280400000000000000000000000000000000000000000000000000000000000028060000000000000000000000000000000000000000000000000000000000002808000000000000000000000000000000000000000000000000000000000000280a000000000000000000000000000000000000000000000000000000000000280c000000000000000000000000000000000000000000000000000000000000280e00000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002812000000000000000000000000000000000000000000000000000000000000281400000000000000000000000000000000000000000000000000000000000028160000000000000000000000000000000000000000000000000000000000002818000000000000000000000000000000000000000000000000000000000000281a000000000000000000000000000000000000000000000000000000000000281c000000000000000000000000000000000000000000000000000000000000281e00000000000000000000000000000000000000000000000000000000000028200000000000000000000000000000000000000000000000000000000000002822000000000000000000000000000000000000000000000000000000000000282400000000000000000000000000000000000000000000000000000000000028260000000000000000000000000000000000000000000000000000000000002828000000000000000000000000000000000000000000000000000000000000282a000000000000000000000000000000000000000000000000000000000000282c000000000000000000000000000000000000000000000000000000000000282e00000000000000000000000000000000000000000000000000000000000028300000000000000000000000000000000000000000000000000000000000002832000000000000000000000000000000000000000000000000000000000000283400000000000000000000000000000000000000000000000000000000000028360000000000000000000000000000000000000000000000000000000000002838000000000000000000000000000000000000000000000000000000000000283a000000000000000000000000000000000000000000000000000000000000283c000000000000000000000000000000000000000000000000000000000000283e00000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002842000000000000000000000000000000000000000000000000000000000000284400000000000000000000000000000000000000000000000000000000000028460000000000000000000000000000000000000000000000000000000000002848000000000000000000000000000000000000000000000000000000000000284a000000000000000000000000000000000000000000000000000000000000284c000000000000000000000000000000000000000000000000000000000000284e00000000000000000000000000000000000000000000000000000000000028500000000000000000000000000000000000000000000000000000000000002852000000000000000000000000000000000000000000000000000000000000285400000000000000000000000000000000000000000000000000000000000028560000000000000000000000000000000000000000000000000000000000002858000000000000000000000000000000000000000000000000000000000000285a000000000000000000000000000000000000000000000000000000000000285c000000000000000000000000000000000000000000000000000000000000285e00000000000000000000000000000000000000000000000000000000000028600000000000000000000000000000000000000000000000000000000000002862000000000000000000000000000000000000000000000000000000000000286400000000000000000000000000000000000000000000000000000000000028660000000000000000000000000000000000000000000000000000000000002868000000000000000000000000000000000000000000000000000000000000286a000000000000000000000000000000000000000000000000000000000000286c000000000000000000000000000000000000000000000000000000000000286e00000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002872000000000000000000000000000000000000000000000000000000000000287400000000000000000000000000000000000000000000000000000000000028760000000000000000000000000000000000000000000000000000000000002878000000000000000000000000000000000000000000000000000000000000287a000000000000000000000000000000000000000000000000000000000000287c000000000000000000000000000000000000000000000000000000000000287e00000000000000000000000000000000000000000000000000000000000028800000000000000000000000000000000000000000000000000000000000002882000000000000000000000000000000000000000000000000000000000000288400000000000000000000000000000000000000000000000000000000000028860000000000000000000000000000000000000000000000000000000000002888000000000000000000000000000000000000000000000000000000000000288a000000000000000000000000000000000000000000000000000000000000288c000000000000000000000000000000000000000000000000000000000000288e00000000000000000000000000000000000000000000000000000000000028900000000000000000000000000000000000000000000000000000000000002892000000000000000000000000000000000000000000000000000000000000289400000000000000000000000000000000000000000000000000000000000028960000000000000000000000000000000000000000000000000000000000002898000000000000000000000000000000000000000000000000000000000000289a000000000000000000000000000000000000000000000000000000000000289c000000000000000000000000000000000000000000000000000000000000289e00000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028a200000000000000000000000000000000000000000000000000000000000028a400000000000000000000000000000000000000000000000000000000000028a600000000000000000000000000000000000000000000000000000000000028a800000000000000000000000000000000000000000000000000000000000028aa00000000000000000000000000000000000000000000000000000000000028ac00000000000000000000000000000000000000000000000000000000000028ae00000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028b200000000000000000000000000000000000000000000000000000000000028b400000000000000000000000000000000000000000000000000000000000028b600000000000000000000000000000000000000000000000000000000000028b800000000000000000000000000000000000000000000000000000000000028ba00000000000000000000000000000000000000000000000000000000000028bc00000000000000000000000000000000000000000000000000000000000028be00000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028c200000000000000000000000000000000000000000000000000000000000028c400000000000000000000000000000000000000000000000000000000000028c600000000000000000000000000000000000000000000000000000000000028c800000000000000000000000000000000000000000000000000000000000028ca00000000000000000000000000000000000000000000000000000000000028cc00000000000000000000000000000000000000000000000000000000000028ce00000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028d200000000000000000000000000000000000000000000000000000000000028d400000000000000000000000000000000000000000000000000000000000028d600000000000000000000000000000000000000000000000000000000000028d800000000000000000000000000000000000000000000000000000000000028da00000000000000000000000000000000000000000000000000000000000028dc00000000000000000000000000000000000000000000000000000000000028de00000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028e200000000000000000000000000000000000000000000000000000000000028e400000000000000000000000000000000000000000000000000000000000028e600000000000000000000000000000000000000000000000000000000000028e800000000000000000000000000000000000000000000000000000000000028ea00000000000000000000000000000000000000000000000000000000000028ec00000000000000000000000000000000000000000000000000000000000028ee00000000000000000000000000000000000000000000000000000000000028f000000000000000000000000000000000000000000000000000000000000028f200000000000000000000000000000000000000000000000000000000000028f400000000000000000000000000000000000000000000000000000000000028f600000000000000000000000000000000000000000000000000000000000028f800000000000000000000000000000000000000000000000000000000000028fa00000000000000000000000000000000000000000000000000000000000028fc00000000000000000000000000000000000000000000000000000000000028fe00000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002902000000000000000000000000000000000000000000000000000000000000290400000000000000000000000000000000000000000000000000000000000029060000000000000000000000000000000000000000000000000000000000002908000000000000000000000000000000000000000000000000000000000000290a000000000000000000000000000000000000000000000000000000000000290c000000000000000000000000000000000000000000000000000000000000290e00000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002912000000000000000000000000000000000000000000000000000000000000291400000000000000000000000000000000000000000000000000000000000029160000000000000000000000000000000000000000000000000000000000002918000000000000000000000000000000000000000000000000000000000000291a000000000000000000000000000000000000000000000000000000000000291c000000000000000000000000000000000000000000000000000000000000291e00000000000000000000000000000000000000000000000000000000000029200000000000000000000000000000000000000000000000000000000000002922000000000000000000000000000000000000000000000000000000000000292400000000000000000000000000000000000000000000000000000000000029260000000000000000000000000000000000000000000000000000000000002928000000000000000000000000000000000000000000000000000000000000292a000000000000000000000000000000000000000000000000000000000000292c000000000000000000000000000000000000000000000000000000000000292e00000000000000000000000000000000000000000000000000000000000029300000000000000000000000000000000000000000000000000000000000002932000000000000000000000000000000000000000000000000000000000000293400000000000000000000000000000000000000000000000000000000000029360000000000000000000000000000000000000000000000000000000000002938000000000000000000000000000000000000000000000000000000000000293a000000000000000000000000000000000000000000000000000000000000293c000000000000000000000000000000000000000000000000000000000000293e00000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002942000000000000000000000000000000000000000000000000000000000000294400000000000000000000000000000000000000000000000000000000000029460000000000000000000000000000000000000000000000000000000000002948000000000000000000000000000000000000000000000000000000000000294a000000000000000000000000000000000000000000000000000000000000294c000000000000000000000000000000000000000000000000000000000000294e00000000000000000000000000000000000000000000000000000000000029500000000000000000000000000000000000000000000000000000000000002952000000000000000000000000000000000000000000000000000000000000295400000000000000000000000000000000000000000000000000000000000029560000000000000000000000000000000000000000000000000000000000002958000000000000000000000000000000000000000000000000000000000000295a000000000000000000000000000000000000000000000000000000000000295c000000000000000000000000000000000000000000000000000000000000295e00000000000000000000000000000000000000000000000000000000000029600000000000000000000000000000000000000000000000000000000000002962000000000000000000000000000000000000000000000000000000000000296400000000000000000000000000000000000000000000000000000000000029660000000000000000000000000000000000000000000000000000000000002968000000000000000000000000000000000000000000000000000000000000296a000000000000000000000000000000000000000000000000000000000000296c000000000000000000000000000000000000000000000000000000000000296e00000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002972000000000000000000000000000000000000000000000000000000000000297400000000000000000000000000000000000000000000000000000000000029760000000000000000000000000000000000000000000000000000000000002978000000000000000000000000000000000000000000000000000000000000297a000000000000000000000000000000000000000000000000000000000000297c000000000000000000000000000000000000000000000000000000000000297e00000000000000000000000000000000000000000000000000000000000029800000000000000000000000000000000000000000000000000000000000002982000000000000000000000000000000000000000000000000000000000000298400000000000000000000000000000000000000000000000000000000000029860000000000000000000000000000000000000000000000000000000000002988000000000000000000000000000000000000000000000000000000000000298a000000000000000000000000000000000000000000000000000000000000298c000000000000000000000000000000000000000000000000000000000000298e00000000000000000000000000000000000000000000000000000000000029900000000000000000000000000000000000000000000000000000000000002992000000000000000000000000000000000000000000000000000000000000299400000000000000000000000000000000000000000000000000000000000029960000000000000000000000000000000000000000000000000000000000002998000000000000000000000000000000000000000000000000000000000000299a000000000000000000000000000000000000000000000000000000000000299c000000000000000000000000000000000000000000000000000000000000299e00000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029a200000000000000000000000000000000000000000000000000000000000029a400000000000000000000000000000000000000000000000000000000000029a600000000000000000000000000000000000000000000000000000000000029a800000000000000000000000000000000000000000000000000000000000029aa00000000000000000000000000000000000000000000000000000000000029ac00000000000000000000000000000000000000000000000000000000000029ae00000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029b200000000000000000000000000000000000000000000000000000000000029b400000000000000000000000000000000000000000000000000000000000029b600000000000000000000000000000000000000000000000000000000000029b800000000000000000000000000000000000000000000000000000000000029ba00000000000000000000000000000000000000000000000000000000000029bc00000000000000000000000000000000000000000000000000000000000029be00000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029c200000000000000000000000000000000000000000000000000000000000029c400000000000000000000000000000000000000000000000000000000000029c600000000000000000000000000000000000000000000000000000000000029c800000000000000000000000000000000000000000000000000000000000029ca00000000000000000000000000000000000000000000000000000000000029cc00000000000000000000000000000000000000000000000000000000000029ce00000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029d200000000000000000000000000000000000000000000000000000000000029d400000000000000000000000000000000000000000000000000000000000029d600000000000000000000000000000000000000000000000000000000000029d800000000000000000000000000000000000000000000000000000000000029da00000000000000000000000000000000000000000000000000000000000029dc00000000000000000000000000000000000000000000000000000000000029de00000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029e200000000000000000000000000000000000000000000000000000000000029e400000000000000000000000000000000000000000000000000000000000029e600000000000000000000000000000000000000000000000000000000000029e800000000000000000000000000000000000000000000000000000000000029ea00000000000000000000000000000000000000000000000000000000000029ec00000000000000000000000000000000000000000000000000000000000029ee00000000000000000000000000000000000000000000000000000000000029f000000000000000000000000000000000000000000000000000000000000029f200000000000000000000000000000000000000000000000000000000000029f400000000000000000000000000000000000000000000000000000000000029f600000000000000000000000000000000000000000000000000000000000029f800000000000000000000000000000000000000000000000000000000000029fa00000000000000000000000000000000000000000000000000000000000029fc00000000000000000000000000000000000000000000000000000000000029fe0000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a020000000000000000000000000000000000000000000000000000000000002a040000000000000000000000000000000000000000000000000000000000002a060000000000000000000000000000000000000000000000000000000000002a080000000000000000000000000000000000000000000000000000000000002a0a0000000000000000000000000000000000000000000000000000000000002a0c0000000000000000000000000000000000000000000000000000000000002a0e0000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a120000000000000000000000000000000000000000000000000000000000002a140000000000000000000000000000000000000000000000000000000000002a160000000000000000000000000000000000000000000000000000000000002a180000000000000000000000000000000000000000000000000000000000002a1a0000000000000000000000000000000000000000000000000000000000002a1c0000000000000000000000000000000000000000000000000000000000002a1e0000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a220000000000000000000000000000000000000000000000000000000000002a240000000000000000000000000000000000000000000000000000000000002a260000000000000000000000000000000000000000000000000000000000002a280000000000000000000000000000000000000000000000000000000000002a2a0000000000000000000000000000000000000000000000000000000000002a2c0000000000000000000000000000000000000000000000000000000000002a2e0000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a320000000000000000000000000000000000000000000000000000000000002a340000000000000000000000000000000000000000000000000000000000002a360000000000000000000000000000000000000000000000000000000000002a380000000000000000000000000000000000000000000000000000000000002a3a0000000000000000000000000000000000000000000000000000000000002a3c0000000000000000000000000000000000000000000000000000000000002a3e0000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a420000000000000000000000000000000000000000000000000000000000002a440000000000000000000000000000000000000000000000000000000000002a460000000000000000000000000000000000000000000000000000000000002a480000000000000000000000000000000000000000000000000000000000002a4a0000000000000000000000000000000000000000000000000000000000002a4c0000000000000000000000000000000000000000000000000000000000002a4e0000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a520000000000000000000000000000000000000000000000000000000000002a540000000000000000000000000000000000000000000000000000000000002a560000000000000000000000000000000000000000000000000000000000002a580000000000000000000000000000000000000000000000000000000000002a5a0000000000000000000000000000000000000000000000000000000000002a5c0000000000000000000000000000000000000000000000000000000000002a5e0000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a620000000000000000000000000000000000000000000000000000000000002a640000000000000000000000000000000000000000000000000000000000002a660000000000000000000000000000000000000000000000000000000000002a680000000000000000000000000000000000000000000000000000000000002a6a0000000000000000000000000000000000000000000000000000000000002a6c0000000000000000000000000000000000000000000000000000000000002a6e0000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a720000000000000000000000000000000000000000000000000000000000002a740000000000000000000000000000000000000000000000000000000000002a760000000000000000000000000000000000000000000000000000000000002a780000000000000000000000000000000000000000000000000000000000002a7a0000000000000000000000000000000000000000000000000000000000002a7c0000000000000000000000000000000000000000000000000000000000002a7e0000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a820000000000000000000000000000000000000000000000000000000000002a840000000000000000000000000000000000000000000000000000000000002a860000000000000000000000000000000000000000000000000000000000002a880000000000000000000000000000000000000000000000000000000000002a8a0000000000000000000000000000000000000000000000000000000000002a8c0000000000000000000000000000000000000000000000000000000000002a8e0000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002a920000000000000000000000000000000000000000000000000000000000002a940000000000000000000000000000000000000000000000000000000000002a960000000000000000000000000000000000000000000000000000000000002a980000000000000000000000000000000000000000000000000000000000002a9a0000000000000000000000000000000000000000000000000000000000002a9c0000000000000000000000000000000000000000000000000000000000002a9e0000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002aa20000000000000000000000000000000000000000000000000000000000002aa40000000000000000000000000000000000000000000000000000000000002aa60000000000000000000000000000000000000000000000000000000000002aa80000000000000000000000000000000000000000000000000000000000002aaa0000000000000000000000000000000000000000000000000000000000002aac0000000000000000000000000000000000000000000000000000000000002aae0000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ab20000000000000000000000000000000000000000000000000000000000002ab40000000000000000000000000000000000000000000000000000000000002ab60000000000000000000000000000000000000000000000000000000000002ab80000000000000000000000000000000000000000000000000000000000002aba0000000000000000000000000000000000000000000000000000000000002abc0000000000000000000000000000000000000000000000000000000000002abe0000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ac20000000000000000000000000000000000000000000000000000000000002ac40000000000000000000000000000000000000000000000000000000000002ac60000000000000000000000000000000000000000000000000000000000002ac80000000000000000000000000000000000000000000000000000000000002aca0000000000000000000000000000000000000000000000000000000000002acc0000000000000000000000000000000000000000000000000000000000002ace0000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ad20000000000000000000000000000000000000000000000000000000000002ad40000000000000000000000000000000000000000000000000000000000002ad60000000000000000000000000000000000000000000000000000000000002ad80000000000000000000000000000000000000000000000000000000000002ada0000000000000000000000000000000000000000000000000000000000002adc0000000000000000000000000000000000000000000000000000000000002ade0000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002ae20000000000000000000000000000000000000000000000000000000000002ae40000000000000000000000000000000000000000000000000000000000002ae60000000000000000000000000000000000000000000000000000000000002ae80000000000000000000000000000000000000000000000000000000000002aea0000000000000000000000000000000000000000000000000000000000002aec0000000000000000000000000000000000000000000000000000000000002aee0000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002af20000000000000000000000000000000000000000000000000000000000002af40000000000000000000000000000000000000000000000000000000000002af60000000000000000000000000000000000000000000000000000000000002af80000000000000000000000000000000000000000000000000000000000002afa0000000000000000000000000000000000000000000000000000000000002afc0000000000000000000000000000000000000000000000000000000000002afe0000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b020000000000000000000000000000000000000000000000000000000000002b040000000000000000000000000000000000000000000000000000000000002b060000000000000000000000000000000000000000000000000000000000002b080000000000000000000000000000000000000000000000000000000000002b0a0000000000000000000000000000000000000000000000000000000000002b0c0000000000000000000000000000000000000000000000000000000000002b0e0000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b120000000000000000000000000000000000000000000000000000000000002b140000000000000000000000000000000000000000000000000000000000002b160000000000000000000000000000000000000000000000000000000000002b180000000000000000000000000000000000000000000000000000000000002b1a0000000000000000000000000000000000000000000000000000000000002b1c0000000000000000000000000000000000000000000000000000000000002b1e0000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b220000000000000000000000000000000000000000000000000000000000002b240000000000000000000000000000000000000000000000000000000000002b260000000000000000000000000000000000000000000000000000000000002b280000000000000000000000000000000000000000000000000000000000002b2a0000000000000000000000000000000000000000000000000000000000002b2c0000000000000000000000000000000000000000000000000000000000002b2e0000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b320000000000000000000000000000000000000000000000000000000000002b340000000000000000000000000000000000000000000000000000000000002b360000000000000000000000000000000000000000000000000000000000002b380000000000000000000000000000000000000000000000000000000000002b3a0000000000000000000000000000000000000000000000000000000000002b3c0000000000000000000000000000000000000000000000000000000000002b3e0000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b420000000000000000000000000000000000000000000000000000000000002b440000000000000000000000000000000000000000000000000000000000002b460000000000000000000000000000000000000000000000000000000000002b480000000000000000000000000000000000000000000000000000000000002b4a0000000000000000000000000000000000000000000000000000000000002b4c0000000000000000000000000000000000000000000000000000000000002b4e0000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b520000000000000000000000000000000000000000000000000000000000002b540000000000000000000000000000000000000000000000000000000000002b560000000000000000000000000000000000000000000000000000000000002b580000000000000000000000000000000000000000000000000000000000002b5a0000000000000000000000000000000000000000000000000000000000002b5c0000000000000000000000000000000000000000000000000000000000002b5e0000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b620000000000000000000000000000000000000000000000000000000000002b640000000000000000000000000000000000000000000000000000000000002b660000000000000000000000000000000000000000000000000000000000002b680000000000000000000000000000000000000000000000000000000000002b6a0000000000000000000000000000000000000000000000000000000000002b6c0000000000000000000000000000000000000000000000000000000000002b6e0000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b720000000000000000000000000000000000000000000000000000000000002b740000000000000000000000000000000000000000000000000000000000002b760000000000000000000000000000000000000000000000000000000000002b780000000000000000000000000000000000000000000000000000000000002b7a0000000000000000000000000000000000000000000000000000000000002b7c0000000000000000000000000000000000000000000000000000000000002b7e0000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b820000000000000000000000000000000000000000000000000000000000002b840000000000000000000000000000000000000000000000000000000000002b860000000000000000000000000000000000000000000000000000000000002b880000000000000000000000000000000000000000000000000000000000002b8a0000000000000000000000000000000000000000000000000000000000002b8c0000000000000000000000000000000000000000000000000000000000002b8e0000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002b920000000000000000000000000000000000000000000000000000000000002b940000000000000000000000000000000000000000000000000000000000002b960000000000000000000000000000000000000000000000000000000000002b980000000000000000000000000000000000000000000000000000000000002b9a0000000000000000000000000000000000000000000000000000000000002b9c0000000000000000000000000000000000000000000000000000000000002b9e0000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002ba20000000000000000000000000000000000000000000000000000000000002ba40000000000000000000000000000000000000000000000000000000000002ba60000000000000000000000000000000000000000000000000000000000002ba80000000000000000000000000000000000000000000000000000000000002baa0000000000000000000000000000000000000000000000000000000000002bac0000000000000000000000000000000000000000000000000000000000002bae0000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bb20000000000000000000000000000000000000000000000000000000000002bb40000000000000000000000000000000000000000000000000000000000002bb60000000000000000000000000000000000000000000000000000000000002bb80000000000000000000000000000000000000000000000000000000000002bba0000000000000000000000000000000000000000000000000000000000002bbc0000000000000000000000000000000000000000000000000000000000002bbe0000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bc20000000000000000000000000000000000000000000000000000000000002bc40000000000000000000000000000000000000000000000000000000000002bc60000000000000000000000000000000000000000000000000000000000002bc80000000000000000000000000000000000000000000000000000000000002bca0000000000000000000000000000000000000000000000000000000000002bcc0000000000000000000000000000000000000000000000000000000000002bce0000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002bd20000000000000000000000000000000000000000000000000000000000002bd40000000000000000000000000000000000000000000000000000000000002bd60000000000000000000000000000000000000000000000000000000000002bd80000000000000000000000000000000000000000000000000000000000002bda0000000000000000000000000000000000000000000000000000000000002bdc0000000000000000000000000000000000000000000000000000000000002bde0000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002be20000000000000000000000000000000000000000000000000000000000002be40000000000000000000000000000000000000000000000000000000000002be60000000000000000000000000000000000000000000000000000000000002be80000000000000000000000000000000000000000000000000000000000002bea0000000000000000000000000000000000000000000000000000000000002bec0000000000000000000000000000000000000000000000000000000000002bee0000000000000000000000000000000000000000000000000000000000002bf00000000000000000000000000000000000000000000000000000000000002bf20000000000000000000000000000000000000000000000000000000000002bf40000000000000000000000000000000000000000000000000000000000002bf60000000000000000000000000000000000000000000000000000000000002bf80000000000000000000000000000000000000000000000000000000000002bfa0000000000000000000000000000000000000000000000000000000000002bfc0000000000000000000000000000000000000000000000000000000000002bfe0000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c020000000000000000000000000000000000000000000000000000000000002c040000000000000000000000000000000000000000000000000000000000002c060000000000000000000000000000000000000000000000000000000000002c080000000000000000000000000000000000000000000000000000000000002c0a0000000000000000000000000000000000000000000000000000000000002c0c0000000000000000000000000000000000000000000000000000000000002c0e0000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c120000000000000000000000000000000000000000000000000000000000002c140000000000000000000000000000000000000000000000000000000000002c160000000000000000000000000000000000000000000000000000000000002c180000000000000000000000000000000000000000000000000000000000002c1a0000000000000000000000000000000000000000000000000000000000002c1c0000000000000000000000000000000000000000000000000000000000002c1e0000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c220000000000000000000000000000000000000000000000000000000000002c240000000000000000000000000000000000000000000000000000000000002c260000000000000000000000000000000000000000000000000000000000002c280000000000000000000000000000000000000000000000000000000000002c2a0000000000000000000000000000000000000000000000000000000000002c2c0000000000000000000000000000000000000000000000000000000000002c2e0000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c320000000000000000000000000000000000000000000000000000000000002c340000000000000000000000000000000000000000000000000000000000002c360000000000000000000000000000000000000000000000000000000000002c380000000000000000000000000000000000000000000000000000000000002c3a0000000000000000000000000000000000000000000000000000000000002c3c0000000000000000000000000000000000000000000000000000000000002c3e0000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c420000000000000000000000000000000000000000000000000000000000002c440000000000000000000000000000000000000000000000000000000000002c460000000000000000000000000000000000000000000000000000000000002c480000000000000000000000000000000000000000000000000000000000002c4a0000000000000000000000000000000000000000000000000000000000002c4c0000000000000000000000000000000000000000000000000000000000002c4e0000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c520000000000000000000000000000000000000000000000000000000000002c540000000000000000000000000000000000000000000000000000000000002c560000000000000000000000000000000000000000000000000000000000002c580000000000000000000000000000000000000000000000000000000000002c5a0000000000000000000000000000000000000000000000000000000000002c5c0000000000000000000000000000000000000000000000000000000000002c5e0000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c620000000000000000000000000000000000000000000000000000000000002c640000000000000000000000000000000000000000000000000000000000002c660000000000000000000000000000000000000000000000000000000000002c680000000000000000000000000000000000000000000000000000000000002c6a0000000000000000000000000000000000000000000000000000000000002c6c0000000000000000000000000000000000000000000000000000000000002c6e0000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c720000000000000000000000000000000000000000000000000000000000002c740000000000000000000000000000000000000000000000000000000000002c760000000000000000000000000000000000000000000000000000000000002c780000000000000000000000000000000000000000000000000000000000002c7a0000000000000000000000000000000000000000000000000000000000002c7c0000000000000000000000000000000000000000000000000000000000002c7e0000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c820000000000000000000000000000000000000000000000000000000000002c840000000000000000000000000000000000000000000000000000000000002c860000000000000000000000000000000000000000000000000000000000002c880000000000000000000000000000000000000000000000000000000000002c8a0000000000000000000000000000000000000000000000000000000000002c8c0000000000000000000000000000000000000000000000000000000000002c8e0000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002c920000000000000000000000000000000000000000000000000000000000002c940000000000000000000000000000000000000000000000000000000000002c960000000000000000000000000000000000000000000000000000000000002c980000000000000000000000000000000000000000000000000000000000002c9a0000000000000000000000000000000000000000000000000000000000002c9c0000000000000000000000000000000000000000000000000000000000002c9e0000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002ca20000000000000000000000000000000000000000000000000000000000002ca40000000000000000000000000000000000000000000000000000000000002ca60000000000000000000000000000000000000000000000000000000000002ca80000000000000000000000000000000000000000000000000000000000002caa0000000000000000000000000000000000000000000000000000000000002cac0000000000000000000000000000000000000000000000000000000000002cae0000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cb20000000000000000000000000000000000000000000000000000000000002cb40000000000000000000000000000000000000000000000000000000000002cb60000000000000000000000000000000000000000000000000000000000002cb80000000000000000000000000000000000000000000000000000000000002cba0000000000000000000000000000000000000000000000000000000000002cbc0000000000000000000000000000000000000000000000000000000000002cbe0000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cc20000000000000000000000000000000000000000000000000000000000002cc40000000000000000000000000000000000000000000000000000000000002cc60000000000000000000000000000000000000000000000000000000000002cc80000000000000000000000000000000000000000000000000000000000002cca0000000000000000000000000000000000000000000000000000000000002ccc0000000000000000000000000000000000000000000000000000000000002cce0000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002cd20000000000000000000000000000000000000000000000000000000000002cd40000000000000000000000000000000000000000000000000000000000002cd60000000000000000000000000000000000000000000000000000000000002cd80000000000000000000000000000000000000000000000000000000000002cda0000000000000000000000000000000000000000000000000000000000002cdc0000000000000000000000000000000000000000000000000000000000002cde0000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002ce20000000000000000000000000000000000000000000000000000000000002ce40000000000000000000000000000000000000000000000000000000000002ce60000000000000000000000000000000000000000000000000000000000002ce80000000000000000000000000000000000000000000000000000000000002cea0000000000000000000000000000000000000000000000000000000000002cec0000000000000000000000000000000000000000000000000000000000002cee0000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002cf20000000000000000000000000000000000000000000000000000000000002cf40000000000000000000000000000000000000000000000000000000000002cf60000000000000000000000000000000000000000000000000000000000002cf80000000000000000000000000000000000000000000000000000000000002cfa0000000000000000000000000000000000000000000000000000000000002cfc0000000000000000000000000000000000000000000000000000000000002cfe0000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d020000000000000000000000000000000000000000000000000000000000002d040000000000000000000000000000000000000000000000000000000000002d060000000000000000000000000000000000000000000000000000000000002d080000000000000000000000000000000000000000000000000000000000002d0a0000000000000000000000000000000000000000000000000000000000002d0c0000000000000000000000000000000000000000000000000000000000002d0e0000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d120000000000000000000000000000000000000000000000000000000000002d140000000000000000000000000000000000000000000000000000000000002d160000000000000000000000000000000000000000000000000000000000002d180000000000000000000000000000000000000000000000000000000000002d1a0000000000000000000000000000000000000000000000000000000000002d1c0000000000000000000000000000000000000000000000000000000000002d1e0000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d220000000000000000000000000000000000000000000000000000000000002d240000000000000000000000000000000000000000000000000000000000002d260000000000000000000000000000000000000000000000000000000000002d280000000000000000000000000000000000000000000000000000000000002d2a0000000000000000000000000000000000000000000000000000000000002d2c0000000000000000000000000000000000000000000000000000000000002d2e0000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d320000000000000000000000000000000000000000000000000000000000002d340000000000000000000000000000000000000000000000000000000000002d360000000000000000000000000000000000000000000000000000000000002d380000000000000000000000000000000000000000000000000000000000002d3a0000000000000000000000000000000000000000000000000000000000002d3c0000000000000000000000000000000000000000000000000000000000002d3e0000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d420000000000000000000000000000000000000000000000000000000000002d440000000000000000000000000000000000000000000000000000000000002d460000000000000000000000000000000000000000000000000000000000002d480000000000000000000000000000000000000000000000000000000000002d4a0000000000000000000000000000000000000000000000000000000000002d4c0000000000000000000000000000000000000000000000000000000000002d4e0000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d520000000000000000000000000000000000000000000000000000000000002d540000000000000000000000000000000000000000000000000000000000002d560000000000000000000000000000000000000000000000000000000000002d580000000000000000000000000000000000000000000000000000000000002d5a0000000000000000000000000000000000000000000000000000000000002d5c0000000000000000000000000000000000000000000000000000000000002d5e0000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d620000000000000000000000000000000000000000000000000000000000002d640000000000000000000000000000000000000000000000000000000000002d660000000000000000000000000000000000000000000000000000000000002d680000000000000000000000000000000000000000000000000000000000002d6a0000000000000000000000000000000000000000000000000000000000002d6c0000000000000000000000000000000000000000000000000000000000002d6e0000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d720000000000000000000000000000000000000000000000000000000000002d740000000000000000000000000000000000000000000000000000000000002d760000000000000000000000000000000000000000000000000000000000002d780000000000000000000000000000000000000000000000000000000000002d7a0000000000000000000000000000000000000000000000000000000000002d7c0000000000000000000000000000000000000000000000000000000000002d7e0000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d820000000000000000000000000000000000000000000000000000000000002d840000000000000000000000000000000000000000000000000000000000002d860000000000000000000000000000000000000000000000000000000000002d880000000000000000000000000000000000000000000000000000000000002d8a0000000000000000000000000000000000000000000000000000000000002d8c0000000000000000000000000000000000000000000000000000000000002d8e0000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002d920000000000000000000000000000000000000000000000000000000000002d940000000000000000000000000000000000000000000000000000000000002d960000000000000000000000000000000000000000000000000000000000002d980000000000000000000000000000000000000000000000000000000000002d9a0000000000000000000000000000000000000000000000000000000000002d9c0000000000000000000000000000000000000000000000000000000000002d9e0000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002da20000000000000000000000000000000000000000000000000000000000002da40000000000000000000000000000000000000000000000000000000000002da60000000000000000000000000000000000000000000000000000000000002da80000000000000000000000000000000000000000000000000000000000002daa0000000000000000000000000000000000000000000000000000000000002dac0000000000000000000000000000000000000000000000000000000000002dae0000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002db20000000000000000000000000000000000000000000000000000000000002db40000000000000000000000000000000000000000000000000000000000002db60000000000000000000000000000000000000000000000000000000000002db80000000000000000000000000000000000000000000000000000000000002dba0000000000000000000000000000000000000000000000000000000000002dbc0000000000000000000000000000000000000000000000000000000000002dbe0000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dc20000000000000000000000000000000000000000000000000000000000002dc40000000000000000000000000000000000000000000000000000000000002dc60000000000000000000000000000000000000000000000000000000000002dc80000000000000000000000000000000000000000000000000000000000002dca0000000000000000000000000000000000000000000000000000000000002dcc0000000000000000000000000000000000000000000000000000000000002dce0000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002dd20000000000000000000000000000000000000000000000000000000000002dd40000000000000000000000000000000000000000000000000000000000002dd60000000000000000000000000000000000000000000000000000000000002dd80000000000000000000000000000000000000000000000000000000000002dda0000000000000000000000000000000000000000000000000000000000002ddc0000000000000000000000000000000000000000000000000000000000002dde0000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002de20000000000000000000000000000000000000000000000000000000000002de40000000000000000000000000000000000000000000000000000000000002de60000000000000000000000000000000000000000000000000000000000002de80000000000000000000000000000000000000000000000000000000000002dea0000000000000000000000000000000000000000000000000000000000002dec0000000000000000000000000000000000000000000000000000000000002dee0000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002df20000000000000000000000000000000000000000000000000000000000002df40000000000000000000000000000000000000000000000000000000000002df60000000000000000000000000000000000000000000000000000000000002df80000000000000000000000000000000000000000000000000000000000002dfa0000000000000000000000000000000000000000000000000000000000002dfc0000000000000000000000000000000000000000000000000000000000002dfe0000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e020000000000000000000000000000000000000000000000000000000000002e040000000000000000000000000000000000000000000000000000000000002e060000000000000000000000000000000000000000000000000000000000002e080000000000000000000000000000000000000000000000000000000000002e0a0000000000000000000000000000000000000000000000000000000000002e0c0000000000000000000000000000000000000000000000000000000000002e0e0000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e120000000000000000000000000000000000000000000000000000000000002e140000000000000000000000000000000000000000000000000000000000002e160000000000000000000000000000000000000000000000000000000000002e180000000000000000000000000000000000000000000000000000000000002e1a0000000000000000000000000000000000000000000000000000000000002e1c0000000000000000000000000000000000000000000000000000000000002e1e0000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e220000000000000000000000000000000000000000000000000000000000002e240000000000000000000000000000000000000000000000000000000000002e260000000000000000000000000000000000000000000000000000000000002e280000000000000000000000000000000000000000000000000000000000002e2a0000000000000000000000000000000000000000000000000000000000002e2c0000000000000000000000000000000000000000000000000000000000002e2e0000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e320000000000000000000000000000000000000000000000000000000000002e340000000000000000000000000000000000000000000000000000000000002e360000000000000000000000000000000000000000000000000000000000002e380000000000000000000000000000000000000000000000000000000000002e3a0000000000000000000000000000000000000000000000000000000000002e3c0000000000000000000000000000000000000000000000000000000000002e3e0000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e420000000000000000000000000000000000000000000000000000000000002e440000000000000000000000000000000000000000000000000000000000002e460000000000000000000000000000000000000000000000000000000000002e480000000000000000000000000000000000000000000000000000000000002e4a0000000000000000000000000000000000000000000000000000000000002e4c0000000000000000000000000000000000000000000000000000000000002e4e0000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e520000000000000000000000000000000000000000000000000000000000002e540000000000000000000000000000000000000000000000000000000000002e560000000000000000000000000000000000000000000000000000000000002e580000000000000000000000000000000000000000000000000000000000002e5a0000000000000000000000000000000000000000000000000000000000002e5c0000000000000000000000000000000000000000000000000000000000002e5e0000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e620000000000000000000000000000000000000000000000000000000000002e640000000000000000000000000000000000000000000000000000000000002e660000000000000000000000000000000000000000000000000000000000002e680000000000000000000000000000000000000000000000000000000000002e6a0000000000000000000000000000000000000000000000000000000000002e6c0000000000000000000000000000000000000000000000000000000000002e6e0000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e720000000000000000000000000000000000000000000000000000000000002e740000000000000000000000000000000000000000000000000000000000002e760000000000000000000000000000000000000000000000000000000000002e780000000000000000000000000000000000000000000000000000000000002e7a0000000000000000000000000000000000000000000000000000000000002e7c0000000000000000000000000000000000000000000000000000000000002e7e0000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e820000000000000000000000000000000000000000000000000000000000002e840000000000000000000000000000000000000000000000000000000000002e860000000000000000000000000000000000000000000000000000000000002e880000000000000000000000000000000000000000000000000000000000002e8a0000000000000000000000000000000000000000000000000000000000002e8c0000000000000000000000000000000000000000000000000000000000002e8e0000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002e920000000000000000000000000000000000000000000000000000000000002e940000000000000000000000000000000000000000000000000000000000002e960000000000000000000000000000000000000000000000000000000000002e980000000000000000000000000000000000000000000000000000000000002e9a0000000000000000000000000000000000000000000000000000000000002e9c0000000000000000000000000000000000000000000000000000000000002e9e0000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002ea20000000000000000000000000000000000000000000000000000000000002ea40000000000000000000000000000000000000000000000000000000000002ea60000000000000000000000000000000000000000000000000000000000002ea80000000000000000000000000000000000000000000000000000000000002eaa0000000000000000000000000000000000000000000000000000000000002eac0000000000000000000000000000000000000000000000000000000000002eae0000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002eb20000000000000000000000000000000000000000000000000000000000002eb40000000000000000000000000000000000000000000000000000000000002eb60000000000000000000000000000000000000000000000000000000000002eb80000000000000000000000000000000000000000000000000000000000002eba0000000000000000000000000000000000000000000000000000000000002ebc0000000000000000000000000000000000000000000000000000000000002ebe0000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ec20000000000000000000000000000000000000000000000000000000000002ec40000000000000000000000000000000000000000000000000000000000002ec60000000000000000000000000000000000000000000000000000000000002ec80000000000000000000000000000000000000000000000000000000000002eca0000000000000000000000000000000000000000000000000000000000002ecc0000000000000000000000000000000000000000000000000000000000002ece0000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ed20000000000000000000000000000000000000000000000000000000000002ed40000000000000000000000000000000000000000000000000000000000002ed60000000000000000000000000000000000000000000000000000000000002ed80000000000000000000000000000000000000000000000000000000000002eda0000000000000000000000000000000000000000000000000000000000002edc0000000000000000000000000000000000000000000000000000000000002ede0000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ee20000000000000000000000000000000000000000000000000000000000002ee40000000000000000000000000000000000000000000000000000000000002ee60000000000000000000000000000000000000000000000000000000000002ee80000000000000000000000000000000000000000000000000000000000002eea0000000000000000000000000000000000000000000000000000000000002eec0000000000000000000000000000000000000000000000000000000000002eee0000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002ef20000000000000000000000000000000000000000000000000000000000002ef40000000000000000000000000000000000000000000000000000000000002ef60000000000000000000000000000000000000000000000000000000000002ef80000000000000000000000000000000000000000000000000000000000002efa0000000000000000000000000000000000000000000000000000000000002efc0000000000000000000000000000000000000000000000000000000000002efe0000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f020000000000000000000000000000000000000000000000000000000000002f040000000000000000000000000000000000000000000000000000000000002f060000000000000000000000000000000000000000000000000000000000002f080000000000000000000000000000000000000000000000000000000000002f0a0000000000000000000000000000000000000000000000000000000000002f0c0000000000000000000000000000000000000000000000000000000000002f0e0000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f120000000000000000000000000000000000000000000000000000000000002f140000000000000000000000000000000000000000000000000000000000002f160000000000000000000000000000000000000000000000000000000000002f180000000000000000000000000000000000000000000000000000000000002f1a0000000000000000000000000000000000000000000000000000000000002f1c0000000000000000000000000000000000000000000000000000000000002f1e0000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f220000000000000000000000000000000000000000000000000000000000002f240000000000000000000000000000000000000000000000000000000000002f260000000000000000000000000000000000000000000000000000000000002f280000000000000000000000000000000000000000000000000000000000002f2a0000000000000000000000000000000000000000000000000000000000002f2c0000000000000000000000000000000000000000000000000000000000002f2e0000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f320000000000000000000000000000000000000000000000000000000000002f340000000000000000000000000000000000000000000000000000000000002f360000000000000000000000000000000000000000000000000000000000002f380000000000000000000000000000000000000000000000000000000000002f3a0000000000000000000000000000000000000000000000000000000000002f3c0000000000000000000000000000000000000000000000000000000000002f3e0000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f420000000000000000000000000000000000000000000000000000000000002f440000000000000000000000000000000000000000000000000000000000002f460000000000000000000000000000000000000000000000000000000000002f480000000000000000000000000000000000000000000000000000000000002f4a0000000000000000000000000000000000000000000000000000000000002f4c0000000000000000000000000000000000000000000000000000000000002f4e0000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f520000000000000000000000000000000000000000000000000000000000002f540000000000000000000000000000000000000000000000000000000000002f560000000000000000000000000000000000000000000000000000000000002f580000000000000000000000000000000000000000000000000000000000002f5a0000000000000000000000000000000000000000000000000000000000002f5c0000000000000000000000000000000000000000000000000000000000002f5e0000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f620000000000000000000000000000000000000000000000000000000000002f640000000000000000000000000000000000000000000000000000000000002f660000000000000000000000000000000000000000000000000000000000002f680000000000000000000000000000000000000000000000000000000000002f6a0000000000000000000000000000000000000000000000000000000000002f6c0000000000000000000000000000000000000000000000000000000000002f6e0000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f720000000000000000000000000000000000000000000000000000000000002f740000000000000000000000000000000000000000000000000000000000002f760000000000000000000000000000000000000000000000000000000000002f780000000000000000000000000000000000000000000000000000000000002f7a0000000000000000000000000000000000000000000000000000000000002f7c0000000000000000000000000000000000000000000000000000000000002f7e0000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f820000000000000000000000000000000000000000000000000000000000002f840000000000000000000000000000000000000000000000000000000000002f860000000000000000000000000000000000000000000000000000000000002f880000000000000000000000000000000000000000000000000000000000002f8a0000000000000000000000000000000000000000000000000000000000002f8c0000000000000000000000000000000000000000000000000000000000002f8e0000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002f920000000000000000000000000000000000000000000000000000000000002f940000000000000000000000000000000000000000000000000000000000002f960000000000000000000000000000000000000000000000000000000000002f980000000000000000000000000000000000000000000000000000000000002f9a0000000000000000000000000000000000000000000000000000000000002f9c0000000000000000000000000000000000000000000000000000000000002f9e0000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fa20000000000000000000000000000000000000000000000000000000000002fa40000000000000000000000000000000000000000000000000000000000002fa60000000000000000000000000000000000000000000000000000000000002fa80000000000000000000000000000000000000000000000000000000000002faa0000000000000000000000000000000000000000000000000000000000002fac0000000000000000000000000000000000000000000000000000000000002fae0000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fb20000000000000000000000000000000000000000000000000000000000002fb40000000000000000000000000000000000000000000000000000000000002fb60000000000000000000000000000000000000000000000000000000000002fb80000000000000000000000000000000000000000000000000000000000002fba0000000000000000000000000000000000000000000000000000000000002fbc0000000000000000000000000000000000000000000000000000000000002fbe0000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fc20000000000000000000000000000000000000000000000000000000000002fc40000000000000000000000000000000000000000000000000000000000002fc60000000000000000000000000000000000000000000000000000000000002fc80000000000000000000000000000000000000000000000000000000000002fca0000000000000000000000000000000000000000000000000000000000002fcc0000000000000000000000000000000000000000000000000000000000002fce0000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fd20000000000000000000000000000000000000000000000000000000000002fd40000000000000000000000000000000000000000000000000000000000002fd60000000000000000000000000000000000000000000000000000000000002fd80000000000000000000000000000000000000000000000000000000000002fda0000000000000000000000000000000000000000000000000000000000002fdc0000000000000000000000000000000000000000000000000000000000002fde0000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002fe20000000000000000000000000000000000000000000000000000000000002fe40000000000000000000000000000000000000000000000000000000000002fe60000000000000000000000000000000000000000000000000000000000002fe80000000000000000000000000000000000000000000000000000000000002fea0000000000000000000000000000000000000000000000000000000000002fec0000000000000000000000000000000000000000000000000000000000002fee0000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000002ff20000000000000000000000000000000000000000000000000000000000002ff40000000000000000000000000000000000000000000000000000000000002ff60000000000000000000000000000000000000000000000000000000000002ff80000000000000000000000000000000000000000000000000000000000002ffa0000000000000000000000000000000000000000000000000000000000002ffc0000000000000000000000000000000000000000000000000000000000002ffe00000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003002000000000000000000000000000000000000000000000000000000000000300400000000000000000000000000000000000000000000000000000000000030060000000000000000000000000000000000000000000000000000000000003008000000000000000000000000000000000000000000000000000000000000300a000000000000000000000000000000000000000000000000000000000000300c000000000000000000000000000000000000000000000000000000000000300e00000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003012000000000000000000000000000000000000000000000000000000000000301400000000000000000000000000000000000000000000000000000000000030160000000000000000000000000000000000000000000000000000000000003018000000000000000000000000000000000000000000000000000000000000301a000000000000000000000000000000000000000000000000000000000000301c000000000000000000000000000000000000000000000000000000000000301e00000000000000000000000000000000000000000000000000000000000030200000000000000000000000000000000000000000000000000000000000003022000000000000000000000000000000000000000000000000000000000000302400000000000000000000000000000000000000000000000000000000000030260000000000000000000000000000000000000000000000000000000000003028000000000000000000000000000000000000000000000000000000000000302a000000000000000000000000000000000000000000000000000000000000302c000000000000000000000000000000000000000000000000000000000000302e00000000000000000000000000000000000000000000000000000000000030300000000000000000000000000000000000000000000000000000000000003032000000000000000000000000000000000000000000000000000000000000303400000000000000000000000000000000000000000000000000000000000030360000000000000000000000000000000000000000000000000000000000003038000000000000000000000000000000000000000000000000000000000000303a000000000000000000000000000000000000000000000000000000000000303c000000000000000000000000000000000000000000000000000000000000303e00000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003042000000000000000000000000000000000000000000000000000000000000304400000000000000000000000000000000000000000000000000000000000030460000000000000000000000000000000000000000000000000000000000003048000000000000000000000000000000000000000000000000000000000000304a000000000000000000000000000000000000000000000000000000000000304c000000000000000000000000000000000000000000000000000000000000304e00000000000000000000000000000000000000000000000000000000000030500000000000000000000000000000000000000000000000000000000000003052000000000000000000000000000000000000000000000000000000000000305400000000000000000000000000000000000000000000000000000000000030560000000000000000000000000000000000000000000000000000000000003058000000000000000000000000000000000000000000000000000000000000305a000000000000000000000000000000000000000000000000000000000000305c000000000000000000000000000000000000000000000000000000000000305e00000000000000000000000000000000000000000000000000000000000030600000000000000000000000000000000000000000000000000000000000003062000000000000000000000000000000000000000000000000000000000000306400000000000000000000000000000000000000000000000000000000000030660000000000000000000000000000000000000000000000000000000000003068000000000000000000000000000000000000000000000000000000000000306a000000000000000000000000000000000000000000000000000000000000306c000000000000000000000000000000000000000000000000000000000000306e00000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003072000000000000000000000000000000000000000000000000000000000000307400000000000000000000000000000000000000000000000000000000000030760000000000000000000000000000000000000000000000000000000000003078000000000000000000000000000000000000000000000000000000000000307a000000000000000000000000000000000000000000000000000000000000307c000000000000000000000000000000000000000000000000000000000000307e00000000000000000000000000000000000000000000000000000000000030800000000000000000000000000000000000000000000000000000000000003082000000000000000000000000000000000000000000000000000000000000308400000000000000000000000000000000000000000000000000000000000030860000000000000000000000000000000000000000000000000000000000003088000000000000000000000000000000000000000000000000000000000000308a000000000000000000000000000000000000000000000000000000000000308c000000000000000000000000000000000000000000000000000000000000308e00000000000000000000000000000000000000000000000000000000000030900000000000000000000000000000000000000000000000000000000000003092000000000000000000000000000000000000000000000000000000000000309400000000000000000000000000000000000000000000000000000000000030960000000000000000000000000000000000000000000000000000000000003098000000000000000000000000000000000000000000000000000000000000309a000000000000000000000000000000000000000000000000000000000000309c000000000000000000000000000000000000000000000000000000000000309e00000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030a200000000000000000000000000000000000000000000000000000000000030a400000000000000000000000000000000000000000000000000000000000030a600000000000000000000000000000000000000000000000000000000000030a800000000000000000000000000000000000000000000000000000000000030aa00000000000000000000000000000000000000000000000000000000000030ac00000000000000000000000000000000000000000000000000000000000030ae00000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030b200000000000000000000000000000000000000000000000000000000000030b400000000000000000000000000000000000000000000000000000000000030b600000000000000000000000000000000000000000000000000000000000030b800000000000000000000000000000000000000000000000000000000000030ba00000000000000000000000000000000000000000000000000000000000030bc00000000000000000000000000000000000000000000000000000000000030be00000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030c200000000000000000000000000000000000000000000000000000000000030c400000000000000000000000000000000000000000000000000000000000030c600000000000000000000000000000000000000000000000000000000000030c800000000000000000000000000000000000000000000000000000000000030ca00000000000000000000000000000000000000000000000000000000000030cc00000000000000000000000000000000000000000000000000000000000030ce00000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030d200000000000000000000000000000000000000000000000000000000000030d400000000000000000000000000000000000000000000000000000000000030d600000000000000000000000000000000000000000000000000000000000030d800000000000000000000000000000000000000000000000000000000000030da00000000000000000000000000000000000000000000000000000000000030dc00000000000000000000000000000000000000000000000000000000000030de00000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030e200000000000000000000000000000000000000000000000000000000000030e400000000000000000000000000000000000000000000000000000000000030e600000000000000000000000000000000000000000000000000000000000030e800000000000000000000000000000000000000000000000000000000000030ea00000000000000000000000000000000000000000000000000000000000030ec00000000000000000000000000000000000000000000000000000000000030ee00000000000000000000000000000000000000000000000000000000000030f000000000000000000000000000000000000000000000000000000000000030f200000000000000000000000000000000000000000000000000000000000030f400000000000000000000000000000000000000000000000000000000000030f600000000000000000000000000000000000000000000000000000000000030f800000000000000000000000000000000000000000000000000000000000030fa00000000000000000000000000000000000000000000000000000000000030fc00000000000000000000000000000000000000000000000000000000000030fe00000000000000000000000000000000000000000000000000000000000031000000000000000000000000000000000000000000000000000000000000003102000000000000000000000000000000000000000000000000000000000000310400000000000000000000000000000000000000000000000000000000000031060000000000000000000000000000000000000000000000000000000000003108000000000000000000000000000000000000000000000000000000000000310a000000000000000000000000000000000000000000000000000000000000310c000000000000000000000000000000000000000000000000000000000000310e00000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003112000000000000000000000000000000000000000000000000000000000000311400000000000000000000000000000000000000000000000000000000000031160000000000000000000000000000000000000000000000000000000000003118000000000000000000000000000000000000000000000000000000000000311a000000000000000000000000000000000000000000000000000000000000311c000000000000000000000000000000000000000000000000000000000000311e00000000000000000000000000000000000000000000000000000000000031200000000000000000000000000000000000000000000000000000000000003122000000000000000000000000000000000000000000000000000000000000312400000000000000000000000000000000000000000000000000000000000031260000000000000000000000000000000000000000000000000000000000003128000000000000000000000000000000000000000000000000000000000000312a000000000000000000000000000000000000000000000000000000000000312c000000000000000000000000000000000000000000000000000000000000312e00000000000000000000000000000000000000000000000000000000000031300000000000000000000000000000000000000000000000000000000000003132000000000000000000000000000000000000000000000000000000000000313400000000000000000000000000000000000000000000000000000000000031360000000000000000000000000000000000000000000000000000000000003138000000000000000000000000000000000000000000000000000000000000313a000000000000000000000000000000000000000000000000000000000000313c000000000000000000000000000000000000000000000000000000000000313e00000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003142000000000000000000000000000000000000000000000000000000000000314400000000000000000000000000000000000000000000000000000000000031460000000000000000000000000000000000000000000000000000000000003148000000000000000000000000000000000000000000000000000000000000314a000000000000000000000000000000000000000000000000000000000000314c000000000000000000000000000000000000000000000000000000000000314e00000000000000000000000000000000000000000000000000000000000031500000000000000000000000000000000000000000000000000000000000003152000000000000000000000000000000000000000000000000000000000000315400000000000000000000000000000000000000000000000000000000000031560000000000000000000000000000000000000000000000000000000000003158000000000000000000000000000000000000000000000000000000000000315a000000000000000000000000000000000000000000000000000000000000315c000000000000000000000000000000000000000000000000000000000000315e00000000000000000000000000000000000000000000000000000000000031600000000000000000000000000000000000000000000000000000000000003162000000000000000000000000000000000000000000000000000000000000316400000000000000000000000000000000000000000000000000000000000031660000000000000000000000000000000000000000000000000000000000003168000000000000000000000000000000000000000000000000000000000000316a000000000000000000000000000000000000000000000000000000000000316c000000000000000000000000000000000000000000000000000000000000316e00000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003172000000000000000000000000000000000000000000000000000000000000317400000000000000000000000000000000000000000000000000000000000031760000000000000000000000000000000000000000000000000000000000003178000000000000000000000000000000000000000000000000000000000000317a000000000000000000000000000000000000000000000000000000000000317c000000000000000000000000000000000000000000000000000000000000317e00000000000000000000000000000000000000000000000000000000000031800000000000000000000000000000000000000000000000000000000000003182000000000000000000000000000000000000000000000000000000000000318400000000000000000000000000000000000000000000000000000000000031860000000000000000000000000000000000000000000000000000000000003188000000000000000000000000000000000000000000000000000000000000318a000000000000000000000000000000000000000000000000000000000000318c000000000000000000000000000000000000000000000000000000000000318e00000000000000000000000000000000000000000000000000000000000031900000000000000000000000000000000000000000000000000000000000003192000000000000000000000000000000000000000000000000000000000000319400000000000000000000000000000000000000000000000000000000000031960000000000000000000000000000000000000000000000000000000000003198000000000000000000000000000000000000000000000000000000000000319a000000000000000000000000000000000000000000000000000000000000319c000000000000000000000000000000000000000000000000000000000000319e00000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031a200000000000000000000000000000000000000000000000000000000000031a400000000000000000000000000000000000000000000000000000000000031a600000000000000000000000000000000000000000000000000000000000031a800000000000000000000000000000000000000000000000000000000000031aa00000000000000000000000000000000000000000000000000000000000031ac00000000000000000000000000000000000000000000000000000000000031ae00000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031b200000000000000000000000000000000000000000000000000000000000031b400000000000000000000000000000000000000000000000000000000000031b600000000000000000000000000000000000000000000000000000000000031b800000000000000000000000000000000000000000000000000000000000031ba00000000000000000000000000000000000000000000000000000000000031bc00000000000000000000000000000000000000000000000000000000000031be00000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031c200000000000000000000000000000000000000000000000000000000000031c400000000000000000000000000000000000000000000000000000000000031c600000000000000000000000000000000000000000000000000000000000031c800000000000000000000000000000000000000000000000000000000000031ca00000000000000000000000000000000000000000000000000000000000031cc00000000000000000000000000000000000000000000000000000000000031ce00000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031d200000000000000000000000000000000000000000000000000000000000031d400000000000000000000000000000000000000000000000000000000000031d600000000000000000000000000000000000000000000000000000000000031d800000000000000000000000000000000000000000000000000000000000031da00000000000000000000000000000000000000000000000000000000000031dc00000000000000000000000000000000000000000000000000000000000031de00000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031e200000000000000000000000000000000000000000000000000000000000031e400000000000000000000000000000000000000000000000000000000000031e600000000000000000000000000000000000000000000000000000000000031e800000000000000000000000000000000000000000000000000000000000031ea00000000000000000000000000000000000000000000000000000000000031ec00000000000000000000000000000000000000000000000000000000000031ee00000000000000000000000000000000000000000000000000000000000031f000000000000000000000000000000000000000000000000000000000000031f200000000000000000000000000000000000000000000000000000000000031f400000000000000000000000000000000000000000000000000000000000031f600000000000000000000000000000000000000000000000000000000000031f800000000000000000000000000000000000000000000000000000000000031fa00000000000000000000000000000000000000000000000000000000000031fc00000000000000000000000000000000000000000000000000000000000031fe00000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003202000000000000000000000000000000000000000000000000000000000000320400000000000000000000000000000000000000000000000000000000000032060000000000000000000000000000000000000000000000000000000000003208000000000000000000000000000000000000000000000000000000000000320a000000000000000000000000000000000000000000000000000000000000320c000000000000000000000000000000000000000000000000000000000000320e00000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003212000000000000000000000000000000000000000000000000000000000000321400000000000000000000000000000000000000000000000000000000000032160000000000000000000000000000000000000000000000000000000000003218000000000000000000000000000000000000000000000000000000000000321a000000000000000000000000000000000000000000000000000000000000321c000000000000000000000000000000000000000000000000000000000000321e00000000000000000000000000000000000000000000000000000000000032200000000000000000000000000000000000000000000000000000000000003222000000000000000000000000000000000000000000000000000000000000322400000000000000000000000000000000000000000000000000000000000032260000000000000000000000000000000000000000000000000000000000003228000000000000000000000000000000000000000000000000000000000000322a000000000000000000000000000000000000000000000000000000000000322c000000000000000000000000000000000000000000000000000000000000322e00000000000000000000000000000000000000000000000000000000000032300000000000000000000000000000000000000000000000000000000000003232000000000000000000000000000000000000000000000000000000000000323400000000000000000000000000000000000000000000000000000000000032360000000000000000000000000000000000000000000000000000000000003238000000000000000000000000000000000000000000000000000000000000323a000000000000000000000000000000000000000000000000000000000000323c000000000000000000000000000000000000000000000000000000000000323e00000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003242000000000000000000000000000000000000000000000000000000000000324400000000000000000000000000000000000000000000000000000000000032460000000000000000000000000000000000000000000000000000000000003248000000000000000000000000000000000000000000000000000000000000324a000000000000000000000000000000000000000000000000000000000000324c000000000000000000000000000000000000000000000000000000000000324e00000000000000000000000000000000000000000000000000000000000032500000000000000000000000000000000000000000000000000000000000003252000000000000000000000000000000000000000000000000000000000000325400000000000000000000000000000000000000000000000000000000000032560000000000000000000000000000000000000000000000000000000000003258000000000000000000000000000000000000000000000000000000000000325a000000000000000000000000000000000000000000000000000000000000325c000000000000000000000000000000000000000000000000000000000000325e00000000000000000000000000000000000000000000000000000000000032600000000000000000000000000000000000000000000000000000000000003262000000000000000000000000000000000000000000000000000000000000326400000000000000000000000000000000000000000000000000000000000032660000000000000000000000000000000000000000000000000000000000003268000000000000000000000000000000000000000000000000000000000000326a000000000000000000000000000000000000000000000000000000000000326c000000000000000000000000000000000000000000000000000000000000326e00000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003272000000000000000000000000000000000000000000000000000000000000327400000000000000000000000000000000000000000000000000000000000032760000000000000000000000000000000000000000000000000000000000003278000000000000000000000000000000000000000000000000000000000000327a000000000000000000000000000000000000000000000000000000000000327c000000000000000000000000000000000000000000000000000000000000327e00000000000000000000000000000000000000000000000000000000000032800000000000000000000000000000000000000000000000000000000000003282000000000000000000000000000000000000000000000000000000000000328400000000000000000000000000000000000000000000000000000000000032860000000000000000000000000000000000000000000000000000000000003288000000000000000000000000000000000000000000000000000000000000328a000000000000000000000000000000000000000000000000000000000000328c000000000000000000000000000000000000000000000000000000000000328e00000000000000000000000000000000000000000000000000000000000032900000000000000000000000000000000000000000000000000000000000003292000000000000000000000000000000000000000000000000000000000000329400000000000000000000000000000000000000000000000000000000000032960000000000000000000000000000000000000000000000000000000000003298000000000000000000000000000000000000000000000000000000000000329a000000000000000000000000000000000000000000000000000000000000329c000000000000000000000000000000000000000000000000000000000000329e00000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032a200000000000000000000000000000000000000000000000000000000000032a400000000000000000000000000000000000000000000000000000000000032a600000000000000000000000000000000000000000000000000000000000032a800000000000000000000000000000000000000000000000000000000000032aa00000000000000000000000000000000000000000000000000000000000032ac00000000000000000000000000000000000000000000000000000000000032ae00000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032b200000000000000000000000000000000000000000000000000000000000032b400000000000000000000000000000000000000000000000000000000000032b600000000000000000000000000000000000000000000000000000000000032b800000000000000000000000000000000000000000000000000000000000032ba00000000000000000000000000000000000000000000000000000000000032bc00000000000000000000000000000000000000000000000000000000000032be00000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032c200000000000000000000000000000000000000000000000000000000000032c400000000000000000000000000000000000000000000000000000000000032c600000000000000000000000000000000000000000000000000000000000032c800000000000000000000000000000000000000000000000000000000000032ca00000000000000000000000000000000000000000000000000000000000032cc00000000000000000000000000000000000000000000000000000000000032ce00000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032d200000000000000000000000000000000000000000000000000000000000032d400000000000000000000000000000000000000000000000000000000000032d600000000000000000000000000000000000000000000000000000000000032d800000000000000000000000000000000000000000000000000000000000032da00000000000000000000000000000000000000000000000000000000000032dc00000000000000000000000000000000000000000000000000000000000032de00000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032e200000000000000000000000000000000000000000000000000000000000032e400000000000000000000000000000000000000000000000000000000000032e600000000000000000000000000000000000000000000000000000000000032e800000000000000000000000000000000000000000000000000000000000032ea00000000000000000000000000000000000000000000000000000000000032ec00000000000000000000000000000000000000000000000000000000000032ee00000000000000000000000000000000000000000000000000000000000032f000000000000000000000000000000000000000000000000000000000000032f200000000000000000000000000000000000000000000000000000000000032f400000000000000000000000000000000000000000000000000000000000032f600000000000000000000000000000000000000000000000000000000000032f800000000000000000000000000000000000000000000000000000000000032fa00000000000000000000000000000000000000000000000000000000000032fc00000000000000000000000000000000000000000000000000000000000032fe00000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003302000000000000000000000000000000000000000000000000000000000000330400000000000000000000000000000000000000000000000000000000000033060000000000000000000000000000000000000000000000000000000000003308000000000000000000000000000000000000000000000000000000000000330a000000000000000000000000000000000000000000000000000000000000330c000000000000000000000000000000000000000000000000000000000000330e00000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003312000000000000000000000000000000000000000000000000000000000000331400000000000000000000000000000000000000000000000000000000000033160000000000000000000000000000000000000000000000000000000000003318000000000000000000000000000000000000000000000000000000000000331a000000000000000000000000000000000000000000000000000000000000331c000000000000000000000000000000000000000000000000000000000000331e00000000000000000000000000000000000000000000000000000000000033200000000000000000000000000000000000000000000000000000000000003322000000000000000000000000000000000000000000000000000000000000332400000000000000000000000000000000000000000000000000000000000033260000000000000000000000000000000000000000000000000000000000003328000000000000000000000000000000000000000000000000000000000000332a000000000000000000000000000000000000000000000000000000000000332c000000000000000000000000000000000000000000000000000000000000332e00000000000000000000000000000000000000000000000000000000000033300000000000000000000000000000000000000000000000000000000000003332000000000000000000000000000000000000000000000000000000000000333400000000000000000000000000000000000000000000000000000000000033360000000000000000000000000000000000000000000000000000000000003338000000000000000000000000000000000000000000000000000000000000333a000000000000000000000000000000000000000000000000000000000000333c000000000000000000000000000000000000000000000000000000000000333e00000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003342000000000000000000000000000000000000000000000000000000000000334400000000000000000000000000000000000000000000000000000000000033460000000000000000000000000000000000000000000000000000000000003348000000000000000000000000000000000000000000000000000000000000334a000000000000000000000000000000000000000000000000000000000000334c000000000000000000000000000000000000000000000000000000000000334e00000000000000000000000000000000000000000000000000000000000033500000000000000000000000000000000000000000000000000000000000003352000000000000000000000000000000000000000000000000000000000000335400000000000000000000000000000000000000000000000000000000000033560000000000000000000000000000000000000000000000000000000000003358000000000000000000000000000000000000000000000000000000000000335a000000000000000000000000000000000000000000000000000000000000335c000000000000000000000000000000000000000000000000000000000000335e00000000000000000000000000000000000000000000000000000000000033600000000000000000000000000000000000000000000000000000000000003362000000000000000000000000000000000000000000000000000000000000336400000000000000000000000000000000000000000000000000000000000033660000000000000000000000000000000000000000000000000000000000003368000000000000000000000000000000000000000000000000000000000000336a000000000000000000000000000000000000000000000000000000000000336c000000000000000000000000000000000000000000000000000000000000336e00000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003372000000000000000000000000000000000000000000000000000000000000337400000000000000000000000000000000000000000000000000000000000033760000000000000000000000000000000000000000000000000000000000003378000000000000000000000000000000000000000000000000000000000000337a000000000000000000000000000000000000000000000000000000000000337c000000000000000000000000000000000000000000000000000000000000337e00000000000000000000000000000000000000000000000000000000000033800000000000000000000000000000000000000000000000000000000000003382000000000000000000000000000000000000000000000000000000000000338400000000000000000000000000000000000000000000000000000000000033860000000000000000000000000000000000000000000000000000000000003388000000000000000000000000000000000000000000000000000000000000338a000000000000000000000000000000000000000000000000000000000000338c000000000000000000000000000000000000000000000000000000000000338e00000000000000000000000000000000000000000000000000000000000033900000000000000000000000000000000000000000000000000000000000003392000000000000000000000000000000000000000000000000000000000000339400000000000000000000000000000000000000000000000000000000000033960000000000000000000000000000000000000000000000000000000000003398000000000000000000000000000000000000000000000000000000000000339a000000000000000000000000000000000000000000000000000000000000339c000000000000000000000000000000000000000000000000000000000000339e00000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033a200000000000000000000000000000000000000000000000000000000000033a400000000000000000000000000000000000000000000000000000000000033a600000000000000000000000000000000000000000000000000000000000033a800000000000000000000000000000000000000000000000000000000000033aa00000000000000000000000000000000000000000000000000000000000033ac00000000000000000000000000000000000000000000000000000000000033ae00000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033b200000000000000000000000000000000000000000000000000000000000033b400000000000000000000000000000000000000000000000000000000000033b600000000000000000000000000000000000000000000000000000000000033b800000000000000000000000000000000000000000000000000000000000033ba00000000000000000000000000000000000000000000000000000000000033bc00000000000000000000000000000000000000000000000000000000000033be00000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033c200000000000000000000000000000000000000000000000000000000000033c400000000000000000000000000000000000000000000000000000000000033c600000000000000000000000000000000000000000000000000000000000033c800000000000000000000000000000000000000000000000000000000000033ca00000000000000000000000000000000000000000000000000000000000033cc00000000000000000000000000000000000000000000000000000000000033ce00000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033d200000000000000000000000000000000000000000000000000000000000033d400000000000000000000000000000000000000000000000000000000000033d600000000000000000000000000000000000000000000000000000000000033d800000000000000000000000000000000000000000000000000000000000033da00000000000000000000000000000000000000000000000000000000000033dc00000000000000000000000000000000000000000000000000000000000033de00000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033e200000000000000000000000000000000000000000000000000000000000033e400000000000000000000000000000000000000000000000000000000000033e600000000000000000000000000000000000000000000000000000000000033e800000000000000000000000000000000000000000000000000000000000033ea00000000000000000000000000000000000000000000000000000000000033ec00000000000000000000000000000000000000000000000000000000000033ee00000000000000000000000000000000000000000000000000000000000033f000000000000000000000000000000000000000000000000000000000000033f200000000000000000000000000000000000000000000000000000000000033f400000000000000000000000000000000000000000000000000000000000033f600000000000000000000000000000000000000000000000000000000000033f800000000000000000000000000000000000000000000000000000000000033fa00000000000000000000000000000000000000000000000000000000000033fc00000000000000000000000000000000000000000000000000000000000033fe00000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003402000000000000000000000000000000000000000000000000000000000000340400000000000000000000000000000000000000000000000000000000000034060000000000000000000000000000000000000000000000000000000000003408000000000000000000000000000000000000000000000000000000000000340a000000000000000000000000000000000000000000000000000000000000340c000000000000000000000000000000000000000000000000000000000000340e00000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003412000000000000000000000000000000000000000000000000000000000000341400000000000000000000000000000000000000000000000000000000000034160000000000000000000000000000000000000000000000000000000000003418000000000000000000000000000000000000000000000000000000000000341a000000000000000000000000000000000000000000000000000000000000341c000000000000000000000000000000000000000000000000000000000000341e00000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000003422000000000000000000000000000000000000000000000000000000000000342400000000000000000000000000000000000000000000000000000000000034260000000000000000000000000000000000000000000000000000000000003428000000000000000000000000000000000000000000000000000000000000342a000000000000000000000000000000000000000000000000000000000000342c000000000000000000000000000000000000000000000000000000000000342e00000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000003432000000000000000000000000000000000000000000000000000000000000343400000000000000000000000000000000000000000000000000000000000034360000000000000000000000000000000000000000000000000000000000003438000000000000000000000000000000000000000000000000000000000000343a000000000000000000000000000000000000000000000000000000000000343c000000000000000000000000000000000000000000000000000000000000343e00000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003442000000000000000000000000000000000000000000000000000000000000344400000000000000000000000000000000000000000000000000000000000034460000000000000000000000000000000000000000000000000000000000003448000000000000000000000000000000000000000000000000000000000000344a000000000000000000000000000000000000000000000000000000000000344c000000000000000000000000000000000000000000000000000000000000344e00000000000000000000000000000000000000000000000000000000000034500000000000000000000000000000000000000000000000000000000000003452000000000000000000000000000000000000000000000000000000000000345400000000000000000000000000000000000000000000000000000000000034560000000000000000000000000000000000000000000000000000000000003458000000000000000000000000000000000000000000000000000000000000345a000000000000000000000000000000000000000000000000000000000000345c000000000000000000000000000000000000000000000000000000000000345e00000000000000000000000000000000000000000000000000000000000034600000000000000000000000000000000000000000000000000000000000003462000000000000000000000000000000000000000000000000000000000000346400000000000000000000000000000000000000000000000000000000000034660000000000000000000000000000000000000000000000000000000000003468000000000000000000000000000000000000000000000000000000000000346a000000000000000000000000000000000000000000000000000000000000346c000000000000000000000000000000000000000000000000000000000000346e00000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003472000000000000000000000000000000000000000000000000000000000000347400000000000000000000000000000000000000000000000000000000000034760000000000000000000000000000000000000000000000000000000000003478000000000000000000000000000000000000000000000000000000000000347a000000000000000000000000000000000000000000000000000000000000347c000000000000000000000000000000000000000000000000000000000000347e00000000000000000000000000000000000000000000000000000000000034800000000000000000000000000000000000000000000000000000000000003482000000000000000000000000000000000000000000000000000000000000348400000000000000000000000000000000000000000000000000000000000034860000000000000000000000000000000000000000000000000000000000003488000000000000000000000000000000000000000000000000000000000000348a000000000000000000000000000000000000000000000000000000000000348c000000000000000000000000000000000000000000000000000000000000348e00000000000000000000000000000000000000000000000000000000000034900000000000000000000000000000000000000000000000000000000000003492000000000000000000000000000000000000000000000000000000000000349400000000000000000000000000000000000000000000000000000000000034960000000000000000000000000000000000000000000000000000000000003498000000000000000000000000000000000000000000000000000000000000349a000000000000000000000000000000000000000000000000000000000000349c000000000000000000000000000000000000000000000000000000000000349e00000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034a200000000000000000000000000000000000000000000000000000000000034a400000000000000000000000000000000000000000000000000000000000034a600000000000000000000000000000000000000000000000000000000000034a800000000000000000000000000000000000000000000000000000000000034aa00000000000000000000000000000000000000000000000000000000000034ac00000000000000000000000000000000000000000000000000000000000034ae00000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034b200000000000000000000000000000000000000000000000000000000000034b400000000000000000000000000000000000000000000000000000000000034b600000000000000000000000000000000000000000000000000000000000034b800000000000000000000000000000000000000000000000000000000000034ba00000000000000000000000000000000000000000000000000000000000034bc00000000000000000000000000000000000000000000000000000000000034be00000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034c200000000000000000000000000000000000000000000000000000000000034c400000000000000000000000000000000000000000000000000000000000034c600000000000000000000000000000000000000000000000000000000000034c800000000000000000000000000000000000000000000000000000000000034ca00000000000000000000000000000000000000000000000000000000000034cc00000000000000000000000000000000000000000000000000000000000034ce00000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034d200000000000000000000000000000000000000000000000000000000000034d400000000000000000000000000000000000000000000000000000000000034d600000000000000000000000000000000000000000000000000000000000034d800000000000000000000000000000000000000000000000000000000000034da00000000000000000000000000000000000000000000000000000000000034dc00000000000000000000000000000000000000000000000000000000000034de00000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034e200000000000000000000000000000000000000000000000000000000000034e400000000000000000000000000000000000000000000000000000000000034e600000000000000000000000000000000000000000000000000000000000034e800000000000000000000000000000000000000000000000000000000000034ea00000000000000000000000000000000000000000000000000000000000034ec00000000000000000000000000000000000000000000000000000000000034ee00000000000000000000000000000000000000000000000000000000000034f000000000000000000000000000000000000000000000000000000000000034f200000000000000000000000000000000000000000000000000000000000034f400000000000000000000000000000000000000000000000000000000000034f600000000000000000000000000000000000000000000000000000000000034f800000000000000000000000000000000000000000000000000000000000034fa00000000000000000000000000000000000000000000000000000000000034fc00000000000000000000000000000000000000000000000000000000000034fe00000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003502000000000000000000000000000000000000000000000000000000000000350400000000000000000000000000000000000000000000000000000000000035060000000000000000000000000000000000000000000000000000000000003508000000000000000000000000000000000000000000000000000000000000350a000000000000000000000000000000000000000000000000000000000000350c000000000000000000000000000000000000000000000000000000000000350e00000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003512000000000000000000000000000000000000000000000000000000000000351400000000000000000000000000000000000000000000000000000000000035160000000000000000000000000000000000000000000000000000000000003518000000000000000000000000000000000000000000000000000000000000351a000000000000000000000000000000000000000000000000000000000000351c000000000000000000000000000000000000000000000000000000000000351e00000000000000000000000000000000000000000000000000000000000035200000000000000000000000000000000000000000000000000000000000003522000000000000000000000000000000000000000000000000000000000000352400000000000000000000000000000000000000000000000000000000000035260000000000000000000000000000000000000000000000000000000000003528000000000000000000000000000000000000000000000000000000000000352a000000000000000000000000000000000000000000000000000000000000352c000000000000000000000000000000000000000000000000000000000000352e00000000000000000000000000000000000000000000000000000000000035300000000000000000000000000000000000000000000000000000000000003532000000000000000000000000000000000000000000000000000000000000353400000000000000000000000000000000000000000000000000000000000035360000000000000000000000000000000000000000000000000000000000003538000000000000000000000000000000000000000000000000000000000000353a000000000000000000000000000000000000000000000000000000000000353c000000000000000000000000000000000000000000000000000000000000353e00000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003542000000000000000000000000000000000000000000000000000000000000354400000000000000000000000000000000000000000000000000000000000035460000000000000000000000000000000000000000000000000000000000003548000000000000000000000000000000000000000000000000000000000000354a000000000000000000000000000000000000000000000000000000000000354c000000000000000000000000000000000000000000000000000000000000354e00000000000000000000000000000000000000000000000000000000000035500000000000000000000000000000000000000000000000000000000000003552000000000000000000000000000000000000000000000000000000000000355400000000000000000000000000000000000000000000000000000000000035560000000000000000000000000000000000000000000000000000000000003558000000000000000000000000000000000000000000000000000000000000355a000000000000000000000000000000000000000000000000000000000000355c000000000000000000000000000000000000000000000000000000000000355e00000000000000000000000000000000000000000000000000000000000035600000000000000000000000000000000000000000000000000000000000003562000000000000000000000000000000000000000000000000000000000000356400000000000000000000000000000000000000000000000000000000000035660000000000000000000000000000000000000000000000000000000000003568000000000000000000000000000000000000000000000000000000000000356a000000000000000000000000000000000000000000000000000000000000356c000000000000000000000000000000000000000000000000000000000000356e00000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003572000000000000000000000000000000000000000000000000000000000000357400000000000000000000000000000000000000000000000000000000000035760000000000000000000000000000000000000000000000000000000000003578000000000000000000000000000000000000000000000000000000000000357a000000000000000000000000000000000000000000000000000000000000357c000000000000000000000000000000000000000000000000000000000000357e00000000000000000000000000000000000000000000000000000000000035800000000000000000000000000000000000000000000000000000000000003582000000000000000000000000000000000000000000000000000000000000358400000000000000000000000000000000000000000000000000000000000035860000000000000000000000000000000000000000000000000000000000003588000000000000000000000000000000000000000000000000000000000000358a000000000000000000000000000000000000000000000000000000000000358c000000000000000000000000000000000000000000000000000000000000358e00000000000000000000000000000000000000000000000000000000000035900000000000000000000000000000000000000000000000000000000000003592000000000000000000000000000000000000000000000000000000000000359400000000000000000000000000000000000000000000000000000000000035960000000000000000000000000000000000000000000000000000000000003598000000000000000000000000000000000000000000000000000000000000359a000000000000000000000000000000000000000000000000000000000000359c000000000000000000000000000000000000000000000000000000000000359e00000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035a200000000000000000000000000000000000000000000000000000000000035a400000000000000000000000000000000000000000000000000000000000035a600000000000000000000000000000000000000000000000000000000000035a800000000000000000000000000000000000000000000000000000000000035aa00000000000000000000000000000000000000000000000000000000000035ac00000000000000000000000000000000000000000000000000000000000035ae00000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035b200000000000000000000000000000000000000000000000000000000000035b400000000000000000000000000000000000000000000000000000000000035b600000000000000000000000000000000000000000000000000000000000035b800000000000000000000000000000000000000000000000000000000000035ba00000000000000000000000000000000000000000000000000000000000035bc00000000000000000000000000000000000000000000000000000000000035be00000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035c200000000000000000000000000000000000000000000000000000000000035c400000000000000000000000000000000000000000000000000000000000035c600000000000000000000000000000000000000000000000000000000000035c800000000000000000000000000000000000000000000000000000000000035ca00000000000000000000000000000000000000000000000000000000000035cc00000000000000000000000000000000000000000000000000000000000035ce00000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035d200000000000000000000000000000000000000000000000000000000000035d400000000000000000000000000000000000000000000000000000000000035d600000000000000000000000000000000000000000000000000000000000035d800000000000000000000000000000000000000000000000000000000000035da00000000000000000000000000000000000000000000000000000000000035dc00000000000000000000000000000000000000000000000000000000000035de00000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035e200000000000000000000000000000000000000000000000000000000000035e400000000000000000000000000000000000000000000000000000000000035e600000000000000000000000000000000000000000000000000000000000035e800000000000000000000000000000000000000000000000000000000000035ea00000000000000000000000000000000000000000000000000000000000035ec00000000000000000000000000000000000000000000000000000000000035ee00000000000000000000000000000000000000000000000000000000000035f000000000000000000000000000000000000000000000000000000000000035f200000000000000000000000000000000000000000000000000000000000035f400000000000000000000000000000000000000000000000000000000000035f600000000000000000000000000000000000000000000000000000000000035f800000000000000000000000000000000000000000000000000000000000035fa00000000000000000000000000000000000000000000000000000000000035fc00000000000000000000000000000000000000000000000000000000000035fe00000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003602000000000000000000000000000000000000000000000000000000000000360400000000000000000000000000000000000000000000000000000000000036060000000000000000000000000000000000000000000000000000000000003608000000000000000000000000000000000000000000000000000000000000360a000000000000000000000000000000000000000000000000000000000000360c000000000000000000000000000000000000000000000000000000000000360e00000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003612000000000000000000000000000000000000000000000000000000000000361400000000000000000000000000000000000000000000000000000000000036160000000000000000000000000000000000000000000000000000000000003618000000000000000000000000000000000000000000000000000000000000361a000000000000000000000000000000000000000000000000000000000000361c000000000000000000000000000000000000000000000000000000000000361e00000000000000000000000000000000000000000000000000000000000036200000000000000000000000000000000000000000000000000000000000003622000000000000000000000000000000000000000000000000000000000000362400000000000000000000000000000000000000000000000000000000000036260000000000000000000000000000000000000000000000000000000000003628000000000000000000000000000000000000000000000000000000000000362a000000000000000000000000000000000000000000000000000000000000362c000000000000000000000000000000000000000000000000000000000000362e00000000000000000000000000000000000000000000000000000000000036300000000000000000000000000000000000000000000000000000000000003632000000000000000000000000000000000000000000000000000000000000363400000000000000000000000000000000000000000000000000000000000036360000000000000000000000000000000000000000000000000000000000003638000000000000000000000000000000000000000000000000000000000000363a000000000000000000000000000000000000000000000000000000000000363c000000000000000000000000000000000000000000000000000000000000363e00000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003642000000000000000000000000000000000000000000000000000000000000364400000000000000000000000000000000000000000000000000000000000036460000000000000000000000000000000000000000000000000000000000003648000000000000000000000000000000000000000000000000000000000000364a000000000000000000000000000000000000000000000000000000000000364c000000000000000000000000000000000000000000000000000000000000364e00000000000000000000000000000000000000000000000000000000000036500000000000000000000000000000000000000000000000000000000000003652000000000000000000000000000000000000000000000000000000000000365400000000000000000000000000000000000000000000000000000000000036560000000000000000000000000000000000000000000000000000000000003658000000000000000000000000000000000000000000000000000000000000365a000000000000000000000000000000000000000000000000000000000000365c000000000000000000000000000000000000000000000000000000000000365e00000000000000000000000000000000000000000000000000000000000036600000000000000000000000000000000000000000000000000000000000003662000000000000000000000000000000000000000000000000000000000000366400000000000000000000000000000000000000000000000000000000000036660000000000000000000000000000000000000000000000000000000000003668000000000000000000000000000000000000000000000000000000000000366a000000000000000000000000000000000000000000000000000000000000366c000000000000000000000000000000000000000000000000000000000000366e00000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003672000000000000000000000000000000000000000000000000000000000000367400000000000000000000000000000000000000000000000000000000000036760000000000000000000000000000000000000000000000000000000000003678000000000000000000000000000000000000000000000000000000000000367a000000000000000000000000000000000000000000000000000000000000367c000000000000000000000000000000000000000000000000000000000000367e00000000000000000000000000000000000000000000000000000000000036800000000000000000000000000000000000000000000000000000000000003682000000000000000000000000000000000000000000000000000000000000368400000000000000000000000000000000000000000000000000000000000036860000000000000000000000000000000000000000000000000000000000003688000000000000000000000000000000000000000000000000000000000000368a000000000000000000000000000000000000000000000000000000000000368c000000000000000000000000000000000000000000000000000000000000368e00000000000000000000000000000000000000000000000000000000000036900000000000000000000000000000000000000000000000000000000000003692000000000000000000000000000000000000000000000000000000000000369400000000000000000000000000000000000000000000000000000000000036960000000000000000000000000000000000000000000000000000000000003698000000000000000000000000000000000000000000000000000000000000369a000000000000000000000000000000000000000000000000000000000000369c000000000000000000000000000000000000000000000000000000000000369e00000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036a200000000000000000000000000000000000000000000000000000000000036a400000000000000000000000000000000000000000000000000000000000036a600000000000000000000000000000000000000000000000000000000000036a800000000000000000000000000000000000000000000000000000000000036aa00000000000000000000000000000000000000000000000000000000000036ac00000000000000000000000000000000000000000000000000000000000036ae00000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036b200000000000000000000000000000000000000000000000000000000000036b400000000000000000000000000000000000000000000000000000000000036b600000000000000000000000000000000000000000000000000000000000036b800000000000000000000000000000000000000000000000000000000000036ba00000000000000000000000000000000000000000000000000000000000036bc00000000000000000000000000000000000000000000000000000000000036be00000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036c200000000000000000000000000000000000000000000000000000000000036c400000000000000000000000000000000000000000000000000000000000036c600000000000000000000000000000000000000000000000000000000000036c800000000000000000000000000000000000000000000000000000000000036ca00000000000000000000000000000000000000000000000000000000000036cc00000000000000000000000000000000000000000000000000000000000036ce00000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036d200000000000000000000000000000000000000000000000000000000000036d400000000000000000000000000000000000000000000000000000000000036d600000000000000000000000000000000000000000000000000000000000036d800000000000000000000000000000000000000000000000000000000000036da00000000000000000000000000000000000000000000000000000000000036dc00000000000000000000000000000000000000000000000000000000000036de00000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036e200000000000000000000000000000000000000000000000000000000000036e400000000000000000000000000000000000000000000000000000000000036e600000000000000000000000000000000000000000000000000000000000036e800000000000000000000000000000000000000000000000000000000000036ea00000000000000000000000000000000000000000000000000000000000036ec00000000000000000000000000000000000000000000000000000000000036ee00000000000000000000000000000000000000000000000000000000000036f000000000000000000000000000000000000000000000000000000000000036f200000000000000000000000000000000000000000000000000000000000036f400000000000000000000000000000000000000000000000000000000000036f600000000000000000000000000000000000000000000000000000000000036f800000000000000000000000000000000000000000000000000000000000036fa00000000000000000000000000000000000000000000000000000000000036fc00000000000000000000000000000000000000000000000000000000000036fe00000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000003702000000000000000000000000000000000000000000000000000000000000370400000000000000000000000000000000000000000000000000000000000037060000000000000000000000000000000000000000000000000000000000003708000000000000000000000000000000000000000000000000000000000000370a000000000000000000000000000000000000000000000000000000000000370c000000000000000000000000000000000000000000000000000000000000370e00000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003712000000000000000000000000000000000000000000000000000000000000371400000000000000000000000000000000000000000000000000000000000037160000000000000000000000000000000000000000000000000000000000003718000000000000000000000000000000000000000000000000000000000000371a000000000000000000000000000000000000000000000000000000000000371c000000000000000000000000000000000000000000000000000000000000371e00000000000000000000000000000000000000000000000000000000000037200000000000000000000000000000000000000000000000000000000000003722000000000000000000000000000000000000000000000000000000000000372400000000000000000000000000000000000000000000000000000000000037260000000000000000000000000000000000000000000000000000000000003728000000000000000000000000000000000000000000000000000000000000372a000000000000000000000000000000000000000000000000000000000000372c000000000000000000000000000000000000000000000000000000000000372e00000000000000000000000000000000000000000000000000000000000037300000000000000000000000000000000000000000000000000000000000003732000000000000000000000000000000000000000000000000000000000000373400000000000000000000000000000000000000000000000000000000000037360000000000000000000000000000000000000000000000000000000000003738000000000000000000000000000000000000000000000000000000000000373a000000000000000000000000000000000000000000000000000000000000373c000000000000000000000000000000000000000000000000000000000000373e00000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003742000000000000000000000000000000000000000000000000000000000000374400000000000000000000000000000000000000000000000000000000000037460000000000000000000000000000000000000000000000000000000000003748000000000000000000000000000000000000000000000000000000000000374a000000000000000000000000000000000000000000000000000000000000374c000000000000000000000000000000000000000000000000000000000000374e00000000000000000000000000000000000000000000000000000000000037500000000000000000000000000000000000000000000000000000000000003752000000000000000000000000000000000000000000000000000000000000375400000000000000000000000000000000000000000000000000000000000037560000000000000000000000000000000000000000000000000000000000003758000000000000000000000000000000000000000000000000000000000000375a000000000000000000000000000000000000000000000000000000000000375c000000000000000000000000000000000000000000000000000000000000375e00000000000000000000000000000000000000000000000000000000000037600000000000000000000000000000000000000000000000000000000000003762000000000000000000000000000000000000000000000000000000000000376400000000000000000000000000000000000000000000000000000000000037660000000000000000000000000000000000000000000000000000000000003768000000000000000000000000000000000000000000000000000000000000376a000000000000000000000000000000000000000000000000000000000000376c000000000000000000000000000000000000000000000000000000000000376e00000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003772000000000000000000000000000000000000000000000000000000000000377400000000000000000000000000000000000000000000000000000000000037760000000000000000000000000000000000000000000000000000000000003778000000000000000000000000000000000000000000000000000000000000377a000000000000000000000000000000000000000000000000000000000000377c000000000000000000000000000000000000000000000000000000000000377e00000000000000000000000000000000000000000000000000000000000037800000000000000000000000000000000000000000000000000000000000003782000000000000000000000000000000000000000000000000000000000000378400000000000000000000000000000000000000000000000000000000000037860000000000000000000000000000000000000000000000000000000000003788000000000000000000000000000000000000000000000000000000000000378a000000000000000000000000000000000000000000000000000000000000378c000000000000000000000000000000000000000000000000000000000000378e00000000000000000000000000000000000000000000000000000000000037900000000000000000000000000000000000000000000000000000000000003792000000000000000000000000000000000000000000000000000000000000379400000000000000000000000000000000000000000000000000000000000037960000000000000000000000000000000000000000000000000000000000003798000000000000000000000000000000000000000000000000000000000000379a000000000000000000000000000000000000000000000000000000000000379c000000000000000000000000000000000000000000000000000000000000379e00000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037a200000000000000000000000000000000000000000000000000000000000037a400000000000000000000000000000000000000000000000000000000000037a600000000000000000000000000000000000000000000000000000000000037a800000000000000000000000000000000000000000000000000000000000037aa00000000000000000000000000000000000000000000000000000000000037ac00000000000000000000000000000000000000000000000000000000000037ae00000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037b200000000000000000000000000000000000000000000000000000000000037b400000000000000000000000000000000000000000000000000000000000037b600000000000000000000000000000000000000000000000000000000000037b800000000000000000000000000000000000000000000000000000000000037ba00000000000000000000000000000000000000000000000000000000000037bc00000000000000000000000000000000000000000000000000000000000037be00000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037c200000000000000000000000000000000000000000000000000000000000037c400000000000000000000000000000000000000000000000000000000000037c600000000000000000000000000000000000000000000000000000000000037c800000000000000000000000000000000000000000000000000000000000037ca00000000000000000000000000000000000000000000000000000000000037cc00000000000000000000000000000000000000000000000000000000000037ce00000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037d200000000000000000000000000000000000000000000000000000000000037d400000000000000000000000000000000000000000000000000000000000037d600000000000000000000000000000000000000000000000000000000000037d800000000000000000000000000000000000000000000000000000000000037da00000000000000000000000000000000000000000000000000000000000037dc00000000000000000000000000000000000000000000000000000000000037de00000000000000000000000000000000000000000000000000000000000037e000000000000000000000000000000000000000000000000000000000000037e200000000000000000000000000000000000000000000000000000000000037e400000000000000000000000000000000000000000000000000000000000037e600000000000000000000000000000000000000000000000000000000000037e800000000000000000000000000000000000000000000000000000000000037ea00000000000000000000000000000000000000000000000000000000000037ec00000000000000000000000000000000000000000000000000000000000037ee00000000000000000000000000000000000000000000000000000000000037f000000000000000000000000000000000000000000000000000000000000037f200000000000000000000000000000000000000000000000000000000000037f400000000000000000000000000000000000000000000000000000000000037f600000000000000000000000000000000000000000000000000000000000037f800000000000000000000000000000000000000000000000000000000000037fa00000000000000000000000000000000000000000000000000000000000037fc00000000000000000000000000000000000000000000000000000000000037fe00000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003802000000000000000000000000000000000000000000000000000000000000380400000000000000000000000000000000000000000000000000000000000038060000000000000000000000000000000000000000000000000000000000003808000000000000000000000000000000000000000000000000000000000000380a000000000000000000000000000000000000000000000000000000000000380c000000000000000000000000000000000000000000000000000000000000380e00000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003812000000000000000000000000000000000000000000000000000000000000381400000000000000000000000000000000000000000000000000000000000038160000000000000000000000000000000000000000000000000000000000003818000000000000000000000000000000000000000000000000000000000000381a000000000000000000000000000000000000000000000000000000000000381c000000000000000000000000000000000000000000000000000000000000381e00000000000000000000000000000000000000000000000000000000000038200000000000000000000000000000000000000000000000000000000000003822000000000000000000000000000000000000000000000000000000000000382400000000000000000000000000000000000000000000000000000000000038260000000000000000000000000000000000000000000000000000000000003828000000000000000000000000000000000000000000000000000000000000382a000000000000000000000000000000000000000000000000000000000000382c000000000000000000000000000000000000000000000000000000000000382e00000000000000000000000000000000000000000000000000000000000038300000000000000000000000000000000000000000000000000000000000003832000000000000000000000000000000000000000000000000000000000000383400000000000000000000000000000000000000000000000000000000000038360000000000000000000000000000000000000000000000000000000000003838000000000000000000000000000000000000000000000000000000000000383a000000000000000000000000000000000000000000000000000000000000383c000000000000000000000000000000000000000000000000000000000000383e00000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003842000000000000000000000000000000000000000000000000000000000000384400000000000000000000000000000000000000000000000000000000000038460000000000000000000000000000000000000000000000000000000000003848000000000000000000000000000000000000000000000000000000000000384a000000000000000000000000000000000000000000000000000000000000384c000000000000000000000000000000000000000000000000000000000000384e00000000000000000000000000000000000000000000000000000000000038500000000000000000000000000000000000000000000000000000000000003852000000000000000000000000000000000000000000000000000000000000385400000000000000000000000000000000000000000000000000000000000038560000000000000000000000000000000000000000000000000000000000003858000000000000000000000000000000000000000000000000000000000000385a000000000000000000000000000000000000000000000000000000000000385c000000000000000000000000000000000000000000000000000000000000385e00000000000000000000000000000000000000000000000000000000000038600000000000000000000000000000000000000000000000000000000000003862000000000000000000000000000000000000000000000000000000000000386400000000000000000000000000000000000000000000000000000000000038660000000000000000000000000000000000000000000000000000000000003868000000000000000000000000000000000000000000000000000000000000386a000000000000000000000000000000000000000000000000000000000000386c000000000000000000000000000000000000000000000000000000000000386e00000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003872000000000000000000000000000000000000000000000000000000000000387400000000000000000000000000000000000000000000000000000000000038760000000000000000000000000000000000000000000000000000000000003878000000000000000000000000000000000000000000000000000000000000387a000000000000000000000000000000000000000000000000000000000000387c000000000000000000000000000000000000000000000000000000000000387e00000000000000000000000000000000000000000000000000000000000038800000000000000000000000000000000000000000000000000000000000003882000000000000000000000000000000000000000000000000000000000000388400000000000000000000000000000000000000000000000000000000000038860000000000000000000000000000000000000000000000000000000000003888000000000000000000000000000000000000000000000000000000000000388a000000000000000000000000000000000000000000000000000000000000388c000000000000000000000000000000000000000000000000000000000000388e00000000000000000000000000000000000000000000000000000000000038900000000000000000000000000000000000000000000000000000000000003892000000000000000000000000000000000000000000000000000000000000389400000000000000000000000000000000000000000000000000000000000038960000000000000000000000000000000000000000000000000000000000003898000000000000000000000000000000000000000000000000000000000000389a000000000000000000000000000000000000000000000000000000000000389c000000000000000000000000000000000000000000000000000000000000389e00000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038a200000000000000000000000000000000000000000000000000000000000038a400000000000000000000000000000000000000000000000000000000000038a600000000000000000000000000000000000000000000000000000000000038a800000000000000000000000000000000000000000000000000000000000038aa00000000000000000000000000000000000000000000000000000000000038ac00000000000000000000000000000000000000000000000000000000000038ae00000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038b200000000000000000000000000000000000000000000000000000000000038b400000000000000000000000000000000000000000000000000000000000038b600000000000000000000000000000000000000000000000000000000000038b800000000000000000000000000000000000000000000000000000000000038ba00000000000000000000000000000000000000000000000000000000000038bc00000000000000000000000000000000000000000000000000000000000038be00000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038c200000000000000000000000000000000000000000000000000000000000038c400000000000000000000000000000000000000000000000000000000000038c600000000000000000000000000000000000000000000000000000000000038c800000000000000000000000000000000000000000000000000000000000038ca00000000000000000000000000000000000000000000000000000000000038cc00000000000000000000000000000000000000000000000000000000000038ce00000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038d200000000000000000000000000000000000000000000000000000000000038d400000000000000000000000000000000000000000000000000000000000038d600000000000000000000000000000000000000000000000000000000000038d800000000000000000000000000000000000000000000000000000000000038da00000000000000000000000000000000000000000000000000000000000038dc00000000000000000000000000000000000000000000000000000000000038de00000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038e200000000000000000000000000000000000000000000000000000000000038e400000000000000000000000000000000000000000000000000000000000038e600000000000000000000000000000000000000000000000000000000000038e800000000000000000000000000000000000000000000000000000000000038ea00000000000000000000000000000000000000000000000000000000000038ec00000000000000000000000000000000000000000000000000000000000038ee00000000000000000000000000000000000000000000000000000000000038f000000000000000000000000000000000000000000000000000000000000038f200000000000000000000000000000000000000000000000000000000000038f400000000000000000000000000000000000000000000000000000000000038f600000000000000000000000000000000000000000000000000000000000038f800000000000000000000000000000000000000000000000000000000000038fa00000000000000000000000000000000000000000000000000000000000038fc00000000000000000000000000000000000000000000000000000000000038fe00000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003902000000000000000000000000000000000000000000000000000000000000390400000000000000000000000000000000000000000000000000000000000039060000000000000000000000000000000000000000000000000000000000003908000000000000000000000000000000000000000000000000000000000000390a000000000000000000000000000000000000000000000000000000000000390c000000000000000000000000000000000000000000000000000000000000390e00000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003912000000000000000000000000000000000000000000000000000000000000391400000000000000000000000000000000000000000000000000000000000039160000000000000000000000000000000000000000000000000000000000003918000000000000000000000000000000000000000000000000000000000000391a000000000000000000000000000000000000000000000000000000000000391c000000000000000000000000000000000000000000000000000000000000391e00000000000000000000000000000000000000000000000000000000000039200000000000000000000000000000000000000000000000000000000000003922000000000000000000000000000000000000000000000000000000000000392400000000000000000000000000000000000000000000000000000000000039260000000000000000000000000000000000000000000000000000000000003928000000000000000000000000000000000000000000000000000000000000392a000000000000000000000000000000000000000000000000000000000000392c000000000000000000000000000000000000000000000000000000000000392e00000000000000000000000000000000000000000000000000000000000039300000000000000000000000000000000000000000000000000000000000003932000000000000000000000000000000000000000000000000000000000000393400000000000000000000000000000000000000000000000000000000000039360000000000000000000000000000000000000000000000000000000000003938000000000000000000000000000000000000000000000000000000000000393a000000000000000000000000000000000000000000000000000000000000393c000000000000000000000000000000000000000000000000000000000000393e00000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003942000000000000000000000000000000000000000000000000000000000000394400000000000000000000000000000000000000000000000000000000000039460000000000000000000000000000000000000000000000000000000000003948000000000000000000000000000000000000000000000000000000000000394a000000000000000000000000000000000000000000000000000000000000394c000000000000000000000000000000000000000000000000000000000000394e00000000000000000000000000000000000000000000000000000000000039500000000000000000000000000000000000000000000000000000000000003952000000000000000000000000000000000000000000000000000000000000395400000000000000000000000000000000000000000000000000000000000039560000000000000000000000000000000000000000000000000000000000003958000000000000000000000000000000000000000000000000000000000000395a000000000000000000000000000000000000000000000000000000000000395c000000000000000000000000000000000000000000000000000000000000395e00000000000000000000000000000000000000000000000000000000000039600000000000000000000000000000000000000000000000000000000000003962000000000000000000000000000000000000000000000000000000000000396400000000000000000000000000000000000000000000000000000000000039660000000000000000000000000000000000000000000000000000000000003968000000000000000000000000000000000000000000000000000000000000396a000000000000000000000000000000000000000000000000000000000000396c000000000000000000000000000000000000000000000000000000000000396e00000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003972000000000000000000000000000000000000000000000000000000000000397400000000000000000000000000000000000000000000000000000000000039760000000000000000000000000000000000000000000000000000000000003978000000000000000000000000000000000000000000000000000000000000397a000000000000000000000000000000000000000000000000000000000000397c000000000000000000000000000000000000000000000000000000000000397e00000000000000000000000000000000000000000000000000000000000039800000000000000000000000000000000000000000000000000000000000003982000000000000000000000000000000000000000000000000000000000000398400000000000000000000000000000000000000000000000000000000000039860000000000000000000000000000000000000000000000000000000000003988000000000000000000000000000000000000000000000000000000000000398a000000000000000000000000000000000000000000000000000000000000398c000000000000000000000000000000000000000000000000000000000000398e00000000000000000000000000000000000000000000000000000000000039900000000000000000000000000000000000000000000000000000000000003992000000000000000000000000000000000000000000000000000000000000399400000000000000000000000000000000000000000000000000000000000039960000000000000000000000000000000000000000000000000000000000003998000000000000000000000000000000000000000000000000000000000000399a000000000000000000000000000000000000000000000000000000000000399c000000000000000000000000000000000000000000000000000000000000399e00000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039a200000000000000000000000000000000000000000000000000000000000039a400000000000000000000000000000000000000000000000000000000000039a600000000000000000000000000000000000000000000000000000000000039a800000000000000000000000000000000000000000000000000000000000039aa00000000000000000000000000000000000000000000000000000000000039ac00000000000000000000000000000000000000000000000000000000000039ae00000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039b200000000000000000000000000000000000000000000000000000000000039b400000000000000000000000000000000000000000000000000000000000039b600000000000000000000000000000000000000000000000000000000000039b800000000000000000000000000000000000000000000000000000000000039ba00000000000000000000000000000000000000000000000000000000000039bc00000000000000000000000000000000000000000000000000000000000039be00000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039c200000000000000000000000000000000000000000000000000000000000039c400000000000000000000000000000000000000000000000000000000000039c600000000000000000000000000000000000000000000000000000000000039c800000000000000000000000000000000000000000000000000000000000039ca00000000000000000000000000000000000000000000000000000000000039cc00000000000000000000000000000000000000000000000000000000000039ce00000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039d200000000000000000000000000000000000000000000000000000000000039d400000000000000000000000000000000000000000000000000000000000039d600000000000000000000000000000000000000000000000000000000000039d800000000000000000000000000000000000000000000000000000000000039da00000000000000000000000000000000000000000000000000000000000039dc00000000000000000000000000000000000000000000000000000000000039de00000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039e200000000000000000000000000000000000000000000000000000000000039e400000000000000000000000000000000000000000000000000000000000039e600000000000000000000000000000000000000000000000000000000000039e800000000000000000000000000000000000000000000000000000000000039ea00000000000000000000000000000000000000000000000000000000000039ec00000000000000000000000000000000000000000000000000000000000039ee00000000000000000000000000000000000000000000000000000000000039f000000000000000000000000000000000000000000000000000000000000039f200000000000000000000000000000000000000000000000000000000000039f400000000000000000000000000000000000000000000000000000000000039f600000000000000000000000000000000000000000000000000000000000039f800000000000000000000000000000000000000000000000000000000000039fa00000000000000000000000000000000000000000000000000000000000039fc00000000000000000000000000000000000000000000000000000000000039fe0000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a020000000000000000000000000000000000000000000000000000000000003a040000000000000000000000000000000000000000000000000000000000003a060000000000000000000000000000000000000000000000000000000000003a080000000000000000000000000000000000000000000000000000000000003a0a0000000000000000000000000000000000000000000000000000000000003a0c0000000000000000000000000000000000000000000000000000000000003a0e0000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a120000000000000000000000000000000000000000000000000000000000003a140000000000000000000000000000000000000000000000000000000000003a160000000000000000000000000000000000000000000000000000000000003a180000000000000000000000000000000000000000000000000000000000003a1a0000000000000000000000000000000000000000000000000000000000003a1c0000000000000000000000000000000000000000000000000000000000003a1e0000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a220000000000000000000000000000000000000000000000000000000000003a240000000000000000000000000000000000000000000000000000000000003a260000000000000000000000000000000000000000000000000000000000003a280000000000000000000000000000000000000000000000000000000000003a2a0000000000000000000000000000000000000000000000000000000000003a2c0000000000000000000000000000000000000000000000000000000000003a2e0000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a320000000000000000000000000000000000000000000000000000000000003a340000000000000000000000000000000000000000000000000000000000003a360000000000000000000000000000000000000000000000000000000000003a380000000000000000000000000000000000000000000000000000000000003a3a0000000000000000000000000000000000000000000000000000000000003a3c0000000000000000000000000000000000000000000000000000000000003a3e0000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a420000000000000000000000000000000000000000000000000000000000003a440000000000000000000000000000000000000000000000000000000000003a460000000000000000000000000000000000000000000000000000000000003a480000000000000000000000000000000000000000000000000000000000003a4a0000000000000000000000000000000000000000000000000000000000003a4c0000000000000000000000000000000000000000000000000000000000003a4e0000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a520000000000000000000000000000000000000000000000000000000000003a540000000000000000000000000000000000000000000000000000000000003a560000000000000000000000000000000000000000000000000000000000003a580000000000000000000000000000000000000000000000000000000000003a5a0000000000000000000000000000000000000000000000000000000000003a5c0000000000000000000000000000000000000000000000000000000000003a5e0000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a620000000000000000000000000000000000000000000000000000000000003a640000000000000000000000000000000000000000000000000000000000003a660000000000000000000000000000000000000000000000000000000000003a680000000000000000000000000000000000000000000000000000000000003a6a0000000000000000000000000000000000000000000000000000000000003a6c0000000000000000000000000000000000000000000000000000000000003a6e0000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a720000000000000000000000000000000000000000000000000000000000003a740000000000000000000000000000000000000000000000000000000000003a760000000000000000000000000000000000000000000000000000000000003a780000000000000000000000000000000000000000000000000000000000003a7a0000000000000000000000000000000000000000000000000000000000003a7c0000000000000000000000000000000000000000000000000000000000003a7e0000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a820000000000000000000000000000000000000000000000000000000000003a840000000000000000000000000000000000000000000000000000000000003a860000000000000000000000000000000000000000000000000000000000003a880000000000000000000000000000000000000000000000000000000000003a8a0000000000000000000000000000000000000000000000000000000000003a8c0000000000000000000000000000000000000000000000000000000000003a8e0000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003a920000000000000000000000000000000000000000000000000000000000003a940000000000000000000000000000000000000000000000000000000000003a960000000000000000000000000000000000000000000000000000000000003a980000000000000000000000000000000000000000000000000000000000003a9a0000000000000000000000000000000000000000000000000000000000003a9c0000000000000000000000000000000000000000000000000000000000003a9e0000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003aa20000000000000000000000000000000000000000000000000000000000003aa40000000000000000000000000000000000000000000000000000000000003aa60000000000000000000000000000000000000000000000000000000000003aa80000000000000000000000000000000000000000000000000000000000003aaa0000000000000000000000000000000000000000000000000000000000003aac0000000000000000000000000000000000000000000000000000000000003aae0000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ab20000000000000000000000000000000000000000000000000000000000003ab40000000000000000000000000000000000000000000000000000000000003ab60000000000000000000000000000000000000000000000000000000000003ab80000000000000000000000000000000000000000000000000000000000003aba0000000000000000000000000000000000000000000000000000000000003abc0000000000000000000000000000000000000000000000000000000000003abe0000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ac20000000000000000000000000000000000000000000000000000000000003ac40000000000000000000000000000000000000000000000000000000000003ac60000000000000000000000000000000000000000000000000000000000003ac80000000000000000000000000000000000000000000000000000000000003aca0000000000000000000000000000000000000000000000000000000000003acc0000000000000000000000000000000000000000000000000000000000003ace0000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ad20000000000000000000000000000000000000000000000000000000000003ad40000000000000000000000000000000000000000000000000000000000003ad60000000000000000000000000000000000000000000000000000000000003ad80000000000000000000000000000000000000000000000000000000000003ada0000000000000000000000000000000000000000000000000000000000003adc0000000000000000000000000000000000000000000000000000000000003ade0000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003ae20000000000000000000000000000000000000000000000000000000000003ae40000000000000000000000000000000000000000000000000000000000003ae60000000000000000000000000000000000000000000000000000000000003ae80000000000000000000000000000000000000000000000000000000000003aea0000000000000000000000000000000000000000000000000000000000003aec0000000000000000000000000000000000000000000000000000000000003aee0000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003af20000000000000000000000000000000000000000000000000000000000003af40000000000000000000000000000000000000000000000000000000000003af60000000000000000000000000000000000000000000000000000000000003af80000000000000000000000000000000000000000000000000000000000003afa0000000000000000000000000000000000000000000000000000000000003afc0000000000000000000000000000000000000000000000000000000000003afe0000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b020000000000000000000000000000000000000000000000000000000000003b040000000000000000000000000000000000000000000000000000000000003b060000000000000000000000000000000000000000000000000000000000003b080000000000000000000000000000000000000000000000000000000000003b0a0000000000000000000000000000000000000000000000000000000000003b0c0000000000000000000000000000000000000000000000000000000000003b0e0000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b120000000000000000000000000000000000000000000000000000000000003b140000000000000000000000000000000000000000000000000000000000003b160000000000000000000000000000000000000000000000000000000000003b180000000000000000000000000000000000000000000000000000000000003b1a0000000000000000000000000000000000000000000000000000000000003b1c0000000000000000000000000000000000000000000000000000000000003b1e0000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b220000000000000000000000000000000000000000000000000000000000003b240000000000000000000000000000000000000000000000000000000000003b260000000000000000000000000000000000000000000000000000000000003b280000000000000000000000000000000000000000000000000000000000003b2a0000000000000000000000000000000000000000000000000000000000003b2c0000000000000000000000000000000000000000000000000000000000003b2e0000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b320000000000000000000000000000000000000000000000000000000000003b340000000000000000000000000000000000000000000000000000000000003b360000000000000000000000000000000000000000000000000000000000003b380000000000000000000000000000000000000000000000000000000000003b3a0000000000000000000000000000000000000000000000000000000000003b3c0000000000000000000000000000000000000000000000000000000000003b3e0000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b420000000000000000000000000000000000000000000000000000000000003b440000000000000000000000000000000000000000000000000000000000003b460000000000000000000000000000000000000000000000000000000000003b480000000000000000000000000000000000000000000000000000000000003b4a0000000000000000000000000000000000000000000000000000000000003b4c0000000000000000000000000000000000000000000000000000000000003b4e0000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b520000000000000000000000000000000000000000000000000000000000003b540000000000000000000000000000000000000000000000000000000000003b560000000000000000000000000000000000000000000000000000000000003b580000000000000000000000000000000000000000000000000000000000003b5a0000000000000000000000000000000000000000000000000000000000003b5c0000000000000000000000000000000000000000000000000000000000003b5e0000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b620000000000000000000000000000000000000000000000000000000000003b640000000000000000000000000000000000000000000000000000000000003b660000000000000000000000000000000000000000000000000000000000003b680000000000000000000000000000000000000000000000000000000000003b6a0000000000000000000000000000000000000000000000000000000000003b6c0000000000000000000000000000000000000000000000000000000000003b6e0000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b720000000000000000000000000000000000000000000000000000000000003b740000000000000000000000000000000000000000000000000000000000003b760000000000000000000000000000000000000000000000000000000000003b780000000000000000000000000000000000000000000000000000000000003b7a0000000000000000000000000000000000000000000000000000000000003b7c0000000000000000000000000000000000000000000000000000000000003b7e0000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b820000000000000000000000000000000000000000000000000000000000003b840000000000000000000000000000000000000000000000000000000000003b860000000000000000000000000000000000000000000000000000000000003b880000000000000000000000000000000000000000000000000000000000003b8a0000000000000000000000000000000000000000000000000000000000003b8c0000000000000000000000000000000000000000000000000000000000003b8e0000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003b920000000000000000000000000000000000000000000000000000000000003b940000000000000000000000000000000000000000000000000000000000003b960000000000000000000000000000000000000000000000000000000000003b980000000000000000000000000000000000000000000000000000000000003b9a0000000000000000000000000000000000000000000000000000000000003b9c0000000000000000000000000000000000000000000000000000000000003b9e0000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003ba20000000000000000000000000000000000000000000000000000000000003ba40000000000000000000000000000000000000000000000000000000000003ba60000000000000000000000000000000000000000000000000000000000003ba80000000000000000000000000000000000000000000000000000000000003baa0000000000000000000000000000000000000000000000000000000000003bac0000000000000000000000000000000000000000000000000000000000003bae0000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bb20000000000000000000000000000000000000000000000000000000000003bb40000000000000000000000000000000000000000000000000000000000003bb60000000000000000000000000000000000000000000000000000000000003bb80000000000000000000000000000000000000000000000000000000000003bba0000000000000000000000000000000000000000000000000000000000003bbc0000000000000000000000000000000000000000000000000000000000003bbe0000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bc20000000000000000000000000000000000000000000000000000000000003bc40000000000000000000000000000000000000000000000000000000000003bc60000000000000000000000000000000000000000000000000000000000003bc80000000000000000000000000000000000000000000000000000000000003bca0000000000000000000000000000000000000000000000000000000000003bcc0000000000000000000000000000000000000000000000000000000000003bce0000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003bd20000000000000000000000000000000000000000000000000000000000003bd40000000000000000000000000000000000000000000000000000000000003bd60000000000000000000000000000000000000000000000000000000000003bd80000000000000000000000000000000000000000000000000000000000003bda0000000000000000000000000000000000000000000000000000000000003bdc0000000000000000000000000000000000000000000000000000000000003bde0000000000000000000000000000000000000000000000000000000000003be00000000000000000000000000000000000000000000000000000000000003be20000000000000000000000000000000000000000000000000000000000003be40000000000000000000000000000000000000000000000000000000000003be60000000000000000000000000000000000000000000000000000000000003be80000000000000000000000000000000000000000000000000000000000003bea0000000000000000000000000000000000000000000000000000000000003bec0000000000000000000000000000000000000000000000000000000000003bee0000000000000000000000000000000000000000000000000000000000003bf00000000000000000000000000000000000000000000000000000000000003bf20000000000000000000000000000000000000000000000000000000000003bf40000000000000000000000000000000000000000000000000000000000003bf60000000000000000000000000000000000000000000000000000000000003bf80000000000000000000000000000000000000000000000000000000000003bfa0000000000000000000000000000000000000000000000000000000000003bfc0000000000000000000000000000000000000000000000000000000000003bfe0000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c020000000000000000000000000000000000000000000000000000000000003c040000000000000000000000000000000000000000000000000000000000003c060000000000000000000000000000000000000000000000000000000000003c080000000000000000000000000000000000000000000000000000000000003c0a0000000000000000000000000000000000000000000000000000000000003c0c0000000000000000000000000000000000000000000000000000000000003c0e0000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c120000000000000000000000000000000000000000000000000000000000003c140000000000000000000000000000000000000000000000000000000000003c160000000000000000000000000000000000000000000000000000000000003c180000000000000000000000000000000000000000000000000000000000003c1a0000000000000000000000000000000000000000000000000000000000003c1c0000000000000000000000000000000000000000000000000000000000003c1e0000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c220000000000000000000000000000000000000000000000000000000000003c240000000000000000000000000000000000000000000000000000000000003c260000000000000000000000000000000000000000000000000000000000003c280000000000000000000000000000000000000000000000000000000000003c2a0000000000000000000000000000000000000000000000000000000000003c2c0000000000000000000000000000000000000000000000000000000000003c2e0000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c320000000000000000000000000000000000000000000000000000000000003c340000000000000000000000000000000000000000000000000000000000003c360000000000000000000000000000000000000000000000000000000000003c380000000000000000000000000000000000000000000000000000000000003c3a0000000000000000000000000000000000000000000000000000000000003c3c0000000000000000000000000000000000000000000000000000000000003c3e0000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c420000000000000000000000000000000000000000000000000000000000003c440000000000000000000000000000000000000000000000000000000000003c460000000000000000000000000000000000000000000000000000000000003c480000000000000000000000000000000000000000000000000000000000003c4a0000000000000000000000000000000000000000000000000000000000003c4c0000000000000000000000000000000000000000000000000000000000003c4e0000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c520000000000000000000000000000000000000000000000000000000000003c540000000000000000000000000000000000000000000000000000000000003c560000000000000000000000000000000000000000000000000000000000003c580000000000000000000000000000000000000000000000000000000000003c5a0000000000000000000000000000000000000000000000000000000000003c5c0000000000000000000000000000000000000000000000000000000000003c5e0000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c620000000000000000000000000000000000000000000000000000000000003c640000000000000000000000000000000000000000000000000000000000003c660000000000000000000000000000000000000000000000000000000000003c680000000000000000000000000000000000000000000000000000000000003c6a0000000000000000000000000000000000000000000000000000000000003c6c0000000000000000000000000000000000000000000000000000000000003c6e0000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c720000000000000000000000000000000000000000000000000000000000003c740000000000000000000000000000000000000000000000000000000000003c760000000000000000000000000000000000000000000000000000000000003c780000000000000000000000000000000000000000000000000000000000003c7a0000000000000000000000000000000000000000000000000000000000003c7c0000000000000000000000000000000000000000000000000000000000003c7e0000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c820000000000000000000000000000000000000000000000000000000000003c840000000000000000000000000000000000000000000000000000000000003c860000000000000000000000000000000000000000000000000000000000003c880000000000000000000000000000000000000000000000000000000000003c8a0000000000000000000000000000000000000000000000000000000000003c8c0000000000000000000000000000000000000000000000000000000000003c8e0000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003c920000000000000000000000000000000000000000000000000000000000003c940000000000000000000000000000000000000000000000000000000000003c960000000000000000000000000000000000000000000000000000000000003c980000000000000000000000000000000000000000000000000000000000003c9a0000000000000000000000000000000000000000000000000000000000003c9c0000000000000000000000000000000000000000000000000000000000003c9e0000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003ca20000000000000000000000000000000000000000000000000000000000003ca40000000000000000000000000000000000000000000000000000000000003ca60000000000000000000000000000000000000000000000000000000000003ca80000000000000000000000000000000000000000000000000000000000003caa0000000000000000000000000000000000000000000000000000000000003cac0000000000000000000000000000000000000000000000000000000000003cae0000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cb20000000000000000000000000000000000000000000000000000000000003cb40000000000000000000000000000000000000000000000000000000000003cb60000000000000000000000000000000000000000000000000000000000003cb80000000000000000000000000000000000000000000000000000000000003cba0000000000000000000000000000000000000000000000000000000000003cbc0000000000000000000000000000000000000000000000000000000000003cbe0000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cc20000000000000000000000000000000000000000000000000000000000003cc40000000000000000000000000000000000000000000000000000000000003cc60000000000000000000000000000000000000000000000000000000000003cc80000000000000000000000000000000000000000000000000000000000003cca0000000000000000000000000000000000000000000000000000000000003ccc0000000000000000000000000000000000000000000000000000000000003cce0000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003cd20000000000000000000000000000000000000000000000000000000000003cd40000000000000000000000000000000000000000000000000000000000003cd60000000000000000000000000000000000000000000000000000000000003cd80000000000000000000000000000000000000000000000000000000000003cda0000000000000000000000000000000000000000000000000000000000003cdc0000000000000000000000000000000000000000000000000000000000003cde0000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003ce20000000000000000000000000000000000000000000000000000000000003ce40000000000000000000000000000000000000000000000000000000000003ce60000000000000000000000000000000000000000000000000000000000003ce80000000000000000000000000000000000000000000000000000000000003cea0000000000000000000000000000000000000000000000000000000000003cec0000000000000000000000000000000000000000000000000000000000003cee0000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003cf20000000000000000000000000000000000000000000000000000000000003cf40000000000000000000000000000000000000000000000000000000000003cf60000000000000000000000000000000000000000000000000000000000003cf80000000000000000000000000000000000000000000000000000000000003cfa0000000000000000000000000000000000000000000000000000000000003cfc0000000000000000000000000000000000000000000000000000000000003cfe0000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d020000000000000000000000000000000000000000000000000000000000003d040000000000000000000000000000000000000000000000000000000000003d060000000000000000000000000000000000000000000000000000000000003d080000000000000000000000000000000000000000000000000000000000003d0a0000000000000000000000000000000000000000000000000000000000003d0c0000000000000000000000000000000000000000000000000000000000003d0e0000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d120000000000000000000000000000000000000000000000000000000000003d140000000000000000000000000000000000000000000000000000000000003d160000000000000000000000000000000000000000000000000000000000003d180000000000000000000000000000000000000000000000000000000000003d1a0000000000000000000000000000000000000000000000000000000000003d1c0000000000000000000000000000000000000000000000000000000000003d1e0000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d220000000000000000000000000000000000000000000000000000000000003d240000000000000000000000000000000000000000000000000000000000003d260000000000000000000000000000000000000000000000000000000000003d280000000000000000000000000000000000000000000000000000000000003d2a0000000000000000000000000000000000000000000000000000000000003d2c0000000000000000000000000000000000000000000000000000000000003d2e0000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d320000000000000000000000000000000000000000000000000000000000003d340000000000000000000000000000000000000000000000000000000000003d360000000000000000000000000000000000000000000000000000000000003d380000000000000000000000000000000000000000000000000000000000003d3a0000000000000000000000000000000000000000000000000000000000003d3c0000000000000000000000000000000000000000000000000000000000003d3e0000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d420000000000000000000000000000000000000000000000000000000000003d440000000000000000000000000000000000000000000000000000000000003d460000000000000000000000000000000000000000000000000000000000003d480000000000000000000000000000000000000000000000000000000000003d4a0000000000000000000000000000000000000000000000000000000000003d4c0000000000000000000000000000000000000000000000000000000000003d4e0000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d520000000000000000000000000000000000000000000000000000000000003d540000000000000000000000000000000000000000000000000000000000003d560000000000000000000000000000000000000000000000000000000000003d580000000000000000000000000000000000000000000000000000000000003d5a0000000000000000000000000000000000000000000000000000000000003d5c0000000000000000000000000000000000000000000000000000000000003d5e0000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d620000000000000000000000000000000000000000000000000000000000003d640000000000000000000000000000000000000000000000000000000000003d660000000000000000000000000000000000000000000000000000000000003d680000000000000000000000000000000000000000000000000000000000003d6a0000000000000000000000000000000000000000000000000000000000003d6c0000000000000000000000000000000000000000000000000000000000003d6e0000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d720000000000000000000000000000000000000000000000000000000000003d740000000000000000000000000000000000000000000000000000000000003d760000000000000000000000000000000000000000000000000000000000003d780000000000000000000000000000000000000000000000000000000000003d7a0000000000000000000000000000000000000000000000000000000000003d7c0000000000000000000000000000000000000000000000000000000000003d7e0000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d820000000000000000000000000000000000000000000000000000000000003d840000000000000000000000000000000000000000000000000000000000003d860000000000000000000000000000000000000000000000000000000000003d880000000000000000000000000000000000000000000000000000000000003d8a0000000000000000000000000000000000000000000000000000000000003d8c0000000000000000000000000000000000000000000000000000000000003d8e0000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003d920000000000000000000000000000000000000000000000000000000000003d940000000000000000000000000000000000000000000000000000000000003d960000000000000000000000000000000000000000000000000000000000003d980000000000000000000000000000000000000000000000000000000000003d9a0000000000000000000000000000000000000000000000000000000000003d9c0000000000000000000000000000000000000000000000000000000000003d9e0000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003da20000000000000000000000000000000000000000000000000000000000003da40000000000000000000000000000000000000000000000000000000000003da60000000000000000000000000000000000000000000000000000000000003da80000000000000000000000000000000000000000000000000000000000003daa0000000000000000000000000000000000000000000000000000000000003dac0000000000000000000000000000000000000000000000000000000000003dae0000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003db20000000000000000000000000000000000000000000000000000000000003db40000000000000000000000000000000000000000000000000000000000003db60000000000000000000000000000000000000000000000000000000000003db80000000000000000000000000000000000000000000000000000000000003dba0000000000000000000000000000000000000000000000000000000000003dbc0000000000000000000000000000000000000000000000000000000000003dbe0000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dc20000000000000000000000000000000000000000000000000000000000003dc40000000000000000000000000000000000000000000000000000000000003dc60000000000000000000000000000000000000000000000000000000000003dc80000000000000000000000000000000000000000000000000000000000003dca0000000000000000000000000000000000000000000000000000000000003dcc0000000000000000000000000000000000000000000000000000000000003dce0000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003dd20000000000000000000000000000000000000000000000000000000000003dd40000000000000000000000000000000000000000000000000000000000003dd60000000000000000000000000000000000000000000000000000000000003dd80000000000000000000000000000000000000000000000000000000000003dda0000000000000000000000000000000000000000000000000000000000003ddc0000000000000000000000000000000000000000000000000000000000003dde0000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003de20000000000000000000000000000000000000000000000000000000000003de40000000000000000000000000000000000000000000000000000000000003de60000000000000000000000000000000000000000000000000000000000003de80000000000000000000000000000000000000000000000000000000000003dea0000000000000000000000000000000000000000000000000000000000003dec0000000000000000000000000000000000000000000000000000000000003dee0000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003df20000000000000000000000000000000000000000000000000000000000003df40000000000000000000000000000000000000000000000000000000000003df60000000000000000000000000000000000000000000000000000000000003df80000000000000000000000000000000000000000000000000000000000003dfa0000000000000000000000000000000000000000000000000000000000003dfc0000000000000000000000000000000000000000000000000000000000003dfe0000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e020000000000000000000000000000000000000000000000000000000000003e040000000000000000000000000000000000000000000000000000000000003e060000000000000000000000000000000000000000000000000000000000003e080000000000000000000000000000000000000000000000000000000000003e0a0000000000000000000000000000000000000000000000000000000000003e0c0000000000000000000000000000000000000000000000000000000000003e0e0000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e120000000000000000000000000000000000000000000000000000000000003e140000000000000000000000000000000000000000000000000000000000003e160000000000000000000000000000000000000000000000000000000000003e180000000000000000000000000000000000000000000000000000000000003e1a0000000000000000000000000000000000000000000000000000000000003e1c0000000000000000000000000000000000000000000000000000000000003e1e0000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e220000000000000000000000000000000000000000000000000000000000003e240000000000000000000000000000000000000000000000000000000000003e260000000000000000000000000000000000000000000000000000000000003e280000000000000000000000000000000000000000000000000000000000003e2a0000000000000000000000000000000000000000000000000000000000003e2c0000000000000000000000000000000000000000000000000000000000003e2e0000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e320000000000000000000000000000000000000000000000000000000000003e340000000000000000000000000000000000000000000000000000000000003e360000000000000000000000000000000000000000000000000000000000003e380000000000000000000000000000000000000000000000000000000000003e3a0000000000000000000000000000000000000000000000000000000000003e3c0000000000000000000000000000000000000000000000000000000000003e3e0000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e420000000000000000000000000000000000000000000000000000000000003e440000000000000000000000000000000000000000000000000000000000003e460000000000000000000000000000000000000000000000000000000000003e480000000000000000000000000000000000000000000000000000000000003e4a0000000000000000000000000000000000000000000000000000000000003e4c0000000000000000000000000000000000000000000000000000000000003e4e0000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e520000000000000000000000000000000000000000000000000000000000003e540000000000000000000000000000000000000000000000000000000000003e560000000000000000000000000000000000000000000000000000000000003e580000000000000000000000000000000000000000000000000000000000003e5a0000000000000000000000000000000000000000000000000000000000003e5c0000000000000000000000000000000000000000000000000000000000003e5e0000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e620000000000000000000000000000000000000000000000000000000000003e640000000000000000000000000000000000000000000000000000000000003e660000000000000000000000000000000000000000000000000000000000003e680000000000000000000000000000000000000000000000000000000000003e6a0000000000000000000000000000000000000000000000000000000000003e6c0000000000000000000000000000000000000000000000000000000000003e6e0000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e720000000000000000000000000000000000000000000000000000000000003e740000000000000000000000000000000000000000000000000000000000003e760000000000000000000000000000000000000000000000000000000000003e780000000000000000000000000000000000000000000000000000000000003e7a0000000000000000000000000000000000000000000000000000000000003e7c0000000000000000000000000000000000000000000000000000000000003e7e0000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e820000000000000000000000000000000000000000000000000000000000003e840000000000000000000000000000000000000000000000000000000000003e860000000000000000000000000000000000000000000000000000000000003e880000000000000000000000000000000000000000000000000000000000003e8a0000000000000000000000000000000000000000000000000000000000003e8c0000000000000000000000000000000000000000000000000000000000003e8e0000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003e920000000000000000000000000000000000000000000000000000000000003e940000000000000000000000000000000000000000000000000000000000003e960000000000000000000000000000000000000000000000000000000000003e980000000000000000000000000000000000000000000000000000000000003e9a0000000000000000000000000000000000000000000000000000000000003e9c0000000000000000000000000000000000000000000000000000000000003e9e0000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003ea20000000000000000000000000000000000000000000000000000000000003ea40000000000000000000000000000000000000000000000000000000000003ea60000000000000000000000000000000000000000000000000000000000003ea80000000000000000000000000000000000000000000000000000000000003eaa0000000000000000000000000000000000000000000000000000000000003eac0000000000000000000000000000000000000000000000000000000000003eae0000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003eb20000000000000000000000000000000000000000000000000000000000003eb40000000000000000000000000000000000000000000000000000000000003eb60000000000000000000000000000000000000000000000000000000000003eb80000000000000000000000000000000000000000000000000000000000003eba0000000000000000000000000000000000000000000000000000000000003ebc0000000000000000000000000000000000000000000000000000000000003ebe0000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ec20000000000000000000000000000000000000000000000000000000000003ec40000000000000000000000000000000000000000000000000000000000003ec60000000000000000000000000000000000000000000000000000000000003ec80000000000000000000000000000000000000000000000000000000000003eca0000000000000000000000000000000000000000000000000000000000003ecc0000000000000000000000000000000000000000000000000000000000003ece0000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ed20000000000000000000000000000000000000000000000000000000000003ed40000000000000000000000000000000000000000000000000000000000003ed60000000000000000000000000000000000000000000000000000000000003ed80000000000000000000000000000000000000000000000000000000000003eda0000000000000000000000000000000000000000000000000000000000003edc0000000000000000000000000000000000000000000000000000000000003ede0000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ee20000000000000000000000000000000000000000000000000000000000003ee40000000000000000000000000000000000000000000000000000000000003ee60000000000000000000000000000000000000000000000000000000000003ee80000000000000000000000000000000000000000000000000000000000003eea0000000000000000000000000000000000000000000000000000000000003eec0000000000000000000000000000000000000000000000000000000000003eee0000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003ef20000000000000000000000000000000000000000000000000000000000003ef40000000000000000000000000000000000000000000000000000000000003ef60000000000000000000000000000000000000000000000000000000000003ef80000000000000000000000000000000000000000000000000000000000003efa0000000000000000000000000000000000000000000000000000000000003efc0000000000000000000000000000000000000000000000000000000000003efe0000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f020000000000000000000000000000000000000000000000000000000000003f040000000000000000000000000000000000000000000000000000000000003f060000000000000000000000000000000000000000000000000000000000003f080000000000000000000000000000000000000000000000000000000000003f0a0000000000000000000000000000000000000000000000000000000000003f0c0000000000000000000000000000000000000000000000000000000000003f0e0000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f120000000000000000000000000000000000000000000000000000000000003f140000000000000000000000000000000000000000000000000000000000003f160000000000000000000000000000000000000000000000000000000000003f180000000000000000000000000000000000000000000000000000000000003f1a0000000000000000000000000000000000000000000000000000000000003f1c0000000000000000000000000000000000000000000000000000000000003f1e0000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f220000000000000000000000000000000000000000000000000000000000003f240000000000000000000000000000000000000000000000000000000000003f260000000000000000000000000000000000000000000000000000000000003f280000000000000000000000000000000000000000000000000000000000003f2a0000000000000000000000000000000000000000000000000000000000003f2c0000000000000000000000000000000000000000000000000000000000003f2e0000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f320000000000000000000000000000000000000000000000000000000000003f340000000000000000000000000000000000000000000000000000000000003f360000000000000000000000000000000000000000000000000000000000003f380000000000000000000000000000000000000000000000000000000000003f3a0000000000000000000000000000000000000000000000000000000000003f3c0000000000000000000000000000000000000000000000000000000000003f3e0000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f420000000000000000000000000000000000000000000000000000000000003f440000000000000000000000000000000000000000000000000000000000003f460000000000000000000000000000000000000000000000000000000000003f480000000000000000000000000000000000000000000000000000000000003f4a0000000000000000000000000000000000000000000000000000000000003f4c0000000000000000000000000000000000000000000000000000000000003f4e0000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f520000000000000000000000000000000000000000000000000000000000003f540000000000000000000000000000000000000000000000000000000000003f560000000000000000000000000000000000000000000000000000000000003f580000000000000000000000000000000000000000000000000000000000003f5a0000000000000000000000000000000000000000000000000000000000003f5c0000000000000000000000000000000000000000000000000000000000003f5e0000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f620000000000000000000000000000000000000000000000000000000000003f640000000000000000000000000000000000000000000000000000000000003f660000000000000000000000000000000000000000000000000000000000003f680000000000000000000000000000000000000000000000000000000000003f6a0000000000000000000000000000000000000000000000000000000000003f6c0000000000000000000000000000000000000000000000000000000000003f6e0000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f720000000000000000000000000000000000000000000000000000000000003f740000000000000000000000000000000000000000000000000000000000003f760000000000000000000000000000000000000000000000000000000000003f780000000000000000000000000000000000000000000000000000000000003f7a0000000000000000000000000000000000000000000000000000000000003f7c0000000000000000000000000000000000000000000000000000000000003f7e0000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f820000000000000000000000000000000000000000000000000000000000003f840000000000000000000000000000000000000000000000000000000000003f860000000000000000000000000000000000000000000000000000000000003f880000000000000000000000000000000000000000000000000000000000003f8a0000000000000000000000000000000000000000000000000000000000003f8c0000000000000000000000000000000000000000000000000000000000003f8e0000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003f920000000000000000000000000000000000000000000000000000000000003f940000000000000000000000000000000000000000000000000000000000003f960000000000000000000000000000000000000000000000000000000000003f980000000000000000000000000000000000000000000000000000000000003f9a0000000000000000000000000000000000000000000000000000000000003f9c0000000000000000000000000000000000000000000000000000000000003f9e0000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fa20000000000000000000000000000000000000000000000000000000000003fa40000000000000000000000000000000000000000000000000000000000003fa60000000000000000000000000000000000000000000000000000000000003fa80000000000000000000000000000000000000000000000000000000000003faa0000000000000000000000000000000000000000000000000000000000003fac0000000000000000000000000000000000000000000000000000000000003fae0000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fb20000000000000000000000000000000000000000000000000000000000003fb40000000000000000000000000000000000000000000000000000000000003fb60000000000000000000000000000000000000000000000000000000000003fb80000000000000000000000000000000000000000000000000000000000003fba0000000000000000000000000000000000000000000000000000000000003fbc0000000000000000000000000000000000000000000000000000000000003fbe0000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fc20000000000000000000000000000000000000000000000000000000000003fc40000000000000000000000000000000000000000000000000000000000003fc60000000000000000000000000000000000000000000000000000000000003fc80000000000000000000000000000000000000000000000000000000000003fca0000000000000000000000000000000000000000000000000000000000003fcc0000000000000000000000000000000000000000000000000000000000003fce0000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fd20000000000000000000000000000000000000000000000000000000000003fd40000000000000000000000000000000000000000000000000000000000003fd60000000000000000000000000000000000000000000000000000000000003fd80000000000000000000000000000000000000000000000000000000000003fda0000000000000000000000000000000000000000000000000000000000003fdc0000000000000000000000000000000000000000000000000000000000003fde0000000000000000000000000000000000000000000000000000000000003fe00000000000000000000000000000000000000000000000000000000000003fe20000000000000000000000000000000000000000000000000000000000003fe40000000000000000000000000000000000000000000000000000000000003fe60000000000000000000000000000000000000000000000000000000000003fe80000000000000000000000000000000000000000000000000000000000003fea0000000000000000000000000000000000000000000000000000000000003fec0000000000000000000000000000000000000000000000000000000000003fee0000000000000000000000000000000000000000000000000000000000003ff00000000000000000000000000000000000000000000000000000000000003ff20000000000000000000000000000000000000000000000000000000000003ff40000000000000000000000000000000000000000000000000000000000003ff60000000000000000000000000000000000000000000000000000000000003ff80000000000000000000000000000000000000000000000000000000000003ffa0000000000000000000000000000000000000000000000000000000000003ffc0000000000000000000000000000000000000000000000000000000000003ffe00000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004002000000000000000000000000000000000000000000000000000000000000400400000000000000000000000000000000000000000000000000000000000040060000000000000000000000000000000000000000000000000000000000004008000000000000000000000000000000000000000000000000000000000000400a000000000000000000000000000000000000000000000000000000000000400c000000000000000000000000000000000000000000000000000000000000400e00000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004012000000000000000000000000000000000000000000000000000000000000401400000000000000000000000000000000000000000000000000000000000040160000000000000000000000000000000000000000000000000000000000004018000000000000000000000000000000000000000000000000000000000000401a000000000000000000000000000000000000000000000000000000000000401c000000000000000000000000000000000000000000000000000000000000401e00000000000000000000000000000000000000000000000000000000000040200000000000000000000000000000000000000000000000000000000000004022000000000000000000000000000000000000000000000000000000000000402400000000000000000000000000000000000000000000000000000000000040260000000000000000000000000000000000000000000000000000000000004028000000000000000000000000000000000000000000000000000000000000402a000000000000000000000000000000000000000000000000000000000000402c000000000000000000000000000000000000000000000000000000000000402e00000000000000000000000000000000000000000000000000000000000040300000000000000000000000000000000000000000000000000000000000004032000000000000000000000000000000000000000000000000000000000000403400000000000000000000000000000000000000000000000000000000000040360000000000000000000000000000000000000000000000000000000000004038000000000000000000000000000000000000000000000000000000000000403a000000000000000000000000000000000000000000000000000000000000403c000000000000000000000000000000000000000000000000000000000000403e00000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004042000000000000000000000000000000000000000000000000000000000000404400000000000000000000000000000000000000000000000000000000000040460000000000000000000000000000000000000000000000000000000000004048000000000000000000000000000000000000000000000000000000000000404a000000000000000000000000000000000000000000000000000000000000404c000000000000000000000000000000000000000000000000000000000000404e00000000000000000000000000000000000000000000000000000000000040500000000000000000000000000000000000000000000000000000000000004052000000000000000000000000000000000000000000000000000000000000405400000000000000000000000000000000000000000000000000000000000040560000000000000000000000000000000000000000000000000000000000004058000000000000000000000000000000000000000000000000000000000000405a000000000000000000000000000000000000000000000000000000000000405c000000000000000000000000000000000000000000000000000000000000405e00000000000000000000000000000000000000000000000000000000000040600000000000000000000000000000000000000000000000000000000000004062000000000000000000000000000000000000000000000000000000000000406400000000000000000000000000000000000000000000000000000000000040660000000000000000000000000000000000000000000000000000000000004068000000000000000000000000000000000000000000000000000000000000406a000000000000000000000000000000000000000000000000000000000000406c000000000000000000000000000000000000000000000000000000000000406e00000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004072000000000000000000000000000000000000000000000000000000000000407400000000000000000000000000000000000000000000000000000000000040760000000000000000000000000000000000000000000000000000000000004078000000000000000000000000000000000000000000000000000000000000407a000000000000000000000000000000000000000000000000000000000000407c000000000000000000000000000000000000000000000000000000000000407e00000000000000000000000000000000000000000000000000000000000040800000000000000000000000000000000000000000000000000000000000004082000000000000000000000000000000000000000000000000000000000000408400000000000000000000000000000000000000000000000000000000000040860000000000000000000000000000000000000000000000000000000000004088000000000000000000000000000000000000000000000000000000000000408a000000000000000000000000000000000000000000000000000000000000408c000000000000000000000000000000000000000000000000000000000000408e00000000000000000000000000000000000000000000000000000000000040900000000000000000000000000000000000000000000000000000000000004092000000000000000000000000000000000000000000000000000000000000409400000000000000000000000000000000000000000000000000000000000040960000000000000000000000000000000000000000000000000000000000004098000000000000000000000000000000000000000000000000000000000000409a000000000000000000000000000000000000000000000000000000000000409c000000000000000000000000000000000000000000000000000000000000409e00000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040a200000000000000000000000000000000000000000000000000000000000040a400000000000000000000000000000000000000000000000000000000000040a600000000000000000000000000000000000000000000000000000000000040a800000000000000000000000000000000000000000000000000000000000040aa00000000000000000000000000000000000000000000000000000000000040ac00000000000000000000000000000000000000000000000000000000000040ae00000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040b200000000000000000000000000000000000000000000000000000000000040b400000000000000000000000000000000000000000000000000000000000040b600000000000000000000000000000000000000000000000000000000000040b800000000000000000000000000000000000000000000000000000000000040ba00000000000000000000000000000000000000000000000000000000000040bc00000000000000000000000000000000000000000000000000000000000040be00000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040c200000000000000000000000000000000000000000000000000000000000040c400000000000000000000000000000000000000000000000000000000000040c600000000000000000000000000000000000000000000000000000000000040c800000000000000000000000000000000000000000000000000000000000040ca00000000000000000000000000000000000000000000000000000000000040cc00000000000000000000000000000000000000000000000000000000000040ce00000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040d200000000000000000000000000000000000000000000000000000000000040d400000000000000000000000000000000000000000000000000000000000040d600000000000000000000000000000000000000000000000000000000000040d800000000000000000000000000000000000000000000000000000000000040da00000000000000000000000000000000000000000000000000000000000040dc00000000000000000000000000000000000000000000000000000000000040de00000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040e200000000000000000000000000000000000000000000000000000000000040e400000000000000000000000000000000000000000000000000000000000040e600000000000000000000000000000000000000000000000000000000000040e800000000000000000000000000000000000000000000000000000000000040ea00000000000000000000000000000000000000000000000000000000000040ec00000000000000000000000000000000000000000000000000000000000040ee00000000000000000000000000000000000000000000000000000000000040f000000000000000000000000000000000000000000000000000000000000040f200000000000000000000000000000000000000000000000000000000000040f400000000000000000000000000000000000000000000000000000000000040f600000000000000000000000000000000000000000000000000000000000040f800000000000000000000000000000000000000000000000000000000000040fa00000000000000000000000000000000000000000000000000000000000040fc00000000000000000000000000000000000000000000000000000000000040fe00000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000004102000000000000000000000000000000000000000000000000000000000000410400000000000000000000000000000000000000000000000000000000000041060000000000000000000000000000000000000000000000000000000000004108000000000000000000000000000000000000000000000000000000000000410a000000000000000000000000000000000000000000000000000000000000410c000000000000000000000000000000000000000000000000000000000000410e00000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004112000000000000000000000000000000000000000000000000000000000000411400000000000000000000000000000000000000000000000000000000000041160000000000000000000000000000000000000000000000000000000000004118000000000000000000000000000000000000000000000000000000000000411a000000000000000000000000000000000000000000000000000000000000411c000000000000000000000000000000000000000000000000000000000000411e00000000000000000000000000000000000000000000000000000000000041200000000000000000000000000000000000000000000000000000000000004122000000000000000000000000000000000000000000000000000000000000412400000000000000000000000000000000000000000000000000000000000041260000000000000000000000000000000000000000000000000000000000004128000000000000000000000000000000000000000000000000000000000000412a000000000000000000000000000000000000000000000000000000000000412c000000000000000000000000000000000000000000000000000000000000412e00000000000000000000000000000000000000000000000000000000000041300000000000000000000000000000000000000000000000000000000000004132000000000000000000000000000000000000000000000000000000000000413400000000000000000000000000000000000000000000000000000000000041360000000000000000000000000000000000000000000000000000000000004138000000000000000000000000000000000000000000000000000000000000413a000000000000000000000000000000000000000000000000000000000000413c000000000000000000000000000000000000000000000000000000000000413e00000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004142000000000000000000000000000000000000000000000000000000000000414400000000000000000000000000000000000000000000000000000000000041460000000000000000000000000000000000000000000000000000000000004148000000000000000000000000000000000000000000000000000000000000414a000000000000000000000000000000000000000000000000000000000000414c000000000000000000000000000000000000000000000000000000000000414e00000000000000000000000000000000000000000000000000000000000041500000000000000000000000000000000000000000000000000000000000004152000000000000000000000000000000000000000000000000000000000000415400000000000000000000000000000000000000000000000000000000000041560000000000000000000000000000000000000000000000000000000000004158000000000000000000000000000000000000000000000000000000000000415a000000000000000000000000000000000000000000000000000000000000415c000000000000000000000000000000000000000000000000000000000000415e00000000000000000000000000000000000000000000000000000000000041600000000000000000000000000000000000000000000000000000000000004162000000000000000000000000000000000000000000000000000000000000416400000000000000000000000000000000000000000000000000000000000041660000000000000000000000000000000000000000000000000000000000004168000000000000000000000000000000000000000000000000000000000000416a000000000000000000000000000000000000000000000000000000000000416c000000000000000000000000000000000000000000000000000000000000416e00000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004172000000000000000000000000000000000000000000000000000000000000417400000000000000000000000000000000000000000000000000000000000041760000000000000000000000000000000000000000000000000000000000004178000000000000000000000000000000000000000000000000000000000000417a000000000000000000000000000000000000000000000000000000000000417c000000000000000000000000000000000000000000000000000000000000417e00000000000000000000000000000000000000000000000000000000000041800000000000000000000000000000000000000000000000000000000000004182000000000000000000000000000000000000000000000000000000000000418400000000000000000000000000000000000000000000000000000000000041860000000000000000000000000000000000000000000000000000000000004188000000000000000000000000000000000000000000000000000000000000418a000000000000000000000000000000000000000000000000000000000000418c000000000000000000000000000000000000000000000000000000000000418e00000000000000000000000000000000000000000000000000000000000041900000000000000000000000000000000000000000000000000000000000004192000000000000000000000000000000000000000000000000000000000000419400000000000000000000000000000000000000000000000000000000000041960000000000000000000000000000000000000000000000000000000000004198000000000000000000000000000000000000000000000000000000000000419a000000000000000000000000000000000000000000000000000000000000419c000000000000000000000000000000000000000000000000000000000000419e00000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041a200000000000000000000000000000000000000000000000000000000000041a400000000000000000000000000000000000000000000000000000000000041a600000000000000000000000000000000000000000000000000000000000041a800000000000000000000000000000000000000000000000000000000000041aa00000000000000000000000000000000000000000000000000000000000041ac00000000000000000000000000000000000000000000000000000000000041ae00000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041b200000000000000000000000000000000000000000000000000000000000041b400000000000000000000000000000000000000000000000000000000000041b600000000000000000000000000000000000000000000000000000000000041b800000000000000000000000000000000000000000000000000000000000041ba00000000000000000000000000000000000000000000000000000000000041bc00000000000000000000000000000000000000000000000000000000000041be00000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041c200000000000000000000000000000000000000000000000000000000000041c400000000000000000000000000000000000000000000000000000000000041c600000000000000000000000000000000000000000000000000000000000041c800000000000000000000000000000000000000000000000000000000000041ca00000000000000000000000000000000000000000000000000000000000041cc00000000000000000000000000000000000000000000000000000000000041ce00000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041d200000000000000000000000000000000000000000000000000000000000041d400000000000000000000000000000000000000000000000000000000000041d600000000000000000000000000000000000000000000000000000000000041d800000000000000000000000000000000000000000000000000000000000041da00000000000000000000000000000000000000000000000000000000000041dc00000000000000000000000000000000000000000000000000000000000041de00000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041e200000000000000000000000000000000000000000000000000000000000041e400000000000000000000000000000000000000000000000000000000000041e600000000000000000000000000000000000000000000000000000000000041e800000000000000000000000000000000000000000000000000000000000041ea00000000000000000000000000000000000000000000000000000000000041ec00000000000000000000000000000000000000000000000000000000000041ee00000000000000000000000000000000000000000000000000000000000041f000000000000000000000000000000000000000000000000000000000000041f200000000000000000000000000000000000000000000000000000000000041f400000000000000000000000000000000000000000000000000000000000041f600000000000000000000000000000000000000000000000000000000000041f800000000000000000000000000000000000000000000000000000000000041fa00000000000000000000000000000000000000000000000000000000000041fc00000000000000000000000000000000000000000000000000000000000041fe00000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004202000000000000000000000000000000000000000000000000000000000000420400000000000000000000000000000000000000000000000000000000000042060000000000000000000000000000000000000000000000000000000000004208000000000000000000000000000000000000000000000000000000000000420a000000000000000000000000000000000000000000000000000000000000420c000000000000000000000000000000000000000000000000000000000000420e00000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004212000000000000000000000000000000000000000000000000000000000000421400000000000000000000000000000000000000000000000000000000000042160000000000000000000000000000000000000000000000000000000000004218000000000000000000000000000000000000000000000000000000000000421a000000000000000000000000000000000000000000000000000000000000421c000000000000000000000000000000000000000000000000000000000000421e00000000000000000000000000000000000000000000000000000000000042200000000000000000000000000000000000000000000000000000000000004222000000000000000000000000000000000000000000000000000000000000422400000000000000000000000000000000000000000000000000000000000042260000000000000000000000000000000000000000000000000000000000004228000000000000000000000000000000000000000000000000000000000000422a000000000000000000000000000000000000000000000000000000000000422c000000000000000000000000000000000000000000000000000000000000422e00000000000000000000000000000000000000000000000000000000000042300000000000000000000000000000000000000000000000000000000000004232000000000000000000000000000000000000000000000000000000000000423400000000000000000000000000000000000000000000000000000000000042360000000000000000000000000000000000000000000000000000000000004238000000000000000000000000000000000000000000000000000000000000423a000000000000000000000000000000000000000000000000000000000000423c000000000000000000000000000000000000000000000000000000000000423e00000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004242000000000000000000000000000000000000000000000000000000000000424400000000000000000000000000000000000000000000000000000000000042460000000000000000000000000000000000000000000000000000000000004248000000000000000000000000000000000000000000000000000000000000424a000000000000000000000000000000000000000000000000000000000000424c000000000000000000000000000000000000000000000000000000000000424e00000000000000000000000000000000000000000000000000000000000042500000000000000000000000000000000000000000000000000000000000004252000000000000000000000000000000000000000000000000000000000000425400000000000000000000000000000000000000000000000000000000000042560000000000000000000000000000000000000000000000000000000000004258000000000000000000000000000000000000000000000000000000000000425a000000000000000000000000000000000000000000000000000000000000425c000000000000000000000000000000000000000000000000000000000000425e00000000000000000000000000000000000000000000000000000000000042600000000000000000000000000000000000000000000000000000000000004262000000000000000000000000000000000000000000000000000000000000426400000000000000000000000000000000000000000000000000000000000042660000000000000000000000000000000000000000000000000000000000004268000000000000000000000000000000000000000000000000000000000000426a000000000000000000000000000000000000000000000000000000000000426c000000000000000000000000000000000000000000000000000000000000426e00000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004272000000000000000000000000000000000000000000000000000000000000427400000000000000000000000000000000000000000000000000000000000042760000000000000000000000000000000000000000000000000000000000004278000000000000000000000000000000000000000000000000000000000000427a000000000000000000000000000000000000000000000000000000000000427c000000000000000000000000000000000000000000000000000000000000427e00000000000000000000000000000000000000000000000000000000000042800000000000000000000000000000000000000000000000000000000000004282000000000000000000000000000000000000000000000000000000000000428400000000000000000000000000000000000000000000000000000000000042860000000000000000000000000000000000000000000000000000000000004288000000000000000000000000000000000000000000000000000000000000428a000000000000000000000000000000000000000000000000000000000000428c000000000000000000000000000000000000000000000000000000000000428e00000000000000000000000000000000000000000000000000000000000042900000000000000000000000000000000000000000000000000000000000004292000000000000000000000000000000000000000000000000000000000000429400000000000000000000000000000000000000000000000000000000000042960000000000000000000000000000000000000000000000000000000000004298000000000000000000000000000000000000000000000000000000000000429a000000000000000000000000000000000000000000000000000000000000429c000000000000000000000000000000000000000000000000000000000000429e00000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042a200000000000000000000000000000000000000000000000000000000000042a400000000000000000000000000000000000000000000000000000000000042a600000000000000000000000000000000000000000000000000000000000042a800000000000000000000000000000000000000000000000000000000000042aa00000000000000000000000000000000000000000000000000000000000042ac00000000000000000000000000000000000000000000000000000000000042ae00000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042b200000000000000000000000000000000000000000000000000000000000042b400000000000000000000000000000000000000000000000000000000000042b600000000000000000000000000000000000000000000000000000000000042b800000000000000000000000000000000000000000000000000000000000042ba00000000000000000000000000000000000000000000000000000000000042bc00000000000000000000000000000000000000000000000000000000000042be00000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042c200000000000000000000000000000000000000000000000000000000000042c400000000000000000000000000000000000000000000000000000000000042c600000000000000000000000000000000000000000000000000000000000042c800000000000000000000000000000000000000000000000000000000000042ca00000000000000000000000000000000000000000000000000000000000042cc00000000000000000000000000000000000000000000000000000000000042ce00000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042d200000000000000000000000000000000000000000000000000000000000042d400000000000000000000000000000000000000000000000000000000000042d600000000000000000000000000000000000000000000000000000000000042d800000000000000000000000000000000000000000000000000000000000042da00000000000000000000000000000000000000000000000000000000000042dc00000000000000000000000000000000000000000000000000000000000042de00000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042e200000000000000000000000000000000000000000000000000000000000042e400000000000000000000000000000000000000000000000000000000000042e600000000000000000000000000000000000000000000000000000000000042e800000000000000000000000000000000000000000000000000000000000042ea00000000000000000000000000000000000000000000000000000000000042ec00000000000000000000000000000000000000000000000000000000000042ee00000000000000000000000000000000000000000000000000000000000042f000000000000000000000000000000000000000000000000000000000000042f200000000000000000000000000000000000000000000000000000000000042f400000000000000000000000000000000000000000000000000000000000042f600000000000000000000000000000000000000000000000000000000000042f800000000000000000000000000000000000000000000000000000000000042fa00000000000000000000000000000000000000000000000000000000000042fc00000000000000000000000000000000000000000000000000000000000042fe00000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000004302000000000000000000000000000000000000000000000000000000000000430400000000000000000000000000000000000000000000000000000000000043060000000000000000000000000000000000000000000000000000000000004308000000000000000000000000000000000000000000000000000000000000430a000000000000000000000000000000000000000000000000000000000000430c000000000000000000000000000000000000000000000000000000000000430e00000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004312000000000000000000000000000000000000000000000000000000000000431400000000000000000000000000000000000000000000000000000000000043160000000000000000000000000000000000000000000000000000000000004318000000000000000000000000000000000000000000000000000000000000431a000000000000000000000000000000000000000000000000000000000000431c000000000000000000000000000000000000000000000000000000000000431e00000000000000000000000000000000000000000000000000000000000043200000000000000000000000000000000000000000000000000000000000004322000000000000000000000000000000000000000000000000000000000000432400000000000000000000000000000000000000000000000000000000000043260000000000000000000000000000000000000000000000000000000000004328000000000000000000000000000000000000000000000000000000000000432a000000000000000000000000000000000000000000000000000000000000432c000000000000000000000000000000000000000000000000000000000000432e00000000000000000000000000000000000000000000000000000000000043300000000000000000000000000000000000000000000000000000000000004332000000000000000000000000000000000000000000000000000000000000433400000000000000000000000000000000000000000000000000000000000043360000000000000000000000000000000000000000000000000000000000004338000000000000000000000000000000000000000000000000000000000000433a000000000000000000000000000000000000000000000000000000000000433c000000000000000000000000000000000000000000000000000000000000433e00000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004342000000000000000000000000000000000000000000000000000000000000434400000000000000000000000000000000000000000000000000000000000043460000000000000000000000000000000000000000000000000000000000004348000000000000000000000000000000000000000000000000000000000000434a000000000000000000000000000000000000000000000000000000000000434c000000000000000000000000000000000000000000000000000000000000434e00000000000000000000000000000000000000000000000000000000000043500000000000000000000000000000000000000000000000000000000000004352000000000000000000000000000000000000000000000000000000000000435400000000000000000000000000000000000000000000000000000000000043560000000000000000000000000000000000000000000000000000000000004358000000000000000000000000000000000000000000000000000000000000435a000000000000000000000000000000000000000000000000000000000000435c000000000000000000000000000000000000000000000000000000000000435e00000000000000000000000000000000000000000000000000000000000043600000000000000000000000000000000000000000000000000000000000004362000000000000000000000000000000000000000000000000000000000000436400000000000000000000000000000000000000000000000000000000000043660000000000000000000000000000000000000000000000000000000000004368000000000000000000000000000000000000000000000000000000000000436a000000000000000000000000000000000000000000000000000000000000436c000000000000000000000000000000000000000000000000000000000000436e00000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004372000000000000000000000000000000000000000000000000000000000000437400000000000000000000000000000000000000000000000000000000000043760000000000000000000000000000000000000000000000000000000000004378000000000000000000000000000000000000000000000000000000000000437a000000000000000000000000000000000000000000000000000000000000437c000000000000000000000000000000000000000000000000000000000000437e00000000000000000000000000000000000000000000000000000000000043800000000000000000000000000000000000000000000000000000000000004382000000000000000000000000000000000000000000000000000000000000438400000000000000000000000000000000000000000000000000000000000043860000000000000000000000000000000000000000000000000000000000004388000000000000000000000000000000000000000000000000000000000000438a000000000000000000000000000000000000000000000000000000000000438c000000000000000000000000000000000000000000000000000000000000438e00000000000000000000000000000000000000000000000000000000000043900000000000000000000000000000000000000000000000000000000000004392000000000000000000000000000000000000000000000000000000000000439400000000000000000000000000000000000000000000000000000000000043960000000000000000000000000000000000000000000000000000000000004398000000000000000000000000000000000000000000000000000000000000439a000000000000000000000000000000000000000000000000000000000000439c000000000000000000000000000000000000000000000000000000000000439e00000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043a200000000000000000000000000000000000000000000000000000000000043a400000000000000000000000000000000000000000000000000000000000043a600000000000000000000000000000000000000000000000000000000000043a800000000000000000000000000000000000000000000000000000000000043aa00000000000000000000000000000000000000000000000000000000000043ac00000000000000000000000000000000000000000000000000000000000043ae00000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043b200000000000000000000000000000000000000000000000000000000000043b400000000000000000000000000000000000000000000000000000000000043b600000000000000000000000000000000000000000000000000000000000043b800000000000000000000000000000000000000000000000000000000000043ba00000000000000000000000000000000000000000000000000000000000043bc00000000000000000000000000000000000000000000000000000000000043be00000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043c200000000000000000000000000000000000000000000000000000000000043c400000000000000000000000000000000000000000000000000000000000043c600000000000000000000000000000000000000000000000000000000000043c800000000000000000000000000000000000000000000000000000000000043ca00000000000000000000000000000000000000000000000000000000000043cc00000000000000000000000000000000000000000000000000000000000043ce00000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043d200000000000000000000000000000000000000000000000000000000000043d400000000000000000000000000000000000000000000000000000000000043d600000000000000000000000000000000000000000000000000000000000043d800000000000000000000000000000000000000000000000000000000000043da00000000000000000000000000000000000000000000000000000000000043dc00000000000000000000000000000000000000000000000000000000000043de00000000000000000000000000000000000000000000000000000000000043e000000000000000000000000000000000000000000000000000000000000043e200000000000000000000000000000000000000000000000000000000000043e400000000000000000000000000000000000000000000000000000000000043e600000000000000000000000000000000000000000000000000000000000043e800000000000000000000000000000000000000000000000000000000000043ea00000000000000000000000000000000000000000000000000000000000043ec00000000000000000000000000000000000000000000000000000000000043ee00000000000000000000000000000000000000000000000000000000000043f000000000000000000000000000000000000000000000000000000000000043f200000000000000000000000000000000000000000000000000000000000043f400000000000000000000000000000000000000000000000000000000000043f600000000000000000000000000000000000000000000000000000000000043f800000000000000000000000000000000000000000000000000000000000043fa00000000000000000000000000000000000000000000000000000000000043fc00000000000000000000000000000000000000000000000000000000000043fe00000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004402000000000000000000000000000000000000000000000000000000000000440400000000000000000000000000000000000000000000000000000000000044060000000000000000000000000000000000000000000000000000000000004408000000000000000000000000000000000000000000000000000000000000440a000000000000000000000000000000000000000000000000000000000000440c000000000000000000000000000000000000000000000000000000000000440e00000000000000000000000000000000000000000000000000000000000044100000000000000000000000000000000000000000000000000000000000004412000000000000000000000000000000000000000000000000000000000000441400000000000000000000000000000000000000000000000000000000000044160000000000000000000000000000000000000000000000000000000000004418000000000000000000000000000000000000000000000000000000000000441a000000000000000000000000000000000000000000000000000000000000441c000000000000000000000000000000000000000000000000000000000000441e00000000000000000000000000000000000000000000000000000000000044200000000000000000000000000000000000000000000000000000000000004422000000000000000000000000000000000000000000000000000000000000442400000000000000000000000000000000000000000000000000000000000044260000000000000000000000000000000000000000000000000000000000004428000000000000000000000000000000000000000000000000000000000000442a000000000000000000000000000000000000000000000000000000000000442c000000000000000000000000000000000000000000000000000000000000442e00000000000000000000000000000000000000000000000000000000000044300000000000000000000000000000000000000000000000000000000000004432000000000000000000000000000000000000000000000000000000000000443400000000000000000000000000000000000000000000000000000000000044360000000000000000000000000000000000000000000000000000000000004438000000000000000000000000000000000000000000000000000000000000443a000000000000000000000000000000000000000000000000000000000000443c000000000000000000000000000000000000000000000000000000000000443e00000000000000000000000000000000000000000000000000000000000044400000000000000000000000000000000000000000000000000000000000004442000000000000000000000000000000000000000000000000000000000000444400000000000000000000000000000000000000000000000000000000000044460000000000000000000000000000000000000000000000000000000000004448000000000000000000000000000000000000000000000000000000000000444a000000000000000000000000000000000000000000000000000000000000444c000000000000000000000000000000000000000000000000000000000000444e00000000000000000000000000000000000000000000000000000000000044500000000000000000000000000000000000000000000000000000000000004452000000000000000000000000000000000000000000000000000000000000445400000000000000000000000000000000000000000000000000000000000044560000000000000000000000000000000000000000000000000000000000004458000000000000000000000000000000000000000000000000000000000000445a000000000000000000000000000000000000000000000000000000000000445c000000000000000000000000000000000000000000000000000000000000445e00000000000000000000000000000000000000000000000000000000000044600000000000000000000000000000000000000000000000000000000000004462000000000000000000000000000000000000000000000000000000000000446400000000000000000000000000000000000000000000000000000000000044660000000000000000000000000000000000000000000000000000000000004468000000000000000000000000000000000000000000000000000000000000446a000000000000000000000000000000000000000000000000000000000000446c000000000000000000000000000000000000000000000000000000000000446e00000000000000000000000000000000000000000000000000000000000044700000000000000000000000000000000000000000000000000000000000004472000000000000000000000000000000000000000000000000000000000000447400000000000000000000000000000000000000000000000000000000000044760000000000000000000000000000000000000000000000000000000000004478000000000000000000000000000000000000000000000000000000000000447a000000000000000000000000000000000000000000000000000000000000447c000000000000000000000000000000000000000000000000000000000000447e00000000000000000000000000000000000000000000000000000000000044800000000000000000000000000000000000000000000000000000000000004482000000000000000000000000000000000000000000000000000000000000448400000000000000000000000000000000000000000000000000000000000044860000000000000000000000000000000000000000000000000000000000004488000000000000000000000000000000000000000000000000000000000000448a000000000000000000000000000000000000000000000000000000000000448c000000000000000000000000000000000000000000000000000000000000448e00000000000000000000000000000000000000000000000000000000000044900000000000000000000000000000000000000000000000000000000000004492000000000000000000000000000000000000000000000000000000000000449400000000000000000000000000000000000000000000000000000000000044960000000000000000000000000000000000000000000000000000000000004498000000000000000000000000000000000000000000000000000000000000449a000000000000000000000000000000000000000000000000000000000000449c000000000000000000000000000000000000000000000000000000000000449e00000000000000000000000000000000000000000000000000000000000044a000000000000000000000000000000000000000000000000000000000000044a200000000000000000000000000000000000000000000000000000000000044a400000000000000000000000000000000000000000000000000000000000044a600000000000000000000000000000000000000000000000000000000000044a800000000000000000000000000000000000000000000000000000000000044aa00000000000000000000000000000000000000000000000000000000000044ac00000000000000000000000000000000000000000000000000000000000044ae00000000000000000000000000000000000000000000000000000000000044b000000000000000000000000000000000000000000000000000000000000044b200000000000000000000000000000000000000000000000000000000000044b400000000000000000000000000000000000000000000000000000000000044b600000000000000000000000000000000000000000000000000000000000044b800000000000000000000000000000000000000000000000000000000000044ba00000000000000000000000000000000000000000000000000000000000044bc00000000000000000000000000000000000000000000000000000000000044be00000000000000000000000000000000000000000000000000000000000044c000000000000000000000000000000000000000000000000000000000000044c200000000000000000000000000000000000000000000000000000000000044c400000000000000000000000000000000000000000000000000000000000044c600000000000000000000000000000000000000000000000000000000000044c800000000000000000000000000000000000000000000000000000000000044ca00000000000000000000000000000000000000000000000000000000000044cc00000000000000000000000000000000000000000000000000000000000044ce00000000000000000000000000000000000000000000000000000000000044d000000000000000000000000000000000000000000000000000000000000044d200000000000000000000000000000000000000000000000000000000000044d400000000000000000000000000000000000000000000000000000000000044d600000000000000000000000000000000000000000000000000000000000044d800000000000000000000000000000000000000000000000000000000000044da00000000000000000000000000000000000000000000000000000000000044dc00000000000000000000000000000000000000000000000000000000000044de00000000000000000000000000000000000000000000000000000000000044e000000000000000000000000000000000000000000000000000000000000044e200000000000000000000000000000000000000000000000000000000000044e400000000000000000000000000000000000000000000000000000000000044e600000000000000000000000000000000000000000000000000000000000044e800000000000000000000000000000000000000000000000000000000000044ea00000000000000000000000000000000000000000000000000000000000044ec00000000000000000000000000000000000000000000000000000000000044ee00000000000000000000000000000000000000000000000000000000000044f000000000000000000000000000000000000000000000000000000000000044f200000000000000000000000000000000000000000000000000000000000044f400000000000000000000000000000000000000000000000000000000000044f600000000000000000000000000000000000000000000000000000000000044f800000000000000000000000000000000000000000000000000000000000044fa00000000000000000000000000000000000000000000000000000000000044fc00000000000000000000000000000000000000000000000000000000000044fe00000000000000000000000000000000000000000000000000000000000045000000000000000000000000000000000000000000000000000000000000004502000000000000000000000000000000000000000000000000000000000000450400000000000000000000000000000000000000000000000000000000000045060000000000000000000000000000000000000000000000000000000000004508000000000000000000000000000000000000000000000000000000000000450a000000000000000000000000000000000000000000000000000000000000450c000000000000000000000000000000000000000000000000000000000000450e00000000000000000000000000000000000000000000000000000000000045100000000000000000000000000000000000000000000000000000000000004512000000000000000000000000000000000000000000000000000000000000451400000000000000000000000000000000000000000000000000000000000045160000000000000000000000000000000000000000000000000000000000004518000000000000000000000000000000000000000000000000000000000000451a000000000000000000000000000000000000000000000000000000000000451c000000000000000000000000000000000000000000000000000000000000451e00000000000000000000000000000000000000000000000000000000000045200000000000000000000000000000000000000000000000000000000000004522000000000000000000000000000000000000000000000000000000000000452400000000000000000000000000000000000000000000000000000000000045260000000000000000000000000000000000000000000000000000000000004528000000000000000000000000000000000000000000000000000000000000452a000000000000000000000000000000000000000000000000000000000000452c000000000000000000000000000000000000000000000000000000000000452e00000000000000000000000000000000000000000000000000000000000045300000000000000000000000000000000000000000000000000000000000004532000000000000000000000000000000000000000000000000000000000000453400000000000000000000000000000000000000000000000000000000000045360000000000000000000000000000000000000000000000000000000000004538000000000000000000000000000000000000000000000000000000000000453a000000000000000000000000000000000000000000000000000000000000453c000000000000000000000000000000000000000000000000000000000000453e00000000000000000000000000000000000000000000000000000000000045400000000000000000000000000000000000000000000000000000000000004542000000000000000000000000000000000000000000000000000000000000454400000000000000000000000000000000000000000000000000000000000045460000000000000000000000000000000000000000000000000000000000004548000000000000000000000000000000000000000000000000000000000000454a000000000000000000000000000000000000000000000000000000000000454c000000000000000000000000000000000000000000000000000000000000454e00000000000000000000000000000000000000000000000000000000000045500000000000000000000000000000000000000000000000000000000000004552000000000000000000000000000000000000000000000000000000000000455400000000000000000000000000000000000000000000000000000000000045560000000000000000000000000000000000000000000000000000000000004558000000000000000000000000000000000000000000000000000000000000455a000000000000000000000000000000000000000000000000000000000000455c000000000000000000000000000000000000000000000000000000000000455e00000000000000000000000000000000000000000000000000000000000045600000000000000000000000000000000000000000000000000000000000004562000000000000000000000000000000000000000000000000000000000000456400000000000000000000000000000000000000000000000000000000000045660000000000000000000000000000000000000000000000000000000000004568000000000000000000000000000000000000000000000000000000000000456a000000000000000000000000000000000000000000000000000000000000456c000000000000000000000000000000000000000000000000000000000000456e00000000000000000000000000000000000000000000000000000000000045700000000000000000000000000000000000000000000000000000000000004572000000000000000000000000000000000000000000000000000000000000457400000000000000000000000000000000000000000000000000000000000045760000000000000000000000000000000000000000000000000000000000004578000000000000000000000000000000000000000000000000000000000000457a000000000000000000000000000000000000000000000000000000000000457c000000000000000000000000000000000000000000000000000000000000457e00000000000000000000000000000000000000000000000000000000000045800000000000000000000000000000000000000000000000000000000000004582000000000000000000000000000000000000000000000000000000000000458400000000000000000000000000000000000000000000000000000000000045860000000000000000000000000000000000000000000000000000000000004588000000000000000000000000000000000000000000000000000000000000458a000000000000000000000000000000000000000000000000000000000000458c000000000000000000000000000000000000000000000000000000000000458e00000000000000000000000000000000000000000000000000000000000045900000000000000000000000000000000000000000000000000000000000004592000000000000000000000000000000000000000000000000000000000000459400000000000000000000000000000000000000000000000000000000000045960000000000000000000000000000000000000000000000000000000000004598000000000000000000000000000000000000000000000000000000000000459a000000000000000000000000000000000000000000000000000000000000459c000000000000000000000000000000000000000000000000000000000000459e00000000000000000000000000000000000000000000000000000000000045a000000000000000000000000000000000000000000000000000000000000045a200000000000000000000000000000000000000000000000000000000000045a400000000000000000000000000000000000000000000000000000000000045a600000000000000000000000000000000000000000000000000000000000045a800000000000000000000000000000000000000000000000000000000000045aa00000000000000000000000000000000000000000000000000000000000045ac00000000000000000000000000000000000000000000000000000000000045ae00000000000000000000000000000000000000000000000000000000000045b000000000000000000000000000000000000000000000000000000000000045b200000000000000000000000000000000000000000000000000000000000045b400000000000000000000000000000000000000000000000000000000000045b600000000000000000000000000000000000000000000000000000000000045b800000000000000000000000000000000000000000000000000000000000045ba00000000000000000000000000000000000000000000000000000000000045bc00000000000000000000000000000000000000000000000000000000000045be00000000000000000000000000000000000000000000000000000000000045c000000000000000000000000000000000000000000000000000000000000045c200000000000000000000000000000000000000000000000000000000000045c400000000000000000000000000000000000000000000000000000000000045c600000000000000000000000000000000000000000000000000000000000045c800000000000000000000000000000000000000000000000000000000000045ca00000000000000000000000000000000000000000000000000000000000045cc00000000000000000000000000000000000000000000000000000000000045ce00000000000000000000000000000000000000000000000000000000000045d000000000000000000000000000000000000000000000000000000000000045d200000000000000000000000000000000000000000000000000000000000045d400000000000000000000000000000000000000000000000000000000000045d600000000000000000000000000000000000000000000000000000000000045d800000000000000000000000000000000000000000000000000000000000045da00000000000000000000000000000000000000000000000000000000000045dc00000000000000000000000000000000000000000000000000000000000045de00000000000000000000000000000000000000000000000000000000000045e000000000000000000000000000000000000000000000000000000000000045e200000000000000000000000000000000000000000000000000000000000045e400000000000000000000000000000000000000000000000000000000000045e600000000000000000000000000000000000000000000000000000000000045e800000000000000000000000000000000000000000000000000000000000045ea00000000000000000000000000000000000000000000000000000000000045ec00000000000000000000000000000000000000000000000000000000000045ee00000000000000000000000000000000000000000000000000000000000045f000000000000000000000000000000000000000000000000000000000000045f200000000000000000000000000000000000000000000000000000000000045f400000000000000000000000000000000000000000000000000000000000045f600000000000000000000000000000000000000000000000000000000000045f800000000000000000000000000000000000000000000000000000000000045fa00000000000000000000000000000000000000000000000000000000000045fc00000000000000000000000000000000000000000000000000000000000045fe00000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004602000000000000000000000000000000000000000000000000000000000000460400000000000000000000000000000000000000000000000000000000000046060000000000000000000000000000000000000000000000000000000000004608000000000000000000000000000000000000000000000000000000000000460a000000000000000000000000000000000000000000000000000000000000460c000000000000000000000000000000000000000000000000000000000000460e00000000000000000000000000000000000000000000000000000000000046100000000000000000000000000000000000000000000000000000000000004612000000000000000000000000000000000000000000000000000000000000461400000000000000000000000000000000000000000000000000000000000046160000000000000000000000000000000000000000000000000000000000004618000000000000000000000000000000000000000000000000000000000000461a000000000000000000000000000000000000000000000000000000000000461c000000000000000000000000000000000000000000000000000000000000461e00000000000000000000000000000000000000000000000000000000000046200000000000000000000000000000000000000000000000000000000000004622000000000000000000000000000000000000000000000000000000000000462400000000000000000000000000000000000000000000000000000000000046260000000000000000000000000000000000000000000000000000000000004628000000000000000000000000000000000000000000000000000000000000462a000000000000000000000000000000000000000000000000000000000000462c000000000000000000000000000000000000000000000000000000000000462e00000000000000000000000000000000000000000000000000000000000046300000000000000000000000000000000000000000000000000000000000004632000000000000000000000000000000000000000000000000000000000000463400000000000000000000000000000000000000000000000000000000000046360000000000000000000000000000000000000000000000000000000000004638000000000000000000000000000000000000000000000000000000000000463a000000000000000000000000000000000000000000000000000000000000463c000000000000000000000000000000000000000000000000000000000000463e00000000000000000000000000000000000000000000000000000000000046400000000000000000000000000000000000000000000000000000000000004642000000000000000000000000000000000000000000000000000000000000464400000000000000000000000000000000000000000000000000000000000046460000000000000000000000000000000000000000000000000000000000004648000000000000000000000000000000000000000000000000000000000000464a000000000000000000000000000000000000000000000000000000000000464c000000000000000000000000000000000000000000000000000000000000464e00000000000000000000000000000000000000000000000000000000000046500000000000000000000000000000000000000000000000000000000000004652000000000000000000000000000000000000000000000000000000000000465400000000000000000000000000000000000000000000000000000000000046560000000000000000000000000000000000000000000000000000000000004658000000000000000000000000000000000000000000000000000000000000465a000000000000000000000000000000000000000000000000000000000000465c000000000000000000000000000000000000000000000000000000000000465e00000000000000000000000000000000000000000000000000000000000046600000000000000000000000000000000000000000000000000000000000004662000000000000000000000000000000000000000000000000000000000000466400000000000000000000000000000000000000000000000000000000000046660000000000000000000000000000000000000000000000000000000000004668000000000000000000000000000000000000000000000000000000000000466a000000000000000000000000000000000000000000000000000000000000466c000000000000000000000000000000000000000000000000000000000000466e00000000000000000000000000000000000000000000000000000000000046700000000000000000000000000000000000000000000000000000000000004672000000000000000000000000000000000000000000000000000000000000467400000000000000000000000000000000000000000000000000000000000046760000000000000000000000000000000000000000000000000000000000004678000000000000000000000000000000000000000000000000000000000000467a000000000000000000000000000000000000000000000000000000000000467c000000000000000000000000000000000000000000000000000000000000467e00000000000000000000000000000000000000000000000000000000000046800000000000000000000000000000000000000000000000000000000000004682000000000000000000000000000000000000000000000000000000000000468400000000000000000000000000000000000000000000000000000000000046860000000000000000000000000000000000000000000000000000000000004688000000000000000000000000000000000000000000000000000000000000468a000000000000000000000000000000000000000000000000000000000000468c000000000000000000000000000000000000000000000000000000000000468e00000000000000000000000000000000000000000000000000000000000046900000000000000000000000000000000000000000000000000000000000004692000000000000000000000000000000000000000000000000000000000000469400000000000000000000000000000000000000000000000000000000000046960000000000000000000000000000000000000000000000000000000000004698000000000000000000000000000000000000000000000000000000000000469a000000000000000000000000000000000000000000000000000000000000469c000000000000000000000000000000000000000000000000000000000000469e00000000000000000000000000000000000000000000000000000000000046a000000000000000000000000000000000000000000000000000000000000046a200000000000000000000000000000000000000000000000000000000000046a400000000000000000000000000000000000000000000000000000000000046a600000000000000000000000000000000000000000000000000000000000046a800000000000000000000000000000000000000000000000000000000000046aa00000000000000000000000000000000000000000000000000000000000046ac00000000000000000000000000000000000000000000000000000000000046ae00000000000000000000000000000000000000000000000000000000000046b000000000000000000000000000000000000000000000000000000000000046b200000000000000000000000000000000000000000000000000000000000046b400000000000000000000000000000000000000000000000000000000000046b600000000000000000000000000000000000000000000000000000000000046b800000000000000000000000000000000000000000000000000000000000046ba00000000000000000000000000000000000000000000000000000000000046bc00000000000000000000000000000000000000000000000000000000000046be00000000000000000000000000000000000000000000000000000000000046c000000000000000000000000000000000000000000000000000000000000046c200000000000000000000000000000000000000000000000000000000000046c400000000000000000000000000000000000000000000000000000000000046c600000000000000000000000000000000000000000000000000000000000046c800000000000000000000000000000000000000000000000000000000000046ca00000000000000000000000000000000000000000000000000000000000046cc00000000000000000000000000000000000000000000000000000000000046ce00000000000000000000000000000000000000000000000000000000000046d000000000000000000000000000000000000000000000000000000000000046d200000000000000000000000000000000000000000000000000000000000046d400000000000000000000000000000000000000000000000000000000000046d600000000000000000000000000000000000000000000000000000000000046d800000000000000000000000000000000000000000000000000000000000046da00000000000000000000000000000000000000000000000000000000000046dc00000000000000000000000000000000000000000000000000000000000046de00000000000000000000000000000000000000000000000000000000000046e000000000000000000000000000000000000000000000000000000000000046e200000000000000000000000000000000000000000000000000000000000046e400000000000000000000000000000000000000000000000000000000000046e600000000000000000000000000000000000000000000000000000000000046e800000000000000000000000000000000000000000000000000000000000046ea00000000000000000000000000000000000000000000000000000000000046ec00000000000000000000000000000000000000000000000000000000000046ee00000000000000000000000000000000000000000000000000000000000046f000000000000000000000000000000000000000000000000000000000000046f200000000000000000000000000000000000000000000000000000000000046f400000000000000000000000000000000000000000000000000000000000046f600000000000000000000000000000000000000000000000000000000000046f800000000000000000000000000000000000000000000000000000000000046fa00000000000000000000000000000000000000000000000000000000000046fc00000000000000000000000000000000000000000000000000000000000046fe00000000000000000000000000000000000000000000000000000000000047000000000000000000000000000000000000000000000000000000000000004702000000000000000000000000000000000000000000000000000000000000470400000000000000000000000000000000000000000000000000000000000047060000000000000000000000000000000000000000000000000000000000004708000000000000000000000000000000000000000000000000000000000000470a000000000000000000000000000000000000000000000000000000000000470c000000000000000000000000000000000000000000000000000000000000470e00000000000000000000000000000000000000000000000000000000000047100000000000000000000000000000000000000000000000000000000000004712000000000000000000000000000000000000000000000000000000000000471400000000000000000000000000000000000000000000000000000000000047160000000000000000000000000000000000000000000000000000000000004718000000000000000000000000000000000000000000000000000000000000471a000000000000000000000000000000000000000000000000000000000000471c000000000000000000000000000000000000000000000000000000000000471e00000000000000000000000000000000000000000000000000000000000047200000000000000000000000000000000000000000000000000000000000004722000000000000000000000000000000000000000000000000000000000000472400000000000000000000000000000000000000000000000000000000000047260000000000000000000000000000000000000000000000000000000000004728000000000000000000000000000000000000000000000000000000000000472a000000000000000000000000000000000000000000000000000000000000472c000000000000000000000000000000000000000000000000000000000000472e00000000000000000000000000000000000000000000000000000000000047300000000000000000000000000000000000000000000000000000000000004732000000000000000000000000000000000000000000000000000000000000473400000000000000000000000000000000000000000000000000000000000047360000000000000000000000000000000000000000000000000000000000004738000000000000000000000000000000000000000000000000000000000000473a000000000000000000000000000000000000000000000000000000000000473c000000000000000000000000000000000000000000000000000000000000473e00000000000000000000000000000000000000000000000000000000000047400000000000000000000000000000000000000000000000000000000000004742000000000000000000000000000000000000000000000000000000000000474400000000000000000000000000000000000000000000000000000000000047460000000000000000000000000000000000000000000000000000000000004748000000000000000000000000000000000000000000000000000000000000474a000000000000000000000000000000000000000000000000000000000000474c000000000000000000000000000000000000000000000000000000000000474e00000000000000000000000000000000000000000000000000000000000047500000000000000000000000000000000000000000000000000000000000004752000000000000000000000000000000000000000000000000000000000000475400000000000000000000000000000000000000000000000000000000000047560000000000000000000000000000000000000000000000000000000000004758000000000000000000000000000000000000000000000000000000000000475a000000000000000000000000000000000000000000000000000000000000475c000000000000000000000000000000000000000000000000000000000000475e00000000000000000000000000000000000000000000000000000000000047600000000000000000000000000000000000000000000000000000000000004762000000000000000000000000000000000000000000000000000000000000476400000000000000000000000000000000000000000000000000000000000047660000000000000000000000000000000000000000000000000000000000004768000000000000000000000000000000000000000000000000000000000000476a000000000000000000000000000000000000000000000000000000000000476c000000000000000000000000000000000000000000000000000000000000476e00000000000000000000000000000000000000000000000000000000000047700000000000000000000000000000000000000000000000000000000000004772000000000000000000000000000000000000000000000000000000000000477400000000000000000000000000000000000000000000000000000000000047760000000000000000000000000000000000000000000000000000000000004778000000000000000000000000000000000000000000000000000000000000477a000000000000000000000000000000000000000000000000000000000000477c000000000000000000000000000000000000000000000000000000000000477e00000000000000000000000000000000000000000000000000000000000047800000000000000000000000000000000000000000000000000000000000004782000000000000000000000000000000000000000000000000000000000000478400000000000000000000000000000000000000000000000000000000000047860000000000000000000000000000000000000000000000000000000000004788000000000000000000000000000000000000000000000000000000000000478a000000000000000000000000000000000000000000000000000000000000478c000000000000000000000000000000000000000000000000000000000000478e00000000000000000000000000000000000000000000000000000000000047900000000000000000000000000000000000000000000000000000000000004792000000000000000000000000000000000000000000000000000000000000479400000000000000000000000000000000000000000000000000000000000047960000000000000000000000000000000000000000000000000000000000004798000000000000000000000000000000000000000000000000000000000000479a000000000000000000000000000000000000000000000000000000000000479c000000000000000000000000000000000000000000000000000000000000479e00000000000000000000000000000000000000000000000000000000000047a000000000000000000000000000000000000000000000000000000000000047a200000000000000000000000000000000000000000000000000000000000047a400000000000000000000000000000000000000000000000000000000000047a600000000000000000000000000000000000000000000000000000000000047a800000000000000000000000000000000000000000000000000000000000047aa00000000000000000000000000000000000000000000000000000000000047ac00000000000000000000000000000000000000000000000000000000000047ae00000000000000000000000000000000000000000000000000000000000047b000000000000000000000000000000000000000000000000000000000000047b200000000000000000000000000000000000000000000000000000000000047b400000000000000000000000000000000000000000000000000000000000047b600000000000000000000000000000000000000000000000000000000000047b800000000000000000000000000000000000000000000000000000000000047ba00000000000000000000000000000000000000000000000000000000000047bc00000000000000000000000000000000000000000000000000000000000047be00000000000000000000000000000000000000000000000000000000000047c000000000000000000000000000000000000000000000000000000000000047c200000000000000000000000000000000000000000000000000000000000047c400000000000000000000000000000000000000000000000000000000000047c600000000000000000000000000000000000000000000000000000000000047c800000000000000000000000000000000000000000000000000000000000047ca00000000000000000000000000000000000000000000000000000000000047cc00000000000000000000000000000000000000000000000000000000000047ce00000000000000000000000000000000000000000000000000000000000047d000000000000000000000000000000000000000000000000000000000000047d200000000000000000000000000000000000000000000000000000000000047d400000000000000000000000000000000000000000000000000000000000047d600000000000000000000000000000000000000000000000000000000000047d800000000000000000000000000000000000000000000000000000000000047da00000000000000000000000000000000000000000000000000000000000047dc00000000000000000000000000000000000000000000000000000000000047de00000000000000000000000000000000000000000000000000000000000047e000000000000000000000000000000000000000000000000000000000000047e200000000000000000000000000000000000000000000000000000000000047e400000000000000000000000000000000000000000000000000000000000047e600000000000000000000000000000000000000000000000000000000000047e800000000000000000000000000000000000000000000000000000000000047ea00000000000000000000000000000000000000000000000000000000000047ec00000000000000000000000000000000000000000000000000000000000047ee00000000000000000000000000000000000000000000000000000000000047f000000000000000000000000000000000000000000000000000000000000047f200000000000000000000000000000000000000000000000000000000000047f400000000000000000000000000000000000000000000000000000000000047f600000000000000000000000000000000000000000000000000000000000047f800000000000000000000000000000000000000000000000000000000000047fa00000000000000000000000000000000000000000000000000000000000047fc00000000000000000000000000000000000000000000000000000000000047fe00000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004802000000000000000000000000000000000000000000000000000000000000480400000000000000000000000000000000000000000000000000000000000048060000000000000000000000000000000000000000000000000000000000004808000000000000000000000000000000000000000000000000000000000000480a000000000000000000000000000000000000000000000000000000000000480c000000000000000000000000000000000000000000000000000000000000480e00000000000000000000000000000000000000000000000000000000000048100000000000000000000000000000000000000000000000000000000000004812000000000000000000000000000000000000000000000000000000000000481400000000000000000000000000000000000000000000000000000000000048160000000000000000000000000000000000000000000000000000000000004818000000000000000000000000000000000000000000000000000000000000481a000000000000000000000000000000000000000000000000000000000000481c000000000000000000000000000000000000000000000000000000000000481e00000000000000000000000000000000000000000000000000000000000048200000000000000000000000000000000000000000000000000000000000004822000000000000000000000000000000000000000000000000000000000000482400000000000000000000000000000000000000000000000000000000000048260000000000000000000000000000000000000000000000000000000000004828000000000000000000000000000000000000000000000000000000000000482a000000000000000000000000000000000000000000000000000000000000482c000000000000000000000000000000000000000000000000000000000000482e00000000000000000000000000000000000000000000000000000000000048300000000000000000000000000000000000000000000000000000000000004832000000000000000000000000000000000000000000000000000000000000483400000000000000000000000000000000000000000000000000000000000048360000000000000000000000000000000000000000000000000000000000004838000000000000000000000000000000000000000000000000000000000000483a000000000000000000000000000000000000000000000000000000000000483c000000000000000000000000000000000000000000000000000000000000483e00000000000000000000000000000000000000000000000000000000000048400000000000000000000000000000000000000000000000000000000000004842000000000000000000000000000000000000000000000000000000000000484400000000000000000000000000000000000000000000000000000000000048460000000000000000000000000000000000000000000000000000000000004848000000000000000000000000000000000000000000000000000000000000484a000000000000000000000000000000000000000000000000000000000000484c000000000000000000000000000000000000000000000000000000000000484e00000000000000000000000000000000000000000000000000000000000048500000000000000000000000000000000000000000000000000000000000004852000000000000000000000000000000000000000000000000000000000000485400000000000000000000000000000000000000000000000000000000000048560000000000000000000000000000000000000000000000000000000000004858000000000000000000000000000000000000000000000000000000000000485a000000000000000000000000000000000000000000000000000000000000485c000000000000000000000000000000000000000000000000000000000000485e00000000000000000000000000000000000000000000000000000000000048600000000000000000000000000000000000000000000000000000000000004862000000000000000000000000000000000000000000000000000000000000486400000000000000000000000000000000000000000000000000000000000048660000000000000000000000000000000000000000000000000000000000004868000000000000000000000000000000000000000000000000000000000000486a000000000000000000000000000000000000000000000000000000000000486c000000000000000000000000000000000000000000000000000000000000486e00000000000000000000000000000000000000000000000000000000000048700000000000000000000000000000000000000000000000000000000000004872000000000000000000000000000000000000000000000000000000000000487400000000000000000000000000000000000000000000000000000000000048760000000000000000000000000000000000000000000000000000000000004878000000000000000000000000000000000000000000000000000000000000487a000000000000000000000000000000000000000000000000000000000000487c000000000000000000000000000000000000000000000000000000000000487e00000000000000000000000000000000000000000000000000000000000048800000000000000000000000000000000000000000000000000000000000004882000000000000000000000000000000000000000000000000000000000000488400000000000000000000000000000000000000000000000000000000000048860000000000000000000000000000000000000000000000000000000000004888000000000000000000000000000000000000000000000000000000000000488a000000000000000000000000000000000000000000000000000000000000488c000000000000000000000000000000000000000000000000000000000000488e00000000000000000000000000000000000000000000000000000000000048900000000000000000000000000000000000000000000000000000000000004892000000000000000000000000000000000000000000000000000000000000489400000000000000000000000000000000000000000000000000000000000048960000000000000000000000000000000000000000000000000000000000004898000000000000000000000000000000000000000000000000000000000000489a000000000000000000000000000000000000000000000000000000000000489c000000000000000000000000000000000000000000000000000000000000489e00000000000000000000000000000000000000000000000000000000000048a000000000000000000000000000000000000000000000000000000000000048a200000000000000000000000000000000000000000000000000000000000048a400000000000000000000000000000000000000000000000000000000000048a600000000000000000000000000000000000000000000000000000000000048a800000000000000000000000000000000000000000000000000000000000048aa00000000000000000000000000000000000000000000000000000000000048ac00000000000000000000000000000000000000000000000000000000000048ae00000000000000000000000000000000000000000000000000000000000048b000000000000000000000000000000000000000000000000000000000000048b200000000000000000000000000000000000000000000000000000000000048b400000000000000000000000000000000000000000000000000000000000048b600000000000000000000000000000000000000000000000000000000000048b800000000000000000000000000000000000000000000000000000000000048ba00000000000000000000000000000000000000000000000000000000000048bc00000000000000000000000000000000000000000000000000000000000048be00000000000000000000000000000000000000000000000000000000000048c000000000000000000000000000000000000000000000000000000000000048c200000000000000000000000000000000000000000000000000000000000048c400000000000000000000000000000000000000000000000000000000000048c600000000000000000000000000000000000000000000000000000000000048c800000000000000000000000000000000000000000000000000000000000048ca00000000000000000000000000000000000000000000000000000000000048cc00000000000000000000000000000000000000000000000000000000000048ce00000000000000000000000000000000000000000000000000000000000048d000000000000000000000000000000000000000000000000000000000000048d200000000000000000000000000000000000000000000000000000000000048d400000000000000000000000000000000000000000000000000000000000048d600000000000000000000000000000000000000000000000000000000000048d800000000000000000000000000000000000000000000000000000000000048da00000000000000000000000000000000000000000000000000000000000048dc00000000000000000000000000000000000000000000000000000000000048de00000000000000000000000000000000000000000000000000000000000048e000000000000000000000000000000000000000000000000000000000000048e200000000000000000000000000000000000000000000000000000000000048e400000000000000000000000000000000000000000000000000000000000048e600000000000000000000000000000000000000000000000000000000000048e800000000000000000000000000000000000000000000000000000000000048ea00000000000000000000000000000000000000000000000000000000000048ec00000000000000000000000000000000000000000000000000000000000048ee00000000000000000000000000000000000000000000000000000000000048f000000000000000000000000000000000000000000000000000000000000048f200000000000000000000000000000000000000000000000000000000000048f400000000000000000000000000000000000000000000000000000000000048f600000000000000000000000000000000000000000000000000000000000048f800000000000000000000000000000000000000000000000000000000000048fa00000000000000000000000000000000000000000000000000000000000048fc00000000000000000000000000000000000000000000000000000000000048fe00000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000004902000000000000000000000000000000000000000000000000000000000000490400000000000000000000000000000000000000000000000000000000000049060000000000000000000000000000000000000000000000000000000000004908000000000000000000000000000000000000000000000000000000000000490a000000000000000000000000000000000000000000000000000000000000490c000000000000000000000000000000000000000000000000000000000000490e00000000000000000000000000000000000000000000000000000000000049100000000000000000000000000000000000000000000000000000000000004912000000000000000000000000000000000000000000000000000000000000491400000000000000000000000000000000000000000000000000000000000049160000000000000000000000000000000000000000000000000000000000004918000000000000000000000000000000000000000000000000000000000000491a000000000000000000000000000000000000000000000000000000000000491c000000000000000000000000000000000000000000000000000000000000491e00000000000000000000000000000000000000000000000000000000000049200000000000000000000000000000000000000000000000000000000000004922000000000000000000000000000000000000000000000000000000000000492400000000000000000000000000000000000000000000000000000000000049260000000000000000000000000000000000000000000000000000000000004928000000000000000000000000000000000000000000000000000000000000492a000000000000000000000000000000000000000000000000000000000000492c000000000000000000000000000000000000000000000000000000000000492e00000000000000000000000000000000000000000000000000000000000049300000000000000000000000000000000000000000000000000000000000004932000000000000000000000000000000000000000000000000000000000000493400000000000000000000000000000000000000000000000000000000000049360000000000000000000000000000000000000000000000000000000000004938000000000000000000000000000000000000000000000000000000000000493a000000000000000000000000000000000000000000000000000000000000493c000000000000000000000000000000000000000000000000000000000000493e00000000000000000000000000000000000000000000000000000000000049400000000000000000000000000000000000000000000000000000000000004942000000000000000000000000000000000000000000000000000000000000494400000000000000000000000000000000000000000000000000000000000049460000000000000000000000000000000000000000000000000000000000004948000000000000000000000000000000000000000000000000000000000000494a000000000000000000000000000000000000000000000000000000000000494c000000000000000000000000000000000000000000000000000000000000494e00000000000000000000000000000000000000000000000000000000000049500000000000000000000000000000000000000000000000000000000000004952000000000000000000000000000000000000000000000000000000000000495400000000000000000000000000000000000000000000000000000000000049560000000000000000000000000000000000000000000000000000000000004958000000000000000000000000000000000000000000000000000000000000495a000000000000000000000000000000000000000000000000000000000000495c000000000000000000000000000000000000000000000000000000000000495e00000000000000000000000000000000000000000000000000000000000049600000000000000000000000000000000000000000000000000000000000004962000000000000000000000000000000000000000000000000000000000000496400000000000000000000000000000000000000000000000000000000000049660000000000000000000000000000000000000000000000000000000000004968000000000000000000000000000000000000000000000000000000000000496a000000000000000000000000000000000000000000000000000000000000496c000000000000000000000000000000000000000000000000000000000000496e00000000000000000000000000000000000000000000000000000000000049700000000000000000000000000000000000000000000000000000000000004972000000000000000000000000000000000000000000000000000000000000497400000000000000000000000000000000000000000000000000000000000049760000000000000000000000000000000000000000000000000000000000004978000000000000000000000000000000000000000000000000000000000000497a000000000000000000000000000000000000000000000000000000000000497c000000000000000000000000000000000000000000000000000000000000497e00000000000000000000000000000000000000000000000000000000000049800000000000000000000000000000000000000000000000000000000000004982000000000000000000000000000000000000000000000000000000000000498400000000000000000000000000000000000000000000000000000000000049860000000000000000000000000000000000000000000000000000000000004988000000000000000000000000000000000000000000000000000000000000498a000000000000000000000000000000000000000000000000000000000000498c000000000000000000000000000000000000000000000000000000000000498e00000000000000000000000000000000000000000000000000000000000049900000000000000000000000000000000000000000000000000000000000004992000000000000000000000000000000000000000000000000000000000000499400000000000000000000000000000000000000000000000000000000000049960000000000000000000000000000000000000000000000000000000000004998000000000000000000000000000000000000000000000000000000000000499a000000000000000000000000000000000000000000000000000000000000499c000000000000000000000000000000000000000000000000000000000000499e00000000000000000000000000000000000000000000000000000000000049a000000000000000000000000000000000000000000000000000000000000049a200000000000000000000000000000000000000000000000000000000000049a400000000000000000000000000000000000000000000000000000000000049a600000000000000000000000000000000000000000000000000000000000049a800000000000000000000000000000000000000000000000000000000000049aa00000000000000000000000000000000000000000000000000000000000049ac00000000000000000000000000000000000000000000000000000000000049ae00000000000000000000000000000000000000000000000000000000000049b000000000000000000000000000000000000000000000000000000000000049b200000000000000000000000000000000000000000000000000000000000049b400000000000000000000000000000000000000000000000000000000000049b600000000000000000000000000000000000000000000000000000000000049b800000000000000000000000000000000000000000000000000000000000049ba00000000000000000000000000000000000000000000000000000000000049bc00000000000000000000000000000000000000000000000000000000000049be00000000000000000000000000000000000000000000000000000000000049c000000000000000000000000000000000000000000000000000000000000049c200000000000000000000000000000000000000000000000000000000000049c400000000000000000000000000000000000000000000000000000000000049c600000000000000000000000000000000000000000000000000000000000049c800000000000000000000000000000000000000000000000000000000000049ca00000000000000000000000000000000000000000000000000000000000049cc00000000000000000000000000000000000000000000000000000000000049ce00000000000000000000000000000000000000000000000000000000000049d000000000000000000000000000000000000000000000000000000000000049d200000000000000000000000000000000000000000000000000000000000049d400000000000000000000000000000000000000000000000000000000000049d600000000000000000000000000000000000000000000000000000000000049d800000000000000000000000000000000000000000000000000000000000049da00000000000000000000000000000000000000000000000000000000000049dc00000000000000000000000000000000000000000000000000000000000049de00000000000000000000000000000000000000000000000000000000000049e000000000000000000000000000000000000000000000000000000000000049e200000000000000000000000000000000000000000000000000000000000049e400000000000000000000000000000000000000000000000000000000000049e600000000000000000000000000000000000000000000000000000000000049e800000000000000000000000000000000000000000000000000000000000049ea00000000000000000000000000000000000000000000000000000000000049ec00000000000000000000000000000000000000000000000000000000000049ee00000000000000000000000000000000000000000000000000000000000049f000000000000000000000000000000000000000000000000000000000000049f200000000000000000000000000000000000000000000000000000000000049f400000000000000000000000000000000000000000000000000000000000049f600000000000000000000000000000000000000000000000000000000000049f800000000000000000000000000000000000000000000000000000000000049fa00000000000000000000000000000000000000000000000000000000000049fc00000000000000000000000000000000000000000000000000000000000049fe0000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004a020000000000000000000000000000000000000000000000000000000000004a040000000000000000000000000000000000000000000000000000000000004a060000000000000000000000000000000000000000000000000000000000004a080000000000000000000000000000000000000000000000000000000000004a0a0000000000000000000000000000000000000000000000000000000000004a0c0000000000000000000000000000000000000000000000000000000000004a0e0000000000000000000000000000000000000000000000000000000000004a100000000000000000000000000000000000000000000000000000000000004a120000000000000000000000000000000000000000000000000000000000004a140000000000000000000000000000000000000000000000000000000000004a160000000000000000000000000000000000000000000000000000000000004a180000000000000000000000000000000000000000000000000000000000004a1a0000000000000000000000000000000000000000000000000000000000004a1c0000000000000000000000000000000000000000000000000000000000004a1e0000000000000000000000000000000000000000000000000000000000004a200000000000000000000000000000000000000000000000000000000000004a220000000000000000000000000000000000000000000000000000000000004a240000000000000000000000000000000000000000000000000000000000004a260000000000000000000000000000000000000000000000000000000000004a280000000000000000000000000000000000000000000000000000000000004a2a0000000000000000000000000000000000000000000000000000000000004a2c0000000000000000000000000000000000000000000000000000000000004a2e0000000000000000000000000000000000000000000000000000000000004a300000000000000000000000000000000000000000000000000000000000004a320000000000000000000000000000000000000000000000000000000000004a340000000000000000000000000000000000000000000000000000000000004a360000000000000000000000000000000000000000000000000000000000004a380000000000000000000000000000000000000000000000000000000000004a3a0000000000000000000000000000000000000000000000000000000000004a3c0000000000000000000000000000000000000000000000000000000000004a3e0000000000000000000000000000000000000000000000000000000000004a400000000000000000000000000000000000000000000000000000000000004a420000000000000000000000000000000000000000000000000000000000004a440000000000000000000000000000000000000000000000000000000000004a460000000000000000000000000000000000000000000000000000000000004a480000000000000000000000000000000000000000000000000000000000004a4a0000000000000000000000000000000000000000000000000000000000004a4c0000000000000000000000000000000000000000000000000000000000004a4e0000000000000000000000000000000000000000000000000000000000004a500000000000000000000000000000000000000000000000000000000000004a520000000000000000000000000000000000000000000000000000000000004a540000000000000000000000000000000000000000000000000000000000004a560000000000000000000000000000000000000000000000000000000000004a580000000000000000000000000000000000000000000000000000000000004a5a0000000000000000000000000000000000000000000000000000000000004a5c0000000000000000000000000000000000000000000000000000000000004a5e0000000000000000000000000000000000000000000000000000000000004a600000000000000000000000000000000000000000000000000000000000004a620000000000000000000000000000000000000000000000000000000000004a640000000000000000000000000000000000000000000000000000000000004a660000000000000000000000000000000000000000000000000000000000004a680000000000000000000000000000000000000000000000000000000000004a6a0000000000000000000000000000000000000000000000000000000000004a6c0000000000000000000000000000000000000000000000000000000000004a6e0000000000000000000000000000000000000000000000000000000000004a700000000000000000000000000000000000000000000000000000000000004a720000000000000000000000000000000000000000000000000000000000004a740000000000000000000000000000000000000000000000000000000000004a760000000000000000000000000000000000000000000000000000000000004a780000000000000000000000000000000000000000000000000000000000004a7a0000000000000000000000000000000000000000000000000000000000004a7c0000000000000000000000000000000000000000000000000000000000004a7e0000000000000000000000000000000000000000000000000000000000004a800000000000000000000000000000000000000000000000000000000000004a820000000000000000000000000000000000000000000000000000000000004a840000000000000000000000000000000000000000000000000000000000004a860000000000000000000000000000000000000000000000000000000000004a880000000000000000000000000000000000000000000000000000000000004a8a0000000000000000000000000000000000000000000000000000000000004a8c0000000000000000000000000000000000000000000000000000000000004a8e0000000000000000000000000000000000000000000000000000000000004a900000000000000000000000000000000000000000000000000000000000004a920000000000000000000000000000000000000000000000000000000000004a940000000000000000000000000000000000000000000000000000000000004a960000000000000000000000000000000000000000000000000000000000004a980000000000000000000000000000000000000000000000000000000000004a9a0000000000000000000000000000000000000000000000000000000000004a9c0000000000000000000000000000000000000000000000000000000000004a9e0000000000000000000000000000000000000000000000000000000000004aa00000000000000000000000000000000000000000000000000000000000004aa20000000000000000000000000000000000000000000000000000000000004aa40000000000000000000000000000000000000000000000000000000000004aa60000000000000000000000000000000000000000000000000000000000004aa80000000000000000000000000000000000000000000000000000000000004aaa0000000000000000000000000000000000000000000000000000000000004aac0000000000000000000000000000000000000000000000000000000000004aae0000000000000000000000000000000000000000000000000000000000004ab00000000000000000000000000000000000000000000000000000000000004ab20000000000000000000000000000000000000000000000000000000000004ab40000000000000000000000000000000000000000000000000000000000004ab60000000000000000000000000000000000000000000000000000000000004ab80000000000000000000000000000000000000000000000000000000000004aba0000000000000000000000000000000000000000000000000000000000004abc0000000000000000000000000000000000000000000000000000000000004abe0000000000000000000000000000000000000000000000000000000000004ac00000000000000000000000000000000000000000000000000000000000004ac20000000000000000000000000000000000000000000000000000000000004ac40000000000000000000000000000000000000000000000000000000000004ac60000000000000000000000000000000000000000000000000000000000004ac80000000000000000000000000000000000000000000000000000000000004aca0000000000000000000000000000000000000000000000000000000000004acc0000000000000000000000000000000000000000000000000000000000004ace0000000000000000000000000000000000000000000000000000000000004ad00000000000000000000000000000000000000000000000000000000000004ad20000000000000000000000000000000000000000000000000000000000004ad40000000000000000000000000000000000000000000000000000000000004ad60000000000000000000000000000000000000000000000000000000000004ad80000000000000000000000000000000000000000000000000000000000004ada0000000000000000000000000000000000000000000000000000000000004adc0000000000000000000000000000000000000000000000000000000000004ade0000000000000000000000000000000000000000000000000000000000004ae00000000000000000000000000000000000000000000000000000000000004ae20000000000000000000000000000000000000000000000000000000000004ae40000000000000000000000000000000000000000000000000000000000004ae60000000000000000000000000000000000000000000000000000000000004ae80000000000000000000000000000000000000000000000000000000000004aea0000000000000000000000000000000000000000000000000000000000004aec0000000000000000000000000000000000000000000000000000000000004aee0000000000000000000000000000000000000000000000000000000000004af00000000000000000000000000000000000000000000000000000000000004af20000000000000000000000000000000000000000000000000000000000004af40000000000000000000000000000000000000000000000000000000000004af60000000000000000000000000000000000000000000000000000000000004af80000000000000000000000000000000000000000000000000000000000004afa0000000000000000000000000000000000000000000000000000000000004afc0000000000000000000000000000000000000000000000000000000000004afe0000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000004b020000000000000000000000000000000000000000000000000000000000004b040000000000000000000000000000000000000000000000000000000000004b060000000000000000000000000000000000000000000000000000000000004b080000000000000000000000000000000000000000000000000000000000004b0a0000000000000000000000000000000000000000000000000000000000004b0c0000000000000000000000000000000000000000000000000000000000004b0e0000000000000000000000000000000000000000000000000000000000004b100000000000000000000000000000000000000000000000000000000000004b120000000000000000000000000000000000000000000000000000000000004b140000000000000000000000000000000000000000000000000000000000004b160000000000000000000000000000000000000000000000000000000000004b180000000000000000000000000000000000000000000000000000000000004b1a0000000000000000000000000000000000000000000000000000000000004b1c0000000000000000000000000000000000000000000000000000000000004b1e0000000000000000000000000000000000000000000000000000000000004b200000000000000000000000000000000000000000000000000000000000004b220000000000000000000000000000000000000000000000000000000000004b240000000000000000000000000000000000000000000000000000000000004b260000000000000000000000000000000000000000000000000000000000004b280000000000000000000000000000000000000000000000000000000000004b2a0000000000000000000000000000000000000000000000000000000000004b2c0000000000000000000000000000000000000000000000000000000000004b2e0000000000000000000000000000000000000000000000000000000000004b300000000000000000000000000000000000000000000000000000000000004b320000000000000000000000000000000000000000000000000000000000004b340000000000000000000000000000000000000000000000000000000000004b360000000000000000000000000000000000000000000000000000000000004b380000000000000000000000000000000000000000000000000000000000004b3a0000000000000000000000000000000000000000000000000000000000004b3c0000000000000000000000000000000000000000000000000000000000004b3e0000000000000000000000000000000000000000000000000000000000004b400000000000000000000000000000000000000000000000000000000000004b420000000000000000000000000000000000000000000000000000000000004b440000000000000000000000000000000000000000000000000000000000004b460000000000000000000000000000000000000000000000000000000000004b480000000000000000000000000000000000000000000000000000000000004b4a0000000000000000000000000000000000000000000000000000000000004b4c0000000000000000000000000000000000000000000000000000000000004b4e0000000000000000000000000000000000000000000000000000000000004b500000000000000000000000000000000000000000000000000000000000004b520000000000000000000000000000000000000000000000000000000000004b540000000000000000000000000000000000000000000000000000000000004b560000000000000000000000000000000000000000000000000000000000004b580000000000000000000000000000000000000000000000000000000000004b5a0000000000000000000000000000000000000000000000000000000000004b5c0000000000000000000000000000000000000000000000000000000000004b5e0000000000000000000000000000000000000000000000000000000000004b600000000000000000000000000000000000000000000000000000000000004b620000000000000000000000000000000000000000000000000000000000004b640000000000000000000000000000000000000000000000000000000000004b660000000000000000000000000000000000000000000000000000000000004b680000000000000000000000000000000000000000000000000000000000004b6a0000000000000000000000000000000000000000000000000000000000004b6c0000000000000000000000000000000000000000000000000000000000004b6e0000000000000000000000000000000000000000000000000000000000004b700000000000000000000000000000000000000000000000000000000000004b720000000000000000000000000000000000000000000000000000000000004b740000000000000000000000000000000000000000000000000000000000004b760000000000000000000000000000000000000000000000000000000000004b780000000000000000000000000000000000000000000000000000000000004b7a0000000000000000000000000000000000000000000000000000000000004b7c0000000000000000000000000000000000000000000000000000000000004b7e0000000000000000000000000000000000000000000000000000000000004b800000000000000000000000000000000000000000000000000000000000004b820000000000000000000000000000000000000000000000000000000000004b840000000000000000000000000000000000000000000000000000000000004b860000000000000000000000000000000000000000000000000000000000004b880000000000000000000000000000000000000000000000000000000000004b8a0000000000000000000000000000000000000000000000000000000000004b8c0000000000000000000000000000000000000000000000000000000000004b8e0000000000000000000000000000000000000000000000000000000000004b900000000000000000000000000000000000000000000000000000000000004b920000000000000000000000000000000000000000000000000000000000004b940000000000000000000000000000000000000000000000000000000000004b960000000000000000000000000000000000000000000000000000000000004b980000000000000000000000000000000000000000000000000000000000004b9a0000000000000000000000000000000000000000000000000000000000004b9c0000000000000000000000000000000000000000000000000000000000004b9e0000000000000000000000000000000000000000000000000000000000004ba00000000000000000000000000000000000000000000000000000000000004ba20000000000000000000000000000000000000000000000000000000000004ba40000000000000000000000000000000000000000000000000000000000004ba60000000000000000000000000000000000000000000000000000000000004ba80000000000000000000000000000000000000000000000000000000000004baa0000000000000000000000000000000000000000000000000000000000004bac0000000000000000000000000000000000000000000000000000000000004bae0000000000000000000000000000000000000000000000000000000000004bb00000000000000000000000000000000000000000000000000000000000004bb20000000000000000000000000000000000000000000000000000000000004bb40000000000000000000000000000000000000000000000000000000000004bb60000000000000000000000000000000000000000000000000000000000004bb80000000000000000000000000000000000000000000000000000000000004bba0000000000000000000000000000000000000000000000000000000000004bbc0000000000000000000000000000000000000000000000000000000000004bbe0000000000000000000000000000000000000000000000000000000000004bc00000000000000000000000000000000000000000000000000000000000004bc20000000000000000000000000000000000000000000000000000000000004bc40000000000000000000000000000000000000000000000000000000000004bc60000000000000000000000000000000000000000000000000000000000004bc80000000000000000000000000000000000000000000000000000000000004bca0000000000000000000000000000000000000000000000000000000000004bcc0000000000000000000000000000000000000000000000000000000000004bce0000000000000000000000000000000000000000000000000000000000004bd00000000000000000000000000000000000000000000000000000000000004bd20000000000000000000000000000000000000000000000000000000000004bd40000000000000000000000000000000000000000000000000000000000004bd60000000000000000000000000000000000000000000000000000000000004bd80000000000000000000000000000000000000000000000000000000000004bda0000000000000000000000000000000000000000000000000000000000004bdc0000000000000000000000000000000000000000000000000000000000004bde0000000000000000000000000000000000000000000000000000000000004be00000000000000000000000000000000000000000000000000000000000004be20000000000000000000000000000000000000000000000000000000000004be40000000000000000000000000000000000000000000000000000000000004be60000000000000000000000000000000000000000000000000000000000004be80000000000000000000000000000000000000000000000000000000000004bea0000000000000000000000000000000000000000000000000000000000004bec0000000000000000000000000000000000000000000000000000000000004bee0000000000000000000000000000000000000000000000000000000000004bf00000000000000000000000000000000000000000000000000000000000004bf20000000000000000000000000000000000000000000000000000000000004bf40000000000000000000000000000000000000000000000000000000000004bf60000000000000000000000000000000000000000000000000000000000004bf80000000000000000000000000000000000000000000000000000000000004bfa0000000000000000000000000000000000000000000000000000000000004bfc0000000000000000000000000000000000000000000000000000000000004bfe0000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c020000000000000000000000000000000000000000000000000000000000004c040000000000000000000000000000000000000000000000000000000000004c060000000000000000000000000000000000000000000000000000000000004c080000000000000000000000000000000000000000000000000000000000004c0a0000000000000000000000000000000000000000000000000000000000004c0c0000000000000000000000000000000000000000000000000000000000004c0e0000000000000000000000000000000000000000000000000000000000004c100000000000000000000000000000000000000000000000000000000000004c120000000000000000000000000000000000000000000000000000000000004c140000000000000000000000000000000000000000000000000000000000004c160000000000000000000000000000000000000000000000000000000000004c180000000000000000000000000000000000000000000000000000000000004c1a0000000000000000000000000000000000000000000000000000000000004c1c0000000000000000000000000000000000000000000000000000000000004c1e0000000000000000000000000000000000000000000000000000000000004c200000000000000000000000000000000000000000000000000000000000004c220000000000000000000000000000000000000000000000000000000000004c240000000000000000000000000000000000000000000000000000000000004c260000000000000000000000000000000000000000000000000000000000004c280000000000000000000000000000000000000000000000000000000000004c2a0000000000000000000000000000000000000000000000000000000000004c2c0000000000000000000000000000000000000000000000000000000000004c2e0000000000000000000000000000000000000000000000000000000000004c300000000000000000000000000000000000000000000000000000000000004c320000000000000000000000000000000000000000000000000000000000004c340000000000000000000000000000000000000000000000000000000000004c360000000000000000000000000000000000000000000000000000000000004c380000000000000000000000000000000000000000000000000000000000004c3a0000000000000000000000000000000000000000000000000000000000004c3c0000000000000000000000000000000000000000000000000000000000004c3e0000000000000000000000000000000000000000000000000000000000004c400000000000000000000000000000000000000000000000000000000000004c420000000000000000000000000000000000000000000000000000000000004c440000000000000000000000000000000000000000000000000000000000004c460000000000000000000000000000000000000000000000000000000000004c480000000000000000000000000000000000000000000000000000000000004c4a0000000000000000000000000000000000000000000000000000000000004c4c0000000000000000000000000000000000000000000000000000000000004c4e0000000000000000000000000000000000000000000000000000000000004c500000000000000000000000000000000000000000000000000000000000004c520000000000000000000000000000000000000000000000000000000000004c540000000000000000000000000000000000000000000000000000000000004c560000000000000000000000000000000000000000000000000000000000004c580000000000000000000000000000000000000000000000000000000000004c5a0000000000000000000000000000000000000000000000000000000000004c5c0000000000000000000000000000000000000000000000000000000000004c5e0000000000000000000000000000000000000000000000000000000000004c600000000000000000000000000000000000000000000000000000000000004c620000000000000000000000000000000000000000000000000000000000004c640000000000000000000000000000000000000000000000000000000000004c660000000000000000000000000000000000000000000000000000000000004c680000000000000000000000000000000000000000000000000000000000004c6a0000000000000000000000000000000000000000000000000000000000004c6c0000000000000000000000000000000000000000000000000000000000004c6e0000000000000000000000000000000000000000000000000000000000004c700000000000000000000000000000000000000000000000000000000000004c720000000000000000000000000000000000000000000000000000000000004c740000000000000000000000000000000000000000000000000000000000004c760000000000000000000000000000000000000000000000000000000000004c780000000000000000000000000000000000000000000000000000000000004c7a0000000000000000000000000000000000000000000000000000000000004c7c0000000000000000000000000000000000000000000000000000000000004c7e0000000000000000000000000000000000000000000000000000000000004c800000000000000000000000000000000000000000000000000000000000004c820000000000000000000000000000000000000000000000000000000000004c840000000000000000000000000000000000000000000000000000000000004c860000000000000000000000000000000000000000000000000000000000004c880000000000000000000000000000000000000000000000000000000000004c8a0000000000000000000000000000000000000000000000000000000000004c8c0000000000000000000000000000000000000000000000000000000000004c8e0000000000000000000000000000000000000000000000000000000000004c900000000000000000000000000000000000000000000000000000000000004c920000000000000000000000000000000000000000000000000000000000004c940000000000000000000000000000000000000000000000000000000000004c960000000000000000000000000000000000000000000000000000000000004c980000000000000000000000000000000000000000000000000000000000004c9a0000000000000000000000000000000000000000000000000000000000004c9c0000000000000000000000000000000000000000000000000000000000004c9e0000000000000000000000000000000000000000000000000000000000004ca00000000000000000000000000000000000000000000000000000000000004ca20000000000000000000000000000000000000000000000000000000000004ca40000000000000000000000000000000000000000000000000000000000004ca60000000000000000000000000000000000000000000000000000000000004ca80000000000000000000000000000000000000000000000000000000000004caa0000000000000000000000000000000000000000000000000000000000004cac0000000000000000000000000000000000000000000000000000000000004cae0000000000000000000000000000000000000000000000000000000000004cb00000000000000000000000000000000000000000000000000000000000004cb20000000000000000000000000000000000000000000000000000000000004cb40000000000000000000000000000000000000000000000000000000000004cb60000000000000000000000000000000000000000000000000000000000004cb80000000000000000000000000000000000000000000000000000000000004cba0000000000000000000000000000000000000000000000000000000000004cbc0000000000000000000000000000000000000000000000000000000000004cbe0000000000000000000000000000000000000000000000000000000000004cc00000000000000000000000000000000000000000000000000000000000004cc20000000000000000000000000000000000000000000000000000000000004cc40000000000000000000000000000000000000000000000000000000000004cc60000000000000000000000000000000000000000000000000000000000004cc80000000000000000000000000000000000000000000000000000000000004cca0000000000000000000000000000000000000000000000000000000000004ccc0000000000000000000000000000000000000000000000000000000000004cce0000000000000000000000000000000000000000000000000000000000004cd00000000000000000000000000000000000000000000000000000000000004cd20000000000000000000000000000000000000000000000000000000000004cd40000000000000000000000000000000000000000000000000000000000004cd60000000000000000000000000000000000000000000000000000000000004cd80000000000000000000000000000000000000000000000000000000000004cda0000000000000000000000000000000000000000000000000000000000004cdc0000000000000000000000000000000000000000000000000000000000004cde0000000000000000000000000000000000000000000000000000000000004ce00000000000000000000000000000000000000000000000000000000000004ce20000000000000000000000000000000000000000000000000000000000004ce40000000000000000000000000000000000000000000000000000000000004ce60000000000000000000000000000000000000000000000000000000000004ce80000000000000000000000000000000000000000000000000000000000004cea0000000000000000000000000000000000000000000000000000000000004cec0000000000000000000000000000000000000000000000000000000000004cee0000000000000000000000000000000000000000000000000000000000004cf00000000000000000000000000000000000000000000000000000000000004cf20000000000000000000000000000000000000000000000000000000000004cf40000000000000000000000000000000000000000000000000000000000004cf60000000000000000000000000000000000000000000000000000000000004cf80000000000000000000000000000000000000000000000000000000000004cfa0000000000000000000000000000000000000000000000000000000000004cfc0000000000000000000000000000000000000000000000000000000000004cfe0000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000004d020000000000000000000000000000000000000000000000000000000000004d040000000000000000000000000000000000000000000000000000000000004d060000000000000000000000000000000000000000000000000000000000004d080000000000000000000000000000000000000000000000000000000000004d0a0000000000000000000000000000000000000000000000000000000000004d0c0000000000000000000000000000000000000000000000000000000000004d0e0000000000000000000000000000000000000000000000000000000000004d100000000000000000000000000000000000000000000000000000000000004d120000000000000000000000000000000000000000000000000000000000004d140000000000000000000000000000000000000000000000000000000000004d160000000000000000000000000000000000000000000000000000000000004d180000000000000000000000000000000000000000000000000000000000004d1a0000000000000000000000000000000000000000000000000000000000004d1c0000000000000000000000000000000000000000000000000000000000004d1e0000000000000000000000000000000000000000000000000000000000004d200000000000000000000000000000000000000000000000000000000000004d220000000000000000000000000000000000000000000000000000000000004d240000000000000000000000000000000000000000000000000000000000004d260000000000000000000000000000000000000000000000000000000000004d280000000000000000000000000000000000000000000000000000000000004d2a0000000000000000000000000000000000000000000000000000000000004d2c0000000000000000000000000000000000000000000000000000000000004d2e0000000000000000000000000000000000000000000000000000000000004d300000000000000000000000000000000000000000000000000000000000004d320000000000000000000000000000000000000000000000000000000000004d340000000000000000000000000000000000000000000000000000000000004d360000000000000000000000000000000000000000000000000000000000004d380000000000000000000000000000000000000000000000000000000000004d3a0000000000000000000000000000000000000000000000000000000000004d3c0000000000000000000000000000000000000000000000000000000000004d3e0000000000000000000000000000000000000000000000000000000000004d400000000000000000000000000000000000000000000000000000000000004d420000000000000000000000000000000000000000000000000000000000004d440000000000000000000000000000000000000000000000000000000000004d460000000000000000000000000000000000000000000000000000000000004d480000000000000000000000000000000000000000000000000000000000004d4a0000000000000000000000000000000000000000000000000000000000004d4c0000000000000000000000000000000000000000000000000000000000004d4e0000000000000000000000000000000000000000000000000000000000004d500000000000000000000000000000000000000000000000000000000000004d520000000000000000000000000000000000000000000000000000000000004d540000000000000000000000000000000000000000000000000000000000004d560000000000000000000000000000000000000000000000000000000000004d580000000000000000000000000000000000000000000000000000000000004d5a0000000000000000000000000000000000000000000000000000000000004d5c0000000000000000000000000000000000000000000000000000000000004d5e0000000000000000000000000000000000000000000000000000000000004d600000000000000000000000000000000000000000000000000000000000004d620000000000000000000000000000000000000000000000000000000000004d640000000000000000000000000000000000000000000000000000000000004d660000000000000000000000000000000000000000000000000000000000004d680000000000000000000000000000000000000000000000000000000000004d6a0000000000000000000000000000000000000000000000000000000000004d6c0000000000000000000000000000000000000000000000000000000000004d6e0000000000000000000000000000000000000000000000000000000000004d700000000000000000000000000000000000000000000000000000000000004d720000000000000000000000000000000000000000000000000000000000004d740000000000000000000000000000000000000000000000000000000000004d760000000000000000000000000000000000000000000000000000000000004d780000000000000000000000000000000000000000000000000000000000004d7a0000000000000000000000000000000000000000000000000000000000004d7c0000000000000000000000000000000000000000000000000000000000004d7e0000000000000000000000000000000000000000000000000000000000004d800000000000000000000000000000000000000000000000000000000000004d820000000000000000000000000000000000000000000000000000000000004d840000000000000000000000000000000000000000000000000000000000004d860000000000000000000000000000000000000000000000000000000000004d880000000000000000000000000000000000000000000000000000000000004d8a0000000000000000000000000000000000000000000000000000000000004d8c0000000000000000000000000000000000000000000000000000000000004d8e0000000000000000000000000000000000000000000000000000000000004d900000000000000000000000000000000000000000000000000000000000004d920000000000000000000000000000000000000000000000000000000000004d940000000000000000000000000000000000000000000000000000000000004d960000000000000000000000000000000000000000000000000000000000004d980000000000000000000000000000000000000000000000000000000000004d9a0000000000000000000000000000000000000000000000000000000000004d9c0000000000000000000000000000000000000000000000000000000000004d9e0000000000000000000000000000000000000000000000000000000000004da00000000000000000000000000000000000000000000000000000000000004da20000000000000000000000000000000000000000000000000000000000004da40000000000000000000000000000000000000000000000000000000000004da60000000000000000000000000000000000000000000000000000000000004da80000000000000000000000000000000000000000000000000000000000004daa0000000000000000000000000000000000000000000000000000000000004dac0000000000000000000000000000000000000000000000000000000000004dae0000000000000000000000000000000000000000000000000000000000004db00000000000000000000000000000000000000000000000000000000000004db20000000000000000000000000000000000000000000000000000000000004db40000000000000000000000000000000000000000000000000000000000004db60000000000000000000000000000000000000000000000000000000000004db80000000000000000000000000000000000000000000000000000000000004dba0000000000000000000000000000000000000000000000000000000000004dbc0000000000000000000000000000000000000000000000000000000000004dbe0000000000000000000000000000000000000000000000000000000000004dc00000000000000000000000000000000000000000000000000000000000004dc20000000000000000000000000000000000000000000000000000000000004dc40000000000000000000000000000000000000000000000000000000000004dc60000000000000000000000000000000000000000000000000000000000004dc80000000000000000000000000000000000000000000000000000000000004dca0000000000000000000000000000000000000000000000000000000000004dcc0000000000000000000000000000000000000000000000000000000000004dce0000000000000000000000000000000000000000000000000000000000004dd00000000000000000000000000000000000000000000000000000000000004dd20000000000000000000000000000000000000000000000000000000000004dd40000000000000000000000000000000000000000000000000000000000004dd60000000000000000000000000000000000000000000000000000000000004dd80000000000000000000000000000000000000000000000000000000000004dda0000000000000000000000000000000000000000000000000000000000004ddc0000000000000000000000000000000000000000000000000000000000004dde0000000000000000000000000000000000000000000000000000000000004de00000000000000000000000000000000000000000000000000000000000004de20000000000000000000000000000000000000000000000000000000000004de40000000000000000000000000000000000000000000000000000000000004de60000000000000000000000000000000000000000000000000000000000004de80000000000000000000000000000000000000000000000000000000000004dea0000000000000000000000000000000000000000000000000000000000004dec0000000000000000000000000000000000000000000000000000000000004dee0000000000000000000000000000000000000000000000000000000000004df00000000000000000000000000000000000000000000000000000000000004df20000000000000000000000000000000000000000000000000000000000004df40000000000000000000000000000000000000000000000000000000000004df60000000000000000000000000000000000000000000000000000000000004df80000000000000000000000000000000000000000000000000000000000004dfa0000000000000000000000000000000000000000000000000000000000004dfc0000000000000000000000000000000000000000000000000000000000004dfe0000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004e020000000000000000000000000000000000000000000000000000000000004e040000000000000000000000000000000000000000000000000000000000004e060000000000000000000000000000000000000000000000000000000000004e080000000000000000000000000000000000000000000000000000000000004e0a0000000000000000000000000000000000000000000000000000000000004e0c0000000000000000000000000000000000000000000000000000000000004e0e0000000000000000000000000000000000000000000000000000000000004e100000000000000000000000000000000000000000000000000000000000004e120000000000000000000000000000000000000000000000000000000000004e140000000000000000000000000000000000000000000000000000000000004e160000000000000000000000000000000000000000000000000000000000004e180000000000000000000000000000000000000000000000000000000000004e1a0000000000000000000000000000000000000000000000000000000000004e1c0000000000000000000000000000000000000000000000000000000000004e1e0000000000000000000000000000000000000000000000000000000000004e200000000000000000000000000000000000000000000000000000000000004e220000000000000000000000000000000000000000000000000000000000004e240000000000000000000000000000000000000000000000000000000000004e260000000000000000000000000000000000000000000000000000000000004e280000000000000000000000000000000000000000000000000000000000004e2a0000000000000000000000000000000000000000000000000000000000004e2c0000000000000000000000000000000000000000000000000000000000004e2e0000000000000000000000000000000000000000000000000000000000004e300000000000000000000000000000000000000000000000000000000000004e320000000000000000000000000000000000000000000000000000000000004e340000000000000000000000000000000000000000000000000000000000004e360000000000000000000000000000000000000000000000000000000000004e380000000000000000000000000000000000000000000000000000000000004e3a0000000000000000000000000000000000000000000000000000000000004e3c0000000000000000000000000000000000000000000000000000000000004e3e0000000000000000000000000000000000000000000000000000000000004e400000000000000000000000000000000000000000000000000000000000004e420000000000000000000000000000000000000000000000000000000000004e440000000000000000000000000000000000000000000000000000000000004e460000000000000000000000000000000000000000000000000000000000004e480000000000000000000000000000000000000000000000000000000000004e4a0000000000000000000000000000000000000000000000000000000000004e4c0000000000000000000000000000000000000000000000000000000000004e4e0000000000000000000000000000000000000000000000000000000000004e500000000000000000000000000000000000000000000000000000000000004e520000000000000000000000000000000000000000000000000000000000004e540000000000000000000000000000000000000000000000000000000000004e560000000000000000000000000000000000000000000000000000000000004e580000000000000000000000000000000000000000000000000000000000004e5a0000000000000000000000000000000000000000000000000000000000004e5c0000000000000000000000000000000000000000000000000000000000004e5e0000000000000000000000000000000000000000000000000000000000004e600000000000000000000000000000000000000000000000000000000000004e620000000000000000000000000000000000000000000000000000000000004e640000000000000000000000000000000000000000000000000000000000004e660000000000000000000000000000000000000000000000000000000000004e680000000000000000000000000000000000000000000000000000000000004e6a0000000000000000000000000000000000000000000000000000000000004e6c0000000000000000000000000000000000000000000000000000000000004e6e0000000000000000000000000000000000000000000000000000000000004e700000000000000000000000000000000000000000000000000000000000004e720000000000000000000000000000000000000000000000000000000000004e740000000000000000000000000000000000000000000000000000000000004e760000000000000000000000000000000000000000000000000000000000004e780000000000000000000000000000000000000000000000000000000000004e7a0000000000000000000000000000000000000000000000000000000000004e7c0000000000000000000000000000000000000000000000000000000000004e7e0000000000000000000000000000000000000000000000000000000000004e800000000000000000000000000000000000000000000000000000000000004e820000000000000000000000000000000000000000000000000000000000004e840000000000000000000000000000000000000000000000000000000000004e860000000000000000000000000000000000000000000000000000000000004e880000000000000000000000000000000000000000000000000000000000004e8a0000000000000000000000000000000000000000000000000000000000004e8c0000000000000000000000000000000000000000000000000000000000004e8e0000000000000000000000000000000000000000000000000000000000004e900000000000000000000000000000000000000000000000000000000000004e920000000000000000000000000000000000000000000000000000000000004e940000000000000000000000000000000000000000000000000000000000004e960000000000000000000000000000000000000000000000000000000000004e980000000000000000000000000000000000000000000000000000000000004e9a0000000000000000000000000000000000000000000000000000000000004e9c0000000000000000000000000000000000000000000000000000000000004e9e0000000000000000000000000000000000000000000000000000000000004ea00000000000000000000000000000000000000000000000000000000000004ea20000000000000000000000000000000000000000000000000000000000004ea40000000000000000000000000000000000000000000000000000000000004ea60000000000000000000000000000000000000000000000000000000000004ea80000000000000000000000000000000000000000000000000000000000004eaa0000000000000000000000000000000000000000000000000000000000004eac0000000000000000000000000000000000000000000000000000000000004eae0000000000000000000000000000000000000000000000000000000000004eb00000000000000000000000000000000000000000000000000000000000004eb20000000000000000000000000000000000000000000000000000000000004eb40000000000000000000000000000000000000000000000000000000000004eb60000000000000000000000000000000000000000000000000000000000004eb80000000000000000000000000000000000000000000000000000000000004eba0000000000000000000000000000000000000000000000000000000000004ebc0000000000000000000000000000000000000000000000000000000000004ebe0000000000000000000000000000000000000000000000000000000000004ec00000000000000000000000000000000000000000000000000000000000004ec20000000000000000000000000000000000000000000000000000000000004ec40000000000000000000000000000000000000000000000000000000000004ec60000000000000000000000000000000000000000000000000000000000004ec80000000000000000000000000000000000000000000000000000000000004eca0000000000000000000000000000000000000000000000000000000000004ecc0000000000000000000000000000000000000000000000000000000000004ece0000000000000000000000000000000000000000000000000000000000004ed00000000000000000000000000000000000000000000000000000000000004ed20000000000000000000000000000000000000000000000000000000000004ed40000000000000000000000000000000000000000000000000000000000004ed60000000000000000000000000000000000000000000000000000000000004ed80000000000000000000000000000000000000000000000000000000000004eda0000000000000000000000000000000000000000000000000000000000004edc0000000000000000000000000000000000000000000000000000000000004ede0000000000000000000000000000000000000000000000000000000000004ee00000000000000000000000000000000000000000000000000000000000004ee20000000000000000000000000000000000000000000000000000000000004ee40000000000000000000000000000000000000000000000000000000000004ee60000000000000000000000000000000000000000000000000000000000004ee80000000000000000000000000000000000000000000000000000000000004eea0000000000000000000000000000000000000000000000000000000000004eec0000000000000000000000000000000000000000000000000000000000004eee0000000000000000000000000000000000000000000000000000000000004ef00000000000000000000000000000000000000000000000000000000000004ef20000000000000000000000000000000000000000000000000000000000004ef40000000000000000000000000000000000000000000000000000000000004ef60000000000000000000000000000000000000000000000000000000000004ef80000000000000000000000000000000000000000000000000000000000004efa0000000000000000000000000000000000000000000000000000000000004efc0000000000000000000000000000000000000000000000000000000000004efe0000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000004f020000000000000000000000000000000000000000000000000000000000004f040000000000000000000000000000000000000000000000000000000000004f060000000000000000000000000000000000000000000000000000000000004f080000000000000000000000000000000000000000000000000000000000004f0a0000000000000000000000000000000000000000000000000000000000004f0c0000000000000000000000000000000000000000000000000000000000004f0e0000000000000000000000000000000000000000000000000000000000004f100000000000000000000000000000000000000000000000000000000000004f120000000000000000000000000000000000000000000000000000000000004f140000000000000000000000000000000000000000000000000000000000004f160000000000000000000000000000000000000000000000000000000000004f180000000000000000000000000000000000000000000000000000000000004f1a0000000000000000000000000000000000000000000000000000000000004f1c0000000000000000000000000000000000000000000000000000000000004f1e0000000000000000000000000000000000000000000000000000000000004f200000000000000000000000000000000000000000000000000000000000004f220000000000000000000000000000000000000000000000000000000000004f240000000000000000000000000000000000000000000000000000000000004f260000000000000000000000000000000000000000000000000000000000004f280000000000000000000000000000000000000000000000000000000000004f2a0000000000000000000000000000000000000000000000000000000000004f2c0000000000000000000000000000000000000000000000000000000000004f2e0000000000000000000000000000000000000000000000000000000000004f300000000000000000000000000000000000000000000000000000000000004f320000000000000000000000000000000000000000000000000000000000004f340000000000000000000000000000000000000000000000000000000000004f360000000000000000000000000000000000000000000000000000000000004f380000000000000000000000000000000000000000000000000000000000004f3a0000000000000000000000000000000000000000000000000000000000004f3c0000000000000000000000000000000000000000000000000000000000004f3e0000000000000000000000000000000000000000000000000000000000004f400000000000000000000000000000000000000000000000000000000000004f420000000000000000000000000000000000000000000000000000000000004f440000000000000000000000000000000000000000000000000000000000004f460000000000000000000000000000000000000000000000000000000000004f480000000000000000000000000000000000000000000000000000000000004f4a0000000000000000000000000000000000000000000000000000000000004f4c0000000000000000000000000000000000000000000000000000000000004f4e0000000000000000000000000000000000000000000000000000000000004f500000000000000000000000000000000000000000000000000000000000004f520000000000000000000000000000000000000000000000000000000000004f540000000000000000000000000000000000000000000000000000000000004f560000000000000000000000000000000000000000000000000000000000004f580000000000000000000000000000000000000000000000000000000000004f5a0000000000000000000000000000000000000000000000000000000000004f5c0000000000000000000000000000000000000000000000000000000000004f5e0000000000000000000000000000000000000000000000000000000000004f600000000000000000000000000000000000000000000000000000000000004f620000000000000000000000000000000000000000000000000000000000004f640000000000000000000000000000000000000000000000000000000000004f660000000000000000000000000000000000000000000000000000000000004f680000000000000000000000000000000000000000000000000000000000004f6a0000000000000000000000000000000000000000000000000000000000004f6c0000000000000000000000000000000000000000000000000000000000004f6e0000000000000000000000000000000000000000000000000000000000004f700000000000000000000000000000000000000000000000000000000000004f720000000000000000000000000000000000000000000000000000000000004f740000000000000000000000000000000000000000000000000000000000004f760000000000000000000000000000000000000000000000000000000000004f780000000000000000000000000000000000000000000000000000000000004f7a0000000000000000000000000000000000000000000000000000000000004f7c0000000000000000000000000000000000000000000000000000000000004f7e0000000000000000000000000000000000000000000000000000000000004f800000000000000000000000000000000000000000000000000000000000004f820000000000000000000000000000000000000000000000000000000000004f840000000000000000000000000000000000000000000000000000000000004f860000000000000000000000000000000000000000000000000000000000004f880000000000000000000000000000000000000000000000000000000000004f8a0000000000000000000000000000000000000000000000000000000000004f8c0000000000000000000000000000000000000000000000000000000000004f8e0000000000000000000000000000000000000000000000000000000000004f900000000000000000000000000000000000000000000000000000000000004f920000000000000000000000000000000000000000000000000000000000004f940000000000000000000000000000000000000000000000000000000000004f960000000000000000000000000000000000000000000000000000000000004f980000000000000000000000000000000000000000000000000000000000004f9a0000000000000000000000000000000000000000000000000000000000004f9c0000000000000000000000000000000000000000000000000000000000004f9e0000000000000000000000000000000000000000000000000000000000004fa00000000000000000000000000000000000000000000000000000000000004fa20000000000000000000000000000000000000000000000000000000000004fa40000000000000000000000000000000000000000000000000000000000004fa60000000000000000000000000000000000000000000000000000000000004fa80000000000000000000000000000000000000000000000000000000000004faa0000000000000000000000000000000000000000000000000000000000004fac0000000000000000000000000000000000000000000000000000000000004fae0000000000000000000000000000000000000000000000000000000000004fb00000000000000000000000000000000000000000000000000000000000004fb20000000000000000000000000000000000000000000000000000000000004fb40000000000000000000000000000000000000000000000000000000000004fb60000000000000000000000000000000000000000000000000000000000004fb80000000000000000000000000000000000000000000000000000000000004fba0000000000000000000000000000000000000000000000000000000000004fbc0000000000000000000000000000000000000000000000000000000000004fbe0000000000000000000000000000000000000000000000000000000000004fc00000000000000000000000000000000000000000000000000000000000004fc20000000000000000000000000000000000000000000000000000000000004fc40000000000000000000000000000000000000000000000000000000000004fc60000000000000000000000000000000000000000000000000000000000004fc80000000000000000000000000000000000000000000000000000000000004fca0000000000000000000000000000000000000000000000000000000000004fcc0000000000000000000000000000000000000000000000000000000000004fce0000000000000000000000000000000000000000000000000000000000004fd00000000000000000000000000000000000000000000000000000000000004fd20000000000000000000000000000000000000000000000000000000000004fd40000000000000000000000000000000000000000000000000000000000004fd60000000000000000000000000000000000000000000000000000000000004fd80000000000000000000000000000000000000000000000000000000000004fda0000000000000000000000000000000000000000000000000000000000004fdc0000000000000000000000000000000000000000000000000000000000004fde0000000000000000000000000000000000000000000000000000000000004fe00000000000000000000000000000000000000000000000000000000000004fe20000000000000000000000000000000000000000000000000000000000004fe40000000000000000000000000000000000000000000000000000000000004fe60000000000000000000000000000000000000000000000000000000000004fe80000000000000000000000000000000000000000000000000000000000004fea0000000000000000000000000000000000000000000000000000000000004fec0000000000000000000000000000000000000000000000000000000000004fee0000000000000000000000000000000000000000000000000000000000004ff00000000000000000000000000000000000000000000000000000000000004ff20000000000000000000000000000000000000000000000000000000000004ff40000000000000000000000000000000000000000000000000000000000004ff60000000000000000000000000000000000000000000000000000000000004ff80000000000000000000000000000000000000000000000000000000000004ffa0000000000000000000000000000000000000000000000000000000000004ffc0000000000000000000000000000000000000000000000000000000000004ffe00000000000000000000000000000000000000000000000000000000000050000 (327744 bytes)]
+ `,
)
expect(() =>
AbiParameters.decode(AbiParameters.from(arr4), p2),
From b010f6444d56184917a5c34e75ac8c4326a93dff Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:34:37 +1000
Subject: [PATCH 054/192] revert(block): drop MissingFieldError throw from
fromRpc, keep totalDifficulty undefined preservation
Per design preference: fromRpc methods should not make fields required.
Reverts the throw added in 9fdaeee4 while keeping the totalDifficulty=undefined fix.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1976-9c6f-745e-87d8-d00af1fe5aaf
---
...ock-state-block-fromrpc-required-fields.md | 2 +-
src/core/Block.ts | 28 ++++-------------
src/core/_test/Block.test.ts | 30 -------------------
3 files changed, 7 insertions(+), 53 deletions(-)
diff --git a/.changeset/wave-0-block-state-block-fromrpc-required-fields.md b/.changeset/wave-0-block-state-block-fromrpc-required-fields.md
index ff78a4fb..6aa73909 100644
--- a/.changeset/wave-0-block-state-block-fromrpc-required-fields.md
+++ b/.changeset/wave-0-block-state-block-fromrpc-required-fields.md
@@ -2,4 +2,4 @@
"ox": patch
---
-Made `Block.fromRpc` throw `Block.MissingFieldError` when a required Block field is absent and preserved `totalDifficulty` as `undefined` instead of silently coercing missing required fields and the optional `totalDifficulty` to `0n`.
+Preserved `Block.fromRpc().totalDifficulty` as `undefined` instead of silently coercing missing values to `0n`.
diff --git a/src/core/Block.ts b/src/core/Block.ts
index aea9c65d..8cb74e89 100644
--- a/src/core/Block.ts
+++ b/src/core/Block.ts
@@ -1,5 +1,5 @@
import type * as Address from './Address.js'
-import * as Errors from './Errors.js'
+import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
import type { Compute, OneOf } from './internal/types.js'
import * as Transaction from './Transaction.js'
@@ -299,12 +299,12 @@ export function fromRpc<
excessBlobGas: block.excessBlobGas
? BigInt(block.excessBlobGas)
: undefined,
- gasLimit: requiredBigInt(block.gasLimit, 'gasLimit'),
- gasUsed: requiredBigInt(block.gasUsed, 'gasUsed'),
+ gasLimit: BigInt(block.gasLimit ?? 0n),
+ gasUsed: BigInt(block.gasUsed ?? 0n),
number: block.number ? BigInt(block.number) : null,
- size: requiredBigInt(block.size, 'size'),
+ size: BigInt(block.size ?? 0n),
stateRoot: block.stateRoot,
- timestamp: requiredBigInt(block.timestamp, 'timestamp'),
+ timestamp: BigInt(block.timestamp ?? 0n),
totalDifficulty:
typeof block.totalDifficulty !== 'undefined' &&
block.totalDifficulty !== null
@@ -324,21 +324,5 @@ export declare namespace fromRpc {
includeTransactions?: includeTransactions | boolean | undefined
}
- type ErrorType = MissingFieldError | Errors.GlobalErrorType
-}
-
-/** Thrown when a required Block field is missing in an RPC response. */
-export class MissingFieldError extends Errors.BaseError {
- override readonly name = 'Block.MissingFieldError'
-
- constructor({ field }: { field: string }) {
- super(`Required Block field \`${field}\` is missing.`)
- }
-}
-
-/** @internal */
-function requiredBigInt(value: Hex.Hex | bigint | undefined, field: string) {
- if (typeof value === 'undefined' || value === null)
- throw new MissingFieldError({ field })
- return BigInt(value)
+ type ErrorType = Errors.GlobalErrorType
}
diff --git a/src/core/_test/Block.test.ts b/src/core/_test/Block.test.ts
index 7bcdda39..1c6be5d0 100644
--- a/src/core/_test/Block.test.ts
+++ b/src/core/_test/Block.test.ts
@@ -83,35 +83,6 @@ describe('fromRpc', () => {
expect(block).toBeNull()
})
- test('behavior: missing required field throws', () => {
- expect(() =>
- // @ts-expect-error
- Block.fromRpc({
- extraData: '0x',
- hash: '0xebc3644804e4040c0a74c5a5bbbc6b46a71a5d4010fe0c92ebb2fdf4a43ea5dd',
- logsBloom: '0x',
- miner: '0x0000000000000000000000000000000000000000',
- mixHash:
- '0x0000000000000000000000000000000000000000000000000000000000000000',
- nonce: '0x0000000000000000',
- parentHash:
- '0xe55516ad8029e53cd32087f14653d851401b05245abb1b2d6ed4ddcc597ac5a6',
- receiptsRoot:
- '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
- sha3Uncles:
- '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
- stateRoot:
- '0x0000000000000000000000000000000000000000000000000000000000000000',
- transactions: [],
- transactionsRoot:
- '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
- uncles: [],
- }),
- ).toThrowErrorMatchingInlineSnapshot(
- '[Block.MissingFieldError: Required Block field `gasLimit` is missing.]',
- )
- })
-
test('behavior: optional totalDifficulty preserved as undefined', () => {
const block = Block.fromRpc({
extraData: '0x',
@@ -665,7 +636,6 @@ test('exports', () => {
[
"toRpc",
"fromRpc",
- "MissingFieldError",
]
`)
})
From 88fa2d09a3cf4377f3c1d85fe20a89fd3f38f0bb Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:40:02 +1000
Subject: [PATCH 055/192] revert(tempo): keep `data` (not `input`) on calls[]
in Transaction.toRpc
Reverts 62233c46. Tempo Transaction.calls[] uses `data`, not `input`.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1976-9c6f-745e-87d8-d00af1fe5aaf
---
.changeset/wave-0-tempo-transaction-rpc-input.md | 5 -----
src/tempo/Transaction.test.ts | 6 +++---
src/tempo/Transaction.ts | 2 +-
3 files changed, 4 insertions(+), 9 deletions(-)
delete mode 100644 .changeset/wave-0-tempo-transaction-rpc-input.md
diff --git a/.changeset/wave-0-tempo-transaction-rpc-input.md b/.changeset/wave-0-tempo-transaction-rpc-input.md
deleted file mode 100644
index 758e792c..00000000
--- a/.changeset/wave-0-tempo-transaction-rpc-input.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"ox": patch
----
-
-Fixed `tempo.Transaction.toRpc` to emit each call's data as `input` to match the `TempoRpc` schema and round-trip with `tempo.Transaction.fromRpc`.
diff --git a/src/tempo/Transaction.test.ts b/src/tempo/Transaction.test.ts
index 6cb319ec..4923f070 100644
--- a/src/tempo/Transaction.test.ts
+++ b/src/tempo/Transaction.test.ts
@@ -304,7 +304,7 @@ describe('toRpc', () => {
"blockNumber": "0x12f296f",
"calls": [
{
- "input": "0xdeadbeef",
+ "data": "0xdeadbeef",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"value": "0x9b6e64a8ec60000",
},
@@ -380,7 +380,7 @@ describe('toRpc', () => {
"blockNumber": "0x12f296f",
"calls": [
{
- "input": "0xdeadbeef",
+ "data": "0xdeadbeef",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"value": "0x9b6e64a8ec60000",
},
@@ -476,7 +476,7 @@ describe('toRpc', () => {
"blockNumber": "0x12f296f",
"calls": [
{
- "input": "0xdeadbeef",
+ "data": "0xdeadbeef",
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"value": "0x9b6e64a8ec60000",
},
diff --git a/src/tempo/Transaction.ts b/src/tempo/Transaction.ts
index 5de7cd10..e8f417d1 100644
--- a/src/tempo/Transaction.ts
+++ b/src/tempo/Transaction.ts
@@ -307,7 +307,7 @@ export function toRpc(
rpc.calls = transaction.calls.map((call) => ({
to: call.to,
value: call.value ? Hex.fromNumber(call.value) : undefined,
- input: call.data,
+ data: call.data,
}))
if (transaction.feeToken) rpc.feeToken = transaction.feeToken
if (transaction.keyAuthorization)
From b1221650e4e1cad951e4c80d8157762121449f3d Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:46:56 +1000
Subject: [PATCH 056/192] fix(bytes,rlp): even-pad odd-nibble hex from
`Hex.fromNumber` before strict parse
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
.changeset/wave-0-bytes-rlp-odd-length-pad.md | 5 +++++
src/core/Bytes.ts | 7 ++++++-
src/core/Rlp.ts | 9 ++++++++-
3 files changed, 19 insertions(+), 2 deletions(-)
create mode 100644 .changeset/wave-0-bytes-rlp-odd-length-pad.md
diff --git a/.changeset/wave-0-bytes-rlp-odd-length-pad.md b/.changeset/wave-0-bytes-rlp-odd-length-pad.md
new file mode 100644
index 00000000..4b32acff
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Bytes.ts b/src/core/Bytes.ts
index f6016658..4ad8566d 100644
--- a/src/core/Bytes.ts
+++ b/src/core/Bytes.ts
@@ -286,7 +286,12 @@ export function fromNumber(
options?: fromNumber.Options | undefined,
) {
const hex = Hex.fromNumber(value, options)
- return fromHex(hex)
+ // Hex.fromNumber may produce odd-nibble hex (e.g. `0x7`, total length 3);
+ // even-pad before handing to the strict `fromHex` parser.
+ const evenHex = (
+ (hex.length & 1) === 1 ? `0x0${hex.slice(2)}` : hex
+ ) as Hex.Hex
+ return fromHex(evenHex)
}
export declare namespace fromNumber {
diff --git a/src/core/Rlp.ts b/src/core/Rlp.ts
index 5aad2dc7..77334c79 100644
--- a/src/core/Rlp.ts
+++ b/src/core/Rlp.ts
@@ -323,7 +323,14 @@ function getEncodableList(list: Encodable[]): Encodable {
function getEncodableBytes(bytesOrHex: Bytes.Bytes | Hex.Hex): Encodable {
const bytes =
- typeof bytesOrHex === 'string' ? Bytes.fromHex(bytesOrHex) : bytesOrHex
+ typeof bytesOrHex === 'string'
+ ? // Even-pad odd-length hex (e.g. `0x1`) before strict parsing.
+ Bytes.fromHex(
+ ((bytesOrHex.length & 1) === 1
+ ? `0x0${bytesOrHex.slice(2)}`
+ : bytesOrHex) as Hex.Hex,
+ )
+ : bytesOrHex
const sizeOfBytesLength = getSizeOfLength(bytes.length)
const length = (() => {
From 642423c72632c165b3eeb52a2110847959dc5ab2 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:47:00 +1000
Subject: [PATCH 057/192] fix(transactions): preserve legacy `v` from RPC in
`Transaction.fromRpc`
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
.changeset/wave-0-transactions-legacy-v-fromrpc.md | 5 +++++
src/core/Transaction.ts | 6 +++++-
src/core/_test/Transaction.test.ts | 6 +++---
3 files changed, 13 insertions(+), 4 deletions(-)
create mode 100644 .changeset/wave-0-transactions-legacy-v-fromrpc.md
diff --git a/.changeset/wave-0-transactions-legacy-v-fromrpc.md b/.changeset/wave-0-transactions-legacy-v-fromrpc.md
new file mode 100644
index 00000000..10461804
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/Transaction.ts b/src/core/Transaction.ts
index b8d667a8..e5582fe5 100644
--- a/src/core/Transaction.ts
+++ b/src/core/Transaction.ts
@@ -316,7 +316,11 @@ export function fromRpc<
if (transaction.type)
transaction_.type =
(fromRpcType as any)[transaction.type] ?? transaction.type
- if (signature) transaction_.v = Signature.yParityToV(signature.yParity)
+ if (signature)
+ transaction_.v =
+ transaction.type === '0x0' && typeof transaction.v !== 'undefined'
+ ? Number(transaction.v)
+ : Signature.yParityToV(signature.yParity)
return transaction_ as never
}
diff --git a/src/core/_test/Transaction.test.ts b/src/core/_test/Transaction.test.ts
index eb907946..cbdbd501 100644
--- a/src/core/_test/Transaction.test.ts
+++ b/src/core/_test/Transaction.test.ts
@@ -51,7 +51,7 @@ describe('fromRpc', () => {
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"transactionIndex": 2,
"type": "legacy",
- "v": 27,
+ "v": 0,
"value": 700000000000000000n,
"yParity": 0,
}
@@ -94,7 +94,7 @@ describe('fromRpc', () => {
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"transactionIndex": 2,
"type": "legacy",
- "v": 27,
+ "v": 0,
"value": 0n,
"yParity": 0,
}
@@ -143,7 +143,7 @@ describe('fromRpc', () => {
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"transactionIndex": null,
"type": "legacy",
- "v": 27,
+ "v": 0,
"value": 700000000000000000n,
"yParity": 0,
}
From f646084568d8cc8770424d084c0026aeaba41bd6 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:47:20 +1000
Subject: [PATCH 058/192] chore(tests): refresh Bytes, Base58, PublicKey
snapshots after error and trim updates
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
src/core/_test/Base58.test.ts | 3 ++-
src/core/_test/Bytes.test.ts | 18 +++++-------------
src/core/_test/PublicKey.test.ts | 5 +++--
3 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/src/core/_test/Base58.test.ts b/src/core/_test/Base58.test.ts
index 54c50119..a45dfb8e 100644
--- a/src/core/_test/Base58.test.ts
+++ b/src/core/_test/Base58.test.ts
@@ -54,7 +54,7 @@ describe('toHex', () => {
expect(Base58.toHex('233QC4')).toBe('0x287fb4cd')
expect(Base58.toHex('11233QC4')).toBe('0x0000287fb4cd')
expect(() => Base58.toHex('233QC4I')).toThrowErrorMatchingInlineSnapshot(
- '[Error: invalid base58 character: I]',
+ `[Base58.InvalidCharacterError: Invalid Base58 character: "I".]`,
)
})
})
@@ -79,6 +79,7 @@ test('exports', () => {
"toBytes",
"toHex",
"toString",
+ "InvalidCharacterError",
]
`)
})
diff --git a/src/core/_test/Bytes.test.ts b/src/core/_test/Bytes.test.ts
index a4d8f5bb..15edcef8 100644
--- a/src/core/_test/Bytes.test.ts
+++ b/src/core/_test/Bytes.test.ts
@@ -196,13 +196,11 @@ describe('fromHex', () => {
97,
]
`)
- expect(Bytes.fromHex('0xabcde')).toMatchInlineSnapshot(
+ expect(() => Bytes.fromHex('0xabcde')).toThrowErrorMatchingInlineSnapshot(
`
- Uint8Array [
- 10,
- 188,
- 222,
- ]
+ [Hex.InvalidLengthError: Hex value \`"0xabcde"\` is an odd length (5 nibbles).
+
+ It must be an even length.]
`,
)
expect(Bytes.fromHex('0x616263')).toMatchInlineSnapshot(
@@ -1560,13 +1558,7 @@ describe('trim', () => {
test('default', () => {
expect(
Bytes.trimLeft(new Uint8Array([0, 0, 0, 0, 0])),
- ).toMatchInlineSnapshot(
- `
- Uint8Array [
- 0,
- ]
- `,
- )
+ ).toMatchInlineSnapshot('Uint8Array []')
expect(
Bytes.trimLeft(
diff --git a/src/core/_test/PublicKey.test.ts b/src/core/_test/PublicKey.test.ts
index 2b5f1c9e..2cc3b80d 100644
--- a/src/core/_test/PublicKey.test.ts
+++ b/src/core/_test/PublicKey.test.ts
@@ -257,8 +257,9 @@ describe('PublicKey.fromBytes', () => {
const serialized = Bytes.fromHex(
'0x058318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5',
)
- expect(() => PublicKey.fromBytes(serialized))
- .toThrowErrorMatchingInlineSnapshot(`
+ expect(() =>
+ PublicKey.fromBytes(serialized),
+ ).toThrowErrorMatchingInlineSnapshot(`
[PublicKey.InvalidPrefixError: Prefix "5" is invalid.
Details: Prefix must be 4 for uncompressed public keys.]
From 0ea10571079cf683a29c1ba290c7319f83286191 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:48:47 +1000
Subject: [PATCH 059/192] fix(transactions): preserve or derive EIP-155 `v` in
`TxEnvelopeLegacy.toRpc`
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
.../wave-0-transactions-legacy-v-torpc.md | 5 ++++
src/core/TxEnvelopeLegacy.ts | 14 ++++++++++-
.../_test/TransactionEnvelopeLegacy.test.ts | 24 ++++++++++++++++++-
3 files changed, 41 insertions(+), 2 deletions(-)
create mode 100644 .changeset/wave-0-transactions-legacy-v-torpc.md
diff --git a/.changeset/wave-0-transactions-legacy-v-torpc.md b/.changeset/wave-0-transactions-legacy-v-torpc.md
new file mode 100644
index 00000000..8400d089
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/TxEnvelopeLegacy.ts b/src/core/TxEnvelopeLegacy.ts
index 65560ab9..9f90b171 100644
--- a/src/core/TxEnvelopeLegacy.ts
+++ b/src/core/TxEnvelopeLegacy.ts
@@ -592,7 +592,19 @@ export function toRpc(envelope: Omit): Rpc {
...(signature
? {
...Signature.toRpc(signature),
- v: signature.yParity === 0 ? '0x1b' : '0x1c',
+ v: (() => {
+ // Prefer the original `v` from the envelope when present
+ // (preserves EIP-155 `v = chainId * 2 + 35 + yParity`).
+ if (typeof envelope.v === 'number')
+ return Hex.fromNumber(envelope.v)
+ // Otherwise derive EIP-155 `v` from `chainId` + `yParity`.
+ if (typeof envelope.chainId === 'number' && envelope.chainId > 0)
+ return Hex.fromNumber(
+ envelope.chainId * 2 + 35 + signature.yParity,
+ )
+ // Fall back to pre-EIP-155 `27`/`28`.
+ return signature.yParity === 0 ? '0x1b' : '0x1c'
+ })(),
}
: {}),
} as never
diff --git a/src/core/_test/TransactionEnvelopeLegacy.test.ts b/src/core/_test/TransactionEnvelopeLegacy.test.ts
index 94e387e4..7f2934a0 100644
--- a/src/core/_test/TransactionEnvelopeLegacy.test.ts
+++ b/src/core/_test/TransactionEnvelopeLegacy.test.ts
@@ -859,7 +859,7 @@ describe('toRpc', () => {
"s": "0x0000000000000000000000000000000000000000000000000000000000000002",
"to": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
"type": "0x0",
- "v": "0x1b",
+ "v": "0x25",
"value": "0xde0b6b3a7640000",
"yParity": "0x0",
}
@@ -880,6 +880,28 @@ describe('toRpc', () => {
`)
})
+ test('behavior: preserves explicit `v`', () => {
+ const transaction = TxEnvelopeLegacy.toRpc({
+ chainId: 1,
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ r: 1n,
+ s: 2n,
+ v: 38,
+ yParity: 1,
+ })
+ expect(transaction.v).toBe('0x26')
+ })
+
+ test('behavior: pre-EIP-155 (no chainId)', () => {
+ const transaction = TxEnvelopeLegacy.toRpc({
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ r: 1n,
+ s: 2n,
+ yParity: 1,
+ })
+ expect(transaction.v).toBe('0x1c')
+ })
+
test('behavior: network', async () => {
const nonce = await anvilMainnet.request({
method: 'eth_getTransactionCount',
From ef8a468323c9cbda0bed8a73347ad9bd42e03ceb Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:51:11 +1000
Subject: [PATCH 060/192] fix(transactions): honor `input` alias in
`TxEnvelopeEip4844.serialize`
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
.changeset/wave-0-transactions-eip4844-input-alias.md | 5 +++++
src/core/TxEnvelopeEip4844.ts | 3 ++-
2 files changed, 7 insertions(+), 1 deletion(-)
create mode 100644 .changeset/wave-0-transactions-eip4844-input-alias.md
diff --git a/.changeset/wave-0-transactions-eip4844-input-alias.md b/.changeset/wave-0-transactions-eip4844-input-alias.md
new file mode 100644
index 00000000..6d181ec4
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/TxEnvelopeEip4844.ts b/src/core/TxEnvelopeEip4844.ts
index dd890594..66b21d22 100644
--- a/src/core/TxEnvelopeEip4844.ts
+++ b/src/core/TxEnvelopeEip4844.ts
@@ -562,6 +562,7 @@ export function serialize(
maxPriorityFeePerGas,
accessList,
data,
+ input,
} = envelope
assert(envelope)
@@ -578,7 +579,7 @@ export function serialize(
gas ? Hex.fromNumber(gas) : '0x',
to ?? '0x',
value ? Hex.fromNumber(value) : '0x',
- data ?? '0x',
+ data ?? input ?? '0x',
accessTupleList,
maxFeePerBlobGas ? Hex.fromNumber(maxFeePerBlobGas) : '0x',
blobVersionedHashes ?? [],
From f1a57693a4218832981cdc5d87de965ff4fc9b3d Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:51:49 +1000
Subject: [PATCH 061/192] fix(transactions): tighten EIP-4844 blob/sidecar
validation and deserialize diagnostics
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
...-0-transactions-eip4844-blob-validation.md | 5 ++
...ns-eip4844-deserialize-error-attributes.md | 5 ++
...ransactions-eip4844-sidecar-cardinality.md | 5 ++
src/core/TxEnvelopeEip4844.ts | 64 +++++++++++++------
.../_test/TransactionEnvelopeEip4844.test.ts | 20 +++---
5 files changed, 71 insertions(+), 28 deletions(-)
create mode 100644 .changeset/wave-0-transactions-eip4844-blob-validation.md
create mode 100644 .changeset/wave-0-transactions-eip4844-deserialize-error-attributes.md
create mode 100644 .changeset/wave-0-transactions-eip4844-sidecar-cardinality.md
diff --git a/.changeset/wave-0-transactions-eip4844-blob-validation.md b/.changeset/wave-0-transactions-eip4844-blob-validation.md
new file mode 100644
index 00000000..751070f3
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-transactions-eip4844-deserialize-error-attributes.md b/.changeset/wave-0-transactions-eip4844-deserialize-error-attributes.md
new file mode 100644
index 00000000..13980d64
--- /dev/null
+++ b/.changeset/wave-0-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/wave-0-transactions-eip4844-sidecar-cardinality.md b/.changeset/wave-0-transactions-eip4844-sidecar-cardinality.md
new file mode 100644
index 00000000..ab0b9aa8
--- /dev/null
+++ b/.changeset/wave-0-transactions-eip4844-sidecar-cardinality.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Validated sidecar wrapper cardinality in `TxEnvelopeEip4844.deserialize` so that mismatched `blobs` / `commitments` / `proofs` / `blobVersionedHashes` lengths throw `InvalidSerializedError` instead of fabricating `undefined` sidecar entries via blind indexing in `Blobs.toSidecars`.
diff --git a/src/core/TxEnvelopeEip4844.ts b/src/core/TxEnvelopeEip4844.ts
index 66b21d22..8265f532 100644
--- a/src/core/TxEnvelopeEip4844.ts
+++ b/src/core/TxEnvelopeEip4844.ts
@@ -74,20 +74,21 @@ export type Type = 'eip4844'
*/
export function assert(envelope: PartialBy) {
const { blobVersionedHashes } = envelope
- if (blobVersionedHashes) {
- if (blobVersionedHashes.length === 0)
- throw new Blobs.EmptyBlobVersionedHashesError()
- for (const hash of blobVersionedHashes) {
- const size = Hex.size(hash)
- const version = Hex.toNumber(Hex.slice(hash, 0, 1))
- if (size !== 32)
- throw new Blobs.InvalidVersionedHashSizeError({ hash, size })
- if (version !== Kzg.versionedHashVersion)
- throw new Blobs.InvalidVersionedHashVersionError({
- hash,
- version,
- })
- }
+ // EIP-4844 requires at least one versioned blob hash. Treat a missing
+ // field as an empty list to give callers a single, descriptive error
+ // rather than a downstream RLP/serialization failure.
+ if (!blobVersionedHashes || blobVersionedHashes.length === 0)
+ throw new Blobs.EmptyBlobVersionedHashesError()
+ for (const hash of blobVersionedHashes) {
+ const size = Hex.size(hash)
+ const version = Hex.toNumber(Hex.slice(hash, 0, 1))
+ if (size !== 32)
+ throw new Blobs.InvalidVersionedHashSizeError({ hash, size })
+ if (version !== Kzg.versionedHashVersion)
+ throw new Blobs.InvalidVersionedHashVersionError({
+ hash,
+ version,
+ })
}
TxEnvelopeEip1559.assert(
envelope as {} as TxEnvelopeEip1559.TxEnvelopeEip1559,
@@ -172,7 +173,9 @@ export function deserialize(
value,
data,
accessList,
- ...(transactionArray.length > 9
+ maxFeePerBlobGas,
+ blobVersionedHashes,
+ ...(transactionArray.length > 11
? {
yParity,
r,
@@ -203,11 +206,34 @@ export function deserialize(
transaction.maxPriorityFeePerGas = BigInt(maxPriorityFeePerGas)
if (accessList?.length !== 0 && accessList !== '0x')
transaction.accessList = AccessList.fromTupleList(accessList as any)
- if (blobs && commitments && proofs)
- transaction.sidecars = Blobs.toSidecars(blobs as Hex.Hex[], {
- commitments: commitments as Hex.Hex[],
- proofs: proofs as Hex.Hex[],
+ if (blobs && commitments && proofs) {
+ // Validate sidecar wrapper cardinality before zipping; otherwise
+ // `Blobs.toSidecars` blindly indexes `commitments[i]!` / `proofs[i]!`
+ // and fabricates `undefined` entries from a malformed payload.
+ const blobsArr = blobs as readonly Hex.Hex[]
+ const commitmentsArr = commitments as readonly Hex.Hex[]
+ const proofsArr = proofs as readonly Hex.Hex[]
+ const versionedHashesArr = blobVersionedHashes as readonly Hex.Hex[]
+ if (
+ blobsArr.length !== commitmentsArr.length ||
+ blobsArr.length !== proofsArr.length ||
+ blobsArr.length !== versionedHashesArr.length
+ )
+ throw new TransactionEnvelope.InvalidSerializedError({
+ attributes: {
+ blobVersionedHashes,
+ blobs: blobsArr.length,
+ commitments: commitmentsArr.length,
+ proofs: proofsArr.length,
+ },
+ serialized,
+ type,
+ })
+ transaction.sidecars = Blobs.toSidecars(blobsArr as Hex.Hex[], {
+ commitments: commitmentsArr as Hex.Hex[],
+ proofs: proofsArr as Hex.Hex[],
})
+ }
const signature =
r && s && yParity
diff --git a/src/core/_test/TransactionEnvelopeEip4844.test.ts b/src/core/_test/TransactionEnvelopeEip4844.test.ts
index 3be90a06..df30b7d7 100644
--- a/src/core/_test/TransactionEnvelopeEip4844.test.ts
+++ b/src/core/_test/TransactionEnvelopeEip4844.test.ts
@@ -225,7 +225,7 @@ describe('deserialize', () => {
[TransactionEnvelope.InvalidSerializedError: Invalid serialized transaction of type "eip4844" was provided.
Serialized Transaction: "0x03c0"
- Missing Attributes: chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gas, to, value, data, accessList]
+ Missing Attributes: chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gas, to, value, data, accessList, maxFeePerBlobGas, blobVersionedHashes]
`)
})
@@ -238,7 +238,7 @@ describe('deserialize', () => {
[TransactionEnvelope.InvalidSerializedError: Invalid serialized transaction of type "eip4844" was provided.
Serialized Transaction: "0x03c20001"
- Missing Attributes: maxPriorityFeePerGas, maxFeePerGas, gas, to, value, data, accessList]
+ Missing Attributes: maxPriorityFeePerGas, maxFeePerGas, gas, to, value, data, accessList, maxFeePerBlobGas, blobVersionedHashes]
`)
})
@@ -498,13 +498,15 @@ describe('serialize', () => {
})
test('no blobVersionedHashes', () => {
- // @ts-expect-error
- const transaction = TxEnvelopeEip4844.from({
- chainId: 1,
- nonce: 0n,
- })
- const serialized = TxEnvelopeEip4844.serialize(transaction)
- expect(serialized).toMatchInlineSnapshot(`"0x03cb0180808080808080c080c0"`)
+ expect(() =>
+ TxEnvelopeEip4844.from({
+ // @ts-expect-error
+ chainId: 1,
+ nonce: 0n,
+ }),
+ ).toThrowErrorMatchingInlineSnapshot(
+ `[Blobs.EmptyBlobVersionedHashesError: Blob versioned hashes must not be empty.]`,
+ )
})
test('options: signature', async () => {
From c09b14e53bec9c7f96fae5288629ab7adc6077c0 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:53:40 +1000
Subject: [PATCH 062/192] fix(transactions): add missing
`TxEnvelopeEip7702.toRpc`
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
.../wave-0-transactions-eip7702-torpc.md | 5 ++
src/core/TxEnvelopeEip7702.ts | 64 +++++++++++++++++++
.../_test/TransactionEnvelopeEip7702.test.ts | 52 +++++++++++++++
3 files changed, 121 insertions(+)
create mode 100644 .changeset/wave-0-transactions-eip7702-torpc.md
diff --git a/.changeset/wave-0-transactions-eip7702-torpc.md b/.changeset/wave-0-transactions-eip7702-torpc.md
new file mode 100644
index 00000000..f4e6d6dc
--- /dev/null
+++ b/.changeset/wave-0-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/src/core/TxEnvelopeEip7702.ts b/src/core/TxEnvelopeEip7702.ts
index 4a0cfa90..461d4fe5 100644
--- a/src/core/TxEnvelopeEip7702.ts
+++ b/src/core/TxEnvelopeEip7702.ts
@@ -571,6 +571,70 @@ export declare namespace serialize {
| Errors.GlobalErrorType
}
+/**
+ * Converts an {@link ox#TxEnvelopeEip7702.TxEnvelopeEip7702} to an {@link ox#TxEnvelopeEip7702.Rpc}.
+ *
+ * @example
+ * ```ts twoslash
+ * // @noErrors
+ * import { Authorization, RpcRequest, TxEnvelopeEip7702, Value } from 'ox'
+ *
+ * const envelope = TxEnvelopeEip7702.from({
+ * authorizationList: [...],
+ * chainId: 1,
+ * nonce: 0n,
+ * gas: 21000n,
+ * maxFeePerGas: Value.fromGwei('10'),
+ * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ * value: Value.fromEther('1'),
+ * })
+ *
+ * const envelope_rpc = TxEnvelopeEip7702.toRpc(envelope) // [!code focus]
+ *
+ * const request = RpcRequest.from({
+ * id: 0,
+ * method: 'eth_sendTransaction',
+ * params: [envelope_rpc],
+ * })
+ * ```
+ *
+ * @param envelope - The EIP-7702 transaction envelope to convert.
+ * @returns An RPC-formatted EIP-7702 transaction envelope.
+ */
+export function toRpc(envelope: Omit): Rpc {
+ const signature = Signature.extract(envelope)
+
+ return {
+ ...envelope,
+ authorizationList: Authorization.toRpcList(envelope.authorizationList),
+ chainId: Hex.fromNumber(envelope.chainId),
+ data: envelope.data ?? envelope.input,
+ type: '0x4',
+ ...(typeof envelope.gas === 'bigint'
+ ? { gas: Hex.fromNumber(envelope.gas) }
+ : {}),
+ ...(typeof envelope.nonce === 'bigint'
+ ? { nonce: Hex.fromNumber(envelope.nonce) }
+ : {}),
+ ...(typeof envelope.value === 'bigint'
+ ? { value: Hex.fromNumber(envelope.value) }
+ : {}),
+ ...(typeof envelope.maxFeePerGas === 'bigint'
+ ? { maxFeePerGas: Hex.fromNumber(envelope.maxFeePerGas) }
+ : {}),
+ ...(typeof envelope.maxPriorityFeePerGas === 'bigint'
+ ? {
+ maxPriorityFeePerGas: Hex.fromNumber(envelope.maxPriorityFeePerGas),
+ }
+ : {}),
+ ...(signature ? Signature.toRpc(signature) : {}),
+ } as never
+}
+
+export declare namespace toRpc {
+ export type ErrorType = Signature.extract.ErrorType | Errors.GlobalErrorType
+}
+
/**
* Validates a {@link ox#TxEnvelopeEip7702.TxEnvelopeEip7702}. Returns `true` if the envelope is valid, `false` otherwise.
*
diff --git a/src/core/_test/TransactionEnvelopeEip7702.test.ts b/src/core/_test/TransactionEnvelopeEip7702.test.ts
index b0d55f7f..1a1baccc 100644
--- a/src/core/_test/TransactionEnvelopeEip7702.test.ts
+++ b/src/core/_test/TransactionEnvelopeEip7702.test.ts
@@ -909,6 +909,57 @@ describe('serialize', () => {
})
})
+describe('toRpc', () => {
+ test('default', () => {
+ const transaction = TxEnvelopeEip7702.toRpc({
+ authorizationList: [
+ {
+ address: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ chainId: 1,
+ nonce: 0n,
+ r: 1n,
+ s: 2n,
+ yParity: 0,
+ },
+ ],
+ chainId: 1,
+ nonce: 0n,
+ gas: 21000n,
+ maxFeePerGas: 1000000000n,
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ value: 1000000000000000000n,
+ r: 1n,
+ s: 2n,
+ yParity: 0,
+ })
+ expect(transaction).toMatchInlineSnapshot(`
+ {
+ "authorizationList": [
+ {
+ "address": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
+ "chainId": "0x1",
+ "nonce": "0x0",
+ "r": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "s": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "yParity": "0x0",
+ },
+ ],
+ "chainId": "0x1",
+ "data": undefined,
+ "gas": "0x5208",
+ "maxFeePerGas": "0x3b9aca00",
+ "nonce": "0x0",
+ "r": "0x0000000000000000000000000000000000000000000000000000000000000001",
+ "s": "0x0000000000000000000000000000000000000000000000000000000000000002",
+ "to": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
+ "type": "0x4",
+ "value": "0xde0b6b3a7640000",
+ "yParity": "0x0",
+ }
+ `)
+ })
+})
+
describe('validate', () => {
test('default', () => {
expect(
@@ -938,6 +989,7 @@ test('exports', () => {
"getSignPayload",
"hash",
"serialize",
+ "toRpc",
"validate",
]
`)
From c242993cf4bbd2f27874157e17f99dd64bf0e482 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 10:56:45 +1000
Subject: [PATCH 063/192] feat(account-proof): add `fromRpc`/`toRpc` converters
Also unify the RPC-quantity conversion blocks across `Block`, `BlockOverrides`,
and `StateOverrides` behind an internal helper so optional bigint fields with
explicit `'0x0'` round-trip as `0n` instead of being silently dropped by the
previous truthy checks.
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a8-f995-717d-9ca9-b5f6a741d96c
---
.changeset/wave-1-account-proof-converters.md | 5 +
.../wave-1-block-state-quantity-converters.md | 5 +
src/core/AccountProof.ts | 114 ++++++++++++++++-
src/core/Block.ts | 44 ++-----
src/core/BlockOverrides.ts | 99 +++++++--------
src/core/StateOverrides.ts | 23 ++--
src/core/_test/AccountProof.test.ts | 116 +++++++++++++++++-
src/core/internal/quantity.ts | 85 +++++++++++++
8 files changed, 394 insertions(+), 97 deletions(-)
create mode 100644 .changeset/wave-1-account-proof-converters.md
create mode 100644 .changeset/wave-1-block-state-quantity-converters.md
create mode 100644 src/core/internal/quantity.ts
diff --git a/.changeset/wave-1-account-proof-converters.md b/.changeset/wave-1-account-proof-converters.md
new file mode 100644
index 00000000..2e6f89dd
--- /dev/null
+++ b/.changeset/wave-1-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/wave-1-block-state-quantity-converters.md b/.changeset/wave-1-block-state-quantity-converters.md
new file mode 100644
index 00000000..7a9b97ec
--- /dev/null
+++ b/.changeset/wave-1-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/src/core/AccountProof.ts b/src/core/AccountProof.ts
index 74ef26ab..5fc44c17 100644
--- a/src/core/AccountProof.ts
+++ b/src/core/AccountProof.ts
@@ -1,4 +1,7 @@
-import type { Address, Hex } from '../index.js'
+import type * as Address from './Address.js'
+import type * as Errors from './Errors.js'
+import * as Hex from './Hex.js'
+import * as Quantity from './internal/quantity.js'
/** An Account Proof as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/state.yaml). */
export type AccountProof = {
@@ -33,3 +36,112 @@ export type StorageProof = {
/** An RPC Storage Proof as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/state.yaml). */
export type StorageProofRpc = StorageProof
+
+/**
+ * Converts an {@link ox#AccountProof.Rpc} to an {@link ox#AccountProof.AccountProof}.
+ *
+ * @example
+ * ```ts twoslash
+ * import { AccountProof } from 'ox'
+ *
+ * const proof = AccountProof.fromRpc({
+ * address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
+ * balance: '0x1',
+ * codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ * nonce: '0x2',
+ * storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ * accountProof: [],
+ * storageProof: [
+ * {
+ * key: '0x0000000000000000000000000000000000000000000000000000000000000000',
+ * proof: [],
+ * value: '0x3',
+ * },
+ * ],
+ * })
+ * // @log: {
+ * // @log: address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
+ * // @log: balance: 1n,
+ * // @log: codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ * // @log: nonce: 2,
+ * // @log: storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ * // @log: accountProof: [],
+ * // @log: storageProof: [
+ * // @log: {
+ * // @log: key: '0x0000000000000000000000000000000000000000000000000000000000000000',
+ * // @log: proof: [],
+ * // @log: value: 3n,
+ * // @log: },
+ * // @log: ],
+ * // @log: }
+ * ```
+ *
+ * @param proof - The RPC account proof.
+ * @returns An instantiated {@link ox#AccountProof.AccountProof}.
+ */
+export function fromRpc(proof: Rpc): AccountProof {
+ return {
+ address: proof.address,
+ balance: BigInt(proof.balance),
+ codeHash: proof.codeHash,
+ nonce: Number(proof.nonce),
+ storageHash: proof.storageHash,
+ accountProof: proof.accountProof,
+ storageProof: proof.storageProof.map((slot) => ({
+ key: slot.key,
+ proof: slot.proof,
+ value: BigInt(slot.value),
+ })),
+ }
+}
+
+export declare namespace fromRpc {
+ type ErrorType = Errors.GlobalErrorType
+}
+
+/**
+ * Converts an {@link ox#AccountProof.AccountProof} to an {@link ox#AccountProof.Rpc}.
+ *
+ * @example
+ * ```ts twoslash
+ * import { AccountProof } from 'ox'
+ *
+ * const proof = AccountProof.toRpc({
+ * address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
+ * balance: 1n,
+ * codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ * nonce: 2,
+ * storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ * accountProof: [],
+ * storageProof: [
+ * {
+ * key: '0x0000000000000000000000000000000000000000000000000000000000000000',
+ * proof: [],
+ * value: 3n,
+ * },
+ * ],
+ * })
+ * ```
+ *
+ * @param proof - The account proof to convert.
+ * @returns An RPC account proof.
+ */
+export function toRpc(proof: AccountProof): Rpc {
+ return {
+ address: proof.address,
+ balance: Hex.fromNumber(proof.balance),
+ codeHash: proof.codeHash,
+ nonce: Hex.fromNumber(proof.nonce),
+ storageHash: proof.storageHash,
+ accountProof: proof.accountProof,
+ storageProof: proof.storageProof.map((slot) => ({
+ key: slot.key,
+ proof: slot.proof,
+ value: Quantity.bigIntToQuantity(slot.value)!,
+ })),
+ }
+}
+
+export declare namespace toRpc {
+ type ErrorType = Errors.GlobalErrorType
+}
diff --git a/src/core/Block.ts b/src/core/Block.ts
index 8cb74e89..1ff82432 100644
--- a/src/core/Block.ts
+++ b/src/core/Block.ts
@@ -1,6 +1,7 @@
import type * as Address from './Address.js'
import type * as Errors from './Errors.js'
import * as Hex from './Hex.js'
+import * as Quantity from './internal/quantity.js'
import type { Compute, OneOf } from './internal/types.js'
import * as Transaction from './Transaction.js'
import * as Withdrawal from './Withdrawal.js'
@@ -155,23 +156,11 @@ export function toRpc<
return Transaction.toRpc(transaction as any) as any
})
return {
- baseFeePerGas:
- typeof block.baseFeePerGas === 'bigint'
- ? Hex.fromNumber(block.baseFeePerGas)
- : undefined,
- blobGasUsed:
- typeof block.blobGasUsed === 'bigint'
- ? Hex.fromNumber(block.blobGasUsed)
- : undefined,
- excessBlobGas:
- typeof block.excessBlobGas === 'bigint'
- ? Hex.fromNumber(block.excessBlobGas)
- : undefined,
+ baseFeePerGas: Quantity.bigIntToQuantity(block.baseFeePerGas),
+ blobGasUsed: Quantity.bigIntToQuantity(block.blobGasUsed),
+ excessBlobGas: Quantity.bigIntToQuantity(block.excessBlobGas),
extraData: block.extraData,
- difficulty:
- typeof block.difficulty === 'bigint'
- ? Hex.fromNumber(block.difficulty)
- : undefined,
+ difficulty: Quantity.bigIntToQuantity(block.difficulty),
gasLimit: Hex.fromNumber(block.gasLimit),
gasUsed: Hex.fromNumber(block.gasUsed),
hash: block.hash,
@@ -190,10 +179,7 @@ export function toRpc<
size: Hex.fromNumber(block.size),
stateRoot: block.stateRoot,
timestamp: Hex.fromNumber(block.timestamp),
- totalDifficulty:
- typeof block.totalDifficulty === 'bigint'
- ? Hex.fromNumber(block.totalDifficulty)
- : undefined,
+ totalDifficulty: Quantity.bigIntToQuantity(block.totalDifficulty),
transactions,
transactionsRoot: block.transactionsRoot,
uncles: block.uncles,
@@ -291,25 +277,17 @@ export function fromRpc<
})
return {
...block,
- baseFeePerGas: block.baseFeePerGas
- ? BigInt(block.baseFeePerGas)
- : undefined,
- blobGasUsed: block.blobGasUsed ? BigInt(block.blobGasUsed) : undefined,
- difficulty: block.difficulty ? BigInt(block.difficulty) : undefined,
- excessBlobGas: block.excessBlobGas
- ? BigInt(block.excessBlobGas)
- : undefined,
+ baseFeePerGas: Quantity.quantityToBigInt(block.baseFeePerGas),
+ blobGasUsed: Quantity.quantityToBigInt(block.blobGasUsed),
+ difficulty: Quantity.quantityToBigInt(block.difficulty),
+ excessBlobGas: Quantity.quantityToBigInt(block.excessBlobGas),
gasLimit: BigInt(block.gasLimit ?? 0n),
gasUsed: BigInt(block.gasUsed ?? 0n),
number: block.number ? BigInt(block.number) : null,
size: BigInt(block.size ?? 0n),
stateRoot: block.stateRoot,
timestamp: BigInt(block.timestamp ?? 0n),
- totalDifficulty:
- typeof block.totalDifficulty !== 'undefined' &&
- block.totalDifficulty !== null
- ? BigInt(block.totalDifficulty)
- : undefined,
+ totalDifficulty: Quantity.quantityToBigInt(block.totalDifficulty),
transactions,
withdrawals: block.withdrawals?.map(Withdrawal.fromRpc),
} as Block as never
diff --git a/src/core/BlockOverrides.ts b/src/core/BlockOverrides.ts
index 4b8511c4..029e6b63 100644
--- a/src/core/BlockOverrides.ts
+++ b/src/core/BlockOverrides.ts
@@ -1,5 +1,6 @@
import type * as Address from './Address.js'
-import * as Hex from './Hex.js'
+import type * as Hex from './Hex.js'
+import * as Quantity from './internal/quantity.js'
import * as Withdrawal from './Withdrawal.js'
/**
@@ -59,32 +60,32 @@ export type Rpc = BlockOverrides
* @returns An instantiated {@link ox#BlockOverrides.BlockOverrides}.
*/
export function fromRpc(rpcBlockOverrides: Rpc): BlockOverrides {
- return {
- ...(rpcBlockOverrides.baseFeePerGas && {
- baseFeePerGas: BigInt(rpcBlockOverrides.baseFeePerGas),
- }),
- ...(rpcBlockOverrides.blobBaseFee && {
- blobBaseFee: BigInt(rpcBlockOverrides.blobBaseFee),
- }),
- ...(rpcBlockOverrides.feeRecipient && {
- feeRecipient: rpcBlockOverrides.feeRecipient,
- }),
- ...(rpcBlockOverrides.gasLimit && {
- gasLimit: BigInt(rpcBlockOverrides.gasLimit),
- }),
- ...(rpcBlockOverrides.number && {
- number: BigInt(rpcBlockOverrides.number),
- }),
- ...(rpcBlockOverrides.prevRandao && {
- prevRandao: BigInt(rpcBlockOverrides.prevRandao),
- }),
- ...(rpcBlockOverrides.time && {
- time: BigInt(rpcBlockOverrides.time),
- }),
- ...(rpcBlockOverrides.withdrawals && {
- withdrawals: rpcBlockOverrides.withdrawals.map(Withdrawal.fromRpc),
- }),
- }
+ const overrides: BlockOverrides = {}
+ if (rpcBlockOverrides.baseFeePerGas !== undefined)
+ overrides.baseFeePerGas = Quantity.quantityToBigInt(
+ rpcBlockOverrides.baseFeePerGas,
+ )
+ if (rpcBlockOverrides.blobBaseFee !== undefined)
+ overrides.blobBaseFee = Quantity.quantityToBigInt(
+ rpcBlockOverrides.blobBaseFee,
+ )
+ if (rpcBlockOverrides.feeRecipient !== undefined)
+ overrides.feeRecipient = rpcBlockOverrides.feeRecipient
+ if (rpcBlockOverrides.gasLimit !== undefined)
+ overrides.gasLimit = Quantity.quantityToBigInt(rpcBlockOverrides.gasLimit)
+ if (rpcBlockOverrides.number !== undefined)
+ overrides.number = Quantity.quantityToBigInt(rpcBlockOverrides.number)
+ if (rpcBlockOverrides.prevRandao !== undefined)
+ overrides.prevRandao = Quantity.quantityToBigInt(
+ rpcBlockOverrides.prevRandao,
+ )
+ if (rpcBlockOverrides.time !== undefined)
+ overrides.time = Quantity.quantityToBigInt(rpcBlockOverrides.time)
+ if (rpcBlockOverrides.withdrawals !== undefined)
+ overrides.withdrawals = rpcBlockOverrides.withdrawals.map(
+ Withdrawal.fromRpc,
+ )
+ return overrides
}
/**
@@ -117,30 +118,22 @@ export function fromRpc(rpcBlockOverrides: Rpc): BlockOverrides {
* @returns An instantiated {@link ox#BlockOverrides.Rpc}.
*/
export function toRpc(blockOverrides: BlockOverrides): Rpc {
- return {
- ...(typeof blockOverrides.baseFeePerGas === 'bigint' && {
- baseFeePerGas: Hex.fromNumber(blockOverrides.baseFeePerGas),
- }),
- ...(typeof blockOverrides.blobBaseFee === 'bigint' && {
- blobBaseFee: Hex.fromNumber(blockOverrides.blobBaseFee),
- }),
- ...(typeof blockOverrides.feeRecipient === 'string' && {
- feeRecipient: blockOverrides.feeRecipient,
- }),
- ...(typeof blockOverrides.gasLimit === 'bigint' && {
- gasLimit: Hex.fromNumber(blockOverrides.gasLimit),
- }),
- ...(typeof blockOverrides.number === 'bigint' && {
- number: Hex.fromNumber(blockOverrides.number),
- }),
- ...(typeof blockOverrides.prevRandao === 'bigint' && {
- prevRandao: Hex.fromNumber(blockOverrides.prevRandao),
- }),
- ...(typeof blockOverrides.time === 'bigint' && {
- time: Hex.fromNumber(blockOverrides.time),
- }),
- ...(blockOverrides.withdrawals && {
- withdrawals: blockOverrides.withdrawals.map(Withdrawal.toRpc),
- }),
- }
+ const rpc: Rpc = {}
+ if (typeof blockOverrides.baseFeePerGas === 'bigint')
+ rpc.baseFeePerGas = Quantity.bigIntToQuantity(blockOverrides.baseFeePerGas)
+ if (typeof blockOverrides.blobBaseFee === 'bigint')
+ rpc.blobBaseFee = Quantity.bigIntToQuantity(blockOverrides.blobBaseFee)
+ if (typeof blockOverrides.feeRecipient === 'string')
+ rpc.feeRecipient = blockOverrides.feeRecipient
+ if (typeof blockOverrides.gasLimit === 'bigint')
+ rpc.gasLimit = Quantity.bigIntToQuantity(blockOverrides.gasLimit)
+ if (typeof blockOverrides.number === 'bigint')
+ rpc.number = Quantity.bigIntToQuantity(blockOverrides.number)
+ if (typeof blockOverrides.prevRandao === 'bigint')
+ rpc.prevRandao = Quantity.bigIntToQuantity(blockOverrides.prevRandao)
+ if (typeof blockOverrides.time === 'bigint')
+ rpc.time = Quantity.bigIntToQuantity(blockOverrides.time)
+ if (blockOverrides.withdrawals !== undefined)
+ rpc.withdrawals = blockOverrides.withdrawals.map(Withdrawal.toRpc)
+ return rpc
}
diff --git a/src/core/StateOverrides.ts b/src/core/StateOverrides.ts
index 3e81fe04..1a4e81b4 100644
--- a/src/core/StateOverrides.ts
+++ b/src/core/StateOverrides.ts
@@ -1,5 +1,6 @@
import type * as Address from './Address.js'
-import * as Hex from './Hex.js'
+import type * as Hex from './Hex.js'
+import * as Quantity from './internal/quantity.js'
import type { Compute, OneOf } from './internal/types.js'
/**
@@ -74,15 +75,19 @@ export function fromRpc(rpcStateOverrides: Rpc): StateOverrides {
rpcStateOverrides,
)) {
const accountOverrides: AccountOverrides = {}
- if (accountOverridesRpc.balance)
- accountOverrides.balance = BigInt(accountOverridesRpc.balance)
+ if (accountOverridesRpc.balance !== undefined)
+ accountOverrides.balance = Quantity.quantityToBigInt(
+ accountOverridesRpc.balance,
+ )
if (accountOverridesRpc.code)
accountOverrides.code = accountOverridesRpc.code
if (accountOverridesRpc.movePrecompileToAddress)
accountOverrides.movePrecompileToAddress =
accountOverridesRpc.movePrecompileToAddress
- if (accountOverridesRpc.nonce)
- accountOverrides.nonce = BigInt(accountOverridesRpc.nonce)
+ if (accountOverridesRpc.nonce !== undefined)
+ accountOverrides.nonce = Quantity.quantityToBigInt(
+ accountOverridesRpc.nonce,
+ )
if (accountOverridesRpc.state)
accountOverrides.state = accountOverridesRpc.state
if (accountOverridesRpc.stateDiff)
@@ -114,13 +119,17 @@ export function toRpc(stateOverrides: StateOverrides): Rpc {
for (const [address, accountOverrides] of Object.entries(stateOverrides)) {
const accountOverridesRpc: RpcAccountOverrides = {}
if (typeof accountOverrides.balance === 'bigint')
- accountOverridesRpc.balance = Hex.fromNumber(accountOverrides.balance)
+ accountOverridesRpc.balance = Quantity.bigIntToQuantity(
+ accountOverrides.balance,
+ )
if (accountOverrides.code) accountOverridesRpc.code = accountOverrides.code
if (accountOverrides.movePrecompileToAddress)
accountOverridesRpc.movePrecompileToAddress =
accountOverrides.movePrecompileToAddress
if (typeof accountOverrides.nonce === 'bigint')
- accountOverridesRpc.nonce = Hex.fromNumber(accountOverrides.nonce)
+ accountOverridesRpc.nonce = Quantity.bigIntToQuantity(
+ accountOverrides.nonce,
+ )
if (accountOverrides.state)
accountOverridesRpc.state = accountOverrides.state
if (accountOverrides.stateDiff)
diff --git a/src/core/_test/AccountProof.test.ts b/src/core/_test/AccountProof.test.ts
index 5a29fa9a..eeba7a86 100644
--- a/src/core/_test/AccountProof.test.ts
+++ b/src/core/_test/AccountProof.test.ts
@@ -1,6 +1,116 @@
-import { expect, test } from 'vitest'
-import * as exports from '../AccountProof.js'
+import { AccountProof } from 'ox'
+import { describe, expect, test } from 'vitest'
+
+describe('fromRpc', () => {
+ test('default', () => {
+ expect(
+ AccountProof.fromRpc({
+ address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
+ balance: '0x1',
+ codeHash:
+ '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ nonce: '0x2',
+ storageHash:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ accountProof: ['0xabcd', '0x1234'],
+ storageProof: [
+ {
+ key: '0x0000000000000000000000000000000000000000000000000000000000000000',
+ proof: ['0xdead'],
+ value: '0x3',
+ },
+ ],
+ }),
+ ).toMatchInlineSnapshot(`
+ {
+ "accountProof": [
+ "0xabcd",
+ "0x1234",
+ ],
+ "address": "0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9",
+ "balance": 1n,
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "nonce": 2,
+ "storageHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "storageProof": [
+ {
+ "key": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "proof": [
+ "0xdead",
+ ],
+ "value": 3n,
+ },
+ ],
+ }
+ `)
+ })
+})
+
+describe('toRpc', () => {
+ test('default', () => {
+ expect(
+ AccountProof.toRpc({
+ address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
+ balance: 1n,
+ codeHash:
+ '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ nonce: 2,
+ storageHash:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ accountProof: ['0xabcd', '0x1234'],
+ storageProof: [
+ {
+ key: '0x0000000000000000000000000000000000000000000000000000000000000000',
+ proof: ['0xdead'],
+ value: 3n,
+ },
+ ],
+ }),
+ ).toMatchInlineSnapshot(`
+ {
+ "accountProof": [
+ "0xabcd",
+ "0x1234",
+ ],
+ "address": "0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9",
+ "balance": "0x1",
+ "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "nonce": "0x2",
+ "storageHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "storageProof": [
+ {
+ "key": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "proof": [
+ "0xdead",
+ ],
+ "value": "0x3",
+ },
+ ],
+ }
+ `)
+ })
+
+ test('round-trip', () => {
+ const value = {
+ address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
+ balance: 0n,
+ codeHash:
+ '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ nonce: 0,
+ storageHash:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ accountProof: [],
+ storageProof: [],
+ } as const
+ expect(AccountProof.fromRpc(AccountProof.toRpc(value))).toEqual(value)
+ })
+})
test('exports', () => {
- expect(Object.keys(exports)).toMatchInlineSnapshot('[]')
+ expect(Object.keys(AccountProof)).toMatchInlineSnapshot(`
+ [
+ "fromRpc",
+ "toRpc",
+ ]
+ `)
})
diff --git a/src/core/internal/quantity.ts b/src/core/internal/quantity.ts
new file mode 100644
index 00000000..c824dec3
--- /dev/null
+++ b/src/core/internal/quantity.ts
@@ -0,0 +1,85 @@
+import * as Hex from '../Hex.js'
+
+/** @internal */
+export class MissingFieldError extends Error {
+ override readonly name = 'Quantity.MissingFieldError'
+ constructor(args: { field: string; container?: string | undefined }) {
+ const { field, container } = args
+ super(
+ container
+ ? `Missing required field \`${field}\` on \`${container}\`.`
+ : `Missing required field \`${field}\`.`,
+ )
+ }
+}
+
+/**
+ * Converts an optional RPC quantity (`Hex.Hex | undefined | null`) to `bigint | undefined`.
+ *
+ * Returns `undefined` for both `undefined` and `null` (RPC encoders may use either to mean "absent").
+ *
+ * @internal
+ */
+export function quantityToBigInt(
+ value: Hex.Hex | undefined | null,
+): bigint | undefined {
+ if (value === undefined || value === null) return undefined
+ return BigInt(value)
+}
+
+/**
+ * Converts a required RPC quantity to `bigint`. Throws `MissingFieldError` if the
+ * value is `undefined` or `null`.
+ *
+ * @internal
+ */
+export function quantityToBigIntRequired(
+ value: Hex.Hex | undefined | null,
+ field: string,
+ container?: string | undefined,
+): bigint {
+ if (value === undefined || value === null)
+ throw new MissingFieldError(
+ container ? { field, container } : { field },
+ )
+ return BigInt(value)
+}
+
+/**
+ * Converts an optional RPC quantity to `number | undefined` via `BigInt` to avoid
+ * silent precision loss on values that overflow Number.MAX_SAFE_INTEGER.
+ *
+ * Returns `undefined` for both `undefined` and `null`.
+ *
+ * @internal
+ */
+export function quantityToNumber(
+ value: Hex.Hex | undefined | null,
+): number | undefined {
+ if (value === undefined || value === null) return undefined
+ return Number(value)
+}
+
+/**
+ * Converts an optional `bigint` to an RPC quantity (`Hex.Hex | undefined`).
+ *
+ * @internal
+ */
+export function bigIntToQuantity(
+ value: bigint | undefined | null,
+): Hex.Hex | undefined {
+ if (typeof value !== 'bigint') return undefined
+ return Hex.fromNumber(value)
+}
+
+/**
+ * Converts an optional `number` to an RPC quantity (`Hex.Hex | undefined`).
+ *
+ * @internal
+ */
+export function numberToQuantity(
+ value: number | undefined | null,
+): Hex.Hex | undefined {
+ if (typeof value !== 'number') return undefined
+ return Hex.fromNumber(value)
+}
From f53c67d1c222449f83668423fff0c3f2583ae9e5 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 11:00:44 +1000
Subject: [PATCH 064/192] feat(typed-data,bloom): per-call type-hash
memoization and prepared-bloom APIs
- Thread an optional `typeHashes` cache through `TypedData.encode`,
`TypedData.hashStruct`, and `TypedData.hashDomain` so
`keccak256(encodeType(t))` is computed once per type per call instead of once
per nested struct or array element.
- Add `Bloom.prepare`, `Bloom.containsPrepared`, and `Bloom.containsHash`
so repeated membership checks against the same filter skip the per-call
`Bytes.fromHex` allocation in `Bloom.contains`.
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a8-f995-717d-9ca9-b5f6a741d96c
---
.changeset/wave-2-bloom-prepared.md | 5 +
.../wave-2-typed-data-type-hashes-memo.md | 5 +
src/core/Bloom.ts | 108 ++++++++++++++++--
src/core/TypedData.ts | 39 +++++--
src/core/_test/Bloom.test.ts | 45 +++++++-
src/core/_test/TypedData.test.ts | 26 +++++
6 files changed, 211 insertions(+), 17 deletions(-)
create mode 100644 .changeset/wave-2-bloom-prepared.md
create mode 100644 .changeset/wave-2-typed-data-type-hashes-memo.md
diff --git a/.changeset/wave-2-bloom-prepared.md b/.changeset/wave-2-bloom-prepared.md
new file mode 100644
index 00000000..646aeee8
--- /dev/null
+++ b/.changeset/wave-2-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/wave-2-typed-data-type-hashes-memo.md b/.changeset/wave-2-typed-data-type-hashes-memo.md
new file mode 100644
index 00000000..9770f7be
--- /dev/null
+++ b/.changeset/wave-2-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. `TypedData.encode` populates a fresh map internally; advanced callers signing many messages against the same schema can pass a shared `Map` across calls.
diff --git a/src/core/Bloom.ts b/src/core/Bloom.ts
index 6a5f9b41..955c4072 100644
--- a/src/core/Bloom.ts
+++ b/src/core/Bloom.ts
@@ -25,26 +25,116 @@ export function contains(
bloom: Hex.Hex,
input: Hex.Hex | Bytes.Bytes,
): boolean {
+ return containsPrepared(prepare(bloom), input)
+}
+
+export declare namespace contains {
+ type ErrorType =
+ | Bytes.fromHex.ErrorType
+ | Hash.keccak256.ErrorType
+ | InvalidBloomError
+ | Errors.GlobalErrorType
+}
+
+/** Prepared bloom filter for use with {@link Bloom.containsPrepared}/{@link Bloom.containsHash}. */
+export type Prepared = {
+ filter: Uint8Array
+}
+
+/**
+ * Prepares a bloom filter for repeated membership checks against the same filter.
+ *
+ * Pairs with {@link Bloom.containsPrepared} (or {@link Bloom.containsHash}) to avoid
+ * the per-call hex-to-bytes conversion that {@link Bloom.contains} pays.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Bloom } from 'ox'
+ *
+ * const prepared = Bloom.prepare(
+ * '0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ * )
+ * Bloom.containsPrepared(prepared, '0xef2d6d194084c2de36e0dabfce45d046b37d1106')
+ * // @log: true
+ * ```
+ *
+ * @param bloom - Bloom filter value.
+ * @returns A prepared bloom filter.
+ */
+export function prepare(bloom: Hex.Hex): Prepared {
if (!validate(bloom)) throw new InvalidBloomError({ bloom })
+ return { filter: Bytes.fromHex(bloom) }
+}
- const filter = Bytes.fromHex(bloom)
- const hash = Hash.keccak256(input, { as: 'Bytes' })
+export declare namespace prepare {
+ type ErrorType =
+ | Bytes.fromHex.ErrorType
+ | InvalidBloomError
+ | Errors.GlobalErrorType
+}
+/**
+ * Checks if an input is matched in a {@link Bloom.Prepared} bloom filter.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Bloom } from 'ox'
+ *
+ * const prepared = Bloom.prepare(
+ * '0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ * )
+ * Bloom.containsPrepared(prepared, '0xef2d6d194084c2de36e0dabfce45d046b37d1106')
+ * // @log: true
+ * ```
+ *
+ * @param prepared - Prepared bloom filter.
+ * @param input - Input to check.
+ * @returns Whether the input is matched in the bloom filter.
+ */
+export function containsPrepared(
+ prepared: Prepared,
+ input: Hex.Hex | Bytes.Bytes,
+): boolean {
+ return containsHash(prepared, Hash.keccak256(input, { as: 'Bytes' }))
+}
+
+export declare namespace containsPrepared {
+ type ErrorType = Hash.keccak256.ErrorType | Errors.GlobalErrorType
+}
+
+/**
+ * Checks if a precomputed `keccak256` hash is matched in a {@link Bloom.Prepared}
+ * bloom filter. Use when the caller already has the hash and wants to skip the
+ * keccak inside `containsPrepared`.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Bloom, Hash } from 'ox'
+ *
+ * const prepared = Bloom.prepare(
+ * '0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ * )
+ * const hash = Hash.keccak256('0xef2d6d194084c2de36e0dabfce45d046b37d1106', { as: 'Bytes' })
+ * Bloom.containsHash(prepared, hash)
+ * // @log: true
+ * ```
+ *
+ * @param prepared - Prepared bloom filter.
+ * @param hash - Precomputed `keccak256` hash of the input, as `Bytes`.
+ * @returns Whether the input is matched in the bloom filter.
+ */
+export function containsHash(prepared: Prepared, hash: Bytes.Bytes): boolean {
+ const { filter } = prepared
for (const i of [0, 2, 4]) {
const bit = (hash[i + 1]! + (hash[i]! << 8)) & 0x7ff
if ((filter[256 - 1 - Math.floor(bit / 8)]! & (1 << (bit % 8))) === 0)
return false
}
-
return true
}
-export declare namespace contains {
- type ErrorType =
- | Bytes.fromHex.ErrorType
- | Hash.keccak256.ErrorType
- | InvalidBloomError
- | Errors.GlobalErrorType
+export declare namespace containsHash {
+ type ErrorType = Errors.GlobalErrorType
}
/**
diff --git a/src/core/TypedData.ts b/src/core/TypedData.ts
index df9a1ff8..fec623b1 100644
--- a/src/core/TypedData.ts
+++ b/src/core/TypedData.ts
@@ -304,6 +304,11 @@ export function encode<
types,
})
+ // Memoize `keccak256(encodeType(t))` per type for the duration of this
+ // encode call. Same `(primaryType, types)` is hashed once instead of once
+ // per nested struct / array element.
+ const typeHashes = new Map()
+
// Typed Data Format: `0x19 ‖ 0x01 ‖ domainSeparator ‖ hashStruct(message)`
const parts: Hex.Hex[] = ['0x19', '0x01']
if (domain)
@@ -311,6 +316,7 @@ export function encode<
hashDomain({
domain,
types,
+ typeHashes,
}),
)
if (primaryType !== 'EIP712Domain')
@@ -319,6 +325,7 @@ export function encode<
data: message,
primaryType,
types,
+ typeHashes,
}),
)
@@ -516,7 +523,7 @@ export declare namespace getSignPayload {
* @returns The hashed domain.
*/
export function hashDomain(value: hashDomain.Value): Hex.Hex {
- const { domain, types } = value
+ const { domain, types, typeHashes } = value
return hashStruct({
data: domain,
primaryType: 'EIP712Domain',
@@ -524,6 +531,7 @@ export function hashDomain(value: hashDomain.Value): Hex.Hex {
...types,
EIP712Domain: types?.EIP712Domain || extractEip712DomainTypes(domain),
},
+ typeHashes,
})
}
@@ -538,6 +546,8 @@ export declare namespace hashDomain {
[key: string]: readonly Parameter[] | undefined
}
| undefined
+ /** Optional cache of `keccak256(encodeType(t))` keyed by type name, shared across nested struct/array calls. */
+ typeHashes?: Map | undefined
}
type ErrorType = hashStruct.ErrorType | Errors.GlobalErrorType
@@ -572,11 +582,12 @@ export declare namespace hashDomain {
* @returns The hashed Typed Data struct.
*/
export function hashStruct(value: hashStruct.Value): Hex.Hex {
- const { data, primaryType, types } = value
+ const { data, primaryType, types, typeHashes } = value
const encoded = encodeData({
data,
primaryType,
types,
+ typeHashes,
})
return Hash.keccak256(encoded)
}
@@ -589,6 +600,8 @@ export declare namespace hashStruct {
primaryType: string
/** The types of the Typed Data struct. */
types: TypedData
+ /** Optional cache of `keccak256(encodeType(t))` keyed by type name, shared across nested struct/array calls. */
+ typeHashes?: Map | undefined
}
type ErrorType =
@@ -822,10 +835,12 @@ export function encodeData(value: {
data: Record
primaryType: string
types: TypedData
+ typeHashes?: Map | undefined
}): Hex.Hex {
const { data, primaryType, types } = value
+ const typeHashes = value.typeHashes ?? new Map()
const encodedTypes: AbiParameters.Parameter[] = [{ type: 'bytes32' }]
- const encodedValues: unknown[] = [hashType({ primaryType, types })]
+ const encodedValues: unknown[] = [hashType({ primaryType, types, typeHashes })]
for (const field of types[primaryType] ?? []) {
const [type, value] = encodeField({
@@ -833,6 +848,7 @@ export function encodeData(value: {
name: field.name,
type: field.type,
value: data[field.name],
+ typeHashes,
})
encodedTypes.push(type)
encodedValues.push(value)
@@ -854,10 +870,15 @@ export declare namespace encodeData {
export function hashType(value: {
primaryType: string
types: TypedData
+ typeHashes?: Map | undefined
}): Hex.Hex {
- const { primaryType, types } = value
+ const { primaryType, types, typeHashes } = value
+ const cached = typeHashes?.get(primaryType)
+ if (cached) return cached
const encodedHashType = Hex.fromString(encodeType({ primaryType, types }))
- return Hash.keccak256(encodedHashType)
+ const hash = Hash.keccak256(encodedHashType)
+ typeHashes?.set(primaryType, hash)
+ return hash
}
/** @internal */
@@ -875,13 +896,16 @@ export function encodeField(properties: {
name: string
type: string
value: any
+ typeHashes?: Map | undefined
}): [type: AbiParameters.Parameter, value: Hex.Hex] {
- let { types, name, type, value } = properties
+ let { types, name, type, value, typeHashes } = properties
if (types[type] !== undefined)
return [
{ type: 'bytes32' },
- Hash.keccak256(encodeData({ data: value, primaryType: type, types })),
+ Hash.keccak256(
+ encodeData({ data: value, primaryType: type, types, typeHashes }),
+ ),
]
if (type === 'bytes') {
@@ -920,6 +944,7 @@ export function encodeField(properties: {
type: parsedType,
types,
value: item,
+ typeHashes,
}),
)
return [
diff --git a/src/core/_test/Bloom.test.ts b/src/core/_test/Bloom.test.ts
index 81963fd5..a99e4b4b 100644
--- a/src/core/_test/Bloom.test.ts
+++ b/src/core/_test/Bloom.test.ts
@@ -1,4 +1,4 @@
-import { Bloom } from 'ox'
+import { Bloom, Hash } from 'ox'
import { describe, expect, test } from 'vitest'
describe('contains', () => {
@@ -78,3 +78,46 @@ describe('validate', () => {
).toBeTruthy()
})
})
+
+const matchingBloom =
+ '0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' as const
+const matchingAddress =
+ '0xef2d6d194084c2de36e0dabfce45d046b37d1106' as const
+
+describe('prepare + containsPrepared', () => {
+ test('matches contains() for matching address', () => {
+ const prepared = Bloom.prepare(matchingBloom)
+ expect(Bloom.containsPrepared(prepared, matchingAddress)).toBe(
+ Bloom.contains(matchingBloom, matchingAddress),
+ )
+ })
+
+ test('throws for invalid bloom', () => {
+ expect(() =>
+ Bloom.prepare('0xdeadbeef'),
+ ).toThrowErrorMatchingInlineSnapshot(
+ '[Bloom.InvalidBloomError: Value `0xdeadbeef` is not a valid bloom filter (must be a 256-byte hex string).]',
+ )
+ })
+})
+
+describe('containsHash', () => {
+ test('skips keccak when caller pre-hashes the input', () => {
+ const prepared = Bloom.prepare(matchingBloom)
+ const hash = Hash.keccak256(matchingAddress, { as: 'Bytes' })
+ expect(Bloom.containsHash(prepared, hash)).toBe(true)
+ })
+})
+
+test('exports', () => {
+ expect(Object.keys(Bloom)).toMatchInlineSnapshot(`
+ [
+ "contains",
+ "prepare",
+ "containsPrepared",
+ "containsHash",
+ "validate",
+ "InvalidBloomError",
+ ]
+ `)
+})
diff --git a/src/core/_test/TypedData.test.ts b/src/core/_test/TypedData.test.ts
index 4e169c9c..e7186cd1 100644
--- a/src/core/_test/TypedData.test.ts
+++ b/src/core/_test/TypedData.test.ts
@@ -1053,6 +1053,32 @@ describe('hashStruct', () => {
`"0xc52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e"`,
)
})
+
+ test('behavior: shared `typeHashes` cache produces identical hash and is populated', () => {
+ const typeHashes = new Map()
+ const hash = TypedData.hashStruct({
+ ...typedData.basic,
+ primaryType: 'Mail',
+ data: typedData.basic.message,
+ typeHashes,
+ })
+ expect(hash).toBe(
+ '0xc52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e',
+ )
+ // Mail nests Person twice (from + to), so both should be cached.
+ expect(typeHashes.has('Mail')).toBe(true)
+ expect(typeHashes.has('Person')).toBe(true)
+
+ // Re-using the populated cache yields the same hash.
+ expect(
+ TypedData.hashStruct({
+ ...typedData.basic,
+ primaryType: 'Mail',
+ data: typedData.basic.message,
+ typeHashes,
+ }),
+ ).toBe(hash)
+ })
})
describe('serialize', () => {
From 64e18e3018ba61ca618e39210da017c2944224a3 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 11:04:53 +1000
Subject: [PATCH 065/192] feat(fee,solidity,personal-message): add
converters/helpers and hoist ERC-191 prefix
- Add `Fee.fromHistoryRpc`, `Fee.toHistoryRpc`, `Fee.estimateMaxFeePerGas`, and
`Fee.effectiveGasPrice` for converting between RPC/instantiated `FeeHistory`
shapes and computing common EIP-1559 fee values.
- Add `Solidity.intRange(bits, signed)` and `Solidity.maxUint(bits)` helpers
that compute integer ranges by bit width.
- Hoist the invariant `0x19 \u2016 "Ethereum Signed Message:\\n"` prefix in
`PersonalMessage.encode` to a precomputed module constant.
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a8-f995-717d-9ca9-b5f6a741d96c
---
.../wave-2-typed-data-type-hashes-memo.md | 2 +-
.changeset/wave-4-fee-helpers.md | 5 +
.changeset/wave-4-personal-message-prefix.md | 5 +
.changeset/wave-4-solidity-helpers.md | 5 +
src/core/Fee.ts | 182 +++++++++++++++++-
src/core/PersonalMessage.ts | 14 +-
src/core/Solidity.ts | 57 ++++++
src/core/TypedData.ts | 4 +-
src/core/_test/Bloom.test.ts | 3 +-
src/core/_test/Fee.test.ts | 87 ++++++++-
src/core/_test/Solidity.test.ts | 29 ++-
src/core/internal/quantity.ts | 4 +-
12 files changed, 384 insertions(+), 13 deletions(-)
create mode 100644 .changeset/wave-4-fee-helpers.md
create mode 100644 .changeset/wave-4-personal-message-prefix.md
create mode 100644 .changeset/wave-4-solidity-helpers.md
diff --git a/.changeset/wave-2-typed-data-type-hashes-memo.md b/.changeset/wave-2-typed-data-type-hashes-memo.md
index 9770f7be..85c13ee6 100644
--- a/.changeset/wave-2-typed-data-type-hashes-memo.md
+++ b/.changeset/wave-2-typed-data-type-hashes-memo.md
@@ -2,4 +2,4 @@
"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. `TypedData.encode` populates a fresh map internally; advanced callers signing many messages against the same schema can pass a shared `Map` across calls.
+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/wave-4-fee-helpers.md b/.changeset/wave-4-fee-helpers.md
new file mode 100644
index 00000000..667e3cf5
--- /dev/null
+++ b/.changeset/wave-4-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/wave-4-personal-message-prefix.md b/.changeset/wave-4-personal-message-prefix.md
new file mode 100644
index 00000000..908602a2
--- /dev/null
+++ b/.changeset/wave-4-personal-message-prefix.md
@@ -0,0 +1,5 @@
+---
+"ox": patch
+---
+
+Hoisted the invariant `0x19 ‖ "Ethereum Signed Message:\n"` ERC-191 prefix in `PersonalMessage.encode` to a precomputed module constant so each call only encodes the per-message length suffix instead of re-encoding the full prefix string.
diff --git a/.changeset/wave-4-solidity-helpers.md b/.changeset/wave-4-solidity-helpers.md
new file mode 100644
index 00000000..63929e3b
--- /dev/null
+++ b/.changeset/wave-4-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/src/core/Fee.ts b/src/core/Fee.ts
index 70addc8b..dae308ac 100644
--- a/src/core/Fee.ts
+++ b/src/core/Fee.ts
@@ -1,4 +1,5 @@
-import type * as Hex from './Hex.js'
+import type * as Errors from './Errors.js'
+import * as Hex from './Hex.js'
import type { Compute, OneOf } from './internal/types.js'
export type FeeHistory = Compute<{
@@ -55,3 +56,182 @@ export type FeeValuesRpc = OneOf<
>
export type FeeValuesType = 'legacy' | 'eip1559' | 'eip4844'
+
+/**
+ * Converts a {@link ox#Fee.FeeHistoryRpc} to a {@link ox#Fee.FeeHistory}.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Fee } from 'ox'
+ *
+ * const history = Fee.fromHistoryRpc({
+ * baseFeePerGas: ['0x01', '0x02'],
+ * gasUsedRatio: [0.5, 0.6],
+ * oldestBlock: '0x10',
+ * reward: [['0x01']],
+ * })
+ * // @log: { baseFeePerGas: [1n, 2n], gasUsedRatio: [0.5, 0.6], oldestBlock: 16n, reward: [[1n]] }
+ * ```
+ *
+ * @param history - The RPC fee history to convert.
+ * @returns An instantiated {@link ox#Fee.FeeHistory}.
+ */
+export function fromHistoryRpc(history: FeeHistoryRpc): FeeHistory {
+ return {
+ baseFeePerGas: history.baseFeePerGas.map((value) => BigInt(value)),
+ gasUsedRatio: history.gasUsedRatio,
+ oldestBlock: BigInt(history.oldestBlock),
+ ...(history.reward
+ ? {
+ reward: history.reward.map((row) =>
+ row.map((value) => BigInt(value)),
+ ),
+ }
+ : {}),
+ }
+}
+
+export declare namespace fromHistoryRpc {
+ type ErrorType = Errors.GlobalErrorType
+}
+
+/**
+ * Converts a {@link ox#Fee.FeeHistory} to a {@link ox#Fee.FeeHistoryRpc}.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Fee } from 'ox'
+ *
+ * const rpc = Fee.toHistoryRpc({
+ * baseFeePerGas: [1n, 2n],
+ * gasUsedRatio: [0.5, 0.6],
+ * oldestBlock: 16n,
+ * reward: [[1n]],
+ * })
+ * ```
+ *
+ * @param history - The fee history to convert.
+ * @returns An RPC fee history.
+ */
+export function toHistoryRpc(history: FeeHistory): FeeHistoryRpc {
+ return {
+ baseFeePerGas: history.baseFeePerGas.map((value) => Hex.fromNumber(value)),
+ gasUsedRatio: history.gasUsedRatio,
+ oldestBlock: Hex.fromNumber(history.oldestBlock),
+ ...(history.reward
+ ? {
+ reward: history.reward.map((row) =>
+ row.map((value) => Hex.fromNumber(value)),
+ ),
+ }
+ : {}),
+ }
+}
+
+export declare namespace toHistoryRpc {
+ type ErrorType = Errors.GlobalErrorType
+}
+
+/**
+ * Estimates a `maxFeePerGas` from a base fee, a priority tip, and a multiplier
+ * applied to the base fee:
+ *
+ * ```
+ * maxFeePerGas = baseFeePerGas * multiplier + maxPriorityFeePerGas
+ * ```
+ *
+ * The multiplier is supplied as `multiplierNumerator / multiplierDenominator`
+ * to keep the math in `bigint`. The default is `2 / 1` (i.e. 2x), matching the
+ * common wallet/relay heuristic for headroom against base-fee bumps.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Fee } from 'ox'
+ *
+ * Fee.estimateMaxFeePerGas({
+ * baseFeePerGas: 100n,
+ * maxPriorityFeePerGas: 5n,
+ * })
+ * // @log: 205n
+ *
+ * Fee.estimateMaxFeePerGas({
+ * baseFeePerGas: 100n,
+ * maxPriorityFeePerGas: 5n,
+ * multiplierNumerator: 3n,
+ * multiplierDenominator: 2n,
+ * })
+ * // @log: 155n (= 100n * 3n / 2n + 5n)
+ * ```
+ *
+ * @param args.baseFeePerGas - Block base fee per gas.
+ * @param args.maxPriorityFeePerGas - Tip per gas.
+ * @param args.multiplierNumerator - Numerator of the base-fee multiplier (default `2n`).
+ * @param args.multiplierDenominator - Denominator of the base-fee multiplier (default `1n`).
+ * @returns Suggested `maxFeePerGas`.
+ */
+export function estimateMaxFeePerGas(args: {
+ baseFeePerGas: bigint
+ maxPriorityFeePerGas: bigint
+ multiplierNumerator?: bigint | undefined
+ multiplierDenominator?: bigint | undefined
+}): bigint {
+ const {
+ baseFeePerGas,
+ maxPriorityFeePerGas,
+ multiplierNumerator = 2n,
+ multiplierDenominator = 1n,
+ } = args
+ return (
+ (baseFeePerGas * multiplierNumerator) / multiplierDenominator +
+ maxPriorityFeePerGas
+ )
+}
+
+export declare namespace estimateMaxFeePerGas {
+ type ErrorType = Errors.GlobalErrorType
+}
+
+/**
+ * Computes the effective gas price an EIP-1559 transaction will pay:
+ *
+ * ```
+ * effective = min(maxFeePerGas, baseFeePerGas + maxPriorityFeePerGas)
+ * ```
+ *
+ * @example
+ * ```ts twoslash
+ * import { Fee } from 'ox'
+ *
+ * Fee.effectiveGasPrice({
+ * baseFeePerGas: 100n,
+ * maxFeePerGas: 200n,
+ * maxPriorityFeePerGas: 50n,
+ * })
+ * // @log: 150n (= 100n + 50n)
+ *
+ * Fee.effectiveGasPrice({
+ * baseFeePerGas: 100n,
+ * maxFeePerGas: 120n,
+ * maxPriorityFeePerGas: 50n,
+ * })
+ * // @log: 120n (capped at maxFeePerGas)
+ * ```
+ *
+ * @param args.baseFeePerGas - Block base fee per gas.
+ * @param args.maxFeePerGas - Sender-supplied `maxFeePerGas`.
+ * @param args.maxPriorityFeePerGas - Sender-supplied tip.
+ * @returns Effective gas price (in wei).
+ */
+export function effectiveGasPrice(args: {
+ baseFeePerGas: bigint
+ maxFeePerGas: bigint
+ maxPriorityFeePerGas: bigint
+}): bigint {
+ const { baseFeePerGas, maxFeePerGas, maxPriorityFeePerGas } = args
+ const ceiling = baseFeePerGas + maxPriorityFeePerGas
+ return ceiling < maxFeePerGas ? ceiling : maxFeePerGas
+}
+
+export declare namespace effectiveGasPrice {
+ type ErrorType = Errors.GlobalErrorType
+}
diff --git a/src/core/PersonalMessage.ts b/src/core/PersonalMessage.ts
index 1f30602e..d3cea6b9 100644
--- a/src/core/PersonalMessage.ts
+++ b/src/core/PersonalMessage.ts
@@ -3,6 +3,16 @@ import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
import * as Hex from './Hex.js'
+/**
+ * Precomputed `0x19 ‖ "Ethereum Signed Message:\n"` prefix (the invariant part
+ * of the ERC-191 v0x45 envelope). Concatenated with the per-message
+ * `Hex.fromString(String(byteLength))` and the message itself.
+ *
+ * @internal
+ */
+const erc191PrefixHex = /*#__PURE__*/ ('0x19' +
+ Hex.fromString('Ethereum Signed Message:\n').slice(2)) as Hex.Hex
+
/**
* Encodes a personal sign message in [ERC-191 format](https://eips.ethereum.org/EIPS/eip-191#version-0x45-e): `0x19 ‖ "Ethereum Signed Message:\n" + message.length ‖ message`.
*
@@ -22,8 +32,8 @@ export function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {
const message = Hex.from(data)
return Hex.concat(
// Personal Sign Format: `0x19 ‖ "Ethereum Signed Message:\n" ‖ message.length ‖ message`
- '0x19',
- Hex.fromString('Ethereum Signed Message:\n' + Hex.size(message)),
+ erc191PrefixHex,
+ Hex.fromString(String(Hex.size(message))),
message,
)
}
diff --git a/src/core/Solidity.ts b/src/core/Solidity.ts
index 47d89bba..c5b1037c 100644
--- a/src/core/Solidity.ts
+++ b/src/core/Solidity.ts
@@ -107,3 +107,60 @@ export const maxUint232 = 2n ** 232n - 1n
export const maxUint240 = 2n ** 240n - 1n
export const maxUint248 = 2n ** 248n - 1n
export const maxUint256 = 2n ** 256n - 1n
+
+/**
+ * Returns the inclusive `[min, max]` range of values representable by a Solidity
+ * integer of the given bit width.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Solidity } from 'ox'
+ *
+ * Solidity.intRange(8, false)
+ * // @log: { min: 0n, max: 255n }
+ *
+ * Solidity.intRange(8, true)
+ * // @log: { min: -128n, max: 127n }
+ * ```
+ *
+ * @param bits - Bit width (must be a positive multiple of 8 in `[8, 256]`).
+ * @param signed - Whether the integer is signed.
+ * @returns `{ min, max }` inclusive bounds.
+ */
+export function intRange(
+ bits: number,
+ signed: boolean,
+): { min: bigint; max: bigint } {
+ if (!Number.isInteger(bits) || bits < 8 || bits > 256 || bits % 8 !== 0)
+ throw new Error(
+ `\`bits\` must be a positive multiple of 8 in [8, 256]. Got \`${bits}\`.`,
+ )
+ const big = BigInt(bits)
+ if (signed) {
+ const max = 2n ** (big - 1n) - 1n
+ return { min: -(max + 1n), max }
+ }
+ return { min: 0n, max: 2n ** big - 1n }
+}
+
+/**
+ * Returns the maximum value representable by an unsigned Solidity integer of the
+ * given bit width.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Solidity } from 'ox'
+ *
+ * Solidity.maxUint(8)
+ * // @log: 255n
+ *
+ * Solidity.maxUint(256) === Solidity.maxUint256
+ * // @log: true
+ * ```
+ *
+ * @param bits - Bit width (must be a positive multiple of 8 in `[8, 256]`).
+ * @returns The maximum unsigned value.
+ */
+export function maxUint(bits: number): bigint {
+ return intRange(bits, false).max
+}
diff --git a/src/core/TypedData.ts b/src/core/TypedData.ts
index fec623b1..8a5fb9d1 100644
--- a/src/core/TypedData.ts
+++ b/src/core/TypedData.ts
@@ -840,7 +840,9 @@ export function encodeData(value: {
const { data, primaryType, types } = value
const typeHashes = value.typeHashes ?? new Map()
const encodedTypes: AbiParameters.Parameter[] = [{ type: 'bytes32' }]
- const encodedValues: unknown[] = [hashType({ primaryType, types, typeHashes })]
+ const encodedValues: unknown[] = [
+ hashType({ primaryType, types, typeHashes }),
+ ]
for (const field of types[primaryType] ?? []) {
const [type, value] = encodeField({
diff --git a/src/core/_test/Bloom.test.ts b/src/core/_test/Bloom.test.ts
index a99e4b4b..4369f233 100644
--- a/src/core/_test/Bloom.test.ts
+++ b/src/core/_test/Bloom.test.ts
@@ -81,8 +81,7 @@ describe('validate', () => {
const matchingBloom =
'0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' as const
-const matchingAddress =
- '0xef2d6d194084c2de36e0dabfce45d046b37d1106' as const
+const matchingAddress = '0xef2d6d194084c2de36e0dabfce45d046b37d1106' as const
describe('prepare + containsPrepared', () => {
test('matches contains() for matching address', () => {
diff --git a/src/core/_test/Fee.test.ts b/src/core/_test/Fee.test.ts
index 831f157d..10b24052 100644
--- a/src/core/_test/Fee.test.ts
+++ b/src/core/_test/Fee.test.ts
@@ -1,6 +1,89 @@
import { Fee } from 'ox'
-import { expect, test } from 'vitest'
+import { describe, expect, test } from 'vitest'
+
+describe('fromHistoryRpc / toHistoryRpc', () => {
+ test('round-trips', () => {
+ const rpc = {
+ baseFeePerGas: ['0x1', '0x2'] as `0x${string}`[],
+ gasUsedRatio: [0.5, 0.6],
+ oldestBlock: '0x10' as `0x${string}`,
+ reward: [['0x1' as `0x${string}`]],
+ }
+ expect(Fee.fromHistoryRpc(rpc)).toEqual({
+ baseFeePerGas: [1n, 2n],
+ gasUsedRatio: [0.5, 0.6],
+ oldestBlock: 16n,
+ reward: [[1n]],
+ })
+ expect(Fee.toHistoryRpc(Fee.fromHistoryRpc(rpc))).toEqual(rpc)
+ })
+
+ test('omits `reward` when not present', () => {
+ expect(
+ Fee.fromHistoryRpc({
+ baseFeePerGas: ['0x01'],
+ gasUsedRatio: [0.5],
+ oldestBlock: '0x10',
+ }),
+ ).toEqual({
+ baseFeePerGas: [1n],
+ gasUsedRatio: [0.5],
+ oldestBlock: 16n,
+ })
+ })
+})
+
+describe('estimateMaxFeePerGas', () => {
+ test('default 2x multiplier', () => {
+ expect(
+ Fee.estimateMaxFeePerGas({
+ baseFeePerGas: 100n,
+ maxPriorityFeePerGas: 5n,
+ }),
+ ).toBe(205n)
+ })
+
+ test('custom 1.5x multiplier', () => {
+ expect(
+ Fee.estimateMaxFeePerGas({
+ baseFeePerGas: 100n,
+ maxPriorityFeePerGas: 5n,
+ multiplierNumerator: 3n,
+ multiplierDenominator: 2n,
+ }),
+ ).toBe(155n)
+ })
+})
+
+describe('effectiveGasPrice', () => {
+ test('uses base+tip when within cap', () => {
+ expect(
+ Fee.effectiveGasPrice({
+ baseFeePerGas: 100n,
+ maxFeePerGas: 200n,
+ maxPriorityFeePerGas: 50n,
+ }),
+ ).toBe(150n)
+ })
+
+ test('caps at maxFeePerGas when base+tip exceeds it', () => {
+ expect(
+ Fee.effectiveGasPrice({
+ baseFeePerGas: 100n,
+ maxFeePerGas: 120n,
+ maxPriorityFeePerGas: 50n,
+ }),
+ ).toBe(120n)
+ })
+})
test('exports', () => {
- expect(Object.keys(Fee)).toMatchInlineSnapshot('[]')
+ expect(Object.keys(Fee)).toMatchInlineSnapshot(`
+ [
+ "fromHistoryRpc",
+ "toHistoryRpc",
+ "estimateMaxFeePerGas",
+ "effectiveGasPrice",
+ ]
+ `)
})
diff --git a/src/core/_test/Solidity.test.ts b/src/core/_test/Solidity.test.ts
index 3c136078..ea53a7a0 100644
--- a/src/core/_test/Solidity.test.ts
+++ b/src/core/_test/Solidity.test.ts
@@ -1,5 +1,5 @@
import { Solidity } from 'ox'
-import { expect, test } from 'vitest'
+import { describe, expect, test } from 'vitest'
test('exports', () => {
expect(Object.keys(Solidity)).toMatchInlineSnapshot(`
@@ -103,6 +103,33 @@ test('exports', () => {
"maxUint240",
"maxUint248",
"maxUint256",
+ "intRange",
+ "maxUint",
]
`)
})
+
+describe('intRange', () => {
+ test('unsigned 8-bit', () => {
+ expect(Solidity.intRange(8, false)).toEqual({ min: 0n, max: 255n })
+ })
+ test('signed 8-bit', () => {
+ expect(Solidity.intRange(8, true)).toEqual({ min: -128n, max: 127n })
+ })
+ test('matches existing constants', () => {
+ expect(Solidity.intRange(256, false).max).toBe(Solidity.maxUint256)
+ expect(Solidity.intRange(8, true).max).toBe(Solidity.maxInt8)
+ })
+ test('rejects non-multiple-of-8 widths', () => {
+ expect(() => Solidity.intRange(7, false)).toThrowError(
+ '`bits` must be a positive multiple of 8 in [8, 256]. Got `7`.',
+ )
+ })
+})
+
+describe('maxUint', () => {
+ test('matches existing constants', () => {
+ expect(Solidity.maxUint(8)).toBe(Solidity.maxUint8)
+ expect(Solidity.maxUint(256)).toBe(Solidity.maxUint256)
+ })
+})
diff --git a/src/core/internal/quantity.ts b/src/core/internal/quantity.ts
index c824dec3..03a0ef18 100644
--- a/src/core/internal/quantity.ts
+++ b/src/core/internal/quantity.ts
@@ -39,9 +39,7 @@ export function quantityToBigIntRequired(
container?: string | undefined,
): bigint {
if (value === undefined || value === null)
- throw new MissingFieldError(
- container ? { field, container } : { field },
- )
+ throw new MissingFieldError(container ? { field, container } : { field })
return BigInt(value)
}
From 04683c8ccb35e8c2cc155b6e6ee27bd5185b4f20 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 11:14:06 +1000
Subject: [PATCH 066/192] perf(erc4337): hoist `UserOperation.hash` ABI
descriptors and share `packUint128Pair` / `EMPTY_KECCAK`
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-bca0-706c-bbe4-5ac3789142dd
---
...wave-1-erc4337-user-operation-hash-perf.md | 5 +
src/erc4337/UserOperation.ts | 180 ++++++++++--------
2 files changed, 110 insertions(+), 75 deletions(-)
create mode 100644 .changeset/wave-1-erc4337-user-operation-hash-perf.md
diff --git a/.changeset/wave-1-erc4337-user-operation-hash-perf.md b/.changeset/wave-1-erc4337-user-operation-hash-perf.md
new file mode 100644
index 00000000..46c79a7d
--- /dev/null
+++ b/.changeset/wave-1-erc4337-user-operation-hash-perf.md
@@ -0,0 +1,5 @@
+---
+'ox': patch
+---
+
+Hoisted `UserOperation.hash` ABI parameter descriptors to module scope, added a shared `packUint128Pair` helper for v0.7+ gas-limit packing, and reused a precomputed empty-bytes keccak for empty `initCode`/`paymasterAndData`.
diff --git a/src/erc4337/UserOperation.ts b/src/erc4337/UserOperation.ts
index 6d7e8cc9..0ddebe12 100644
--- a/src/erc4337/UserOperation.ts
+++ b/src/erc4337/UserOperation.ts
@@ -9,6 +9,56 @@ import * as Signature from '../core/Signature.js'
import * as TypedData from '../core/TypedData.js'
import type * as EntryPoint from './EntryPoint.js'
+// ---- Module-scoped constants for hot paths ---------------------------------
+
+/** keccak256 of empty bytes (`0x`). Reused for empty initCode/paymasterAndData. */
+const EMPTY_KECCAK = /*#__PURE__*/ Hash.keccak256('0x')
+
+/** ABI parameters for v0.6 user operation packed encoding. */
+const v06HashParameters = [
+ { type: 'address' },
+ { type: 'uint256' },
+ { type: 'bytes32' },
+ { type: 'bytes32' },
+ { type: 'uint256' },
+ { type: 'uint256' },
+ { type: 'uint256' },
+ { type: 'uint256' },
+ { type: 'uint256' },
+ { type: 'bytes32' },
+] as const satisfies readonly AbiParameters.Parameter[]
+
+/** ABI parameters for v0.7 user operation packed encoding. */
+const v07HashParameters = [
+ { type: 'address' },
+ { type: 'uint256' },
+ { type: 'bytes32' },
+ { type: 'bytes32' },
+ { type: 'bytes32' },
+ { type: 'uint256' },
+ { type: 'bytes32' },
+ { type: 'bytes32' },
+] as const satisfies readonly AbiParameters.Parameter[]
+
+/** ABI parameters for the outer hash envelope `(packedUserOpHash, entryPoint, chainId)`. */
+const hashEnvelopeParameters = [
+ { type: 'bytes32' },
+ { type: 'address' },
+ { type: 'uint256' },
+] as const satisfies readonly AbiParameters.Parameter[]
+
+/**
+ * Packs two `uint128` values into a single `bytes32` word, with `high` in the
+ * upper 16 bytes and `low` in the lower 16 bytes. Used for `accountGasLimits`
+ * and `gasFees` packing in v0.7+ user operations.
+ */
+function packUint128Pair(high: bigint | number, low: bigint | number): Hex.Hex {
+ return Hex.concat(
+ Hex.padLeft(Hex.fromNumber(high), 16),
+ Hex.padLeft(Hex.fromNumber(low), 16),
+ )
+}
+
/** User Operation. */
export type UserOperation<
entryPointVersion extends EntryPoint.Version = EntryPoint.Version,
@@ -466,49 +516,40 @@ export function hash<
const packedUserOp = (() => {
if (entryPointVersion === '0.6') {
- return AbiParameters.encode(
- [
- { type: 'address' },
- { type: 'uint256' },
- { type: 'bytes32' },
- { type: 'bytes32' },
- { type: 'uint256' },
- { type: 'uint256' },
- { type: 'uint256' },
- { type: 'uint256' },
- { type: 'uint256' },
- { type: 'bytes32' },
- ],
- [
- sender,
- nonce,
- Hash.keccak256(initCode ?? '0x'),
- Hash.keccak256(callData),
- callGasLimit,
- verificationGasLimit,
- preVerificationGas,
- maxFeePerGas,
- maxPriorityFeePerGas,
- Hash.keccak256(paymasterAndData ?? '0x'),
- ],
- )
+ const initCodeHash =
+ !initCode || initCode === '0x' ? EMPTY_KECCAK : Hash.keccak256(initCode)
+ const paymasterAndDataHash =
+ !paymasterAndData || paymasterAndData === '0x'
+ ? EMPTY_KECCAK
+ : Hash.keccak256(paymasterAndData)
+
+ return AbiParameters.encode(v06HashParameters, [
+ sender,
+ nonce,
+ initCodeHash,
+ Hash.keccak256(callData),
+ callGasLimit,
+ verificationGasLimit,
+ preVerificationGas,
+ maxFeePerGas,
+ maxPriorityFeePerGas,
+ paymasterAndDataHash,
+ ])
}
if (entryPointVersion === '0.7') {
- const accountGasLimits = Hex.concat(
- Hex.padLeft(Hex.fromNumber(verificationGasLimit), 16),
- Hex.padLeft(Hex.fromNumber(callGasLimit), 16),
+ const accountGasLimits = packUint128Pair(
+ verificationGasLimit,
+ callGasLimit,
)
- const gasFees = Hex.concat(
- Hex.padLeft(Hex.fromNumber(maxPriorityFeePerGas), 16),
- Hex.padLeft(Hex.fromNumber(maxFeePerGas), 16),
- )
- const initCode_hashed = Hash.keccak256(
- factory && factoryData ? Hex.concat(factory, factoryData) : '0x',
- )
- const paymasterAndData_hashed = Hash.keccak256(
- paymaster
- ? Hex.concat(
+ const gasFees = packUint128Pair(maxPriorityFeePerGas, maxFeePerGas)
+ const initCode_hashed =
+ factory && factoryData
+ ? Hash.keccak256(Hex.concat(factory, factoryData))
+ : EMPTY_KECCAK
+ const paymasterAndData_hashed = paymaster
+ ? Hash.keccak256(
+ Hex.concat(
paymaster,
Hex.padLeft(
Hex.fromNumber(paymasterVerificationGasLimit || 0),
@@ -516,42 +557,31 @@ export function hash<
),
Hex.padLeft(Hex.fromNumber(paymasterPostOpGasLimit || 0), 16),
paymasterData || '0x',
- )
- : '0x',
- )
-
- return AbiParameters.encode(
- [
- { type: 'address' },
- { type: 'uint256' },
- { type: 'bytes32' },
- { type: 'bytes32' },
- { type: 'bytes32' },
- { type: 'uint256' },
- { type: 'bytes32' },
- { type: 'bytes32' },
- ],
- [
- sender,
- nonce,
- initCode_hashed,
- Hash.keccak256(callData),
- accountGasLimits,
- preVerificationGas,
- gasFees,
- paymasterAndData_hashed,
- ],
- )
+ ),
+ )
+ : EMPTY_KECCAK
+
+ return AbiParameters.encode(v07HashParameters, [
+ sender,
+ nonce,
+ initCode_hashed,
+ Hash.keccak256(callData),
+ accountGasLimits,
+ preVerificationGas,
+ gasFees,
+ paymasterAndData_hashed,
+ ])
}
throw new Error(`entryPointVersion "${entryPointVersion}" not supported.`)
})()
return Hash.keccak256(
- AbiParameters.encode(
- [{ type: 'bytes32' }, { type: 'address' }, { type: 'uint256' }],
- [Hash.keccak256(packedUserOp), entryPointAddress, BigInt(chainId)],
- ),
+ AbiParameters.encode(hashEnvelopeParameters, [
+ Hash.keccak256(packedUserOp),
+ entryPointAddress,
+ BigInt(chainId),
+ ]),
)
}
@@ -661,14 +691,14 @@ export function toPacked(
verificationGasLimit,
} = userOperation
- const accountGasLimits = Hex.concat(
- Hex.padLeft(Hex.fromNumber(verificationGasLimit || 0n), 16),
- Hex.padLeft(Hex.fromNumber(callGasLimit || 0n), 16),
+ const accountGasLimits = packUint128Pair(
+ verificationGasLimit || 0n,
+ callGasLimit || 0n,
)
const initCode = toInitCode(userOperation)
- const gasFees = Hex.concat(
- Hex.padLeft(Hex.fromNumber(maxPriorityFeePerGas || 0n), 16),
- Hex.padLeft(Hex.fromNumber(maxFeePerGas || 0n), 16),
+ const gasFees = packUint128Pair(
+ maxPriorityFeePerGas || 0n,
+ maxFeePerGas || 0n,
)
const paymasterAndData = paymaster
? Hex.concat(
From ed3980e290effa4e86905c2e8191a016fc6ce8be Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 11:14:13 +1000
Subject: [PATCH 067/192] perf(erc6492): cache `address, bytes, bytes` ABI
parameters at module scope
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-bca0-706c-bbe4-5ac3789142dd
---
.../wave-1-erc6492-cache-abi-parameters.md | 5 +++++
src/erc6492/SignatureErc6492.ts | 16 +++++++---------
2 files changed, 12 insertions(+), 9 deletions(-)
create mode 100644 .changeset/wave-1-erc6492-cache-abi-parameters.md
diff --git a/.changeset/wave-1-erc6492-cache-abi-parameters.md b/.changeset/wave-1-erc6492-cache-abi-parameters.md
new file mode 100644
index 00000000..9797f63c
--- /dev/null
+++ b/.changeset/wave-1-erc6492-cache-abi-parameters.md
@@ -0,0 +1,5 @@
+---
+'ox': patch
+---
+
+Cached the `address, bytes, bytes` ABI parameter list at module scope in `SignatureErc6492` so `wrap` and `unwrap` no longer reparse on every call.
diff --git a/src/erc6492/SignatureErc6492.ts b/src/erc6492/SignatureErc6492.ts
index d87bf3fd..a591c47e 100644
--- a/src/erc6492/SignatureErc6492.ts
+++ b/src/erc6492/SignatureErc6492.ts
@@ -24,6 +24,11 @@ export type Wrapped = Hex.Hex
export const magicBytes =
'0x6492649264926492649264926492649264926492649264926492649264926492' as const
+/** Cached ABI parameters for ERC-6492 wrapped signature payloads. */
+const wrappedParameters = /*#__PURE__*/ AbiParameters.from(
+ 'address, bytes, bytes',
+)
+
/**
* Deployless ERC-6492 signature verification bytecode.
*/
@@ -181,10 +186,7 @@ export function unwrap(wrapped: Wrapped): Unwrapped {
assert(wrapped)
const body = Hex.slice(wrapped, 0, -32)
- const [to, data, signature] = AbiParameters.decode(
- AbiParameters.from('address, bytes, bytes'),
- body,
- )
+ const [to, data, signature] = AbiParameters.decode(wrappedParameters, body)
return { data, signature, to }
}
@@ -224,11 +226,7 @@ export function wrap(value: Unwrapped): Wrapped {
const { data, signature, to } = value
return Hex.concat(
- AbiParameters.encode(AbiParameters.from('address, bytes, bytes'), [
- to,
- data,
- signature,
- ]),
+ AbiParameters.encode(wrappedParameters, [to, data, signature]),
magicBytes,
)
}
From e8d9231e1f6d8dab17df642559fa2b39d097add8 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 11:14:21 +1000
Subject: [PATCH 068/192] perf(erc7821): cache `Calls` and `Execute` ABI
parameters at module scope
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-bca0-706c-bbe4-5ac3789142dd
---
.../wave-1-erc7821-cache-abi-parameters.md | 5 +++++
src/erc7821/Calls.ts | 19 ++++++++++++++-----
src/erc7821/Execute.ts | 7 +++++--
3 files changed, 24 insertions(+), 7 deletions(-)
create mode 100644 .changeset/wave-1-erc7821-cache-abi-parameters.md
diff --git a/.changeset/wave-1-erc7821-cache-abi-parameters.md b/.changeset/wave-1-erc7821-cache-abi-parameters.md
new file mode 100644
index 00000000..8e1fe33b
--- /dev/null
+++ b/.changeset/wave-1-erc7821-cache-abi-parameters.md
@@ -0,0 +1,5 @@
+---
+'ox': patch
+---
+
+Cached the `Calls` ABI parameter lists (with and without `opData`) and the `bytes[]` parameter used by `Execute.encodeBatchOfBatchesData`/`decodeBatchOfBatchesData` at module scope to avoid reparsing on every encode/decode.
diff --git a/src/erc7821/Calls.ts b/src/erc7821/Calls.ts
index 80004ae1..c2d3a2d1 100644
--- a/src/erc7821/Calls.ts
+++ b/src/erc7821/Calls.ts
@@ -8,6 +8,19 @@ export type Call = {
value?: bigintType | undefined
}
+/** Cached ABI parameters for ERC-7821 calls without `opData`. */
+const callsParameters = /*#__PURE__*/ AbiParameters.from([
+ 'struct Call { address target; uint256 value; bytes data; }',
+ 'Call[] calls',
+])
+
+/** Cached ABI parameters for ERC-7821 calls with `opData`. */
+const callsWithOpDataParameters = /*#__PURE__*/ AbiParameters.from([
+ 'struct Call { address target; uint256 value; bytes data; }',
+ 'Call[] calls',
+ 'bytes opData',
+])
+
/**
* Encodes a set of ERC-7821 calls.
*
@@ -68,11 +81,7 @@ export declare namespace encode {
*/
export function getAbiParameters(options: getAbiParameters.Options = {}) {
const { opData } = options
- return AbiParameters.from([
- 'struct Call { address target; uint256 value; bytes data; }',
- 'Call[] calls',
- ...(opData ? ['bytes opData'] : []),
- ])
+ return opData ? callsWithOpDataParameters : callsParameters
}
export declare namespace getAbiParameters {
diff --git a/src/erc7821/Execute.ts b/src/erc7821/Execute.ts
index 89ab624b..9aeb57d3 100644
--- a/src/erc7821/Execute.ts
+++ b/src/erc7821/Execute.ts
@@ -10,6 +10,9 @@ export type Batch = {
export type Call = Calls.Call
+/** Cached ABI parameters for the encoded `bytes[]` payload of batch-of-batches. */
+const batchesParameters = /*#__PURE__*/ AbiParameters.from('bytes[]')
+
export const abiFunction = {
type: 'function',
name: 'execute',
@@ -86,7 +89,7 @@ export function decodeBatchOfBatchesData(
]
const [encodedBatches] = AbiParameters.decode(
- AbiParameters.from('bytes[]'),
+ batchesParameters,
executionData,
) as readonly [Hex.Hex[]]
@@ -146,7 +149,7 @@ export declare namespace decodeBatchOfBatchesData {
* @returns The encoded data.
*/
export function encodeBatchOfBatchesData(batches: readonly Batch[]) {
- const b = AbiParameters.encode(AbiParameters.from('bytes[]'), [
+ const b = AbiParameters.encode(batchesParameters, [
batches.map((b) => {
const batch = b as Batch
return Calls.encode(batch.calls, {
From bc9c64e46ad24f547da2a8b85fbdcb945f3f7a9f Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 11:14:22 +1000
Subject: [PATCH 069/192] refactor(erc8021): share schema-0/1 codes-tail decode
in `Attribution.fromData`
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-bca0-706c-bbe4-5ac3789142dd
---
...rc8021-attribution-fromdata-shared-tail.md | 5 ++
src/erc8021/Attribution.ts | 71 +++++++++----------
2 files changed, 38 insertions(+), 38 deletions(-)
create mode 100644 .changeset/wave-1-erc8021-attribution-fromdata-shared-tail.md
diff --git a/.changeset/wave-1-erc8021-attribution-fromdata-shared-tail.md b/.changeset/wave-1-erc8021-attribution-fromdata-shared-tail.md
new file mode 100644
index 00000000..b6f46871
--- /dev/null
+++ b/.changeset/wave-1-erc8021-attribution-fromdata-shared-tail.md
@@ -0,0 +1,5 @@
+---
+'ox': patch
+---
+
+Refactored `Attribution.fromData` to share the schema-0/1 `codes ∥ codesLength` tail-decode through a single helper, removing duplicated boundary arithmetic between schema branches.
diff --git a/src/erc8021/Attribution.ts b/src/erc8021/Attribution.ts
index cd974600..402f4033 100644
--- a/src/erc8021/Attribution.ts
+++ b/src/erc8021/Attribution.ts
@@ -303,53 +303,25 @@ export function fromData(data: Hex.Hex): Attribution | undefined {
if (suffix !== ercSuffix) return undefined
// Extract schema ID (1 byte before the ERC suffix)
- const schemaIdHex = Hex.slice(data, -ercSuffixSize - 1, -ercSuffixSize)
- const schemaId = Hex.toNumber(schemaIdHex)
+ const schemaIdEnd = -ercSuffixSize
+ const schemaIdStart = schemaIdEnd - 1
+ const schemaId = Hex.toNumber(Hex.slice(data, schemaIdStart, schemaIdEnd))
// Schema 0: Canonical registry
- if (schemaId === 0) {
- // Extract codes length (1 byte before schema ID)
- const codesLengthHex = Hex.slice(
- data,
- -ercSuffixSize - 2,
- -ercSuffixSize - 1,
- )
- const codesLength = Hex.toNumber(codesLengthHex)
-
- // Extract codes
- const codesStart = -ercSuffixSize - 2 - codesLength
- const codesEnd = -ercSuffixSize - 2
- const codesHex = Hex.slice(data, codesStart, codesEnd)
- const codesString = Hex.toString(codesHex)
- const codes = codesString.length > 0 ? codesString.split(',') : []
-
- return { codes, id: 0 }
- }
-
// Schema 1: Custom registry
- // Format: codeRegistryAddress (20 bytes) ∥ chainId ∥ chainIdLength (1 byte) ∥ codes ∥ codesLength (1 byte) ∥ schemaId (1 byte) ∥ ercSuffix
- if (schemaId === 1) {
- // Extract codes length (1 byte before schema ID)
- const codesLengthHex = Hex.slice(
- data,
- -ercSuffixSize - 2,
- -ercSuffixSize - 1,
- )
- const codesLength = Hex.toNumber(codesLengthHex)
+ // Format: [codeRegistryAddress (20) ∥ chainId ∥ chainIdLength (1)]? ∥ codes ∥ codesLength (1) ∥ schemaId (1) ∥ ercSuffix
+ if (schemaId === 0 || schemaId === 1) {
+ const codes = decodeCodesTail(data, schemaIdStart)
+ if (!codes) return undefined
- // Extract codes
- const codesStart = -ercSuffixSize - 2 - codesLength
- const codesEnd = -ercSuffixSize - 2
- const codesHex = Hex.slice(data, codesStart, codesEnd)
- const codesString = Hex.toString(codesHex)
- const codes = codesString.length > 0 ? codesString.split(',') : []
+ if (schemaId === 0) return { codes: codes.codes, id: 0 }
// Extract registry by reading backwards from just before codes
- const codeRegistry = registryFromData(Hex.slice(data, 0, codesStart))
+ const codeRegistry = registryFromData(Hex.slice(data, 0, codes.codesStart))
if (codeRegistry === undefined) return undefined
return {
- codes,
+ codes: codes.codes,
codeRegistry,
id: 1,
}
@@ -363,6 +335,29 @@ export function fromData(data: Hex.Hex): Attribution | undefined {
return undefined
}
+/**
+ * Reads the trailing `codes ∥ codesLength (1)` segment from a schema-0/1
+ * payload, given the absolute end-offset of the codes-length byte (which is
+ * the start of the schema ID).
+ */
+function decodeCodesTail(
+ data: Hex.Hex,
+ schemaIdStart: number,
+): { codes: string[]; codesStart: number } | undefined {
+ const codesLengthEnd = schemaIdStart
+ const codesLengthStart = codesLengthEnd - 1
+ const codesLength = Hex.toNumber(
+ Hex.slice(data, codesLengthStart, codesLengthEnd),
+ )
+
+ const codesEnd = codesLengthStart
+ const codesStart = codesEnd - codesLength
+ const codesHex = Hex.slice(data, codesStart, codesEnd)
+ const codesString = Hex.toString(codesHex)
+ const codes = codesString.length > 0 ? codesString.split(',') : []
+ return { codes, codesStart }
+}
+
function registryFromData(
data: Hex.Hex,
): AttributionSchemaId1Registry | undefined {
From e9c59bd44445ead684d3c39e03a41e256a1e7c2b Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 11:23:11 +1000
Subject: [PATCH 070/192] test: refresh export snapshots and add EIP-4844
envelope snapshot
Picks up new error class exports from encoding thread fixes
(InvalidPaddingError on Base32/Base64, InvalidValueError +
NonMinimalEncodingError on CompactSize, InvalidLengthError on Base64)
and the new TransactionEnvelopeEip4844 test snapshot file.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1976-9c6f-745e-87d8-d00af1fe5aaf
---
src/core/_test/Base32.test.ts | 1 +
src/core/_test/Base64.test.ts | 3 +++
src/core/_test/CompactSize.test.ts | 2 ++
.../__snapshots__/TransactionEnvelopeEip4844.test.ts.snap | 3 +++
4 files changed, 9 insertions(+)
create mode 100644 src/core/_test/__snapshots__/TransactionEnvelopeEip4844.test.ts.snap
diff --git a/src/core/_test/Base32.test.ts b/src/core/_test/Base32.test.ts
index aa4f6870..8c9a8e7f 100644
--- a/src/core/_test/Base32.test.ts
+++ b/src/core/_test/Base32.test.ts
@@ -61,6 +61,7 @@ test('exports', () => {
"toBytes",
"toHex",
"InvalidCharacterError",
+ "InvalidPaddingError",
]
`)
})
diff --git a/src/core/_test/Base64.test.ts b/src/core/_test/Base64.test.ts
index e77a3edd..d87879a2 100644
--- a/src/core/_test/Base64.test.ts
+++ b/src/core/_test/Base64.test.ts
@@ -98,6 +98,9 @@ test('exports', () => {
"toBytes",
"toHex",
"toString",
+ "InvalidCharacterError",
+ "InvalidLengthError",
+ "InvalidPaddingError",
]
`)
})
diff --git a/src/core/_test/CompactSize.test.ts b/src/core/_test/CompactSize.test.ts
index 76a8c17c..cf1a0020 100644
--- a/src/core/_test/CompactSize.test.ts
+++ b/src/core/_test/CompactSize.test.ts
@@ -169,6 +169,8 @@ test('exports', () => {
"fromHex",
"NegativeValueError",
"InsufficientBytesError",
+ "InvalidValueError",
+ "NonMinimalEncodingError",
]
`)
})
diff --git a/src/core/_test/__snapshots__/TransactionEnvelopeEip4844.test.ts.snap b/src/core/_test/__snapshots__/TransactionEnvelopeEip4844.test.ts.snap
new file mode 100644
index 00000000..26c01cd1
--- /dev/null
+++ b/src/core/_test/__snapshots__/TransactionEnvelopeEip4844.test.ts.snap
@@ -0,0 +1,3 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`serialize > options: sidecars 1`] = `"0x03fa0200b8f84a018203118080809470997970c51812dc3a010c7d01b50e0d17dc79c8880de0b6b3a764000080c080e1a001627c687261b0e7f8638af1112efa8a77e23656f6e7945275b19e9deed80261fa020004ba0200000061626364800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1b0aa4706df98b7ebcfd50ef27a5e0b209015872ce161a8bd549d310e8371839192ff2a114976f2946c81b3937cadc57172f1b0aa3d8787420ed1689a1ec46ecb47a862629caa405c0f414378fa927d0ba3c99bcd5e73e85a746b409dd2d98fd23a3850"`;
From 377784fe746b99237f07987be93511d7f0e7cf77 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Tue, 12 May 2026 16:35:03 +1000
Subject: [PATCH 071/192] test: align fixtures and snapshots with wave-0
correctness fixes
- test/constants/accounts: pass `as: 'Hex'` to `Mnemonic.toPrivateKey`
to keep the typed `privateKey: Hex.Hex` contract after the default
return type was corrected to `Bytes`.
- Provider.test.ts: `Provider.from > default` now wraps the response
with `RpcResponse.parse` to match the strict EIP-1193 contract
(envelope sniffing was removed).
- RpcTransport.test.ts: mock `fetchOptions` servers now return a full
JSON-RPC envelope (`id`, `jsonrpc`, `result`) per the strict
parser contract.
- Registration.test.ts: `error: challenge mismatch` uses an
even-length hex challenge so the strict hex parser does not fail
before the mismatch check.
- Block snapshots: `totalDifficulty: undefined` (no longer coerced
to `0n`) and EIP-155 `v: 37` preserved (no longer normalized to
27).
Amp-Thread-ID: https://ampcode.com/threads/T-019e1976-9c6f-745e-87d8-d00af1fe5aaf
---
src/core/_test/Block.test.ts | 2 +-
src/core/_test/Provider.test.ts | 4 +-
src/core/_test/RpcTransport.test.ts | 4 +-
src/core/_test/_snap/Block.test.ts.snap | 54 ++++++++++++-------------
src/webauthn/_test/Registration.test.ts | 2 +-
test/constants/accounts.ts | 2 +-
6 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/src/core/_test/Block.test.ts b/src/core/_test/Block.test.ts
index 1c6be5d0..5af476c1 100644
--- a/src/core/_test/Block.test.ts
+++ b/src/core/_test/Block.test.ts
@@ -143,7 +143,7 @@ describe('fromRpc', () => {
"size": 56024n,
"stateRoot": "0x115fd5eac921e6728825958b2b87da8aaf17edc0085164f11de798f6ed00abbd",
"timestamp": 1715686979n,
- "totalDifficulty": 0n,
+ "totalDifficulty": undefined,
"transactions": [
"0x5d374a026007c13e901765497b9164d44822902463efdf7b574b10c476ee2ad6",
"0x2762a7fb7c973e888edc457a3808d3882b5c8fc4f6c43a082d823319b126b91a",
diff --git a/src/core/_test/Provider.test.ts b/src/core/_test/Provider.test.ts
index bf65df10..bbe465a7 100644
--- a/src/core/_test/Provider.test.ts
+++ b/src/core/_test/Provider.test.ts
@@ -36,7 +36,9 @@ describe('Provider.from', () => {
headers: {
'Content-Type': 'application/json',
},
- }).then((res) => res.json())
+ })
+ .then((res) => res.json())
+ .then(RpcResponse.parse)
},
})
diff --git a/src/core/_test/RpcTransport.test.ts b/src/core/_test/RpcTransport.test.ts
index 03fdbfa0..bbf7a5a7 100644
--- a/src/core/_test/RpcTransport.test.ts
+++ b/src/core/_test/RpcTransport.test.ts
@@ -54,7 +54,7 @@ describe('fromHttp', () => {
test('options: fetchOptions', async () => {
const server = await createHttpServer((req, res) => {
const header = req.headers['x-custom-header']
- res.end(JSON.stringify({ result: header }))
+ res.end(JSON.stringify({ id: 0, jsonrpc: '2.0', result: header }))
})
const transport = RpcTransport.fromHttp(server.url, {
@@ -73,7 +73,7 @@ describe('fromHttp', () => {
test('options: fetchOptions (fn)', async () => {
const server = await createHttpServer((req, res) => {
const header = req.headers['x-custom-header']
- res.end(JSON.stringify({ result: header }))
+ res.end(JSON.stringify({ id: 0, jsonrpc: '2.0', result: header }))
})
const transport = RpcTransport.fromHttp(server.url, {
diff --git a/src/core/_test/_snap/Block.test.ts.snap b/src/core/_test/_snap/Block.test.ts.snap
index b3fdd420..da4bd117 100644
--- a/src/core/_test/_snap/Block.test.ts.snap
+++ b/src/core/_test/_snap/Block.test.ts.snap
@@ -22,7 +22,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"size": 56024n,
"stateRoot": "0x115fd5eac921e6728825958b2b87da8aaf17edc0085164f11de798f6ed00abbd",
"timestamp": 1715686979n,
- "totalDifficulty": 0n,
+ "totalDifficulty": undefined,
"transactions": [
{
"accessList": [],
@@ -504,7 +504,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x32353a6c91143bfd6c7d363b546e62a9a2489a20",
"transactionIndex": 18,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 0n,
"yParity": 0,
},
@@ -524,7 +524,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x6e1175d47c18e42ec010c4882eb2d735da67e857",
"transactionIndex": 19,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 1800000000000000n,
"yParity": 0,
},
@@ -636,7 +636,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"transactionIndex": 24,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 0n,
"yParity": 0,
},
@@ -656,7 +656,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xe1684d83b5ebc9e5661b8e9577108b9c7a6f3a98",
"transactionIndex": 25,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 0n,
"yParity": 0,
},
@@ -791,7 +791,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"transactionIndex": 31,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 0n,
"yParity": 1,
},
@@ -811,7 +811,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xd56e4eab23cb81f43168f9f45211eb027b9ac7cc",
"transactionIndex": 32,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 0n,
"yParity": 0,
},
@@ -1521,7 +1521,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xda26c7aa533780bd83bcbed583fbf424e8de23a3",
"transactionIndex": 63,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 1000000000000000000n,
"yParity": 0,
},
@@ -1541,7 +1541,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x0a992d191deec32afe36203ad87d7d289a738f81",
"transactionIndex": 64,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 0n,
"yParity": 0,
},
@@ -1561,7 +1561,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad",
"transactionIndex": 65,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 0n,
"yParity": 1,
},
@@ -1604,7 +1604,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"transactionIndex": 67,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 0n,
"yParity": 0,
},
@@ -1624,7 +1624,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"transactionIndex": 68,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 0n,
"yParity": 1,
},
@@ -1644,7 +1644,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x191caf41fca15700a2b73ec5c6bed942de15a6f2",
"transactionIndex": 69,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 10190000000000000n,
"yParity": 1,
},
@@ -1779,7 +1779,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x51876db703ce0f5b0023061dd1ee1230db7ab0b2",
"transactionIndex": 75,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 20996807858639000n,
"yParity": 1,
},
@@ -1983,7 +1983,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x44976275d2e2e53d11083d068028d52a9659eba6",
"transactionIndex": 84,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 64328149241306137n,
"yParity": 0,
},
@@ -2003,7 +2003,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xd3cf518c44d59686fbe01abec9711b9a97f67649",
"transactionIndex": 85,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 31000000000000000n,
"yParity": 1,
},
@@ -2023,7 +2023,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x7ab6c736baf1dac266aab43884d82974a9adcccf",
"transactionIndex": 86,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 11064022769138538n,
"yParity": 0,
},
@@ -2043,7 +2043,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x7ab6c736baf1dac266aab43884d82974a9adcccf",
"transactionIndex": 87,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 10264501514304336n,
"yParity": 1,
},
@@ -2063,7 +2063,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x774332b42d125e62ccd61f52198a589f44b6344d",
"transactionIndex": 88,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 355829000000000000n,
"yParity": 1,
},
@@ -2083,7 +2083,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x7ab6c736baf1dac266aab43884d82974a9adcccf",
"transactionIndex": 89,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 11060574742346550n,
"yParity": 1,
},
@@ -2103,7 +2103,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x7ab6c736baf1dac266aab43884d82974a9adcccf",
"transactionIndex": 90,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 8136991272916506n,
"yParity": 0,
},
@@ -2123,7 +2123,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"transactionIndex": 91,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 0n,
"yParity": 0,
},
@@ -2143,7 +2143,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xb8a8db037c873ffbaf7b1695abb4f3a04636cc4a",
"transactionIndex": 92,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 81869000000000000n,
"yParity": 1,
},
@@ -2163,7 +2163,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x7ab6c736baf1dac266aab43884d82974a9adcccf",
"transactionIndex": 93,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 9630113499451606n,
"yParity": 1,
},
@@ -2183,7 +2183,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"transactionIndex": 94,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 0n,
"yParity": 1,
},
@@ -2203,7 +2203,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x7ab6c736baf1dac266aab43884d82974a9adcccf",
"transactionIndex": 95,
"type": "legacy",
- "v": 27,
+ "v": 37,
"value": 11073297640854000n,
"yParity": 0,
},
@@ -2223,7 +2223,7 @@ exports[`fromRpc > behavior: network (with tx) 1`] = `
"to": "0x7ab6c736baf1dac266aab43884d82974a9adcccf",
"transactionIndex": 96,
"type": "legacy",
- "v": 28,
+ "v": 38,
"value": 13111814440728655n,
"yParity": 1,
},
diff --git a/src/webauthn/_test/Registration.test.ts b/src/webauthn/_test/Registration.test.ts
index cf4738b4..9b78721c 100644
--- a/src/webauthn/_test/Registration.test.ts
+++ b/src/webauthn/_test/Registration.test.ts
@@ -888,7 +888,7 @@ describe('verify', () => {
expect(() =>
Registration.verify({
credential,
- challenge: '0xbadbadbad',
+ challenge: '0xbadbadbadbad',
origin,
rpId,
}),
diff --git a/test/constants/accounts.ts b/test/constants/accounts.ts
index f7925b83..4d0f3c6c 100644
--- a/test/constants/accounts.ts
+++ b/test/constants/accounts.ts
@@ -3,7 +3,7 @@ import { Address, type Hex, Mnemonic, Secp256k1 } from 'ox'
export const accounts = new Array(20).fill(0).map((_, i) => {
const privateKey = Mnemonic.toPrivateKey(
'test test test test test test test test test test test junk',
- { path: Mnemonic.path({ index: i }) },
+ { as: 'Hex', path: Mnemonic.path({ index: i }) },
)
return {
address: Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey })),
From 326adfc16be3568b9a1d545a74c929c9e146cab2 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Wed, 13 May 2026 05:52:43 +1000
Subject: [PATCH 072/192] chore: drop wave prefix from changeset filenames
Amp-Thread-ID: https://ampcode.com/threads/T-019e1619-ba4f-7081-a18b-287d7a0711e9
---
.../{wave-0-abi-anonymous-events.md => abi-anonymous-events.md} | 0
...ctor-bytecode-prefix.md => abi-constructor-bytecode-prefix.md} | 0
...ecode-fast-partition.md => abi-event-decode-fast-partition.md} | 0
...opic-normalization.md => abi-event-hex-topic-normalization.md} | 0
...or-only-calldata.md => abi-function-selector-only-calldata.md} | 0
...eters-data-size-bound.md => abi-parameters-data-size-bound.md} | 0
...arameters-encode-packed.md => abi-parameters-encode-packed.md} | 0
...-1-account-proof-converters.md => account-proof-converters.md} | 0
...tore-async-pbkdf2.md => address-keys-keystore-async-pbkdf2.md} | 0
...-kdf-validation.md => address-keys-keystore-kdf-validation.md} | 0
...crypt-async-pr.md => address-keys-keystore-scrypt-async-pr.md} | 0
...-keys-mnemonic-default.md => address-keys-mnemonic-default.md} | 0
...erify-padding.md => anchor-crypto-webcrypto-verify-padding.md} | 0
...publickey-assert-shape.md => anchor-publickey-assert-shape.md} | 0
...y-fromhex-validate.md => anchor-publickey-fromhex-validate.md} | 0
...red-fields.md => block-state-block-fromrpc-required-fields.md} | 0
...te-length.md => block-state-bloom-contains-validate-length.md} | 0
...c-address-null.md => block-state-filter-torpc-address-null.md} | 0
...-quantity-converters.md => block-state-quantity-converters.md} | 0
...y-validation.md => block-state-typed-data-array-validation.md} | 0
...-address.md => block-state-validator-data-validate-address.md} | 0
...-state-value-validation.md => block-state-value-validation.md} | 0
.changeset/{wave-2-bloom-prepared.md => bloom-prepared.md} | 0
...-0-bytes-rlp-odd-length-pad.md => bytes-rlp-odd-length-pad.md} | 0
...bls-aggregate-validate.md => crypto-bls-aggregate-validate.md} | 0
...oint-frombytes-group.md => crypto-blspoint-frombytes-group.md} | 0
...sekey-validate-header.md => crypto-cosekey-validate-header.md} | 0
...entropy-default-doc.md => crypto-extra-entropy-default-doc.md} | 0
...-0-crypto-kzg-from-receiver.md => crypto-kzg-from-receiver.md} | 0
...pto-doc-corrections.md => crypto-webcrypto-doc-corrections.md} | 0
...ped-error.md => crypto-webcrypto-shared-secret-typed-error.md} | 0
...ked-typing.md => erc4337-user-operation-from-packed-typing.md} | 0
...ser-operation-gas-v08.md => erc4337-user-operation-gas-v08.md} | 0
...operation-hash-perf.md => erc4337-user-operation-hash-perf.md} | 0
...thorization.md => erc4337-user-operation-v08-authorization.md} | 0
...92-cache-abi-parameters.md => erc6492-cache-abi-parameters.md} | 0
...-magic-and-validate.md => erc6492-strip-magic-and-validate.md} | 0
...21-cache-abi-parameters.md => erc7821-cache-abi-parameters.md} | 0
...tural-detection.md => erc7821-execute-structural-detection.md} | 0
...ffix-and-recovery.md => erc8010-assert-suffix-and-recovery.md} | 0
...shared-tail.md => erc8021-attribution-fromdata-shared-tail.md} | 0
.changeset/{wave-4-fee-helpers.md => fee-helpers.md} | 0
...ve-4-personal-message-prefix.md => personal-message-prefix.md} | 0
...out-single-reject.md => promise-with-timeout-single-reject.md} | 0
...ve-0-provider-from-prototype.md => provider-from-prototype.md} | 0
...der-from-strict-eip1193.md => provider-from-strict-eip1193.md} | 0
...esponse-from-validation.md => rpc-response-from-validation.md} | 0
...rse-error-preserve.md => rpc-response-parse-error-preserve.md} | 0
...ponse-parse-validation.md => rpc-response-parse-validation.md} | 0
...-0-rpc-transport-empty-body.md => rpc-transport-empty-body.md} | 0
...-http-error-details.md => rpc-transport-http-error-details.md} | 0
...ransport-signal-compose.md => rpc-transport-signal-compose.md} | 0
.changeset/{wave-4-solidity-helpers.md => solidity-helpers.md} | 0
...re-normalize.md => tempo-authorization-signature-normalize.md} | 0
.../{wave-0-tempo-noncekey-random.md => tempo-noncekey-random.md} | 0
...wave-0-tempo-poolid-canonical.md => tempo-poolid-canonical.md} | 0
...ope-validate-prefix.md => tempo-txenvelope-validate-prefix.md} | 0
...ge-keys.md => transactions-access-list-strict-storage-keys.md} | 0
...md => transactions-authorization-fromtuplelist-return-type.md} | 0
...blob-validation.md => transactions-eip4844-blob-validation.md} | 0
...es.md => transactions-eip4844-deserialize-error-attributes.md} | 0
...eip4844-input-alias.md => transactions-eip4844-input-alias.md} | 0
...cardinality.md => transactions-eip4844-sidecar-cardinality.md} | 0
...ransactions-eip7702-torpc.md => transactions-eip7702-torpc.md} | 0
...tions-legacy-v-fromrpc.md => transactions-legacy-v-fromrpc.md} | 0
...nsactions-legacy-v-torpc.md => transactions-legacy-v-torpc.md} | 0
...eld.md => transactions-transaction-request-duplicate-field.md} | 0
...e.md => transactions-transaction-request-fromrpc-no-mutate.md} | 0
....md => transactions-transaction-rpc-transaction-index-zero.md} | 0
...ed-data-type-hashes-memo.md => typed-data-type-hashes-memo.md} | 0
...oad-hash.md => webauthn-authentication-getsignpayload-hash.md} | 0
...tication-sign-utf8.md => webauthn-authentication-sign-utf8.md} | 0
...-ed-flags.md => webauthn-authentication-verify-at-ed-flags.md} | 0
...d => webauthn-registration-verify-attestation-default-docs.md} | 0
74 files changed, 0 insertions(+), 0 deletions(-)
rename .changeset/{wave-0-abi-anonymous-events.md => abi-anonymous-events.md} (100%)
rename .changeset/{wave-0-abi-constructor-bytecode-prefix.md => abi-constructor-bytecode-prefix.md} (100%)
rename .changeset/{wave-0-abi-event-decode-fast-partition.md => abi-event-decode-fast-partition.md} (100%)
rename .changeset/{wave-0-abi-event-hex-topic-normalization.md => abi-event-hex-topic-normalization.md} (100%)
rename .changeset/{wave-0-abi-function-selector-only-calldata.md => abi-function-selector-only-calldata.md} (100%)
rename .changeset/{wave-0-abi-parameters-data-size-bound.md => abi-parameters-data-size-bound.md} (100%)
rename .changeset/{wave-0-abi-parameters-encode-packed.md => abi-parameters-encode-packed.md} (100%)
rename .changeset/{wave-1-account-proof-converters.md => account-proof-converters.md} (100%)
rename .changeset/{wave-0-address-keys-keystore-async-pbkdf2.md => address-keys-keystore-async-pbkdf2.md} (100%)
rename .changeset/{wave-0-address-keys-keystore-kdf-validation.md => address-keys-keystore-kdf-validation.md} (100%)
rename .changeset/{wave-0-address-keys-keystore-scrypt-async-pr.md => address-keys-keystore-scrypt-async-pr.md} (100%)
rename .changeset/{wave-0-address-keys-mnemonic-default.md => address-keys-mnemonic-default.md} (100%)
rename .changeset/{wave-0-anchor-crypto-webcrypto-verify-padding.md => anchor-crypto-webcrypto-verify-padding.md} (100%)
rename .changeset/{wave-0-anchor-publickey-assert-shape.md => anchor-publickey-assert-shape.md} (100%)
rename .changeset/{wave-0-anchor-publickey-fromhex-validate.md => anchor-publickey-fromhex-validate.md} (100%)
rename .changeset/{wave-0-block-state-block-fromrpc-required-fields.md => block-state-block-fromrpc-required-fields.md} (100%)
rename .changeset/{wave-0-block-state-bloom-contains-validate-length.md => block-state-bloom-contains-validate-length.md} (100%)
rename .changeset/{wave-0-block-state-filter-torpc-address-null.md => block-state-filter-torpc-address-null.md} (100%)
rename .changeset/{wave-1-block-state-quantity-converters.md => block-state-quantity-converters.md} (100%)
rename .changeset/{wave-0-block-state-typed-data-array-validation.md => block-state-typed-data-array-validation.md} (100%)
rename .changeset/{wave-0-block-state-validator-data-validate-address.md => block-state-validator-data-validate-address.md} (100%)
rename .changeset/{wave-0-block-state-value-validation.md => block-state-value-validation.md} (100%)
rename .changeset/{wave-2-bloom-prepared.md => bloom-prepared.md} (100%)
rename .changeset/{wave-0-bytes-rlp-odd-length-pad.md => bytes-rlp-odd-length-pad.md} (100%)
rename .changeset/{wave-0-crypto-bls-aggregate-validate.md => crypto-bls-aggregate-validate.md} (100%)
rename .changeset/{wave-0-crypto-blspoint-frombytes-group.md => crypto-blspoint-frombytes-group.md} (100%)
rename .changeset/{wave-0-crypto-cosekey-validate-header.md => crypto-cosekey-validate-header.md} (100%)
rename .changeset/{wave-0-crypto-extra-entropy-default-doc.md => crypto-extra-entropy-default-doc.md} (100%)
rename .changeset/{wave-0-crypto-kzg-from-receiver.md => crypto-kzg-from-receiver.md} (100%)
rename .changeset/{wave-0-crypto-webcrypto-doc-corrections.md => crypto-webcrypto-doc-corrections.md} (100%)
rename .changeset/{wave-0-crypto-webcrypto-shared-secret-typed-error.md => crypto-webcrypto-shared-secret-typed-error.md} (100%)
rename .changeset/{wave-0-erc4337-user-operation-from-packed-typing.md => erc4337-user-operation-from-packed-typing.md} (100%)
rename .changeset/{wave-0-erc4337-user-operation-gas-v08.md => erc4337-user-operation-gas-v08.md} (100%)
rename .changeset/{wave-1-erc4337-user-operation-hash-perf.md => erc4337-user-operation-hash-perf.md} (100%)
rename .changeset/{wave-0-erc4337-user-operation-v08-authorization.md => erc4337-user-operation-v08-authorization.md} (100%)
rename .changeset/{wave-1-erc6492-cache-abi-parameters.md => erc6492-cache-abi-parameters.md} (100%)
rename .changeset/{wave-0-erc6492-strip-magic-and-validate.md => erc6492-strip-magic-and-validate.md} (100%)
rename .changeset/{wave-1-erc7821-cache-abi-parameters.md => erc7821-cache-abi-parameters.md} (100%)
rename .changeset/{wave-0-erc7821-execute-structural-detection.md => erc7821-execute-structural-detection.md} (100%)
rename .changeset/{wave-0-erc8010-assert-suffix-and-recovery.md => erc8010-assert-suffix-and-recovery.md} (100%)
rename .changeset/{wave-1-erc8021-attribution-fromdata-shared-tail.md => erc8021-attribution-fromdata-shared-tail.md} (100%)
rename .changeset/{wave-4-fee-helpers.md => fee-helpers.md} (100%)
rename .changeset/{wave-4-personal-message-prefix.md => personal-message-prefix.md} (100%)
rename .changeset/{wave-0-promise-with-timeout-single-reject.md => promise-with-timeout-single-reject.md} (100%)
rename .changeset/{wave-0-provider-from-prototype.md => provider-from-prototype.md} (100%)
rename .changeset/{wave-0-provider-from-strict-eip1193.md => provider-from-strict-eip1193.md} (100%)
rename .changeset/{wave-0-rpc-response-from-validation.md => rpc-response-from-validation.md} (100%)
rename .changeset/{wave-0-rpc-response-parse-error-preserve.md => rpc-response-parse-error-preserve.md} (100%)
rename .changeset/{wave-0-rpc-response-parse-validation.md => rpc-response-parse-validation.md} (100%)
rename .changeset/{wave-0-rpc-transport-empty-body.md => rpc-transport-empty-body.md} (100%)
rename .changeset/{wave-0-rpc-transport-http-error-details.md => rpc-transport-http-error-details.md} (100%)
rename .changeset/{wave-0-rpc-transport-signal-compose.md => rpc-transport-signal-compose.md} (100%)
rename .changeset/{wave-4-solidity-helpers.md => solidity-helpers.md} (100%)
rename .changeset/{wave-0-tempo-authorization-signature-normalize.md => tempo-authorization-signature-normalize.md} (100%)
rename .changeset/{wave-0-tempo-noncekey-random.md => tempo-noncekey-random.md} (100%)
rename .changeset/{wave-0-tempo-poolid-canonical.md => tempo-poolid-canonical.md} (100%)
rename .changeset/{wave-0-tempo-txenvelope-validate-prefix.md => tempo-txenvelope-validate-prefix.md} (100%)
rename .changeset/{wave-0-transactions-access-list-strict-storage-keys.md => transactions-access-list-strict-storage-keys.md} (100%)
rename .changeset/{wave-0-transactions-authorization-fromtuplelist-return-type.md => transactions-authorization-fromtuplelist-return-type.md} (100%)
rename .changeset/{wave-0-transactions-eip4844-blob-validation.md => transactions-eip4844-blob-validation.md} (100%)
rename .changeset/{wave-0-transactions-eip4844-deserialize-error-attributes.md => transactions-eip4844-deserialize-error-attributes.md} (100%)
rename .changeset/{wave-0-transactions-eip4844-input-alias.md => transactions-eip4844-input-alias.md} (100%)
rename .changeset/{wave-0-transactions-eip4844-sidecar-cardinality.md => transactions-eip4844-sidecar-cardinality.md} (100%)
rename .changeset/{wave-0-transactions-eip7702-torpc.md => transactions-eip7702-torpc.md} (100%)
rename .changeset/{wave-0-transactions-legacy-v-fromrpc.md => transactions-legacy-v-fromrpc.md} (100%)
rename .changeset/{wave-0-transactions-legacy-v-torpc.md => transactions-legacy-v-torpc.md} (100%)
rename .changeset/{wave-0-transactions-transaction-request-duplicate-field.md => transactions-transaction-request-duplicate-field.md} (100%)
rename .changeset/{wave-0-transactions-transaction-request-fromrpc-no-mutate.md => transactions-transaction-request-fromrpc-no-mutate.md} (100%)
rename .changeset/{wave-0-transactions-transaction-rpc-transaction-index-zero.md => transactions-transaction-rpc-transaction-index-zero.md} (100%)
rename .changeset/{wave-2-typed-data-type-hashes-memo.md => typed-data-type-hashes-memo.md} (100%)
rename .changeset/{wave-0-webauthn-authentication-getsignpayload-hash.md => webauthn-authentication-getsignpayload-hash.md} (100%)
rename .changeset/{wave-0-webauthn-authentication-sign-utf8.md => webauthn-authentication-sign-utf8.md} (100%)
rename .changeset/{wave-0-webauthn-authentication-verify-at-ed-flags.md => webauthn-authentication-verify-at-ed-flags.md} (100%)
rename .changeset/{wave-0-webauthn-registration-verify-attestation-default-docs.md => webauthn-registration-verify-attestation-default-docs.md} (100%)
diff --git a/.changeset/wave-0-abi-anonymous-events.md b/.changeset/abi-anonymous-events.md
similarity index 100%
rename from .changeset/wave-0-abi-anonymous-events.md
rename to .changeset/abi-anonymous-events.md
diff --git a/.changeset/wave-0-abi-constructor-bytecode-prefix.md b/.changeset/abi-constructor-bytecode-prefix.md
similarity index 100%
rename from .changeset/wave-0-abi-constructor-bytecode-prefix.md
rename to .changeset/abi-constructor-bytecode-prefix.md
diff --git a/.changeset/wave-0-abi-event-decode-fast-partition.md b/.changeset/abi-event-decode-fast-partition.md
similarity index 100%
rename from .changeset/wave-0-abi-event-decode-fast-partition.md
rename to .changeset/abi-event-decode-fast-partition.md
diff --git a/.changeset/wave-0-abi-event-hex-topic-normalization.md b/.changeset/abi-event-hex-topic-normalization.md
similarity index 100%
rename from .changeset/wave-0-abi-event-hex-topic-normalization.md
rename to .changeset/abi-event-hex-topic-normalization.md
diff --git a/.changeset/wave-0-abi-function-selector-only-calldata.md b/.changeset/abi-function-selector-only-calldata.md
similarity index 100%
rename from .changeset/wave-0-abi-function-selector-only-calldata.md
rename to .changeset/abi-function-selector-only-calldata.md
diff --git a/.changeset/wave-0-abi-parameters-data-size-bound.md b/.changeset/abi-parameters-data-size-bound.md
similarity index 100%
rename from .changeset/wave-0-abi-parameters-data-size-bound.md
rename to .changeset/abi-parameters-data-size-bound.md
diff --git a/.changeset/wave-0-abi-parameters-encode-packed.md b/.changeset/abi-parameters-encode-packed.md
similarity index 100%
rename from .changeset/wave-0-abi-parameters-encode-packed.md
rename to .changeset/abi-parameters-encode-packed.md
diff --git a/.changeset/wave-1-account-proof-converters.md b/.changeset/account-proof-converters.md
similarity index 100%
rename from .changeset/wave-1-account-proof-converters.md
rename to .changeset/account-proof-converters.md
diff --git a/.changeset/wave-0-address-keys-keystore-async-pbkdf2.md b/.changeset/address-keys-keystore-async-pbkdf2.md
similarity index 100%
rename from .changeset/wave-0-address-keys-keystore-async-pbkdf2.md
rename to .changeset/address-keys-keystore-async-pbkdf2.md
diff --git a/.changeset/wave-0-address-keys-keystore-kdf-validation.md b/.changeset/address-keys-keystore-kdf-validation.md
similarity index 100%
rename from .changeset/wave-0-address-keys-keystore-kdf-validation.md
rename to .changeset/address-keys-keystore-kdf-validation.md
diff --git a/.changeset/wave-0-address-keys-keystore-scrypt-async-pr.md b/.changeset/address-keys-keystore-scrypt-async-pr.md
similarity index 100%
rename from .changeset/wave-0-address-keys-keystore-scrypt-async-pr.md
rename to .changeset/address-keys-keystore-scrypt-async-pr.md
diff --git a/.changeset/wave-0-address-keys-mnemonic-default.md b/.changeset/address-keys-mnemonic-default.md
similarity index 100%
rename from .changeset/wave-0-address-keys-mnemonic-default.md
rename to .changeset/address-keys-mnemonic-default.md
diff --git a/.changeset/wave-0-anchor-crypto-webcrypto-verify-padding.md b/.changeset/anchor-crypto-webcrypto-verify-padding.md
similarity index 100%
rename from .changeset/wave-0-anchor-crypto-webcrypto-verify-padding.md
rename to .changeset/anchor-crypto-webcrypto-verify-padding.md
diff --git a/.changeset/wave-0-anchor-publickey-assert-shape.md b/.changeset/anchor-publickey-assert-shape.md
similarity index 100%
rename from .changeset/wave-0-anchor-publickey-assert-shape.md
rename to .changeset/anchor-publickey-assert-shape.md
diff --git a/.changeset/wave-0-anchor-publickey-fromhex-validate.md b/.changeset/anchor-publickey-fromhex-validate.md
similarity index 100%
rename from .changeset/wave-0-anchor-publickey-fromhex-validate.md
rename to .changeset/anchor-publickey-fromhex-validate.md
diff --git a/.changeset/wave-0-block-state-block-fromrpc-required-fields.md b/.changeset/block-state-block-fromrpc-required-fields.md
similarity index 100%
rename from .changeset/wave-0-block-state-block-fromrpc-required-fields.md
rename to .changeset/block-state-block-fromrpc-required-fields.md
diff --git a/.changeset/wave-0-block-state-bloom-contains-validate-length.md b/.changeset/block-state-bloom-contains-validate-length.md
similarity index 100%
rename from .changeset/wave-0-block-state-bloom-contains-validate-length.md
rename to .changeset/block-state-bloom-contains-validate-length.md
diff --git a/.changeset/wave-0-block-state-filter-torpc-address-null.md b/.changeset/block-state-filter-torpc-address-null.md
similarity index 100%
rename from .changeset/wave-0-block-state-filter-torpc-address-null.md
rename to .changeset/block-state-filter-torpc-address-null.md
diff --git a/.changeset/wave-1-block-state-quantity-converters.md b/.changeset/block-state-quantity-converters.md
similarity index 100%
rename from .changeset/wave-1-block-state-quantity-converters.md
rename to .changeset/block-state-quantity-converters.md
diff --git a/.changeset/wave-0-block-state-typed-data-array-validation.md b/.changeset/block-state-typed-data-array-validation.md
similarity index 100%
rename from .changeset/wave-0-block-state-typed-data-array-validation.md
rename to .changeset/block-state-typed-data-array-validation.md
diff --git a/.changeset/wave-0-block-state-validator-data-validate-address.md b/.changeset/block-state-validator-data-validate-address.md
similarity index 100%
rename from .changeset/wave-0-block-state-validator-data-validate-address.md
rename to .changeset/block-state-validator-data-validate-address.md
diff --git a/.changeset/wave-0-block-state-value-validation.md b/.changeset/block-state-value-validation.md
similarity index 100%
rename from .changeset/wave-0-block-state-value-validation.md
rename to .changeset/block-state-value-validation.md
diff --git a/.changeset/wave-2-bloom-prepared.md b/.changeset/bloom-prepared.md
similarity index 100%
rename from .changeset/wave-2-bloom-prepared.md
rename to .changeset/bloom-prepared.md
diff --git a/.changeset/wave-0-bytes-rlp-odd-length-pad.md b/.changeset/bytes-rlp-odd-length-pad.md
similarity index 100%
rename from .changeset/wave-0-bytes-rlp-odd-length-pad.md
rename to .changeset/bytes-rlp-odd-length-pad.md
diff --git a/.changeset/wave-0-crypto-bls-aggregate-validate.md b/.changeset/crypto-bls-aggregate-validate.md
similarity index 100%
rename from .changeset/wave-0-crypto-bls-aggregate-validate.md
rename to .changeset/crypto-bls-aggregate-validate.md
diff --git a/.changeset/wave-0-crypto-blspoint-frombytes-group.md b/.changeset/crypto-blspoint-frombytes-group.md
similarity index 100%
rename from .changeset/wave-0-crypto-blspoint-frombytes-group.md
rename to .changeset/crypto-blspoint-frombytes-group.md
diff --git a/.changeset/wave-0-crypto-cosekey-validate-header.md b/.changeset/crypto-cosekey-validate-header.md
similarity index 100%
rename from .changeset/wave-0-crypto-cosekey-validate-header.md
rename to .changeset/crypto-cosekey-validate-header.md
diff --git a/.changeset/wave-0-crypto-extra-entropy-default-doc.md b/.changeset/crypto-extra-entropy-default-doc.md
similarity index 100%
rename from .changeset/wave-0-crypto-extra-entropy-default-doc.md
rename to .changeset/crypto-extra-entropy-default-doc.md
diff --git a/.changeset/wave-0-crypto-kzg-from-receiver.md b/.changeset/crypto-kzg-from-receiver.md
similarity index 100%
rename from .changeset/wave-0-crypto-kzg-from-receiver.md
rename to .changeset/crypto-kzg-from-receiver.md
diff --git a/.changeset/wave-0-crypto-webcrypto-doc-corrections.md b/.changeset/crypto-webcrypto-doc-corrections.md
similarity index 100%
rename from .changeset/wave-0-crypto-webcrypto-doc-corrections.md
rename to .changeset/crypto-webcrypto-doc-corrections.md
diff --git a/.changeset/wave-0-crypto-webcrypto-shared-secret-typed-error.md b/.changeset/crypto-webcrypto-shared-secret-typed-error.md
similarity index 100%
rename from .changeset/wave-0-crypto-webcrypto-shared-secret-typed-error.md
rename to .changeset/crypto-webcrypto-shared-secret-typed-error.md
diff --git a/.changeset/wave-0-erc4337-user-operation-from-packed-typing.md b/.changeset/erc4337-user-operation-from-packed-typing.md
similarity index 100%
rename from .changeset/wave-0-erc4337-user-operation-from-packed-typing.md
rename to .changeset/erc4337-user-operation-from-packed-typing.md
diff --git a/.changeset/wave-0-erc4337-user-operation-gas-v08.md b/.changeset/erc4337-user-operation-gas-v08.md
similarity index 100%
rename from .changeset/wave-0-erc4337-user-operation-gas-v08.md
rename to .changeset/erc4337-user-operation-gas-v08.md
diff --git a/.changeset/wave-1-erc4337-user-operation-hash-perf.md b/.changeset/erc4337-user-operation-hash-perf.md
similarity index 100%
rename from .changeset/wave-1-erc4337-user-operation-hash-perf.md
rename to .changeset/erc4337-user-operation-hash-perf.md
diff --git a/.changeset/wave-0-erc4337-user-operation-v08-authorization.md b/.changeset/erc4337-user-operation-v08-authorization.md
similarity index 100%
rename from .changeset/wave-0-erc4337-user-operation-v08-authorization.md
rename to .changeset/erc4337-user-operation-v08-authorization.md
diff --git a/.changeset/wave-1-erc6492-cache-abi-parameters.md b/.changeset/erc6492-cache-abi-parameters.md
similarity index 100%
rename from .changeset/wave-1-erc6492-cache-abi-parameters.md
rename to .changeset/erc6492-cache-abi-parameters.md
diff --git a/.changeset/wave-0-erc6492-strip-magic-and-validate.md b/.changeset/erc6492-strip-magic-and-validate.md
similarity index 100%
rename from .changeset/wave-0-erc6492-strip-magic-and-validate.md
rename to .changeset/erc6492-strip-magic-and-validate.md
diff --git a/.changeset/wave-1-erc7821-cache-abi-parameters.md b/.changeset/erc7821-cache-abi-parameters.md
similarity index 100%
rename from .changeset/wave-1-erc7821-cache-abi-parameters.md
rename to .changeset/erc7821-cache-abi-parameters.md
diff --git a/.changeset/wave-0-erc7821-execute-structural-detection.md b/.changeset/erc7821-execute-structural-detection.md
similarity index 100%
rename from .changeset/wave-0-erc7821-execute-structural-detection.md
rename to .changeset/erc7821-execute-structural-detection.md
diff --git a/.changeset/wave-0-erc8010-assert-suffix-and-recovery.md b/.changeset/erc8010-assert-suffix-and-recovery.md
similarity index 100%
rename from .changeset/wave-0-erc8010-assert-suffix-and-recovery.md
rename to .changeset/erc8010-assert-suffix-and-recovery.md
diff --git a/.changeset/wave-1-erc8021-attribution-fromdata-shared-tail.md b/.changeset/erc8021-attribution-fromdata-shared-tail.md
similarity index 100%
rename from .changeset/wave-1-erc8021-attribution-fromdata-shared-tail.md
rename to .changeset/erc8021-attribution-fromdata-shared-tail.md
diff --git a/.changeset/wave-4-fee-helpers.md b/.changeset/fee-helpers.md
similarity index 100%
rename from .changeset/wave-4-fee-helpers.md
rename to .changeset/fee-helpers.md
diff --git a/.changeset/wave-4-personal-message-prefix.md b/.changeset/personal-message-prefix.md
similarity index 100%
rename from .changeset/wave-4-personal-message-prefix.md
rename to .changeset/personal-message-prefix.md
diff --git a/.changeset/wave-0-promise-with-timeout-single-reject.md b/.changeset/promise-with-timeout-single-reject.md
similarity index 100%
rename from .changeset/wave-0-promise-with-timeout-single-reject.md
rename to .changeset/promise-with-timeout-single-reject.md
diff --git a/.changeset/wave-0-provider-from-prototype.md b/.changeset/provider-from-prototype.md
similarity index 100%
rename from .changeset/wave-0-provider-from-prototype.md
rename to .changeset/provider-from-prototype.md
diff --git a/.changeset/wave-0-provider-from-strict-eip1193.md b/.changeset/provider-from-strict-eip1193.md
similarity index 100%
rename from .changeset/wave-0-provider-from-strict-eip1193.md
rename to .changeset/provider-from-strict-eip1193.md
diff --git a/.changeset/wave-0-rpc-response-from-validation.md b/.changeset/rpc-response-from-validation.md
similarity index 100%
rename from .changeset/wave-0-rpc-response-from-validation.md
rename to .changeset/rpc-response-from-validation.md
diff --git a/.changeset/wave-0-rpc-response-parse-error-preserve.md b/.changeset/rpc-response-parse-error-preserve.md
similarity index 100%
rename from .changeset/wave-0-rpc-response-parse-error-preserve.md
rename to .changeset/rpc-response-parse-error-preserve.md
diff --git a/.changeset/wave-0-rpc-response-parse-validation.md b/.changeset/rpc-response-parse-validation.md
similarity index 100%
rename from .changeset/wave-0-rpc-response-parse-validation.md
rename to .changeset/rpc-response-parse-validation.md
diff --git a/.changeset/wave-0-rpc-transport-empty-body.md b/.changeset/rpc-transport-empty-body.md
similarity index 100%
rename from .changeset/wave-0-rpc-transport-empty-body.md
rename to .changeset/rpc-transport-empty-body.md
diff --git a/.changeset/wave-0-rpc-transport-http-error-details.md b/.changeset/rpc-transport-http-error-details.md
similarity index 100%
rename from .changeset/wave-0-rpc-transport-http-error-details.md
rename to .changeset/rpc-transport-http-error-details.md
diff --git a/.changeset/wave-0-rpc-transport-signal-compose.md b/.changeset/rpc-transport-signal-compose.md
similarity index 100%
rename from .changeset/wave-0-rpc-transport-signal-compose.md
rename to .changeset/rpc-transport-signal-compose.md
diff --git a/.changeset/wave-4-solidity-helpers.md b/.changeset/solidity-helpers.md
similarity index 100%
rename from .changeset/wave-4-solidity-helpers.md
rename to .changeset/solidity-helpers.md
diff --git a/.changeset/wave-0-tempo-authorization-signature-normalize.md b/.changeset/tempo-authorization-signature-normalize.md
similarity index 100%
rename from .changeset/wave-0-tempo-authorization-signature-normalize.md
rename to .changeset/tempo-authorization-signature-normalize.md
diff --git a/.changeset/wave-0-tempo-noncekey-random.md b/.changeset/tempo-noncekey-random.md
similarity index 100%
rename from .changeset/wave-0-tempo-noncekey-random.md
rename to .changeset/tempo-noncekey-random.md
diff --git a/.changeset/wave-0-tempo-poolid-canonical.md b/.changeset/tempo-poolid-canonical.md
similarity index 100%
rename from .changeset/wave-0-tempo-poolid-canonical.md
rename to .changeset/tempo-poolid-canonical.md
diff --git a/.changeset/wave-0-tempo-txenvelope-validate-prefix.md b/.changeset/tempo-txenvelope-validate-prefix.md
similarity index 100%
rename from .changeset/wave-0-tempo-txenvelope-validate-prefix.md
rename to .changeset/tempo-txenvelope-validate-prefix.md
diff --git a/.changeset/wave-0-transactions-access-list-strict-storage-keys.md b/.changeset/transactions-access-list-strict-storage-keys.md
similarity index 100%
rename from .changeset/wave-0-transactions-access-list-strict-storage-keys.md
rename to .changeset/transactions-access-list-strict-storage-keys.md
diff --git a/.changeset/wave-0-transactions-authorization-fromtuplelist-return-type.md b/.changeset/transactions-authorization-fromtuplelist-return-type.md
similarity index 100%
rename from .changeset/wave-0-transactions-authorization-fromtuplelist-return-type.md
rename to .changeset/transactions-authorization-fromtuplelist-return-type.md
diff --git a/.changeset/wave-0-transactions-eip4844-blob-validation.md b/.changeset/transactions-eip4844-blob-validation.md
similarity index 100%
rename from .changeset/wave-0-transactions-eip4844-blob-validation.md
rename to .changeset/transactions-eip4844-blob-validation.md
diff --git a/.changeset/wave-0-transactions-eip4844-deserialize-error-attributes.md b/.changeset/transactions-eip4844-deserialize-error-attributes.md
similarity index 100%
rename from .changeset/wave-0-transactions-eip4844-deserialize-error-attributes.md
rename to .changeset/transactions-eip4844-deserialize-error-attributes.md
diff --git a/.changeset/wave-0-transactions-eip4844-input-alias.md b/.changeset/transactions-eip4844-input-alias.md
similarity index 100%
rename from .changeset/wave-0-transactions-eip4844-input-alias.md
rename to .changeset/transactions-eip4844-input-alias.md
diff --git a/.changeset/wave-0-transactions-eip4844-sidecar-cardinality.md b/.changeset/transactions-eip4844-sidecar-cardinality.md
similarity index 100%
rename from .changeset/wave-0-transactions-eip4844-sidecar-cardinality.md
rename to .changeset/transactions-eip4844-sidecar-cardinality.md
diff --git a/.changeset/wave-0-transactions-eip7702-torpc.md b/.changeset/transactions-eip7702-torpc.md
similarity index 100%
rename from .changeset/wave-0-transactions-eip7702-torpc.md
rename to .changeset/transactions-eip7702-torpc.md
diff --git a/.changeset/wave-0-transactions-legacy-v-fromrpc.md b/.changeset/transactions-legacy-v-fromrpc.md
similarity index 100%
rename from .changeset/wave-0-transactions-legacy-v-fromrpc.md
rename to .changeset/transactions-legacy-v-fromrpc.md
diff --git a/.changeset/wave-0-transactions-legacy-v-torpc.md b/.changeset/transactions-legacy-v-torpc.md
similarity index 100%
rename from .changeset/wave-0-transactions-legacy-v-torpc.md
rename to .changeset/transactions-legacy-v-torpc.md
diff --git a/.changeset/wave-0-transactions-transaction-request-duplicate-field.md b/.changeset/transactions-transaction-request-duplicate-field.md
similarity index 100%
rename from .changeset/wave-0-transactions-transaction-request-duplicate-field.md
rename to .changeset/transactions-transaction-request-duplicate-field.md
diff --git a/.changeset/wave-0-transactions-transaction-request-fromrpc-no-mutate.md b/.changeset/transactions-transaction-request-fromrpc-no-mutate.md
similarity index 100%
rename from .changeset/wave-0-transactions-transaction-request-fromrpc-no-mutate.md
rename to .changeset/transactions-transaction-request-fromrpc-no-mutate.md
diff --git a/.changeset/wave-0-transactions-transaction-rpc-transaction-index-zero.md b/.changeset/transactions-transaction-rpc-transaction-index-zero.md
similarity index 100%
rename from .changeset/wave-0-transactions-transaction-rpc-transaction-index-zero.md
rename to .changeset/transactions-transaction-rpc-transaction-index-zero.md
diff --git a/.changeset/wave-2-typed-data-type-hashes-memo.md b/.changeset/typed-data-type-hashes-memo.md
similarity index 100%
rename from .changeset/wave-2-typed-data-type-hashes-memo.md
rename to .changeset/typed-data-type-hashes-memo.md
diff --git a/.changeset/wave-0-webauthn-authentication-getsignpayload-hash.md b/.changeset/webauthn-authentication-getsignpayload-hash.md
similarity index 100%
rename from .changeset/wave-0-webauthn-authentication-getsignpayload-hash.md
rename to .changeset/webauthn-authentication-getsignpayload-hash.md
diff --git a/.changeset/wave-0-webauthn-authentication-sign-utf8.md b/.changeset/webauthn-authentication-sign-utf8.md
similarity index 100%
rename from .changeset/wave-0-webauthn-authentication-sign-utf8.md
rename to .changeset/webauthn-authentication-sign-utf8.md
diff --git a/.changeset/wave-0-webauthn-authentication-verify-at-ed-flags.md b/.changeset/webauthn-authentication-verify-at-ed-flags.md
similarity index 100%
rename from .changeset/wave-0-webauthn-authentication-verify-at-ed-flags.md
rename to .changeset/webauthn-authentication-verify-at-ed-flags.md
diff --git a/.changeset/wave-0-webauthn-registration-verify-attestation-default-docs.md b/.changeset/webauthn-registration-verify-attestation-default-docs.md
similarity index 100%
rename from .changeset/wave-0-webauthn-registration-verify-attestation-default-docs.md
rename to .changeset/webauthn-registration-verify-attestation-default-docs.md
From 2b97654d0850b158d1fb80dc639430b78243896f Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Wed, 13 May 2026 07:17:26 +1000
Subject: [PATCH 073/192] refactor(internal): rename quantity helpers to
`toBigInt` / `fromBigInt` / `toNumber` / `fromNumber`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1619-ba4f-7081-a18b-287d7a0711e9
---
src/core/AccountProof.ts | 2 +-
src/core/Block.ts | 20 ++++++++++----------
src/core/BlockOverrides.ts | 24 ++++++++++++------------
src/core/StateOverrides.ts | 8 ++++----
src/core/internal/quantity.ts | 10 +++++-----
5 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/src/core/AccountProof.ts b/src/core/AccountProof.ts
index 5fc44c17..cf8a466a 100644
--- a/src/core/AccountProof.ts
+++ b/src/core/AccountProof.ts
@@ -137,7 +137,7 @@ export function toRpc(proof: AccountProof): Rpc {
storageProof: proof.storageProof.map((slot) => ({
key: slot.key,
proof: slot.proof,
- value: Quantity.bigIntToQuantity(slot.value)!,
+ value: Quantity.fromBigInt(slot.value)!,
})),
}
}
diff --git a/src/core/Block.ts b/src/core/Block.ts
index 1ff82432..1ba91410 100644
--- a/src/core/Block.ts
+++ b/src/core/Block.ts
@@ -156,11 +156,11 @@ export function toRpc<
return Transaction.toRpc(transaction as any) as any
})
return {
- baseFeePerGas: Quantity.bigIntToQuantity(block.baseFeePerGas),
- blobGasUsed: Quantity.bigIntToQuantity(block.blobGasUsed),
- excessBlobGas: Quantity.bigIntToQuantity(block.excessBlobGas),
+ baseFeePerGas: Quantity.fromBigInt(block.baseFeePerGas),
+ blobGasUsed: Quantity.fromBigInt(block.blobGasUsed),
+ excessBlobGas: Quantity.fromBigInt(block.excessBlobGas),
extraData: block.extraData,
- difficulty: Quantity.bigIntToQuantity(block.difficulty),
+ difficulty: Quantity.fromBigInt(block.difficulty),
gasLimit: Hex.fromNumber(block.gasLimit),
gasUsed: Hex.fromNumber(block.gasUsed),
hash: block.hash,
@@ -179,7 +179,7 @@ export function toRpc<
size: Hex.fromNumber(block.size),
stateRoot: block.stateRoot,
timestamp: Hex.fromNumber(block.timestamp),
- totalDifficulty: Quantity.bigIntToQuantity(block.totalDifficulty),
+ totalDifficulty: Quantity.fromBigInt(block.totalDifficulty),
transactions,
transactionsRoot: block.transactionsRoot,
uncles: block.uncles,
@@ -277,17 +277,17 @@ export function fromRpc<
})
return {
...block,
- baseFeePerGas: Quantity.quantityToBigInt(block.baseFeePerGas),
- blobGasUsed: Quantity.quantityToBigInt(block.blobGasUsed),
- difficulty: Quantity.quantityToBigInt(block.difficulty),
- excessBlobGas: Quantity.quantityToBigInt(block.excessBlobGas),
+ baseFeePerGas: Quantity.toBigInt(block.baseFeePerGas),
+ blobGasUsed: Quantity.toBigInt(block.blobGasUsed),
+ difficulty: Quantity.toBigInt(block.difficulty),
+ excessBlobGas: Quantity.toBigInt(block.excessBlobGas),
gasLimit: BigInt(block.gasLimit ?? 0n),
gasUsed: BigInt(block.gasUsed ?? 0n),
number: block.number ? BigInt(block.number) : null,
size: BigInt(block.size ?? 0n),
stateRoot: block.stateRoot,
timestamp: BigInt(block.timestamp ?? 0n),
- totalDifficulty: Quantity.quantityToBigInt(block.totalDifficulty),
+ totalDifficulty: Quantity.toBigInt(block.totalDifficulty),
transactions,
withdrawals: block.withdrawals?.map(Withdrawal.fromRpc),
} as Block as never
diff --git a/src/core/BlockOverrides.ts b/src/core/BlockOverrides.ts
index 029e6b63..3cc33c60 100644
--- a/src/core/BlockOverrides.ts
+++ b/src/core/BlockOverrides.ts
@@ -62,25 +62,25 @@ export type Rpc = BlockOverrides
export function fromRpc(rpcBlockOverrides: Rpc): BlockOverrides {
const overrides: BlockOverrides = {}
if (rpcBlockOverrides.baseFeePerGas !== undefined)
- overrides.baseFeePerGas = Quantity.quantityToBigInt(
+ overrides.baseFeePerGas = Quantity.toBigInt(
rpcBlockOverrides.baseFeePerGas,
)
if (rpcBlockOverrides.blobBaseFee !== undefined)
- overrides.blobBaseFee = Quantity.quantityToBigInt(
+ overrides.blobBaseFee = Quantity.toBigInt(
rpcBlockOverrides.blobBaseFee,
)
if (rpcBlockOverrides.feeRecipient !== undefined)
overrides.feeRecipient = rpcBlockOverrides.feeRecipient
if (rpcBlockOverrides.gasLimit !== undefined)
- overrides.gasLimit = Quantity.quantityToBigInt(rpcBlockOverrides.gasLimit)
+ overrides.gasLimit = Quantity.toBigInt(rpcBlockOverrides.gasLimit)
if (rpcBlockOverrides.number !== undefined)
- overrides.number = Quantity.quantityToBigInt(rpcBlockOverrides.number)
+ overrides.number = Quantity.toBigInt(rpcBlockOverrides.number)
if (rpcBlockOverrides.prevRandao !== undefined)
- overrides.prevRandao = Quantity.quantityToBigInt(
+ overrides.prevRandao = Quantity.toBigInt(
rpcBlockOverrides.prevRandao,
)
if (rpcBlockOverrides.time !== undefined)
- overrides.time = Quantity.quantityToBigInt(rpcBlockOverrides.time)
+ overrides.time = Quantity.toBigInt(rpcBlockOverrides.time)
if (rpcBlockOverrides.withdrawals !== undefined)
overrides.withdrawals = rpcBlockOverrides.withdrawals.map(
Withdrawal.fromRpc,
@@ -120,19 +120,19 @@ export function fromRpc(rpcBlockOverrides: Rpc): BlockOverrides {
export function toRpc(blockOverrides: BlockOverrides): Rpc {
const rpc: Rpc = {}
if (typeof blockOverrides.baseFeePerGas === 'bigint')
- rpc.baseFeePerGas = Quantity.bigIntToQuantity(blockOverrides.baseFeePerGas)
+ rpc.baseFeePerGas = Quantity.fromBigInt(blockOverrides.baseFeePerGas)
if (typeof blockOverrides.blobBaseFee === 'bigint')
- rpc.blobBaseFee = Quantity.bigIntToQuantity(blockOverrides.blobBaseFee)
+ rpc.blobBaseFee = Quantity.fromBigInt(blockOverrides.blobBaseFee)
if (typeof blockOverrides.feeRecipient === 'string')
rpc.feeRecipient = blockOverrides.feeRecipient
if (typeof blockOverrides.gasLimit === 'bigint')
- rpc.gasLimit = Quantity.bigIntToQuantity(blockOverrides.gasLimit)
+ rpc.gasLimit = Quantity.fromBigInt(blockOverrides.gasLimit)
if (typeof blockOverrides.number === 'bigint')
- rpc.number = Quantity.bigIntToQuantity(blockOverrides.number)
+ rpc.number = Quantity.fromBigInt(blockOverrides.number)
if (typeof blockOverrides.prevRandao === 'bigint')
- rpc.prevRandao = Quantity.bigIntToQuantity(blockOverrides.prevRandao)
+ rpc.prevRandao = Quantity.fromBigInt(blockOverrides.prevRandao)
if (typeof blockOverrides.time === 'bigint')
- rpc.time = Quantity.bigIntToQuantity(blockOverrides.time)
+ rpc.time = Quantity.fromBigInt(blockOverrides.time)
if (blockOverrides.withdrawals !== undefined)
rpc.withdrawals = blockOverrides.withdrawals.map(Withdrawal.toRpc)
return rpc
diff --git a/src/core/StateOverrides.ts b/src/core/StateOverrides.ts
index 1a4e81b4..2850b98a 100644
--- a/src/core/StateOverrides.ts
+++ b/src/core/StateOverrides.ts
@@ -76,7 +76,7 @@ export function fromRpc(rpcStateOverrides: Rpc): StateOverrides {
)) {
const accountOverrides: AccountOverrides = {}
if (accountOverridesRpc.balance !== undefined)
- accountOverrides.balance = Quantity.quantityToBigInt(
+ accountOverrides.balance = Quantity.toBigInt(
accountOverridesRpc.balance,
)
if (accountOverridesRpc.code)
@@ -85,7 +85,7 @@ export function fromRpc(rpcStateOverrides: Rpc): StateOverrides {
accountOverrides.movePrecompileToAddress =
accountOverridesRpc.movePrecompileToAddress
if (accountOverridesRpc.nonce !== undefined)
- accountOverrides.nonce = Quantity.quantityToBigInt(
+ accountOverrides.nonce = Quantity.toBigInt(
accountOverridesRpc.nonce,
)
if (accountOverridesRpc.state)
@@ -119,7 +119,7 @@ export function toRpc(stateOverrides: StateOverrides): Rpc {
for (const [address, accountOverrides] of Object.entries(stateOverrides)) {
const accountOverridesRpc: RpcAccountOverrides = {}
if (typeof accountOverrides.balance === 'bigint')
- accountOverridesRpc.balance = Quantity.bigIntToQuantity(
+ accountOverridesRpc.balance = Quantity.fromBigInt(
accountOverrides.balance,
)
if (accountOverrides.code) accountOverridesRpc.code = accountOverrides.code
@@ -127,7 +127,7 @@ export function toRpc(stateOverrides: StateOverrides): Rpc {
accountOverridesRpc.movePrecompileToAddress =
accountOverrides.movePrecompileToAddress
if (typeof accountOverrides.nonce === 'bigint')
- accountOverridesRpc.nonce = Quantity.bigIntToQuantity(
+ accountOverridesRpc.nonce = Quantity.fromBigInt(
accountOverrides.nonce,
)
if (accountOverrides.state)
diff --git a/src/core/internal/quantity.ts b/src/core/internal/quantity.ts
index 03a0ef18..8792eea9 100644
--- a/src/core/internal/quantity.ts
+++ b/src/core/internal/quantity.ts
@@ -20,7 +20,7 @@ export class MissingFieldError extends Error {
*
* @internal
*/
-export function quantityToBigInt(
+export function toBigInt(
value: Hex.Hex | undefined | null,
): bigint | undefined {
if (value === undefined || value === null) return undefined
@@ -33,7 +33,7 @@ export function quantityToBigInt(
*
* @internal
*/
-export function quantityToBigIntRequired(
+export function toBigIntRequired(
value: Hex.Hex | undefined | null,
field: string,
container?: string | undefined,
@@ -51,7 +51,7 @@ export function quantityToBigIntRequired(
*
* @internal
*/
-export function quantityToNumber(
+export function toNumber(
value: Hex.Hex | undefined | null,
): number | undefined {
if (value === undefined || value === null) return undefined
@@ -63,7 +63,7 @@ export function quantityToNumber(
*
* @internal
*/
-export function bigIntToQuantity(
+export function fromBigInt(
value: bigint | undefined | null,
): Hex.Hex | undefined {
if (typeof value !== 'bigint') return undefined
@@ -75,7 +75,7 @@ export function bigIntToQuantity(
*
* @internal
*/
-export function numberToQuantity(
+export function fromNumber(
value: number | undefined | null,
): Hex.Hex | undefined {
if (typeof value !== 'number') return undefined
From 0077cbabb3345407846d575145b58c0263b9bd1d Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Wed, 13 May 2026 07:38:18 +1000
Subject: [PATCH 074/192] fix(ci): repair prerelease prepublish order and
silence false-positive type errors in tests
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
.github/workflows/prerelease.yml | 4 ++--
src/core/_test/AbiParameters.test.ts | 1 +
src/core/_test/TransactionEnvelopeEip4844.test.ts | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml
index 82db807c..cf198d23 100644
--- a/.github/workflows/prerelease.yml
+++ b/.github/workflows/prerelease.yml
@@ -16,6 +16,6 @@ jobs:
- name: Prepublish
run: |
- cd src && pnpm version prerelease --preid $(git rev-parse --short=7 HEAD) && cd ..
pnpm exec zile publish:prepare
- pnpx pkg-pr-new publish --pnpm --compact './src'
+ pnpm version prerelease --preid $(git rev-parse --short=7 HEAD) --no-git-tag-version --allow-same-version
+ pnpx pkg-pr-new publish --pnpm --compact
diff --git a/src/core/_test/AbiParameters.test.ts b/src/core/_test/AbiParameters.test.ts
index ff11d40c..0fca382a 100644
--- a/src/core/_test/AbiParameters.test.ts
+++ b/src/core/_test/AbiParameters.test.ts
@@ -255,6 +255,7 @@ describe('encodePacked', () => {
test('error: fixed-array length mismatch', () => {
expect(() =>
+ // @ts-expect-error
AbiParameters.encodePacked(['uint256[2]'], [[1n, 2n, 3n]]),
).toThrowErrorMatchingInlineSnapshot(
'[AbiParameters.ArrayLengthMismatchError: Array length mismatch for type `uint256[2]`. Expected: `2`. Given: `3`.]',
diff --git a/src/core/_test/TransactionEnvelopeEip4844.test.ts b/src/core/_test/TransactionEnvelopeEip4844.test.ts
index df30b7d7..e2ff2912 100644
--- a/src/core/_test/TransactionEnvelopeEip4844.test.ts
+++ b/src/core/_test/TransactionEnvelopeEip4844.test.ts
@@ -499,8 +499,8 @@ describe('serialize', () => {
test('no blobVersionedHashes', () => {
expect(() =>
+ // @ts-expect-error
TxEnvelopeEip4844.from({
- // @ts-expect-error
chainId: 1,
nonce: 0n,
}),
From 76b9145a5e04a445457b1b9abec0cdfd609e41fb Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Wed, 13 May 2026 07:45:48 +1000
Subject: [PATCH 075/192] ci(prerelease): match zile template (`pnpm run build`
+ `pkg-pr-new publish --pnpm`)
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
.github/workflows/prerelease.yml | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml
index cf198d23..0638709b 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: |
- pnpm exec zile publish:prepare
- pnpm version prerelease --preid $(git rev-parse --short=7 HEAD) --no-git-tag-version --allow-same-version
- pnpx pkg-pr-new publish --pnpm --compact
+ pnpm run build
+ pnpx pkg-pr-new publish --pnpm
From 94d3e4bc1b3109ef841a7b4ffbb462dbf02372da Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Wed, 13 May 2026 07:52:03 +1000
Subject: [PATCH 076/192] fix(tsdoc): mark internal helpers `packUint128Pair`
and `decodeCodesTail` with `@internal`
Amp-Thread-ID: https://ampcode.com/threads/T-019e19a3-5fc8-73aa-8b28-4d3406911c63
---
src/erc4337/UserOperation.ts | 2 ++
src/erc8021/Attribution.ts | 2 ++
2 files changed, 4 insertions(+)
diff --git a/src/erc4337/UserOperation.ts b/src/erc4337/UserOperation.ts
index 0ddebe12..98098283 100644
--- a/src/erc4337/UserOperation.ts
+++ b/src/erc4337/UserOperation.ts
@@ -51,6 +51,8 @@ const hashEnvelopeParameters = [
* Packs two `uint128` values into a single `bytes32` word, with `high` in the
* upper 16 bytes and `low` in the lower 16 bytes. Used for `accountGasLimits`
* and `gasFees` packing in v0.7+ user operations.
+ *
+ * @internal
*/
function packUint128Pair(high: bigint | number, low: bigint | number): Hex.Hex {
return Hex.concat(
diff --git a/src/erc8021/Attribution.ts b/src/erc8021/Attribution.ts
index 402f4033..53c33c1f 100644
--- a/src/erc8021/Attribution.ts
+++ b/src/erc8021/Attribution.ts
@@ -339,6 +339,8 @@ export function fromData(data: Hex.Hex): Attribution | undefined {
* Reads the trailing `codes ∥ codesLength (1)` segment from a schema-0/1
* payload, given the absolute end-offset of the codes-length byte (which is
* the start of the schema ID).
+ *
+ * @internal
*/
function decodeCodesTail(
data: Hex.Hex,
From fe923fdca9fe455a82a236c6f564361edacea059 Mon Sep 17 00:00:00 2001
From: jxom <7336481+jxom@users.noreply.github.com>
Date: Wed, 13 May 2026 12:34:46 +1000
Subject: [PATCH 077/192] feat: v1-1 (#233)
* ci(bench): add Track B bench harness
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-7b95d908f442
* refactor(internal): add tx quantity helpers
Adds shared scalar codec helpers used by every transaction envelope: `quantityToHex`, `hexToBigIntOrUndefined`, `hexToBigIntOrZero`, `hexToNumberOrUndefined`, and `hexToHexOrUndefined`. Replaces the per-envelope `x ? Hex.fromNumber(x) : '0x'` and `Hex.validate(x) && x !== '0x' ? BigInt(x) : ...` patterns with a single set of branch-free helpers and drops the redundant `Hex.validate` checks from RLP-decoded values.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-846ef733b3c0
* perf(transactions): use tx quantity helpers in envelopes
Routes each envelope (`TxEnvelopeEip1559`, `TxEnvelopeEip2930`, `TxEnvelopeEip4844`, `TxEnvelopeEip7702`, `TxEnvelopeLegacy`) through `internal/tx.ts`. On serialize this collapses the `field ? Hex.fromNumber(field) : '0x'` blocks; on deserialize it drops the redundant `Hex.validate` checks (RLP-decoded leaves are already valid hex) and folds the per-field `x !== '0x' ? BigInt(x) : ...` shape into single helper calls.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-846ef733b3c0
* feat(crypto): add `returnByteLength` and `returnDecoded` options to `CoseKey.toPublicKey`
Lets WebAuthn callers consume the COSE key, its byte length and the decoded CBOR map in a single decode pass. The byte length lets verifiers detect trailing bytes after the COSE key without re-encoding.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a0ea94701da4
* perf(internal/webauthn): direct SPKI parse for P-256 in `parseCredentialPublicKey`
Removes two `crypto.subtle.importKey` and `crypto.subtle.exportKey` calls from the WebAuthn registration path. The WebAuthn `getPublicKey()` returns a fixed 91 byte SPKI for ES256, where the trailing 65 bytes are the SEC1 uncompressed point. Validates the SPKI prefix and slices the raw key directly.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a0ea94701da4
* perf(rlp): single-pass encode and hex-leaf fast path
Replaces the parallel `Encodable` tree built by `getEncodable` with two specialized walks: `encodedLength` measures the RLP byte length, `writeEncoded` emits bytes straight into a pre-sized `Uint8Array`. Hex leaves are nibble-decoded directly into the destination buffer via `internal_bytes.charCodeToBase16`, skipping the per-leaf `Bytes.fromHex` allocation. Removes the per-node closure objects and the per-list `reduce` over child lengths. Same public API, same output, no behavior change.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-846ef733b3c0
* refactor(webauthn): shared `parseAuthenticatorData` and `serializeResponseFields` helpers
Adds internal helpers in `webauthn/internal/utils.ts` consumed by `Authentication`, `Authenticator`, `Credential` and `Registration` in follow-up commits.
`parseAuthenticatorData` decodes the fixed 37 byte header (rpIdHash, flags, signCount) into a typed shape so callers no longer re-bit-twiddle the same bytes.
`serializeResponseFields` consolidates the getter fallback path used when browsers/passkey providers expose `authenticatorData` and friends only via getter methods.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a0ea94701da4
* perf(transactions): decode envelopes via Rlp.toBytes
Switches every envelope deserializer (`TxEnvelopeEip1559`, `TxEnvelopeEip2930`, `TxEnvelopeEip4844`, `TxEnvelopeEip7702`, `TxEnvelopeLegacy`) from `Rlp.toHex` to `Rlp.toBytes`. The bytes form returns `Uint8Array` subarray views into the source, so the per-leaf `Hex.fromBytes` allocation that `Rlp.toHex` previously paid for every scalar (chainId, nonce, gas, value, fee fields) is now skipped. New `internal/tx.ts` helpers (`bytesToBigIntOrUndefined`, `bytesToBigIntOrZero`, `bytesToNumberOrUndefined`, `bytesToHexOrUndefined`, `bytesToHex`, `bytesTreeToHex`) consume the byte views directly. Scalars under 7 bytes (the common case for non-fee fields) accumulate via native `Number` arithmetic rather than round-tripping through hex; wider scalars still build a hex string but only once per field. Hex is rebuilt on demand for opaque `to` / `data` fields and the `AccessList` / `Authorization` sub-trees, which still flow through their hex-typed `fromTupleList` codecs.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-846ef733b3c0
* perf(webauthn): bytes-first `getAuthenticatorData` with `as` overload
Builds the authenticator bytes directly into a single `Uint8Array` instead of going via several intermediate hex strings and `Hex.concat`. Added an `as: 'Hex' | 'Bytes'` option so callers that already operate on bytes (verifier, payload builder) can skip the trailing `Hex.fromBytes`.
`getSignCount` now accepts `Hex.Hex | Uint8Array` and routes through the shared `parseAuthenticatorData` helper, removing the unconditional `Bytes.fromHex` on the verify hot path.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a0ea94701da4
* refactor(webauthn): consume shared helpers in `Authentication`
`Authentication.verify` now reads flag bits and `rpIdHash` from `parseAuthenticatorData`. `Authentication.serializeResponse` delegates the response field getter fallback to `serializeResponseFields`.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a0ea94701da4
* refactor(webauthn): use shared response-field serializer in `Credential.serialize`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a0ea94701da4
* refactor(webauthn): use shared response-field serializer in `Registration.serializeResponse`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a0ea94701da4
* perf(registration): single COSE decode in `Registration.verify`
Replaces the `bytes -> hex -> Cbor.decode -> CoseKey.toPublicKey -> CoseKey.fromPublicKey` chain in `Registration.verify` with a single `CoseKey.toPublicKey(coseKeyBytes, { returnByteLength: true })` call. The prior approach re-encoded the parsed public key just to compute its byte length, which mis-rejected valid COSE keys with optional members.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a0ea94701da4
* ci(bench): add Track B bench harness
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e63-676e-70ce-a669-c57b3a5eef27
* test(erc4337): add UserOperation.hash and toPacked benches
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-94cc8bc7197c
* perf(address): bounded checksum cache
Replaces the global `Caches.checksum` LRU map with a 32,768-entry FIFO `BoundedMap`. Reads no longer trigger an `delete` + `set` MRU shuffle, and bigger workloads (block builders, indexers) keep more entries hot.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-889e77d45c80
* test(erc6492): add SignatureErc6492 wrap and unwrap benches
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-94cc8bc7197c
* perf(address): manual ASCII validation and isEqual fast path
Replaces the regex / try-catch path in `Address.assert` and `Address.validate` with a single manual ASCII pass that classifies shape and lowercase status together. `Address.checksum` now does a direct `Map.get` lookup before any work and uses lowercase-normalized secondary keys so mixed-case spellings of the same address share an entry. `Address.isEqual` skips per-input regex `assert` calls in favor of a manual shape check plus an identity short-circuit.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-889e77d45c80
* refactor(log): use shared quantity helpers in fromRpc / toRpc
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-8ddf713c828b
* test(erc7821): add Calls encode and decode benches
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-94cc8bc7197c
* test(address): add microbenches for assert, validate, checksum, isEqual
Covers valid + invalid `Address.validate`, lowercase + checksummed strict `Address.assert`, cache-hit and cache-miss `Address.checksum`, and equal / different `Address.isEqual` shapes.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-889e77d45c80
* test(block-state): add fromRpc/toRpc benches for `AccountProof`, `Block`, `Log`
* test(erc8021): add Attribution.fromData benches
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-94cc8bc7197c
* perf(rpc-request): single-pass prepare and prepared-request fast path
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-9be53a108338
* perf(rpc-response): copy-on-write from and code-table parseError
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-9be53a108338
* perf(rpc-transport): direct fetchFn call and lazy timeout allocation
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-9be53a108338
* perf(provider): parseError code-to-constructor table
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-9be53a108338
* perf(bytes): fast-path `fromNumber` and `toBigInt` for fixed-width unsigned values
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-7dbb43759db9
* perf(hex): tighten `Hex.concat` and `Hex.slice` to skip per-arg `replace`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-7dbb43759db9
* perf(signature): rewrite `fromTuple` and `toTuple` to skip bigint round-trip
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-7dbb43759db9
* feat(signature): expose compact/recovered byte helpers
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-7dbb43759db9
* perf(bls): replace `Array.reduce` with tight loop in `aggregate`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-7dbb43759db9
* test(perf): add foundation benches for `Bytes`, `Hex`, `Signature`, `Bls`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-7dbb43759db9
* docs(bench): record `Bytes`, `Hex`, `Signature`, `Bls` foundations baselines
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e63-676e-70ce-a669-c57b3a5eef27
* perf(internal/cursor): forward-only fast path for `_touch`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a7f6c1886bcd
* perf(abi-event): primitive topic codecs and hoisted array-suffix regex
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a7f6c1886bcd
* perf(tempo): add `TempoAddress.unwrap` fast-path helper
Adds an internal helper that strips the `tempox` prefix and validates
the remaining hex without running EIP-55 checksum or allocating a
`{ address }` wrapper. Suitable for hot paths that only need
format-validated bytes (hashing, byte slicing, tuple encoding).
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-9ebb7dd6bce3
* perf(abi-item): use `find` for selector lookups in `fromAbi`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a7f6c1886bcd
* perf(virtual-address): resolve via `TempoAddress.unwrap`
Skips the EIP-55 checksum keccak when an input arrives with a
`tempox` prefix. Also re-documents the existing `toFixedHex` helper
to call out that it already routes bytes inputs through bytes-first
padding, satisfying the bytes-first normalization audit point without
the round-trip cost of forcing every caller through a buffer.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-9ebb7dd6bce3
* perf(internal/abi-item): hoist overload-resolution regexes and swap `for...in` for indexed loop
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a7f6c1886bcd
* perf(hash): bytes fast path
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-902e724b1983
* perf(virtual-master): direct fixed-layout registration digest
`getRegistrationHash` and `validateSalt` now build the
`address || salt` byte buffer directly and feed it to keccak256,
instead of round-tripping through `Hex.concat`. The `toFixedBytes`
helper now branches to bytes for numeric and bytes inputs without
going through hex first, and the master address is resolved with
`TempoAddress.unwrap` to skip the EIP-55 checksum work.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-9ebb7dd6bce3
* perf(internal/abi-parameters): hoist `getArrayComponents` array-suffix regex
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a7f6c1886bcd
* perf(aes-gcm): single-buffer write
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-902e724b1983
* perf(token-id): TIP-20 fast paths for `compute` and `fromAddress`
`TokenId.compute` now builds the 64-byte ABI `(address, bytes32)`
buffer directly and hashes it with keccak256, instead of going through
`AbiParameters.encode` plus `Hex.toBigInt`. `TokenId.fromAddress`
peeks the TIP-20 prefix bytes via `charCodeAt` to avoid a full
`.toLowerCase()` on already-lowercase inputs (the common case), and
both functions resolve the input through `TempoAddress.unwrap`.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-9ebb7dd6bce3
* test(abi): add Phase 1 perf benches for `AbiParameters`, `AbiFunction`, `AbiEvent`, `AbiItem`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-a7f6c1886bcd
* test(crypto): add Hash, AesGcm, Bls, WebCryptoP256, Mnemonic benches
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e63-676e-70ce-a669-c57b3a5eef27
* docs(bench): record Tempo Phase 1 perf-foundations results
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e63-676e-70ce-a669-c57b3a5eef27
* docs(bench): record Phase 1 ABI perf numbers
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e63-676e-70ce-a669-c57b3a5eef27
* chore(changeset): describe public-API impact
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e63-676e-70ce-a669-c57b3a5eef27
* chore(changeset): describe public-API impact
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e63-676e-70ce-a669-c57b3a5eef27
* test(webauthn): add Phase 1 perf benches for `Authentication`, `Authenticator`, `Registration`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-8228-756d-b140-0b187eb5187d
* docs(bench): record WebAuthn Phase 1 perf results
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-8228-756d-b140-0b187eb5187d
* perf(rlp): cache list body lengths during measure pass
Replaces the recursive recompute in writeEncoded with a precomputed
lengths cache populated by measure. Avoids the O(N depth) re-walk per
list node so deeply nested inputs encode in a single linear pass.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-bb12-7211-93f1-74662163e7a5
* test(bench): add transaction-shaped Rlp + EIP-1559 envelope benches
Adds bench coverage for the RLP encode/decode hot paths exercised by
every TxEnvelope codec, plus serialize / deserialize / hash benches for
the EIP-1559 envelope. The Rlp bench file is named `Rlp_tx.bench.ts`
to avoid collision with the parallel encoding-thread `Rlp.bench.ts`.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-bb12-7211-93f1-74662163e7a5
* ci(bench): record Track B transactions Phase 1 results
Records bench measurements for the transactions area at PR
`a57efdb8` against baseline `origin/v1` (`94d3e4bc`).
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-bb12-7211-93f1-74662163e7a5
* refactor(internal): extract codec core (`utf8`, `hex`, `int`, `bech32-base32`, `errors`)
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-819c13d0330a
* refactor(bytes,hex): break `Bytes` <-> `Hex` runtime cycle via codec core
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-819c13d0330a
* perf(internal/hex): use raw nibble arithmetic in `pad`/`assertSize`
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-819c13d0330a
* refactor(base32,bech32m): share `convertBits` and BIP-173 alphabet
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-819c13d0330a
* perf(cursor): defer `positionReadCount` map allocation
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e69-1284-7603-84ed-819c13d0330a
* perf(base64): native `Uint8Array` fast path and tight JS fallback
- Detects `Uint8Array.prototype.toBase64` / `Uint8Array.fromBase64` (Node 22+,
Safari 18+, Firefox 133+) and routes through the native codec when present.
- Replaces the `Record` lookup tables with `Uint8Array(256)`
tables sentinel-marked at `0xff`; the encode/decode hot loops now do a
direct integer index instead of a property hash.
- Drops the `encoder.encodeInto` round-trip in the JS decode fallback in
favour of a tight `charCodeAt` accumulator that writes directly into the
output buffer.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-ff62-73b8-a262-b462a657ae02
* perf(json): short-circuit `Json.parse` when bigint sentinel is absent
When the input string does not contain the `#__bigint` sentinel, skip the
bigint reviver wrapper entirely and call `JSON.parse(string)` (or pass the
user reviver directly). Engines parse much faster without a reviver
because they do not have to materialize each property to a JS value before
re-walking it, so this short-circuit is a clear win for the common case
of bigint-free payloads (RPC responses, ABI fixtures, etc.).
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-ff62-73b8-a262-b462a657ae02
* chore(format): apply biome `--unsafe` import sort and line-wrap fixes
Mechanical reformat carried out by `biome check . --fix --unsafe` after
the Phase 1 codec extraction. No behaviour changes.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-ff62-73b8-a262-b462a657ae02
* test(bench): add encoding-track bench suites
Adds first-pass `vitest bench` suites for `Bytes`, `Hex`, `Rlp`, `Cbor`,
`Base64`, and `Json` so the Phase 1 / Phase 2 perf wins on this track can
be measured against `origin/v1` and recorded under `bench/encoding.md` and
`bench/foundations.md`.
Each suite seeds fixtures of mixed sizes (small / medium / large) outside
of the bench callbacks and exercises the public hot-path entrypoints
identified by the encoding audit:
- `Bytes`: `fromHex` / `toHex` / `concat` / `fromString` / `toString` /
`fromNumber` / `padLeft`.
- `Hex`: `fromBytes` / `toBytes` / `concat` / `fromNumber` (incl.
safe-int fast path) / `toBigInt` / `padLeft` / `fromString` /
`validate({ strict: true })`.
- `Rlp`: encode / decode for single strings and flat / nested lists,
both `Hex` and `Bytes` codecs.
- `Cbor`: `encode` / `decode` for small / medium objects and a
256-byte buffer, both `Hex` and `Bytes` outputs.
- `Base64`: `fromBytes` / `toBytes` for 32 / 256 / 4096 byte payloads
and `pad: false` / `url: true` variants, plus
`fromString` / `toString` round trips.
- `Json`: `parse` (with and without the `#__bigint` sentinel),
`stringify`, and `canonicalize`.
No production code is touched.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-ff62-73b8-a262-b462a657ae02
* docs(bench): record encoding-track Phase 1 / 2 results
Captures `pnpm bench --run` numbers for `Bytes`, `Hex`, `Base64`, and
`Json` against `origin/v1` (`94d3e4bc`) and the track-b/encoding tip
(`c3d2eff6`), `core` project only, on macOS arm64 / Node 24.
Highlights:
- `Hex.toBytes` / `Bytes.fromHex` 4096 bytes: +2400% via the native
`Uint8Array.fromHex` fast path.
- `Hex.fromBytes` / `Bytes.toHex` 4096 bytes: +1900% via
`Uint8Array.prototype.toHex`.
- `Json.parse` medium 32-tx payload (no `#__bigint`): +556% via the
reviver short-circuit.
- `Base64.toBytes` URL-safe 32 bytes: +222% via the native
`Uint8Array.fromBase64` fast path; padded 32 bytes: +118%.
`Rlp` baseline measurement is still pending due to concurrent port
contention on `:8545` between Track B worktrees.
Amp-Thread-ID: https://ampcode.com/threads/T-019e1e9e-ff62-73b8-a262-b462a657ae02
* chore(changeset): describe public-API impact
Amp-Thread-ID: https://ampcode.com/threads/T-019e1ebc-12b1-7182-8425-043467b61064
* chore(changeset): describe transactions Phase 1 perf work
Amp-Thread-ID: https://ampcode.com/threads/T-019e1ebc-12b1-7182-8425-043467b61064
* chore(changeset): describe public-API impact
Amp-Thread-ID: https://ampcode.com/threads/T-019e1ebc-12b1-7182-8425-043467b61064
* perf(rlp): hex-output fast path for transaction-shaped encode
When every leaf in the input tree is already hex and the caller asked for
hex output, emit the RLP encoding directly as a hex string instead of
allocating an intermediate `Uint8Array` and round-tripping through
`Hex.fromBytes`. This is the dominant shape for transaction envelope
serialize.
Recovers the `TxEnvelopeEip1559.serialize` regression flagged in
`bench/regressions.md` (-41% -> +241% vs `origin/v1` on minimal envelope;
-11% -> +344% with access list).
* perf(hex): no-end fast path for `Hex.slice`
When `Hex.slice` is called without an `end` and with a non-negative
`start`, skip the `replace('0x', '')` + bounded `slice` chain and either
return the input unchanged (start 0) or do a single offset `slice` from
the post-`0x` data. The general path (negative offsets, explicit `end`)
still strips `0x` once and uses `String.prototype.slice`'s native
negative-offset semantics.
Recovers the `Hex.slice` no-end-positive-start regression
(-10%) flagged in `bench/regressions.md`.
* fix(cursor): preserve recursive-read accounting in forward-only fast path
`13466b52 perf(internal/cursor): forward-only fast path for _touch` set
`maxLinearPosition` to the start position of the read (not past it), so a
re-read of the same byte after `setPosition` was indistinguishable from
the first read and never charged to the recursive-read budget. The
`args: recursiveReadLimit > === 2` test in `cursor.test.ts` regressed.
Reframe the fast path: track `position + 1` as the frontier of observed
bytes. Reads that start at or past the frontier are forward and skip
bookkeeping; reads that start strictly before the frontier overlap
already-touched bytes and increment `recursiveReadCount`. This preserves
the per-read cost of the optimization (no `Map.get`/`Map.set`) while
making the recursive-read limit fire on cyclic inputs again.
* chore(gitignore): untrack `tasks/` and remove the `tasks/bench/` exception
`tasks/bench/README.md` was the only tracked file under `tasks/` and was
local working notes for the bench harness, not source the repo needs to
distribute. Drop it from the index and tighten `.gitignore` so the entire
`tasks/` directory stays local to each contributor.
* refactor(address/internal): match public-module convention
Drop the `Address` prefix from the internal helpers and switch the
caller to a wildcard import. Aligns `internal/address.ts` with the rest
of the `internal/*` modules (`internal/hex.ts`, `internal/bytes.ts`,
etc.), which export bare verbs (`assertSize`, `pad`) and are imported as
`internal`.
- `classifyAddress` -> `classify`
- `hasAddressShape` -> `hasShape`
- `lowercaseAddress` -> `lowercase`
- `addressLength` -> `length`
Address.ts now imports as `import * as internal from './internal/address.js'`
and call sites read `internal.classify(...)`, `internal.hasShape(...)`,
`internal.lowercase(...)`.
* chore(changeset): drop perf-only and refactor-only entries
Changesets should record observable changes to the public API (new APIs,
behavior changes, validation tightening, error/type-shape changes, doc
corrections that affect what callers can rely on). Pure perf wins and
internal refactors don't change what `ox` does, so they don't belong in
the user-facing changelog -- they're recorded in `bench/` and the commit
log instead.
Removes 43 entries covering:
- Perf fast paths and hot-loop rewrites across `Abi*`, `Address`,
`AesGcm`, `Base64`, `Bls`, `Bytes`, `Cursor`, `erc4337`, `erc6492`,
`erc7821`, `Hash`, `Hex`, `Json`, `PersonalMessage`, `Provider`,
`Registration`, `Rlp`, `RpcRequest`, `RpcResponse`, `RpcTransport`,
`Signature`, `tempo.*`, `TxEnvelope*`, `webauthn.*`.
- Internal refactors that share helpers without changing call signatures
(`Base32`/`Bech32m`, `erc8021.Attribution`, `webauthn.*` shared
serializers, `TransactionRequest.toRpc` dead-code removal).
- The `bench-harness.md` entry, which documented the dev-only
`pnpm bench` tooling rather than a public API addition.
Remaining 72 entries cover only behavior changes, new APIs, validation
tightening, error/type changes, and JSDoc corrections that fix
previously-misleading defaults.
---
.changeset/abi-event-decode-fast-partition.md | 5 -
.../cosekey-topublickey-bytes-options.md | 5 +
.../erc4337-user-operation-hash-perf.md | 5 -
.changeset/erc6492-cache-abi-parameters.md | 5 -
.changeset/erc7821-cache-abi-parameters.md | 5 -
...rc8021-attribution-fromdata-shared-tail.md | 5 -
.changeset/hex-tobytes-buffer-pool-fix.md | 5 +
.changeset/personal-message-prefix.md | 5 -
.changeset/signature-byte-helpers.md | 5 +
...ons-transaction-request-duplicate-field.md | 5 -
.../webauthn-authenticator-bytes-first.md | 5 +
.gitignore | 3 +-
bench/abi.md | 27 ++
bench/address-keys.md | 8 +
bench/block-state.md | 8 +
bench/crypto.md | 33 ++
bench/encoding.md | 36 ++
bench/erc.md | 8 +
bench/foundations.md | 23 +
bench/rpc.md | 8 +
bench/tempo.md | 25 ++
bench/transactions.md | 24 +
bench/webauthn.md | 26 ++
package.json | 1 +
src/core/AbiEvent.bench.ts | 29 ++
src/core/AbiEvent.ts | 114 ++++-
src/core/AbiFunction.bench.ts | 54 +++
src/core/AbiItem.bench.ts | 40 ++
src/core/AbiItem.ts | 25 +-
src/core/AbiParameters.bench.ts | 82 ++++
src/core/AccountProof.bench.ts | 66 +++
src/core/Address.bench.ts | 92 ++++
src/core/Address.ts | 94 ++--
src/core/AesGcm.bench.ts | 25 ++
src/core/AesGcm.ts | 6 +-
src/core/Base32.ts | 55 +--
src/core/Base64.bench.ts | 70 +++
src/core/Base64.ts | 155 +++++--
src/core/Bech32m.ts | 61 +--
src/core/Block.bench.ts | 115 +++++
src/core/BlockOverrides.ts | 12 +-
src/core/Bls.bench.ts | 32 ++
src/core/Bls.ts | 19 +-
src/core/Bls_crypto.bench.ts | 23 +
src/core/Bytes.bench.ts | 121 ++++++
src/core/Bytes.ts | 111 +++--
src/core/Caches.ts | 4 +-
src/core/Cbor.bench.ts | 58 +++
src/core/CoseKey.ts | 126 +++++-
src/core/Hash.bench.ts | 31 ++
src/core/Hash.ts | 22 +-
src/core/Hex.bench.ts | 121 ++++++
src/core/Hex.ts | 203 ++++-----
src/core/Json.bench.ts | 65 +++
src/core/Json.ts | 7 +
src/core/Log.bench.ts | 53 +++
src/core/Log.ts | 24 +-
src/core/Mnemonic.bench.ts | 16 +
src/core/Provider.bench.ts | 31 ++
src/core/Provider.ts | 52 +--
src/core/Rlp.bench.ts | 73 ++++
src/core/Rlp.ts | 410 ++++++++++++++----
src/core/Rlp_tx.bench.ts | 97 +++++
src/core/RpcRequest.bench.ts | 41 ++
src/core/RpcRequest.ts | 5 +-
src/core/RpcResponse.bench.ts | 65 +++
src/core/RpcResponse.ts | 63 +--
src/core/RpcTransport.bench.ts | 42 ++
src/core/RpcTransport.ts | 3 +-
src/core/Signature.bench.ts | 56 +++
src/core/Signature.ts | 138 +++++-
src/core/StateOverrides.ts | 12 +-
src/core/TxEnvelopeEip1559.bench.ts | 75 ++++
src/core/TxEnvelopeEip1559.ts | 57 ++-
src/core/TxEnvelopeEip2930.ts | 49 ++-
src/core/TxEnvelopeEip4844.ts | 99 +++--
src/core/TxEnvelopeEip7702.ts | 63 ++-
src/core/TxEnvelopeLegacy.ts | 44 +-
src/core/WebCryptoP256.bench.ts | 38 ++
src/core/_test/Bytes.test.ts | 6 +-
src/core/_test/Hex.test.ts | 6 +-
src/core/_test/Signature.test.ts | 4 +
src/core/internal/abiItem.ts | 90 ++--
src/core/internal/abiParameters.ts | 11 +-
src/core/internal/address.ts | 79 ++++
src/core/internal/codec/bech32-base32.ts | 64 +++
src/core/internal/codec/errors.ts | 30 ++
src/core/internal/codec/hex.ts | 145 +++++++
src/core/internal/codec/int.ts | 186 ++++++++
src/core/internal/codec/utf8.ts | 11 +
src/core/internal/cursor.ts | 38 +-
src/core/internal/hex.ts | 36 +-
src/core/internal/lru.ts | 24 +
src/core/internal/promise.ts | 20 +-
src/core/internal/rpcTransport.ts | 15 +-
src/core/internal/signature.ts | 53 +--
src/core/internal/tx.ts | 185 ++++++++
src/core/internal/webauthn.ts | 46 +-
src/erc4337/UserOperation.bench.ts | 87 ++++
src/erc6492/SignatureErc6492.bench.ts | 21 +
src/erc7821/Calls.bench.ts | 36 ++
src/erc8021/Attribution.bench.ts | 25 ++
src/tempo/TempoAddress.bench.ts | 34 ++
src/tempo/TempoAddress.ts | 19 +
src/tempo/TokenId.bench.ts | 47 ++
src/tempo/TokenId.ts | 43 +-
src/tempo/VirtualAddress.bench.ts | 49 +++
src/tempo/VirtualAddress.ts | 9 +-
src/tempo/VirtualMaster.bench.ts | 51 +++
src/tempo/VirtualMaster.ts | 52 ++-
src/webauthn/Authentication.bench.ts | 93 ++++
src/webauthn/Authentication.ts | 43 +-
src/webauthn/Authenticator.bench.ts | 63 +++
src/webauthn/Authenticator.ts | 78 +++-
src/webauthn/Credential.ts | 20 +-
src/webauthn/Registration.bench.ts | 108 +++++
src/webauthn/Registration.ts | 63 ++-
src/webauthn/internal/utils.ts | 86 ++++
118 files changed, 5047 insertions(+), 958 deletions(-)
delete mode 100644 .changeset/abi-event-decode-fast-partition.md
create mode 100644 .changeset/cosekey-topublickey-bytes-options.md
delete mode 100644 .changeset/erc4337-user-operation-hash-perf.md
delete mode 100644 .changeset/erc6492-cache-abi-parameters.md
delete mode 100644 .changeset/erc7821-cache-abi-parameters.md
delete mode 100644 .changeset/erc8021-attribution-fromdata-shared-tail.md
create mode 100644 .changeset/hex-tobytes-buffer-pool-fix.md
delete mode 100644 .changeset/personal-message-prefix.md
create mode 100644 .changeset/signature-byte-helpers.md
delete mode 100644 .changeset/transactions-transaction-request-duplicate-field.md
create mode 100644 .changeset/webauthn-authenticator-bytes-first.md
create mode 100644 bench/abi.md
create mode 100644 bench/address-keys.md
create mode 100644 bench/block-state.md
create mode 100644 bench/crypto.md
create mode 100644 bench/encoding.md
create mode 100644 bench/erc.md
create mode 100644 bench/foundations.md
create mode 100644 bench/rpc.md
create mode 100644 bench/tempo.md
create mode 100644 bench/transactions.md
create mode 100644 bench/webauthn.md
create mode 100644 src/core/AbiEvent.bench.ts
create mode 100644 src/core/AbiFunction.bench.ts
create mode 100644 src/core/AbiItem.bench.ts
create mode 100644 src/core/AbiParameters.bench.ts
create mode 100644 src/core/AccountProof.bench.ts
create mode 100644 src/core/Address.bench.ts
create mode 100644 src/core/AesGcm.bench.ts
create mode 100644 src/core/Base64.bench.ts
create mode 100644 src/core/Block.bench.ts
create mode 100644 src/core/Bls.bench.ts
create mode 100644 src/core/Bls_crypto.bench.ts
create mode 100644 src/core/Bytes.bench.ts
create mode 100644 src/core/Cbor.bench.ts
create mode 100644 src/core/Hash.bench.ts
create mode 100644 src/core/Hex.bench.ts
create mode 100644 src/core/Json.bench.ts
create mode 100644 src/core/Log.bench.ts
create mode 100644 src/core/Mnemonic.bench.ts
create mode 100644 src/core/Provider.bench.ts
create mode 100644 src/core/Rlp.bench.ts
create mode 100644 src/core/Rlp_tx.bench.ts
create mode 100644 src/core/RpcRequest.bench.ts
create mode 100644 src/core/RpcResponse.bench.ts
create mode 100644 src/core/RpcTransport.bench.ts
create mode 100644 src/core/Signature.bench.ts
create mode 100644 src/core/TxEnvelopeEip1559.bench.ts
create mode 100644 src/core/WebCryptoP256.bench.ts
create mode 100644 src/core/internal/address.ts
create mode 100644 src/core/internal/codec/bech32-base32.ts
create mode 100644 src/core/internal/codec/errors.ts
create mode 100644 src/core/internal/codec/hex.ts
create mode 100644 src/core/internal/codec/int.ts
create mode 100644 src/core/internal/codec/utf8.ts
create mode 100644 src/core/internal/tx.ts
create mode 100644 src/erc4337/UserOperation.bench.ts
create mode 100644 src/erc6492/SignatureErc6492.bench.ts
create mode 100644 src/erc7821/Calls.bench.ts
create mode 100644 src/erc8021/Attribution.bench.ts
create mode 100644 src/tempo/TempoAddress.bench.ts
create mode 100644 src/tempo/TokenId.bench.ts
create mode 100644 src/tempo/VirtualAddress.bench.ts
create mode 100644 src/tempo/VirtualMaster.bench.ts
create mode 100644 src/webauthn/Authentication.bench.ts
create mode 100644 src/webauthn/Authenticator.bench.ts
create mode 100644 src/webauthn/Registration.bench.ts
diff --git a/.changeset/abi-event-decode-fast-partition.md b/.changeset/abi-event-decode-fast-partition.md
deleted file mode 100644
index 2819a79c..00000000
--- a/.changeset/abi-event-decode-fast-partition.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"ox": patch
----
-
-Fixed `AbiEvent.decode` to partition `indexed` and non-`indexed` inputs in a single pass and to look up each non-indexed input's original position via a precomputed index map instead of `inputs.indexOf(...)`.
diff --git a/.changeset/cosekey-topublickey-bytes-options.md b/.changeset/cosekey-topublickey-bytes-options.md
new file mode 100644
index 00000000..1436705b
--- /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/erc4337-user-operation-hash-perf.md b/.changeset/erc4337-user-operation-hash-perf.md
deleted file mode 100644
index 46c79a7d..00000000
--- a/.changeset/erc4337-user-operation-hash-perf.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'ox': patch
----
-
-Hoisted `UserOperation.hash` ABI parameter descriptors to module scope, added a shared `packUint128Pair` helper for v0.7+ gas-limit packing, and reused a precomputed empty-bytes keccak for empty `initCode`/`paymasterAndData`.
diff --git a/.changeset/erc6492-cache-abi-parameters.md b/.changeset/erc6492-cache-abi-parameters.md
deleted file mode 100644
index 9797f63c..00000000
--- a/.changeset/erc6492-cache-abi-parameters.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'ox': patch
----
-
-Cached the `address, bytes, bytes` ABI parameter list at module scope in `SignatureErc6492` so `wrap` and `unwrap` no longer reparse on every call.
diff --git a/.changeset/erc7821-cache-abi-parameters.md b/.changeset/erc7821-cache-abi-parameters.md
deleted file mode 100644
index 8e1fe33b..00000000
--- a/.changeset/erc7821-cache-abi-parameters.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'ox': patch
----
-
-Cached the `Calls` ABI parameter lists (with and without `opData`) and the `bytes[]` parameter used by `Execute.encodeBatchOfBatchesData`/`decodeBatchOfBatchesData` at module scope to avoid reparsing on every encode/decode.
diff --git a/.changeset/erc8021-attribution-fromdata-shared-tail.md b/.changeset/erc8021-attribution-fromdata-shared-tail.md
deleted file mode 100644
index b6f46871..00000000
--- a/.changeset/erc8021-attribution-fromdata-shared-tail.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'ox': patch
----
-
-Refactored `Attribution.fromData` to share the schema-0/1 `codes ∥ codesLength` tail-decode through a single helper, removing duplicated boundary arithmetic between schema branches.
diff --git a/.changeset/hex-tobytes-buffer-pool-fix.md b/.changeset/hex-tobytes-buffer-pool-fix.md
new file mode 100644
index 00000000..36135b8c
--- /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/personal-message-prefix.md b/.changeset/personal-message-prefix.md
deleted file mode 100644
index 908602a2..00000000
--- a/.changeset/personal-message-prefix.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"ox": patch
----
-
-Hoisted the invariant `0x19 ‖ "Ethereum Signed Message:\n"` ERC-191 prefix in `PersonalMessage.encode` to a precomputed module constant so each call only encodes the per-message length suffix instead of re-encoding the full prefix string.
diff --git a/.changeset/signature-byte-helpers.md b/.changeset/signature-byte-helpers.md
new file mode 100644
index 00000000..ee81975c
--- /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/transactions-transaction-request-duplicate-field.md b/.changeset/transactions-transaction-request-duplicate-field.md
deleted file mode 100644
index 9e97ed46..00000000
--- a/.changeset/transactions-transaction-request-duplicate-field.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"ox": patch
----
-
-Removed duplicate `maxPriorityFeePerGas` assignment in `TransactionRequest.toRpc`.
diff --git a/.changeset/webauthn-authenticator-bytes-first.md b/.changeset/webauthn-authenticator-bytes-first.md
new file mode 100644
index 00000000..796606c5
--- /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/.gitignore b/.gitignore
index 1468886a..8d373e1f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*.map
+.bench
.DS_Store
.attest
.env
@@ -7,7 +8,7 @@
dist
coverage
node_modules
-tasks
+tasks/
tsconfig.*.tsbuildinfo
tsconfig.tsbuildinfo
tsdoc.d.tson
diff --git a/bench/abi.md b/bench/abi.md
new file mode 100644
index 00000000..6de0d721
--- /dev/null
+++ b/bench/abi.md
@@ -0,0 +1,27 @@
+# Bench results: abi
+
+_Abi, AbiConstructor, AbiError, AbiEvent, AbiFunction, AbiItem, AbiParameters._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+Phase 1 perf foundations. Baseline: `94d3e4bc`. PR: `5fe9d65a`.
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
+| `AbiParameters.bench.ts::AbiParameters.encode::(uint256[1000])` | 2,798 ops/s | 2,919 ops/s | +4.3% | `5fe9d65a` |
+| `AbiParameters.bench.ts::AbiParameters.encode::(address[100])` | 40,192 ops/s | 43,998 ops/s | +9.5% | `5fe9d65a` |
+| `AbiParameters.bench.ts::AbiParameters.encode::(string) 1KB` | 95,978 ops/s | 95,482 ops/s | -0.5% | `5fe9d65a` |
+| `AbiParameters.bench.ts::AbiParameters.encode::nested (tuple, tuple, tuple)` | 390,371 ops/s | 395,981 ops/s | +1.4% | `5fe9d65a` |
+| `AbiParameters.bench.ts::AbiParameters.decode::(uint256[1000])` | 1,189 ops/s | 1,230 ops/s | +3.4% | `5fe9d65a` |
+| `AbiParameters.bench.ts::AbiParameters.decode::(address[100])` | 15,041 ops/s | 15,955 ops/s | +6.1% | `5fe9d65a` |
+| `AbiParameters.bench.ts::AbiParameters.decode::(string) 1KB` | 61,870 ops/s | 62,012 ops/s | +0.2% | `5fe9d65a` |
+| `AbiParameters.bench.ts::AbiParameters.decode::nested (tuple, tuple, tuple)` | 145,740 ops/s | 150,436 ops/s | +3.2% | `5fe9d65a` |
+| `AbiFunction.bench.ts::AbiFunction.encodeData::erc20.transfer` | 1,378,487 ops/s | 1,418,232 ops/s | +2.9% | `5fe9d65a` |
+| `AbiFunction.bench.ts::AbiFunction.encodeData::erc20.transferFrom` | 1,107,972 ops/s | 1,112,394 ops/s | +0.4% | `5fe9d65a` |
+| `AbiFunction.bench.ts::AbiFunction.decodeData::erc20.transfer` | 538,874 ops/s | 561,790 ops/s | +4.3% | `5fe9d65a` |
+| `AbiFunction.bench.ts::AbiFunction.decodeData::erc20.transferFrom` | 305,198 ops/s | 399,397 ops/s | +30.9% | `5fe9d65a` |
+| `AbiItem.bench.ts::AbiItem.fromAbi (selector)::200-item ABI: last function` | 1,174 ops/s | 1,308 ops/s | +11.4% | `5fe9d65a` |
+| `AbiItem.bench.ts::AbiItem.fromAbi (selector)::200-item ABI: first function` | 1,198 ops/s | 120,160 ops/s | +9930% (~100x) | `5fe9d65a` |
+| `AbiItem.bench.ts::AbiItem.fromAbi (name)::200-item ABI: last function by name` | 107,822 ops/s | 109,894 ops/s | +1.9% | `5fe9d65a` |
+| `AbiEvent.bench.ts::AbiEvent.encode::Transfer` | 1,422,697 ops/s | 2,831,470 ops/s | +99.0% (~2.0x) | `5fe9d65a` |
+| `AbiEvent.bench.ts::AbiEvent.decode::Transfer` | 325,986 ops/s | 843,813 ops/s | +158.8% (~2.6x) | `5fe9d65a` |
diff --git a/bench/address-keys.md b/bench/address-keys.md
new file mode 100644
index 00000000..7d416eb5
--- /dev/null
+++ b/bench/address-keys.md
@@ -0,0 +1,8 @@
+# Bench results: address-keys
+
+_Address, HdKey, Mnemonic, Keystore, Ens, ContractAddress._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
diff --git a/bench/block-state.md b/bench/block-state.md
new file mode 100644
index 00000000..0ec5caf3
--- /dev/null
+++ b/bench/block-state.md
@@ -0,0 +1,8 @@
+# Bench results: block-state
+
+_Block, Log, Filter, Bloom, Fee, BinaryStateTree, AccountProof, BlockOverrides, StateOverrides._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
diff --git a/bench/crypto.md b/bench/crypto.md
new file mode 100644
index 00000000..c11370a4
--- /dev/null
+++ b/bench/crypto.md
@@ -0,0 +1,33 @@
+# Bench results: crypto
+
+_Secp256k1, P256, Ed25519, X25519, Bls, Hash, AesGcm._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+Baseline SHA `94d3e4bc`. Bench host: macOS arm64, Node 24.15. Benches run via vitest 4 with the project bench config; each row is the median of three runs. AesGcm and BLS aggregate rows have wide rme so numbers are reported to two significant figures.
+
+`Hash.*` rows reflect the bytes fast path in `e3000513`; `AesGcm.encrypt` rows reflect the single-buffer write in `35d33678`. The `Bls.aggregate(1 point)` row exists to lock in the existing single-element fast path against regression. The `WebCryptoP256.verify` and `Mnemonic.toSeed` rows are informational baselines for the prepared-key and async-seed work in Phase 3 / Phase 2.
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
+| `Hash.bench.ts::Hash.sha256 (32 bytes input)::Bytes.Bytes input` | 1,668,000 ops/s | 1,742,000 ops/s | +4.4% | `e3000513` |
+| `Hash.bench.ts::Hash.sha256 (256 bytes input)::Bytes.Bytes input` | 656,800 ops/s | 701,800 ops/s | +6.9% | `e3000513` |
+| `Hash.bench.ts::Hash.sha256 (4096 bytes input)::Bytes.Bytes input` | 69,900 ops/s | 68,300 ops/s | within noise | `e3000513` |
+| `Hash.bench.ts::Hash.keccak256 (32 bytes input)::Bytes.Bytes input` | 372,700 ops/s | 352,200 ops/s | within noise | `e3000513` |
+| `Hash.bench.ts::Hash.keccak256 (256 bytes input)::Bytes.Bytes input` | 186,600 ops/s | 189,000 ops/s | +1.3% | `e3000513` |
+| `AesGcm.bench.ts::AesGcm.encrypt (32 bytes)::encrypt` | 63,500 ops/s | 49,500 ops/s | within noise | `35d33678` |
+| `AesGcm.bench.ts::AesGcm.encrypt (1024 bytes)::encrypt` | 68,000 ops/s | 47,300 ops/s | within noise | `35d33678` |
+| `AesGcm.bench.ts::AesGcm.encrypt (65536 bytes)::encrypt` | 31,800 ops/s | 20,200 ops/s | within noise | `35d33678` |
+| `Bls_crypto.bench.ts::Bls.aggregate (1 points)::aggregate` | 30,800,000 ops/s | 30,800,000 ops/s | n/a (fast path already in v1) | `14af5bc5` |
+| `Bls_crypto.bench.ts::Bls.aggregate (10 points)::aggregate` | 12,100 ops/s | 12,100 ops/s | n/a | `14af5bc5` |
+| `Bls_crypto.bench.ts::Bls.aggregate (100 points)::aggregate` | 1,440 ops/s | 1,440 ops/s | n/a | `14af5bc5` |
+| `Bls_crypto.bench.ts::Bls.aggregate (1000 points)::aggregate` | 246 ops/s | 246 ops/s | n/a | `14af5bc5` |
+| `WebCryptoP256.bench.ts::WebCryptoP256.verify::verify (importKey per call)` | 11,140 ops/s | 11,140 ops/s | n/a (Phase 3 candidate) | n/a |
+| `WebCryptoP256.bench.ts::WebCryptoP256.verify::verify (prepared key reused)` | 14,350 ops/s | 14,350 ops/s | 1.29x faster than per-call import | n/a |
+| `Mnemonic.bench.ts::Mnemonic.toSeed::toSeed (sync, PBKDF2-HMAC-SHA512 x 2048)` | 181 ops/s | 181 ops/s | n/a (Phase 2 candidate) | n/a |
+| `Mnemonic.bench.ts::Mnemonic.toPrivateKey::toPrivateKey (default path)` | 119 ops/s | 119 ops/s | n/a | n/a |
+
+Notes:
+
+- `AesGcm.encrypt` rows are reported as "within noise" because the bench host had a competing vitest e2e session pinned to the same cores during measurement; `rme` was ±5% to ±25% on individual runs, which masks the single-allocation win expected from the change. Re-bench on a quiet host to confirm.
+- The `Bls.aggregate(1 point)` row is ~25,000x faster than the 10-point row, which is the visible signature of the single-element fast path. The fast path itself was added upstream in `14af5bc5`; the row is here to catch regressions.
diff --git a/bench/encoding.md b/bench/encoding.md
new file mode 100644
index 00000000..ee039ff0
--- /dev/null
+++ b/bench/encoding.md
@@ -0,0 +1,36 @@
+# Bench results: encoding
+
+_Cbor, Json, CompactSize, Base32 / Base58 / Base64, Bech32m._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+Numbers below come from `pnpm bench --run` on the indicated suite, `core`
+project only, on macOS arm64 / Node 24. Baseline = `origin/v1`
+(`94d3e4bc`). PR = `c3d2eff6` (track-b/encoding tip).
+
+## Base64
+
+| bench | baseline ops/s | PR ops/s | delta | SHA |
+| ------------------------------------ | -------------- | ---------- | ----------- | -------- |
+| `Base64.fromBytes` 32 bytes (padded) | 3,196,863 | 4,224,045 | +32% | c3d2eff6 |
+| `Base64.fromBytes` 256 bytes | 1,571,379 | 2,117,780 | +35% | c3d2eff6 |
+| `Base64.fromBytes` 4096 bytes | 185,611 | 242,788 | +31% | c3d2eff6 |
+| `Base64.fromBytes` 32 bytes (url) | 2,920,138 | 3,365,584 | +15% | c3d2eff6 |
+| `Base64.toBytes` 32 bytes (padded) | 3,293,632 | 7,172,709 | +118% | c3d2eff6 |
+| `Base64.toBytes` 256 bytes | 842,228 | 1,078,274 | +28% | c3d2eff6 |
+| `Base64.toBytes` 4096 bytes | 62,870 | 75,990 | +21% | c3d2eff6 |
+| `Base64.toBytes` 32 bytes (no pad) | 3,448,068 | 6,232,964 | +81% | c3d2eff6 |
+| `Base64.toBytes` 32 bytes (url) | 3,068,493 | 9,895,648 | +222% | c3d2eff6 |
+| `Base64.toString` hello | 3,622,405 | 7,388,637 | +104% | c3d2eff6 |
+| `Base64.toString` lorem (768 chars) | 368,166 | 622,463 | +69% | c3d2eff6 |
+
+## Json
+
+| bench | baseline ops/s | PR ops/s | delta | SHA |
+| ------------------------------------ | -------------- | ---------- | ----------- | -------- |
+| `Json.parse` small (no bigint) | 1,127,912 | 5,591,907 | +396% | c3d2eff6 |
+| `Json.parse` medium 32 txs (no bigint) | 24,066 | 157,841 | +556% | c3d2eff6 |
+| `Json.parse` small with bigint | 382,934 | 389,578 | flat | c3d2eff6 |
+| `Json.stringify` small | 3,922,494 | 3,910,835 | flat | c3d2eff6 |
+| `Json.stringify` medium 32 txs | 136,042 | 126,995 | -7% | c3d2eff6 |
+| `Json.canonicalize` small | 2,770,818 | 2,702,280 | flat | c3d2eff6 |
diff --git a/bench/erc.md b/bench/erc.md
new file mode 100644
index 00000000..25b5abc4
--- /dev/null
+++ b/bench/erc.md
@@ -0,0 +1,8 @@
+# Bench results: erc
+
+_erc4337, erc6492, erc7821, erc8010, erc8021._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
diff --git a/bench/foundations.md b/bench/foundations.md
new file mode 100644
index 00000000..fcb34db8
--- /dev/null
+++ b/bench/foundations.md
@@ -0,0 +1,23 @@
+# Bench results: foundations
+
+_Bytes, Hex, Hash, Rlp leaf primitives._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+Baseline: `94d3e4bc` (`origin/v1`). PR: `track-b/foundations`. Numbers in ops/sec from `pnpm vitest bench --project core` on the same machine. Delta is `(PR / baseline) - 1`.
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
+| `Bytes.bench.ts::Bytes.fromNumber({ size: 32 })::bigint, max` | 1,225,360 | 1,225,997 | +0.05% | 82be3ad5 |
+| `Bytes.bench.ts::Bytes.fromNumber({ size: 32 })::bigint, small` | 1,171,817 | 10,207,393 | +771% | 82be3ad5 |
+| `Bytes.bench.ts::Bytes.fromNumber({ size: 32 })::number` | 1,130,334 | 10,197,954 | +802% | 82be3ad5 |
+| `Bytes.bench.ts::Bytes.fromNumber({ size: 32 })::bigint, max u32` | 1,128,445 | 7,246,790 | +542% | 82be3ad5 |
+| `Bytes.bench.ts::Bytes.toBigInt::32 bytes` | 3,291,487 | 9,988,153 | +203% | 82be3ad5 |
+| `Bytes.bench.ts::Bytes.toBigInt::32 bytes (zero)` | 3,808,801 | 14,470,733 | +280% | 82be3ad5 |
+| `Bytes.bench.ts::Bytes.toBigInt::32 bytes, size: 32` | 2,487,890 | 8,667,941 | +248% | 82be3ad5 |
+| `Hex.bench.ts::Hex.concat::2 args` | 15,956,622 | 35,163,183 | +120% | 82be3ad5 |
+| `Hex.bench.ts::Hex.concat::3 args` | 12,542,139 | 25,015,271 | +99% | 82be3ad5 |
+| `Hex.bench.ts::Hex.concat::8 args` | 4,643,717 | 13,828,740 | +198% | 82be3ad5 |
+| `Hex.bench.ts::Hex.slice::positive start, no end` | 16,990,555 | 15,273,499 | -10% | 82be3ad5 |
+| `Hex.bench.ts::Hex.slice::positive start + end` | 24,106,798 | 30,023,615 | +25% | 82be3ad5 |
+| `Hex.bench.ts::Hex.slice::negative start` | 23,095,156 | 32,018,333 | +39% | 82be3ad5 |
diff --git a/bench/rpc.md b/bench/rpc.md
new file mode 100644
index 00000000..0f4e83fe
--- /dev/null
+++ b/bench/rpc.md
@@ -0,0 +1,8 @@
+# Bench results: rpc
+
+_Provider, Rpc*, Caches, Errors._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
diff --git a/bench/tempo.md b/bench/tempo.md
new file mode 100644
index 00000000..3a3a9b5a
--- /dev/null
+++ b/bench/tempo.md
@@ -0,0 +1,25 @@
+# Bench results: tempo
+
+_All `src/tempo/*` modules._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+Baseline SHA: `94d3e4bc` (origin/v1). All numbers in ops/s, taken from
+`pnpm bench --run --project tempo-unit src/tempo` on darwin/arm64
+(Node 24.15.0). Re-runs of noisy benches were averaged.
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
+| `TempoAddress.bench.ts::TempoAddress.resolve::hex passthrough` | 43,538,336 | 43,220,915 | -0.7% | `75d6cd5a` |
+| `TempoAddress.bench.ts::TempoAddress.resolve::tempo prefix` | 3,687,568 | 3,693,680 | +0.2% | `75d6cd5a` |
+| `TempoAddress.bench.ts::TempoAddress.unwrap::hex passthrough` | n/a (new) | 43,972,087 | new | `75d6cd5a` |
+| `TempoAddress.bench.ts::TempoAddress.unwrap::tempo prefix` | n/a (new) | 12,178,808 | new (3.30x vs `resolve`) | `75d6cd5a` |
+| `VirtualAddress.bench.ts::VirtualAddress.parse::hex address` | 4,449,465 | 4,228,085 | -5.0% | `75d6cd5a` |
+| `VirtualAddress.bench.ts::VirtualAddress.parse::tempo address` | 1,997,542 | 3,193,111 | +59.9% | `75d6cd5a` |
+| `VirtualMaster.bench.ts::VirtualMaster.getRegistrationHash::hex address, hex salt` | 241,464 | 243,487 | +0.8% | `75d6cd5a` |
+| `VirtualMaster.bench.ts::VirtualMaster.getRegistrationHash::hex address, bytes salt` | 235,987 | 284,045 | +20.4% | `75d6cd5a` |
+| `VirtualMaster.bench.ts::VirtualMaster.getRegistrationHash::tempo address, hex salt` | 229,003 | 234,485 | +2.4% | `75d6cd5a` |
+| `TokenId.bench.ts::TokenId.compute::hex sender` | 197,876 | 270,508 | +36.7% | `75d6cd5a` |
+| `TokenId.bench.ts::TokenId.compute::tempo sender` | 187,991 | 260,789 | +38.7% | `75d6cd5a` |
+| `TokenId.bench.ts::TokenId.fromAddress::hex address` | 7,323,405 | 12,687,434 | +73.2% | `75d6cd5a` |
+| `TokenId.bench.ts::TokenId.fromAddress::tempo address` | 2,374,826 | 7,023,025 | +195.7% | `75d6cd5a` |
diff --git a/bench/transactions.md b/bench/transactions.md
new file mode 100644
index 00000000..511f7658
--- /dev/null
+++ b/bench/transactions.md
@@ -0,0 +1,24 @@
+# Bench results: transactions
+
+_TxEnvelope*, AccessList, Authorization, Withdrawal, Blobs._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+Baseline: `94d3e4bc` (origin/v1).
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
+| `Rlp_tx.bench.ts::Rlp.fromHex (transaction-shaped)::eip1559 tuple` | 360,488 ops/s | 441,626 ops/s | +22.5% | a57efdb8 |
+| `Rlp_tx.bench.ts::Rlp.fromHex (transaction-shaped)::eip7702 tuple (with access + authorization lists)` | 150,945 ops/s | 175,186 ops/s | +16.1% | a57efdb8 |
+| `Rlp_tx.bench.ts::Rlp.toHex (transaction-shaped)::eip1559 tuple` | 323,896 ops/s | 325,369 ops/s | +0.5% | a57efdb8 |
+| `Rlp_tx.bench.ts::Rlp.toHex (transaction-shaped)::eip7702 tuple (with access + authorization lists)` | 139,158 ops/s | 140,680 ops/s | +1.1% | a57efdb8 |
+| `Rlp_tx.bench.ts::Rlp.toBytes (transaction-shaped)::eip1559 tuple` | 423,112 ops/s | 302,199 ops/s | -28.6% | a57efdb8 |
+| `Rlp_tx.bench.ts::Rlp.toBytes (transaction-shaped)::eip7702 tuple (with access + authorization lists)` | 173,571 ops/s | 165,334 ops/s | -4.7% | a57efdb8 |
+| `TxEnvelopeEip1559.bench.ts::TxEnvelopeEip1559.serialize::minimal (no access list)` | 475,391 ops/s | 282,563 ops/s | -40.6% | a57efdb8 |
+| `TxEnvelopeEip1559.bench.ts::TxEnvelopeEip1559.serialize::with access list (2 entries, 4 storage keys)` | 153,759 ops/s | 136,665 ops/s | -11.1% | a57efdb8 |
+| `TxEnvelopeEip1559.bench.ts::TxEnvelopeEip1559.deserialize::minimal (no access list)` | 456,898 ops/s | 258,835 ops/s | -43.4% | a57efdb8 |
+| `TxEnvelopeEip1559.bench.ts::TxEnvelopeEip1559.deserialize::with access list (2 entries, 4 storage keys)` | 147,861 ops/s | 111,625 ops/s | -24.5% | a57efdb8 |
+| `TxEnvelopeEip1559.bench.ts::TxEnvelopeEip1559.hash::minimal (no access list)` | 168,751 ops/s | 109,894 ops/s | -34.9% | a57efdb8 |
+| `TxEnvelopeEip1559.bench.ts::TxEnvelopeEip1559.hash::with access list (2 entries, 4 storage keys)` | 58,327 ops/s | 51,429 ops/s | -11.8% | a57efdb8 |
+
+> Note: serialize/deserialize/hash regressions tracked for follow-up — read paths (`Rlp.fromHex`) gained 16-22% but the encode/hash paths regressed and need re-investigation before the next bench cycle.
diff --git a/bench/webauthn.md b/bench/webauthn.md
new file mode 100644
index 00000000..192aa4a0
--- /dev/null
+++ b/bench/webauthn.md
@@ -0,0 +1,26 @@
+# Bench results: webauthn
+
+_`src/webauthn/*`, CoseKey, WebCryptoP256, WebAuthnP256._
+
+See [tasks/bench/README.md](../tasks/bench/README.md) for the convention.
+
+Baseline: `94d3e4bc`. PR: `8e907a32` (track-b/webauthn).
+
+| bench | baseline | PR | delta | SHA |
+| ----- | -------- | -- | ----- | --- |
+| `Authentication.bench.ts::Authentication.sign (mock)::default` | 444,389 | 516,057 | +16.1% | `8e907a32` |
+| `Authentication.bench.ts::Authentication.verify::default` | 691.51 | 825.25 | +19.3% | `8e907a32` |
+| `Authenticator.bench.ts::getAuthenticatorData (no credential)::hex output` | 541,646 | 646,294 | +19.3% | `8e907a32` |
+| `Authenticator.bench.ts::getAuthenticatorData (no credential)::bytes output` | n/a (new API) | 1,317,423 | +143.2% vs baseline-hex | `8e907a32` |
+| `Authenticator.bench.ts::getAuthenticatorData (with credential)::hex output` | 156,125 | 193,553 | +24.0% | `8e907a32` |
+| `Authenticator.bench.ts::getAuthenticatorData (with credential)::bytes output` | n/a (new API) | 189,208 | +21.2% vs baseline-hex | `8e907a32` |
+| `Authenticator.bench.ts::getSignCount::from hex` | 1,124,365 | 1,550,874 | +37.9% | `8e907a32` |
+| `Authenticator.bench.ts::getSignCount::from bytes` | n/a (new API) | 42,920,355 | +3717.3% vs baseline-hex | `8e907a32` |
+| `Registration.bench.ts::Registration.verify (packed)::default` | 629.62 | 782.30 | +24.2% | `8e907a32` |
+| `Registration.bench.ts::Registration.verify (none)::default` | 33,542 | 57,800 | +72.3% | `8e907a32` |
+
+Notes:
+- `Authentication.sign` is benched against a mocked `getFn` returning the signed fixture; it isolates the host-side parsing and metadata construction work that this phase touched.
+- `Authentication.verify` and `Registration.verify (packed)` are bottlenecked by P-256 signature verification; the measured deltas reflect the savings from the bytes-first authenticator-data parsing and (for `Registration.verify`) the single COSE decode.
+- `Registration.verify (none)` skips the attestation signature verification, isolating the COSE decode and authData parsing wins.
+- `getAuthenticatorData` and `getSignCount` `bytes` rows are new API surface (not present on baseline); compared against the baseline `hex` row for context.
diff --git a/package.json b/package.json
index 2729a7e2..0f97b1de 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,7 @@
"preinstall": "pnpx only-allow pnpm",
"prepare": "pnpm simple-git-hooks",
"size": "size-limit",
+ "bench": "vitest bench -c ./test/vitest.config.ts",
"test": "vitest -c ./test/vitest.config.ts",
"test:cov": "vitest -c ./test/vitest.config.ts --coverage",
"test:types": "TYPES=true vitest -c ./test/vitest.config.ts",
diff --git a/src/core/AbiEvent.bench.ts b/src/core/AbiEvent.bench.ts
new file mode 100644
index 00000000..5343fdfd
--- /dev/null
+++ b/src/core/AbiEvent.bench.ts
@@ -0,0 +1,29 @@
+import { bench, describe } from 'vitest'
+import * as AbiEvent from './AbiEvent.js'
+
+const transfer = AbiEvent.from(
+ 'event Transfer(address indexed from, address indexed to, uint256 value)',
+)
+
+const args = {
+ from: '0x1234567890123456789012345678901234567890' as `0x${string}`,
+ to: '0x9876543210987654321098765432109876543210' as `0x${string}`,
+}
+
+const encoded = AbiEvent.encode(transfer, args)
+const log = {
+ topics: encoded.topics as readonly `0x${string}`[],
+ data: '0x0000000000000000000000000000000000000000000000000de0b6b3a7640000' as `0x${string}`,
+}
+
+describe('AbiEvent.encode', () => {
+ bench('Transfer', () => {
+ AbiEvent.encode(transfer, args)
+ })
+})
+
+describe('AbiEvent.decode', () => {
+ bench('Transfer', () => {
+ AbiEvent.decode(transfer, log)
+ })
+})
diff --git a/src/core/AbiEvent.ts b/src/core/AbiEvent.ts
index a2825b5a..dd1a17a1 100644
--- a/src/core/AbiEvent.ts
+++ b/src/core/AbiEvent.ts
@@ -19,6 +19,94 @@ export type AbiEvent = abitype.AbiEvent & {
overloads?: readonly AbiEvent[] | undefined
}
+/**
+ * Module-scope regex for matching an array suffix on an indexed event
+ * parameter type (e.g. `uint256[]`, `bytes32[3]`). Hoisted out of
+ * `decode` / `encode` so we don't recompile per call.
+ *
+ * @internal
+ */
+const arraySuffixRegex = /^(.*)\[(\d+)?\]$/
+
+/**
+ * Encodes a primitive (32-byte) indexed event topic directly to a
+ * left-padded 32-byte hex word, skipping the `AbiParameters.encode`
+ * → `prepareParameters` → `Hex.concat` round-trip used for general
+ * parameters. Returns `undefined` if the parameter type isn't a
+ * supported primitive.
+ *
+ * @internal
+ */
+function encodePrimitiveTopic(
+ type: string,
+ value: unknown,
+): Hex.Hex | undefined {
+ if (type === 'address') {
+ Address.assert(value as Address.Address, { strict: false })
+ return `0x000000000000000000000000${(value as string).slice(2).toLowerCase()}` as Hex.Hex
+ }
+ if (type === 'bool') {
+ if (typeof value !== 'boolean') return undefined
+ return value
+ ? '0x0000000000000000000000000000000000000000000000000000000000000001'
+ : '0x0000000000000000000000000000000000000000000000000000000000000000'
+ }
+ // `uintN` / `intN` (covers all 8-bit-aligned widths up to 256).
+ if (type.startsWith('uint') || type.startsWith('int')) {
+ const signed = type[0] === 'i'
+ const sizeStr = signed ? type.slice(3) : type.slice(4)
+ const size = sizeStr === '' ? 256 : Number(sizeStr)
+ if (!Number.isFinite(size)) return undefined
+ return Hex.fromNumber(value as number | bigint, { size: 32, signed })
+ }
+ // `bytesN` (fixed): right-pad to 32 bytes.
+ if (type.startsWith('bytes') && type.length > 5) {
+ if (typeof value !== 'string') return undefined
+ return Hex.padRight(value as Hex.Hex, 32)
+ }
+ return undefined
+}
+
+/**
+ * Decodes a primitive (32-byte) indexed event topic directly to a
+ * primitive value, skipping the `AbiParameters.decode` round-trip.
+ * Returns a `[value]` tuple on hit, or `undefined` on miss.
+ *
+ * @internal
+ */
+function decodePrimitiveTopic(
+ type: string,
+ topic: Hex.Hex,
+): [value: unknown] | undefined {
+ if (type === 'address') {
+ // Trailing 20 bytes; topic is always 66 chars (`0x` + 64 hex).
+ return [`0x${topic.slice(26)}` as Hex.Hex]
+ }
+ if (type === 'bool') {
+ // Last byte determines truthiness (Solidity left-pads booleans).
+ return [topic.charCodeAt(65) === 49 /* '1' */]
+ }
+ if (type.startsWith('uint') || type.startsWith('int')) {
+ const signed = type[0] === 'i'
+ const sizeStr = signed ? type.slice(3) : type.slice(4)
+ const size = sizeStr === '' ? 256 : Number(sizeStr)
+ if (!Number.isFinite(size)) return undefined
+ const big =
+ size > 48
+ ? Hex.toBigInt(topic, { signed })
+ : Hex.toNumber(topic, { signed })
+ return [big]
+ }
+ if (type.startsWith('bytes') && type.length > 5) {
+ const sizeStr = type.slice(5)
+ const size = Number(sizeStr)
+ if (!Number.isFinite(size)) return undefined
+ // Take leading `size` bytes of the 32-byte topic.
+ return [`0x${topic.slice(2, 2 + size * 2)}` as Hex.Hex]
+ }
+ return undefined
+}
+
/**
* Extracts an {@link ox#AbiEvent.AbiEvent} item from an {@link ox#Abi.Abi}, given a name.
*
@@ -417,13 +505,19 @@ export function decode(
param: param as abitype.AbiParameter & { indexed: boolean },
})
args[isUnnamed ? i : param.name || i] = (() => {
+ const t = param.type
if (
- param.type === 'string' ||
- param.type === 'bytes' ||
- param.type === 'tuple' ||
- param.type.match(/^(.*)\[(\d+)?\]$/)
+ t === 'string' ||
+ t === 'bytes' ||
+ t === 'tuple' ||
+ arraySuffixRegex.test(t)
)
return topic
+ // Fast path: 32-byte primitive (`address`, `bool`, `uintN`,
+ // `intN`, `bytesN`). Reads the topic word directly without
+ // allocating a `Cursor` or running `Bytes.fromHex`.
+ const fast = decodePrimitiveTopic(t, topic)
+ if (fast) return fast[0]
const decoded = AbiParameters.decode([param], topic) || []
return decoded[0]
})()
@@ -684,17 +778,21 @@ export function encode(
if (args_.length > 0) {
const encode = (param: abitype.AbiParameter, value: unknown) => {
- if (param.type === 'string')
+ const t = param.type
+ if (t === 'string')
return Hash.keccak256(Hex.fromString(value as string), { as: 'Hex' })
- if (param.type === 'bytes') {
+ if (t === 'bytes') {
const hex =
typeof value === 'string'
? (value as Hex.Hex)
: Hex.fromBytes(value as Bytes.Bytes)
return Hash.keccak256(hex, { as: 'Hex' })
}
- if (param.type === 'tuple' || param.type.match(/^(.*)\[(\d+)?\]$/))
- throw new FilterTypeNotSupportedError(param.type)
+ if (t === 'tuple' || arraySuffixRegex.test(t))
+ throw new FilterTypeNotSupportedError(t)
+ // Fast path for 32-byte primitives.
+ const fast = encodePrimitiveTopic(t, value)
+ if (fast) return fast
return AbiParameters.encode([param], [value])
}
diff --git a/src/core/AbiFunction.bench.ts b/src/core/AbiFunction.bench.ts
new file mode 100644
index 00000000..6f18de70
--- /dev/null
+++ b/src/core/AbiFunction.bench.ts
@@ -0,0 +1,54 @@
+import { bench, describe } from 'vitest'
+import * as Abi from './Abi.js'
+import * as AbiFunction from './AbiFunction.js'
+
+const erc20Abi = Abi.from([
+ 'function name() view returns (string)',
+ 'function symbol() view returns (string)',
+ 'function decimals() view returns (uint8)',
+ 'function totalSupply() view returns (uint256)',
+ 'function balanceOf(address owner) view returns (uint256)',
+ 'function transfer(address to, uint256 amount) returns (bool)',
+ 'function transferFrom(address from, address to, uint256 amount) returns (bool)',
+ 'function approve(address spender, uint256 amount) returns (bool)',
+ 'function allowance(address owner, address spender) view returns (uint256)',
+])
+
+const transferFn = AbiFunction.fromAbi(erc20Abi, 'transfer')
+const transferArgs = [
+ '0x1234567890123456789012345678901234567890' as `0x${string}`,
+ 1000000000000000000n,
+] as const
+
+const transferEncoded = AbiFunction.encodeData(transferFn, transferArgs)
+
+const transferFromFn = AbiFunction.fromAbi(erc20Abi, 'transferFrom')
+const transferFromArgs = [
+ '0x1234567890123456789012345678901234567890' as `0x${string}`,
+ '0x9876543210987654321098765432109876543210' as `0x${string}`,
+ 500000000000000000n,
+] as const
+const transferFromEncoded = AbiFunction.encodeData(
+ transferFromFn,
+ transferFromArgs,
+)
+
+describe('AbiFunction.encodeData', () => {
+ bench('erc20.transfer', () => {
+ AbiFunction.encodeData(transferFn, transferArgs)
+ })
+
+ bench('erc20.transferFrom', () => {
+ AbiFunction.encodeData(transferFromFn, transferFromArgs)
+ })
+})
+
+describe('AbiFunction.decodeData', () => {
+ bench('erc20.transfer', () => {
+ AbiFunction.decodeData(transferFn, transferEncoded)
+ })
+
+ bench('erc20.transferFrom', () => {
+ AbiFunction.decodeData(transferFromFn, transferFromEncoded)
+ })
+})
diff --git a/src/core/AbiItem.bench.ts b/src/core/AbiItem.bench.ts
new file mode 100644
index 00000000..b4887672
--- /dev/null
+++ b/src/core/AbiItem.bench.ts
@@ -0,0 +1,40 @@
+import { bench, describe } from 'vitest'
+import * as Abi from './Abi.js'
+import * as AbiItem from './AbiItem.js'
+
+// Build a 200-item ABI (mix of function + event signatures) so each
+// `fromAbi` selector lookup walks a realistically large list.
+const signatures: string[] = []
+for (let i = 0; i < 180; i++) {
+ signatures.push(`function fn${i}(uint256 a, address b) returns (bool)`)
+}
+for (let i = 0; i < 20; i++) {
+ signatures.push(
+ `event Evt${i}(address indexed a, uint256 b, bytes32 indexed c)`,
+ )
+}
+const abi200 = Abi.from(signatures)
+
+// Use the last function so a naive linear scan is forced to walk to
+// the end before matching.
+const lastFn = AbiItem.fromAbi(abi200, 'fn179')
+const lastSelector = AbiItem.getSelector(lastFn)
+
+const firstFn = AbiItem.fromAbi(abi200, 'fn0')
+const firstSelector = AbiItem.getSelector(firstFn)
+
+describe('AbiItem.fromAbi (selector)', () => {
+ bench('200-item ABI: last function', () => {
+ AbiItem.fromAbi(abi200, lastSelector)
+ })
+
+ bench('200-item ABI: first function', () => {
+ AbiItem.fromAbi(abi200, firstSelector)
+ })
+})
+
+describe('AbiItem.fromAbi (name)', () => {
+ bench('200-item ABI: last function by name', () => {
+ AbiItem.fromAbi(abi200, 'fn179')
+ })
+})
diff --git a/src/core/AbiItem.ts b/src/core/AbiItem.ts
index 57bf61c1..b6be5253 100644
--- a/src/core/AbiItem.ts
+++ b/src/core/AbiItem.ts
@@ -340,15 +340,28 @@ export function fromAbi<
{}) as unknown as fromAbi.Options
const isSelector = Hex.validate(name, { strict: false })
- const abiItems = (abi as Abi.Abi).filter((abiItem) => {
- if (isSelector) {
+
+ // Selector lookups are always unique on the ABI: precompute the
+ // function/error 4-byte selector once and short-circuit via `find`
+ // instead of building a full `filter` result we'd discard.
+ if (isSelector) {
+ const selector = Hex.slice(name, 0, 4)
+ const abiItem = (abi as Abi.Abi).find((abiItem) => {
if (abiItem.type === 'function' || abiItem.type === 'error')
- return getSelector(abiItem) === Hex.slice(name, 0, 4)
+ return getSelector(abiItem) === selector
if (abiItem.type === 'event') return getSignatureHash(abiItem) === name
return false
- }
- return 'name' in abiItem && abiItem.name === name
- })
+ })
+ if (!abiItem) throw new NotFoundError({ name: name as string })
+ return {
+ ...abiItem,
+ ...(prepare ? { hash: getSignatureHash(abiItem) } : {}),
+ } as never
+ }
+
+ const abiItems = (abi as Abi.Abi).filter(
+ (abiItem) => 'name' in abiItem && abiItem.name === name,
+ )
if (abiItems.length === 0) throw new NotFoundError({ name: name as string })
if (abiItems.length === 1)
diff --git a/src/core/AbiParameters.bench.ts b/src/core/AbiParameters.bench.ts
new file mode 100644
index 00000000..9e790397
--- /dev/null
+++ b/src/core/AbiParameters.bench.ts
@@ -0,0 +1,82 @@
+import { bench, describe } from 'vitest'
+import * as AbiParameters from './AbiParameters.js'
+
+const uint256_1000 = AbiParameters.from('uint256[]')
+const uint256_1000_values = Array.from({ length: 1000 }, (_, i) => BigInt(i))
+const uint256_1000_encoded = AbiParameters.encode(uint256_1000, [
+ uint256_1000_values,
+])
+
+const address_100 = AbiParameters.from('address[]')
+const address_100_values = Array.from(
+ { length: 100 },
+ (_, i) => `0x${i.toString(16).padStart(40, '0')}` as `0x${string}`,
+)
+const address_100_encoded = AbiParameters.encode(address_100, [
+ address_100_values,
+])
+
+const string_param = AbiParameters.from('string')
+const string_value = 'a'.repeat(1024)
+const string_encoded = AbiParameters.encode(string_param, [string_value])
+
+const tuple_nested = AbiParameters.from(
+ '(uint256 a, address b, bool c), (uint256 a, address b, bool c), (uint256 a, address b, bool c)',
+)
+const tuple_nested_values = [
+ {
+ a: 1n,
+ b: '0x0000000000000000000000000000000000000001' as `0x${string}`,
+ c: true,
+ },
+ {
+ a: 2n,
+ b: '0x0000000000000000000000000000000000000002' as `0x${string}`,
+ c: false,
+ },
+ {
+ a: 3n,
+ b: '0x0000000000000000000000000000000000000003' as `0x${string}`,
+ c: true,
+ },
+] as const
+const tuple_nested_encoded = AbiParameters.encode(
+ tuple_nested,
+ tuple_nested_values as never,
+)
+
+describe('AbiParameters.encode', () => {
+ bench('(uint256[1000])', () => {
+ AbiParameters.encode(uint256_1000, [uint256_1000_values])
+ })
+
+ bench('(address[100])', () => {
+ AbiParameters.encode(address_100, [address_100_values])
+ })
+
+ bench('(string) 1KB', () => {
+ AbiParameters.encode(string_param, [string_value])
+ })
+
+ bench('nested (tuple, tuple, tuple)', () => {
+ AbiParameters.encode(tuple_nested, tuple_nested_values as never)
+ })
+})
+
+describe('AbiParameters.decode', () => {
+ bench('(uint256[1000])', () => {
+ AbiParameters.decode(uint256_1000, uint256_1000_encoded)
+ })
+
+ bench('(address[100])', () => {
+ AbiParameters.decode(address_100, address_100_encoded)
+ })
+
+ bench('(string) 1KB', () => {
+ AbiParameters.decode(string_param, string_encoded)
+ })
+
+ bench('nested (tuple, tuple, tuple)', () => {
+ AbiParameters.decode(tuple_nested, tuple_nested_encoded)
+ })
+})
diff --git a/src/core/AccountProof.bench.ts b/src/core/AccountProof.bench.ts
new file mode 100644
index 00000000..4bd0a494
--- /dev/null
+++ b/src/core/AccountProof.bench.ts
@@ -0,0 +1,66 @@
+import { bench, describe } from 'vitest'
+import * as AccountProof from './AccountProof.js'
+
+const accountProofSegment =
+ '0xf90211a090dcaf88c40c7bbc95a912cbdde67c175767b31173df9ee4b0d733bfdd511c43a0babe369f6b12092f49181ae04ca173fb68d1a5456f18d20fa32cbd3f9aa75e9da0473ecf8a7e36a829e75039a3b055e51b8332cbf03324ab4af2066bbd6fbf0021'
+
+const baseProof: AccountProof.Rpc = {
+ address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9',
+ balance: '0xde0b6b3a7640000',
+ codeHash:
+ '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ nonce: '0x2a',
+ storageHash:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ accountProof: Array.from(
+ { length: 6 },
+ () => accountProofSegment as `0x${string}`,
+ ),
+ storageProof: [],
+}
+
+function withSlots(count: number): AccountProof.Rpc {
+ return {
+ ...baseProof,
+ storageProof: Array.from({ length: count }, (_, i) => ({
+ key: ('0x' + i.toString(16).padStart(64, '0')) as `0x${string}`,
+ proof: Array.from(
+ { length: 4 },
+ () => accountProofSegment as `0x${string}`,
+ ),
+ value: ('0x' + (i + 1).toString(16)) as `0x${string}`,
+ })),
+ }
+}
+
+const small = withSlots(1)
+const medium = withSlots(10)
+const large = withSlots(100)
+
+const smallParsed = AccountProof.fromRpc(small)
+const mediumParsed = AccountProof.fromRpc(medium)
+const largeParsed = AccountProof.fromRpc(large)
+
+describe('AccountProof.fromRpc', () => {
+ bench('1 slot', () => {
+ AccountProof.fromRpc(small)
+ })
+ bench('10 slots', () => {
+ AccountProof.fromRpc(medium)
+ })
+ bench('100 slots', () => {
+ AccountProof.fromRpc(large)
+ })
+})
+
+describe('AccountProof.toRpc', () => {
+ bench('1 slot', () => {
+ AccountProof.toRpc(smallParsed)
+ })
+ bench('10 slots', () => {
+ AccountProof.toRpc(mediumParsed)
+ })
+ bench('100 slots', () => {
+ AccountProof.toRpc(largeParsed)
+ })
+})
diff --git a/src/core/Address.bench.ts b/src/core/Address.bench.ts
new file mode 100644
index 00000000..638b4362
--- /dev/null
+++ b/src/core/Address.bench.ts
@@ -0,0 +1,92 @@
+import { bench, describe } from 'vitest'
+
+import * as Address from './Address.js'
+import * as Caches from './Caches.js'
+
+const lower = '0xa0cf798816d4b9b9866b5330eea46a18382f251e'
+const checksummed = '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
+const mixedNoChecksum = '0xA0Cf798816D4b9b9866b5330Eea46a18382f251e'
+const tooShort = '0xa'
+const garbage = 'hello world'
+const wrongLength = '0xa5cc3c03994db5b0d9a5eEdD10Cabab0813678aff'
+const badHex = '0xa5cc3c03994db5b0d9a5eEdD10Cabab0813678az'
+
+describe('Address.assert (valid)', () => {
+ bench('checksummed input (strict)', () => {
+ Address.assert(checksummed)
+ })
+
+ bench('lowercase input (strict)', () => {
+ Address.assert(lower)
+ })
+
+ bench('lowercase input (strict: false)', () => {
+ Address.assert(lower, { strict: false })
+ })
+})
+
+describe('Address.validate (valid)', () => {
+ bench('checksummed input (strict)', () => {
+ Address.validate(checksummed)
+ })
+
+ bench('lowercase input (strict)', () => {
+ Address.validate(lower)
+ })
+
+ bench('lowercase input (strict: false)', () => {
+ Address.validate(lower, { strict: false })
+ })
+})
+
+describe('Address.validate (invalid)', () => {
+ bench('too short', () => {
+ Address.validate(tooShort)
+ })
+
+ bench('garbage string', () => {
+ Address.validate(garbage)
+ })
+
+ bench('wrong length', () => {
+ Address.validate(wrongLength)
+ })
+
+ bench('bad hex char', () => {
+ Address.validate(badHex)
+ })
+
+ bench('mixed-case bad checksum', () => {
+ Address.validate(mixedNoChecksum)
+ })
+})
+
+describe('Address.checksum', () => {
+ // Hot cache: same address requested repeatedly.
+ bench('cache hit (lowercase key)', () => {
+ Address.checksum(lower)
+ })
+
+ bench('cache hit (mixed-case input)', () => {
+ Address.checksum(mixedNoChecksum)
+ })
+
+ bench('cache miss (cleared each iter)', () => {
+ Caches.clear()
+ Address.checksum(lower)
+ })
+})
+
+describe('Address.isEqual', () => {
+ bench('equal lowercase / checksummed', () => {
+ Address.isEqual(lower, checksummed)
+ })
+
+ bench('equal lowercase / lowercase', () => {
+ Address.isEqual(lower, lower)
+ })
+
+ bench('different addresses', () => {
+ Address.isEqual(lower, '0xA0Cf798816D4b9b9866b5330EEa46a18382f251f')
+ })
+})
diff --git a/src/core/Address.ts b/src/core/Address.ts
index 5399ffa0..c4d7a363 100644
--- a/src/core/Address.ts
+++ b/src/core/Address.ts
@@ -3,10 +3,9 @@ import * as Bytes from './Bytes.js'
import * as Caches from './Caches.js'
import * as Errors from './Errors.js'
import * as Hash from './Hash.js'
+import * as internal from './internal/address.js'
import * as PublicKey from './PublicKey.js'
-const addressRegex = /^0x[a-fA-F0-9]{40}$/
-
/** Root type for Address. */
export type Address = abitype_Address
@@ -37,20 +36,19 @@ export function assert(
): asserts value is Address {
const { strict = true } = options
- if (!addressRegex.test(value))
+ const kind = internal.classify(value)
+ if (kind === 0)
throw new InvalidAddressError({
address: value,
cause: new InvalidInputError(),
})
- if (strict) {
- if (value.toLowerCase() === value) return
- if (checksum(value as Address) !== value)
- throw new InvalidAddressError({
- address: value,
- cause: new InvalidChecksumError(),
- })
- }
+ // Lowercase inputs are exempt from checksum verification.
+ if (strict && kind === 2 && checksum(value as Address) !== value)
+ throw new InvalidAddressError({
+ address: value,
+ cause: new InvalidChecksumError(),
+ })
}
export declare namespace assert {
@@ -81,25 +79,48 @@ export declare namespace assert {
* @returns The checksummed address.
*/
export function checksum(address: string): Address {
- if (Caches.checksum.has(address)) return Caches.checksum.get(address)!
+ // Direct cache lookup keeps the common hot path (callers passing the same
+ // string repeatedly) at a single `Map.get`.
+ const direct = Caches.checksum.get(address)
+ if (direct !== undefined) return direct
- assert(address, { strict: false })
-
- const hexAddress = address.substring(2).toLowerCase()
- const hash = Hash.keccak256(Bytes.fromString(hexAddress), { as: 'Bytes' })
+ if (!internal.hasShape(address))
+ throw new InvalidAddressError({
+ address,
+ cause: new InvalidInputError(),
+ })
- const characters = hexAddress.split('')
- for (let i = 0; i < 40; i += 2) {
- if (hash[i >> 1]! >> 4 >= 8 && characters[i]) {
- characters[i] = characters[i]!.toUpperCase()
- }
- if ((hash[i >> 1]! & 0x0f) >= 8 && characters[i + 1]) {
- characters[i + 1] = characters[i + 1]!.toUpperCase()
+ // Secondary lookup keyed by the canonical lowercase form so that mixed-case
+ // spellings of the same address share an entry instead of competing for two
+ // slots in a bounded cache.
+ const key = internal.lowercase(address)
+ if (key !== address) {
+ const cached = Caches.checksum.get(key)
+ if (cached !== undefined) {
+ Caches.checksum.set(address, cached)
+ return cached
}
}
- const result = `0x${characters.join('')}` as const
- Caches.checksum.set(address, result)
+ const hash = Hash.keccak256(Bytes.fromString(key.slice(2)), { as: 'Bytes' })
+
+ const out = new Uint16Array(42)
+ out[0] = 48 // '0'
+ out[1] = 120 // 'x'
+ for (let i = 0; i < 40; i++) {
+ const code = key.charCodeAt(i + 2)
+ const nibble = (i & 1) === 0 ? hash[i >> 1]! >> 4 : hash[i >> 1]! & 0x0f
+ // Uppercase a-f when the corresponding nibble is >= 8. ASCII 'a'..'f' are
+ // 97..102; subtracting 32 yields 'A'..'F'.
+ out[i + 2] = nibble >= 8 && code >= 97 ? code - 32 : code
+ }
+
+ const result = String.fromCharCode.apply(
+ null,
+ out as unknown as number[],
+ ) as Address
+ Caches.checksum.set(key, result)
+ if (key !== address) Caches.checksum.set(address, result)
return result
}
@@ -241,8 +262,17 @@ export declare namespace fromPublicKey {
* @returns Whether the addresses are equal.
*/
export function isEqual(addressA: Address, addressB: Address): boolean {
- assert(addressA, { strict: false })
- assert(addressB, { strict: false })
+ if (!internal.hasShape(addressA))
+ throw new InvalidAddressError({
+ address: addressA,
+ cause: new InvalidInputError(),
+ })
+ if (!internal.hasShape(addressB))
+ throw new InvalidAddressError({
+ address: addressB,
+ cause: new InvalidInputError(),
+ })
+ if (addressA === addressB) return true
return addressA.toLowerCase() === addressB.toLowerCase()
}
@@ -278,12 +308,10 @@ export function validate(
options: validate.Options = {},
): address is Address {
const { strict = true } = options ?? {}
- try {
- assert(address, { strict })
- return true
- } catch {
- return false
- }
+ const kind = internal.classify(address)
+ if (kind === 0) return false
+ if (!strict || kind === 1) return true
+ return checksum(address as Address) === address
}
export declare namespace validate {
diff --git a/src/core/AesGcm.bench.ts b/src/core/AesGcm.bench.ts
new file mode 100644
index 00000000..a0afef95
--- /dev/null
+++ b/src/core/AesGcm.bench.ts
@@ -0,0 +1,25 @@
+import { bench, describe } from 'vitest'
+import * as AesGcm from './AesGcm.js'
+import * as Bytes from './Bytes.js'
+
+const key = await AesGcm.getKey({ password: 'bench-password' })
+
+const sizes = [32, 1024, 65536] as const
+
+for (const size of sizes) {
+ const value = Bytes.random(size)
+
+ describe(`AesGcm.encrypt (${size} bytes)`, () => {
+ bench('encrypt', async () => {
+ await AesGcm.encrypt(value, key)
+ })
+ })
+
+ const encrypted = await AesGcm.encrypt(value, key)
+
+ describe(`AesGcm.decrypt (${size} bytes)`, () => {
+ bench('decrypt', async () => {
+ await AesGcm.decrypt(encrypted, key)
+ })
+ })
+}
diff --git a/src/core/AesGcm.ts b/src/core/AesGcm.ts
index 891faf20..fb48d8b1 100644
--- a/src/core/AesGcm.ts
+++ b/src/core/AesGcm.ts
@@ -107,7 +107,11 @@ export async function encrypt<
key,
Bytes.from(value),
)
- const result = Bytes.concat(iv, new Uint8Array(encrypted))
+ // Write IV and ciphertext into a single output buffer to avoid an extra
+ // allocation and copy from `Bytes.concat(iv, ciphertext)`.
+ const result = new Uint8Array(ivLength + encrypted.byteLength)
+ result.set(iv, 0)
+ result.set(new Uint8Array(encrypted), ivLength)
if (as === 'Bytes') return result as never
return Hex.from(result) as never
}
diff --git a/src/core/Base32.ts b/src/core/Base32.ts
index de8e9857..090a44a5 100644
--- a/src/core/Base32.ts
+++ b/src/core/Base32.ts
@@ -1,14 +1,11 @@
import * as Bytes from './Bytes.js'
import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
-
-/** Bech32 base32 alphabet (BIP-173). */
-const alphabet = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
-const alphabetMap = /*#__PURE__*/ (() => {
- const map: Record = {}
- for (let i = 0; i < alphabet.length; i++) map[alphabet[i]!] = i
- return map
-})()
+import {
+ alphabet,
+ alphabetMap,
+ convertBits,
+} from './internal/codec/bech32-base32.js'
/**
* Encodes a {@link ox#Bytes.Bytes} value to a Base32-encoded string (using the BIP-173 bech32 alphabet).
@@ -24,19 +21,11 @@ const alphabetMap = /*#__PURE__*/ (() => {
* @returns The Base32 encoded string.
*/
export function fromBytes(value: Bytes.Bytes): string {
- let bits = 0
- let acc = 0
- let result = ''
- for (const byte of value) {
- acc = (acc << 8) | byte
- bits += 8
- while (bits >= 5) {
- bits -= 5
- result += alphabet[(acc >>> bits) & 0x1f]
- }
- }
- if (bits > 0) result += alphabet[(acc << (5 - bits)) & 0x1f]
- return result
+ const data5 = convertBits(value, 8, 5, true)
+ const len = data5.length
+ const out = new Array(len)
+ for (let i = 0; i < len; i++) out[i] = alphabet[data5[i]!]!
+ return out.join('')
}
export declare namespace fromBytes {
@@ -78,25 +67,29 @@ export declare namespace fromHex {
* @returns The decoded byte array.
*/
export function toBytes(value: string): Bytes.Bytes {
- const values: number[] = []
- for (const char of value) {
- const v = alphabetMap[char]
- if (v === undefined) throw new InvalidCharacterError({ character: char })
- values.push(v)
+ const len = value.length
+ const values = new Array(len)
+ for (let i = 0; i < len; i++) {
+ const ch = value[i]!
+ const v = alphabetMap[ch]
+ if (v === undefined) throw new InvalidCharacterError({ character: ch })
+ values[i] = v
}
let bits = 0
let acc = 0
- const bytes: number[] = []
- for (const v of values) {
- acc = (acc << 5) | v
+ // Worst-case: every 5 bits maps to up to 1 byte; preallocate.
+ const bytes = new Uint8Array((len * 5) >> 3)
+ let n = 0
+ for (let i = 0; i < len; i++) {
+ acc = (acc << 5) | values[i]!
bits += 5
if (bits >= 8) {
bits -= 8
- bytes.push((acc >>> bits) & 0xff)
+ bytes[n++] = (acc >>> bits) & 0xff
}
}
- return new Uint8Array(bytes)
+ return bytes.subarray(0, n)
}
export declare namespace toBytes {
diff --git a/src/core/Base64.bench.ts b/src/core/Base64.bench.ts
new file mode 100644
index 00000000..ea6bf888
--- /dev/null
+++ b/src/core/Base64.bench.ts
@@ -0,0 +1,70 @@
+import { bench, describe } from 'vitest'
+import * as Base64 from './Base64.js'
+
+const small = new Uint8Array(32).map((_, i) => i)
+const medium = new Uint8Array(256).map((_, i) => i & 0xff)
+const large = new Uint8Array(4096).map((_, i) => i & 0xff)
+
+const smallEncoded = Base64.fromBytes(small)
+const mediumEncoded = Base64.fromBytes(medium)
+const largeEncoded = Base64.fromBytes(large)
+
+const smallEncodedNoPad = Base64.fromBytes(small, { pad: false })
+const smallEncodedUrl = Base64.fromBytes(small, { url: true })
+
+const helloString = 'hello world'
+const loremString = 'lorem ipsum '.repeat(64)
+
+describe('Base64.fromBytes', () => {
+ bench('32 bytes (padded)', () => {
+ Base64.fromBytes(small)
+ })
+ bench('256 bytes (padded)', () => {
+ Base64.fromBytes(medium)
+ })
+ bench('4096 bytes (padded)', () => {
+ Base64.fromBytes(large)
+ })
+ bench('32 bytes (no pad)', () => {
+ Base64.fromBytes(small, { pad: false })
+ })
+ bench('32 bytes (url)', () => {
+ Base64.fromBytes(small, { url: true })
+ })
+})
+
+describe('Base64.toBytes', () => {
+ bench('32 bytes (padded)', () => {
+ Base64.toBytes(smallEncoded)
+ })
+ bench('256 bytes (padded)', () => {
+ Base64.toBytes(mediumEncoded)
+ })
+ bench('4096 bytes (padded)', () => {
+ Base64.toBytes(largeEncoded)
+ })
+ bench('32 bytes (no pad)', () => {
+ Base64.toBytes(smallEncodedNoPad)
+ })
+ bench('32 bytes (url)', () => {
+ Base64.toBytes(smallEncodedUrl)
+ })
+})
+
+describe('Base64.fromString / toString', () => {
+ const helloEncoded = Base64.fromString(helloString)
+ const loremEncoded = Base64.fromString(loremString)
+
+ bench('fromString hello', () => {
+ Base64.fromString(helloString)
+ })
+ bench('fromString lorem (768 chars)', () => {
+ Base64.fromString(loremString)
+ })
+ bench('toString hello', () => {
+ Base64.toString(helloEncoded)
+ })
+ bench('toString lorem (768 chars)', () => {
+ Base64.toString(loremEncoded)
+ })
+})
diff --git a/src/core/Base64.ts b/src/core/Base64.ts
index e3bf0980..9f29b39d 100644
--- a/src/core/Base64.ts
+++ b/src/core/Base64.ts
@@ -1,26 +1,66 @@
import * as Bytes from './Bytes.js'
import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
-
-const encoder = /*#__PURE__*/ new TextEncoder()
-const decoder = /*#__PURE__*/ new TextDecoder()
-
-const integerToCharacter = /*#__PURE__*/ Object.fromEntries(
- Array.from(
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
- ).map((a, i) => [i, a.charCodeAt(0)]),
-)
-
-const characterToInteger = {
- ...Object.fromEntries(
- Array.from(
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
- ).map((a, i) => [a.charCodeAt(0), i]),
- ),
- ['='.charCodeAt(0)]: 0,
- ['-'.charCodeAt(0)]: 62,
- ['_'.charCodeAt(0)]: 63,
-} as Record
+import { decoder } from './internal/codec/utf8.js'
+
+// Standard Base64 alphabet (RFC 4648 section 4) and URL-safe alphabet (section 5).
+const stdAlphabet =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
+
+// Char-code -> 6-bit integer lookup. Sentinel `0xff` = invalid character.
+// Standard alphabet plus URL-safe `-`/`_` (decoders are alphabet-agnostic).
+const characterToInteger = /*#__PURE__*/ (() => {
+ const table = new Uint8Array(256).fill(0xff)
+ for (let i = 0; i < stdAlphabet.length; i++)
+ table[stdAlphabet.charCodeAt(i)] = i
+ // URL-safe alternates: `-` for `+` (62), `_` for `/` (63).
+ table[45 /* '-' */] = 62
+ table[95 /* '_' */] = 63
+ return table
+})()
+
+// Integer -> char-code table for the standard alphabet, indexed by 6-bit value.
+const integerToCharacter = /*#__PURE__*/ (() => {
+ const table = new Uint8Array(64)
+ for (let i = 0; i < stdAlphabet.length; i++)
+ table[i] = stdAlphabet.charCodeAt(i)
+ return table
+})()
+
+// Phase 2 native fast-path detection: `Uint8Array.prototype.toBase64` /
+// `Uint8Array.fromBase64` ship in Node 22+, Safari 18+, Firefox 133+.
+const nativeToBase64:
+ | ((
+ this: Uint8Array,
+ options?: { alphabet?: 'base64' | 'base64url'; omitPadding?: boolean },
+ ) => string)
+ | undefined = (
+ Uint8Array.prototype as Uint8Array & {
+ toBase64?: (options?: {
+ alphabet?: 'base64' | 'base64url'
+ omitPadding?: boolean
+ }) => string
+ }
+).toBase64
+const nativeFromBase64:
+ | ((
+ value: string,
+ options?: {
+ alphabet?: 'base64' | 'base64url-or-base64'
+ lastChunkHandling?: 'loose' | 'strict' | 'stop-before-partial'
+ },
+ ) => Uint8Array)
+ | undefined = (
+ Uint8Array as typeof Uint8Array & {
+ fromBase64?: (
+ value: string,
+ options?: {
+ alphabet?: 'base64' | 'base64url-or-base64'
+ lastChunkHandling?: 'loose' | 'strict' | 'stop-before-partial'
+ },
+ ) => Uint8Array
+ }
+).fromBase64
/**
* Encodes a {@link ox#Bytes.Bytes} to a Base64-encoded string (with optional padding and/or URL-safe characters).
@@ -63,6 +103,20 @@ const characterToInteger = {
export function fromBytes(value: Bytes.Bytes, options: fromBytes.Options = {}) {
const { pad = true, url = false } = options
+ if (nativeToBase64) {
+ const out = nativeToBase64.call(value, {
+ alphabet: url ? 'base64url' : 'base64',
+ omitPadding: !pad,
+ })
+ // Native `base64url` already omits padding; if pad was requested, restore it.
+ if (url && pad) {
+ const k = value.length % 3
+ if (k === 1) return `${out}==`
+ if (k === 2) return `${out}=`
+ }
+ return out
+ }
+
const encoded = new Uint8Array(Math.ceil(value.length / 3) * 4)
for (let i = 0, j = 0; j < value.length; i += 4, j += 3) {
@@ -239,44 +293,53 @@ export declare namespace fromString {
*/
export function toBytes(value: string): Bytes.Bytes {
// Strip trailing '=' padding (only at the very end).
- let body = value
+ let bodyEnd = value.length
let pad = 0
- while (body.length > 0 && body.charCodeAt(body.length - 1) === 61 /* '=' */) {
- body = body.slice(0, -1)
+ while (bodyEnd > 0 && value.charCodeAt(bodyEnd - 1) === 61 /* '=' */) {
+ bodyEnd--
pad++
}
- const size = body.length
+ const size = bodyEnd
// Reject impossible lengths and excessive padding.
if (size % 4 === 1) throw new InvalidLengthError({ length: value.length })
if (pad > 2) throw new InvalidPaddingError({ padding: pad })
- // Validate characters: every char must be in the standard or URL-safe alphabet,
- // and '=' may not appear in the body (only stripped trailing padding).
+ if (nativeFromBase64) {
+ try {
+ // `base64url-or-base64` accepts both alphabets transparently.
+ return nativeFromBase64(value.slice(0, bodyEnd), {
+ alphabet: 'base64url-or-base64',
+ lastChunkHandling: 'loose',
+ })
+ } catch {
+ // Fall through to the JS path so we throw the typed error class.
+ }
+ }
+
+ // Validate characters: every char must be in the standard or URL-safe
+ // alphabet, and '=' may not appear in the body (only stripped trailing
+ // padding).
+ const decoded = new Uint8Array(
+ (size >> 2) * 3 + (size % 4 ? (size % 4) - 1 : 0),
+ )
+ let acc = 0
+ let bits = 0
+ let n = 0
for (let i = 0; i < size; i++) {
- const code = body.charCodeAt(i)
+ const code = value.charCodeAt(i)
if (code === 61 /* '=' */)
throw new InvalidCharacterError({ character: '=' })
- if (characterToInteger[code] === undefined)
- throw new InvalidCharacterError({ character: body[i]! })
+ const v = characterToInteger[code]!
+ if (v === 0xff) throw new InvalidCharacterError({ character: value[i]! })
+ acc = (acc << 6) | v
+ bits += 6
+ if (bits >= 8) {
+ bits -= 8
+ decoded[n++] = (acc >>> bits) & 0xff
+ }
}
-
- const decoded = new Uint8Array(size + 3)
- encoder.encodeInto(body + '===', decoded)
-
- for (let i = 0, j = 0; i < size; i += 4, j += 3) {
- const x =
- (characterToInteger[decoded[i]!]! << 18) +
- (characterToInteger[decoded[i + 1]!]! << 12) +
- (characterToInteger[decoded[i + 2]!]! << 6) +
- characterToInteger[decoded[i + 3]!]!
- decoded[j] = x >> 16
- decoded[j + 1] = (x >> 8) & 0xff
- decoded[j + 2] = x & 0xff
- }
-
- const decodedSize = (size >> 2) * 3 + (size % 4 && (size % 4) - 1)
- return new Uint8Array(decoded.buffer, 0, decodedSize)
+ return decoded
}
export declare namespace toBytes {
diff --git a/src/core/Bech32m.ts b/src/core/Bech32m.ts
index dfc61173..0e5e33ba 100644
--- a/src/core/Bech32m.ts
+++ b/src/core/Bech32m.ts
@@ -1,5 +1,11 @@
import type * as Errors from './Errors.js'
import { BaseError } from './Errors.js'
+import {
+ InvalidPaddingError as SharedInvalidPaddingError,
+ alphabet as sharedAlphabet,
+ alphabetMap as sharedAlphabetMap,
+ convertBits as sharedConvertBits,
+} from './internal/codec/bech32-base32.js'
/**
* Encodes data bytes with a human-readable part (HRP) into a bech32m string (BIP-350).
@@ -151,13 +157,14 @@ export class InvalidCharacterError extends BaseError {
}
}
-/** Thrown when the padding bits are invalid during base32 conversion. */
-export class InvalidPaddingError extends BaseError {
- override readonly name = 'Bech32m.InvalidPaddingError'
- constructor() {
- super('Invalid padding in bech32m data.')
- }
-}
+/**
+ * Thrown when the padding bits are invalid during base32 conversion.
+ *
+ * Re-exported from `internal/codec/bech32-base32.ts` for shared identity
+ * with `Base32`'s padding validation.
+ */
+export const InvalidPaddingError = SharedInvalidPaddingError
+export type InvalidPaddingError = InstanceType
/** Thrown when a bech32m string contains mixed case. */
export class MixedCaseError extends BaseError {
@@ -185,15 +192,9 @@ export class ExceedsLengthError extends BaseError {
}
}
-/** @internal */
-const alphabet = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
-
-/** @internal */
-const alphabetMap = /*#__PURE__*/ (() => {
- const map: Record = {}
- for (let i = 0; i < alphabet.length; i++) map[alphabet[i]!] = i
- return map
-})()
+/** Shared with `Base32` (BIP-173). */
+const alphabet = sharedAlphabet
+const alphabetMap = sharedAlphabetMap
/** @internal */
const BECH32M_CONST = 0x2bc830a3
@@ -235,29 +236,5 @@ function verifyChecksum(hrp: string, data: number[]): boolean {
return polymod(hrpExpand(hrp).concat(data)) === BECH32M_CONST
}
-/** @internal */
-function convertBits(
- data: Iterable,
- fromBits: number,
- toBits: number,
- pad: boolean,
-): number[] {
- let acc = 0
- let bits = 0
- const maxv = (1 << toBits) - 1
- const ret: number[] = []
- for (const value of data) {
- acc = (acc << fromBits) | value
- bits += fromBits
- while (bits >= toBits) {
- bits -= toBits
- ret.push((acc >> bits) & maxv)
- }
- }
- if (pad) {
- if (bits > 0) ret.push((acc << (toBits - bits)) & maxv)
- } else if (bits >= fromBits || (acc << (toBits - bits)) & maxv) {
- throw new InvalidPaddingError()
- }
- return ret
-}
+/** Shared with `Base32`. */
+const convertBits = sharedConvertBits
diff --git a/src/core/Block.bench.ts b/src/core/Block.bench.ts
new file mode 100644
index 00000000..65bf5402
--- /dev/null
+++ b/src/core/Block.bench.ts
@@ -0,0 +1,115 @@
+import { bench, describe } from 'vitest'
+import * as Block from './Block.js'
+import type * as Hex from './Hex.js'
+import type * as Transaction from './Transaction.js'
+
+const txHash =
+ '0xcfa52db0bc2cb5bdcb2c5bd8816df7a2f018a0e3964ab1ef4d794cf327966e93' as Hex.Hex
+
+const baseTransaction: Transaction.Rpc = {
+ type: '0x2',
+ blockHash:
+ '0xebc3644804e4040c0a74c5a5bbbc6b46a71a5d4010fe0c92ebb2fdf4a43ea5dd',
+ blockNumber: '0xec6fc6',
+ chainId: '0x1',
+ from: '0x0000000000000000000000000000000000000000',
+ gas: '0x5208',
+ hash: txHash,
+ input: '0x',
+ maxFeePerGas: '0x59682f00',
+ maxPriorityFeePerGas: '0x59682f00',
+ nonce: '0x0',
+ r: '0x0',
+ s: '0x0',
+ to: '0x0000000000000000000000000000000000000000',
+ transactionIndex: '0x0',
+ v: '0x0',
+ yParity: '0x0',
+ value: '0x0',
+ accessList: [],
+}
+
+function makeRpc(txCount: number): Block.Rpc {
+ return {
+ blobGasUsed: '0x1',
+ baseFeePerGas: '0x0',
+ difficulty: '0x2d3a678cddba9b',
+ excessBlobGas: '0x2',
+ extraData: '0x',
+ gasLimit: '0x1c9c347',
+ gasUsed: '0x0',
+ hash: '0xebc3644804e4040c0a74c5a5bbbc6b46a71a5d4010fe0c92ebb2fdf4a43ea5dd',
+ logsBloom: ('0x' + '0'.repeat(512)) as Hex.Hex,
+ miner: '0x0000000000000000000000000000000000000000',
+ mixHash:
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
+ nonce: '0x0000000000000000',
+ number: '0xec6fc6',
+ parentHash:
+ '0xe55516ad8029e53cd32087f14653d851401b05245abb1b2d6ed4ddcc597ac5a6',
+ receiptsRoot:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ sealFields: [],
+ sha3Uncles:
+ '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
+ size: '0x208',
+ stateRoot:
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
+ timestamp: '0x63198f6f',
+ totalDifficulty: '0x1',
+ transactions: Array.from(
+ { length: txCount },
+ () => baseTransaction,
+ ) as readonly Transaction.Rpc[],
+ transactionsRoot:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ uncles: [],
+ withdrawals: [],
+ withdrawalsRoot:
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ }
+}
+
+const hashesOnly: any = {
+ ...makeRpc(0),
+ transactions: Array.from({ length: 100 }, () => txHash),
+}
+
+const withTxs1: any = makeRpc(1)
+const withTxs10: any = makeRpc(10)
+const withTxs100: any = makeRpc(100)
+
+const parsedHashes: any = Block.fromRpc(hashesOnly)
+const parsedTxs1: any = Block.fromRpc(withTxs1)
+const parsedTxs10: any = Block.fromRpc(withTxs10)
+const parsedTxs100: any = Block.fromRpc(withTxs100)
+
+describe('Block.fromRpc', () => {
+ bench('hashes only (100)', () => {
+ Block.fromRpc(hashesOnly)
+ })
+ bench('with 1 transaction', () => {
+ Block.fromRpc(withTxs1)
+ })
+ bench('with 10 transactions', () => {
+ Block.fromRpc(withTxs10)
+ })
+ bench('with 100 transactions', () => {
+ Block.fromRpc(withTxs100)
+ })
+})
+
+describe('Block.toRpc', () => {
+ bench('hashes only (100)', () => {
+ Block.toRpc(parsedHashes)
+ })
+ bench('with 1 transaction', () => {
+ Block.toRpc(parsedTxs1)
+ })
+ bench('with 10 transactions', () => {
+ Block.toRpc(parsedTxs10)
+ })
+ bench('with 100 transactions', () => {
+ Block.toRpc(parsedTxs100)
+ })
+})
diff --git a/src/core/BlockOverrides.ts b/src/core/BlockOverrides.ts
index 3cc33c60..a3221dce 100644
--- a/src/core/BlockOverrides.ts
+++ b/src/core/BlockOverrides.ts
@@ -62,13 +62,9 @@ export type Rpc = BlockOverrides
export function fromRpc(rpcBlockOverrides: Rpc): BlockOverrides {
const overrides: BlockOverrides = {}
if (rpcBlockOverrides.baseFeePerGas !== undefined)
- overrides.baseFeePerGas = Quantity.toBigInt(
- rpcBlockOverrides.baseFeePerGas,
- )
+ overrides.baseFeePerGas = Quantity.toBigInt(rpcBlockOverrides.baseFeePerGas)
if (rpcBlockOverrides.blobBaseFee !== undefined)
- overrides.blobBaseFee = Quantity.toBigInt(
- rpcBlockOverrides.blobBaseFee,
- )
+ overrides.blobBaseFee = Quantity.toBigInt(rpcBlockOverrides.blobBaseFee)
if (rpcBlockOverrides.feeRecipient !== undefined)
overrides.feeRecipient = rpcBlockOverrides.feeRecipient
if (rpcBlockOverrides.gasLimit !== undefined)
@@ -76,9 +72,7 @@ export function fromRpc(rpcBlockOverrides: Rpc): BlockOverrides {
if (rpcBlockOverrides.number !== undefined)
overrides.number = Quantity.toBigInt(rpcBlockOverrides.number)
if (rpcBlockOverrides.prevRandao !== undefined)
- overrides.prevRandao = Quantity.toBigInt(
- rpcBlockOverrides.prevRandao,
- )
+ overrides.prevRandao = Quantity.toBigInt(rpcBlockOverrides.prevRandao)
if (rpcBlockOverrides.time !== undefined)
overrides.time = Quantity.toBigInt(rpcBlockOverrides.time)
if (rpcBlockOverrides.withdrawals !== undefined)
diff --git a/src/core/Bls.bench.ts b/src/core/Bls.bench.ts
new file mode 100644
index 00000000..63363803
--- /dev/null
+++ b/src/core/Bls.bench.ts
@@ -0,0 +1,32 @@
+import { bench, describe } from 'vitest'
+import * as Bls from './Bls.js'
+import * as Hex from './Hex.js'
+
+const payload = Hex.fromBytes(new Uint8Array(32).fill(0xab))
+
+function makeSignatures(count: number) {
+ const signatures: ReturnType[] = []
+ for (let i = 0; i < count; i++) {
+ const privateKey = Bls.randomPrivateKey()
+ signatures.push(Bls.sign({ payload, privateKey }))
+ }
+ return signatures
+}
+
+const sig10 = makeSignatures(10)
+const sig100 = makeSignatures(100)
+const sig1000 = makeSignatures(1000)
+
+describe('Bls.aggregate', () => {
+ bench('10 signatures', () => {
+ Bls.aggregate(sig10)
+ })
+
+ bench('100 signatures', () => {
+ Bls.aggregate(sig100)
+ })
+
+ bench('1000 signatures', () => {
+ Bls.aggregate(sig1000)
+ })
+})
diff --git a/src/core/Bls.ts b/src/core/Bls.ts
index d9f63ad4..eb6f4284 100644
--- a/src/core/Bls.ts
+++ b/src/core/Bls.ts
@@ -71,15 +71,18 @@ export function aggregate(
}
const group = isG1 ? bls.G1 : bls.G2
- const point = points.reduce(
- (acc, point) =>
- acc.add(new (group as any).Point(point.x, point.y, point.z)),
- group.Point.ZERO,
- )
+ // Hoist the noble Point ctor reference and accumulate via a tight loop
+ // (avoids the per-iteration callback overhead from `Array.reduce`).
+ const PointCtor = (group as any).Point
+ let acc = group.Point.ZERO
+ for (let i = 0; i < points.length; i++) {
+ const p = points[i]!
+ acc = acc.add(new PointCtor(p.x, p.y, p.z))
+ }
return {
- x: point.X,
- y: point.Y,
- z: point.Z,
+ x: acc.X,
+ y: acc.Y,
+ z: acc.Z,
}
}
diff --git a/src/core/Bls_crypto.bench.ts b/src/core/Bls_crypto.bench.ts
new file mode 100644
index 00000000..ab1b0894
--- /dev/null
+++ b/src/core/Bls_crypto.bench.ts
@@ -0,0 +1,23 @@
+import { bench, describe } from 'vitest'
+import * as Bls from './Bls.js'
+
+const sizes = [1, 10, 100, 1000] as const
+
+const max = Math.max(...sizes)
+
+// Pre-compute the maximum number of public-key points once. Each `getPublicKey`
+// call is heavy compared to `aggregate`, so we want only the aggregation cost
+// to land in the bench timing window.
+const allPublicKeys = Array.from({ length: max }, () =>
+ Bls.getPublicKey({ privateKey: Bls.randomPrivateKey() }),
+)
+
+for (const size of sizes) {
+ const points = allPublicKeys.slice(0, size)
+
+ describe(`Bls.aggregate (${size} points)`, () => {
+ bench('aggregate', () => {
+ Bls.aggregate(points)
+ })
+ })
+}
diff --git a/src/core/Bytes.bench.ts b/src/core/Bytes.bench.ts
new file mode 100644
index 00000000..a5e3f97a
--- /dev/null
+++ b/src/core/Bytes.bench.ts
@@ -0,0 +1,121 @@
+import { bench, describe } from 'vitest'
+import * as Bytes from './Bytes.js'
+
+const small = new Uint8Array(32).map((_, i) => i)
+const medium = new Uint8Array(256).map((_, i) => i & 0xff)
+const large = new Uint8Array(4096).map((_, i) => i & 0xff)
+
+const smallHex = Bytes.toHex(small)
+const mediumHex = Bytes.toHex(medium)
+const largeHex = Bytes.toHex(large)
+
+const smallString = 'Hello world!'
+const mediumString = 'lorem ipsum '.repeat(32)
+const helloBytes = Bytes.fromString('hello world')
+
+const u32 = 2_147_483_647n
+const u256 = (1n << 256n) - 1n
+const bytes32 = (() => {
+ const b = new Uint8Array(32)
+ for (let i = 0; i < 32; i++) b[i] = (i * 7 + 11) & 0xff
+ return b
+})()
+const bytes32Zero = new Uint8Array(32)
+
+describe('Bytes.fromHex', () => {
+ bench('32 bytes', () => {
+ Bytes.fromHex(smallHex)
+ })
+ bench('256 bytes', () => {
+ Bytes.fromHex(mediumHex)
+ })
+ bench('4096 bytes', () => {
+ Bytes.fromHex(largeHex)
+ })
+})
+
+describe('Bytes.toHex', () => {
+ bench('32 bytes', () => {
+ Bytes.toHex(small)
+ })
+ bench('256 bytes', () => {
+ Bytes.toHex(medium)
+ })
+ bench('4096 bytes', () => {
+ Bytes.toHex(large)
+ })
+})
+
+describe('Bytes.concat', () => {
+ bench('two small', () => {
+ Bytes.concat(small, small)
+ })
+ bench('eight small', () => {
+ Bytes.concat(small, small, small, small, small, small, small, small)
+ })
+})
+
+describe('Bytes.fromString', () => {
+ bench('short ASCII', () => {
+ Bytes.fromString(smallString)
+ })
+ bench('medium ASCII', () => {
+ Bytes.fromString(mediumString)
+ })
+})
+
+describe('Bytes.toString', () => {
+ bench('short ASCII', () => {
+ Bytes.toString(helloBytes)
+ })
+})
+
+describe('Bytes.fromNumber', () => {
+ bench('small (size 32)', () => {
+ Bytes.fromNumber(420, { size: 32 })
+ })
+ bench('large bigint (size 32)', () => {
+ Bytes.fromNumber(0xdeadbeefcafe1234n, { size: 32 })
+ })
+})
+
+describe('Bytes.fromNumber({ size: 32 })', () => {
+ bench('bigint, max', () => {
+ Bytes.fromNumber(u256, { size: 32 })
+ })
+
+ bench('bigint, small', () => {
+ Bytes.fromNumber(420n, { size: 32 })
+ })
+
+ bench('number', () => {
+ Bytes.fromNumber(420, { size: 32 })
+ })
+
+ bench('bigint, max u32', () => {
+ Bytes.fromNumber(u32, { size: 32 })
+ })
+})
+
+describe('Bytes.toBigInt', () => {
+ bench('32 bytes', () => {
+ Bytes.toBigInt(bytes32)
+ })
+
+ bench('32 bytes (zero)', () => {
+ Bytes.toBigInt(bytes32Zero)
+ })
+
+ bench('32 bytes, size: 32', () => {
+ Bytes.toBigInt(bytes32, { size: 32 })
+ })
+})
+
+describe('Bytes.padLeft', () => {
+ bench('32 -> 32 (noop)', () => {
+ Bytes.padLeft(small, 32)
+ })
+ bench('1 -> 32', () => {
+ Bytes.padLeft(small.subarray(0, 1), 32)
+ })
+})
diff --git a/src/core/Bytes.ts b/src/core/Bytes.ts
index 4ad8566d..6f0a7d07 100644
--- a/src/core/Bytes.ts
+++ b/src/core/Bytes.ts
@@ -1,12 +1,24 @@
import { equalBytes } from '@noble/curves/utils.js'
import * as Errors from './Errors.js'
-import * as Hex from './Hex.js'
import * as internal from './internal/bytes.js'
+import {
+ bytesToHex,
+ type Hex as Hex_codec,
+ hexToBytes,
+ type InvalidHexValueError,
+ type InvalidLengthError,
+} from './internal/codec/hex.js'
+import {
+ bigIntToBytes,
+ bytesToBigInt,
+ bytesToSafeNumber,
+} from './internal/codec/int.js'
+import { decoder, encoder } from './internal/codec/utf8.js'
import * as internal_hex from './internal/hex.js'
import * as Json from './Json.js'
-const decoder = /*#__PURE__*/ new TextDecoder()
-const encoder = /*#__PURE__*/ new TextEncoder()
+/** Local alias of the `Hex` type from `internal/codec/hex.ts` to avoid a runtime import of `./Hex.js`. */
+type HexStr = Hex_codec
/** Root type for a Bytes array. */
export type Bytes = Uint8Array
@@ -105,7 +117,7 @@ export declare namespace concat {
* @param value - Value to convert.
* @returns A {@link ox#Bytes.Bytes} instance.
*/
-export function from(value: Hex.Hex | Bytes | readonly number[]): Bytes {
+export function from(value: HexStr | Bytes | readonly number[]): Bytes {
if (value instanceof Uint8Array) return value
if (typeof value === 'string') return fromHex(value)
return fromArray(value)
@@ -209,39 +221,15 @@ export declare namespace fromBoolean {
* @param options - Encoding options.
* @returns Encoded {@link ox#Bytes.Bytes}.
*/
-export function fromHex(value: Hex.Hex, options: fromHex.Options = {}): Bytes {
+export function fromHex(value: HexStr, options: fromHex.Options = {}): Bytes {
const { size } = options
-
- if (
- typeof value !== 'string' ||
- value.length < 2 ||
- value.charCodeAt(0) !== 48 /* '0' */ ||
- value.charCodeAt(1) !== 120 /* 'x' */
- )
- throw new Hex.InvalidHexValueError(value)
-
- let hex = value
- if (size) {
+ if (typeof size === 'number') {
internal_hex.assertSize(value, size)
- hex = Hex.padRight(value, size)
- }
-
- const hexString = hex.slice(2)
- if ((hexString.length & 1) !== 0) throw new Hex.InvalidLengthError(hex)
-
- const length = hexString.length >> 1
- const bytes = new Uint8Array(length)
- for (let index = 0, j = 0; index < length; index++) {
- const nibbleLeft = internal.charCodeToBase16(hexString.charCodeAt(j++))
- const nibbleRight = internal.charCodeToBase16(hexString.charCodeAt(j++))
- if (nibbleLeft === undefined || nibbleRight === undefined) {
- throw new Errors.BaseError(
- `Invalid byte sequence ("${hexString[j - 2]}${hexString[j - 1]}" in "${hexString}").`,
- )
- }
- bytes[index] = (nibbleLeft << 4) | nibbleRight
+ // Right-pad the hex string before parsing to preserve odd-nibble
+ // semantics of the previous implementation.
+ return hexToBytes(internal_hex.pad(value, { dir: 'right', size }))
}
- return bytes
+ return hexToBytes(value)
}
export declare namespace fromHex {
@@ -252,9 +240,9 @@ export declare namespace fromHex {
type ErrorType =
| internal_hex.assertSize.ErrorType
- | Hex.padRight.ErrorType
- | Hex.InvalidHexValueError
- | Hex.InvalidLengthError
+ | internal_hex.pad.ErrorType
+ | InvalidHexValueError
+ | InvalidLengthError
| Errors.GlobalErrorType
}
@@ -285,22 +273,13 @@ export function fromNumber(
value: bigint | number,
options?: fromNumber.Options | undefined,
) {
- const hex = Hex.fromNumber(value, options)
- // Hex.fromNumber may produce odd-nibble hex (e.g. `0x7`, total length 3);
- // even-pad before handing to the strict `fromHex` parser.
- const evenHex = (
- (hex.length & 1) === 1 ? `0x0${hex.slice(2)}` : hex
- ) as Hex.Hex
- return fromHex(evenHex)
+ return bigIntToBytes(value, options)
}
export declare namespace fromNumber {
- export type Options = Hex.fromNumber.Options
+ export type Options = bigIntToBytes.Options
- export type ErrorType =
- | Hex.fromNumber.ErrorType
- | fromHex.ErrorType
- | Errors.GlobalErrorType
+ export type ErrorType = bigIntToBytes.ErrorType | Errors.GlobalErrorType
}
/**
@@ -538,10 +517,9 @@ export declare namespace slice {
* @returns Decoded bigint.
*/
export function toBigInt(bytes: Bytes, options: toBigInt.Options = {}): bigint {
- const { size } = options
+ const { signed, size } = options
if (typeof size !== 'undefined') internal.assertSize(bytes, size)
- const hex = Hex.fromBytes(bytes, options)
- return Hex.toBigInt(hex, options)
+ return bytesToBigInt(bytes, signed)
}
export declare namespace toBigInt {
@@ -553,8 +531,8 @@ export declare namespace toBigInt {
}
type ErrorType =
- | Hex.fromBytes.ErrorType
- | Hex.toBigInt.ErrorType
+ | internal.assertSize.ErrorType
+ | bytesToBigInt.ErrorType
| Errors.GlobalErrorType
}
@@ -615,8 +593,14 @@ export declare namespace toBoolean {
* @param options - Options.
* @returns Decoded {@link ox#Hex.Hex} value.
*/
-export function toHex(value: Bytes, options: toHex.Options = {}): Hex.Hex {
- return Hex.fromBytes(value, options)
+export function toHex(value: Bytes, options: toHex.Options = {}): HexStr {
+ const hex = bytesToHex(value)
+ const { size } = options
+ if (typeof size === 'number') {
+ internal_hex.assertSize(hex, size)
+ return internal_hex.pad(hex, { dir: 'right', size })
+ }
+ return hex
}
export declare namespace toHex {
@@ -625,7 +609,11 @@ export declare namespace toHex {
size?: number | undefined
}
- type ErrorType = Hex.fromBytes.ErrorType | Errors.GlobalErrorType
+ type ErrorType =
+ | internal_hex.assertSize.ErrorType
+ | internal_hex.pad.ErrorType
+ | bytesToHex.ErrorType
+ | Errors.GlobalErrorType
}
/**
@@ -640,10 +628,9 @@ export declare namespace toHex {
* ```
*/
export function toNumber(bytes: Bytes, options: toNumber.Options = {}): number {
- const { size } = options
+ const { signed, size } = options
if (typeof size !== 'undefined') internal.assertSize(bytes, size)
- const hex = Hex.fromBytes(bytes, options)
- return Hex.toNumber(hex, options)
+ return bytesToSafeNumber(bytes, signed)
}
export declare namespace toNumber {
@@ -655,8 +642,8 @@ export declare namespace toNumber {
}
type ErrorType =
- | Hex.fromBytes.ErrorType
- | Hex.toNumber.ErrorType
+ | internal.assertSize.ErrorType
+ | bytesToSafeNumber.ErrorType
| Errors.GlobalErrorType
}
diff --git a/src/core/Caches.ts b/src/core/Caches.ts
index dfcb3e50..e7836b4a 100644
--- a/src/core/Caches.ts
+++ b/src/core/Caches.ts
@@ -1,8 +1,8 @@
import type * as Address from './Address.js'
-import { LruMap } from './internal/lru.js'
+import { BoundedMap } from './internal/lru.js'
const caches = {
- checksum: /*#__PURE__*/ new LruMap(8192),
+ checksum: /*#__PURE__*/ new BoundedMap(32_768),
}
export const checksum = caches.checksum
diff --git a/src/core/Cbor.bench.ts b/src/core/Cbor.bench.ts
new file mode 100644
index 00000000..c6441633
--- /dev/null
+++ b/src/core/Cbor.bench.ts
@@ -0,0 +1,58 @@
+import { bench, describe } from 'vitest'
+import * as Cbor from './Cbor.js'
+
+const small = { ok: true, n: 42, msg: 'hello' }
+const medium = {
+ jsonrpc: '2.0',
+ id: 1,
+ result: {
+ blockNumber: '0x1a4',
+ transactions: Array.from({ length: 16 }, (_, i) => `0xfeed${i}`),
+ logs: Array.from({ length: 8 }, (_, i) => ({
+ address: `0xabc${i}`,
+ topics: ['0xdead', '0xbeef'],
+ data: '0xcafe',
+ })),
+ },
+}
+const bytesPayload = new Uint8Array(256).map((_, i) => i & 0xff)
+
+const encodedSmall = Cbor.encode(small)
+const encodedMedium = Cbor.encode(medium)
+const encodedBytes = Cbor.encode(bytesPayload)
+
+const encodedSmallBytes = Cbor.encode(small, { as: 'Bytes' })
+const encodedMediumBytes = Cbor.encode(medium, { as: 'Bytes' })
+
+describe('Cbor.encode', () => {
+ bench('small object', () => {
+ Cbor.encode(small)
+ })
+ bench('medium object', () => {
+ Cbor.encode(medium)
+ })
+ bench('256-byte buffer', () => {
+ Cbor.encode(bytesPayload)
+ })
+ bench('small object (as: Bytes)', () => {
+ Cbor.encode(small, { as: 'Bytes' })
+ })
+})
+
+describe('Cbor.decode', () => {
+ bench('small object (Hex)', () => {
+ Cbor.decode(encodedSmall)
+ })
+ bench('medium object (Hex)', () => {
+ Cbor.decode(encodedMedium)
+ })
+ bench('256-byte buffer (Hex)', () => {
+ Cbor.decode(encodedBytes)
+ })
+ bench('small object (Bytes)', () => {
+ Cbor.decode(encodedSmallBytes)
+ })
+ bench('medium object (Bytes)', () => {
+ Cbor.decode(encodedMediumBytes)
+ })
+})
diff --git a/src/core/CoseKey.ts b/src/core/CoseKey.ts
index e1726403..8abdb9cd 100644
--- a/src/core/CoseKey.ts
+++ b/src/core/CoseKey.ts
@@ -1,6 +1,8 @@
+import * as Bytes from './Bytes.js'
import * as Cbor from './Cbor.js'
import * as Errors from './Errors.js'
import type * as Hex from './Hex.js'
+import * as Cursor from './internal/cursor.js'
import * as PublicKey from './PublicKey.js'
/**
@@ -50,6 +52,12 @@ export declare namespace fromPublicKey {
/**
* Converts a CBOR-encoded COSE_Key to a P256 {@link ox#PublicKey.PublicKey}.
*
+ * Accepts the COSE key as either a hex string or raw bytes. When the
+ * `returnByteLength` or `returnDecoded` option is set, the function returns an
+ * object containing the public key plus the consumed byte length and/or the
+ * decoded CBOR map. This is useful for parsing CBOR streams (such as WebAuthn
+ * `authenticatorData`) where the COSE key is followed by trailing data.
+ *
* @example
* ```ts twoslash
* import { CoseKey, P256 } from 'ox'
@@ -60,11 +68,38 @@ export declare namespace fromPublicKey {
* const publicKey2 = CoseKey.toPublicKey(coseKey)
* ```
*
- * @param coseKey - The CBOR-encoded COSE_Key.
- * @returns The P256 public key.
+ * @example
+ * ### With Byte Length
+ *
+ * ```ts twoslash
+ * import { CoseKey, P256 } from 'ox'
+ *
+ * const { publicKey } = P256.createKeyPair()
+ * const coseKey = CoseKey.fromPublicKey(publicKey)
+ *
+ * const { publicKey: pk, byteLength } = CoseKey.toPublicKey(coseKey, {
+ * returnByteLength: true,
+ * })
+ * ```
+ *
+ * @param coseKey - The CBOR-encoded COSE_Key as hex or bytes.
+ * @param options - Decoding options.
+ * @returns The P256 public key, optionally with byte length and decoded CBOR.
*/
-export function toPublicKey(coseKey: Hex.Hex): PublicKey.PublicKey {
- const decoded = Cbor.decode>(coseKey)
+export function toPublicKey(
+ coseKey: Hex.Hex | Uint8Array,
+ options: options | toPublicKey.Options = {},
+): toPublicKey.ReturnType {
+ const bytes = typeof coseKey === 'string' ? Bytes.fromHex(coseKey) : coseKey
+
+ const cursor = Cursor.create(bytes)
+ const decoded = Cbor.decode>(bytes)
+ // After Cbor.decode, the cursor's position would advance, but Cbor.decode
+ // creates its own cursor internally. Walk the bytes here to compute consumed
+ // byte length without re-encoding (which loses optional COSE members).
+ cursor.position = 0
+ cborSkip(cursor)
+ const byteLength = cursor.position
// Validate COSE_Key header per RFC 9053 (kty=2 EC2, alg=-7 ES256, crv=1 P-256).
if (decoded['1'] !== 2 || decoded['3'] !== -7 || decoded['-1'] !== 1)
@@ -81,17 +116,98 @@ export function toPublicKey(coseKey: Hex.Hex): PublicKey.PublicKey {
)
throw new InvalidCoseKeyError()
- return PublicKey.from(new Uint8Array([0x04, ...x, ...y]))
+ const raw = new Uint8Array(65)
+ raw[0] = 0x04
+ raw.set(x, 1)
+ raw.set(y, 33)
+ const publicKey = PublicKey.from(raw)
+
+ if (!options.returnByteLength && !options.returnDecoded)
+ return publicKey as toPublicKey.ReturnType
+
+ const result: toPublicKey.ResultObject = { publicKey }
+ if (options.returnByteLength) result.byteLength = byteLength
+ if (options.returnDecoded) result.decoded = decoded
+ return result as toPublicKey.ReturnType
}
export declare namespace toPublicKey {
+ type Options = {
+ /** Include the consumed byte length of the COSE key in the result. */
+ returnByteLength?: boolean | undefined
+ /** Include the decoded CBOR map in the result. */
+ returnDecoded?: boolean | undefined
+ }
+
+ type ResultObject = {
+ publicKey: PublicKey.PublicKey
+ byteLength?: number
+ decoded?: Record
+ }
+
+ type ReturnType =
+ options['returnByteLength'] extends true
+ ? ResultObject
+ : options['returnDecoded'] extends true
+ ? ResultObject
+ : PublicKey.PublicKey
+
type ErrorType =
+ | Bytes.fromHex.ErrorType
| Cbor.decode.ErrorType
| PublicKey.from.ErrorType
| InvalidCoseKeyError
| Errors.GlobalErrorType
}
+/**
+ * Walks one CBOR element on the cursor, advancing `cursor.position` past it.
+ * Supports the major types used by COSE keys: unsigned int (0), negative int
+ * (1), byte string (2), text string (3), array (4), map (5).
+ *
+ * @internal
+ */
+function cborSkip(cursor: Cursor.Cursor): void {
+ const initialByte = cursor.readUint8()
+ const majorType = initialByte >> 5
+ const additionalInfo = initialByte & 0b00011111
+ const length = cborReadLength(cursor, additionalInfo)
+
+ switch (majorType) {
+ case 0:
+ case 1:
+ // value already consumed by `cborReadLength`.
+ return
+ case 2:
+ case 3:
+ // skip `length` bytes of byte/text string content
+ cursor.readBytes(length)
+ return
+ case 4:
+ for (let i = 0; i < length; i++) cborSkip(cursor)
+ return
+ case 5:
+ for (let i = 0; i < length; i++) {
+ cborSkip(cursor)
+ cborSkip(cursor)
+ }
+ return
+ case 7:
+ return
+ default:
+ throw new InvalidCoseKeyError()
+ }
+}
+
+/** @internal */
+function cborReadLength(cursor: Cursor.Cursor, ai: number): number {
+ if (ai < 24) return ai
+ if (ai === 24) return cursor.readUint8()
+ if (ai === 25) return cursor.readUint16()
+ if (ai === 26) return cursor.readUint32()
+ throw new InvalidCoseKeyError()
+}
+
/** Thrown when a COSE_Key does not contain valid P256 public key coordinates. */
export class InvalidCoseKeyError extends Errors.BaseError {
override readonly name = 'CoseKey.InvalidCoseKeyError'
diff --git a/src/core/Hash.bench.ts b/src/core/Hash.bench.ts
new file mode 100644
index 00000000..c0a42070
--- /dev/null
+++ b/src/core/Hash.bench.ts
@@ -0,0 +1,31 @@
+import { bench, describe } from 'vitest'
+import * as Bytes from './Bytes.js'
+import * as Hash from './Hash.js'
+import * as Hex from './Hex.js'
+
+const sizes = [32, 256, 4096] as const
+
+for (const size of sizes) {
+ const bytes = Bytes.random(size)
+ const hex = Hex.fromBytes(bytes)
+
+ describe(`Hash.sha256 (${size} bytes input)`, () => {
+ bench('Bytes.Bytes input', () => {
+ Hash.sha256(bytes)
+ })
+
+ bench('Hex.Hex input', () => {
+ Hash.sha256(hex)
+ })
+ })
+
+ describe(`Hash.keccak256 (${size} bytes input)`, () => {
+ bench('Bytes.Bytes input', () => {
+ Hash.keccak256(bytes)
+ })
+
+ bench('Hex.Hex input', () => {
+ Hash.keccak256(hex)
+ })
+ })
+}
diff --git a/src/core/Hash.ts b/src/core/Hash.ts
index e0a62a4a..8d7bc9ef 100644
--- a/src/core/Hash.ts
+++ b/src/core/Hash.ts
@@ -52,8 +52,9 @@ export function keccak256<
value: value | Hex.Hex | Bytes.Bytes,
options: keccak256.Options = {},
): keccak256.ReturnType {
- const { as = typeof value === 'string' ? 'Hex' : 'Bytes' } = options
- const bytes = noble_keccak256(Bytes.from(value))
+ const isBytes = value instanceof Uint8Array
+ const { as = isBytes ? 'Bytes' : 'Hex' } = options
+ const bytes = noble_keccak256(isBytes ? value : Bytes.from(value))
if (as === 'Bytes') return bytes as never
return Hex.fromBytes(bytes) as never
}
@@ -112,8 +113,11 @@ export function hmac256<
value: value | Hex.Hex | Bytes.Bytes,
options: hmac256.Options = {},
): hmac256.ReturnType {
- const { as = typeof value === 'string' ? 'Hex' : 'Bytes' } = options
- const bytes = hmac(noble_sha256, Bytes.from(key), Bytes.from(value))
+ const isBytes = value instanceof Uint8Array
+ const { as = isBytes ? 'Bytes' : 'Hex' } = options
+ const keyBytes = key instanceof Uint8Array ? key : Bytes.from(key)
+ const valueBytes = isBytes ? value : Bytes.from(value)
+ const bytes = hmac(noble_sha256, keyBytes, valueBytes)
if (as === 'Bytes') return bytes as never
return Hex.fromBytes(bytes) as never
}
@@ -160,8 +164,9 @@ export function ripemd160<
value: value | Hex.Hex | Bytes.Bytes,
options: ripemd160.Options = {},
): ripemd160.ReturnType {
- const { as = typeof value === 'string' ? 'Hex' : 'Bytes' } = options
- const bytes = noble_ripemd160(Bytes.from(value))
+ const isBytes = value instanceof Uint8Array
+ const { as = isBytes ? 'Bytes' : 'Hex' } = options
+ const bytes = noble_ripemd160(isBytes ? value : Bytes.from(value))
if (as === 'Bytes') return bytes as never
return Hex.fromBytes(bytes) as never
}
@@ -208,8 +213,9 @@ export function sha256<
value: value | Hex.Hex | Bytes.Bytes,
options: sha256.Options = {},
): sha256.ReturnType {
- const { as = typeof value === 'string' ? 'Hex' : 'Bytes' } = options
- const bytes = noble_sha256(Bytes.from(value))
+ const isBytes = value instanceof Uint8Array
+ const { as = isBytes ? 'Bytes' : 'Hex' } = options
+ const bytes = noble_sha256(isBytes ? value : Bytes.from(value))
if (as === 'Bytes') return bytes as never
return Hex.fromBytes(bytes) as never
}
diff --git a/src/core/Hex.bench.ts b/src/core/Hex.bench.ts
new file mode 100644
index 00000000..018be8a7
--- /dev/null
+++ b/src/core/Hex.bench.ts
@@ -0,0 +1,121 @@
+import { bench, describe } from 'vitest'
+import * as Hex from './Hex.js'
+
+const small = new Uint8Array(32).map((_, i) => i)
+const medium = new Uint8Array(256).map((_, i) => i & 0xff)
+const large = new Uint8Array(4096).map((_, i) => i & 0xff)
+
+const smallHex = Hex.fromBytes(small)
+const mediumHex = Hex.fromBytes(medium)
+const largeHex = Hex.fromBytes(large)
+
+const hex8: Hex.Hex = '0xdeadbeef'
+const hex32: Hex.Hex = `0x${'a'.repeat(64)}` as Hex.Hex
+const hex65: Hex.Hex = `0x${'b'.repeat(130)}` as Hex.Hex
+
+describe('Hex.fromBytes', () => {
+ bench('32 bytes', () => {
+ Hex.fromBytes(small)
+ })
+ bench('256 bytes', () => {
+ Hex.fromBytes(medium)
+ })
+ bench('4096 bytes', () => {
+ Hex.fromBytes(large)
+ })
+})
+
+describe('Hex.toBytes', () => {
+ bench('32 bytes', () => {
+ Hex.toBytes(smallHex)
+ })
+ bench('256 bytes', () => {
+ Hex.toBytes(mediumHex)
+ })
+ bench('4096 bytes', () => {
+ Hex.toBytes(largeHex)
+ })
+})
+
+describe('Hex.concat', () => {
+ bench('two small', () => {
+ Hex.concat(smallHex, smallHex)
+ })
+ bench('eight small', () => {
+ Hex.concat(
+ smallHex,
+ smallHex,
+ smallHex,
+ smallHex,
+ smallHex,
+ smallHex,
+ smallHex,
+ smallHex,
+ )
+ })
+
+ bench('2 args (32+32)', () => {
+ Hex.concat(hex32, hex32)
+ })
+
+ bench('3 args (32+32+1)', () => {
+ Hex.concat(hex32, hex32, '0x1c' as Hex.Hex)
+ })
+
+ bench('8 args (8x4)', () => {
+ Hex.concat(hex8, hex8, hex8, hex8, hex8, hex8, hex8, hex8)
+ })
+})
+
+describe('Hex.slice', () => {
+ bench('positive start, no end', () => {
+ Hex.slice(hex65, 1)
+ })
+
+ bench('positive start + end', () => {
+ Hex.slice(hex65, 0, 32)
+ })
+
+ bench('negative start', () => {
+ Hex.slice(hex65, -32)
+ })
+})
+
+describe('Hex.fromNumber', () => {
+ bench('small number (no size)', () => {
+ Hex.fromNumber(420)
+ })
+ bench('safe-int fast path (size 32)', () => {
+ Hex.fromNumber(420, { size: 32 })
+ })
+ bench('bigint (size 32)', () => {
+ Hex.fromNumber(0xdeadbeefcafe1234n, { size: 32 })
+ })
+})
+
+describe('Hex.toBigInt', () => {
+ bench('32 bytes', () => {
+ Hex.toBigInt(smallHex)
+ })
+})
+
+describe('Hex.padLeft', () => {
+ bench('32 -> 32 (noop)', () => {
+ Hex.padLeft(smallHex, 32)
+ })
+ bench('1 -> 32', () => {
+ Hex.padLeft(Hex.fromBytes(small.subarray(0, 1)), 32)
+ })
+})
+
+describe('Hex.fromString', () => {
+ bench('short ASCII', () => {
+ Hex.fromString('Hello world!')
+ })
+})
+
+describe('Hex.validate (strict)', () => {
+ bench('256 bytes', () => {
+ Hex.validate(mediumHex, { strict: true })
+ })
+})
diff --git a/src/core/Hex.ts b/src/core/Hex.ts
index 80c8a5e9..389ee347 100644
--- a/src/core/Hex.ts
+++ b/src/core/Hex.ts
@@ -1,16 +1,17 @@
import { equalBytes } from '@noble/curves/utils.js'
-import * as Bytes from './Bytes.js'
import * as Errors from './Errors.js'
-import * as internal_bytes from './internal/bytes.js'
+import { BytesSizeOverflowError } from './internal/codec/errors.js'
+import {
+ bytesToHex,
+ hexToBytes,
+ InvalidHexValueError as InvalidHexValueError_codec,
+ InvalidLengthError as InvalidLengthError_codec,
+} from './internal/codec/hex.js'
+import { IntegerOutOfRangeError as IntegerOutOfRangeError_codec } from './internal/codec/int.js'
+import { decoder, encoder } from './internal/codec/utf8.js'
import * as internal from './internal/hex.js'
import * as Json from './Json.js'
-const encoder = /*#__PURE__*/ new TextEncoder()
-
-const hexes = /*#__PURE__*/ Array.from({ length: 256 }, (_v, i) =>
- i.toString(16).padStart(2, '0'),
-)
-
/** Root type for a Hex string. */
export type Hex = `0x${string}`
@@ -69,7 +70,14 @@ export declare namespace assert {
* @returns The concatenated {@link ox#Hex.Hex} value.
*/
export function concat(...values: readonly Hex[]): Hex {
- return `0x${(values as Hex[]).reduce((acc, x) => acc + x.replace('0x', ''), '')}`
+ if (values.length === 0) return '0x'
+ if (values.length === 1) return values[0]!
+ if (values.length === 2)
+ return `0x${(values[0] as string).slice(2)}${(values[1] as string).slice(2)}` as Hex
+ const parts = new Array(values.length)
+ for (let i = 0; i < values.length; i++)
+ parts[i] = (values[i] as string).slice(2)
+ return `0x${parts.join('')}` as Hex
}
export declare namespace concat {
@@ -105,7 +113,7 @@ export declare namespace concat {
* @param value - The {@link ox#Bytes.Bytes} value to encode.
* @returns The encoded {@link ox#Hex.Hex} value.
*/
-export function from(value: Hex | Bytes.Bytes | readonly number[]): Hex {
+export function from(value: Hex | Uint8Array | readonly number[]): Hex {
if (value instanceof Uint8Array) return fromBytes(value)
if (Array.isArray(value)) return fromBytes(new Uint8Array(value))
assert(value)
@@ -182,12 +190,10 @@ export declare namespace fromBoolean {
* @returns The encoded {@link ox#Hex.Hex} value.
*/
export function fromBytes(
- value: Bytes.Bytes,
+ value: Uint8Array,
options: fromBytes.Options = {},
): Hex {
- let string = ''
- for (let i = 0; i < value.length; i++) string += hexes[value[i]!]
- const hex = `0x${string}` as const
+ const hex = bytesToHex(value)
if (typeof options.size === 'number') {
internal.assertSize(hex, options.size)
@@ -232,6 +238,29 @@ export function fromNumber(
): Hex {
const { signed, size } = options
+ // Safe-integer unsigned fast path: skip BigInt conversion entirely.
+ if (
+ !signed &&
+ typeof value === 'number' &&
+ value >= 0 &&
+ Number.isSafeInteger(value)
+ ) {
+ if (size) {
+ const maxValue = 2n ** (BigInt(size) * 8n) - 1n
+ if (BigInt(value) > maxValue)
+ throw new IntegerOutOfRangeError({
+ max: `${maxValue}`,
+ min: '0',
+ signed: false,
+ size,
+ value: `${value}`,
+ })
+ const hex = `0x${value.toString(16)}` as Hex
+ return padLeft(hex, size)
+ }
+ return `0x${value.toString(16)}` as Hex
+ }
+
const value_ = BigInt(value)
let maxValue: bigint | number | undefined
@@ -336,11 +365,11 @@ export declare namespace fromString {
* @returns `true` if the two {@link ox#Hex.Hex} values are equal, `false` otherwise.
*/
export function isEqual(hexA: Hex, hexB: Hex) {
- return equalBytes(Bytes.fromHex(hexA), Bytes.fromHex(hexB))
+ return equalBytes(hexToBytes(hexA), hexToBytes(hexB))
}
export declare namespace isEqual {
- type ErrorType = Bytes.fromHex.ErrorType | Errors.GlobalErrorType
+ type ErrorType = hexToBytes.ErrorType | Errors.GlobalErrorType
}
/**
@@ -411,7 +440,7 @@ export declare namespace padRight {
* @returns Random {@link ox#Hex.Hex} value.
*/
export function random(length: number): Hex {
- return fromBytes(Bytes.random(length))
+ return fromBytes(crypto.getRandomValues(new Uint8Array(length)))
}
export declare namespace random {
@@ -443,9 +472,21 @@ export function slice(
): Hex {
const { strict } = options
internal.assertStartOffset(value, start)
- const value_ = `0x${value
- .replace('0x', '')
- .slice((start ?? 0) * 2, (end ?? value.length) * 2)}` as const
+ let value_: Hex
+ if (end === undefined && (start === undefined || start >= 0)) {
+ // Non-negative-start, no-end fast path: avoid the intermediate
+ // `replace('0x', '')` / `slice(0, length)` allocation chain.
+ if (start === undefined || start === 0) value_ = value
+ else value_ = `0x${value.slice(2 + start * 2)}` as Hex
+ } else {
+ // Strip the `0x` prefix once and offset against the data (post-`0x`).
+ // Negative offsets fall through here (rare) so they can rely on
+ // `String.prototype.slice`'s negative-offset semantics.
+ const data = value.slice(2)
+ const startOffset = (start ?? 0) * 2
+ const endOffset = end !== undefined ? end * 2 : undefined
+ value_ = `0x${data.slice(startOffset, endOffset)}` as Hex
+ }
if (strict) internal.assertEndOffset(value_, start, end)
return value_
}
@@ -632,8 +673,14 @@ export declare namespace toBoolean {
* @param options - Options.
* @returns The decoded {@link ox#Bytes.Bytes}.
*/
-export function toBytes(hex: Hex, options: toBytes.Options = {}): Bytes.Bytes {
- return Bytes.fromHex(hex, options)
+export function toBytes(hex: Hex, options: toBytes.Options = {}): Uint8Array {
+ const { size } = options
+ let value = hex
+ if (typeof size === 'number') {
+ internal.assertSize(value, size)
+ value = padRight(value, size)
+ }
+ return hexToBytes(value)
}
export declare namespace toBytes {
@@ -642,7 +689,10 @@ export declare namespace toBytes {
size?: number | undefined
}
- type ErrorType = Bytes.fromHex.ErrorType | Errors.GlobalErrorType
+ type ErrorType =
+ | internal.assertSize.ErrorType
+ | hexToBytes.ErrorType
+ | Errors.GlobalErrorType
}
/**
@@ -706,12 +756,18 @@ export declare namespace toNumber {
export function toString(hex: Hex, options: toString.Options = {}): string {
const { size } = options
- let bytes = Bytes.fromHex(hex)
- if (size) {
- internal_bytes.assertSize(bytes, size)
- bytes = Bytes.trimRight(bytes)
- }
- return new TextDecoder().decode(bytes)
+ const bytes = hexToBytes(hex)
+ if (!size) return decoder.decode(bytes)
+
+ // Match legacy semantics: assert against bytes length so the thrown class
+ // matches `Bytes.SizeOverflowError` rather than `Hex.SizeOverflowError`.
+ if (bytes.length > size)
+ throw new BytesSizeOverflowError({ givenSize: bytes.length, maxSize: size })
+
+ // Trim trailing zero bytes when a `size` is given.
+ let end = bytes.length
+ while (end > 0 && bytes[end - 1] === 0) end--
+ return decoder.decode(bytes.subarray(0, end))
}
export declare namespace toString {
@@ -721,9 +777,8 @@ export declare namespace toString {
}
type ErrorType =
- | internal_bytes.assertSize.ErrorType
- | Bytes.fromHex.ErrorType
- | Bytes.trimRight.ErrorType
+ | internal.assertSize.ErrorType
+ | hexToBytes.ErrorType
| Errors.GlobalErrorType
}
@@ -770,37 +825,13 @@ export declare namespace validate {
/**
* Thrown when the provided integer is out of range, and cannot be represented as a hex value.
*
- * @example
- * ```ts twoslash
- * import { Hex } from 'ox'
- *
- * Hex.fromNumber(420182738912731283712937129)
- * // @error: Hex.IntegerOutOfRangeError: Number \`4.2018273891273126e+26\` is not in safe unsigned integer range (`0` to `9007199254740991`)
- * ```
+ * Re-exported from `internal/codec/int.ts` to break the `Bytes` <-> `Hex` runtime cycle.
*/
-export class IntegerOutOfRangeError extends Errors.BaseError {
- override readonly name = 'Hex.IntegerOutOfRangeError'
-
- constructor({
- max,
- min,
- signed,
- size,
- value,
- }: {
- max?: string | undefined
- min: string
- signed?: boolean | undefined
- size?: number | undefined
- value: string
- }) {
- super(
- `Number \`${value}\` is not in safe${
- size ? ` ${size * 8}-bit` : ''
- }${signed ? ' signed' : ' unsigned'} integer range ${max ? `(\`${min}\` to \`${max}\`)` : `(above \`${min}\`)`}`,
- )
- }
-}
+export const IntegerOutOfRangeError = IntegerOutOfRangeError_codec
+/** Re-exported from `internal/codec/int.ts`. */
+export type IntegerOutOfRangeError = InstanceType<
+ typeof IntegerOutOfRangeError_codec
+>
/**
* Thrown when the provided hex value cannot be represented as a boolean.
@@ -853,50 +884,22 @@ export class InvalidHexTypeError extends Errors.BaseError {
/**
* Thrown when the provided hex value is invalid.
*
- * @example
- * ```ts twoslash
- * import { Hex } from 'ox'
- *
- * Hex.assert('0x0123456789abcdefg')
- * // @error: Hex.InvalidHexValueError: Value `0x0123456789abcdefg` is an invalid hex value.
- * // @error: Hex values must start with `"0x"` and contain only hexadecimal characters (0-9, a-f, A-F).
- * ```
+ * Re-exported from `internal/codec/hex.ts` to break the `Bytes` <-> `Hex` runtime cycle.
*/
-export class InvalidHexValueError extends Errors.BaseError {
- override readonly name = 'Hex.InvalidHexValueError'
-
- constructor(value: unknown) {
- super(`Value \`${value}\` is an invalid hex value.`, {
- metaMessages: [
- 'Hex values must start with `"0x"` and contain only hexadecimal characters (0-9, a-f, A-F).',
- ],
- })
- }
-}
+export const InvalidHexValueError = InvalidHexValueError_codec
+/** Re-exported from `internal/codec/hex.ts`. */
+export type InvalidHexValueError = InstanceType<
+ typeof InvalidHexValueError_codec
+>
/**
* Thrown when the provided hex value is an odd length.
*
- * @example
- * ```ts twoslash
- * import { Bytes } from 'ox'
- *
- * Bytes.fromHex('0xabcde')
- * // @error: Hex.InvalidLengthError: Hex value `"0xabcde"` is an odd length (5 nibbles).
- * ```
+ * Re-exported from `internal/codec/hex.ts` to break the `Bytes` <-> `Hex` runtime cycle.
*/
-export class InvalidLengthError extends Errors.BaseError {
- override readonly name = 'Hex.InvalidLengthError'
-
- constructor(value: Hex) {
- super(
- `Hex value \`"${value}"\` is an odd length (${value.length - 2} nibbles).`,
- {
- metaMessages: ['It must be an even length.'],
- },
- )
- }
-}
+export const InvalidLengthError = InvalidLengthError_codec
+/** Re-exported from `internal/codec/hex.ts`. */
+export type InvalidLengthError = InstanceType
/**
* Thrown when the size of the value exceeds the expected max size.
diff --git a/src/core/Json.bench.ts b/src/core/Json.bench.ts
new file mode 100644
index 00000000..80ab45de
--- /dev/null
+++ b/src/core/Json.bench.ts
@@ -0,0 +1,65 @@
+import { bench, describe } from 'vitest'
+import * as Json from './Json.js'
+
+const small = { foo: 'bar', n: 42, ok: true }
+
+const medium = {
+ jsonrpc: '2.0',
+ id: 1,
+ result: {
+ blockNumber: '0x1a4',
+ transactions: Array.from({ length: 32 }, (_, i) => ({
+ hash: `0xfeed${i}`,
+ from: `0xabc${i}`,
+ to: `0xdef${i}`,
+ value: '0x0',
+ nonce: i,
+ })),
+ },
+}
+
+const withBigInt = {
+ ...small,
+ big: 12345678901234567890n,
+ arr: [1n, 2n, 3n, 4n, 5n],
+}
+
+const smallStr = JSON.stringify(small)
+const mediumStr = JSON.stringify(medium)
+const withBigIntStr = Json.stringify(withBigInt)
+
+describe('Json.parse (no bigint sentinel)', () => {
+ bench('small object', () => {
+ Json.parse(smallStr)
+ })
+ bench('medium object (32 txs)', () => {
+ Json.parse(mediumStr)
+ })
+})
+
+describe('Json.parse (with bigint sentinel)', () => {
+ bench('small object with bigint', () => {
+ Json.parse(withBigIntStr)
+ })
+})
+
+describe('Json.stringify', () => {
+ bench('small object', () => {
+ Json.stringify(small)
+ })
+ bench('medium object (32 txs)', () => {
+ Json.stringify(medium)
+ })
+ bench('object with bigint', () => {
+ Json.stringify(withBigInt)
+ })
+})
+
+describe('Json.canonicalize', () => {
+ bench('small object', () => {
+ Json.canonicalize(small)
+ })
+ bench('medium object (32 txs)', () => {
+ Json.canonicalize(medium)
+ })
+})
diff --git a/src/core/Json.ts b/src/core/Json.ts
index 7a976df0..d2dd7efe 100644
--- a/src/core/Json.ts
+++ b/src/core/Json.ts
@@ -96,6 +96,13 @@ export function parse(
string: string,
reviver?: ((this: any, key: string, value: any) => any) | undefined,
) {
+ // Fast path: when the bigint sentinel is absent, skip the reviver wrapper
+ // entirely. `JSON.parse` is dramatically faster without a reviver because
+ // engines avoid materializing intermediate values for every key.
+ if (!string.includes(bigIntSuffix)) {
+ if (typeof reviver === 'function') return JSON.parse(string, reviver)
+ return JSON.parse(string)
+ }
return JSON.parse(string, (key, value_) => {
const value = value_
if (typeof value === 'string' && value.endsWith(bigIntSuffix))
diff --git a/src/core/Log.bench.ts b/src/core/Log.bench.ts
new file mode 100644
index 00000000..ad3e9426
--- /dev/null
+++ b/src/core/Log.bench.ts
@@ -0,0 +1,53 @@
+import { bench, describe } from 'vitest'
+import * as Log from './Log.js'
+
+const baseRpc: Log.Rpc = {
+ address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
+ blockHash:
+ '0xabe69134e80a12f6a93d0aa18215b5b86c2fb338bae911790ca374a8716e01a4',
+ blockNumber: '0x12d846c',
+ data: '0x',
+ logIndex: '0x10f',
+ removed: false,
+ topics: [
+ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
+ '0x0000000000000000000000000c04d9e9278ec5e4d424476d3ebec70cb5d648d1',
+ '0x000000000000000000000000000000000000000000000000000000000000025b',
+ ],
+ transactionHash:
+ '0xcfa52db0bc2cb5bdcb2c5bd8816df7a2f018a0e3964ab1ef4d794cf327966e93',
+ transactionIndex: '0x91',
+}
+
+const parsed = Log.fromRpc(baseRpc)
+
+const batch10 = Array.from({ length: 10 }, () => baseRpc)
+const batch100 = Array.from({ length: 100 }, () => baseRpc)
+
+const parsed10 = batch10.map((log) => Log.fromRpc(log))
+const parsed100 = batch100.map((log) => Log.fromRpc(log))
+
+describe('Log.fromRpc', () => {
+ bench('single', () => {
+ Log.fromRpc(baseRpc)
+ })
+ bench('batch of 10', () => {
+ for (const log of batch10) Log.fromRpc(log)
+ })
+ bench('batch of 100', () => {
+ for (const log of batch100) Log.fromRpc(log)
+ })
+})
+
+describe('Log.toRpc', () => {
+ bench('single', () => {
+ Log.toRpc(parsed)
+ })
+ bench('batch of 10', () => {
+ for (const log of parsed10) Log.toRpc(log)
+ })
+ bench('batch of 100', () => {
+ for (const log of parsed100) Log.toRpc(log)
+ })
+})
diff --git a/src/core/Log.ts b/src/core/Log.ts
index 243e11ac..ca239390 100644
--- a/src/core/Log.ts
+++ b/src/core/Log.ts
@@ -1,6 +1,7 @@
import type * as Address from './Address.js'
import type * as Errors from './Errors.js'
-import * as Hex from './Hex.js'
+import type * as Hex from './Hex.js'
+import * as Quantity from './internal/quantity.js'
import type { Compute } from './internal/types.js'
/** A Log as defined in the [Execution API specification](https://github.com/ethereum/execution-apis/blob/main/src/schemas/receipt.yaml). */
@@ -144,11 +145,9 @@ export function fromRpc<
): Log {
return {
...log,
- blockNumber: log.blockNumber ? BigInt(log.blockNumber) : null,
- logIndex: log.logIndex ? Number(log.logIndex) : null,
- transactionIndex: log.transactionIndex
- ? Number(log.transactionIndex)
- : null,
+ blockNumber: Quantity.toBigInt(log.blockNumber) ?? null,
+ logIndex: Quantity.toNumber(log.logIndex) ?? null,
+ transactionIndex: Quantity.toNumber(log.transactionIndex) ?? null,
} as Log
}
@@ -214,19 +213,12 @@ export function toRpc<
return {
address: log.address,
blockHash: log.blockHash,
- blockNumber:
- typeof log.blockNumber === 'bigint'
- ? Hex.fromNumber(log.blockNumber)
- : null,
+ blockNumber: Quantity.fromBigInt(log.blockNumber) ?? null,
data: log.data,
- logIndex:
- typeof log.logIndex === 'number' ? Hex.fromNumber(log.logIndex) : null,
+ logIndex: Quantity.fromNumber(log.logIndex) ?? null,
topics: log.topics,
transactionHash: log.transactionHash,
- transactionIndex:
- typeof log.transactionIndex === 'number'
- ? Hex.fromNumber(log.transactionIndex)
- : null,
+ transactionIndex: Quantity.fromNumber(log.transactionIndex) ?? null,
removed: log.removed,
} as Rpc as never
}
diff --git a/src/core/Mnemonic.bench.ts b/src/core/Mnemonic.bench.ts
new file mode 100644
index 00000000..500d187c
--- /dev/null
+++ b/src/core/Mnemonic.bench.ts
@@ -0,0 +1,16 @@
+import { bench, describe } from 'vitest'
+import * as Mnemonic from './Mnemonic.js'
+
+const mnemonic = Mnemonic.random(Mnemonic.english)
+
+describe('Mnemonic.toSeed', () => {
+ bench('toSeed (sync, PBKDF2-HMAC-SHA512 x 2048)', () => {
+ Mnemonic.toSeed(mnemonic)
+ })
+})
+
+describe('Mnemonic.toPrivateKey', () => {
+ bench('toPrivateKey (default path)', () => {
+ Mnemonic.toPrivateKey(mnemonic)
+ })
+})
diff --git a/src/core/Provider.bench.ts b/src/core/Provider.bench.ts
new file mode 100644
index 00000000..14fe0250
--- /dev/null
+++ b/src/core/Provider.bench.ts
@@ -0,0 +1,31 @@
+import { bench, describe } from 'vitest'
+import * as Provider from './Provider.js'
+
+describe('Provider.createEmitter', () => {
+ bench('createEmitter()', () => {
+ Provider.createEmitter()
+ })
+})
+
+describe('Provider.parseError', () => {
+ const knownCodes = [
+ 4001, 4100, 4200, 4900, 4901, 4902, 5700, 5701, 5710, 5711, 5720, 5750,
+ ]
+ const errors = knownCodes.map((code) => ({
+ code: -32603,
+ message: 'Internal',
+ data: { code, message: 'inner' },
+ }))
+
+ bench('parseError(provider code rotating)', () => {
+ for (const error of errors) Provider.parseError(error)
+ })
+
+ bench('parseError(rpc code)', () => {
+ Provider.parseError({ code: -32000, message: 'oops' })
+ })
+
+ bench('parseError(plain Error)', () => {
+ Provider.parseError(new Error('boom'))
+ })
+})
diff --git a/src/core/Provider.ts b/src/core/Provider.ts
index fe43fedb..e558eec2 100644
--- a/src/core/Provider.ts
+++ b/src/core/Provider.ts
@@ -548,36 +548,36 @@ export function parseError<
if (!error_.data) return error_ as never
const { code } = error_.data as RpcResponse.ErrorObject
- if (code === DisconnectedError.code)
- return new DisconnectedError(error_) as never
- if (code === ChainDisconnectedError.code)
- return new ChainDisconnectedError(error_) as never
- if (code === UserRejectedRequestError.code)
- return new UserRejectedRequestError(error_) as never
- if (code === UnauthorizedError.code)
- return new UnauthorizedError(error_) as never
- if (code === UnsupportedMethodError.code)
- return new UnsupportedMethodError(error_) as never
- if (code === SwitchChainError.code)
- return new SwitchChainError(error_) as never
- if (code === AtomicReadyWalletRejectedUpgradeError.code)
- return new AtomicReadyWalletRejectedUpgradeError(error_) as never
- if (code === AtomicityNotSupportedError.code)
- return new AtomicityNotSupportedError(error_) as never
- if (code === BundleTooLargeError.code)
- return new BundleTooLargeError(error_) as never
- if (code === UnknownBundleIdError.code)
- return new UnknownBundleIdError(error_) as never
- if (code === DuplicateIdError.code)
- return new DuplicateIdError(error_) as never
- if (code === UnsupportedChainIdError.code)
- return new UnsupportedChainIdError(error_) as never
- if (code === UnsupportedNonOptionalCapabilityError.code)
- return new UnsupportedNonOptionalCapabilityError(error_) as never
+ const Constructor = providerErrorCodeMap[code]
+ if (Constructor) return new Constructor(error_) as never
}
return error_ as never
}
+/** @internal */
+const providerErrorCodeMap: Record<
+ number,
+ new (parameters: {
+ message?: string | undefined
+ }) => ProviderRpcError
+> = {
+ [DisconnectedError.code]: DisconnectedError,
+ [ChainDisconnectedError.code]: ChainDisconnectedError,
+ [UserRejectedRequestError.code]: UserRejectedRequestError,
+ [UnauthorizedError.code]: UnauthorizedError,
+ [UnsupportedMethodError.code]: UnsupportedMethodError,
+ [SwitchChainError.code]: SwitchChainError,
+ [AtomicReadyWalletRejectedUpgradeError.code]:
+ AtomicReadyWalletRejectedUpgradeError,
+ [AtomicityNotSupportedError.code]: AtomicityNotSupportedError,
+ [BundleTooLargeError.code]: BundleTooLargeError,
+ [UnknownBundleIdError.code]: UnknownBundleIdError,
+ [DuplicateIdError.code]: DuplicateIdError,
+ [UnsupportedChainIdError.code]: UnsupportedChainIdError,
+ [UnsupportedNonOptionalCapabilityError.code]:
+ UnsupportedNonOptionalCapabilityError,
+}
+
export declare namespace parseError {
type ReturnType<
errorObject extends RpcResponse.ErrorObject | unknown,
diff --git a/src/core/Rlp.bench.ts b/src/core/Rlp.bench.ts
new file mode 100644
index 00000000..87d85dc4
--- /dev/null
+++ b/src/core/Rlp.bench.ts
@@ -0,0 +1,73 @@
+import { bench, describe } from 'vitest'
+import * as Hex from './Hex.js'
+import * as Rlp from './Rlp.js'
+
+const empty = new Uint8Array()
+const small = new Uint8Array(32).map((_, i) => i)
+const medium = new Uint8Array(256).map((_, i) => i & 0xff)
+const large = new Uint8Array(4096).map((_, i) => i & 0xff)
+
+const flatList = [empty, small, small, small, small]
+const nestedList = [
+ small,
+ [small, small, small],
+ [[small, small], [small]],
+ medium,
+]
+
+const encodedSmall = Rlp.fromBytes(small)
+const encodedFlat = Rlp.fromBytes(flatList)
+const encodedNested = Rlp.fromBytes(nestedList)
+const encodedMedium = Rlp.fromBytes(medium)
+
+const encodedSmallHex = Rlp.fromBytes(small, { as: 'Hex' })
+const encodedFlatHex = Rlp.fromBytes(flatList, { as: 'Hex' })
+
+describe('Rlp.fromBytes (encode)', () => {
+ bench('single 32-byte string', () => {
+ Rlp.fromBytes(small)
+ })
+ bench('single 256-byte string', () => {
+ Rlp.fromBytes(medium)
+ })
+ bench('single 4096-byte string', () => {
+ Rlp.fromBytes(large)
+ })
+ bench('flat list of 5x 32-byte strings', () => {
+ Rlp.fromBytes(flatList)
+ })
+ bench('nested list', () => {
+ Rlp.fromBytes(nestedList)
+ })
+})
+
+describe('Rlp.toBytes (decode)', () => {
+ bench('single 32-byte string', () => {
+ Rlp.toBytes(encodedSmall)
+ })
+ bench('single 256-byte string', () => {
+ Rlp.toBytes(encodedMedium)
+ })
+ bench('flat list of 5x 32-byte strings', () => {
+ Rlp.toBytes(encodedFlat)
+ })
+ bench('nested list', () => {
+ Rlp.toBytes(encodedNested)
+ })
+})
+
+describe('Rlp.fromHex (encode)', () => {
+ const smallHex = Hex.fromBytes(small)
+ bench('single 32-byte string', () => {
+ Rlp.fromHex(smallHex)
+ })
+})
+
+describe('Rlp.toHex (decode)', () => {
+ bench('single 32-byte string', () => {
+ Rlp.toHex(encodedSmallHex)
+ })
+ bench('flat list of 5x 32-byte strings', () => {
+ Rlp.toHex(encodedFlatHex)
+ })
+})
diff --git a/src/core/Rlp.ts b/src/core/Rlp.ts
index 77334c79..e23eff81 100644
--- a/src/core/Rlp.ts
+++ b/src/core/Rlp.ts
@@ -1,6 +1,7 @@
import * as Bytes from './Bytes.js'
import * as Errors from './Errors.js'
import * as Hex from './Hex.js'
+import * as internal_bytes from './internal/bytes.js'
import * as Cursor from './internal/cursor.js'
import type { ExactPartial, RecursiveArray } from './internal/types.js'
@@ -161,11 +162,6 @@ export declare namespace readList {
type ErrorType = Errors.GlobalErrorType
}
-type Encodable = {
- length: number
- encode(cursor: Cursor.Cursor): void
-}
-
/**
* Encodes a {@link ox#Bytes.Bytes} or {@link ox#Hex.Hex} value into a Recursive-Length Prefix (RLP) value.
*
@@ -190,12 +186,35 @@ export function from(
): from.ReturnType {
const { as } = options
- const encodable = getEncodable(value)
- const cursor = Cursor.create(new Uint8Array(encodable.length))
- encodable.encode(cursor)
+ // Two-walk encode without the per-node `Encodable` closure tree:
+ // 1. `measure` walks the input once and caches each list's `bodyLength`
+ // in a side array indexed by visit order. This makes the second walk
+ // O(N) instead of O(N²) for nested inputs.
+ // 2. `writeEncoded` walks again, reads cached body lengths, and writes
+ // bytes straight into the pre-sized buffer. Hex leaves are
+ // nibble-decoded directly into the destination, skipping the per-leaf
+ // `Bytes.fromHex` allocation.
+ const ctx: EncodeCtx = { lengths: [], cursor: 0 }
+ const totalLength = measure(value, ctx)
+
+ // Hex-output fast path: when the caller asked for hex AND every leaf is
+ // already hex, emit a hex string directly instead of allocating an
+ // intermediate `Uint8Array` and round-tripping through `Hex.fromBytes`.
+ // This is the dominant shape for transaction envelope serialize.
+ if (as === 'Hex' && isAllHex(value)) {
+ const parts: string[] = []
+ writeEncodedHex(parts, value as RecursiveArray, {
+ lengths: ctx.lengths,
+ cursor: 0,
+ })
+ return `0x${parts.join('')}` as from.ReturnType
+ }
- if (as === 'Hex') return Hex.fromBytes(cursor.bytes) as from.ReturnType
- return cursor.bytes as from.ReturnType
+ const bytes = new Uint8Array(totalLength)
+ writeEncoded(bytes, 0, value, { lengths: ctx.lengths, cursor: 0 })
+
+ if (as === 'Hex') return Hex.fromBytes(bytes) as from.ReturnType
+ return bytes as from.ReturnType
}
export declare namespace from {
@@ -285,84 +304,315 @@ export declare namespace fromHex {
// Internal
/////////////////////////////////////////////////////////////////////////////////
-function getEncodable(
- bytes: RecursiveArray | RecursiveArray,
-): Encodable {
- if (Array.isArray(bytes))
- return getEncodableList(bytes.map((x) => getEncodable(x)))
- return getEncodableBytes(bytes as any)
+/**
+ * Returns the byte length needed to encode `length` itself (1-4 bytes per
+ * RLP), or throws when `length` exceeds the protocol cap.
+ */
+function getSizeOfLength(length: number) {
+ if (length <= 0xff) return 1
+ if (length <= 0xff_ff) return 2
+ if (length <= 0xff_ff_ff) return 3
+ if (length <= 0xff_ff_ff_ff) return 4
+ throw new Errors.BaseError('Length is too large.')
}
-function getEncodableList(list: Encodable[]): Encodable {
- const bodyLength = list.reduce((acc, x) => acc + x.length, 0)
+/**
+ * Side-channel used by `measure` and `writeEncoded` to share precomputed
+ * list body lengths. `lengths` is filled in pre-order (DFS) by `measure` and
+ * read back in the same order by `writeEncoded` via `cursor`. This avoids
+ * re-walking subtrees from `writeEncoded` (which would be O(N²) on nested
+ * inputs) without allocating a per-node `Encodable` closure tree.
+ */
+type EncodeCtx = { lengths: number[]; cursor: number }
- const sizeOfBodyLength = getSizeOfLength(bodyLength)
- const length = (() => {
+/**
+ * Walks `value` once, caches each list's `bodyLength` into `ctx.lengths`,
+ * and returns the total encoded byte length. Allocates nothing per node
+ * beyond the shared `lengths` array entries.
+ */
+function measure(
+ value: RecursiveArray | RecursiveArray,
+ ctx: EncodeCtx,
+): number {
+ if (Array.isArray(value)) {
+ // Reserve this list's slot before descending so children's slots come
+ // after ours; `writeEncoded` walks in the same order and reads slot N
+ // when it visits the Nth list.
+ const slot = ctx.lengths.length
+ ctx.lengths.push(0)
+ let bodyLength = 0
+ for (let i = 0; i < value.length; i++) bodyLength += measure(value[i]!, ctx)
+ ctx.lengths[slot] = bodyLength
if (bodyLength <= 55) return 1 + bodyLength
- return 1 + sizeOfBodyLength + bodyLength
- })()
-
- return {
- length,
- encode(cursor: Cursor.Cursor) {
- if (bodyLength <= 55) {
- cursor.pushByte(0xc0 + bodyLength)
- } else {
- cursor.pushByte(0xc0 + 55 + sizeOfBodyLength)
- if (sizeOfBodyLength === 1) cursor.pushUint8(bodyLength)
- else if (sizeOfBodyLength === 2) cursor.pushUint16(bodyLength)
- else if (sizeOfBodyLength === 3) cursor.pushUint24(bodyLength)
- else cursor.pushUint32(bodyLength)
- }
- for (const { encode } of list) {
- encode(cursor)
- }
- },
+ return 1 + getSizeOfLength(bodyLength) + bodyLength
}
+
+ // Hex leaf: byte length = ceil((hex.length - 2) / 2). The `>> 1` of
+ // `length - 1` yields ceil for both odd- and even-nibble inputs.
+ if (typeof value === 'string') {
+ const byteLen = (value.length - 1) >> 1
+ if (byteLen === 0) return 1
+ if (byteLen === 1) {
+ // Single-byte values < 0x80 encode as themselves (no prefix).
+ const odd = (value.length & 1) === 1
+ const firstChar = value.charCodeAt(odd ? 2 : 3)
+ const high = odd
+ ? 0
+ : (internal_bytes.charCodeToBase16(value.charCodeAt(2)) ?? 0) << 4
+ const low = internal_bytes.charCodeToBase16(firstChar) ?? 0
+ const byte = high | low
+ if (byte < 0x80) return 1
+ return 2
+ }
+ if (byteLen <= 55) return 1 + byteLen
+ return 1 + getSizeOfLength(byteLen) + byteLen
+ }
+
+ // Bytes leaf
+ const len = (value as Bytes.Bytes).length
+ if (len === 1 && (value as Bytes.Bytes)[0]! < 0x80) return 1
+ if (len <= 55) return 1 + len
+ return 1 + getSizeOfLength(len) + len
}
-function getEncodableBytes(bytesOrHex: Bytes.Bytes | Hex.Hex): Encodable {
- const bytes =
- typeof bytesOrHex === 'string'
- ? // Even-pad odd-length hex (e.g. `0x1`) before strict parsing.
- Bytes.fromHex(
- ((bytesOrHex.length & 1) === 1
- ? `0x0${bytesOrHex.slice(2)}`
- : bytesOrHex) as Hex.Hex,
- )
- : bytesOrHex
-
- const sizeOfBytesLength = getSizeOfLength(bytes.length)
- const length = (() => {
- if (bytes.length === 1 && bytes[0]! < 0x80) return 1
- if (bytes.length <= 55) return 1 + bytes.length
- return 1 + sizeOfBytesLength + bytes.length
- })()
-
- return {
- length,
- encode(cursor: Cursor.Cursor) {
- if (bytes.length === 1 && bytes[0]! < 0x80) {
- cursor.pushBytes(bytes)
- } else if (bytes.length <= 55) {
- cursor.pushByte(0x80 + bytes.length)
- cursor.pushBytes(bytes)
- } else {
- cursor.pushByte(0x80 + 55 + sizeOfBytesLength)
- if (sizeOfBytesLength === 1) cursor.pushUint8(bytes.length)
- else if (sizeOfBytesLength === 2) cursor.pushUint16(bytes.length)
- else if (sizeOfBytesLength === 3) cursor.pushUint24(bytes.length)
- else cursor.pushUint32(bytes.length)
- cursor.pushBytes(bytes)
- }
- },
+/**
+ * Writes `value`'s RLP encoding into `bytes` starting at `offset` and returns
+ * the next free offset. Reads list body lengths from `ctx.lengths` in the
+ * same DFS order that `measure` filled them. Hex leaves are nibble-decoded
+ * directly into the destination, skipping the per-leaf `Bytes.fromHex`
+ * allocation.
+ */
+function writeEncoded(
+ bytes: Uint8Array,
+ offset: number,
+ value: RecursiveArray | RecursiveArray,
+ ctx: EncodeCtx,
+): number {
+ if (Array.isArray(value)) {
+ const bodyLength = ctx.lengths[ctx.cursor++]!
+
+ let cursor = offset
+ if (bodyLength <= 55) {
+ bytes[cursor++] = 0xc0 + bodyLength
+ } else {
+ const sizeOfBodyLength = getSizeOfLength(bodyLength)
+ bytes[cursor++] = 0xc0 + 55 + sizeOfBodyLength
+ cursor = writeBigEndian(bytes, cursor, bodyLength, sizeOfBodyLength)
+ }
+ for (let i = 0; i < value.length; i++)
+ cursor = writeEncoded(bytes, cursor, value[i]!, ctx)
+ return cursor
}
+
+ if (typeof value === 'string') return writeHexLeaf(bytes, offset, value)
+
+ return writeBytesLeaf(bytes, offset, value as Bytes.Bytes)
}
-function getSizeOfLength(length: number) {
- if (length <= 0xff) return 1
- if (length <= 0xff_ff) return 2
- if (length <= 0xff_ff_ff) return 3
- if (length <= 0xff_ff_ff_ff) return 4
- throw new Errors.BaseError('Length is too large.')
+/**
+ * Hex-leaf fast path: writes the RLP encoding of a hex string directly into
+ * `bytes` by nibble-decoding the source hex chars into the destination
+ * buffer. Even-pads odd-nibble hex (e.g. `'0x1'`) on the fly.
+ */
+function writeHexLeaf(bytes: Uint8Array, offset: number, hex: Hex.Hex): number {
+ const dataStart = 2
+ let byteLen = (hex.length - 2) >> 1
+ let highNibbleFromOddPad = false
+ if ((hex.length & 1) === 1) {
+ // Odd-nibble: first emitted byte's high nibble is `0` (left-pad).
+ byteLen += 1
+ highNibbleFromOddPad = true
+ }
+
+ // Empty leaf -> single 0x80 prefix byte (zero-length string in RLP).
+ if (byteLen === 0) {
+ bytes[offset] = 0x80
+ return offset + 1
+ }
+
+ // Single-byte fast path: if the byte < 0x80, write it as-is (no prefix).
+ if (byteLen === 1) {
+ let byte: number
+ if (highNibbleFromOddPad) {
+ byte = internal_bytes.charCodeToBase16(hex.charCodeAt(dataStart)) ?? 0
+ } else {
+ const high =
+ internal_bytes.charCodeToBase16(hex.charCodeAt(dataStart)) ?? 0
+ const low =
+ internal_bytes.charCodeToBase16(hex.charCodeAt(dataStart + 1)) ?? 0
+ byte = (high << 4) | low
+ }
+ if (byte < 0x80) {
+ bytes[offset] = byte
+ return offset + 1
+ }
+ bytes[offset] = 0x80 + 1
+ bytes[offset + 1] = byte
+ return offset + 2
+ }
+
+ let dest = offset
+ if (byteLen <= 55) {
+ bytes[dest++] = 0x80 + byteLen
+ } else {
+ const sizeOfBytesLength = getSizeOfLength(byteLen)
+ bytes[dest++] = 0x80 + 55 + sizeOfBytesLength
+ dest = writeBigEndian(bytes, dest, byteLen, sizeOfBytesLength)
+ }
+
+ // Decode hex nibbles directly into the destination buffer.
+ let src = dataStart
+ if (highNibbleFromOddPad) {
+ const low = internal_bytes.charCodeToBase16(hex.charCodeAt(src++))
+ if (low === undefined) throw invalidNibble(hex)
+ bytes[dest++] = low
+ }
+ while (src < hex.length) {
+ const high = internal_bytes.charCodeToBase16(hex.charCodeAt(src++))
+ const low = internal_bytes.charCodeToBase16(hex.charCodeAt(src++))
+ if (high === undefined || low === undefined) throw invalidNibble(hex)
+ bytes[dest++] = (high << 4) | low
+ }
+ return dest
+}
+
+function writeBytesLeaf(
+ bytes: Uint8Array,
+ offset: number,
+ leaf: Bytes.Bytes,
+): number {
+ const len = leaf.length
+
+ if (len === 1 && leaf[0]! < 0x80) {
+ bytes[offset] = leaf[0]!
+ return offset + 1
+ }
+
+ let dest = offset
+ if (len <= 55) {
+ bytes[dest++] = 0x80 + len
+ } else {
+ const sizeOfBytesLength = getSizeOfLength(len)
+ bytes[dest++] = 0x80 + 55 + sizeOfBytesLength
+ dest = writeBigEndian(bytes, dest, len, sizeOfBytesLength)
+ }
+ bytes.set(leaf, dest)
+ return dest + len
+}
+
+/**
+ * Returns true if every leaf in the (possibly nested) input is a hex string.
+ * Used to gate the hex-output fast path in `from`.
+ */
+function isAllHex(
+ value: RecursiveArray | RecursiveArray,
+): boolean {
+ if (Array.isArray(value)) {
+ for (let i = 0; i < value.length; i++)
+ if (!isAllHex(value[i]!)) return false
+ return true
+ }
+ return typeof value === 'string'
+}
+
+/**
+ * Hex-output fast path: writes the RLP encoding of `value` directly as hex
+ * substrings into `parts`. Avoids the intermediate `Uint8Array` allocation
+ * (and the trailing `Hex.fromBytes` round-trip) used by the bytes path.
+ *
+ * Length-prefix bytes are formatted via the cached `hexes[]` table so we
+ * never call `toString(16)` per node.
+ */
+function writeEncodedHex(
+ parts: string[],
+ value: RecursiveArray,
+ ctx: EncodeCtx,
+): void {
+ if (Array.isArray(value)) {
+ const bodyLength = ctx.lengths[ctx.cursor++]!
+ if (bodyLength <= 55) {
+ parts.push(hexes[0xc0 + bodyLength]!)
+ } else {
+ const sizeOfBodyLength = getSizeOfLength(bodyLength)
+ parts.push(hexes[0xc0 + 55 + sizeOfBodyLength]!)
+ parts.push(bigEndianHex(bodyLength, sizeOfBodyLength))
+ }
+ for (let i = 0; i < value.length; i++)
+ writeEncodedHex(parts, value[i]!, ctx)
+ return
+ }
+
+ // Hex leaf: even-pad odd-nibble inputs and skip the `0x` prefix.
+ const hex = value as string
+ const odd = (hex.length & 1) === 1
+ const body = odd ? `0${hex.slice(2)}` : hex.slice(2)
+ const byteLen = body.length >> 1
+
+ if (byteLen === 0) {
+ parts.push(hexes[0x80]!)
+ return
+ }
+ if (byteLen === 1) {
+ const byte = parseInt(body, 16)
+ if (byte < 0x80) {
+ parts.push(body)
+ } else {
+ parts.push(hexes[0x81]!)
+ parts.push(body)
+ }
+ return
+ }
+ if (byteLen <= 55) {
+ parts.push(hexes[0x80 + byteLen]!)
+ parts.push(body)
+ return
+ }
+ const sizeOfBytesLength = getSizeOfLength(byteLen)
+ parts.push(hexes[0x80 + 55 + sizeOfBytesLength]!)
+ parts.push(bigEndianHex(byteLen, sizeOfBytesLength))
+ parts.push(body)
+}
+
+const hexes = /*#__PURE__*/ Array.from({ length: 256 }, (_v, i) =>
+ i.toString(16).padStart(2, '0'),
+)
+
+/**
+ * Returns the big-endian hex encoding of `value` in `size` bytes.
+ */
+function bigEndianHex(value: number, size: number): string {
+ if (size === 1) return hexes[value & 0xff]!
+ if (size === 2)
+ return `${hexes[(value >>> 8) & 0xff]!}${hexes[value & 0xff]!}`
+ if (size === 3)
+ return `${hexes[(value >>> 16) & 0xff]!}${hexes[(value >>> 8) & 0xff]!}${hexes[value & 0xff]!}`
+ return `${hexes[(value >>> 24) & 0xff]!}${hexes[(value >>> 16) & 0xff]!}${hexes[(value >>> 8) & 0xff]!}${hexes[value & 0xff]!}`
+}
+
+function writeBigEndian(
+ bytes: Uint8Array,
+ offset: number,
+ value: number,
+ size: number,
+): number {
+ if (size === 1) {
+ bytes[offset] = value & 0xff
+ } else if (size === 2) {
+ bytes[offset] = (value >>> 8) & 0xff
+ bytes[offset + 1] = value & 0xff
+ } else if (size === 3) {
+ bytes[offset] = (value >>> 16) & 0xff
+ bytes[offset + 1] = (value >>> 8) & 0xff
+ bytes[offset + 2] = value & 0xff
+ } else {
+ bytes[offset] = (value >>> 24) & 0xff
+ bytes[offset + 1] = (value >>> 16) & 0xff
+ bytes[offset + 2] = (value >>> 8) & 0xff
+ bytes[offset + 3] = value & 0xff
+ }
+ return offset + size
+}
+
+function invalidNibble(hex: Hex.Hex): Errors.BaseError {
+ return new Errors.BaseError(`Invalid hex string \`${hex}\`.`)
}
diff --git a/src/core/Rlp_tx.bench.ts b/src/core/Rlp_tx.bench.ts
new file mode 100644
index 00000000..46030ba7
--- /dev/null
+++ b/src/core/Rlp_tx.bench.ts
@@ -0,0 +1,97 @@
+// Track B / transactions: bench coverage for the RLP encode/decode hot
+// paths exercised by every TxEnvelope codec. The encoding thread owns
+// codec-only bench naming under `src/core/Rlp.bench.ts`; this file scopes
+// to transaction-shaped inputs to avoid collision.
+
+import { bench, describe } from 'vitest'
+import * as Hex from './Hex.js'
+import * as Rlp from './Rlp.js'
+
+// Mirrors the EIP-1559 tuple shape (12 elements: 9 base + 3 signature).
+const eip1559Tuple = [
+ '0x01',
+ '0x',
+ '0x3b9aca00',
+ '0x6fc23ac0',
+ '0x5208',
+ '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ '0x0de0b6b3a7640000',
+ '0x',
+ [],
+ '0x01',
+ '0xa0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0',
+ '0xb0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0',
+] as const
+
+const eip1559TupleHex = Rlp.fromHex(eip1559Tuple as never, { as: 'Hex' })
+
+// Larger 7702-shaped tuple with an access list and authorization list of
+// modest size (2 entries each).
+const eip7702Tuple = [
+ '0x01',
+ '0x10',
+ '0x3b9aca00',
+ '0x6fc23ac0',
+ '0x5208',
+ '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ '0x0de0b6b3a7640000',
+ '0x',
+ [
+ [
+ '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ [
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
+ ],
+ ],
+ ],
+ [
+ [
+ '0x01',
+ '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ '0x',
+ '0x01',
+ '0xa1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1',
+ '0xb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1',
+ ],
+ ],
+ '0x01',
+ '0xa0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0',
+ '0xb0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0',
+] as const
+
+const eip7702TupleHex = Rlp.fromHex(eip7702Tuple as never, { as: 'Hex' })
+
+describe('Rlp.fromHex (transaction-shaped)', () => {
+ bench('eip1559 tuple', () => {
+ Rlp.fromHex(eip1559Tuple as never, { as: 'Hex' })
+ })
+
+ bench('eip7702 tuple (with access + authorization lists)', () => {
+ Rlp.fromHex(eip7702Tuple as never, { as: 'Hex' })
+ })
+})
+
+describe('Rlp.toHex (transaction-shaped)', () => {
+ bench('eip1559 tuple', () => {
+ Rlp.toHex(eip1559TupleHex)
+ })
+
+ bench('eip7702 tuple (with access + authorization lists)', () => {
+ Rlp.toHex(eip7702TupleHex)
+ })
+})
+
+describe('Rlp.toBytes (transaction-shaped)', () => {
+ bench('eip1559 tuple', () => {
+ Rlp.toBytes(eip1559TupleHex)
+ })
+
+ bench('eip7702 tuple (with access + authorization lists)', () => {
+ Rlp.toBytes(eip7702TupleHex)
+ })
+})
+
+// Sanity-check: keep the Hex import live so the file remains valid even if
+// the bench list is trimmed.
+void Hex.size
diff --git a/src/core/RpcRequest.bench.ts b/src/core/RpcRequest.bench.ts
new file mode 100644
index 00000000..4eeb214d
--- /dev/null
+++ b/src/core/RpcRequest.bench.ts
@@ -0,0 +1,41 @@
+import { bench, describe } from 'vitest'
+import * as RpcRequest from './RpcRequest.js'
+
+describe('RpcRequest.createStore: prepare', () => {
+ const store = RpcRequest.createStore()
+
+ bench('prepare(no params)', () => {
+ store.prepare({ method: 'eth_blockNumber' })
+ })
+
+ bench('prepare(with params)', () => {
+ store.prepare({
+ method: 'eth_call',
+ params: [
+ {
+ to: '0x0000000000000000000000000000000000000000',
+ data: '0xdeadbeef',
+ },
+ ],
+ } as never)
+ })
+})
+
+describe('RpcRequest.from', () => {
+ bench('from(no params)', () => {
+ RpcRequest.from({ id: 0, method: 'eth_blockNumber' })
+ })
+
+ bench('from(with params)', () => {
+ RpcRequest.from({
+ id: 0,
+ method: 'eth_call',
+ params: [
+ {
+ to: '0x0000000000000000000000000000000000000000',
+ data: '0xdeadbeef',
+ },
+ ],
+ } as never)
+ })
+})
diff --git a/src/core/RpcRequest.ts b/src/core/RpcRequest.ts
index c82f106d..5c68c41a 100644
--- a/src/core/RpcRequest.ts
+++ b/src/core/RpcRequest.ts
@@ -107,10 +107,7 @@ export function createStore<
let id = options.id ?? 0
return {
prepare(options) {
- return from({
- id: id++,
- ...options,
- } as never) as never
+ return { id: id++, ...options, jsonrpc: '2.0' } as never
},
get id() {
return id
diff --git a/src/core/RpcResponse.bench.ts b/src/core/RpcResponse.bench.ts
new file mode 100644
index 00000000..4e4d675f
--- /dev/null
+++ b/src/core/RpcResponse.bench.ts
@@ -0,0 +1,65 @@
+import { bench, describe } from 'vitest'
+import * as RpcRequest from './RpcRequest.js'
+import * as RpcResponse from './RpcResponse.js'
+
+const successResponse = {
+ id: 0,
+ jsonrpc: '2.0',
+ result: '0x1a2b3c',
+} as const
+
+const errorResponse = {
+ id: 0,
+ jsonrpc: '2.0',
+ error: { code: -32000, message: 'oops' },
+} as const
+
+describe('RpcResponse.parse', () => {
+ bench('parse(success)', () => {
+ RpcResponse.parse(successResponse)
+ })
+
+ bench('parse(success, raw)', () => {
+ RpcResponse.parse(successResponse, { raw: true })
+ })
+
+ bench('parse(error, raw)', () => {
+ RpcResponse.parse(errorResponse, { raw: true })
+ })
+})
+
+describe('RpcResponse.from', () => {
+ const request = RpcRequest.from({ id: 1, method: 'eth_blockNumber' })
+
+ bench('from(complete envelope)', () => {
+ RpcResponse.from(successResponse, { request })
+ })
+
+ bench('from(missing id+jsonrpc)', () => {
+ RpcResponse.from({ result: '0x1' } as never, { request })
+ })
+
+ bench('from(no request, complete)', () => {
+ RpcResponse.from(successResponse)
+ })
+})
+
+describe('RpcResponse.parseError', () => {
+ const knownCodes = [
+ -32000, -32001, -32002, -32003, -32004, -32005, -32006, -32600, -32601,
+ -32602, -32603, -32700,
+ ]
+ const errors = knownCodes.map((code) => ({ code, message: 'm' }))
+
+ bench('parseError(known code rotating)', () => {
+ for (const error of errors) RpcResponse.parseError(error)
+ })
+
+ bench('parseError(unknown code)', () => {
+ RpcResponse.parseError({ code: 9999, message: 'unknown' })
+ })
+
+ bench('parseError(plain Error)', () => {
+ RpcResponse.parseError(new Error('boom'))
+ })
+})
diff --git a/src/core/RpcResponse.ts b/src/core/RpcResponse.ts
index a8050a62..2235ce15 100644
--- a/src/core/RpcResponse.ts
+++ b/src/core/RpcResponse.ts
@@ -76,12 +76,15 @@ export function from<
// eslint-disable-next-line jsdoc/require-jsdoc
export function from(response: RpcResponse, options: any = {}): RpcResponse {
const { request } = options
- if (request)
- return {
- ...response,
- id: response.id ?? request.id,
- jsonrpc: response.jsonrpc ?? request.jsonrpc,
- }
+ if (request) {
+ const needsId = response.id === undefined
+ const needsJsonrpc = response.jsonrpc === undefined
+ if (!needsId && !needsJsonrpc) return response
+ if (needsId && needsJsonrpc)
+ return { ...response, id: request.id, jsonrpc: request.jsonrpc }
+ if (needsId) return { ...response, id: request.id }
+ return { ...response, jsonrpc: request.jsonrpc }
+ }
if (response.id === undefined || response.jsonrpc === undefined)
throw new ParseError({ message: 'Invalid JSON-RPC response.' })
return response
@@ -307,30 +310,9 @@ export function parseError(
stack: error_.stack,
}) as never
- const { code } = error_
- if (code === InternalError.code)
- return new InternalError(error_ as never) as never
- if (code === InvalidInputError.code)
- return new InvalidInputError(error_) as never
- if (code === InvalidParamsError.code)
- return new InvalidParamsError(error_) as never
- if (code === InvalidRequestError.code)
- return new InvalidRequestError(error_) as never
- if (code === LimitExceededError.code)
- return new LimitExceededError(error_) as never
- if (code === MethodNotFoundError.code)
- return new MethodNotFoundError(error_) as never
- if (code === MethodNotSupportedError.code)
- return new MethodNotSupportedError(error_) as never
- if (code === ParseError.code) return new ParseError(error_) as never
- if (code === ResourceNotFoundError.code)
- return new ResourceNotFoundError(error_) as never
- if (code === ResourceUnavailableError.code)
- return new ResourceUnavailableError(error_) as never
- if (code === TransactionRejectedError.code)
- return new TransactionRejectedError(error_) as never
- if (code === VersionNotSupportedError.code)
- return new VersionNotSupportedError(error_) as never
+ const code = (error_ as ErrorObject).code
+ const Constructor = errorCodeMap[code]
+ if (Constructor) return new Constructor(error_ as never) as never
return new InternalError({
cause: error_ instanceof Error ? error_ : undefined,
data: error_,
@@ -638,3 +620,24 @@ export class ParseError extends BaseError {
})
}
}
+
+/** @internal */
+const errorCodeMap: Record<
+ number,
+ new (
+ parameters: Partial>,
+ ) => BaseError
+> = {
+ [InternalError.code]: InternalError as never,
+ [InvalidInputError.code]: InvalidInputError,
+ [InvalidParamsError.code]: InvalidParamsError,
+ [InvalidRequestError.code]: InvalidRequestError,
+ [LimitExceededError.code]: LimitExceededError,
+ [MethodNotFoundError.code]: MethodNotFoundError,
+ [MethodNotSupportedError.code]: MethodNotSupportedError,
+ [ParseError.code]: ParseError,
+ [ResourceNotFoundError.code]: ResourceNotFoundError,
+ [ResourceUnavailableError.code]: ResourceUnavailableError,
+ [TransactionRejectedError.code]: TransactionRejectedError,
+ [VersionNotSupportedError.code]: VersionNotSupportedError,
+}
diff --git a/src/core/RpcTransport.bench.ts b/src/core/RpcTransport.bench.ts
new file mode 100644
index 00000000..3fbc5078
--- /dev/null
+++ b/src/core/RpcTransport.bench.ts
@@ -0,0 +1,42 @@
+import { bench, describe } from 'vitest'
+import * as RpcTransport from './RpcTransport.js'
+
+const jsonHeaders = new Headers({ 'Content-Type': 'application/json' })
+
+const mockFetch = (async () => {
+ return new Response(
+ JSON.stringify({ id: 0, jsonrpc: '2.0', result: '0x1a2b3c' }),
+ { status: 200, headers: jsonHeaders },
+ )
+}) as typeof fetch
+
+describe('RpcTransport.fromHttp', () => {
+ const transport = RpcTransport.fromHttp('https://example.com', {
+ fetchFn: mockFetch,
+ })
+
+ bench('request(no params)', async () => {
+ await transport.request({ method: 'eth_blockNumber' })
+ })
+
+ bench('request(with params)', async () => {
+ await transport.request({
+ method: 'eth_call',
+ params: [
+ {
+ to: '0x0000000000000000000000000000000000000000',
+ data: '0xdeadbeef',
+ },
+ ],
+ } as never)
+ })
+
+ const rawTransport = RpcTransport.fromHttp('https://example.com', {
+ fetchFn: mockFetch,
+ raw: true,
+ })
+
+ bench('request(raw)', async () => {
+ await rawTransport.request({ method: 'eth_blockNumber' })
+ })
+})
diff --git a/src/core/RpcTransport.ts b/src/core/RpcTransport.ts
index 8b751ba2..bf0557ed 100644
--- a/src/core/RpcTransport.ts
+++ b/src/core/RpcTransport.ts
@@ -118,8 +118,7 @@ export function fromHttp<
method: fetchOptions?.method ?? 'POST',
signal: composedSignal,
}
- const request = new Request(url, init)
- return fetchFn(request)
+ return fetchFn(url, init)
},
{
timeout,
diff --git a/src/core/Signature.bench.ts b/src/core/Signature.bench.ts
new file mode 100644
index 00000000..95db4fd7
--- /dev/null
+++ b/src/core/Signature.bench.ts
@@ -0,0 +1,56 @@
+import { bench, describe } from 'vitest'
+import * as Secp256k1 from './Secp256k1.js'
+import * as Signature from './Signature.js'
+
+const privateKey =
+ '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' as const
+const payload =
+ '0x0000000000000000000000000000000000000000000000000000000000000123' as const
+const publicKey = Secp256k1.getPublicKey({ privateKey })
+const signature = Secp256k1.sign({ payload, privateKey })
+
+const tuple = Signature.toTuple(signature)
+const recoveredBytes = Signature.toRecoveredBytes(signature)
+const compactBytes = Signature.toCompactBytes(signature)
+
+describe('Signature.fromTuple', () => {
+ bench('default', () => {
+ Signature.fromTuple(tuple)
+ })
+})
+
+describe('Signature.toTuple', () => {
+ bench('default', () => {
+ Signature.toTuple(signature)
+ })
+})
+
+describe('Signature.toRecoveredBytes / fromRecoveredBytes', () => {
+ bench('toRecoveredBytes', () => {
+ Signature.toRecoveredBytes(signature)
+ })
+
+ bench('fromRecoveredBytes', () => {
+ Signature.fromRecoveredBytes(recoveredBytes)
+ })
+})
+
+describe('Signature.toCompactBytes / fromCompactBytes', () => {
+ bench('toCompactBytes', () => {
+ Signature.toCompactBytes(signature)
+ })
+
+ bench('fromCompactBytes', () => {
+ Signature.fromCompactBytes(compactBytes)
+ })
+})
+
+describe('Secp256k1.sign + verify', () => {
+ bench('sign', () => {
+ Secp256k1.sign({ payload, privateKey })
+ })
+
+ bench('verify (publicKey)', () => {
+ Secp256k1.verify({ payload, publicKey, signature })
+ })
+})
diff --git a/src/core/Signature.ts b/src/core/Signature.ts
index d8e0edf7..13546ce7 100644
--- a/src/core/Signature.ts
+++ b/src/core/Signature.ts
@@ -461,15 +461,20 @@ export declare namespace fromRpc {
*/
export function fromTuple(tuple: Tuple): Signature {
const [yParity, r, s] = tuple
- return from({
+ // Construct directly without routing through `from()` so we skip its runtime
+ // type discrimination on every TxEnvelope decode. `assert` still validates
+ // the result.
+ const sig: Signature = {
r: r === '0x' ? 0n : BigInt(r),
s: s === '0x' ? 0n : BigInt(s),
yParity: yParity === '0x' ? 0 : Number(yParity),
- })
+ }
+ assert(sig)
+ return sig
}
export declare namespace fromTuple {
- type ErrorType = from.ErrorType | Errors.GlobalErrorType
+ type ErrorType = assert.ErrorType | Errors.GlobalErrorType
}
/**
@@ -501,6 +506,122 @@ export declare namespace toBytes {
| Errors.GlobalErrorType
}
+/**
+ * Encodes a {@link ox#Signature.Signature} as a 64-byte compact byte
+ * representation (`r ++ s`, big-endian, 32 bytes each).
+ *
+ * Used for signature inputs that omit the recovery byte (e.g. ECDSA verify).
+ *
+ * @example
+ * ```ts twoslash
+ * import { Signature } from 'ox'
+ *
+ * const bytes = Signature.toCompactBytes({
+ * r: 49782753348462494199823712700004552394425719014458918871452329774910450607807n,
+ * s: 33726695977844476214676913201140481102225469284307016937915595756355928419768n,
+ * yParity: 1,
+ * })
+ * // @log: Uint8Array [110, 16, 10, ...] // 64 bytes
+ * ```
+ *
+ * @param signature - The signature to encode.
+ * @returns The 64-byte compact representation.
+ */
+export function toCompactBytes(signature: Signature): Bytes.Bytes {
+ const bytes = new Uint8Array(64)
+ bytes.set(Bytes.fromNumber(signature.r, { size: 32 }), 0)
+ bytes.set(Bytes.fromNumber(signature.s, { size: 32 }), 32)
+ return bytes
+}
+
+export declare namespace toCompactBytes {
+ type ErrorType = Bytes.fromNumber.ErrorType | Errors.GlobalErrorType
+}
+
+/**
+ * Decodes a 64-byte compact byte representation (`r ++ s`, big-endian) into a
+ * {@link ox#Signature.Signature} (without recovery).
+ *
+ * @example
+ * ```ts twoslash
+ * import { Signature } from 'ox'
+ *
+ * const signature = Signature.fromCompactBytes(new Uint8Array(64))
+ * // @log: { r: 0n, s: 0n }
+ * ```
+ *
+ * @param bytes - The 64-byte compact representation.
+ * @returns The decoded {@link ox#Signature.Signature}.
+ */
+export function fromCompactBytes(bytes: Bytes.Bytes): Signature {
+ return {
+ r: Bytes.toBigInt(bytes.subarray(0, 32)),
+ s: Bytes.toBigInt(bytes.subarray(32, 64)),
+ }
+}
+
+export declare namespace fromCompactBytes {
+ type ErrorType = Bytes.toBigInt.ErrorType | Errors.GlobalErrorType
+}
+
+/**
+ * Encodes a {@link ox#Signature.Signature} as a 65-byte recovered byte
+ * representation (`yParity ++ r ++ s`, big-endian).
+ *
+ * @example
+ * ```ts twoslash
+ * import { Signature } from 'ox'
+ *
+ * const bytes = Signature.toRecoveredBytes({
+ * r: 49782753348462494199823712700004552394425719014458918871452329774910450607807n,
+ * s: 33726695977844476214676913201140481102225469284307016937915595756355928419768n,
+ * yParity: 1,
+ * })
+ * // @log: Uint8Array [1, 110, 16, ...] // 65 bytes
+ * ```
+ *
+ * @param signature - The signature to encode.
+ * @returns The 65-byte recovered representation.
+ */
+export function toRecoveredBytes(signature: Signature): Bytes.Bytes {
+ const bytes = new Uint8Array(65)
+ bytes[0] = signature.yParity
+ bytes.set(Bytes.fromNumber(signature.r, { size: 32 }), 1)
+ bytes.set(Bytes.fromNumber(signature.s, { size: 32 }), 33)
+ return bytes
+}
+
+export declare namespace toRecoveredBytes {
+ type ErrorType = Bytes.fromNumber.ErrorType | Errors.GlobalErrorType
+}
+
+/**
+ * Decodes a 65-byte recovered byte representation (`yParity ++ r ++ s`,
+ * big-endian) into a {@link ox#Signature.Signature}.
+ *
+ * @example
+ * ```ts twoslash
+ * import { Signature } from 'ox'
+ *
+ * const signature = Signature.fromRecoveredBytes(new Uint8Array(65))
+ * // @log: { r: 0n, s: 0n, yParity: 0 }
+ * ```
+ *
+ * @param bytes - The 65-byte recovered representation.
+ * @returns The decoded {@link ox#Signature.Signature}.
+ */
+export function fromRecoveredBytes(bytes: Bytes.Bytes): Signature {
+ return {
+ r: Bytes.toBigInt(bytes.subarray(1, 33)),
+ s: Bytes.toBigInt(bytes.subarray(33, 65)),
+ yParity: bytes[0]!,
+ }
+}
+
+export declare namespace fromRecoveredBytes {
+ type ErrorType = Bytes.toBigInt.ErrorType | Errors.GlobalErrorType
+}
+
/**
* Serializes a {@link ox#Signature.Signature} to {@link ox#Hex.Hex}.
*
@@ -677,18 +798,17 @@ export declare namespace toRpc {
export function toTuple(signature: Signature): Tuple {
const { r, s, yParity } = signature
+ // Skip the `Hex.fromNumber` + `Hex.trimLeft` round-trip used by previous
+ // versions; bigint -> minimal hex is already what RLP wants.
return [
yParity ? '0x01' : '0x',
- r === 0n ? '0x' : Hex.trimLeft(Hex.fromNumber(r!)),
- s === 0n ? '0x' : Hex.trimLeft(Hex.fromNumber(s!)),
+ r === 0n ? '0x' : (`0x${r.toString(16)}` as Hex.Hex),
+ s === 0n ? '0x' : (`0x${s.toString(16)}` as Hex.Hex),
] as const
}
export declare namespace toTuple {
- type ErrorType =
- | Hex.trimLeft.ErrorType
- | Hex.fromNumber.ErrorType
- | Errors.GlobalErrorType
+ type ErrorType = Errors.GlobalErrorType
}
/**
diff --git a/src/core/StateOverrides.ts b/src/core/StateOverrides.ts
index 2850b98a..09870d8a 100644
--- a/src/core/StateOverrides.ts
+++ b/src/core/StateOverrides.ts
@@ -76,18 +76,14 @@ export function fromRpc(rpcStateOverrides: Rpc): StateOverrides {
)) {
const accountOverrides: AccountOverrides = {}
if (accountOverridesRpc.balance !== undefined)
- accountOverrides.balance = Quantity.toBigInt(
- accountOverridesRpc.balance,
- )
+ accountOverrides.balance = Quantity.toBigInt(accountOverridesRpc.balance)
if (accountOverridesRpc.code)
accountOverrides.code = accountOverridesRpc.code
if (accountOverridesRpc.movePrecompileToAddress)
accountOverrides.movePrecompileToAddress =
accountOverridesRpc.movePrecompileToAddress
if (accountOverridesRpc.nonce !== undefined)
- accountOverrides.nonce = Quantity.toBigInt(
- accountOverridesRpc.nonce,
- )
+ accountOverrides.nonce = Quantity.toBigInt(accountOverridesRpc.nonce)
if (accountOverridesRpc.state)
accountOverrides.state = accountOverridesRpc.state
if (accountOverridesRpc.stateDiff)
@@ -127,9 +123,7 @@ export function toRpc(stateOverrides: StateOverrides): Rpc {
accountOverridesRpc.movePrecompileToAddress =
accountOverrides.movePrecompileToAddress
if (typeof accountOverrides.nonce === 'bigint')
- accountOverridesRpc.nonce = Quantity.fromBigInt(
- accountOverrides.nonce,
- )
+ accountOverridesRpc.nonce = Quantity.fromBigInt(accountOverrides.nonce)
if (accountOverrides.state)
accountOverridesRpc.state = accountOverrides.state
if (accountOverrides.stateDiff)
diff --git a/src/core/TxEnvelopeEip1559.bench.ts b/src/core/TxEnvelopeEip1559.bench.ts
new file mode 100644
index 00000000..44773531
--- /dev/null
+++ b/src/core/TxEnvelopeEip1559.bench.ts
@@ -0,0 +1,75 @@
+// Track B / transactions: bench coverage for the EIP-1559 envelope
+// serialize / deserialize / hash hot paths. Targets per
+// `tasks/perf-api-audit-transactions.md` Phase 1: ≥ 2× faster envelope
+// serialize and deserialize at the same input.
+
+import { bench, describe } from 'vitest'
+import * as TxEnvelopeEip1559 from './TxEnvelopeEip1559.js'
+
+const envelope = TxEnvelopeEip1559.from({
+ chainId: 1,
+ nonce: 785n,
+ maxPriorityFeePerGas: 2_000_000_000n,
+ maxFeePerGas: 2_000_000_000n,
+ gas: 1_000_000n,
+ to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ value: 1_000_000_000_000_000_000n,
+ r: 49782753348462494199823712700004552394425719014458918871452329774910450607807n,
+ s: 33726695977844476214676913201140481102225469284307016937915595756355928419768n,
+ yParity: 1,
+})
+
+const envelopeWithAccessList = TxEnvelopeEip1559.from({
+ ...envelope,
+ accessList: [
+ {
+ address: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
+ storageKeys: [
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
+ '0x0000000000000000000000000000000000000000000000000000000000000002',
+ ],
+ },
+ {
+ address: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
+ storageKeys: [
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
+ ],
+ },
+ ],
+})
+
+const serialized = TxEnvelopeEip1559.serialize(envelope)
+const serializedWithAccessList = TxEnvelopeEip1559.serialize(
+ envelopeWithAccessList,
+)
+
+describe('TxEnvelopeEip1559.serialize', () => {
+ bench('minimal (no access list)', () => {
+ TxEnvelopeEip1559.serialize(envelope)
+ })
+
+ bench('with access list (2 entries, 4 storage keys)', () => {
+ TxEnvelopeEip1559.serialize(envelopeWithAccessList)
+ })
+})
+
+describe('TxEnvelopeEip1559.deserialize', () => {
+ bench('minimal (no access list)', () => {
+ TxEnvelopeEip1559.deserialize(serialized)
+ })
+
+ bench('with access list (2 entries, 4 storage keys)', () => {
+ TxEnvelopeEip1559.deserialize(serializedWithAccessList)
+ })
+})
+
+describe('TxEnvelopeEip1559.hash', () => {
+ bench('minimal (no access list)', () => {
+ TxEnvelopeEip1559.hash(envelope)
+ })
+
+ bench('with access list (2 entries, 4 storage keys)', () => {
+ TxEnvelopeEip1559.hash(envelopeWithAccessList)
+ })
+})
diff --git a/src/core/TxEnvelopeEip1559.ts b/src/core/TxEnvelopeEip1559.ts
index 8181e5b8..bb1f2639 100644
--- a/src/core/TxEnvelopeEip1559.ts
+++ b/src/core/TxEnvelopeEip1559.ts
@@ -1,8 +1,10 @@
import * as AccessList from './AccessList.js'
import * as Address from './Address.js'
+import type * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
import * as Hex from './Hex.js'
+import * as Tx from './internal/tx.js'
import type {
Assign,
Compute,
@@ -117,7 +119,7 @@ export declare namespace assert {
export function deserialize(
serialized: Serialized,
): Compute {
- const transactionArray = Rlp.toHex(Hex.slice(serialized, 1))
+ const transactionArray = Rlp.toBytes(Hex.slice(serialized, 1))
const [
chainId,
@@ -132,7 +134,7 @@ export function deserialize(
yParity,
r,
s,
- ] = transactionArray as readonly Hex.Hex[]
+ ] = transactionArray as readonly Bytes.Bytes[]
if (!(transactionArray.length === 9 || transactionArray.length === 12))
throw new TransactionEnvelope.InvalidSerializedError({
@@ -159,24 +161,37 @@ export function deserialize(
})
let transaction = {
- chainId: Number(chainId),
+ chainId: Number(Tx.bytesToBigIntOrZero(chainId)),
type,
} as TxEnvelopeEip1559
- if (Hex.validate(to) && to !== '0x') transaction.to = to
- if (Hex.validate(gas) && gas !== '0x') transaction.gas = BigInt(gas)
- if (Hex.validate(data) && data !== '0x') transaction.data = data
- if (Hex.validate(nonce))
- transaction.nonce = nonce === '0x' ? 0n : BigInt(nonce)
- if (Hex.validate(value) && value !== '0x') transaction.value = BigInt(value)
- if (Hex.validate(maxFeePerGas) && maxFeePerGas !== '0x')
- transaction.maxFeePerGas = BigInt(maxFeePerGas)
- if (Hex.validate(maxPriorityFeePerGas) && maxPriorityFeePerGas !== '0x')
- transaction.maxPriorityFeePerGas = BigInt(maxPriorityFeePerGas)
- if (accessList!.length !== 0 && accessList !== '0x')
- transaction.accessList = AccessList.fromTupleList(accessList as any)
+ const to_ = Tx.bytesToHexOrUndefined(to)
+ if (to_) transaction.to = to_
+ const gas_ = Tx.bytesToBigIntOrUndefined(gas)
+ if (gas_ !== undefined) transaction.gas = gas_
+ const data_ = Tx.bytesToHexOrUndefined(data)
+ if (data_) transaction.data = data_
+ if (nonce !== undefined) transaction.nonce = Tx.bytesToBigIntOrZero(nonce)
+ const value_ = Tx.bytesToBigIntOrUndefined(value)
+ if (value_ !== undefined) transaction.value = value_
+ const maxFeePerGas_ = Tx.bytesToBigIntOrUndefined(maxFeePerGas)
+ if (maxFeePerGas_ !== undefined) transaction.maxFeePerGas = maxFeePerGas_
+ const maxPriorityFeePerGas_ =
+ Tx.bytesToBigIntOrUndefined(maxPriorityFeePerGas)
+ if (maxPriorityFeePerGas_ !== undefined)
+ transaction.maxPriorityFeePerGas = maxPriorityFeePerGas_
+ if ((accessList as unknown as readonly unknown[]).length !== 0)
+ transaction.accessList = AccessList.fromTupleList(
+ Tx.bytesTreeToHex(accessList as never) as never,
+ )
const signature =
- r && s && yParity ? Signature.fromTuple([yParity, r, s]) : undefined
+ r && s && yParity
+ ? Signature.fromTuple([
+ Tx.bytesToHex(yParity),
+ Tx.bytesToHex(r),
+ Tx.bytesToHex(s),
+ ])
+ : undefined
if (signature)
transaction = {
...transaction,
@@ -497,12 +512,12 @@ export function serialize(
const serialized = [
Hex.fromNumber(chainId),
- nonce ? Hex.fromNumber(nonce) : '0x',
- maxPriorityFeePerGas ? Hex.fromNumber(maxPriorityFeePerGas) : '0x',
- maxFeePerGas ? Hex.fromNumber(maxFeePerGas) : '0x',
- gas ? Hex.fromNumber(gas) : '0x',
+ Tx.quantityToHex(nonce),
+ Tx.quantityToHex(maxPriorityFeePerGas),
+ Tx.quantityToHex(maxFeePerGas),
+ Tx.quantityToHex(gas),
to ?? '0x',
- value ? Hex.fromNumber(value) : '0x',
+ Tx.quantityToHex(value),
data ?? input ?? '0x',
accessTupleList,
...(signature ? Signature.toTuple(signature) : []),
diff --git a/src/core/TxEnvelopeEip2930.ts b/src/core/TxEnvelopeEip2930.ts
index 3e9db916..86f7cb9c 100644
--- a/src/core/TxEnvelopeEip2930.ts
+++ b/src/core/TxEnvelopeEip2930.ts
@@ -1,8 +1,10 @@
import * as AccessList from './AccessList.js'
import * as Address from './Address.js'
+import type * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
import * as Hex from './Hex.js'
+import * as Tx from './internal/tx.js'
import type {
Assign,
Compute,
@@ -103,7 +105,7 @@ export declare namespace assert {
* @returns Deserialized Transaction Envelope.
*/
export function deserialize(serialized: Serialized): TxEnvelopeEip2930 {
- const transactionArray = Rlp.toHex(Hex.slice(serialized, 1))
+ const transactionArray = Rlp.toBytes(Hex.slice(serialized, 1))
const [
chainId,
@@ -117,7 +119,7 @@ export function deserialize(serialized: Serialized): TxEnvelopeEip2930 {
yParity,
r,
s,
- ] = transactionArray as readonly Hex.Hex[]
+ ] = transactionArray as readonly Bytes.Bytes[]
if (!(transactionArray.length === 8 || transactionArray.length === 11))
throw new TransactionEnvelope.InvalidSerializedError({
@@ -143,22 +145,33 @@ export function deserialize(serialized: Serialized): TxEnvelopeEip2930 {
})
let transaction = {
- chainId: Number(chainId as Hex.Hex),
+ chainId: Number(Tx.bytesToBigIntOrZero(chainId)),
type,
} as TxEnvelopeEip2930
- if (Hex.validate(to) && to !== '0x') transaction.to = to
- if (Hex.validate(gas) && gas !== '0x') transaction.gas = BigInt(gas)
- if (Hex.validate(data) && data !== '0x') transaction.data = data
- if (Hex.validate(nonce))
- transaction.nonce = nonce === '0x' ? 0n : BigInt(nonce)
- if (Hex.validate(value) && value !== '0x') transaction.value = BigInt(value)
- if (Hex.validate(gasPrice) && gasPrice !== '0x')
- transaction.gasPrice = BigInt(gasPrice)
- if (accessList!.length !== 0 && accessList !== '0x')
- transaction.accessList = AccessList.fromTupleList(accessList as any)
+ const to_ = Tx.bytesToHexOrUndefined(to)
+ if (to_) transaction.to = to_
+ const gas_ = Tx.bytesToBigIntOrUndefined(gas)
+ if (gas_ !== undefined) transaction.gas = gas_
+ const data_ = Tx.bytesToHexOrUndefined(data)
+ if (data_) transaction.data = data_
+ if (nonce !== undefined) transaction.nonce = Tx.bytesToBigIntOrZero(nonce)
+ const value_ = Tx.bytesToBigIntOrUndefined(value)
+ if (value_ !== undefined) transaction.value = value_
+ const gasPrice_ = Tx.bytesToBigIntOrUndefined(gasPrice)
+ if (gasPrice_ !== undefined) transaction.gasPrice = gasPrice_
+ if ((accessList as unknown as readonly unknown[]).length !== 0)
+ transaction.accessList = AccessList.fromTupleList(
+ Tx.bytesTreeToHex(accessList as never) as never,
+ )
const signature =
- r && s && yParity ? Signature.fromTuple([yParity, r, s]) : undefined
+ r && s && yParity
+ ? Signature.fromTuple([
+ Tx.bytesToHex(yParity),
+ Tx.bytesToHex(r),
+ Tx.bytesToHex(s),
+ ])
+ : undefined
if (signature)
transaction = {
...transaction,
@@ -467,11 +480,11 @@ export function serialize(
const serialized = [
Hex.fromNumber(chainId),
- nonce ? Hex.fromNumber(nonce) : '0x',
- gasPrice ? Hex.fromNumber(gasPrice) : '0x',
- gas ? Hex.fromNumber(gas) : '0x',
+ Tx.quantityToHex(nonce),
+ Tx.quantityToHex(gasPrice),
+ Tx.quantityToHex(gas),
to ?? '0x',
- value ? Hex.fromNumber(value) : '0x',
+ Tx.quantityToHex(value),
data ?? input ?? '0x',
accessTupleList,
...(signature ? Signature.toTuple(signature) : []),
diff --git a/src/core/TxEnvelopeEip4844.ts b/src/core/TxEnvelopeEip4844.ts
index 8265f532..bcc1ab05 100644
--- a/src/core/TxEnvelopeEip4844.ts
+++ b/src/core/TxEnvelopeEip4844.ts
@@ -1,8 +1,10 @@
import * as AccessList from './AccessList.js'
import * as Blobs from './Blobs.js'
+import type * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
import * as Hex from './Hex.js'
+import * as Tx from './internal/tx.js'
import type {
Assign,
Compute,
@@ -132,15 +134,17 @@ export declare namespace assert {
export function deserialize(
serialized: Serialized,
): Compute {
- const transactionOrWrapperArray = Rlp.toHex(Hex.slice(serialized, 1))
+ const transactionOrWrapperArray = Rlp.toBytes(Hex.slice(serialized, 1))
const hasNetworkWrapper = transactionOrWrapperArray.length === 4
const transactionArray = hasNetworkWrapper
- ? transactionOrWrapperArray[0]!
- : transactionOrWrapperArray
+ ? (transactionOrWrapperArray[0]! as ReadonlyArray)
+ : (transactionOrWrapperArray as ReadonlyArray)
const wrapperArray = hasNetworkWrapper
- ? transactionOrWrapperArray.slice(1)
+ ? (transactionOrWrapperArray.slice(1) as ReadonlyArray<
+ ReadonlyArray
+ >)
: []
const [
@@ -158,7 +162,7 @@ export function deserialize(
yParity,
r,
s,
- ] = transactionArray
+ ] = transactionArray as readonly (Bytes.Bytes | ReadonlyArray)[]
const [blobs, commitments, proofs] = wrapperArray
if (!(transactionArray.length === 11 || transactionArray.length === 14))
@@ -188,32 +192,48 @@ export function deserialize(
})
let transaction = {
- blobVersionedHashes: blobVersionedHashes as Hex.Hex[],
- chainId: Number(chainId),
+ blobVersionedHashes: (
+ blobVersionedHashes as ReadonlyArray
+ ).map((b) => Tx.bytesToHex(b)),
+ chainId: Number(Tx.bytesToBigIntOrZero(chainId as Bytes.Bytes)),
type,
} as TxEnvelopeEip4844
- if (Hex.validate(to) && to !== '0x') transaction.to = to
- if (Hex.validate(gas) && gas !== '0x') transaction.gas = BigInt(gas)
- if (Hex.validate(data) && data !== '0x') transaction.data = data
- if (Hex.validate(nonce))
- transaction.nonce = nonce === '0x' ? 0n : BigInt(nonce)
- if (Hex.validate(value) && value !== '0x') transaction.value = BigInt(value)
- if (Hex.validate(maxFeePerBlobGas) && maxFeePerBlobGas !== '0x')
- transaction.maxFeePerBlobGas = BigInt(maxFeePerBlobGas)
- if (Hex.validate(maxFeePerGas) && maxFeePerGas !== '0x')
- transaction.maxFeePerGas = BigInt(maxFeePerGas)
- if (Hex.validate(maxPriorityFeePerGas) && maxPriorityFeePerGas !== '0x')
- transaction.maxPriorityFeePerGas = BigInt(maxPriorityFeePerGas)
- if (accessList?.length !== 0 && accessList !== '0x')
- transaction.accessList = AccessList.fromTupleList(accessList as any)
+ const to_ = Tx.bytesToHexOrUndefined(to as Bytes.Bytes | undefined)
+ if (to_) transaction.to = to_
+ const gas_ = Tx.bytesToBigIntOrUndefined(gas as Bytes.Bytes | undefined)
+ if (gas_ !== undefined) transaction.gas = gas_
+ const data_ = Tx.bytesToHexOrUndefined(data as Bytes.Bytes | undefined)
+ if (data_) transaction.data = data_
+ if (nonce !== undefined)
+ transaction.nonce = Tx.bytesToBigIntOrZero(nonce as Bytes.Bytes)
+ const value_ = Tx.bytesToBigIntOrUndefined(value as Bytes.Bytes | undefined)
+ if (value_ !== undefined) transaction.value = value_
+ const maxFeePerBlobGas_ = Tx.bytesToBigIntOrUndefined(
+ maxFeePerBlobGas as Bytes.Bytes | undefined,
+ )
+ if (maxFeePerBlobGas_ !== undefined)
+ transaction.maxFeePerBlobGas = maxFeePerBlobGas_
+ const maxFeePerGas_ = Tx.bytesToBigIntOrUndefined(
+ maxFeePerGas as Bytes.Bytes | undefined,
+ )
+ if (maxFeePerGas_ !== undefined) transaction.maxFeePerGas = maxFeePerGas_
+ const maxPriorityFeePerGas_ = Tx.bytesToBigIntOrUndefined(
+ maxPriorityFeePerGas as Bytes.Bytes | undefined,
+ )
+ if (maxPriorityFeePerGas_ !== undefined)
+ transaction.maxPriorityFeePerGas = maxPriorityFeePerGas_
+ if (accessList && (accessList as readonly unknown[]).length !== 0)
+ transaction.accessList = AccessList.fromTupleList(
+ Tx.bytesTreeToHex(accessList as never) as never,
+ )
if (blobs && commitments && proofs) {
// Validate sidecar wrapper cardinality before zipping; otherwise
// `Blobs.toSidecars` blindly indexes `commitments[i]!` / `proofs[i]!`
// and fabricates `undefined` entries from a malformed payload.
- const blobsArr = blobs as readonly Hex.Hex[]
- const commitmentsArr = commitments as readonly Hex.Hex[]
- const proofsArr = proofs as readonly Hex.Hex[]
- const versionedHashesArr = blobVersionedHashes as readonly Hex.Hex[]
+ const blobsArr = blobs as ReadonlyArray
+ const commitmentsArr = commitments as ReadonlyArray
+ const proofsArr = proofs as ReadonlyArray
+ const versionedHashesArr = blobVersionedHashes as ReadonlyArray
if (
blobsArr.length !== commitmentsArr.length ||
blobsArr.length !== proofsArr.length ||
@@ -229,15 +249,22 @@ export function deserialize(
serialized,
type,
})
- transaction.sidecars = Blobs.toSidecars(blobsArr as Hex.Hex[], {
- commitments: commitmentsArr as Hex.Hex[],
- proofs: proofsArr as Hex.Hex[],
- })
+ transaction.sidecars = Blobs.toSidecars(
+ blobsArr.map((b) => Tx.bytesToHex(b)) as Hex.Hex[],
+ {
+ commitments: commitmentsArr.map((b) => Tx.bytesToHex(b)) as Hex.Hex[],
+ proofs: proofsArr.map((b) => Tx.bytesToHex(b)) as Hex.Hex[],
+ },
+ )
}
const signature =
r && s && yParity
- ? Signature.fromTuple([yParity as Hex.Hex, r as Hex.Hex, s as Hex.Hex])
+ ? Signature.fromTuple([
+ Tx.bytesToHex(yParity as Bytes.Bytes),
+ Tx.bytesToHex(r as Bytes.Bytes),
+ Tx.bytesToHex(s as Bytes.Bytes),
+ ])
: undefined
if (signature)
transaction = {
@@ -599,15 +626,15 @@ export function serialize(
const serialized = [
Hex.fromNumber(chainId),
- nonce ? Hex.fromNumber(nonce) : '0x',
- maxPriorityFeePerGas ? Hex.fromNumber(maxPriorityFeePerGas) : '0x',
- maxFeePerGas ? Hex.fromNumber(maxFeePerGas) : '0x',
- gas ? Hex.fromNumber(gas) : '0x',
+ Tx.quantityToHex(nonce),
+ Tx.quantityToHex(maxPriorityFeePerGas),
+ Tx.quantityToHex(maxFeePerGas),
+ Tx.quantityToHex(gas),
to ?? '0x',
- value ? Hex.fromNumber(value) : '0x',
+ Tx.quantityToHex(value),
data ?? input ?? '0x',
accessTupleList,
- maxFeePerBlobGas ? Hex.fromNumber(maxFeePerBlobGas) : '0x',
+ Tx.quantityToHex(maxFeePerBlobGas),
blobVersionedHashes ?? [],
...(signature ? Signature.toTuple(signature) : []),
] as const
diff --git a/src/core/TxEnvelopeEip7702.ts b/src/core/TxEnvelopeEip7702.ts
index 461d4fe5..c2b26a31 100644
--- a/src/core/TxEnvelopeEip7702.ts
+++ b/src/core/TxEnvelopeEip7702.ts
@@ -1,9 +1,11 @@
import * as AccessList from './AccessList.js'
import * as Address from './Address.js'
import * as Authorization from './Authorization.js'
+import type * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
import * as Hex from './Hex.js'
+import * as Tx from './internal/tx.js'
import type {
Assign,
Compute,
@@ -118,7 +120,7 @@ export declare namespace assert {
export function deserialize(
serialized: Serialized,
): Compute {
- const transactionArray = Rlp.toHex(Hex.slice(serialized, 1))
+ const transactionArray = Rlp.toBytes(Hex.slice(serialized, 1))
const [
chainId,
@@ -134,7 +136,7 @@ export function deserialize(
yParity,
r,
s,
- ] = transactionArray as readonly Hex.Hex[]
+ ] = transactionArray as readonly Bytes.Bytes[]
if (!(transactionArray.length === 10 || transactionArray.length === 13))
throw new TransactionEnvelope.InvalidSerializedError({
@@ -162,28 +164,43 @@ export function deserialize(
})
let transaction = {
- chainId: Number(chainId),
+ chainId: Number(Tx.bytesToBigIntOrZero(chainId)),
type,
} as TxEnvelopeEip7702
- if (Hex.validate(to) && to !== '0x') transaction.to = to
- if (Hex.validate(gas) && gas !== '0x') transaction.gas = BigInt(gas)
- if (Hex.validate(data) && data !== '0x') transaction.data = data
- if (Hex.validate(nonce))
- transaction.nonce = nonce === '0x' ? 0n : BigInt(nonce)
- if (Hex.validate(value) && value !== '0x') transaction.value = BigInt(value)
- if (Hex.validate(maxFeePerGas) && maxFeePerGas !== '0x')
- transaction.maxFeePerGas = BigInt(maxFeePerGas)
- if (Hex.validate(maxPriorityFeePerGas) && maxPriorityFeePerGas !== '0x')
- transaction.maxPriorityFeePerGas = BigInt(maxPriorityFeePerGas)
- if (accessList!.length !== 0 && accessList !== '0x')
- transaction.accessList = AccessList.fromTupleList(accessList as never)
- if (authorizationList !== '0x')
+ const to_ = Tx.bytesToHexOrUndefined(to)
+ if (to_) transaction.to = to_
+ const gas_ = Tx.bytesToBigIntOrUndefined(gas)
+ if (gas_ !== undefined) transaction.gas = gas_
+ const data_ = Tx.bytesToHexOrUndefined(data)
+ if (data_) transaction.data = data_
+ if (nonce !== undefined) transaction.nonce = Tx.bytesToBigIntOrZero(nonce)
+ const value_ = Tx.bytesToBigIntOrUndefined(value)
+ if (value_ !== undefined) transaction.value = value_
+ const maxFeePerGas_ = Tx.bytesToBigIntOrUndefined(maxFeePerGas)
+ if (maxFeePerGas_ !== undefined) transaction.maxFeePerGas = maxFeePerGas_
+ const maxPriorityFeePerGas_ =
+ Tx.bytesToBigIntOrUndefined(maxPriorityFeePerGas)
+ if (maxPriorityFeePerGas_ !== undefined)
+ transaction.maxPriorityFeePerGas = maxPriorityFeePerGas_
+ if ((accessList as unknown as readonly unknown[]).length !== 0)
+ transaction.accessList = AccessList.fromTupleList(
+ Tx.bytesTreeToHex(accessList as never) as never,
+ )
+ // Authorization list is preserved even when empty for round-trip parity
+ // with the legacy `authorizationList !== '0x'` hex check.
+ if (Array.isArray(authorizationList))
transaction.authorizationList = Authorization.fromTupleList(
- authorizationList as never,
+ Tx.bytesTreeToHex(authorizationList as never) as never,
)
const signature =
- r && s && yParity ? Signature.fromTuple([yParity, r, s]) : undefined
+ r && s && yParity
+ ? Signature.fromTuple([
+ Tx.bytesToHex(yParity),
+ Tx.bytesToHex(r),
+ Tx.bytesToHex(s),
+ ])
+ : undefined
if (signature)
transaction = {
...transaction,
@@ -541,12 +558,12 @@ export function serialize(
const serialized = [
Hex.fromNumber(chainId),
- nonce ? Hex.fromNumber(nonce) : '0x',
- maxPriorityFeePerGas ? Hex.fromNumber(maxPriorityFeePerGas) : '0x',
- maxFeePerGas ? Hex.fromNumber(maxFeePerGas) : '0x',
- gas ? Hex.fromNumber(gas) : '0x',
+ Tx.quantityToHex(nonce),
+ Tx.quantityToHex(maxPriorityFeePerGas),
+ Tx.quantityToHex(maxFeePerGas),
+ Tx.quantityToHex(gas),
to ?? '0x',
- value ? Hex.fromNumber(value) : '0x',
+ Tx.quantityToHex(value),
data ?? input ?? '0x',
accessTupleList,
authorizationTupleList,
diff --git a/src/core/TxEnvelopeLegacy.ts b/src/core/TxEnvelopeLegacy.ts
index 9f90b171..ceeaadc1 100644
--- a/src/core/TxEnvelopeLegacy.ts
+++ b/src/core/TxEnvelopeLegacy.ts
@@ -1,7 +1,9 @@
import * as Address from './Address.js'
+import type * as Bytes from './Bytes.js'
import type * as Errors from './Errors.js'
import * as Hash from './Hash.js'
import * as Hex from './Hex.js'
+import * as Tx from './internal/tx.js'
import type {
Assign,
Branded,
@@ -101,10 +103,10 @@ export declare namespace assert {
* @returns Deserialized Transaction Envelope.
*/
export function deserialize(serialized: Hex.Hex): Compute {
- const tuple = Rlp.toHex(serialized)
+ const tuple = Rlp.toBytes(serialized)
const [nonce, gasPrice, gas, to, value, data, chainIdOrV_, r, s] =
- tuple as readonly Hex.Hex[]
+ tuple as readonly Bytes.Bytes[]
if (!(tuple.length === 6 || tuple.length === 9))
throw new TransactionEnvelope.InvalidSerializedError({
@@ -130,23 +132,23 @@ export function deserialize(serialized: Hex.Hex): Compute {
const transaction = {
type,
} as TxEnvelopeLegacy
- if (Hex.validate(to) && to !== '0x') transaction.to = to
- if (Hex.validate(gas) && gas !== '0x') transaction.gas = BigInt(gas)
- if (Hex.validate(data) && data !== '0x') transaction.data = data
- if (Hex.validate(nonce))
- transaction.nonce = nonce === '0x' ? 0n : BigInt(nonce)
- if (Hex.validate(value) && value !== '0x') transaction.value = BigInt(value)
- if (Hex.validate(gasPrice) && gasPrice !== '0x')
- transaction.gasPrice = BigInt(gasPrice)
+ const to_ = Tx.bytesToHexOrUndefined(to)
+ if (to_) transaction.to = to_
+ const gas_ = Tx.bytesToBigIntOrUndefined(gas)
+ if (gas_ !== undefined) transaction.gas = gas_
+ const data_ = Tx.bytesToHexOrUndefined(data)
+ if (data_) transaction.data = data_
+ if (nonce !== undefined) transaction.nonce = Tx.bytesToBigIntOrZero(nonce)
+ const value_ = Tx.bytesToBigIntOrUndefined(value)
+ if (value_ !== undefined) transaction.value = value_
+ const gasPrice_ = Tx.bytesToBigIntOrUndefined(gasPrice)
+ if (gasPrice_ !== undefined) transaction.gasPrice = gasPrice_
if (tuple.length === 6) return transaction
- const chainIdOrV =
- Hex.validate(chainIdOrV_) && chainIdOrV_ !== '0x'
- ? Number(chainIdOrV_ as Hex.Hex)
- : 0
+ const chainIdOrV = Tx.bytesToNumberOrUndefined(chainIdOrV_) ?? 0
- if (s === '0x' && r === '0x') {
+ if ((s as Bytes.Bytes).length === 0 && (r as Bytes.Bytes).length === 0) {
if (chainIdOrV > 0) transaction.chainId = Number(chainIdOrV)
return transaction
}
@@ -158,8 +160,8 @@ export function deserialize(serialized: Hex.Hex): Compute {
transaction.yParity = Signature.vToYParity(v)
transaction.v = v
- transaction.s = s === '0x' ? 0n : BigInt(s!)
- transaction.r = r === '0x' ? 0n : BigInt(r!)
+ transaction.s = Tx.bytesToBigIntOrZero(s)
+ transaction.r = Tx.bytesToBigIntOrZero(r)
assert(transaction)
@@ -468,11 +470,11 @@ export function serialize(
assert(envelope)
let serialized = [
- nonce ? Hex.fromNumber(nonce) : '0x',
- gasPrice ? Hex.fromNumber(gasPrice) : '0x',
- gas ? Hex.fromNumber(gas) : '0x',
+ Tx.quantityToHex(nonce),
+ Tx.quantityToHex(gasPrice),
+ Tx.quantityToHex(gas),
to ?? '0x',
- value ? Hex.fromNumber(value) : '0x',
+ Tx.quantityToHex(value),
data ?? input ?? '0x',
]
diff --git a/src/core/WebCryptoP256.bench.ts b/src/core/WebCryptoP256.bench.ts
new file mode 100644
index 00000000..12046f94
--- /dev/null
+++ b/src/core/WebCryptoP256.bench.ts
@@ -0,0 +1,38 @@
+import { bench, describe } from 'vitest'
+import * as Bytes from './Bytes.js'
+import * as PublicKey from './PublicKey.js'
+import * as WebCryptoP256 from './WebCryptoP256.js'
+
+const { privateKey, publicKey } = await WebCryptoP256.createKeyPair()
+const payload = Bytes.random(32)
+const signature = await WebCryptoP256.sign({ payload, privateKey })
+
+// Pre-import the verifying key once; this models a hypothetical
+// `verifyPrepared` fast path that would skip `subtle.importKey` per call.
+const preparedVerifyKey = await globalThis.crypto.subtle.importKey(
+ 'raw',
+ PublicKey.toBytes(publicKey),
+ { name: 'ECDSA', namedCurve: 'P-256' },
+ true,
+ ['verify'],
+)
+
+const signatureBytes = Bytes.concat(
+ Bytes.fromNumber(signature.r, { size: 32 }),
+ Bytes.fromNumber(signature.s, { size: 32 }),
+)
+
+describe('WebCryptoP256.verify', () => {
+ bench('verify (importKey per call)', async () => {
+ await WebCryptoP256.verify({ payload, publicKey, signature })
+ })
+
+ bench('verify (prepared key reused)', async () => {
+ await globalThis.crypto.subtle.verify(
+ { name: 'ECDSA', hash: 'SHA-256' },
+ preparedVerifyKey,
+ signatureBytes,
+ payload,
+ )
+ })
+})
diff --git a/src/core/_test/Bytes.test.ts b/src/core/_test/Bytes.test.ts
index 15edcef8..3265f1a5 100644
--- a/src/core/_test/Bytes.test.ts
+++ b/src/core/_test/Bytes.test.ts
@@ -307,7 +307,11 @@ describe('fromHex', () => {
expect(() =>
Bytes.fromHex('0xabcdefgh'),
).toThrowErrorMatchingInlineSnapshot(
- `[BaseError: Invalid byte sequence ("gh" in "abcdefgh").]`,
+ `
+ [Hex.InvalidHexValueError: Value \`0xabcdefgh\` is an invalid hex value.
+
+ Hex values must start with \`"0x"\` and contain only hexadecimal characters (0-9, a-f, A-F).]
+ `,
)
})
})
diff --git a/src/core/_test/Hex.test.ts b/src/core/_test/Hex.test.ts
index 950b5a7c..bb15458a 100644
--- a/src/core/_test/Hex.test.ts
+++ b/src/core/_test/Hex.test.ts
@@ -586,7 +586,11 @@ describe('toBytes', () => {
expect(() =>
Hex.toBytes('0x420fggf11a'),
).toThrowErrorMatchingInlineSnapshot(
- `[BaseError: Invalid byte sequence ("gg" in "420fggf11a").]`,
+ `
+ [Hex.InvalidHexValueError: Value \`0x420fggf11a\` is an invalid hex value.
+
+ Hex values must start with \`"0x"\` and contain only hexadecimal characters (0-9, a-f, A-F).]
+ `,
)
})
})
diff --git a/src/core/_test/Signature.test.ts b/src/core/_test/Signature.test.ts
index f5441f7e..9b75c566 100644
--- a/src/core/_test/Signature.test.ts
+++ b/src/core/_test/Signature.test.ts
@@ -800,6 +800,10 @@ test('exports', () => {
"fromRpc",
"fromTuple",
"toBytes",
+ "toCompactBytes",
+ "fromCompactBytes",
+ "toRecoveredBytes",
+ "fromRecoveredBytes",
"toHex",
"toDerBytes",
"toDerHex",
diff --git a/src/core/internal/abiItem.ts b/src/core/internal/abiItem.ts
index 23043ee4..1c246bb5 100644
--- a/src/core/internal/abiItem.ts
+++ b/src/core/internal/abiItem.ts
@@ -488,6 +488,37 @@ export declare namespace normalizeSignature {
export type ErrorType = Errors.BaseError | Errors.GlobalErrorType
}
+/**
+ * `(u)int` regex: (un)signed integer type of `M` bits, `0 < M <= 256`,
+ * `M % 8 == 0`. Hoisted to module scope; the prior literal at the call
+ * site was recompiled per overload-resolution iteration.
+ *
+ * @internal
+ */
+const integerTypeRegex =
+ /^u?int(8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?$/
+
+/**
+ * `bytes` regex: binary type of `M` bytes, `0 < M <= 32`.
+ *
+ * @internal
+ */
+const fixedBytesTypeRegex = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/
+
+/**
+ * Fixed-length (`[M]`) / dynamic (`[]`) array regex.
+ *
+ * @internal
+ */
+const arrayTypeRegex = /[a-z]+[1-9]{0,3}(\[[0-9]{0,}\])+$/
+
+/**
+ * Strips a single trailing `[...]` array suffix from a type.
+ *
+ * @internal
+ */
+const arraySuffixStripRegex = /(\[[0-9]{0,}\])$/
+
/** @internal */
export function isArgOfType(
arg: unknown,
@@ -515,30 +546,20 @@ export function isArgOfType(
},
)
- // `(u)int`: (un)signed integer type of `M` bits, `0 < M <= 256`, `M % 8 == 0`
- // https://regexr.com/6v8hp
- if (
- /^u?int(8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?$/.test(
- abiParameterType,
- )
- )
+ if (integerTypeRegex.test(abiParameterType))
return argType === 'number' || argType === 'bigint'
- // `bytes`: binary type of `M` bytes, `0 < M <= 32`
- // https://regexr.com/6va55
- if (/^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/.test(abiParameterType))
+ if (fixedBytesTypeRegex.test(abiParameterType))
return argType === 'string' || arg instanceof Uint8Array
- // fixed-length (`[M]`) and dynamic (`[]`) arrays
- // https://regexr.com/6va6i
- if (/[a-z]+[1-9]{0,3}(\[[0-9]{0,}\])+$/.test(abiParameterType)) {
+ if (arrayTypeRegex.test(abiParameterType)) {
return (
Array.isArray(arg) &&
arg.every((x: unknown) =>
isArgOfType(x, {
...abiParameter,
// Pop off `[]` or `[M]` from end of type
- type: abiParameterType.replace(/(\[[0-9]{0,}\])$/, ''),
+ type: abiParameterType.replace(arraySuffixStripRegex, ''),
} as AbiParameters.Parameter),
)
)
@@ -555,7 +576,13 @@ export function getAmbiguousTypes(
targetParameters: readonly AbiParameters.Parameter[],
args: ExtractArgs,
): AbiParameters.Parameter['type'][] | undefined {
- for (const parameterIndex in sourceParameters) {
+ // Indexed `for` loop instead of `for...in` (which iterates inherited
+ // enumerable keys and is materially slower on arrays).
+ for (
+ let parameterIndex = 0;
+ parameterIndex < sourceParameters.length;
+ parameterIndex++
+ ) {
const sourceParameter = sourceParameters[parameterIndex]!
const targetParameter = targetParameters[parameterIndex]!
@@ -571,22 +598,25 @@ export function getAmbiguousTypes(
(args as any)[parameterIndex],
)
- const types = [sourceParameter.type, targetParameter.type]
-
- const ambiguous = (() => {
- if (types.includes('address') && types.includes('bytes20')) return true
- if (types.includes('address') && types.includes('string'))
- return Address.validate(args[parameterIndex] as Address.Address, {
- strict: false,
- })
- if (types.includes('address') && types.includes('bytes'))
- return Address.validate(args[parameterIndex] as Address.Address, {
- strict: false,
- })
- return false
- })()
+ const sourceType = sourceParameter.type
+ const targetType = targetParameter.type
+ const arg = args[parameterIndex] as Address.Address
+
+ let ambiguous = false
+ if (
+ (sourceType === 'address' && targetType === 'bytes20') ||
+ (sourceType === 'bytes20' && targetType === 'address')
+ )
+ ambiguous = true
+ else if (
+ (sourceType === 'address' && targetType === 'string') ||
+ (sourceType === 'string' && targetType === 'address') ||
+ (sourceType === 'address' && targetType === 'bytes') ||
+ (sourceType === 'bytes' && targetType === 'address')
+ )
+ ambiguous = Address.validate(arg, { strict: false })
- if (ambiguous) return types
+ if (ambiguous) return [sourceType, targetType]
}
return
diff --git a/src/core/internal/abiParameters.ts b/src/core/internal/abiParameters.ts
index 42cc50ad..df0840e5 100644
--- a/src/core/internal/abiParameters.ts
+++ b/src/core/internal/abiParameters.ts
@@ -107,6 +107,15 @@ export declare namespace decodeParameter {
const sizeOfLength = 32
const sizeOfOffset = 32
+/**
+ * Cached regex for matching array suffixes (e.g. `uint256[]`,
+ * `bytes32[3]`). Hoisted to module scope so we don't allocate a new
+ * regex per `getArrayComponents` call (hot in encode/decode).
+ *
+ * @internal
+ */
+const arraySuffixRegex = /^(.*)\[(\d+)?\]$/
+
/** @internal */
export function decodeAddress(
cursor: Cursor.Cursor,
@@ -781,7 +790,7 @@ export declare namespace encodeTuple {
export function getArrayComponents(
type: string,
): [length: number | null, innerType: string] | undefined {
- const matches = type.match(/^(.*)\[(\d+)?\]$/)
+ const matches = arraySuffixRegex.exec(type)
return matches
? // Return `null` if the array is dynamic.
[matches[2]! ? Number(matches[2]!) : null, matches[1]!]
diff --git a/src/core/internal/address.ts b/src/core/internal/address.ts
new file mode 100644
index 00000000..1f4c2abe
--- /dev/null
+++ b/src/core/internal/address.ts
@@ -0,0 +1,79 @@
+/** @internal */
+export const length = 42
+
+const ZERO = 48 // '0'
+const NINE = 57 // '9'
+const A_UPPER = 65 // 'A'
+const F_UPPER = 70 // 'F'
+const A_LOWER = 97 // 'a'
+const F_LOWER = 102 // 'f'
+const X_LOWER = 120 // 'x'
+
+/**
+ * @internal
+ *
+ * Combined shape + lowercase classification for an Ethereum address string.
+ * Avoids the regex / try-catch / error-allocation overhead in the hot path
+ * and avoids a second pass for callers that need both pieces of metadata
+ * (e.g. strict validation).
+ *
+ * - `0` = invalid shape (not `0x[0-9a-fA-F]{40}`)
+ * - `1` = valid shape, all-lowercase hex body (no checksum to verify)
+ * - `2` = valid shape, contains at least one `A-F` upper char
+ */
+export function classify(value: string): 0 | 1 | 2 {
+ if (typeof value !== 'string' || value.length !== length) return 0
+ if (value.charCodeAt(0) !== ZERO || value.charCodeAt(1) !== X_LOWER) return 0
+ let hasUpper = false
+ for (let i = 2; i < length; i++) {
+ const code = value.charCodeAt(i)
+ if (code >= ZERO && code <= NINE) continue
+ if (code >= A_LOWER && code <= F_LOWER) continue
+ if (code >= A_UPPER && code <= F_UPPER) {
+ hasUpper = true
+ continue
+ }
+ return 0
+ }
+ return hasUpper ? 2 : 1
+}
+
+/**
+ * @internal
+ *
+ * Manual ASCII shape check for an Ethereum address string. Returns `true`
+ * when `value` has the shape `0x[0-9a-fA-F]{40}`. Does not verify checksum
+ * casing.
+ */
+export function hasShape(value: string): boolean {
+ return classify(value) !== 0
+}
+
+/**
+ * @internal
+ *
+ * Returns the canonical lowercase form of a shape-validated address, or the
+ * input unchanged when it is already all-lowercase. Pre-condition: caller has
+ * already verified the string is shape-valid via {@link hasShape} or
+ * {@link classify}.
+ */
+export function lowercase(value: string): string {
+ let hasUpper = false
+ for (let i = 2; i < length; i++) {
+ const code = value.charCodeAt(i)
+ if (code >= A_UPPER && code <= F_UPPER) {
+ hasUpper = true
+ break
+ }
+ }
+ if (!hasUpper) return value
+
+ const out = new Uint16Array(length)
+ out[0] = ZERO
+ out[1] = X_LOWER
+ for (let i = 2; i < length; i++) {
+ const code = value.charCodeAt(i)
+ out[i] = code >= A_UPPER && code <= F_UPPER ? code + 32 : code
+ }
+ return String.fromCharCode.apply(null, out as unknown as number[])
+}
diff --git a/src/core/internal/codec/bech32-base32.ts b/src/core/internal/codec/bech32-base32.ts
new file mode 100644
index 00000000..1638cf17
--- /dev/null
+++ b/src/core/internal/codec/bech32-base32.ts
@@ -0,0 +1,64 @@
+import * as Errors from '../../Errors.js'
+
+/**
+ * Bech32/BIP-173 base32 alphabet. Shared between `Base32` and `Bech32m`.
+ *
+ * @internal
+ */
+export const alphabet = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
+
+/** @internal */
+export const alphabetMap = /*#__PURE__*/ (() => {
+ const map: Record = {}
+ for (let i = 0; i < alphabet.length; i++) map[alphabet[i]!] = i
+ return map
+})()
+
+/**
+ * Repacks bits between two power-of-two bases (`fromBits` -> `toBits`).
+ *
+ * When `pad` is `true`, leftover bits are zero-padded to a final symbol. When
+ * `pad` is `false`, leftover bits must be zero (canonical form per BIP-173)
+ * and a non-zero remainder throws `InvalidPaddingError`.
+ *
+ * @internal
+ */
+export function convertBits(
+ data: Iterable,
+ fromBits: number,
+ toBits: number,
+ pad: boolean,
+): number[] {
+ let acc = 0
+ let bits = 0
+ const maxv = (1 << toBits) - 1
+ const ret: number[] = []
+ for (const value of data) {
+ acc = (acc << fromBits) | value
+ bits += fromBits
+ while (bits >= toBits) {
+ bits -= toBits
+ ret.push((acc >> bits) & maxv)
+ }
+ }
+ if (pad) {
+ if (bits > 0) ret.push((acc << (toBits - bits)) & maxv)
+ } else if (bits >= fromBits || (acc << (toBits - bits)) & maxv) {
+ throw new InvalidPaddingError()
+ }
+ return ret
+}
+
+/** Thrown when leftover bits during base32 conversion are non-zero. */
+export class InvalidPaddingError extends Errors.BaseError {
+ override readonly name = 'Bech32m.InvalidPaddingError'
+
+ constructor() {
+ super('Invalid padding in base32 data.')
+ }
+}
+
+/** @internal */
+export declare namespace convertBits {
+ type ErrorType = InvalidPaddingError | Errors.GlobalErrorType
+}
diff --git a/src/core/internal/codec/errors.ts b/src/core/internal/codec/errors.ts
new file mode 100644
index 00000000..1fa73774
--- /dev/null
+++ b/src/core/internal/codec/errors.ts
@@ -0,0 +1,30 @@
+import * as Errors from '../../Errors.js'
+
+/**
+ * Shared `SizeOverflowError` class for `Bytes` and `Hex`. The `name` is
+ * passed at construction time so a single class identity backs both
+ * `Bytes.SizeOverflowError` and `Hex.SizeOverflowError` re-exports without
+ * forcing `Bytes` and `Hex` to import each other at runtime.
+ *
+ * @internal
+ */
+export class BytesSizeOverflowError extends Errors.BaseError {
+ override readonly name = 'Bytes.SizeOverflowError'
+
+ constructor({ givenSize, maxSize }: { givenSize: number; maxSize: number }) {
+ super(
+ `Size cannot exceed \`${maxSize}\` bytes. Given size: \`${givenSize}\` bytes.`,
+ )
+ }
+}
+
+/** @internal */
+export class HexSizeOverflowError extends Errors.BaseError {
+ override readonly name = 'Hex.SizeOverflowError'
+
+ constructor({ givenSize, maxSize }: { givenSize: number; maxSize: number }) {
+ super(
+ `Size cannot exceed \`${maxSize}\` bytes. Given size: \`${givenSize}\` bytes.`,
+ )
+ }
+}
diff --git a/src/core/internal/codec/hex.ts b/src/core/internal/codec/hex.ts
new file mode 100644
index 00000000..83b1168f
--- /dev/null
+++ b/src/core/internal/codec/hex.ts
@@ -0,0 +1,145 @@
+import * as Errors from '../../Errors.js'
+
+/** @internal */
+export type Hex = `0x${string}`
+
+/** @internal */
+const hexes = /*#__PURE__*/ Array.from({ length: 256 }, (_v, i) =>
+ i.toString(16).padStart(2, '0'),
+)
+
+// Char-code → 4-bit nibble lookup table. Sentinel `0xff` = invalid.
+const nibbleTable = /*#__PURE__*/ (() => {
+ const table = new Uint8Array(256).fill(0xff)
+ for (let i = 0; i < 10; i++) table[48 + i] = i // '0'-'9'
+ for (let i = 0; i < 6; i++) {
+ table[65 + i] = 10 + i // 'A'-'F'
+ table[97 + i] = 10 + i // 'a'-'f'
+ }
+ return table
+})()
+
+// Phase 2 native fast-path detection: `Uint8Array.prototype.toHex` lands in
+// Node 22+, Safari 18+, Firefox 133+. Falls back to `Buffer` on Node, then to
+// the JS loop.
+const _Buffer: typeof globalThis.Buffer | undefined = (
+ globalThis as typeof globalThis & { Buffer?: typeof globalThis.Buffer }
+).Buffer
+const nativeToHex: ((this: Uint8Array) => string) | undefined = (
+ Uint8Array.prototype as Uint8Array & { toHex?: () => string }
+).toHex
+const nativeFromHex: ((value: string) => Uint8Array) | undefined = (
+ Uint8Array as typeof Uint8Array & { fromHex?: (value: string) => Uint8Array }
+).fromHex
+
+/**
+ * Encodes a `Uint8Array` into a `0x`-prefixed lowercase hex string. Uses the
+ * native `Uint8Array.prototype.toHex` (Node 22+, Safari 18+, Firefox 133+) or
+ * Node's `Buffer` when available; otherwise a tight JS loop.
+ *
+ * @internal
+ */
+export function bytesToHex(value: Uint8Array): Hex {
+ if (nativeToHex) return `0x${nativeToHex.call(value)}` as Hex
+ if (_Buffer)
+ return `0x${_Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString('hex')}` as Hex
+ const length = value.length
+ const parts = new Array(length)
+ for (let i = 0; i < length; i++) parts[i] = hexes[value[i]!]!
+ return `0x${parts.join('')}` as Hex
+}
+
+/**
+ * Strictly decodes a `0x`-prefixed even-length hex string into a `Uint8Array`.
+ * Uses the native `Uint8Array.fromHex` (Node 22+, Safari 18+, Firefox 133+) or
+ * Node's `Buffer` when available; otherwise a tight JS loop.
+ *
+ * @internal
+ */
+export function hexToBytes(value: string): Uint8Array {
+ if (
+ typeof value !== 'string' ||
+ value.length < 2 ||
+ value.charCodeAt(0) !== 48 /* '0' */ ||
+ value.charCodeAt(1) !== 120 /* 'x' */
+ )
+ throw new InvalidHexValueError(value)
+ const body = value.length === 2 ? '' : (value as string).slice(2)
+ if ((body.length & 1) !== 0) throw new InvalidLengthError(value as Hex)
+
+ if (nativeFromHex) {
+ try {
+ return nativeFromHex(body)
+ } catch {
+ throw new InvalidHexValueError(value)
+ }
+ }
+ if (_Buffer && body.length > 0) {
+ // Buffer.from with 'hex' silently truncates on invalid chars; verify
+ // byteLength matches expectations to detect malformed input.
+ const expected = body.length >> 1
+ const buf = _Buffer.from(body, 'hex')
+ if (buf.length !== expected) throw new InvalidHexValueError(value)
+ // Copy out of Buffer pool: callers may rely on `.buffer` being a
+ // standalone ArrayBuffer (e.g. WebAuthn attestationObject round-trips).
+ const out = new Uint8Array(buf.byteLength)
+ out.set(buf)
+ return out
+ }
+
+ const length = body.length >> 1
+ const out = new Uint8Array(length)
+ for (let i = 0, j = 0; i < length; i++) {
+ const hi = nibbleTable[body.charCodeAt(j++)]!
+ const lo = nibbleTable[body.charCodeAt(j++)]!
+ if (hi === 0xff || lo === 0xff) throw new InvalidHexValueError(value)
+ out[i] = (hi << 4) | lo
+ }
+ return out
+}
+
+/** @internal */
+export function charCodeToBase16(char: number): number | undefined {
+ const v = nibbleTable[char]!
+ return v === 0xff ? undefined : v
+}
+
+/** Thrown when a value is not a valid `0x`-prefixed hex string. */
+export class InvalidHexValueError extends Errors.BaseError {
+ override readonly name = 'Hex.InvalidHexValueError'
+
+ constructor(value: unknown) {
+ super(`Value \`${value}\` is an invalid hex value.`, {
+ metaMessages: [
+ 'Hex values must start with `"0x"` and contain only hexadecimal characters (0-9, a-f, A-F).',
+ ],
+ })
+ }
+}
+
+/** Thrown when a hex string has an odd nibble count. */
+export class InvalidLengthError extends Errors.BaseError {
+ override readonly name = 'Hex.InvalidLengthError'
+
+ constructor(value: Hex) {
+ super(
+ `Hex value \`"${value}"\` is an odd length (${value.length - 2} nibbles).`,
+ {
+ metaMessages: ['It must be an even length.'],
+ },
+ )
+ }
+}
+
+/** @internal */
+export declare namespace bytesToHex {
+ type ErrorType = Errors.GlobalErrorType
+}
+
+/** @internal */
+export declare namespace hexToBytes {
+ type ErrorType =
+ | InvalidHexValueError
+ | InvalidLengthError
+ | Errors.GlobalErrorType
+}
diff --git a/src/core/internal/codec/int.ts b/src/core/internal/codec/int.ts
new file mode 100644
index 00000000..66412b10
--- /dev/null
+++ b/src/core/internal/codec/int.ts
@@ -0,0 +1,186 @@
+import * as Errors from '../../Errors.js'
+import { bytesToHex } from './hex.js'
+
+/**
+ * Decodes a big-endian unsigned `Uint8Array` into a `bigint`. When `signed` is
+ * true, applies twos-complement on the high bit.
+ *
+ * @internal
+ */
+export function bytesToBigInt(value: Uint8Array, signed?: boolean): bigint {
+ const len = value.length
+ if (len === 0) return 0n
+
+ // Fast path: unsigned big-endian read using DataView for 8-byte chunks,
+ // skipping the hex round-trip.
+ if (!signed) {
+ let val = 0n
+ let i = 0
+ if (len >= 8) {
+ const view = new DataView(value.buffer, value.byteOffset, len)
+ const tail = len & 7
+ const fullEnd = len - tail
+ while (i < fullEnd) {
+ val = (val << 64n) | view.getBigUint64(i, false)
+ i += 8
+ }
+ }
+ while (i < len) {
+ val = (val << 8n) | BigInt(value[i]!)
+ i++
+ }
+ return val
+ }
+
+ // Signed: BigInt parses hex strings faster than the per-byte loop for
+ // > 8-byte inputs in V8/JSC, so route through `bytesToHex`.
+ const hex = bytesToHex(value)
+ const n = hex === '0x' ? 0n : BigInt(hex)
+ const max_unsigned = 1n << (BigInt(len) * 8n)
+ const max_signed = max_unsigned >> 1n
+ if (n < max_signed) return n
+ return n - max_unsigned
+}
+
+/**
+ * Decodes a big-endian unsigned `Uint8Array` into a number, throwing if the
+ * value cannot be represented as a safe integer.
+ *
+ * @internal
+ */
+export function bytesToSafeNumber(value: Uint8Array, signed?: boolean): number {
+ if (!signed && value.length <= 6) {
+ // Small unsigned values fit in a number directly without BigInt round-trip.
+ let n = 0
+ for (let i = 0; i < value.length; i++) n = n * 256 + value[i]!
+ return n
+ }
+ const big = bytesToBigInt(value, signed)
+ const num = Number(big)
+ if (!Number.isSafeInteger(num)) {
+ throw new IntegerOutOfRangeError({
+ max: `${Number.MAX_SAFE_INTEGER}`,
+ min: signed ? `${Number.MIN_SAFE_INTEGER}` : '0',
+ signed,
+ value: `${num}`,
+ })
+ }
+ return num
+}
+
+/**
+ * Encodes a number/bigint into a big-endian `Uint8Array` of the given byte
+ * size (or minimal size when `size` is omitted).
+ *
+ * @internal
+ */
+export function bigIntToBytes(
+ value: number | bigint,
+ options: bigIntToBytes.Options = {},
+): Uint8Array {
+ const { signed, size } = options
+
+ // Range check (mirrors `Hex.fromNumber` semantics).
+ let value_: bigint
+ if (typeof value === 'bigint') value_ = value
+ else if (Number.isSafeInteger(value)) value_ = BigInt(value)
+ else value_ = BigInt(value)
+
+ let maxValue: bigint | undefined
+ if (size) {
+ if (signed) maxValue = (1n << (BigInt(size) * 8n - 1n)) - 1n
+ else maxValue = (1n << (BigInt(size) * 8n)) - 1n
+ } else if (typeof value === 'number') {
+ maxValue = BigInt(Number.MAX_SAFE_INTEGER)
+ }
+
+ const minValue = typeof maxValue === 'bigint' && signed ? -maxValue - 1n : 0n
+
+ if ((maxValue && value_ > maxValue) || value_ < minValue) {
+ const suffix = typeof value === 'bigint' ? 'n' : ''
+ throw new IntegerOutOfRangeError({
+ max: maxValue ? `${maxValue}${suffix}` : undefined,
+ min: `${minValue}${suffix}`,
+ signed,
+ size,
+ value: `${value}${suffix}`,
+ })
+ }
+
+ // Normalize negatives to two's-complement before encoding.
+ const n =
+ signed && value_ < 0
+ ? BigInt.asUintN((size ?? bigIntByteLength(-value_) + 1) * 8, value_)
+ : value_
+
+ const minBytes = bigIntByteLength(n)
+ const length = size ?? Math.max(minBytes, 1)
+ const out = new Uint8Array(length)
+ // Right-aligned big-endian write.
+ let i = length - 1
+ let rem = n
+ while (rem > 0n && i >= 0) {
+ out[i--] = Number(rem & 0xffn)
+ rem >>= 8n
+ }
+ return out
+}
+
+/** @internal */
+export function bigIntByteLength(n: bigint): number {
+ if (n === 0n) return 0
+ let len = 0
+ let v = n < 0n ? -n : n
+ while (v > 0n) {
+ len++
+ v >>= 8n
+ }
+ return len
+}
+
+/** Thrown when a value cannot be represented as a safe integer. */
+export class IntegerOutOfRangeError extends Errors.BaseError {
+ override readonly name = 'Hex.IntegerOutOfRangeError'
+
+ constructor({
+ max,
+ min,
+ signed,
+ size,
+ value,
+ }: {
+ max?: string | undefined
+ min: string
+ signed?: boolean | undefined
+ size?: number | undefined
+ value: string
+ }) {
+ super(
+ `Number \`${value}\` is not in safe${
+ size ? ` ${size * 8}-bit` : ''
+ }${signed ? ' signed' : ' unsigned'} integer range ${max ? `(\`${min}\` to \`${max}\`)` : `(above \`${min}\`)`}`,
+ )
+ }
+}
+
+/** @internal */
+export declare namespace bigIntToBytes {
+ type Options = {
+ /** Whether the value is signed. */
+ signed?: boolean | undefined
+ /** Size (in bytes) of the output. */
+ size?: number | undefined
+ }
+
+ type ErrorType = IntegerOutOfRangeError | Errors.GlobalErrorType
+}
+
+/** @internal */
+export declare namespace bytesToBigInt {
+ type ErrorType = Errors.GlobalErrorType
+}
+
+/** @internal */
+export declare namespace bytesToSafeNumber {
+ type ErrorType = IntegerOutOfRangeError | Errors.GlobalErrorType
+}
diff --git a/src/core/internal/codec/utf8.ts b/src/core/internal/codec/utf8.ts
new file mode 100644
index 00000000..97993628
--- /dev/null
+++ b/src/core/internal/codec/utf8.ts
@@ -0,0 +1,11 @@
+/**
+ * Shared `TextEncoder` / `TextDecoder` singletons used by primitive and codec
+ * modules. Centralizing them avoids constructing redundant instances per
+ * module and lets engines hoist them to module init time.
+ *
+ * @internal
+ */
+export const encoder = /*#__PURE__*/ new TextEncoder()
+
+/** @internal */
+export const decoder = /*#__PURE__*/ new TextDecoder()
diff --git a/src/core/internal/cursor.ts b/src/core/internal/cursor.ts
index d9f21450..99081d14 100644
--- a/src/core/internal/cursor.ts
+++ b/src/core/internal/cursor.ts
@@ -6,7 +6,16 @@ export type Cursor = {
bytes: Bytes
dataView: DataView
position: number
- positionReadCount: Map
+ /**
+ * Highest cursor position observed so far. Used to short-circuit
+ * `_touch` when reads are monotonically forward (the common ABI
+ * decode case), avoiding `Map.get` / `Map.set` per `read*` call.
+ *
+ * @internal
+ */
+ maxLinearPosition: number
+ /** Lazy: only allocated when a back-jump re-read is observed. */
+ positionReadCount: Map | undefined
recursiveReadCount: number
recursiveReadLimit: number
remaining: number
@@ -41,7 +50,8 @@ const staticCursor: Cursor = {
bytes: new Uint8Array(),
dataView: new DataView(new ArrayBuffer(0)),
position: 0,
- positionReadCount: new Map(),
+ maxLinearPosition: 0,
+ positionReadCount: undefined,
recursiveReadCount: 0,
recursiveReadLimit: Number.POSITIVE_INFINITY,
assertReadLimit() {
@@ -65,7 +75,7 @@ const staticCursor: Cursor = {
this.position = position
},
getReadCount(position) {
- return this.positionReadCount.get(position || this.position) || 0
+ return this.positionReadCount?.get(position || this.position) || 0
},
incrementPosition(offset) {
if (offset < 0) throw new NegativeOffsetError({ offset })
@@ -190,9 +200,22 @@ const staticCursor: Cursor = {
},
_touch() {
if (this.recursiveReadLimit === Number.POSITIVE_INFINITY) return
- const count = this.getReadCount()
- this.positionReadCount.set(this.position, count + 1)
- if (count > 0) this.recursiveReadCount++
+ // Fast path: if reads are advancing monotonically forward (no
+ // back-jumps via `setPosition`), no slot can be re-read. Skip the
+ // `Map` bookkeeping entirely. Real ABI decodes are dominated by
+ // forward reads through static parameter heads.
+ //
+ // `maxLinearPosition` tracks the smallest position the cursor has
+ // not yet observed (i.e. one past the highest byte touched). Any
+ // subsequent read whose start position is strictly less than this
+ // frontier overlaps already-read bytes and must be charged to the
+ // recursive read budget.
+ const next = this.position + 1
+ if (next > this.maxLinearPosition) {
+ this.maxLinearPosition = next
+ return
+ }
+ this.recursiveReadCount++
},
}
@@ -208,7 +231,8 @@ export function create(
bytes.byteOffset,
bytes.byteLength,
)
- cursor.positionReadCount = new Map()
+ cursor.maxLinearPosition = 0
+ cursor.positionReadCount = undefined
cursor.recursiveReadLimit = recursiveReadLimit
return cursor
}
diff --git a/src/core/internal/hex.ts b/src/core/internal/hex.ts
index 645b9c9a..735580ca 100644
--- a/src/core/internal/hex.ts
+++ b/src/core/internal/hex.ts
@@ -3,11 +3,11 @@ import * as Hex from '../Hex.js'
/** @internal */
export function assertSize(hex: Hex.Hex, size_: number): void {
- if (Hex.size(hex) > size_)
- throw new Hex.SizeOverflowError({
- givenSize: Hex.size(hex),
- maxSize: size_,
- })
+ const len = hex.length - 2
+ // Ceil to match `Hex.size` semantics for odd-nibble inputs (e.g. `0x0`).
+ const size = (len + 1) >> 1
+ if (size > size_)
+ throw new Hex.SizeOverflowError({ givenSize: size, maxSize: size_ })
}
/** @internal */
@@ -20,11 +20,13 @@ export declare namespace assertSize {
/** @internal */
export function assertStartOffset(value: Hex.Hex, start?: number | undefined) {
- if (typeof start === 'number' && start > 0 && start > Hex.size(value) - 1)
+ if (typeof start !== 'number' || start <= 0) return
+ const size = (value.length - 2 + 1) >> 1
+ if (start > size - 1)
throw new Hex.SliceOffsetOutOfBoundsError({
offset: start,
position: 'start',
- size: Hex.size(value),
+ size,
})
}
@@ -41,17 +43,14 @@ export function assertEndOffset(
start?: number | undefined,
end?: number | undefined,
) {
- if (
- typeof start === 'number' &&
- typeof end === 'number' &&
- Hex.size(value) !== end - start
- ) {
+ if (typeof start !== 'number' || typeof end !== 'number') return
+ const size = (value.length - 2 + 1) >> 1
+ if (size !== end - start)
throw new Hex.SliceOffsetOutOfBoundsError({
offset: end,
position: 'end',
- size: Hex.size(value),
+ size,
})
- }
}
export declare namespace assertEndOffset {
@@ -67,15 +66,16 @@ export function pad(hex_: Hex.Hex, options: pad.Options = {}) {
if (size === 0) return hex_
- const hex = hex_.replace('0x', '')
- if (hex.length > size * 2)
+ const hex = hex_.slice(2)
+ const target = size * 2
+ if (hex.length > target)
throw new Hex.SizeExceedsPaddingSizeError({
- size: Math.ceil(hex.length / 2),
+ size: (hex.length + 1) >> 1,
targetSize: size,
type: 'Hex',
})
- return `0x${hex[dir === 'right' ? 'padEnd' : 'padStart'](size * 2, '0')}` as Hex.Hex
+ return `0x${dir === 'right' ? hex.padEnd(target, '0') : hex.padStart(target, '0')}` as Hex.Hex
}
/** @internal */
diff --git a/src/core/internal/lru.ts b/src/core/internal/lru.ts
index 0395e314..b2b73d16 100644
--- a/src/core/internal/lru.ts
+++ b/src/core/internal/lru.ts
@@ -32,3 +32,27 @@ export class LruMap extends Map {
return this
}
}
+
+/**
+ * @internal
+ *
+ * Map with a bounded FIFO eviction policy. Cheaper than {@link LruMap} on hot
+ * `get` paths because reads do not reorder entries; only writes touch the
+ * eviction queue.
+ */
+export class BoundedMap extends Map {
+ maxSize: number
+
+ constructor(size: number) {
+ super()
+ this.maxSize = size
+ }
+
+ override set(key: string, value: value) {
+ if (!super.has(key) && this.maxSize && this.size >= this.maxSize) {
+ const firstKey = this.keys().next().value
+ if (firstKey !== undefined) this.delete(firstKey)
+ }
+ return super.set(key, value)
+ }
+}
diff --git a/src/core/internal/promise.ts b/src/core/internal/promise.ts
index 2592a490..ce240d1f 100644
--- a/src/core/internal/promise.ts
+++ b/src/core/internal/promise.ts
@@ -6,22 +6,20 @@ export function withTimeout