@steerprotocol/sdk 4.0.0-next.7 → 4.0.0-next.8

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/index.d.cts CHANGED
@@ -555,7 +555,8 @@ interface VaultMetadata {
555
555
  readonly beaconName: string;
556
556
  readonly createdAt: string;
557
557
  readonly state: string | null;
558
- readonly pool: Address | null;
558
+ /** Pool contract address or a 32-byte pool ID for singleton AMMs such as V4. */
559
+ readonly pool: Hex | null;
559
560
  readonly poolKey?: string | null;
560
561
  readonly token0: Address | null;
561
562
  readonly token1: Address | null;
package/dist/index.d.mts CHANGED
@@ -555,7 +555,8 @@ interface VaultMetadata {
555
555
  readonly beaconName: string;
556
556
  readonly createdAt: string;
557
557
  readonly state: string | null;
558
- readonly pool: Address | null;
558
+ /** Pool contract address or a 32-byte pool ID for singleton AMMs such as V4. */
559
+ readonly pool: Hex | null;
559
560
  readonly poolKey?: string | null;
560
561
  readonly token0: Address | null;
561
562
  readonly token1: Address | null;
package/dist/index.mjs CHANGED
@@ -139,12 +139,20 @@ var Operation = class {
139
139
  };
140
140
  //#endregion
141
141
  //#region src/rpc/read-errors.ts
142
+ /** @internal Shared context or helper execution failed before a member outcome is available. */
143
+ var SharedRpcReadError = class extends Error {
144
+ constructor(message, options) {
145
+ super(message, options);
146
+ this.name = "SharedRpcReadError";
147
+ }
148
+ };
142
149
  /** Transport failures are shared by the request, never successful per-item outcomes. */
143
150
  function sharedReadError(error) {
144
151
  const seen = /* @__PURE__ */ new Set();
145
152
  let shared = false;
146
153
  for (let cause = error; cause && typeof cause === "object" && !seen.has(cause);) {
147
154
  seen.add(cause);
155
+ if (cause instanceof SharedRpcReadError) return true;
148
156
  if (cause instanceof ContractFunctionRevertedError) return false;
149
157
  const value = cause;
150
158
  if (value.name === "ContractFunctionRevertedError") return false;
@@ -175,15 +183,15 @@ function sameAddress(left, right) {
175
183
  return left.toLowerCase() === right.toLowerCase();
176
184
  }
177
185
  function quantity(value) {
178
- if (typeof value !== "string" || !/^0x(?:0|[1-9a-f][\da-f]*)$/i.test(value)) throw new Error("Invalid RPC quantity");
186
+ if (typeof value !== "string" || !/^0x(?:0|[1-9a-f][\da-f]*)$/i.test(value)) throw new SharedRpcReadError("Invalid RPC quantity");
179
187
  return BigInt(value);
180
188
  }
181
189
  async function readContext(context, options) {
182
190
  const transport = context.transport;
183
- if (!transport) throw new Error(`No RPC transport configured for chain ${context.chainId}`);
184
- if (quantity(await transport.request("eth_chainId", [])) !== BigInt(context.chainId)) throw new Error("RPC chain does not match requested chain");
191
+ if (!transport) throw new SharedRpcReadError(`No RPC transport configured for chain ${context.chainId}`);
192
+ if (quantity(await transport.request("eth_chainId", [])) !== BigInt(context.chainId)) throw new SharedRpcReadError("RPC chain does not match requested chain");
185
193
  const blockNumber = options?.blockNumber ?? quantity(await transport.request("eth_blockNumber", []));
186
- if (blockNumber < 0n) throw new Error("Block number must be nonnegative");
194
+ if (blockNumber < 0n) throw new SharedRpcReadError("Block number must be nonnegative");
187
195
  return {
188
196
  ...context,
189
197
  transport,
@@ -777,9 +785,8 @@ function readerUnsupported(error, mode) {
777
785
  for (let cause = error; cause && typeof cause === "object" && !seen.has(cause);) {
778
786
  seen.add(cause);
779
787
  const value = cause;
780
- if (cause instanceof ContractFunctionRevertedError || hasRevertData(value.data)) return false;
788
+ if (hasReaderRevert(cause)) return false;
781
789
  const message = typeof value.message === "string" ? value.message : "";
782
- if (/execution reverted|out of gas|invalid opcode/i.test(message)) return false;
783
790
  if (value.code === -32602 || value.code === -32004 || value.code === -32e3) {
784
791
  const feature = mode === "deployless" ? /contract creation|deployless|creation calls?/i : /state.?overrides?/i;
785
792
  const rejection = /not supported|unsupported|disabled/i;
@@ -796,11 +803,27 @@ function hasRevertData(data) {
796
803
  const wrapped = data;
797
804
  return [wrapped.data, wrapped.originalError?.data].some((value) => typeof value === "string" && /^0x[\da-f]+$/i.test(value));
798
805
  }
806
+ /** A failed member contract must not become a shared malformed-response error. */
807
+ function readerReverted(error) {
808
+ const seen = /* @__PURE__ */ new Set();
809
+ for (let cause = error; cause && typeof cause === "object" && !seen.has(cause);) {
810
+ seen.add(cause);
811
+ if (hasReaderRevert(cause)) return true;
812
+ cause = cause.cause;
813
+ }
814
+ return false;
815
+ }
816
+ function hasReaderRevert(error) {
817
+ const value = error;
818
+ if (value.name?.startsWith("AbiDecoding")) return false;
819
+ return error instanceof ContractFunctionRevertedError || hasRevertData(value.data) || typeof value.message === "string" && /execution reverted|out of gas|invalid opcode/i.test(value.message);
820
+ }
799
821
  //#endregion
800
822
  //#region src/rpc/reader.ts
801
823
  /** Ephemeral code-only execution. Vault callers verify original proxy code before overriding it. */
802
- function executeReader(context, code, mode, read) {
803
- return read(createClient({ transport: custom({ request: ({ method, params }) => context.transport.request(method, params ?? []) }, { retryCount: 0 }) }), mode === "deployless" ? {
824
+ async function executeReader(context, code, mode, read) {
825
+ const client = createClient({ transport: custom({ request: ({ method, params }) => context.transport.request(method, params ?? []) }, { retryCount: 0 }) });
826
+ const execution = mode === "deployless" ? {
804
827
  blockNumber: context.blockNumber,
805
828
  code: code.bytecode
806
829
  } : {
@@ -810,7 +833,13 @@ function executeReader(context, code, mode, read) {
810
833
  address: code.address,
811
834
  code: code.runtime
812
835
  }]
813
- });
836
+ };
837
+ try {
838
+ return await read(client, execution);
839
+ } catch (error) {
840
+ if (readerUnsupported(error, mode) || readerReverted(error) || sharedReadError(error)) throw error;
841
+ throw new SharedRpcReadError("Shared reader execution failed", { cause: error });
842
+ }
814
843
  }
815
844
  /** Compatibility is eligible only after both execution modes explicitly reject support. */
816
845
  async function readWithFallback(read) {
@@ -12238,6 +12267,11 @@ function nullableString(value) {
12238
12267
  if (value === null || typeof value === "string") return value;
12239
12268
  throw new Error("Malformed vault metadata string");
12240
12269
  }
12270
+ function poolIdentifier(value) {
12271
+ if (value === null) return null;
12272
+ if (typeof value === "string" && /^0x[0-9a-fA-F]{64}$/.test(value)) return value.toLowerCase();
12273
+ return indexedAddress(value, true);
12274
+ }
12241
12275
  /** Validate and detach indexed data, preserving nulls and optional pool keys. */
12242
12276
  function vaultMetadata(value) {
12243
12277
  const row = record(value);
@@ -12254,7 +12288,7 @@ function vaultMetadata(value) {
12254
12288
  beaconName: row.beaconName,
12255
12289
  createdAt: row.createdAt,
12256
12290
  state: nullableString(row.state),
12257
- pool: row.pool === null ? null : indexedAddress(row.pool, true),
12291
+ pool: poolIdentifier(row.pool),
12258
12292
  ...row.poolKey === void 0 ? {} : { poolKey: nullableString(row.poolKey) },
12259
12293
  token0: row.token0 === null ? null : indexedAddress(row.token0, true),
12260
12294
  token1: row.token1 === null ? null : indexedAddress(row.token1, true),
@@ -12286,6 +12320,15 @@ function captureVaultMetadata(addresses, values) {
12286
12320
  for (const address of requested) if (!records.has(address)) throw new Error(`Supplied vault metadata is missing address: ${address}`);
12287
12321
  return records;
12288
12322
  }
12323
+ /** @internal A valid indexed response can omit individual vaults. */
12324
+ var MissingVaultMetadataError = class extends Error {
12325
+ records;
12326
+ constructor(records) {
12327
+ super("Vault metadata is not indexed");
12328
+ this.name = "MissingVaultMetadataError";
12329
+ this.records = Object.freeze([...records]);
12330
+ }
12331
+ };
12289
12332
  //#endregion
12290
12333
  //#region src/vault/resolver-types.ts
12291
12334
  let ProtocolContractRole = /* @__PURE__ */ function(ProtocolContractRole) {
@@ -12818,9 +12861,10 @@ var CatalogSteerDataAdapter = class extends SteerDataAdapter {
12818
12861
  if (!unique.includes(metadata.id) || records.has(metadata.id)) throw new Error("Unexpected or duplicate vault metadata");
12819
12862
  records.set(metadata.id, metadata);
12820
12863
  }
12864
+ if (unique.some((id) => !records.has(id))) throw new MissingVaultMetadataError([...records.values()]);
12821
12865
  return Object.freeze(ids.map((id) => {
12822
12866
  const metadata = records.get(id);
12823
- if (!metadata) throw new Error("Vault metadata is not indexed");
12867
+ if (!metadata) throw new Error("Missing validated vault metadata");
12824
12868
  return metadata;
12825
12869
  }));
12826
12870
  }
@@ -23044,17 +23088,20 @@ async function readV4PoolKey(context, contracts, id, options) {
23044
23088
  }
23045
23089
  //#endregion
23046
23090
  //#region src/amm/adapters/uniswap-v4/rpc-data-adapter.ts
23047
- /** Pool-key resolution through onchain metadata, independent of indexed pool listing. */
23091
+ /** Onchain pool-key resolution with optional independent indexed listing. */
23048
23092
  var UniswapV4RpcDataAdapter = class extends V4PoolDataAdapter {
23049
23093
  context;
23050
23094
  contracts;
23051
- constructor(context, contracts) {
23052
- super({ kind: "rpc" });
23095
+ #listing;
23096
+ constructor(context, contracts, listing) {
23097
+ super(listing?.definition ?? { kind: "rpc" });
23053
23098
  this.context = context;
23054
23099
  this.contracts = contracts;
23100
+ this.#listing = listing;
23055
23101
  }
23056
- async listPools() {
23057
- throw new Error("Uniswap V4 pool listing is not configured on this network");
23102
+ async listPools(request, options) {
23103
+ if (!this.#listing) throw new Error("Uniswap V4 pool listing is not configured on this network");
23104
+ return this.#listing.listPools(request, options);
23058
23105
  }
23059
23106
  getPoolKey(id, options) {
23060
23107
  return readV4PoolKey(this.context, this.contracts, id, options);
@@ -23072,8 +23119,11 @@ const uniswapV4Bsc = /* @__PURE__ */ new Deployment({
23072
23119
  stateView: { address: "0xd13dd3d6e93f276fafc9db9e6bb47c1180aee0c4" },
23073
23120
  quoter: { address: "0x9f75dd27d6664c475b90e105573e550ff69437b0" }
23074
23121
  },
23075
- dataAdapter: { kind: "rpc" }
23076
- }, (context, definition) => new UniswapV4(context, definition, new UniswapV4RpcDataAdapter(context, definition.contracts)));
23122
+ dataAdapter: {
23123
+ kind: "subgraph",
23124
+ url: "https://gateway.thegraph.com/api/subgraphs/id/EAq1nJKgjnuKH6Gj4RFjCW7LcL7E2uipbncdwV7TTWkX"
23125
+ }
23126
+ }, (context, definition) => new UniswapV4(context, definition, new UniswapV4RpcDataAdapter(context, definition.contracts, new UniswapV4DataAdapter(definition.dataAdapter, definition.contracts.poolManager.address, context))));
23077
23127
  //#endregion
23078
23128
  //#region src/amm/deployments/uniswap-v4-robinhood.ts
23079
23129
  /** Qualified Robinhood V4 deployment; full pool keys are available from vault contracts. */
@@ -24330,7 +24380,8 @@ var VaultResolver = class {
24330
24380
  }) } : {}
24331
24381
  });
24332
24382
  }
24333
- #metadata(steer, addresses, supplied, onRequestError) {
24383
+ #metadata(steer, addresses, options = {}) {
24384
+ const { supplied, allowMissing, onRequestError } = options;
24334
24385
  let pending;
24335
24386
  return async (address) => {
24336
24387
  if (supplied) {
@@ -24339,6 +24390,7 @@ var VaultResolver = class {
24339
24390
  return metadata;
24340
24391
  }
24341
24392
  pending ??= steer.dataAdapter.getVaultMetadata(addresses).catch((error) => {
24393
+ if (allowMissing && error instanceof MissingVaultMetadataError) return error.records;
24342
24394
  if (onRequestError) return onRequestError(error);
24343
24395
  throw error;
24344
24396
  });
@@ -24373,10 +24425,14 @@ var VaultResolver = class {
24373
24425
  let bulkSupported = !!this.#reader.readMany;
24374
24426
  for (let start = 0; start < inputs.length; start += 64) {
24375
24427
  const batch = inputs.slice(start, start + 64);
24376
- const loadMetadata = this.#metadata(steer, batch, metadata, (error) => {
24377
- metadataFailed = true;
24378
- metadataError = error;
24379
- throw error;
24428
+ const loadMetadata = this.#metadata(steer, batch, {
24429
+ ...metadata ? { supplied: metadata } : {},
24430
+ allowMissing: partial,
24431
+ onRequestError: (error) => {
24432
+ metadataFailed = true;
24433
+ metadataError = error;
24434
+ throw error;
24435
+ }
24380
24436
  });
24381
24437
  const contexts = batch.map((address) => Object.freeze({
24382
24438
  steer,
@@ -24432,10 +24488,13 @@ var VaultResolver = class {
24432
24488
  let bulkSupported = !!this.#reader.readSnapshots;
24433
24489
  for (let start = 0; start < inputs.length; start += 16) {
24434
24490
  const batch = inputs.slice(start, start + 16);
24435
- const loadMetadata = this.#metadata(steer, batch, void 0, (error) => {
24436
- metadataFailed = true;
24437
- metadataError = error;
24438
- throw error;
24491
+ const loadMetadata = this.#metadata(steer, batch, {
24492
+ allowMissing: partial,
24493
+ onRequestError: (error) => {
24494
+ metadataFailed = true;
24495
+ metadataError = error;
24496
+ throw error;
24497
+ }
24439
24498
  });
24440
24499
  const contexts = batch.map((address) => Object.freeze({
24441
24500
  steer,