@1001-digital/proxies 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 1001.digital
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # @1001-digital/proxies
2
+
3
+ Ethereum proxy pattern detection primitives for TypeScript — ERC-2535 diamonds, EIP-1967, EIP-1167, beacon, Safe, EIP-1822, EIP-897.
4
+
5
+ Given a contract address, resolve where the real code lives: one implementation (plain proxy) or N facets (diamond). Uniform detect → enrich → compose pipeline across all patterns.
6
+
7
+ Narrow on purpose: this package knows proxy conventions, selectors, and ABIs. Anything richer — Sourcify, NatSpec, repository metadata — is the consumer's concern. Bring your own enricher.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pnpm add @1001-digital/proxies
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Detect + fetch a proxy
18
+
19
+ ```ts
20
+ import { createProxies } from '@1001-digital/proxies'
21
+
22
+ const proxies = createProxies()
23
+
24
+ const result = await proxies.fetch(
25
+ 'https://eth.llamarpc.com',
26
+ '0xProxyAddress…',
27
+ )
28
+
29
+ if (result) {
30
+ console.log(result.pattern) // 'eip-1967' | 'eip-2535-diamond' | …
31
+ console.log(result.targets) // [{ address, selectors?, abi? }, …]
32
+ console.log(result.compositeAbi) // undefined — no enricher configured
33
+ }
34
+ ```
35
+
36
+ ### Enrich with Sourcify (or anything else)
37
+
38
+ The enricher returns each target's ABI. Anything richer (sources, bytecode,
39
+ documentation, …) is the consumer's concern — see *Detect and do your own
40
+ enrichment* below.
41
+
42
+ ```ts
43
+ import { createProxies } from '@1001-digital/proxies'
44
+
45
+ async function sourcifyAbi(address: string) {
46
+ const res = await fetch(
47
+ `https://sourcify.dev/server/v2/contract/1/${address}?fields=abi`,
48
+ )
49
+ if (!res.ok) return null
50
+ const { abi } = await res.json()
51
+ return { abi }
52
+ }
53
+
54
+ const proxies = createProxies({ enrich: sourcifyAbi })
55
+
56
+ const result = await proxies.fetch(
57
+ 'https://eth.llamarpc.com',
58
+ '0xProxyAddress…',
59
+ )
60
+
61
+ if (result) {
62
+ console.log(result.targets[0].abi) // ABI (filtered to selectors for diamonds, full for plain proxies)
63
+ console.log(result.compositeAbi) // all target ABIs deduped by selector
64
+ }
65
+ ```
66
+
67
+ ### Detect and do your own enrichment
68
+
69
+ For richer per-target metadata, use `detect` and own the enrichment step
70
+ end-to-end. `filterAbiBySelectors` and `buildCompositeAbi` remain useful
71
+ primitives.
72
+
73
+ ```ts
74
+ import {
75
+ createProxies,
76
+ filterAbiBySelectors,
77
+ buildCompositeAbi,
78
+ } from '@1001-digital/proxies'
79
+
80
+ const proxies = createProxies()
81
+ const raw = await proxies.detect(rpc, address)
82
+
83
+ if (raw) {
84
+ const enriched = await Promise.all(raw.targets.map(async t => {
85
+ const src = await mySource(t.address)
86
+ return {
87
+ ...t,
88
+ abi: src?.abi && t.selectors
89
+ ? filterAbiBySelectors(src.abi, t.selectors)
90
+ : src?.abi,
91
+ metadata: src?.metadata,
92
+ }
93
+ }))
94
+
95
+ const compositeAbi = buildCompositeAbi(
96
+ enriched.map(t => t.abi).filter((a): a is unknown[] => !!a),
97
+ )
98
+ }
99
+ ```
100
+
101
+ ### Standalone primitives
102
+
103
+ All low-level utilities are exported directly — use them without the factory:
104
+
105
+ ```ts
106
+ import {
107
+ detectProxy,
108
+ detectDiamond,
109
+ detectEip1967,
110
+ decodeFacets,
111
+ computeSelector,
112
+ canonicalSignature,
113
+ filterAbiBySelectors,
114
+ buildCompositeAbi,
115
+ enrichTargets,
116
+ } from '@1001-digital/proxies'
117
+
118
+ decodeFacets('0x…') // parse a facets() return value
119
+ computeSelector('transfer(address,uint256)') // '0xa9059cbb'
120
+ canonicalSignature({ type: 'function', name: 'transfer', inputs: [/*…*/] })
121
+ ```
122
+
123
+ ## API
124
+
125
+ ### `createProxies(config?)`
126
+
127
+ Creates a proxies client.
128
+
129
+ **Config options:**
130
+
131
+ | Option | Type | Default | Description |
132
+ |--------|------|---------|-------------|
133
+ | `enrich` | `TargetEnricher` | — | Default per-target enricher. Called with each target address; return `{ abi? }` or `null`. Errors are swallowed per-target. |
134
+ | `fetch` | `typeof fetch` | `globalThis.fetch` | Custom fetch function. |
135
+
136
+ **Returns** a `ProxiesClient` with:
137
+
138
+ - **`detect(rpc, address)`** — `Promise<RawProxy | null>`. On-chain probe only.
139
+ - **`fetch(rpc, address, options?)`** — `Promise<Proxy | null>`. Detect, enrich, and compose.
140
+ - `options.enrich` — per-call enricher (overrides config-level)
141
+ - `options.enrich = false` — skip enrichment for this call
142
+
143
+ ### Detection
144
+
145
+ - **`detectProxy(rpc, address, fetchFn)`** — tries all patterns in priority order (`diamond → 1967 → 1967-beacon → 1822 → 1167 → safe → 897`), returns the first match.
146
+ - **`detectDiamond`** — ERC-165 probe, then `facets()` fallback.
147
+ - **`detectEip1967`** — reads impl slot `0x3608…3bc3`; optionally admin slot.
148
+ - **`detectEip1967Beacon`** — reads beacon slot `0xa3f0…750d`, then `implementation()` on the beacon.
149
+ - **`detectEip1822`** — reads PROXIABLE slot `0xc5f1…f8e2`.
150
+ - **`detectEip1167`** — `eth_getCode`, matches minimal proxy bytecode (`363d3d…bf3`).
151
+ - **`detectGnosisSafe`** — reads storage slot 0.
152
+ - **`detectEip897`** — calls `implementation()` as a last resort.
153
+
154
+ Each detector returns `null` if the pattern doesn't match; otherwise a `RawProxy`.
155
+
156
+ ### Composition
157
+
158
+ - **`enrichTargets(targets, enricher | null)`** — applies the enricher to each target; ABIs are filtered to live selectors for diamonds, passed through for plain proxies.
159
+ - **`buildCompositeAbi(abis)`** — pure; dedupes functions/events/errors across ABIs (first-wins).
160
+
161
+ ### Utilities
162
+
163
+ - **`decodeFacets(hex)`** — pure; decodes `(address, bytes4[])[]` loupe return.
164
+ - **`computeSelector(signature)`** — pure; keccak256-based 4-byte selector.
165
+ - **`canonicalSignature(abiEntry)`** — pure; normalizes tuples/arrays into a signature string.
166
+ - **`filterAbiBySelectors(abi, selectors)`** — pure; keeps non-functions, filters functions by selector.
167
+ - **`ethCall`**, **`ethGetStorageAt`**, **`ethGetCode`** — minimal JSON-RPC helpers.
168
+
169
+ ### Constants
170
+
171
+ ```ts
172
+ SUPPORTS_INTERFACE_SELECTOR // '0x01ffc9a7'
173
+ DIAMOND_LOUPE_INTERFACE_ID // '0x48e2b093'
174
+ FACETS_SELECTOR // '0x7a0ed627'
175
+ IMPLEMENTATION_SELECTOR // '0x5c60da1b'
176
+ EIP1967_IMPL_SLOT
177
+ EIP1967_BEACON_SLOT
178
+ EIP1967_ADMIN_SLOT
179
+ EIP1822_PROXIABLE_SLOT
180
+ EIP1167_BYTECODE_PREFIX
181
+ EIP1167_BYTECODE_SUFFIX
182
+ ZERO_ADDRESS
183
+ ```
184
+
185
+ ### Errors
186
+
187
+ - **`ProxiesError`** — base class.
188
+ - **`ProxiesDecodeError`** — malformed `facets()` return.
189
+ - **`ProxiesFetchError`** — JSON-RPC transport error.
190
+
191
+ The client's `detect` and `fetch` methods swallow RPC-layer errors and return
192
+ `null`; only `decodeFacets` (called directly) can throw `ProxiesDecodeError`
193
+ on malformed input.
194
+
195
+ ## Shapes
196
+
197
+ ### `ProxyPattern`
198
+
199
+ ```ts
200
+ type ProxyPattern =
201
+ | 'eip-2535-diamond'
202
+ | 'eip-1967'
203
+ | 'eip-1967-beacon'
204
+ | 'eip-1822'
205
+ | 'eip-1167'
206
+ | 'gnosis-safe'
207
+ | 'eip-897'
208
+ ```
209
+
210
+ ### `ResolvedTarget`
211
+
212
+ ```ts
213
+ {
214
+ address: string
215
+ // undefined = all selectors route here (plain proxy)
216
+ // defined = diamond facet selector scope
217
+ selectors?: string[]
218
+ }
219
+ ```
220
+
221
+ ### `RawProxy`
222
+
223
+ ```ts
224
+ {
225
+ pattern: ProxyPattern
226
+ targets: ResolvedTarget[] // 1 entry except for diamonds
227
+ beacon?: string // only for eip-1967-beacon
228
+ admin?: string // only for eip-1967 when admin slot is set
229
+ }
230
+ ```
231
+
232
+ ### `EnrichedTarget`
233
+
234
+ ```ts
235
+ {
236
+ address: string
237
+ selectors?: string[]
238
+ abi?: unknown[]
239
+ }
240
+ ```
241
+
242
+ ### `Proxy`
243
+
244
+ ```ts
245
+ {
246
+ pattern: ProxyPattern
247
+ targets: EnrichedTarget[]
248
+ beacon?: string
249
+ admin?: string
250
+ compositeAbi?: unknown[] // deduped by selector
251
+ }
252
+ ```
253
+
254
+ ### `TargetEnrichment`
255
+
256
+ ```ts
257
+ { abi?: unknown[] }
258
+ ```
259
+
260
+ ### `TargetEnricher`
261
+
262
+ ```ts
263
+ type TargetEnricher = (address: string) => Promise<TargetEnrichment | null>
264
+ ```
265
+
266
+ ## Design notes
267
+
268
+ - **Narrow scope** — detects patterns and composes ABIs; no opinion on documentation formats or richer per-target metadata.
269
+ - **Dependency-injected enrichment** — the factory wires I/O when you ask; the primitives work offline.
270
+ - **First-wins ABI dedup** — pass the most authoritative ABI first (e.g. main contract → impl, or main diamond → facets).
271
+ - **Single-hop resolution** — if a resolved implementation is itself a proxy, `detectProxy` does not recurse. Beacon stays supported as a defined two-step pattern.
272
+ - **Minimal runtime deps** — only `@noble/hashes` for keccak256.
273
+
274
+ ## License
275
+
276
+ MIT
@@ -0,0 +1,353 @@
1
+ export declare interface AbiFunctionLike {
2
+ type: string;
3
+ name?: string;
4
+ inputs?: AbiParam[];
5
+ }
6
+
7
+ export declare interface AbiParam {
8
+ type: string;
9
+ components?: AbiParam[];
10
+ }
11
+
12
+ /**
13
+ * Combine multiple ABIs into a single composite. First-occurrence wins:
14
+ * - functions deduped by selector
15
+ * - events and errors deduped by `type:name(canonicalInputs)`
16
+ * - other entries (constructor, fallback, receive) kept as-is
17
+ */
18
+ export declare function buildCompositeAbi(abis: unknown[][]): unknown[];
19
+
20
+ /**
21
+ * Build the canonical signature for an ABI function/event/error entry,
22
+ * recursively expanding `tuple` into `(innerTypes)` while preserving any
23
+ * `[]` or `[N]` array suffix. This is the form hashed to produce selectors.
24
+ */
25
+ export declare function canonicalSignature(fn: AbiFunctionLike): string;
26
+
27
+ /**
28
+ * Compute the 4-byte selector for a canonical function signature.
29
+ * Example: `computeSelector('transfer(address,uint256)')` → `'0xa9059cbb'`.
30
+ */
31
+ export declare function computeSelector(signature: string): string;
32
+
33
+ /**
34
+ * Create a proxy inspection client.
35
+ *
36
+ * ```ts
37
+ * const proxies = createProxies()
38
+ * const result = await proxies.fetch('https://rpc…', '0x…')
39
+ * if (result) console.log(result.pattern, result.targets)
40
+ * ```
41
+ *
42
+ * Pass `config.enrich` to populate each target's ABI from any source
43
+ * (Sourcify, Etherscan, a local cache). Omit it to get raw targets with
44
+ * address + (optional) selectors only.
45
+ */
46
+ export declare function createProxies(config?: ProxiesConfig): ProxiesClient;
47
+
48
+ /**
49
+ * Literal on-chain facet tuple (`(address, bytes4[])`) — the shape returned by
50
+ * the ERC-2535 loupe `facets()` call. Use {@link decodeFacets} to parse it.
51
+ */
52
+ export declare interface DecodedFacet {
53
+ facetAddress: string;
54
+ functionSelectors: string[];
55
+ }
56
+
57
+ /**
58
+ * Decode the return value of `facets()` — type `(address, bytes4[])[]`.
59
+ * Throws {@link ProxiesDecodeError} on malformed input.
60
+ */
61
+ export declare function decodeFacets(hex: string): DecodedFacet[];
62
+
63
+ /**
64
+ * Detect whether a contract implements ERC-2535 (Diamond) and return its
65
+ * facets as a {@link RawProxy}. Returns `null` if not a diamond.
66
+ *
67
+ * Strategy:
68
+ * 1. Try ERC-165 `supportsInterface(0x48e2b093)`.
69
+ * - Valid bool `true` → fetch and return facets
70
+ * - Valid bool `false` → definitively not a diamond (null)
71
+ * - Malformed / error → fall through to step 2
72
+ * 2. Probe `facets()` directly. If it returns a non-empty decoded array,
73
+ * treat the contract as a diamond.
74
+ *
75
+ * Zero-address facets (deleted selectors) are filtered out of the result.
76
+ */
77
+ export declare function detectDiamond(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<RawProxy | null>;
78
+
79
+ /**
80
+ * Detect an EIP-1167 minimal proxy (clone) from runtime bytecode.
81
+ *
82
+ * Matches the canonical 45-byte runtime:
83
+ * `363d3d373d3d3d363d73<20-byte impl>5af43d82803e903d91602b57fd5bf3`
84
+ *
85
+ * Does NOT match the "optimized" variants (e.g. push-based relays) that some
86
+ * tooling emits — this is the standards-compliant shape per EIP-1167.
87
+ *
88
+ * Returns `null` when the bytecode does not match.
89
+ */
90
+ export declare function detectEip1167(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<RawProxy | null>;
91
+
92
+ /**
93
+ * Detect an EIP-1822 UUPS proxy.
94
+ *
95
+ * Reads the PROXIABLE slot (`keccak256('PROXIABLE')`). Returns `null` when the
96
+ * slot is empty or malformed.
97
+ *
98
+ * Note: most modern UUPS proxies use the EIP-1967 slot instead — this detector
99
+ * only catches the older EIP-1822 convention.
100
+ */
101
+ export declare function detectEip1822(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<RawProxy | null>;
102
+
103
+ /**
104
+ * Detect an EIP-1967 transparent or UUPS proxy.
105
+ *
106
+ * Reads the implementation slot (`0x3608…3bc3`). If non-zero, reads the admin
107
+ * slot in parallel and attaches it when present.
108
+ *
109
+ * Returns `null` when the implementation slot is empty or malformed.
110
+ */
111
+ export declare function detectEip1967(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<RawProxy | null>;
112
+
113
+ /**
114
+ * Detect an EIP-1967 beacon proxy.
115
+ *
116
+ * Reads the beacon slot (`0xa3f0…750d`); if non-zero, calls `implementation()`
117
+ * on the beacon contract. Returns `null` when the slot is empty or the beacon
118
+ * call fails.
119
+ */
120
+ export declare function detectEip1967Beacon(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<RawProxy | null>;
121
+
122
+ /**
123
+ * Detect an EIP-897 delegate proxy by calling `implementation()` as a view
124
+ * function.
125
+ *
126
+ * Last-resort detector — any contract with a public `implementation()` view
127
+ * returning a non-zero address will match. Only reached when all other
128
+ * pattern detectors have returned `null`.
129
+ *
130
+ * Returns `null` when the call reverts or returns zero.
131
+ */
132
+ export declare function detectEip897(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<RawProxy | null>;
133
+
134
+ /**
135
+ * Detect a Gnosis Safe proxy — the singleton (implementation) address is
136
+ * stored at storage slot 0.
137
+ *
138
+ * Returns `null` when slot 0 is empty or not address-shaped.
139
+ *
140
+ * Cheap, but has a higher false-positive surface than the standard slots
141
+ * because any contract may use storage slot 0. Detector priority puts this
142
+ * after all EIP-standard patterns to keep the match rate clean.
143
+ */
144
+ export declare function detectGnosisSafe(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<RawProxy | null>;
145
+
146
+ /**
147
+ * Detect any supported proxy pattern at `address`.
148
+ *
149
+ * Tries the built-in detectors in priority order (`eip-2535-diamond → eip-1967
150
+ * → eip-1967-beacon → eip-1822 → eip-1167 → gnosis-safe → eip-897`). Returns
151
+ * the first match, or `null` when no pattern matches.
152
+ *
153
+ * Each detector runs with error isolation — an RPC failure in one pattern does
154
+ * not poison the probe for subsequent ones.
155
+ *
156
+ * Single-hop only: if the resolved implementation is itself a proxy, the
157
+ * result describes the direct pattern only. Re-run detection on the resolved
158
+ * implementation to chain manually.
159
+ */
160
+ export declare function detectProxy(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<RawProxy | null>;
161
+
162
+ /** ERC-2535 Diamond Loupe `IDiamondLoupe` interface ID. */
163
+ export declare const DIAMOND_LOUPE_INTERFACE_ID = "0x48e2b093";
164
+
165
+ /** Prefix preceding the 20-byte implementation address in an EIP-1167 minimal proxy. */
166
+ export declare const EIP1167_BYTECODE_PREFIX = "363d3d373d3d3d363d73";
167
+
168
+ /** Suffix following the 20-byte implementation address in an EIP-1167 minimal proxy. */
169
+ export declare const EIP1167_BYTECODE_SUFFIX = "5af43d82803e903d91602b57fd5bf3";
170
+
171
+ /** EIP-1822 UUPS PROXIABLE slot: `keccak256('PROXIABLE')`. */
172
+ export declare const EIP1822_PROXIABLE_SLOT = "0xc5f16f0fcc7e328891200cdca4c1c57b2b360c12265401510d42209b5829f8e2";
173
+
174
+ /** EIP-1967 admin slot: `keccak256('eip1967.proxy.admin') - 1`. */
175
+ export declare const EIP1967_ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103";
176
+
177
+ /** EIP-1967 beacon slot: `keccak256('eip1967.proxy.beacon') - 1`. */
178
+ export declare const EIP1967_BEACON_SLOT = "0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50";
179
+
180
+ /** EIP-1967 implementation slot: `keccak256('eip1967.proxy.implementation') - 1`. */
181
+ export declare const EIP1967_IMPL_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
182
+
183
+ export declare interface EnrichedTarget {
184
+ address: string;
185
+ /** Selector scope for diamond facets; undefined for single-impl proxies (all selectors). */
186
+ selectors?: string[];
187
+ /**
188
+ * ABI for this target. Filtered to `selectors` for diamonds; full implementation
189
+ * ABI for single-impl proxies.
190
+ */
191
+ abi?: unknown[];
192
+ }
193
+
194
+ /**
195
+ * Apply an enricher to each resolved target, producing an `EnrichedTarget[]`.
196
+ *
197
+ * Enricher errors are swallowed per-target — one bad fetch does not fail the
198
+ * whole resolution. Pass `null` to skip enrichment entirely (targets will
199
+ * carry only `address` + `selectors`).
200
+ *
201
+ * When a target has `selectors` defined (diamond facets), the returned ABI is
202
+ * filtered to those selectors. When `selectors` is undefined (any single-impl
203
+ * proxy pattern), the full implementation ABI is passed through untouched.
204
+ */
205
+ export declare function enrichTargets(targets: ResolvedTarget[], enrich: TargetEnricher | null): Promise<EnrichedTarget[]>;
206
+
207
+ /**
208
+ * Minimal JSON-RPC `eth_call` client. Invokes a view call on the given address
209
+ * at the latest block and returns the raw hex result.
210
+ */
211
+ export declare function ethCall(rpc: string, to: string, data: string, fetchFn: typeof globalThis.fetch): Promise<string>;
212
+
213
+ /**
214
+ * Minimal JSON-RPC `eth_getCode` client. Returns the deployed runtime bytecode
215
+ * at the latest block.
216
+ */
217
+ export declare function ethGetCode(rpc: string, address: string, fetchFn: typeof globalThis.fetch): Promise<string>;
218
+
219
+ /**
220
+ * Minimal JSON-RPC `eth_getStorageAt` client. Reads a single 32-byte storage
221
+ * slot at the latest block.
222
+ */
223
+ export declare function ethGetStorageAt(rpc: string, address: string, slot: string, fetchFn: typeof globalThis.fetch): Promise<string>;
224
+
225
+ /** ERC-2535 `facets()` — returns `(address, bytes4[])[]`. */
226
+ export declare const FACETS_SELECTOR = "0x7a0ed627";
227
+
228
+ export declare interface FetchProxyOptions {
229
+ /**
230
+ * Override the client's default enricher for this call. Pass `false` to
231
+ * disable enrichment entirely (address + selectors only).
232
+ */
233
+ enrich?: TargetEnricher | false;
234
+ }
235
+
236
+ /**
237
+ * Keep all non-function ABI entries; keep function entries whose computed
238
+ * selector is in the provided selector set. Verified facet contracts may
239
+ * declare extra functions not actually mounted on the diamond — this trims them.
240
+ */
241
+ export declare function filterAbiBySelectors(abi: unknown[], selectors: string[]): unknown[];
242
+
243
+ /** `implementation()` — used by EIP-897 proxies and EIP-1967 beacons. */
244
+ export declare const IMPLEMENTATION_SELECTOR = "0x5c60da1b";
245
+
246
+ /**
247
+ * Parse a 32-byte ABI-encoded address (right-padded). Returns the lowercase
248
+ * `0x` address, or `null` if the payload is not a well-formed address (wrong
249
+ * length, or non-zero high bytes).
250
+ */
251
+ export declare function parseAddress(hex: string): string | null;
252
+
253
+ export declare interface ProxiesClient {
254
+ /**
255
+ * Detect the proxy pattern and resolve its target(s). Returns `null` if the
256
+ * contract is not a recognised proxy.
257
+ */
258
+ detect: (rpc: string, address: string) => Promise<RawProxy | null>;
259
+ /**
260
+ * Detect + enrich. Returns `null` when the contract is not a recognised proxy.
261
+ * Uses the config-level enricher by default; override per-call via `options.enrich`.
262
+ */
263
+ fetch: (rpc: string, address: string, options?: FetchProxyOptions) => Promise<Proxy_2 | null>;
264
+ }
265
+
266
+ export declare interface ProxiesConfig {
267
+ /**
268
+ * Default enricher used by `fetch` when no per-call enricher is passed.
269
+ * Receives each target address and returns whatever ABI the caller can find.
270
+ * Leave unset to return targets with address + selectors only.
271
+ */
272
+ enrich?: TargetEnricher;
273
+ /** Custom fetch function. Default: `globalThis.fetch`. */
274
+ fetch?: typeof globalThis.fetch;
275
+ }
276
+
277
+ /** Raised when the on-chain `facets()` return value cannot be decoded. */
278
+ export declare class ProxiesDecodeError extends ProxiesError {
279
+ constructor(message: string, options?: ErrorOptions);
280
+ }
281
+
282
+ export declare class ProxiesError extends Error {
283
+ constructor(message: string, options?: ErrorOptions);
284
+ }
285
+
286
+ /** Raised when a JSON-RPC request fails at the transport level. */
287
+ export declare class ProxiesFetchError extends ProxiesError {
288
+ readonly status: number;
289
+ constructor(message: string, details: {
290
+ status: number;
291
+ }, options?: ErrorOptions);
292
+ }
293
+
294
+ declare interface Proxy_2 {
295
+ pattern: ProxyPattern;
296
+ targets: EnrichedTarget[];
297
+ beacon?: string;
298
+ admin?: string;
299
+ /** Composite ABI across targets, deduped by selector (first-wins). */
300
+ compositeAbi?: unknown[];
301
+ }
302
+ export { Proxy_2 as Proxy }
303
+
304
+ /** Discriminator for all supported proxy patterns. */
305
+ export declare type ProxyPattern = 'eip-2535-diamond' | 'eip-1967' | 'eip-1967-beacon' | 'eip-1822' | 'eip-1167' | 'gnosis-safe' | 'eip-897';
306
+
307
+ /**
308
+ * Raw on-chain detection result. Contains a pattern discriminator and the
309
+ * resolved target(s). Single-impl proxies carry exactly one target; diamonds
310
+ * carry one per facet.
311
+ */
312
+ export declare interface RawProxy {
313
+ pattern: ProxyPattern;
314
+ targets: ResolvedTarget[];
315
+ /** EIP-1967 beacon address (only set for `eip-1967-beacon`). */
316
+ beacon?: string;
317
+ /** EIP-1967 admin address (only set for `eip-1967` when the admin slot is non-zero). */
318
+ admin?: string;
319
+ }
320
+
321
+ /**
322
+ * A resolved target behind a proxy — an implementation address, with optional
323
+ * selector scope.
324
+ *
325
+ * - `selectors: string[]` — this target serves exactly these selectors (diamond facets).
326
+ * - `selectors: undefined` — this target receives all calls (every other proxy pattern).
327
+ */
328
+ export declare interface ResolvedTarget {
329
+ address: string;
330
+ selectors?: string[];
331
+ }
332
+
333
+ /** ERC-165 `supportsInterface(bytes4)`. */
334
+ export declare const SUPPORTS_INTERFACE_SELECTOR = "0x01ffc9a7";
335
+
336
+ /**
337
+ * User-supplied per-target enricher. Receives a target's address and returns
338
+ * its ABI. Return `null` for unknown targets — errors are swallowed per-target
339
+ * so one bad fetch does not fail the whole resolution.
340
+ *
341
+ * The package is intentionally narrow here: it only composes ABIs. For
342
+ * richer per-target metadata, use {@link ProxiesClient.detect} and enrich
343
+ * the raw targets yourself.
344
+ */
345
+ export declare type TargetEnricher = (address: string) => Promise<TargetEnrichment | null>;
346
+
347
+ export declare interface TargetEnrichment {
348
+ abi?: unknown[];
349
+ }
350
+
351
+ export declare const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
352
+
353
+ export { }