@steerprotocol/sdk 4.0.0-next.2 → 4.0.0-next.4
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 +64 -7
- package/dist/index.cjs +151 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -17
- package/dist/index.d.mts +43 -17
- package/dist/index.mjs +151 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2062,6 +2062,7 @@ var AerodromeSlipstreamAdapter = class extends AmmAdapter {
|
|
|
2062
2062
|
blockNumber: context.blockNumber,
|
|
2063
2063
|
...captured.account ? { account: captured.account } : {}
|
|
2064
2064
|
});
|
|
2065
|
+
if (result[1] <= sqrtRatioAtTick(-887272) + 1n || result[1] >= sqrtRatioAtTick(887272) - 1n) throw new Error("Slipstream quote reached the price limit; full input consumption is not established");
|
|
2065
2066
|
return Object.freeze({
|
|
2066
2067
|
amountIn: input.amountIn,
|
|
2067
2068
|
amountOut: result[0]
|
|
@@ -2102,6 +2103,9 @@ var SteerDataAdapter = class extends DataAdapter {
|
|
|
2102
2103
|
async listUserVaults(_request, _options) {
|
|
2103
2104
|
throw new Error("User vault discovery is not configured for this data adapter");
|
|
2104
2105
|
}
|
|
2106
|
+
async getVaultMetadata(_addresses, _options) {
|
|
2107
|
+
throw new Error("Vault metadata is not configured for this data adapter");
|
|
2108
|
+
}
|
|
2105
2109
|
};
|
|
2106
2110
|
//#endregion
|
|
2107
2111
|
//#region src/data/subgraph.ts
|
|
@@ -7742,6 +7746,7 @@ var RpcUniswapV3Adapter = class RpcUniswapV3Adapter extends UniswapV3Adapter {
|
|
|
7742
7746
|
fee: pool.fee,
|
|
7743
7747
|
sqrtPriceLimitX96: 0n
|
|
7744
7748
|
}]);
|
|
7749
|
+
if (result[1] <= sqrtRatioAtTick(-887272) + 1n || result[1] >= sqrtRatioAtTick(887272) - 1n) throw new Error("V3 quote reached the price limit; full input consumption is not established");
|
|
7745
7750
|
return {
|
|
7746
7751
|
amountIn: request.amountIn,
|
|
7747
7752
|
amountOut: result[0]
|
|
@@ -11398,6 +11403,50 @@ var DeploymentRegistry = class {
|
|
|
11398
11403
|
}
|
|
11399
11404
|
};
|
|
11400
11405
|
//#endregion
|
|
11406
|
+
//#region src/vault/metadata.ts
|
|
11407
|
+
function nullableString(value) {
|
|
11408
|
+
if (value === null || typeof value === "string") return value;
|
|
11409
|
+
throw new Error("Malformed vault metadata string");
|
|
11410
|
+
}
|
|
11411
|
+
/** Validate and detach indexed data, preserving nulls and optional pool keys. */
|
|
11412
|
+
function vaultMetadata(value) {
|
|
11413
|
+
const row = record(value);
|
|
11414
|
+
if (typeof row.beaconName !== "string" || !row.beaconName || typeof row.createdAt !== "string" || !/^\d+$/.test(row.createdAt)) throw new Error("Malformed vault metadata identity");
|
|
11415
|
+
const decimals = nullableString(row.decimals);
|
|
11416
|
+
if (decimals !== null && !/^\d+$/.test(decimals)) throw new Error("Malformed vault metadata decimals");
|
|
11417
|
+
const strategy = row.strategyToken === null ? null : record(row.strategyToken);
|
|
11418
|
+
if (strategy !== null && (typeof strategy.id !== "string" || !strategy.id)) throw new Error("Malformed vault strategy token");
|
|
11419
|
+
return Object.freeze({
|
|
11420
|
+
id: indexedAddress(row.id),
|
|
11421
|
+
name: nullableString(row.name),
|
|
11422
|
+
symbol: nullableString(row.symbol),
|
|
11423
|
+
decimals,
|
|
11424
|
+
beaconName: row.beaconName,
|
|
11425
|
+
createdAt: row.createdAt,
|
|
11426
|
+
state: nullableString(row.state),
|
|
11427
|
+
pool: row.pool === null ? null : indexedAddress(row.pool, true),
|
|
11428
|
+
...row.poolKey === void 0 ? {} : { poolKey: nullableString(row.poolKey) },
|
|
11429
|
+
token0: row.token0 === null ? null : indexedAddress(row.token0, true),
|
|
11430
|
+
token1: row.token1 === null ? null : indexedAddress(row.token1, true),
|
|
11431
|
+
payloadIpfs: nullableString(row.payloadIpfs),
|
|
11432
|
+
strategyToken: strategy === null ? null : Object.freeze({ id: String(strategy.id) })
|
|
11433
|
+
});
|
|
11434
|
+
}
|
|
11435
|
+
/** Validate and detach caller-owned metadata before any asynchronous resolution. */
|
|
11436
|
+
function captureVaultMetadata(addresses, values) {
|
|
11437
|
+
if (!Array.isArray(values)) throw new Error("Supplied vault metadata must be an array");
|
|
11438
|
+
const requested = new Set(addresses.map((address) => address.toLowerCase()));
|
|
11439
|
+
const records = /* @__PURE__ */ new Map();
|
|
11440
|
+
for (const value of values) {
|
|
11441
|
+
const metadata = vaultMetadata(value);
|
|
11442
|
+
if (!requested.has(metadata.id)) throw new Error(`Supplied vault metadata contains an unrequested address: ${metadata.id}`);
|
|
11443
|
+
if (records.has(metadata.id)) throw new Error(`Supplied vault metadata contains a duplicate address: ${metadata.id}`);
|
|
11444
|
+
records.set(metadata.id, metadata);
|
|
11445
|
+
}
|
|
11446
|
+
for (const address of requested) if (!records.has(address)) throw new Error(`Supplied vault metadata is missing address: ${address}`);
|
|
11447
|
+
return records;
|
|
11448
|
+
}
|
|
11449
|
+
//#endregion
|
|
11401
11450
|
//#region src/vault/resolver-types.ts
|
|
11402
11451
|
let ProtocolContractRole = /* @__PURE__ */ function(ProtocolContractRole) {
|
|
11403
11452
|
ProtocolContractRole["AmmFactory"] = "amm-factory";
|
|
@@ -11785,18 +11834,25 @@ async function filterVaultsByFactory(context, vaults, factory, blockNumber) {
|
|
|
11785
11834
|
//#endregion
|
|
11786
11835
|
//#region src/vault/data-adapter.ts
|
|
11787
11836
|
const nonShareBeacons = ["ScheduledJobs", "DynamicJobs"];
|
|
11788
|
-
const
|
|
11837
|
+
const metadataFields = `id name symbol decimals beaconName createdAt state pool poolKey token0 token1 payloadIpfs strategyToken { id }`;
|
|
11838
|
+
const metadataQuery = `query VaultMetadata($ids: [ID!]!, $first: Int!) {
|
|
11839
|
+
vaults(first: $first, orderBy: id, orderDirection: asc, where: {id_in: $ids}) { ${metadataFields} }
|
|
11840
|
+
_meta { ${metaFields} }
|
|
11841
|
+
}`;
|
|
11842
|
+
const vaultsQuery = (balances) => `query Vaults($first: Int!, $where: Vault_filter!, $block: Int!) {
|
|
11789
11843
|
vaults(first: $first, orderBy: id, orderDirection: asc, where: $where, block: {number: $block}) {
|
|
11790
|
-
id beaconName token0 token1
|
|
11844
|
+
${balances ? "id beaconName token0 token1" : metadataFields}
|
|
11845
|
+
token0Symbol token1Symbol token0Name token1Name
|
|
11791
11846
|
}
|
|
11792
11847
|
_meta(block: {number: $block}) { ${metaFields} }
|
|
11793
11848
|
}`;
|
|
11794
11849
|
function matchesToken(row, token, side) {
|
|
11795
|
-
|
|
11850
|
+
if (row[`token${side}`] === null) return false;
|
|
11851
|
+
const address = indexedAddress(row[`token${side}`], true);
|
|
11796
11852
|
const symbol = row[`token${side}Symbol`];
|
|
11797
11853
|
const name = row[`token${side}Name`];
|
|
11798
|
-
if (typeof symbol !== "string" || typeof name !== "string") throw new Error("Malformed vault token metadata");
|
|
11799
|
-
return (!token.address || token.address === address) && (!token.symbol || symbol.toLowerCase().includes(token.symbol)) && (!token.name || name.toLowerCase().includes(token.name));
|
|
11854
|
+
if (symbol !== null && typeof symbol !== "string" || name !== null && typeof name !== "string") throw new Error("Malformed vault token metadata");
|
|
11855
|
+
return (!token.address || token.address === address) && (!token.symbol || typeof symbol === "string" && symbol.toLowerCase().includes(token.symbol)) && (!token.name || typeof name === "string" && name.toLowerCase().includes(token.name));
|
|
11800
11856
|
}
|
|
11801
11857
|
function vaultFilter(token, after, beacons, balances) {
|
|
11802
11858
|
const base = {
|
|
@@ -11885,7 +11941,7 @@ var CatalogSteerDataAdapter = class extends SteerDataAdapter {
|
|
|
11885
11941
|
...cursor === void 0 ? {} : { cursor },
|
|
11886
11942
|
limit: input.limit ?? 1e3
|
|
11887
11943
|
}, options, true);
|
|
11888
|
-
const items = await scanVaultBalances(this.#context, page.items, input.account, page.indexedBlock);
|
|
11944
|
+
const items = await scanVaultBalances(this.#context, page.items.map((row) => indexedAddress(row.id)), input.account, page.indexedBlock);
|
|
11889
11945
|
return Object.freeze({
|
|
11890
11946
|
items,
|
|
11891
11947
|
indexedBlock: page.indexedBlock,
|
|
@@ -11896,9 +11952,44 @@ var CatalogSteerDataAdapter = class extends SteerDataAdapter {
|
|
|
11896
11952
|
}) } : {}
|
|
11897
11953
|
});
|
|
11898
11954
|
}
|
|
11955
|
+
async #metadataQuery(query, variables, options) {
|
|
11956
|
+
try {
|
|
11957
|
+
return await this.#query(query, variables, options);
|
|
11958
|
+
} catch (error) {
|
|
11959
|
+
const errors = error instanceof Error ? error.cause : void 0;
|
|
11960
|
+
if (!query.includes("poolKey") || !Array.isArray(errors) || !errors.length || !errors.every((value) => typeof value?.message === "string" && /^Cannot query field "poolKey" on type "Vault"\.(?: Did you mean .*\?)?$/.test(value.message))) throw error;
|
|
11961
|
+
return this.#query(query.replace(/\bpoolKey\b/g, ""), variables, options);
|
|
11962
|
+
}
|
|
11963
|
+
}
|
|
11964
|
+
async getVaultMetadata(addresses, options = {}) {
|
|
11965
|
+
const ids = addresses.map((address) => indexedAddress(address));
|
|
11966
|
+
const unique = [...new Set(ids)];
|
|
11967
|
+
if (!unique.length) return Object.freeze([]);
|
|
11968
|
+
if (unique.length > 1e3) throw new Error("Vault metadata lookup supports at most 1000 addresses");
|
|
11969
|
+
const data = await this.#metadataQuery(metadataQuery, {
|
|
11970
|
+
ids: unique,
|
|
11971
|
+
first: unique.length
|
|
11972
|
+
}, options);
|
|
11973
|
+
snapshot(data);
|
|
11974
|
+
if (!Array.isArray(data.vaults) || data.vaults.length > unique.length) throw new Error("Malformed vault metadata response");
|
|
11975
|
+
const records = /* @__PURE__ */ new Map();
|
|
11976
|
+
for (const value of data.vaults) {
|
|
11977
|
+
const metadata = vaultMetadata(value);
|
|
11978
|
+
if (!unique.includes(metadata.id) || records.has(metadata.id)) throw new Error("Unexpected or duplicate vault metadata");
|
|
11979
|
+
records.set(metadata.id, metadata);
|
|
11980
|
+
}
|
|
11981
|
+
return Object.freeze(ids.map((id) => {
|
|
11982
|
+
const metadata = records.get(id);
|
|
11983
|
+
if (!metadata) throw new Error("Vault metadata is not indexed");
|
|
11984
|
+
return metadata;
|
|
11985
|
+
}));
|
|
11986
|
+
}
|
|
11899
11987
|
async listVaults(request = {}, options = {}) {
|
|
11900
|
-
const { indexedBlock: _, ...page } = await this.#listVaults(request, options, false);
|
|
11901
|
-
return Object.freeze(
|
|
11988
|
+
const { indexedBlock: _, items, ...page } = await this.#listVaults(request, options, false);
|
|
11989
|
+
return Object.freeze({
|
|
11990
|
+
...page,
|
|
11991
|
+
items: Object.freeze(items.map(vaultMetadata))
|
|
11992
|
+
});
|
|
11902
11993
|
}
|
|
11903
11994
|
async #listVaults(request = {}, options = {}, balances = false) {
|
|
11904
11995
|
const limit = request.limit ?? 100;
|
|
@@ -11931,7 +12022,7 @@ var CatalogSteerDataAdapter = class extends SteerDataAdapter {
|
|
|
11931
12022
|
} });
|
|
11932
12023
|
} else expected = snapshot(await this.#query(snapshotQuery, {}, options));
|
|
11933
12024
|
const beacons = amm ? this.#beacons.get(amm) : void 0;
|
|
11934
|
-
const data = await this.#
|
|
12025
|
+
const data = await this.#metadataQuery(vaultsQuery(balances), {
|
|
11935
12026
|
first: limit,
|
|
11936
12027
|
where: vaultFilter(token, after, beacons, balances),
|
|
11937
12028
|
block: expected.block
|
|
@@ -11948,13 +12039,15 @@ var CatalogSteerDataAdapter = class extends SteerDataAdapter {
|
|
|
11948
12039
|
if (balances && (typeof row.beaconName !== "string" || nonShareBeacons.includes(row.beaconName))) throw new Error("User vault listing returned a non-share deployment");
|
|
11949
12040
|
if (beacons && (typeof row.beaconName !== "string" || !beacons.includes(row.beaconName))) throw new Error("Vault listing does not match the AMM beacon mapping");
|
|
11950
12041
|
if (token && !matchesToken(row, token, 0) && !matchesToken(row, token, 1)) throw new Error("Vault listing does not match the token filter");
|
|
11951
|
-
|
|
12042
|
+
if (!balances) vaultMetadata(row);
|
|
12043
|
+
return row;
|
|
11952
12044
|
});
|
|
11953
|
-
const last = items.at(-1);
|
|
12045
|
+
const last = items.at(-1)?.id;
|
|
11954
12046
|
const factory = amm ? this.#factories.get(amm) : void 0;
|
|
11955
|
-
const filtered = factory ? await filterVaultsByFactory(this.#context, items, factory, BigInt(expected.block)) : items;
|
|
12047
|
+
const filtered = factory ? await filterVaultsByFactory(this.#context, items.map((row) => indexedAddress(row.id)), factory, BigInt(expected.block)) : items.map((row) => indexedAddress(row.id));
|
|
12048
|
+
const included = new Set(filtered);
|
|
11956
12049
|
return Object.freeze({
|
|
11957
|
-
items: Object.freeze(
|
|
12050
|
+
items: Object.freeze(items.filter((row) => included.has(indexedAddress(row.id)))),
|
|
11958
12051
|
indexedBlock: BigInt(expected.block),
|
|
11959
12052
|
...items.length === limit && last ? { nextCursor: JSON.stringify({
|
|
11960
12053
|
version: 1,
|
|
@@ -13758,10 +13851,13 @@ var SteerVault = class {
|
|
|
13758
13851
|
chain;
|
|
13759
13852
|
steer;
|
|
13760
13853
|
underlying;
|
|
13761
|
-
|
|
13854
|
+
metadata;
|
|
13855
|
+
constructor(address, chain, steer, underlying, metadata) {
|
|
13762
13856
|
this.address = address;
|
|
13763
13857
|
this.chain = chain;
|
|
13764
13858
|
this.steer = steer;
|
|
13859
|
+
this.metadata = vaultMetadata(metadata);
|
|
13860
|
+
if (this.metadata.id !== address.toLowerCase()) throw new Error("Vault metadata belongs to another vault");
|
|
13765
13861
|
this.underlying = Object.freeze([...underlying]);
|
|
13766
13862
|
}
|
|
13767
13863
|
};
|
|
@@ -14423,7 +14519,7 @@ var AerodromeVault = class extends LiquidityVault {
|
|
|
14423
14519
|
#positionManager;
|
|
14424
14520
|
/** @internal */
|
|
14425
14521
|
constructor(context, identity) {
|
|
14426
|
-
super(context.address, context.steer.context, context.steer, context.underlying);
|
|
14522
|
+
super(context.address, context.steer.context, context.steer, context.underlying, context.metadata);
|
|
14427
14523
|
const underlying = context.underlying[0];
|
|
14428
14524
|
if (context.underlying.length !== 1 || underlying?.kind !== "liquidity" || !(underlying.amm instanceof AerodromeSlipstreamAdapter) || typeof underlying.pool !== "string") identityMismatch("Expected one Aerodrome vault pool");
|
|
14429
14525
|
requireAddress(underlying.pool);
|
|
@@ -14527,6 +14623,7 @@ async function readAerodromeBulkSnapshot(vault, data, rpc, beacon) {
|
|
|
14527
14623
|
steer: vault.steer,
|
|
14528
14624
|
address: vault.address,
|
|
14529
14625
|
underlying: vault.underlying,
|
|
14626
|
+
metadata: vault.metadata,
|
|
14530
14627
|
blockNumber: rpc.blockNumber
|
|
14531
14628
|
}, identity, {
|
|
14532
14629
|
raw: decodeAerodromeSnapshot(data),
|
|
@@ -15566,6 +15663,7 @@ async function readIntegralBulkSnapshot(vault, data, rpc) {
|
|
|
15566
15663
|
steer: vault.steer,
|
|
15567
15664
|
address: vault.address,
|
|
15568
15665
|
underlying: vault.underlying,
|
|
15666
|
+
metadata: vault.metadata,
|
|
15569
15667
|
blockNumber: rpc.blockNumber
|
|
15570
15668
|
}, {
|
|
15571
15669
|
raw,
|
|
@@ -15579,7 +15677,7 @@ var AlgebraIntegralVault = class extends LiquidityVault {
|
|
|
15579
15677
|
amm;
|
|
15580
15678
|
pool;
|
|
15581
15679
|
constructor(context) {
|
|
15582
|
-
super(context.address, context.steer.context, context.steer, context.underlying);
|
|
15680
|
+
super(context.address, context.steer.context, context.steer, context.underlying, context.metadata);
|
|
15583
15681
|
const underlying = context.underlying[0];
|
|
15584
15682
|
if (context.underlying.length !== 1 || underlying?.kind !== "liquidity" || !isAlgebraIntegralAdapter(underlying.amm) || typeof underlying.pool !== "string") identityMismatch("Expected one Integral vault pool");
|
|
15585
15683
|
requireAddress(underlying.pool);
|
|
@@ -17178,6 +17276,7 @@ async function readV3BulkSnapshot(vault, data, rpc) {
|
|
|
17178
17276
|
steer: vault.steer,
|
|
17179
17277
|
address: vault.address,
|
|
17180
17278
|
underlying: vault.underlying,
|
|
17279
|
+
metadata: vault.metadata,
|
|
17181
17280
|
blockNumber: rpc.blockNumber
|
|
17182
17281
|
}, {
|
|
17183
17282
|
raw,
|
|
@@ -17191,7 +17290,7 @@ var UniswapV3Vault = class extends LiquidityVault {
|
|
|
17191
17290
|
amm;
|
|
17192
17291
|
pool;
|
|
17193
17292
|
constructor(context) {
|
|
17194
|
-
super(context.address, context.steer.context, context.steer, context.underlying);
|
|
17293
|
+
super(context.address, context.steer.context, context.steer, context.underlying, context.metadata);
|
|
17195
17294
|
const underlying = context.underlying[0];
|
|
17196
17295
|
if (context.underlying.length !== 1 || underlying?.kind !== "liquidity" || !isUniswapV3Adapter(underlying.amm) || typeof underlying.pool !== "string") identityMismatch("Expected one V3 vault pool");
|
|
17197
17296
|
requireAddress(underlying.pool);
|
|
@@ -18824,7 +18923,7 @@ var UniswapV4Vault = class extends LiquidityVault {
|
|
|
18824
18923
|
amm;
|
|
18825
18924
|
pool;
|
|
18826
18925
|
constructor(context) {
|
|
18827
|
-
super(context.address, context.steer.context, context.steer, context.underlying);
|
|
18926
|
+
super(context.address, context.steer.context, context.steer, context.underlying, context.metadata);
|
|
18828
18927
|
const underlying = context.underlying[0];
|
|
18829
18928
|
if (context.underlying.length !== 1 || underlying?.kind !== "liquidity" || !(underlying.amm instanceof UniswapV4Adapter) || !isLiquidityPool(underlying.pool) || typeof underlying.pool === "string") identityMismatch("Expected one standalone V4 vault pool");
|
|
18830
18929
|
this.amm = underlying.amm;
|
|
@@ -20204,6 +20303,7 @@ async function readLegacyBulkSnapshot(vault, data, rpc, beacon) {
|
|
|
20204
20303
|
steer: vault.steer,
|
|
20205
20304
|
address: vault.address,
|
|
20206
20305
|
underlying: vault.underlying,
|
|
20306
|
+
metadata: vault.metadata,
|
|
20207
20307
|
blockNumber: rpc.blockNumber
|
|
20208
20308
|
}, {
|
|
20209
20309
|
raw,
|
|
@@ -20217,7 +20317,7 @@ var AlgebraLegacyVault = class extends LiquidityVault {
|
|
|
20217
20317
|
amm;
|
|
20218
20318
|
pool;
|
|
20219
20319
|
constructor(context) {
|
|
20220
|
-
super(context.address, context.steer.context, context.steer, context.underlying);
|
|
20320
|
+
super(context.address, context.steer.context, context.steer, context.underlying, context.metadata);
|
|
20221
20321
|
const underlying = context.underlying[0];
|
|
20222
20322
|
if (context.underlying.length !== 1 || underlying?.kind !== "liquidity" || !isAlgebraLegacyAdapter(underlying.amm) || typeof underlying.pool !== "string") identityMismatch("Expected one Legacy vault pool");
|
|
20223
20323
|
requireAddress(underlying.pool);
|
|
@@ -20824,7 +20924,7 @@ var VaultResolver = class {
|
|
|
20824
20924
|
if (!vault) throw new Error("Missing resolved vault");
|
|
20825
20925
|
return vault;
|
|
20826
20926
|
}
|
|
20827
|
-
async #createVault(context, identity, verified) {
|
|
20927
|
+
async #createVault(context, identity, loadMetadata, verified) {
|
|
20828
20928
|
const { steer, address } = context;
|
|
20829
20929
|
if (!identity) throw new VaultResolutionError("not-registered", "Vault is not registered with Steer");
|
|
20830
20930
|
if (identity.chainId !== steer.context.chainId || addressKey(identity.vaultAddress) !== addressKey(address) || addressKey(identity.registryAddress) !== addressKey(steer.contracts.VaultRegistry.address) || addressKey(identity.beaconAddress) !== addressKey(identity.proxyBeaconAddress)) throw new VaultResolutionError("identity-mismatch", "Vault identity does not match the request");
|
|
@@ -20836,9 +20936,12 @@ var VaultResolver = class {
|
|
|
20836
20936
|
lending: /* @__PURE__ */ new Map()
|
|
20837
20937
|
};
|
|
20838
20938
|
const resolvedUnderlying = Object.freeze(underlying.map((position) => this.#resolveUnderlying(position, adapters)));
|
|
20939
|
+
const metadata = await loadMetadata();
|
|
20940
|
+
if (metadata.id.toLowerCase() !== address.toLowerCase()) throw new Error("Vault metadata belongs to another vault");
|
|
20839
20941
|
const resolved = Object.freeze({
|
|
20840
20942
|
...context,
|
|
20841
|
-
underlying: resolvedUnderlying
|
|
20943
|
+
underlying: resolvedUnderlying,
|
|
20944
|
+
metadata
|
|
20842
20945
|
});
|
|
20843
20946
|
const vault = binding.createVault(resolved);
|
|
20844
20947
|
this.#validateVault(vault, binding, resolved);
|
|
@@ -20858,21 +20961,39 @@ var VaultResolver = class {
|
|
|
20858
20961
|
steer: vault.steer,
|
|
20859
20962
|
address: vault.address,
|
|
20860
20963
|
underlying: vault.underlying,
|
|
20964
|
+
metadata: vault.metadata,
|
|
20861
20965
|
blockNumber
|
|
20862
20966
|
});
|
|
20863
20967
|
if (snapshot.blockNumber !== blockNumber || !vault.underlying.some((position) => position.kind === "liquidity" && sameLiquidityPool(position.pool, snapshot.pool))) throw new Error("Vault returned another accounting snapshot");
|
|
20864
20968
|
return readValidatedVaultSnapshot(vault, snapshot, vault.steer.context);
|
|
20865
20969
|
}
|
|
20970
|
+
#metadata(steer, addresses, supplied) {
|
|
20971
|
+
let pending;
|
|
20972
|
+
return async (address) => {
|
|
20973
|
+
if (supplied) {
|
|
20974
|
+
const metadata = supplied.get(address.toLowerCase());
|
|
20975
|
+
if (!metadata) throw new Error(`Supplied vault metadata is missing address: ${address}`);
|
|
20976
|
+
return metadata;
|
|
20977
|
+
}
|
|
20978
|
+
pending ??= steer.dataAdapter.getVaultMetadata(addresses);
|
|
20979
|
+
const metadata = (await pending).find((record) => record.id.toLowerCase() === address.toLowerCase());
|
|
20980
|
+
if (!metadata) throw new Error("Vault metadata is not indexed");
|
|
20981
|
+
return metadata;
|
|
20982
|
+
};
|
|
20983
|
+
}
|
|
20866
20984
|
/** Bounded bulk identity pages at one block; compatibility uses four active loads. */
|
|
20867
20985
|
async resolveMany(steer, addresses, options) {
|
|
20868
20986
|
const inputs = [...addresses];
|
|
20869
20987
|
for (const address of inputs) addressKey(address);
|
|
20988
|
+
const supplied = options?.metadata;
|
|
20989
|
+
const metadata = supplied === void 0 ? void 0 : captureVaultMetadata(inputs, supplied);
|
|
20870
20990
|
if (!inputs.length) return Object.freeze([]);
|
|
20871
20991
|
const blockNumber = await this.#blockNumber(steer, options);
|
|
20872
20992
|
const result = [];
|
|
20873
20993
|
let bulkSupported = !!this.#reader.readMany;
|
|
20874
20994
|
for (let start = 0; start < inputs.length; start += 64) {
|
|
20875
20995
|
const batch = inputs.slice(start, start + 64);
|
|
20996
|
+
const loadMetadata = this.#metadata(steer, batch, metadata);
|
|
20876
20997
|
const contexts = batch.map((address) => Object.freeze({
|
|
20877
20998
|
steer,
|
|
20878
20999
|
address,
|
|
@@ -20884,13 +21005,13 @@ var VaultResolver = class {
|
|
|
20884
21005
|
for (const [i, context] of contexts.entries()) {
|
|
20885
21006
|
const read = reads[i];
|
|
20886
21007
|
if (!read) throw new VaultResolutionError("identity-mismatch", "Missing bulk vault identity");
|
|
20887
|
-
result.push((await this.#createVault(context, read.identity, read)).vault);
|
|
21008
|
+
result.push((await this.#createVault(context, read.identity, () => loadMetadata(context.address), read)).vault);
|
|
20888
21009
|
}
|
|
20889
21010
|
} else {
|
|
20890
21011
|
bulkSupported = false;
|
|
20891
21012
|
for (let i = 0; i < batch.length; i += 4) result.push(...await Promise.all(contexts.slice(i, i + 4).map(async (context) => {
|
|
20892
21013
|
const identity = await this.#reader.readIdentity(context);
|
|
20893
|
-
return (await this.#createVault(context, identity)).vault;
|
|
21014
|
+
return (await this.#createVault(context, identity, () => loadMetadata(context.address))).vault;
|
|
20894
21015
|
})));
|
|
20895
21016
|
}
|
|
20896
21017
|
}
|
|
@@ -20906,6 +21027,7 @@ var VaultResolver = class {
|
|
|
20906
21027
|
let bulkSupported = !!this.#reader.readSnapshots;
|
|
20907
21028
|
for (let start = 0; start < inputs.length; start += 16) {
|
|
20908
21029
|
const batch = inputs.slice(start, start + 16);
|
|
21030
|
+
const loadMetadata = this.#metadata(steer, batch);
|
|
20909
21031
|
const contexts = batch.map((address) => Object.freeze({
|
|
20910
21032
|
steer,
|
|
20911
21033
|
address,
|
|
@@ -20917,7 +21039,7 @@ var VaultResolver = class {
|
|
|
20917
21039
|
for (const [i, context] of contexts.entries()) {
|
|
20918
21040
|
const read = reads[i];
|
|
20919
21041
|
if (!read) throw new Error("Missing bulk vault snapshot");
|
|
20920
|
-
const { vault } = await this.#createVault(context, read.identity, read);
|
|
21042
|
+
const { vault } = await this.#createVault(context, read.identity, () => loadMetadata(context.address), read);
|
|
20921
21043
|
if (vault.kind !== "liquidity") throw new VaultResolutionError("invalid-vault", "Vault does not support liquidity snapshots");
|
|
20922
21044
|
result.push(await read.readSnapshot(vault));
|
|
20923
21045
|
}
|
|
@@ -20930,7 +21052,7 @@ var VaultResolver = class {
|
|
|
20930
21052
|
blockNumber
|
|
20931
21053
|
});
|
|
20932
21054
|
const identity = await this.#reader.readIdentity(context);
|
|
20933
|
-
const { vault, binding, context: resolved } = await this.#createVault(context, identity);
|
|
21055
|
+
const { vault, binding, context: resolved } = await this.#createVault(context, identity, () => loadMetadata(context.address));
|
|
20934
21056
|
if (vault.kind !== "liquidity") throw new VaultResolutionError("invalid-vault", "Vault does not support liquidity snapshots");
|
|
20935
21057
|
if (!binding.readSnapshot) throw new VaultResolutionError("not-configured", "No verified snapshot reader configured for vault implementation");
|
|
20936
21058
|
const snapshot = await binding.readSnapshot(resolved);
|
|
@@ -21028,7 +21150,10 @@ var SteerNetwork = class {
|
|
|
21028
21150
|
return this.#vaultResolver().resolve(this, address, options);
|
|
21029
21151
|
}
|
|
21030
21152
|
async getVaults(addresses, options) {
|
|
21031
|
-
if (!addresses.length)
|
|
21153
|
+
if (!addresses.length) {
|
|
21154
|
+
if (options?.metadata !== void 0) captureVaultMetadata(addresses, options.metadata);
|
|
21155
|
+
return Object.freeze([]);
|
|
21156
|
+
}
|
|
21032
21157
|
return this.#vaultResolver().resolveMany(this, addresses, options);
|
|
21033
21158
|
}
|
|
21034
21159
|
getVaultSnapshots(addresses, options) {
|