voltaire-effect 0.3.0 → 1.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/dist/{X25519Test-D5Q-5fL9.d.ts → X25519Test-avt1DUgp.d.ts} +231 -6
- package/dist/crypto/index.d.ts +2 -2
- package/dist/crypto/index.js +72 -2
- package/dist/{index-3UKSP3cd.d.ts → index-DxwZo3xo.d.ts} +7781 -5513
- package/dist/index.d.ts +990 -3096
- package/dist/index.js +2374 -1652
- package/dist/native/index.d.ts +6 -6
- package/dist/native/index.js +2399 -1677
- package/dist/primitives/index.d.ts +7 -6
- package/dist/primitives/index.js +2966 -2361
- package/dist/services/index.d.ts +1631 -1255
- package/dist/services/index.js +4493 -3977
- package/package.json +7 -3
- package/src/crypto/Signers/SignersService.ts +1 -1
- package/src/crypto/Signers/errors.ts +29 -0
- package/src/crypto/Signers/index.ts +1 -0
- package/src/crypto/Signers/operations.ts +26 -8
- package/src/crypto/index.ts +10 -11
- package/src/index.ts +1 -2
- package/src/jsonrpc/Anvil.ts +13 -8
- package/src/jsonrpc/Eth.ts +13 -8
- package/src/jsonrpc/Hardhat.ts +13 -8
- package/src/jsonrpc/IdCounter.ts +21 -5
- package/src/jsonrpc/JsonRpc.test.ts +126 -61
- package/src/jsonrpc/Net.ts +13 -8
- package/src/jsonrpc/Request.ts +16 -8
- package/src/jsonrpc/Txpool.ts +13 -8
- package/src/jsonrpc/Wallet.ts +13 -8
- package/src/jsonrpc/Web3.ts +13 -8
- package/src/jsonrpc/index.ts +1 -1
- package/src/primitives/Abi/AbiSchema.ts +3 -4
- package/src/primitives/Abi/fromBytecode.test.ts +47 -0
- package/src/primitives/Abi/fromBytecode.ts +81 -0
- package/src/primitives/Abi/index.ts +3 -0
- package/src/primitives/AccessList/from.ts +12 -9
- package/src/primitives/Address/Checksummed.ts +21 -27
- package/src/primitives/Address/from.ts +12 -15
- package/src/primitives/Address/toHex.ts +2 -1
- package/src/primitives/Base64/from.ts +21 -4
- package/src/primitives/Blob/from.ts +12 -4
- package/src/primitives/BlockHash/index.ts +2 -2
- package/src/primitives/BlockNumber/index.ts +3 -3
- package/src/primitives/Bytecode/from.ts +11 -2
- package/src/primitives/ContractSignature/verifySignature.ts +3 -5
- package/src/primitives/Ens/from.ts +12 -11
- package/src/primitives/Hex/from.ts +12 -4
- package/src/primitives/Signature/from.ts +11 -2
- package/src/primitives/Transaction/EIP2930/index.ts +12 -12
- package/src/primitives/Transaction/EIP4844/index.ts +14 -14
- package/src/primitives/Transaction/EIP7702/index.ts +13 -13
- package/src/primitives/Transaction/Legacy/index.ts +13 -13
- package/src/primitives/TransactionHash/index.ts +3 -2
- package/src/primitives/TransactionIndex/index.ts +2 -2
- package/src/primitives/Trie/Trie.test.ts +70 -0
- package/src/primitives/Trie/TrieSchema.ts +26 -0
- package/src/primitives/Trie/clear.ts +16 -0
- package/src/primitives/Trie/del.ts +18 -0
- package/src/primitives/Trie/get.ts +18 -0
- package/src/primitives/Trie/index.ts +30 -0
- package/src/primitives/Trie/init.ts +13 -0
- package/src/primitives/Trie/prove.ts +19 -0
- package/src/primitives/Trie/put.ts +20 -0
- package/src/primitives/Trie/rootHash.ts +14 -0
- package/src/primitives/Trie/verify.ts +18 -0
- package/src/primitives/Uint/from.ts +11 -2
- package/src/primitives/Uint16/index.ts +5 -4
- package/src/primitives/Uint64/index.ts +5 -4
- package/src/primitives/Uint8/index.ts +5 -4
- package/src/primitives/index.ts +3 -2
- package/src/services/BlockExplorerApi/BlockExplorerApi.test.ts +789 -0
- package/src/services/BlockExplorerApi/BlockExplorerApi.ts +797 -0
- package/src/services/BlockExplorerApi/BlockExplorerApiErrors.ts +176 -0
- package/src/services/BlockExplorerApi/BlockExplorerApiService.ts +60 -0
- package/src/services/BlockExplorerApi/BlockExplorerApiTypes.ts +225 -0
- package/src/services/BlockExplorerApi/index.ts +42 -0
- package/src/services/Contract/Contract.test.ts +2 -6
- package/src/services/Contract/ContractTypes.ts +26 -8
- package/src/services/Contract/estimateGas.test.ts +4 -7
- package/src/services/Provider/actions/multicall.ts +28 -9
- package/src/services/Provider/actions/readContract.test.ts +8 -11
- package/src/services/Provider/actions/readContract.ts +28 -9
- package/src/services/Provider/functions/getBlock.ts +2 -1
- package/src/services/Provider/functions/getBlockReceipts.ts +2 -1
- package/src/services/Provider/functions/getBlockTransactionCount.ts +2 -1
- package/src/services/Provider/functions/getUncle.ts +2 -1
- package/src/services/Provider/functions/getUncleCount.ts +2 -1
- package/src/services/Signer/actions/deployContract.ts +1 -1
- package/src/services/index.ts +25 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Block Explorer API error definitions.
|
|
3
|
+
*
|
|
4
|
+
* @module BlockExplorerApiErrors
|
|
5
|
+
* @since 0.0.1
|
|
6
|
+
*
|
|
7
|
+
* @description
|
|
8
|
+
* Strongly typed error classes for Block Explorer API operations.
|
|
9
|
+
* All errors are compatible with Effect.catchTag for type-safe error handling.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as Data from "effect/Data";
|
|
13
|
+
import type { ExplorerSourceId } from "./BlockExplorerApiTypes.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Error thrown when configuration is invalid.
|
|
17
|
+
* @since 0.0.1
|
|
18
|
+
*/
|
|
19
|
+
export class BlockExplorerConfigError extends Data.TaggedError(
|
|
20
|
+
"BlockExplorerConfigError",
|
|
21
|
+
)<{
|
|
22
|
+
readonly message: string;
|
|
23
|
+
}> {
|
|
24
|
+
constructor(message: string) {
|
|
25
|
+
super({ message });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Error thrown when no ABI is found from any configured source.
|
|
31
|
+
* @since 0.0.1
|
|
32
|
+
*/
|
|
33
|
+
export class BlockExplorerNotFoundError extends Data.TaggedError(
|
|
34
|
+
"BlockExplorerNotFoundError",
|
|
35
|
+
)<{
|
|
36
|
+
readonly address: `0x${string}`;
|
|
37
|
+
readonly attemptedSources: ReadonlyArray<string>;
|
|
38
|
+
readonly message: string;
|
|
39
|
+
}> {
|
|
40
|
+
constructor(
|
|
41
|
+
address: `0x${string}`,
|
|
42
|
+
attemptedSources: ReadonlyArray<string>,
|
|
43
|
+
) {
|
|
44
|
+
super({
|
|
45
|
+
address,
|
|
46
|
+
attemptedSources,
|
|
47
|
+
message: `No ABI found for ${address}. Attempted sources: ${attemptedSources.join(", ")}`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Error thrown when rate limited by a block explorer source.
|
|
54
|
+
* @since 0.0.1
|
|
55
|
+
*/
|
|
56
|
+
export class BlockExplorerRateLimitError extends Data.TaggedError(
|
|
57
|
+
"BlockExplorerRateLimitError",
|
|
58
|
+
)<{
|
|
59
|
+
readonly source: ExplorerSourceId;
|
|
60
|
+
readonly address: `0x${string}`;
|
|
61
|
+
readonly message: string;
|
|
62
|
+
readonly retryAfterSeconds?: number;
|
|
63
|
+
}> {
|
|
64
|
+
constructor(
|
|
65
|
+
source: ExplorerSourceId,
|
|
66
|
+
address: `0x${string}`,
|
|
67
|
+
message: string,
|
|
68
|
+
retryAfterSeconds?: number,
|
|
69
|
+
) {
|
|
70
|
+
super({ source, address, message, retryAfterSeconds });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Error thrown when a block explorer returns a non-200 response or network error.
|
|
76
|
+
* @since 0.0.1
|
|
77
|
+
*/
|
|
78
|
+
export class BlockExplorerResponseError extends Data.TaggedError(
|
|
79
|
+
"BlockExplorerResponseError",
|
|
80
|
+
)<{
|
|
81
|
+
readonly source: ExplorerSourceId;
|
|
82
|
+
readonly address: `0x${string}`;
|
|
83
|
+
readonly status?: number;
|
|
84
|
+
readonly message: string;
|
|
85
|
+
readonly body?: string;
|
|
86
|
+
}> {
|
|
87
|
+
constructor(
|
|
88
|
+
source: ExplorerSourceId,
|
|
89
|
+
address: `0x${string}`,
|
|
90
|
+
message: string,
|
|
91
|
+
options?: { status?: number; body?: string },
|
|
92
|
+
) {
|
|
93
|
+
super({
|
|
94
|
+
source,
|
|
95
|
+
address,
|
|
96
|
+
message,
|
|
97
|
+
status: options?.status,
|
|
98
|
+
body: options?.body,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Error thrown when a block explorer response cannot be decoded.
|
|
105
|
+
* @since 0.0.1
|
|
106
|
+
*/
|
|
107
|
+
export class BlockExplorerDecodeError extends Data.TaggedError(
|
|
108
|
+
"BlockExplorerDecodeError",
|
|
109
|
+
)<{
|
|
110
|
+
readonly source: ExplorerSourceId;
|
|
111
|
+
readonly address: `0x${string}`;
|
|
112
|
+
readonly message: string;
|
|
113
|
+
readonly bodySnippet?: string;
|
|
114
|
+
}> {
|
|
115
|
+
constructor(
|
|
116
|
+
source: ExplorerSourceId,
|
|
117
|
+
address: `0x${string}`,
|
|
118
|
+
message: string,
|
|
119
|
+
bodySnippet?: string,
|
|
120
|
+
) {
|
|
121
|
+
super({ source, address, message, bodySnippet });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Error thrown when proxy resolution fails.
|
|
127
|
+
* @since 0.0.1
|
|
128
|
+
*/
|
|
129
|
+
export class BlockExplorerProxyResolutionError extends Data.TaggedError(
|
|
130
|
+
"BlockExplorerProxyResolutionError",
|
|
131
|
+
)<{
|
|
132
|
+
readonly address: `0x${string}`;
|
|
133
|
+
readonly message: string;
|
|
134
|
+
}> {
|
|
135
|
+
constructor(address: `0x${string}`, message: string) {
|
|
136
|
+
super({ address, message });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Catch-all error for unexpected failures.
|
|
142
|
+
* @since 0.0.1
|
|
143
|
+
*/
|
|
144
|
+
export class BlockExplorerUnexpectedError extends Data.TaggedError(
|
|
145
|
+
"BlockExplorerUnexpectedError",
|
|
146
|
+
)<{
|
|
147
|
+
readonly phase:
|
|
148
|
+
| "getAbi"
|
|
149
|
+
| "getContract"
|
|
150
|
+
| "getSources"
|
|
151
|
+
| "followProxies"
|
|
152
|
+
| "bestEffortRecovery";
|
|
153
|
+
readonly message: string;
|
|
154
|
+
readonly cause: unknown;
|
|
155
|
+
}> {
|
|
156
|
+
constructor(
|
|
157
|
+
phase: BlockExplorerUnexpectedError["phase"],
|
|
158
|
+
message: string,
|
|
159
|
+
cause: unknown,
|
|
160
|
+
) {
|
|
161
|
+
super({ phase, message, cause });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Union of all Block Explorer API errors.
|
|
167
|
+
* @since 0.0.1
|
|
168
|
+
*/
|
|
169
|
+
export type BlockExplorerApiError =
|
|
170
|
+
| BlockExplorerConfigError
|
|
171
|
+
| BlockExplorerNotFoundError
|
|
172
|
+
| BlockExplorerRateLimitError
|
|
173
|
+
| BlockExplorerResponseError
|
|
174
|
+
| BlockExplorerDecodeError
|
|
175
|
+
| BlockExplorerProxyResolutionError
|
|
176
|
+
| BlockExplorerUnexpectedError;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Block Explorer API service definition.
|
|
3
|
+
*
|
|
4
|
+
* @module BlockExplorerApiService
|
|
5
|
+
* @since 0.0.1
|
|
6
|
+
*
|
|
7
|
+
* @description
|
|
8
|
+
* The BlockExplorerApiService provides typed access to block explorer APIs
|
|
9
|
+
* for resolving contract ABIs, metadata, and source code.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as Context from "effect/Context";
|
|
13
|
+
import type * as Effect from "effect/Effect";
|
|
14
|
+
import type {
|
|
15
|
+
AbiItem,
|
|
16
|
+
ContractSourceFile,
|
|
17
|
+
ExplorerContractInstance,
|
|
18
|
+
GetAbiOptions,
|
|
19
|
+
GetContractOptions,
|
|
20
|
+
GetSourcesOptions,
|
|
21
|
+
} from "./BlockExplorerApiTypes.js";
|
|
22
|
+
import type { BlockExplorerApiError } from "./BlockExplorerApiErrors.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Service interface for Block Explorer API operations.
|
|
26
|
+
* @since 0.0.1
|
|
27
|
+
*/
|
|
28
|
+
export interface BlockExplorerApiShape {
|
|
29
|
+
/**
|
|
30
|
+
* Fetch contract with callable read/write methods.
|
|
31
|
+
*/
|
|
32
|
+
readonly getContract: (
|
|
33
|
+
address: `0x${string}`,
|
|
34
|
+
options?: GetContractOptions,
|
|
35
|
+
) => Effect.Effect<ExplorerContractInstance, BlockExplorerApiError>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convenience wrapper for getContract(...).abi
|
|
39
|
+
*/
|
|
40
|
+
readonly getAbi: (
|
|
41
|
+
address: `0x${string}`,
|
|
42
|
+
options?: GetAbiOptions,
|
|
43
|
+
) => Effect.Effect<ReadonlyArray<AbiItem>, BlockExplorerApiError>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Convenience wrapper for getContract(...).sources
|
|
47
|
+
*/
|
|
48
|
+
readonly getSources: (
|
|
49
|
+
address: `0x${string}`,
|
|
50
|
+
options?: GetSourcesOptions,
|
|
51
|
+
) => Effect.Effect<ReadonlyArray<ContractSourceFile>, BlockExplorerApiError>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Block Explorer API service for resolving contract ABIs and metadata.
|
|
56
|
+
* @since 0.0.1
|
|
57
|
+
*/
|
|
58
|
+
export class BlockExplorerApiService extends Context.Tag(
|
|
59
|
+
"BlockExplorerApiService",
|
|
60
|
+
)<BlockExplorerApiService, BlockExplorerApiShape>() {}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Block Explorer API type definitions.
|
|
3
|
+
*
|
|
4
|
+
* @module BlockExplorerApiTypes
|
|
5
|
+
* @since 0.0.1
|
|
6
|
+
*
|
|
7
|
+
* @description
|
|
8
|
+
* Defines types for Block Explorer API configuration, responses, and errors.
|
|
9
|
+
* Used by BlockExplorerApiService to resolve ABIs and contract metadata.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { Redacted } from "effect";
|
|
13
|
+
import type * as Effect from "effect/Effect";
|
|
14
|
+
import type { ContractCallError, ContractWriteError } from "../Contract/ContractTypes.js";
|
|
15
|
+
import type { ProviderService } from "../Provider/ProviderService.js";
|
|
16
|
+
import type { SignerService } from "../Signer/SignerService.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Identifier for supported block explorer sources.
|
|
20
|
+
* @since 0.0.1
|
|
21
|
+
*/
|
|
22
|
+
export type ExplorerSourceId = "sourcify" | "etherscanV2" | "blockscout";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for the Block Explorer API service.
|
|
26
|
+
* @since 0.0.1
|
|
27
|
+
*/
|
|
28
|
+
export interface BlockExplorerApiConfig {
|
|
29
|
+
readonly sources: {
|
|
30
|
+
readonly sourcify?: {
|
|
31
|
+
readonly enabled: boolean;
|
|
32
|
+
/** Custom Sourcify instance URL */
|
|
33
|
+
readonly baseUrl?: string;
|
|
34
|
+
};
|
|
35
|
+
readonly etherscanV2?: {
|
|
36
|
+
readonly enabled: boolean;
|
|
37
|
+
readonly apiKey?: Redacted.Redacted<string> | string;
|
|
38
|
+
/** Custom Etherscan-compatible API URL */
|
|
39
|
+
readonly baseUrl?: string;
|
|
40
|
+
};
|
|
41
|
+
readonly blockscout?: {
|
|
42
|
+
readonly enabled: boolean;
|
|
43
|
+
readonly apiKey?: Redacted.Redacted<string> | string;
|
|
44
|
+
/** Custom Blockscout instance URL */
|
|
45
|
+
readonly baseUrl?: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Order for "verified-first" resolution.
|
|
51
|
+
* Defaults to ["sourcify", "etherscanV2", "blockscout"].
|
|
52
|
+
*/
|
|
53
|
+
readonly sourceOrder?: ReadonlyArray<ExplorerSourceId>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Default behavior for proxy following.
|
|
57
|
+
*/
|
|
58
|
+
readonly followProxiesByDefault?: boolean;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Enable best-effort ABI recovery (ABR) when verified ABI is missing.
|
|
62
|
+
* Intended for inspection tooling.
|
|
63
|
+
*/
|
|
64
|
+
readonly enableBestEffortAbiRecovery?: boolean;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Cache resolved ABIs.
|
|
68
|
+
*/
|
|
69
|
+
readonly cache?: {
|
|
70
|
+
readonly enabled: boolean;
|
|
71
|
+
readonly ttlMillis?: number;
|
|
72
|
+
readonly capacity?: number;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Single item in an ABI definition.
|
|
78
|
+
* Standard Solidity ABI format.
|
|
79
|
+
* @since 0.0.1
|
|
80
|
+
*/
|
|
81
|
+
export type AbiItem = {
|
|
82
|
+
readonly type: string;
|
|
83
|
+
readonly name?: string;
|
|
84
|
+
readonly inputs?: ReadonlyArray<{
|
|
85
|
+
readonly name?: string;
|
|
86
|
+
readonly type: string;
|
|
87
|
+
readonly indexed?: boolean;
|
|
88
|
+
readonly components?: ReadonlyArray<{ readonly name?: string; readonly type: string }>;
|
|
89
|
+
}>;
|
|
90
|
+
readonly outputs?: ReadonlyArray<{
|
|
91
|
+
readonly name?: string;
|
|
92
|
+
readonly type: string;
|
|
93
|
+
readonly components?: ReadonlyArray<{ readonly name?: string; readonly type: string }>;
|
|
94
|
+
}>;
|
|
95
|
+
readonly stateMutability?: "pure" | "view" | "nonpayable" | "payable";
|
|
96
|
+
readonly anonymous?: boolean;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Source file from a verified contract.
|
|
101
|
+
* @since 0.0.1
|
|
102
|
+
*/
|
|
103
|
+
export interface ContractSourceFile {
|
|
104
|
+
readonly path: string;
|
|
105
|
+
readonly content: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* How the ABI was resolved.
|
|
110
|
+
* @since 0.0.1
|
|
111
|
+
*/
|
|
112
|
+
export type AbiResolution =
|
|
113
|
+
| { readonly mode: "verified"; readonly source: ExplorerSourceId }
|
|
114
|
+
| { readonly mode: "best-effort"; readonly source: "whatsabi" };
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Proxy chain entry for debugging/UX.
|
|
118
|
+
* @since 0.0.1
|
|
119
|
+
*/
|
|
120
|
+
export interface ProxyInfo {
|
|
121
|
+
readonly kind: string;
|
|
122
|
+
readonly address: `0x${string}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Result of resolving a contract from block explorers.
|
|
127
|
+
* @since 0.0.1
|
|
128
|
+
*/
|
|
129
|
+
export interface ResolvedExplorerContract {
|
|
130
|
+
/** Resolved address (implementation if proxies followed) */
|
|
131
|
+
readonly address: `0x${string}`;
|
|
132
|
+
/** Original input address */
|
|
133
|
+
readonly requestedAddress: `0x${string}`;
|
|
134
|
+
/** Contract name if available */
|
|
135
|
+
readonly name?: string;
|
|
136
|
+
/** Resolved ABI */
|
|
137
|
+
readonly abi: ReadonlyArray<AbiItem>;
|
|
138
|
+
/** How the ABI was resolved */
|
|
139
|
+
readonly resolution: AbiResolution;
|
|
140
|
+
/** Source files if requested and available */
|
|
141
|
+
readonly sources?: ReadonlyArray<ContractSourceFile>;
|
|
142
|
+
/** Proxy chain if followProxies was true */
|
|
143
|
+
readonly proxies?: ReadonlyArray<ProxyInfo>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Options for getContract.
|
|
148
|
+
* @since 0.0.1
|
|
149
|
+
*/
|
|
150
|
+
export interface GetContractOptions {
|
|
151
|
+
/**
|
|
152
|
+
* Resolution mode for ABI retrieval.
|
|
153
|
+
* - "verified-only": Only verified ABIs, fail if not found
|
|
154
|
+
* - "verified-first": Try verified first, fail if not found (default)
|
|
155
|
+
* - "best-effort": Fall back to ABI recovery when unverified
|
|
156
|
+
*/
|
|
157
|
+
readonly resolution?: "verified-only" | "verified-first" | "best-effort";
|
|
158
|
+
/** Include source files in response */
|
|
159
|
+
readonly includeSources?: boolean;
|
|
160
|
+
/** Follow proxy contracts to implementation */
|
|
161
|
+
readonly followProxies?: boolean;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Options for getAbi.
|
|
166
|
+
* @since 0.0.1
|
|
167
|
+
*/
|
|
168
|
+
export interface GetAbiOptions {
|
|
169
|
+
readonly resolution?: "verified-only" | "verified-first" | "best-effort";
|
|
170
|
+
readonly followProxies?: boolean;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Options for getSources.
|
|
175
|
+
* @since 0.0.1
|
|
176
|
+
*/
|
|
177
|
+
export interface GetSourcesOptions {
|
|
178
|
+
readonly followProxies?: boolean;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Dynamic contract instance with callable methods.
|
|
183
|
+
* Returned by getContract() for interacting with contracts.
|
|
184
|
+
* @since 0.0.1
|
|
185
|
+
*/
|
|
186
|
+
export interface ExplorerContractInstance {
|
|
187
|
+
/** Resolved address (implementation if proxies followed) */
|
|
188
|
+
readonly address: `0x${string}`;
|
|
189
|
+
/** Original input address */
|
|
190
|
+
readonly requestedAddress: `0x${string}`;
|
|
191
|
+
/** Resolved ABI */
|
|
192
|
+
readonly abi: ReadonlyArray<AbiItem>;
|
|
193
|
+
/** How the ABI was resolved */
|
|
194
|
+
readonly resolution: AbiResolution;
|
|
195
|
+
/** Contract name if available */
|
|
196
|
+
readonly name?: string;
|
|
197
|
+
/** Source files if requested and available */
|
|
198
|
+
readonly sources?: ReadonlyArray<ContractSourceFile>;
|
|
199
|
+
/** Proxy chain if followProxies was true */
|
|
200
|
+
readonly proxies?: ReadonlyArray<ProxyInfo>;
|
|
201
|
+
|
|
202
|
+
/** Read-only methods (view/pure) */
|
|
203
|
+
readonly read: Record<
|
|
204
|
+
string,
|
|
205
|
+
(...args: ReadonlyArray<unknown>) => Effect.Effect<unknown, ContractCallError, ProviderService>
|
|
206
|
+
>;
|
|
207
|
+
|
|
208
|
+
/** Simulate state-changing methods */
|
|
209
|
+
readonly simulate: Record<
|
|
210
|
+
string,
|
|
211
|
+
(...args: ReadonlyArray<unknown>) => Effect.Effect<unknown, ContractCallError, ProviderService>
|
|
212
|
+
>;
|
|
213
|
+
|
|
214
|
+
/** State-changing methods */
|
|
215
|
+
readonly write: Record<
|
|
216
|
+
string,
|
|
217
|
+
(...args: ReadonlyArray<unknown>) => Effect.Effect<`0x${string}`, ContractWriteError, SignerService>
|
|
218
|
+
>;
|
|
219
|
+
|
|
220
|
+
/** Explicit signature-based access */
|
|
221
|
+
readonly call: (
|
|
222
|
+
signature: string,
|
|
223
|
+
args: ReadonlyArray<unknown>,
|
|
224
|
+
) => Effect.Effect<unknown, ContractCallError, ProviderService>;
|
|
225
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Block Explorer API module exports.
|
|
3
|
+
*
|
|
4
|
+
* @module BlockExplorerApi
|
|
5
|
+
* @since 0.0.1
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Types
|
|
9
|
+
export type {
|
|
10
|
+
AbiItem,
|
|
11
|
+
AbiResolution,
|
|
12
|
+
BlockExplorerApiConfig,
|
|
13
|
+
ContractSourceFile,
|
|
14
|
+
ExplorerContractInstance,
|
|
15
|
+
ExplorerSourceId,
|
|
16
|
+
GetAbiOptions,
|
|
17
|
+
GetContractOptions,
|
|
18
|
+
GetSourcesOptions,
|
|
19
|
+
ProxyInfo,
|
|
20
|
+
ResolvedExplorerContract,
|
|
21
|
+
} from "./BlockExplorerApiTypes.js";
|
|
22
|
+
|
|
23
|
+
// Errors
|
|
24
|
+
export {
|
|
25
|
+
BlockExplorerConfigError,
|
|
26
|
+
BlockExplorerDecodeError,
|
|
27
|
+
BlockExplorerNotFoundError,
|
|
28
|
+
BlockExplorerProxyResolutionError,
|
|
29
|
+
BlockExplorerRateLimitError,
|
|
30
|
+
BlockExplorerResponseError,
|
|
31
|
+
BlockExplorerUnexpectedError,
|
|
32
|
+
type BlockExplorerApiError,
|
|
33
|
+
} from "./BlockExplorerApiErrors.js";
|
|
34
|
+
|
|
35
|
+
// Service
|
|
36
|
+
export {
|
|
37
|
+
BlockExplorerApiService,
|
|
38
|
+
type BlockExplorerApiShape,
|
|
39
|
+
} from "./BlockExplorerApiService.js";
|
|
40
|
+
|
|
41
|
+
// Layer factory
|
|
42
|
+
export { BlockExplorerApi } from "./BlockExplorerApi.js";
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
// @ts-nocheck - TODO: Fix ABI type inference issues
|
|
2
1
|
import { beforeEach, describe, expect, it, vi } from "@effect/vitest";
|
|
3
2
|
import { Address } from "@tevm/voltaire";
|
|
4
3
|
import * as Effect from "effect/Effect";
|
|
5
4
|
import * as Layer from "effect/Layer";
|
|
6
|
-
import * as S from "effect/Schema";
|
|
7
|
-
import { fromArray } from "../../primitives/Abi/AbiSchema.js";
|
|
8
5
|
import { ProviderService } from "../Provider/index.js";
|
|
9
6
|
import { SignerService } from "../Signer/index.js";
|
|
10
7
|
import { Contract } from "./Contract.js";
|
|
@@ -13,8 +10,7 @@ type HexType = `0x${string}`;
|
|
|
13
10
|
|
|
14
11
|
const testAddress = Address("0x6B175474E89094C44Da98b954EecdEfaE6E286AB");
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
const erc20Abi = S.decodeUnknownSync(fromArray)([
|
|
13
|
+
const erc20Abi = [
|
|
18
14
|
{
|
|
19
15
|
type: "function",
|
|
20
16
|
name: "balanceOf",
|
|
@@ -99,7 +95,7 @@ const erc20Abi = S.decodeUnknownSync(fromArray)([
|
|
|
99
95
|
{ name: "value", type: "uint256", indexed: false },
|
|
100
96
|
],
|
|
101
97
|
},
|
|
102
|
-
]
|
|
98
|
+
] as const;
|
|
103
99
|
|
|
104
100
|
const mockCallFn = vi.fn();
|
|
105
101
|
const mockGetLogsFn = vi.fn();
|
|
@@ -328,10 +328,30 @@ type ExtractEventNames<TAbi extends Abi> =
|
|
|
328
328
|
type AbiInputsToArgs<
|
|
329
329
|
TInputs extends readonly { type: string; name?: string }[],
|
|
330
330
|
> = {
|
|
331
|
-
[K in keyof TInputs]:
|
|
331
|
+
[K in keyof TInputs]: AbiTypeToInput<TInputs[K]["type"]>;
|
|
332
332
|
};
|
|
333
333
|
|
|
334
|
-
type
|
|
334
|
+
type BytesInput = Uint8Array | `0x${string}`;
|
|
335
|
+
|
|
336
|
+
type AbiTypeToInput<T extends string> = T extends `uint${string}`
|
|
337
|
+
? bigint
|
|
338
|
+
: T extends `int${string}`
|
|
339
|
+
? bigint
|
|
340
|
+
: T extends "address"
|
|
341
|
+
? AddressType
|
|
342
|
+
: T extends "bool"
|
|
343
|
+
? boolean
|
|
344
|
+
: T extends "string"
|
|
345
|
+
? string
|
|
346
|
+
: T extends `bytes${string}` | "bytes"
|
|
347
|
+
? BytesInput
|
|
348
|
+
: T extends `${string}[]`
|
|
349
|
+
? readonly unknown[]
|
|
350
|
+
: T extends `tuple`
|
|
351
|
+
? Record<string, unknown>
|
|
352
|
+
: unknown;
|
|
353
|
+
|
|
354
|
+
type AbiTypeToOutput<T extends string> = T extends `uint${string}`
|
|
335
355
|
? bigint
|
|
336
356
|
: T extends `int${string}`
|
|
337
357
|
? bigint
|
|
@@ -341,11 +361,9 @@ type AbiTypeToTs<T extends string> = T extends `uint${string}`
|
|
|
341
361
|
? boolean
|
|
342
362
|
: T extends "string"
|
|
343
363
|
? string
|
|
344
|
-
: T extends `bytes${string}`
|
|
345
|
-
?
|
|
346
|
-
: T extends
|
|
347
|
-
? HexType
|
|
348
|
-
: T extends `${string}[]`
|
|
364
|
+
: T extends `bytes${string}` | "bytes"
|
|
365
|
+
? Uint8Array
|
|
366
|
+
: T extends `${string}[]`
|
|
349
367
|
? readonly unknown[]
|
|
350
368
|
: T extends `tuple`
|
|
351
369
|
? Record<string, unknown>
|
|
@@ -354,7 +372,7 @@ type AbiTypeToTs<T extends string> = T extends `uint${string}`
|
|
|
354
372
|
type AbiOutputToTs<TOutputs extends readonly { type: string }[]> =
|
|
355
373
|
TOutputs extends readonly [{ type: infer T }]
|
|
356
374
|
? T extends string
|
|
357
|
-
?
|
|
375
|
+
? AbiTypeToOutput<T>
|
|
358
376
|
: unknown
|
|
359
377
|
: TOutputs extends readonly []
|
|
360
378
|
? undefined
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
// @ts-nocheck - TODO: Fix ABI type inference issues
|
|
2
1
|
import { beforeEach, describe, expect, it, vi } from "@effect/vitest";
|
|
3
2
|
import { Address, BrandedAbi } from "@tevm/voltaire";
|
|
4
3
|
import * as Effect from "effect/Effect";
|
|
5
4
|
import * as Layer from "effect/Layer";
|
|
6
|
-
import * as S from "effect/Schema";
|
|
7
|
-
import { fromArray } from "../../primitives/Abi/AbiSchema.js";
|
|
8
5
|
import { ProviderService } from "../Provider/index.js";
|
|
9
6
|
import { Contract } from "./Contract.js";
|
|
10
7
|
|
|
@@ -12,7 +9,7 @@ type HexType = `0x${string}`;
|
|
|
12
9
|
|
|
13
10
|
const testAddress = Address("0x6B175474E89094C44Da98b954EecdEfaE6E286AB");
|
|
14
11
|
|
|
15
|
-
const erc20Abi =
|
|
12
|
+
const erc20Abi = [
|
|
16
13
|
{
|
|
17
14
|
type: "function",
|
|
18
15
|
name: "transfer",
|
|
@@ -30,7 +27,7 @@ const erc20Abi = S.decodeUnknownSync(fromArray)([
|
|
|
30
27
|
inputs: [],
|
|
31
28
|
outputs: [],
|
|
32
29
|
},
|
|
33
|
-
]
|
|
30
|
+
] as const;
|
|
34
31
|
|
|
35
32
|
const mockEstimateGasFn = vi.fn();
|
|
36
33
|
|
|
@@ -76,7 +73,7 @@ describe("Contract.estimateGas", () => {
|
|
|
76
73
|
|
|
77
74
|
const callArgs = mockEstimateGasFn.mock.calls[0][0];
|
|
78
75
|
const expectedData = BrandedAbi.encodeFunction(
|
|
79
|
-
erc20Abi
|
|
76
|
+
erc20Abi,
|
|
80
77
|
"transfer",
|
|
81
78
|
[recipient, amount],
|
|
82
79
|
);
|
|
@@ -98,7 +95,7 @@ describe("Contract.estimateGas", () => {
|
|
|
98
95
|
|
|
99
96
|
const callArgs = mockEstimateGasFn.mock.calls[0][0];
|
|
100
97
|
const expectedData = BrandedAbi.encodeFunction(
|
|
101
|
-
erc20Abi
|
|
98
|
+
erc20Abi,
|
|
102
99
|
"deposit",
|
|
103
100
|
[],
|
|
104
101
|
);
|