@volga-sh/evm-ghostcall 0.0.3 → 0.0.5

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/README.md CHANGED
@@ -1,12 +1,11 @@
1
1
  # ghostcall
2
2
 
3
- `ghostcall` batches EVM blockchain reads without deployment dependencies.
3
+ `ghostcall` batches EVM contract reads without deploying a Multicall contract.
4
4
 
5
5
  ## Documentation
6
6
 
7
- The docs live at [ghostcall.volga.sh](https://ghostcall.volga.sh).
8
-
9
- Start there for installation, examples, the API reference, protocol details, and endpoint limit notes.
7
+ Start at [ghostcall.volga.sh](https://ghostcall.volga.sh) for the setup guide,
8
+ recipes, API reference, protocol, and size limits.
10
9
 
11
10
  ## Install
12
11
 
@@ -14,16 +13,19 @@ Start there for installation, examples, the API reference, protocol details, and
14
13
  npm install @volga-sh/evm-ghostcall
15
14
  ```
16
15
 
17
- ## Quick Start
16
+ ## Quick start
17
+
18
+ This example uses viem for its client and ABI definition. ghostcall uses ox
19
+ internally to encode arguments and decode results:
18
20
 
19
- This example uses viem for the EIP-1193-compatible client and ABI helpers. Install it with `npm install viem` if your app does not already use it.
21
+ ```sh
22
+ npm install viem
23
+ ```
20
24
 
21
25
  ```ts
22
26
  import { aggregateDecodedCalls } from "@volga-sh/evm-ghostcall";
23
27
  import {
24
28
  createPublicClient,
25
- decodeFunctionResult,
26
- encodeFunctionData,
27
29
  http,
28
30
  parseAbi,
29
31
  } from "viem";
@@ -34,50 +36,81 @@ const client = createPublicClient({
34
36
  transport: http(),
35
37
  });
36
38
 
37
- const erc20Abi = parseAbi(["function totalSupply() view returns (uint256)"]);
39
+ const abi = parseAbi(["function totalSupply() view returns (uint256)"]);
40
+ const token = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
38
41
 
39
42
  const [totalSupply] = await aggregateDecodedCalls(client, [
40
43
  {
41
- to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
42
- data: encodeFunctionData({
43
- abi: erc20Abi,
44
- functionName: "totalSupply",
45
- }),
46
- decodeResult: (returnData) =>
47
- decodeFunctionResult({
48
- abi: erc20Abi,
49
- functionName: "totalSupply",
50
- data: returnData,
51
- }),
44
+ to: token,
45
+ abi,
46
+ functionName: "totalSupply",
52
47
  },
53
48
  ]);
49
+ // totalSupply is inferred as bigint.
54
50
  ```
55
51
 
56
- See the [Getting Started guide](https://ghostcall.volga.sh/getting-started/) for a complete viem example with ABI encoding and decoding.
52
+ Function names, arguments, and results are inferred from the ABI. Functions
53
+ with inputs require `args`, for example `args: [owner]` for `balanceOf`.
54
+ Keep ABIs literal with `as const`, viem's `parseAbi`, or ox's `Abi.from`.
55
+
56
+ Since 0.0.5, ABI-decoded addresses are checksummed, including addresses nested in
57
+ tuples and arrays. Earlier versions returned lowercase addresses.
58
+
59
+ For already-encoded calldata, use the raw API:
60
+
61
+ ```ts
62
+ import { aggregateCalls } from "@volga-sh/evm-ghostcall";
63
+
64
+ const results = await aggregateCalls(client, [
65
+ { to: token, data: "0x18160ddd" },
66
+ ]);
67
+ // [{ success: true, returnData: "0x..." }]
68
+ ```
69
+
70
+ `aggregateDecodedCalls()` also accepts raw `data` with a custom `decodeResult`
71
+ callback, including in the same batch as ABI calls. Each entry uses either ABI
72
+ fields or raw calldata; TypeScript rejects entries that mix the two forms.
73
+
74
+ See [Getting Started](https://ghostcall.volga.sh/getting-started/) for a complete
75
+ two-call walkthrough.
57
76
 
58
77
  ## API
59
78
 
60
- - `aggregateDecodedCalls()` sends a strict batch and returns decoded values.
61
- - `aggregateCalls()` sends a batch and returns raw `{ success, returnData }` entries.
62
- - `encodeCalls()` builds the CREATE-style `eth_call` data payload.
63
- - `decodeResults()` parses the packed ghostcall response.
79
+ - `aggregateDecodedCalls()` accepts ABI calls or custom decoders and returns a typed result tuple.
80
+ - `aggregateCalls()` sends calls and returns raw success or failure results.
81
+ - `encodeCalls()` builds request data for an `eth_call` without `to`.
82
+ - `decodeResults()` parses a raw ghostcall response.
83
+
84
+ Read the [API reference](https://ghostcall.volga.sh/api/) for signatures,
85
+ options, return types, and errors.
64
86
 
65
- Full reference: [API docs](https://ghostcall.volga.sh/api/).
87
+ The public type surface contains seven types, including ghostcall's own `Hex`.
88
+ `GhostcallAggregateCall` is merged into `GhostcallCall`. See
89
+ [type import migration](https://ghostcall.volga.sh/api/types/#migrating-type-imports)
90
+ for the removed helper aliases. Runtime exports are unchanged.
66
91
 
67
92
  ## Development
68
93
 
94
+ Use Node.js from `.nvmrc`, npm 12.1.0, and Foundry v1.8.3. CI also tests the
95
+ latest Node.js 24 LTS release. Foundry installs the compiler pinned in
96
+ `foundry.toml` (Solidity 0.8.37); the EVM target stays Prague for compatibility.
97
+
69
98
  ```sh
70
- npm install
99
+ nvm install
100
+ npm install --global npm@12.1.0
101
+ npm ci
71
102
  npm run build:sdk
72
103
  npm run test
73
104
  npm run check
74
105
  ```
75
106
 
76
- Docs are built with Astro Starlight:
107
+ To work on the documentation:
77
108
 
78
109
  ```sh
110
+ npm ci --prefix docs
79
111
  npm run docs:dev
80
112
  npm run docs:build
81
113
  ```
82
114
 
83
- The repository is hosted at [github.com/volga-sh/ghostcall](https://github.com/volga-sh/ghostcall).
115
+ The source is hosted at
116
+ [github.com/volga-sh/ghostcall](https://github.com/volga-sh/ghostcall).
@@ -0,0 +1,39 @@
1
+ import type { Abi } from "ox/Abi";
2
+ import * as AbiFunction from "ox/AbiFunction";
3
+ import type * as AbiItem from "ox/AbiItem";
4
+ import type { GhostcallDecodedCall, Hex } from "./index.ts";
5
+ type FunctionCall<TFunction extends AbiFunction.AbiFunction> = TFunction extends AbiFunction.AbiFunction ? {
6
+ functionName: TFunction["name"];
7
+ } & (TFunction["inputs"] extends readonly [] ? {
8
+ args?: readonly [];
9
+ } : {
10
+ args: NonNullable<AbiFunction.encodeData.Args<TFunction>[0]>;
11
+ }) : never;
12
+ /**
13
+ * An ABI-described call. A literal ABI determines valid function names and args.
14
+ * Use `as const` or an ABI parser to retain those literal types.
15
+ */
16
+ type GhostcallAbiCall<TAbi extends Abi = Abi> = {
17
+ to: Hex;
18
+ abi: TAbi;
19
+ data?: never;
20
+ decodeResult?: never;
21
+ allowFailure?: never;
22
+ } & (Abi extends TAbi ? {
23
+ functionName: string;
24
+ args?: readonly unknown[];
25
+ } : FunctionCall<Extract<TAbi[number], {
26
+ type: "function";
27
+ }>>);
28
+ type CallFunctionName<TCall extends GhostcallAbiCall> = TCall["functionName"] & AbiFunction.Name<TCall["abi"]>;
29
+ type CallArguments<TCall extends GhostcallAbiCall> = TCall extends {
30
+ args: infer TArgs extends readonly unknown[];
31
+ } ? TArgs : readonly [];
32
+ type ResolvedFunction<TCall extends GhostcallAbiCall> = AbiItem.fromAbi.Options<TCall["abi"], CallFunctionName<TCall>> extends AbiItem.fromAbi.Options<TCall["abi"], CallFunctionName<TCall>, infer TArgs> ? AbiItem.fromAbi.ReturnType<TCall["abi"], CallFunctionName<TCall>, Extract<CallArguments<TCall>, TArgs>, AbiFunction.AbiFunction> : never;
33
+ /** The decoded result of an ABI call, including argument-selected overloads. */
34
+ type GhostcallAbiResult<TCall extends GhostcallAbiCall> = AbiFunction.decodeResult.ReturnType<Extract<ResolvedFunction<TCall>, AbiFunction.AbiFunction>>;
35
+ /** Bind encoding and decoding to the same resolved ABI function. */
36
+ declare function prepareAbiCall(call: GhostcallAbiCall): GhostcallDecodedCall;
37
+ export type { GhostcallAbiCall, GhostcallAbiResult };
38
+ export { prepareAbiCall };
39
+ //# sourceMappingURL=abi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abi.d.ts","sourceRoot":"","sources":["../../src/sdk/abi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,KAAK,OAAO,MAAM,YAAY,CAAC;AAE3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAG5D,KAAK,YAAY,CAAC,SAAS,SAAS,WAAW,CAAC,WAAW,IAC1D,SAAS,SAAS,WAAW,CAAC,WAAW,GACtC;IACA,YAAY,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;CAChC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,SAAS,EAAE,GACzC;IAAE,IAAI,CAAC,EAAE,SAAS,EAAE,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC,GACnE,KAAK,CAAC;AAEV;;;GAGG;AACH,KAAK,gBAAgB,CAAC,IAAI,SAAS,GAAG,GAAG,GAAG,IAAI;IAC/C,EAAE,EAAE,GAAG,CAAC;IACR,GAAG,EAAE,IAAI,CAAC;IACV,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,YAAY,CAAC,EAAE,KAAK,CAAC;CACrB,GAAG,CAAC,GAAG,SAAS,IAAI,GAClB;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE,GACnD,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC,CAAC,CAAC;AAE9D,KAAK,gBAAgB,CAAC,KAAK,SAAS,gBAAgB,IAAI,KAAK,CAAC,cAAc,CAAC,GAC5E,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AAEhC,KAAK,aAAa,CAAC,KAAK,SAAS,gBAAgB,IAAI,KAAK,SAAS;IAClE,IAAI,EAAE,MAAM,KAAK,SAAS,SAAS,OAAO,EAAE,CAAC;CAC7C,GACE,KAAK,GACL,SAAS,EAAE,CAAC;AAIf,KAAK,gBAAgB,CAAC,KAAK,SAAS,gBAAgB,IACnD,OAAO,CAAC,OAAO,CAAC,OAAO,CACtB,KAAK,CAAC,KAAK,CAAC,EACZ,gBAAgB,CAAC,KAAK,CAAC,CACvB,SAAS,OAAO,CAAC,OAAO,CAAC,OAAO,CAChC,KAAK,CAAC,KAAK,CAAC,EACZ,gBAAgB,CAAC,KAAK,CAAC,EACvB,MAAM,KAAK,CACX,GACE,OAAO,CAAC,OAAO,CAAC,UAAU,CAC1B,KAAK,CAAC,KAAK,CAAC,EACZ,gBAAgB,CAAC,KAAK,CAAC,EACvB,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EACpC,WAAW,CAAC,WAAW,CACvB,GACA,KAAK,CAAC;AAEV,gFAAgF;AAChF,KAAK,kBAAkB,CAAC,KAAK,SAAS,gBAAgB,IACrD,WAAW,CAAC,YAAY,CAAC,UAAU,CAClC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CACzD,CAAC;AAEH,oEAAoE;AACpE,iBAAS,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,oBAAoB,CAoBpE;AAED,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,20 @@
1
+ import * as AbiFunction from "ox/AbiFunction";
2
+ /** Bind encoding and decoding to the same resolved ABI function. */
3
+ function prepareAbiCall(call) {
4
+ const args = call.args ?? [];
5
+ const abiFunction = AbiFunction.fromAbi(call.abi, call.functionName, {
6
+ args,
7
+ });
8
+ // ox permits selector-only encoding with no args. At this wire boundary,
9
+ // missing arguments must fail before RPC, including for dynamically loaded ABIs.
10
+ if (args.length !== abiFunction.inputs.length) {
11
+ throw new TypeError(`${call.functionName} expects ${abiFunction.inputs.length} arguments, received ${args.length}`);
12
+ }
13
+ return {
14
+ to: call.to,
15
+ data: AbiFunction.encodeData(abiFunction, args),
16
+ decodeResult: (returnData) => AbiFunction.decodeResult(abiFunction, returnData),
17
+ };
18
+ }
19
+ export { prepareAbiCall };
20
+ //# sourceMappingURL=abi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abi.js","sourceRoot":"","sources":["../../src/sdk/abi.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAC;AA+D9C,oEAAoE;AACpE,SAAS,cAAc,CAAC,IAAsB;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,EAAE;QACpE,IAAI;KACJ,CAAC,CAAC;IAEH,yEAAyE;IACzE,iFAAiF;IACjF,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/C,MAAM,IAAI,SAAS,CAClB,GAAG,IAAI,CAAC,YAAY,YAAY,WAAW,CAAC,MAAM,CAAC,MAAM,wBAAwB,IAAI,CAAC,MAAM,EAAE,CAC9F,CAAC;IACH,CAAC;IAED,OAAO;QACN,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,IAAI,EAAE,WAAW,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC;QAC/C,YAAY,EAAE,CAAC,UAAU,EAAE,EAAE,CAC5B,WAAW,CAAC,YAAY,CAAC,WAAW,EAAE,UAAU,CAAC;KAClD,CAAC;AACH,CAAC;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -1,322 +1,89 @@
1
- /**
2
- * Hex-encoded binary data prefixed with `0x`.
3
- *
4
- * Ghostcall request and response data is represented as raw hex strings. The
5
- * SDK does not accept byte arrays or ABI fragments.
6
- */
1
+ import { type GhostcallAbiCall, type GhostcallAbiResult } from "./abi.ts";
2
+ /** A 0x-prefixed string, validated at SDK wire boundaries. */
7
3
  type Hex = `0x${string}`;
8
- /**
9
- * Hex-encoded RPC quantity prefixed with `0x`.
10
- */
11
- type HexQuantity = `0x${string}`;
12
- /**
13
- * Block reference accepted by the outer `eth_call`.
14
- */
15
- type GhostcallBlockReference = string | number | bigint;
16
- /**
17
- * One Ghostcall subcall entry.
18
- */
4
+ /** Raw calldata for one target. Encoding ignores the SDK-only failure policy. */
19
5
  type GhostcallCall = {
20
- /**
21
- * Target contract address to invoke.
22
- */
23
6
  to: Hex;
24
- /**
25
- * Hex-encoded call data to forward to {@link GhostcallCall.to}.
26
- *
27
- * The encoded payload is limited to `65535` bytes because Ghostcall stores each
28
- * calldata length as a big-endian `uint16`.
29
- */
7
+ /** At most 65,535 bytes (the wire format stores a uint16 length). */
30
8
  data: Hex;
31
- };
32
- /**
33
- * One Ghostcall aggregate subcall entry.
34
- *
35
- * The wire format does not include failure-policy bits. `allowFailure` is an SDK
36
- * policy applied after Ghostcall returns the packed result entries.
37
- */
38
- type GhostcallAggregateCall = GhostcallCall & {
39
- /**
40
- * Allows this subcall to return a failed result entry.
41
- *
42
- * Defaults to `false`, matching Multicall3's strict `aggregate3` behavior when
43
- * a call does not explicitly opt into failure.
44
- */
9
+ /** Return failed entries from aggregateCalls instead of throwing. Default: false. */
45
10
  allowFailure?: boolean;
46
11
  };
47
- /**
48
- * One Ghostcall subcall entry for decoded aggregate results.
49
- */
12
+ /** Raw calldata with a decoder that only receives successful results. */
50
13
  type GhostcallDecodedCall<TResult = unknown> = GhostcallCall & {
51
- /**
52
- * Decodes this call's successful return data.
53
- *
54
- * This is intentionally a caller-provided function so the SDK stays independent
55
- * from ABI libraries while still letting callers plug in helpers such as
56
- * `decodeFunctionResult` from viem or ox.
57
- */
58
- decodeResult: GhostcallResultDecoder<TResult>;
14
+ abi?: never;
15
+ functionName?: never;
16
+ args?: never;
17
+ allowFailure?: never;
18
+ decodeResult: (returnData: Hex, entry: Extract<GhostcallResult, {
19
+ success: true;
20
+ }>, index: number) => TResult;
59
21
  };
60
- /**
61
- * One successful Ghostcall result entry.
62
- */
63
- type GhostcallSuccessResult = {
64
- /**
65
- * Indicates whether the underlying EVM `CALL` returned successfully.
66
- *
67
- * A `true` value means the target call returned successfully.
68
- */
22
+ /** Raw results retain input order and include revert data for failed calls. */
23
+ type GhostcallResult = {
69
24
  success: true;
70
- /**
71
- * Raw return data produced by the target call.
72
- */
73
25
  returnData: Hex;
74
- };
75
- /**
76
- * One failed Ghostcall result entry.
77
- */
78
- type GhostcallFailedResult = {
79
- /**
80
- * Indicates whether the underlying EVM `CALL` returned successfully.
81
- *
82
- * A `false` value means the target call reverted or otherwise failed, but the
83
- * Ghostcall batch itself still completed successfully.
84
- */
26
+ } | {
85
27
  success: false;
86
- /**
87
- * Raw return data produced by the target call.
88
- *
89
- * For failed calls this contains revert data, if any. The SDK leaves higher-level
90
- * ABI decoding and failure policy to the caller.
91
- */
92
28
  returnData: Hex;
93
29
  };
94
- /**
95
- * One decoded Ghostcall result entry.
96
- */
97
- type GhostcallResult = GhostcallSuccessResult | GhostcallFailedResult;
98
- /**
99
- * Function used by {@link aggregateCalls} to turn raw successful return data into
100
- * a caller-chosen value.
101
- */
102
- type GhostcallResultDecoder<TResult> = (returnData: Hex, entry: GhostcallSuccessResult, index: number) => TResult;
103
- /**
104
- * Error thrown when a strict Ghostcall batch encounters a failed subcall.
105
- */
106
- declare class GhostcallSubcallError extends Error {
107
- readonly index: number;
108
- readonly call: GhostcallAggregateCall;
109
- readonly result: GhostcallFailedResult;
110
- constructor(index: number, call: GhostcallAggregateCall, result: GhostcallFailedResult);
111
- }
112
- type GhostcallDecodedResults<TCalls extends readonly GhostcallDecodedCall[]> = {
113
- -readonly [Index in keyof TCalls]: TCalls[Index] extends {
114
- decodeResult: GhostcallResultDecoder<infer TResult>;
115
- } ? TResult : never;
30
+ type GhostcallFailedResult = Extract<GhostcallResult, {
31
+ success: false;
32
+ }>;
33
+ type GhostcallDecodedInput = GhostcallAbiCall | GhostcallDecodedCall;
34
+ type ValidatedDecodedCall<TCall extends GhostcallDecodedInput> = TCall extends GhostcallAbiCall ? GhostcallAbiCall<TCall["abi"]> : TCall;
35
+ type ValidatedDecodedCalls<TCalls extends readonly GhostcallDecodedInput[]> = {
36
+ [Index in keyof TCalls]: ValidatedDecodedCall<TCalls[Index]>;
37
+ };
38
+ type DecodedResult<TCall extends GhostcallDecodedInput> = TCall extends GhostcallAbiCall ? GhostcallAbiResult<TCall> : TCall extends GhostcallDecodedCall ? ReturnType<TCall["decodeResult"]> : never;
39
+ type GhostcallDecodedResults<TCalls extends readonly GhostcallDecodedInput[]> = {
40
+ -readonly [Index in keyof TCalls]: DecodedResult<TCalls[Index]>;
116
41
  };
117
42
  type GhostcallEncodeOptions = {
118
- /**
119
- * Maximum allowed CREATE initcode size in bytes.
120
- *
121
- * This applies to the full request `data`, including bundled Ghostcall
122
- * initcode and every encoded subcall entry.
123
- *
124
- * Defaults to Ethereum's EIP-3860 limit of `49,152` bytes.
125
- */
43
+ /** Full CREATE request ceiling, including bundled initcode. Default: 49,152 bytes. */
126
44
  maxInitcodeBytes?: number;
127
45
  };
128
- type GhostcallEthCallOptions = {
129
- /**
130
- * Optional `from` address for the outer `eth_call`.
131
- */
132
- from?: Hex;
133
- /**
134
- * Optional gas limit for the outer `eth_call`.
135
- */
136
- gas?: HexQuantity;
137
- /**
138
- * Optional block tag, hex quantity, or block number for the outer `eth_call`.
139
- *
140
- * Decimal strings, numbers, and bigints are normalized to hex quantities.
141
- * Defaults to `latest`.
142
- */
143
- blockTag?: GhostcallBlockReference;
144
- };
145
46
  type GhostcallAggregateOptions = GhostcallEncodeOptions & {
146
- /**
147
- * Optional outer `eth_call` controls shared by {@link aggregateCalls} and
148
- * {@link aggregateDecodedCalls}.
149
- */
150
- ethCall?: GhostcallEthCallOptions;
47
+ /** Controls the outer eth_call, shared by the entire batch. */
48
+ ethCall?: {
49
+ from?: Hex;
50
+ /** Canonical RPC hex quantity. */
51
+ gas?: Hex;
52
+ /** Decimal block numbers are normalized to hex. Default: "latest". */
53
+ blockTag?: string | number | bigint;
54
+ };
151
55
  };
152
- /**
153
- * Minimal EIP-1193 provider shape used by the SDK.
154
- */
155
- type EIP1193ProviderWithRequestFn = {
56
+ type Provider = {
156
57
  request(args: {
157
58
  method: string;
158
59
  params?: unknown;
159
60
  }): Promise<unknown>;
160
61
  };
62
+ /** A disallowed failure, with its zero-based index, executed call, and revert data. */
63
+ declare class GhostcallSubcallError extends Error {
64
+ readonly index: number;
65
+ readonly call: GhostcallCall;
66
+ readonly result: GhostcallFailedResult;
67
+ constructor(index: number, call: GhostcallCall, result: GhostcallFailedResult);
68
+ }
161
69
  /**
162
- * Encodes a list of contract calls into the full CREATE-style `eth_call` payload
163
- * expected by Ghostcall.
164
- *
165
- * The returned hex string already includes the bundled Ghostcall initcode followed
166
- * by the compact binary payload for each subcall, so callers can pass it directly
167
- * as the `data` field of an `eth_call` request without supplying a `to` address.
168
- * Each encoded subcall entry uses the compact layout `[len(2)][target(20)][data]`.
169
- * The bundled initcode assumes appended bytes follow this exact shape; this
170
- * function is the supported boundary for producing well-formed Ghostcall payloads.
171
- *
172
- * @param calls - Ordered list of subcalls to execute. Each entry becomes one
173
- * Ghostcall payload segment in the same order it appears here.
174
- * @param options - Optional encoding controls.
175
- *
176
- * @returns Full CREATE payload consisting of the bundled Ghostcall initcode plus
177
- * the encoded call list.
178
- *
179
- * @throws {TypeError} If any call address or calldata value is not valid hex.
180
- * @throws {RangeError} If any call data exceeds the protocol `uint16` length limit
181
- * or if the full encoded CREATE payload would exceed the
182
- * configured initcode size limit.
183
- *
184
- * @example
185
- * const data = encodeCalls([
186
- * {
187
- * // USDC on Ethereum mainnet: balanceOf(Binance 14)
188
- * to: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
189
- * data: "0x70a0823100000000000000000000000028c6c06298d514db089934071355e5743bf21d60",
190
- * },
191
- * {
192
- * // WETH9 on Ethereum mainnet: totalSupply()
193
- * to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
194
- * data: "0x18160ddd",
195
- * },
196
- * ]);
197
- *
198
- * // Later:
199
- * // provider.request({ method: "eth_call", params: [{ data }, "latest"] })
200
- */
201
- declare function encodeCalls(calls: readonly GhostcallCall[], options?: GhostcallEncodeOptions): Hex;
202
- /**
203
- * Sends a Ghostcall batch with a CREATE-style `eth_call` and decodes the result.
204
- *
205
- * This is the provider-facing counterpart to {@link encodeCalls} and
206
- * {@link decodeResults}. It sends the bundled Ghostcall initcode as the `data`
207
- * field of `eth_call` without a `to` address, then returns raw result entries
208
- * in the same order as the input calls. Request bytes are built through
209
- * {@link encodeCalls}, so SDK callers get the supported payload validation before
210
- * the RPC request is sent.
211
- *
212
- * By default, any failed subcall makes this method reject. Set
213
- * `allowFailure: true` on a call to receive that failed entry in the returned
214
- * results instead. Use {@link aggregateDecodedCalls} when you want a strict batch
215
- * that returns decoded values directly. Use `options.ethCall` to forward `from`,
216
- * `gas`, or `blockTag` to the outer `eth_call`.
217
- *
218
- * @param provider - EIP-1193-compatible provider with a `request` method.
219
- * @param calls - Ordered list of subcalls to execute.
220
- * @param options - Optional outer call and initcode controls.
221
- *
222
- * @returns Ordered Ghostcall result entries.
223
- *
224
- * @throws {TypeError} If inputs are not valid Ghostcall call entries or if the
225
- * provider returns a non-hex `eth_call` result.
226
- * @throws {RangeError} If the encoded CREATE payload exceeds protocol or the
227
- * configured CREATE initcode ceiling.
228
- * @throws {GhostcallSubcallError} If a subcall fails without `allowFailure: true`.
229
- * @throws {Error} If the response entry count does not match the request entry count.
230
- *
231
- * @example
232
- * const results = await aggregateCalls(provider, [
233
- * {
234
- * // USDC on Ethereum mainnet: balanceOf(Binance 14)
235
- * to: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
236
- * data: "0x70a0823100000000000000000000000028c6c06298d514db089934071355e5743bf21d60",
237
- * },
238
- * {
239
- * // WETH9 on Ethereum mainnet: totalSupply()
240
- * to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
241
- * data: "0x18160ddd",
242
- * },
243
- * ]);
70
+ * Build CREATE-style eth_call data: initcode followed by [length (2)][target (20)][data].
71
+ * Send without a `to` address. Invalid inputs throw TypeError; size limits throw RangeError.
244
72
  */
245
- declare function aggregateCalls(provider: EIP1193ProviderWithRequestFn, calls: readonly GhostcallAggregateCall[], options?: GhostcallAggregateOptions): Promise<GhostcallResult[]>;
73
+ declare function encodeCalls(calls: readonly GhostcallCall[], { maxInitcodeBytes, }?: GhostcallEncodeOptions): Hex;
246
74
  /**
247
- * Sends a strict Ghostcall batch and decodes each successful result entry.
248
- *
249
- * This is the decoded counterpart to {@link aggregateCalls}. It sends the bundled
250
- * Ghostcall initcode as the `data` field of `eth_call` without a `to` address,
251
- * then runs each call's `decodeResult` callback over the successful return data in
252
- * the same order as the input calls.
253
- *
254
- * `aggregateDecodedCalls` is always strict. Its TypeScript input shape requires a
255
- * `decodeResult` callback on every call and does not accept `allowFailure`.
256
- * Any failed subcall rejects with {@link GhostcallSubcallError}. Use
257
- * {@link aggregateCalls} if you need raw failed entries. Use `options.ethCall`
258
- * to forward `from`, `gas`, or `blockTag` to the outer `eth_call`.
259
- *
260
- * @param provider - EIP-1193-compatible provider with a `request` method.
261
- * @param calls - Ordered list of strict decoded subcalls to execute.
262
- * @param options - Optional outer call and initcode controls.
263
- *
264
- * @returns Ordered list of decoded values.
265
- *
266
- * @throws {TypeError} If inputs are not valid Ghostcall call entries or if the
267
- * provider returns a non-hex `eth_call` result.
268
- * @throws {RangeError} If the encoded CREATE payload exceeds protocol or the
269
- * configured CREATE initcode ceiling.
270
- * @throws {GhostcallSubcallError} If any subcall fails.
271
- * @throws {Error} If the response entry count does not match the request entry count.
272
- *
273
- * @example
274
- * const erc20Abi = parseAbi([
275
- * "function balanceOf(address account) view returns (uint256)",
276
- * ]);
277
- * const usdc = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
278
- * const owner = "0x28C6c06298d514Db089934071355E5743bf21d60";
279
- *
280
- * const [balance] = await aggregateDecodedCalls(provider, [
281
- * {
282
- * to: usdc,
283
- * data: "0x70a0823100000000000000000000000028c6c06298d514db089934071355e5743bf21d60",
284
- * decodeResult: (returnData) => decodeFunctionResult({
285
- * abi: erc20Abi,
286
- * functionName: "balanceOf",
287
- * data: returnData,
288
- * }),
289
- * },
290
- * ]);
75
+ * Execute a raw batch in order. Failed calls throw GhostcallSubcallError unless
76
+ * their entry sets allowFailure. Provider errors pass through unchanged.
291
77
  */
292
- declare function aggregateDecodedCalls<const TCalls extends readonly GhostcallDecodedCall<unknown>[]>(provider: EIP1193ProviderWithRequestFn, calls: TCalls, options?: GhostcallAggregateOptions): Promise<GhostcallDecodedResults<TCalls>>;
78
+ declare function aggregateCalls(provider: Provider, calls: readonly GhostcallCall[], options?: GhostcallAggregateOptions): Promise<GhostcallResult[]>;
293
79
  /**
294
- * Decodes the packed result blob returned by Ghostcall.
295
- *
296
- * Each decoded entry corresponds to exactly one subcall in the original batch and
297
- * preserves the original ordering. The SDK intentionally returns raw result bytes
298
- * rather than ABI-decoding them so higher-level callers can apply their own
299
- * decoding and failure policy.
300
- *
301
- * @param data - Raw bytes returned by Ghostcall, typically the direct result of a
302
- * CREATE-style `eth_call`.
303
- *
304
- * @returns Ordered list of decoded Ghostcall result entries. Returns an empty
305
- * array for `0x`.
306
- *
307
- * @throws {TypeError} If the provided data is not valid hex, if a result header is
308
- * truncated, or if an entry body is shorter than advertised.
309
- *
310
- * @example
311
- * const results = decodeResults("0x8002cafe0004deadbeef");
312
- *
313
- * console.log(results);
314
- * // [
315
- * // { success: true, returnData: "0xcafe" },
316
- * // { success: false, returnData: "0xdeadbeef" }
317
- * // ]
80
+ * Execute ABI-described calls or raw calls with custom decoders. Each tuple position
81
+ * retains its result type. Any failed call throws; encoding/decoding errors pass through.
82
+ * ABI-decoded addresses are checksummed, including addresses nested in tuples or arrays.
318
83
  */
84
+ declare function aggregateDecodedCalls<const TCalls extends readonly GhostcallDecodedInput[]>(provider: Provider, calls: TCalls & NoInfer<ValidatedDecodedCalls<TCalls>>, options?: GhostcallAggregateOptions): Promise<GhostcallDecodedResults<TCalls>>;
85
+ /** Decode ordered [success bit | uint15 length][returndata] entries. Reject malformed data. */
319
86
  declare function decodeResults(data: Hex): GhostcallResult[];
320
- export type { EIP1193ProviderWithRequestFn, GhostcallAggregateCall, GhostcallAggregateOptions, GhostcallBlockReference, GhostcallCall, GhostcallDecodedCall, GhostcallDecodedResults, GhostcallEncodeOptions, GhostcallEthCallOptions, GhostcallFailedResult, GhostcallResult, GhostcallResultDecoder, GhostcallSuccessResult, Hex, HexQuantity, };
87
+ export type { GhostcallAbiCall, GhostcallAggregateOptions, GhostcallCall, GhostcallDecodedCall, GhostcallEncodeOptions, GhostcallResult, Hex, };
321
88
  export { aggregateCalls, aggregateDecodedCalls, decodeResults, encodeCalls, GhostcallSubcallError, };
322
89
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,KAAK,GAAG,GAAG,KAAK,MAAM,EAAE,CAAC;AAEzB;;GAEG;AACH,KAAK,WAAW,GAAG,KAAK,MAAM,EAAE,CAAC;AAEjC;;GAEG;AACH,KAAK,uBAAuB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAExD;;GAEG;AACH,KAAK,aAAa,GAAG;IACpB;;OAEG;IACH,EAAE,EAAE,GAAG,CAAC;IAER;;;;;OAKG;IACH,IAAI,EAAE,GAAG,CAAC;CACV,CAAC;AAEF;;;;;GAKG;AACH,KAAK,sBAAsB,GAAG,aAAa,GAAG;IAC7C;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,oBAAoB,CAAC,OAAO,GAAG,OAAO,IAAI,aAAa,GAAG;IAC9D;;;;;;OAMG;IACH,YAAY,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC;CAC9C,CAAC;AAEF;;GAEG;AACH,KAAK,sBAAsB,GAAG;IAC7B;;;;OAIG;IACH,OAAO,EAAE,IAAI,CAAC;IAEd;;OAEG;IACH,UAAU,EAAE,GAAG,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,KAAK,qBAAqB,GAAG;IAC5B;;;;;OAKG;IACH,OAAO,EAAE,KAAK,CAAC;IAEf;;;;;OAKG;IACH,UAAU,EAAE,GAAG,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,KAAK,eAAe,GAAG,sBAAsB,GAAG,qBAAqB,CAAC;AAEtE;;;GAGG;AACH,KAAK,sBAAsB,CAAC,OAAO,IAAI,CACtC,UAAU,EAAE,GAAG,EACf,KAAK,EAAE,sBAAsB,EAC7B,KAAK,EAAE,MAAM,KACT,OAAO,CAAC;AAEb;;GAEG;AACH,cAAM,qBAAsB,SAAQ,KAAK;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;gBAGtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,sBAAsB,EAC5B,MAAM,EAAE,qBAAqB;CAS9B;AAED,KAAK,uBAAuB,CAAC,MAAM,SAAS,SAAS,oBAAoB,EAAE,IAAI;IAC9E,CAAC,UAAU,KAAK,IAAI,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS;QACxD,YAAY,EAAE,sBAAsB,CAAC,MAAM,OAAO,CAAC,CAAC;KACpD,GACE,OAAO,GACP,KAAK;CACR,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC7B;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,KAAK,uBAAuB,GAAG;IAC9B;;OAEG;IACH,IAAI,CAAC,EAAE,GAAG,CAAC;IAEX;;OAEG;IACH,GAAG,CAAC,EAAE,WAAW,CAAC;IAElB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CACnC,CAAC;AAEF,KAAK,yBAAyB,GAAG,sBAAsB,GAAG;IACzD;;;OAGG;IACH,OAAO,CAAC,EAAE,uBAAuB,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,KAAK,4BAA4B,GAAG;IACnC,OAAO,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtE,CAAC;AAWF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,iBAAS,WAAW,CACnB,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,OAAO,GAAE,sBAA2B,GAClC,GAAG,CAmCL;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,iBAAe,cAAc,CAC5B,QAAQ,EAAE,4BAA4B,EACtC,KAAK,EAAE,SAAS,sBAAsB,EAAE,EACxC,OAAO,CAAC,EAAE,yBAAyB,GACjC,OAAO,CAAC,eAAe,EAAE,CAAC,CAyC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,iBAAe,qBAAqB,CACnC,KAAK,CAAC,MAAM,SAAS,SAAS,oBAAoB,CAAC,OAAO,CAAC,EAAE,EAE7D,QAAQ,EAAE,4BAA4B,EACtC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,yBAAyB,GACjC,OAAO,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,CAQ1C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,iBAAS,aAAa,CAAC,IAAI,EAAE,GAAG,GAAG,eAAe,EAAE,CAsCnD;AAqKD,YAAY,EACX,4BAA4B,EAC5B,sBAAsB,EACtB,yBAAyB,EACzB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,GAAG,EACH,WAAW,GACX,CAAC;AACF,OAAO,EACN,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,WAAW,EACX,qBAAqB,GACrB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"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"}