@steerprotocol/sdk 3.2.8 → 3.3.0
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 +35 -0
- package/dist/index.browser.mjs +373 -2
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.cjs +372 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +78 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +373 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -216,6 +216,41 @@ if (preview.success) {
|
|
|
216
216
|
}
|
|
217
217
|
```
|
|
218
218
|
|
|
219
|
+
## Block-pinned vault execution context
|
|
220
|
+
|
|
221
|
+
Strategy execution consumers can read a normalized, JSON-safe vault context without selecting
|
|
222
|
+
protocol adapters or assembling pool state themselves:
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { getVaultExecutionContext } from '@steerprotocol/sdk';
|
|
226
|
+
|
|
227
|
+
const context = await getVaultExecutionContext({
|
|
228
|
+
publicClient,
|
|
229
|
+
vaultAddress: '0x666805942995ff8494294720a1dadb7cd2348750',
|
|
230
|
+
blockNumber: 49_251_269n,
|
|
231
|
+
epochTimestamp: 1_800_000_000n, // Unix seconds; explicit, never wall-clock time
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
if (!context.success) throw new Error(context.error);
|
|
235
|
+
|
|
236
|
+
console.log(context.data.protocol, context.data.currentTick);
|
|
237
|
+
console.log(context.data.totalAmount0, context.data.lastExecutionTimeSeconds);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The same capability is available as `vaultClient.getExecutionContext(...)`. The SDK resolves the
|
|
241
|
+
vault's beacon name, beacon address, and protocol through the deployed `VaultRegistry`, verifies
|
|
242
|
+
non-v4 pool factories against SDK protocol configuration, and reads positions, totals, tick spacing,
|
|
243
|
+
and pool state at the exact supplied block. Uniswap v4 uses the vault's complete `poolKey()`, derives
|
|
244
|
+
its pool ID, and reads state through the configured `StateView`; an optional `poolKey` input acts as
|
|
245
|
+
an assertion and must match exactly.
|
|
246
|
+
|
|
247
|
+
All integer values that may exceed JavaScript's safe range are returned as decimal strings. The
|
|
248
|
+
`provenance` object identifies block-pinned contract data. Last execution comes from the established
|
|
249
|
+
Steer `vaultSnapshots` entity, queried below both the explicit epoch and pinned-block timestamp; its
|
|
250
|
+
provenance is marked `timestamp-bounded` because the entity does not expose a block number. When no
|
|
251
|
+
earlier snapshot exists, both last-execution fields are `null`; lookup or historical consistency
|
|
252
|
+
failures return an unsuccessful `SteerResponse` rather than falling back to latest state.
|
|
253
|
+
|
|
219
254
|
### Advanced Usage
|
|
220
255
|
|
|
221
256
|
#### Using Individual Functions
|
package/dist/index.browser.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { decodeFunctionResult, encodeFunctionData, formatUnits, getContract, isAddressEqual } from "viem";
|
|
1
|
+
import { decodeFunctionResult, encodeAbiParameters, encodeFunctionData, formatUnits, getAddress, getContract, isAddress, isAddressEqual, keccak256, parseAbi } from "viem";
|
|
2
2
|
import { createClient } from "@steerprotocol/api-sdk";
|
|
3
3
|
import { Rounding, Token } from "@uniswap/sdk-core";
|
|
4
4
|
import { Pool } from "@uniswap/v3-sdk";
|
|
@@ -19646,6 +19646,366 @@ var VaultWithdrawClient = class {
|
|
|
19646
19646
|
}
|
|
19647
19647
|
};
|
|
19648
19648
|
//#endregion
|
|
19649
|
+
//#region src/base/vault/execution-context.ts
|
|
19650
|
+
const VAULT_REGISTRY_ABI = parseAbi(["function getVaultDetails(address vault) view returns ((uint8 state,uint256 tokenId,uint256 vaultID,string payloadIpfs,address vaultAddress,string beaconName) details)", "function beaconAddresses(string beaconName) view returns (address)"]);
|
|
19651
|
+
const VAULT_EXECUTION_ABI = parseAbi([
|
|
19652
|
+
"function pool() view returns (address)",
|
|
19653
|
+
"function getPositions() view returns (int24[] lowerTicks,int24[] upperTicks,uint16[] relativeWeights)",
|
|
19654
|
+
"function getTotalAmounts() view returns (uint256 total0,uint256 total1)"
|
|
19655
|
+
]);
|
|
19656
|
+
const V4_VAULT_ABI = parseAbi([
|
|
19657
|
+
"function poolKey() view returns (address currency0,address currency1,uint24 fee,int24 tickSpacing,address hooks)",
|
|
19658
|
+
"function getPositions() view returns (int24[] lowerTicks,int24[] upperTicks,uint16[] relativeWeights)",
|
|
19659
|
+
"function getTotalAmounts() view returns (uint256 total0,uint256 total1)"
|
|
19660
|
+
]);
|
|
19661
|
+
const V3_POOL_ABI = parseAbi([
|
|
19662
|
+
"function factory() view returns (address)",
|
|
19663
|
+
"function slot0() view returns (uint160 sqrtPriceX96,int24 tick,uint16 observationIndex,uint16 observationCardinality,uint16 observationCardinalityNext,uint8 feeProtocol,bool unlocked)",
|
|
19664
|
+
"function tickSpacing() view returns (int24)"
|
|
19665
|
+
]);
|
|
19666
|
+
const AERODROME_POOL_ABI = parseAbi([
|
|
19667
|
+
"function factory() view returns (address)",
|
|
19668
|
+
"function slot0() view returns (uint160 sqrtPriceX96,int24 tick,uint16 observationIndex,uint16 observationCardinality,uint16 observationCardinalityNext,bool unlocked)",
|
|
19669
|
+
"function tickSpacing() view returns (int24)"
|
|
19670
|
+
]);
|
|
19671
|
+
const ALGEBRA_POOL_ABI = parseAbi([
|
|
19672
|
+
"function factory() view returns (address)",
|
|
19673
|
+
"function globalState() view returns (uint160 price,int24 tick,int24 prevInitializedTick,uint16 fee,uint16 timepointIndex,uint8 communityFee,bool unlocked)",
|
|
19674
|
+
"function tickSpacing() view returns (int24)"
|
|
19675
|
+
]);
|
|
19676
|
+
const ALGEBRA_INTEGRAL_POOL_ABI = parseAbi([
|
|
19677
|
+
"function factory() view returns (address)",
|
|
19678
|
+
"function globalState() view returns (uint160 price,int24 tick,uint16 lastFee,uint8 pluginConfig,uint16 communityFee,bool unlocked)",
|
|
19679
|
+
"function tickSpacing() view returns (int24)"
|
|
19680
|
+
]);
|
|
19681
|
+
const ALGEBRA_DIRECTIONAL_POOL_ABI = parseAbi([
|
|
19682
|
+
"function factory() view returns (address)",
|
|
19683
|
+
"function globalState() view returns (uint160 price,int24 tick,uint16 feeZto,uint16 feeOtz,uint16 timepointIndex,uint8 communityFeeToken0,uint8 communityFeeToken1,bool unlocked)",
|
|
19684
|
+
"function tickSpacing() view returns (int24)"
|
|
19685
|
+
]);
|
|
19686
|
+
const STATE_VIEW_ABI = parseAbi(["function getSlot0(bytes32 poolId) view returns (uint160 sqrtPriceX96,int24 tick,uint24 protocolFee,uint24 lpFee)"]);
|
|
19687
|
+
const V4_DYNAMIC_FEE_FLAG = 8388608;
|
|
19688
|
+
const V4_MAX_STATIC_FEE = 1e6;
|
|
19689
|
+
const V4_MAX_TICK_SPACING = 32767;
|
|
19690
|
+
const V4_ALL_HOOK_MASK = (1n << 14n) - 1n;
|
|
19691
|
+
const V4_BEFORE_SWAP_FLAG = 1n << 7n;
|
|
19692
|
+
const V4_AFTER_SWAP_FLAG = 1n << 6n;
|
|
19693
|
+
const V4_AFTER_ADD_LIQUIDITY_FLAG = 1n << 10n;
|
|
19694
|
+
const V4_AFTER_REMOVE_LIQUIDITY_FLAG = 1n << 8n;
|
|
19695
|
+
const V4_BEFORE_SWAP_RETURNS_DELTA_FLAG = 1n << 3n;
|
|
19696
|
+
const V4_AFTER_SWAP_RETURNS_DELTA_FLAG = 1n << 2n;
|
|
19697
|
+
const V4_AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1n << 1n;
|
|
19698
|
+
const V4_AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1n;
|
|
19699
|
+
var ExecutionContextError = class extends Error {
|
|
19700
|
+
constructor(status, message) {
|
|
19701
|
+
super(message);
|
|
19702
|
+
this.status = status;
|
|
19703
|
+
}
|
|
19704
|
+
};
|
|
19705
|
+
function resolvePoolFamily(protocol) {
|
|
19706
|
+
if (isPoolSharkProtocol(protocol)) throw new ExecutionContextError(422, "PoolShark vault execution context is not supported.");
|
|
19707
|
+
if (protocol === Protocol.UniswapV4) return "uniswap-v4";
|
|
19708
|
+
if (isAlgebraDirectionProtocol(protocol)) return "algebra-directional";
|
|
19709
|
+
if (isAlgebraIntegralProtocol(protocol)) return "algebra-integral";
|
|
19710
|
+
if (isAlgebraProtocol(protocol)) return "algebra";
|
|
19711
|
+
if (isAerodromeVault(protocol)) return "aerodrome-cl";
|
|
19712
|
+
return "uniswap-v3-compatible";
|
|
19713
|
+
}
|
|
19714
|
+
function assertPoolKey(poolKey, invalidStatus = 400) {
|
|
19715
|
+
if (!isAddress(poolKey.currency0) || !isAddress(poolKey.currency1) || !isAddress(poolKey.hooks)) throw new ExecutionContextError(invalidStatus, "Uniswap v4 poolKey contains an invalid address.");
|
|
19716
|
+
if (!Number.isInteger(poolKey.fee) || poolKey.fee < 0 || poolKey.fee > V4_MAX_STATIC_FEE && poolKey.fee !== V4_DYNAMIC_FEE_FLAG) throw new ExecutionContextError(invalidStatus, "Uniswap v4 poolKey fee must be at most 1000000 or the dynamic fee flag 0x800000.");
|
|
19717
|
+
if (!Number.isInteger(poolKey.tickSpacing) || poolKey.tickSpacing <= 0 || poolKey.tickSpacing > V4_MAX_TICK_SPACING) throw new ExecutionContextError(invalidStatus, "Uniswap v4 poolKey tickSpacing must be between 1 and 32767.");
|
|
19718
|
+
const normalized = {
|
|
19719
|
+
currency0: getAddress(poolKey.currency0),
|
|
19720
|
+
currency1: getAddress(poolKey.currency1),
|
|
19721
|
+
fee: poolKey.fee,
|
|
19722
|
+
tickSpacing: poolKey.tickSpacing,
|
|
19723
|
+
hooks: getAddress(poolKey.hooks)
|
|
19724
|
+
};
|
|
19725
|
+
if (BigInt(normalized.currency0) >= BigInt(normalized.currency1)) throw new ExecutionContextError(invalidStatus, "Uniswap v4 poolKey currencies are not canonically ordered.");
|
|
19726
|
+
const hooks = BigInt(normalized.hooks);
|
|
19727
|
+
const isDynamicFee = normalized.fee === V4_DYNAMIC_FEE_FLAG;
|
|
19728
|
+
const hasFlag = (flag) => (hooks & flag) !== 0n;
|
|
19729
|
+
if (!hasFlag(V4_BEFORE_SWAP_FLAG) && hasFlag(V4_BEFORE_SWAP_RETURNS_DELTA_FLAG) || !hasFlag(V4_AFTER_SWAP_FLAG) && hasFlag(V4_AFTER_SWAP_RETURNS_DELTA_FLAG) || !hasFlag(V4_AFTER_ADD_LIQUIDITY_FLAG) && hasFlag(V4_AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) || !hasFlag(V4_AFTER_REMOVE_LIQUIDITY_FLAG) && hasFlag(V4_AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)) throw new ExecutionContextError(invalidStatus, "Uniswap v4 poolKey hook return-delta flags require their corresponding action flags.");
|
|
19730
|
+
if (!(hooks === 0n ? !isDynamicFee : (hooks & V4_ALL_HOOK_MASK) !== 0n || isDynamicFee)) throw new ExecutionContextError(invalidStatus, "Uniswap v4 poolKey hook address is incompatible with its fee and permission flags.");
|
|
19731
|
+
return normalized;
|
|
19732
|
+
}
|
|
19733
|
+
function normalizeRawPoolKey(raw) {
|
|
19734
|
+
return assertPoolKey({
|
|
19735
|
+
currency0: raw[0],
|
|
19736
|
+
currency1: raw[1],
|
|
19737
|
+
fee: Number(raw[2]),
|
|
19738
|
+
tickSpacing: Number(raw[3]),
|
|
19739
|
+
hooks: raw[4]
|
|
19740
|
+
}, 422);
|
|
19741
|
+
}
|
|
19742
|
+
function poolKeysEqual(a, b) {
|
|
19743
|
+
return getAddress(a.currency0) === getAddress(b.currency0) && getAddress(a.currency1) === getAddress(b.currency1) && a.fee === b.fee && a.tickSpacing === b.tickSpacing && getAddress(a.hooks) === getAddress(b.hooks);
|
|
19744
|
+
}
|
|
19745
|
+
function getPoolId(poolKey) {
|
|
19746
|
+
return keccak256(encodeAbiParameters([{
|
|
19747
|
+
type: "tuple",
|
|
19748
|
+
components: [
|
|
19749
|
+
{
|
|
19750
|
+
name: "currency0",
|
|
19751
|
+
type: "address"
|
|
19752
|
+
},
|
|
19753
|
+
{
|
|
19754
|
+
name: "currency1",
|
|
19755
|
+
type: "address"
|
|
19756
|
+
},
|
|
19757
|
+
{
|
|
19758
|
+
name: "fee",
|
|
19759
|
+
type: "uint24"
|
|
19760
|
+
},
|
|
19761
|
+
{
|
|
19762
|
+
name: "tickSpacing",
|
|
19763
|
+
type: "int24"
|
|
19764
|
+
},
|
|
19765
|
+
{
|
|
19766
|
+
name: "hooks",
|
|
19767
|
+
type: "address"
|
|
19768
|
+
}
|
|
19769
|
+
]
|
|
19770
|
+
}], [poolKey]));
|
|
19771
|
+
}
|
|
19772
|
+
function normalizePositions(raw) {
|
|
19773
|
+
const [lowerTicks, upperTicks, relativeWeights] = raw;
|
|
19774
|
+
if (lowerTicks.length !== upperTicks.length || lowerTicks.length !== relativeWeights.length) throw new ExecutionContextError(422, "Vault returned malformed position arrays.");
|
|
19775
|
+
return lowerTicks.map((lowerTick, index) => ({
|
|
19776
|
+
lowerTick: Number(lowerTick),
|
|
19777
|
+
upperTick: Number(upperTicks[index]),
|
|
19778
|
+
relativeWeight: Number(relativeWeights[index])
|
|
19779
|
+
}));
|
|
19780
|
+
}
|
|
19781
|
+
function protocolFactory(protocol, chain, subgraphStudioKey) {
|
|
19782
|
+
if (!chain) throw new ExecutionContextError(422, "Chain is absent from the SDK network registry.");
|
|
19783
|
+
const address = getAmmConfig(subgraphStudioKey)[protocol]?.factoryAddress?.[chain];
|
|
19784
|
+
if (!address || !isAddress(address)) throw new ExecutionContextError(422, `${protocol} factory is missing from the SDK protocol registry on ${chain}.`);
|
|
19785
|
+
return getAddress(address);
|
|
19786
|
+
}
|
|
19787
|
+
async function readLastExecution(publicClient, chainId, vaultAddress, blockNumber, epochTimestamp) {
|
|
19788
|
+
const pinnedBlock = await publicClient.getBlock({ blockNumber });
|
|
19789
|
+
const timestampUpperBound = pinnedBlock.timestamp < epochTimestamp ? pinnedBlock.timestamp : epochTimestamp;
|
|
19790
|
+
const subgraphUrl = getSubgraphUrlByChainId(chainId);
|
|
19791
|
+
if (!subgraphUrl) throw new ExecutionContextError(422, `Chain ${chainId} has no Steer subgraph configuration.`);
|
|
19792
|
+
const response = await fetch(subgraphUrl, {
|
|
19793
|
+
method: "POST",
|
|
19794
|
+
headers: { "Content-Type": "application/json" },
|
|
19795
|
+
body: JSON.stringify({ query: `{
|
|
19796
|
+
vaultSnapshots(
|
|
19797
|
+
where: { vaultAddress: "${vaultAddress.toLowerCase()}", timestamp_lte: "${timestampUpperBound}" }
|
|
19798
|
+
orderDirection: desc
|
|
19799
|
+
orderBy: timestamp
|
|
19800
|
+
first: 1
|
|
19801
|
+
) { timestamp }
|
|
19802
|
+
}` })
|
|
19803
|
+
});
|
|
19804
|
+
if (!response.ok) throw new ExecutionContextError(502, `Steer subgraph returned HTTP ${response.status}.`);
|
|
19805
|
+
const result = await response.json();
|
|
19806
|
+
if (result.errors?.length) throw new ExecutionContextError(502, `Steer subgraph error: ${result.errors[0].message}`);
|
|
19807
|
+
const rawTimestamp = result.data?.vaultSnapshots?.[0]?.timestamp;
|
|
19808
|
+
if (!rawTimestamp) return {
|
|
19809
|
+
timestamp: null,
|
|
19810
|
+
elapsed: null,
|
|
19811
|
+
provenance: {
|
|
19812
|
+
source: "steer-subgraph",
|
|
19813
|
+
consistency: "timestamp-bounded",
|
|
19814
|
+
status: "not-found",
|
|
19815
|
+
blockNumber: null,
|
|
19816
|
+
detail: `No indexed vaultSnapshot exists through timestamp ${timestampUpperBound}.`
|
|
19817
|
+
}
|
|
19818
|
+
};
|
|
19819
|
+
let timestamp;
|
|
19820
|
+
try {
|
|
19821
|
+
timestamp = BigInt(rawTimestamp);
|
|
19822
|
+
} catch {
|
|
19823
|
+
throw new ExecutionContextError(502, "Steer subgraph returned a malformed vaultSnapshot timestamp.");
|
|
19824
|
+
}
|
|
19825
|
+
if (timestamp > timestampUpperBound) throw new ExecutionContextError(502, "Steer subgraph returned a vaultSnapshot beyond the query bound.");
|
|
19826
|
+
return {
|
|
19827
|
+
timestamp,
|
|
19828
|
+
elapsed: epochTimestamp - timestamp,
|
|
19829
|
+
provenance: {
|
|
19830
|
+
source: "steer-subgraph",
|
|
19831
|
+
consistency: "timestamp-bounded",
|
|
19832
|
+
status: "indexed",
|
|
19833
|
+
blockNumber: null,
|
|
19834
|
+
detail: `Latest indexed vaultSnapshot bounded by epoch and pinned-block timestamp ${timestampUpperBound}; the entity does not expose its block number.`
|
|
19835
|
+
}
|
|
19836
|
+
};
|
|
19837
|
+
}
|
|
19838
|
+
/**
|
|
19839
|
+
* Builds the normalized read-only state consumed by strategy execution.
|
|
19840
|
+
* Every contract read is evaluated at `blockNumber`; `epochTimestamp` is the sole time reference.
|
|
19841
|
+
*/
|
|
19842
|
+
async function getVaultExecutionContext(params) {
|
|
19843
|
+
try {
|
|
19844
|
+
const { publicClient, blockNumber, epochTimestamp } = params;
|
|
19845
|
+
if (blockNumber < 0n) throw new ExecutionContextError(400, "blockNumber must be non-negative.");
|
|
19846
|
+
if (epochTimestamp < 0n) throw new ExecutionContextError(400, "epochTimestamp must be a non-negative Unix timestamp.");
|
|
19847
|
+
if (!isAddress(params.vaultAddress)) throw new ExecutionContextError(400, "vaultAddress must be a valid EVM address.");
|
|
19848
|
+
const chainId = publicClient.chain?.id;
|
|
19849
|
+
if (!chainId) throw new ExecutionContextError(400, "publicClient must have an active chain.");
|
|
19850
|
+
const chain = chainIdToName(chainId);
|
|
19851
|
+
const network = getNetworkByChainId(chainId);
|
|
19852
|
+
const vaultRegistry = getContractAddressByChainIdAndContractName(chainId, "VaultRegistry");
|
|
19853
|
+
if (!chain || !network || !vaultRegistry || !isAddress(vaultRegistry)) throw new ExecutionContextError(422, `Chain ${chainId} is missing required SDK deployment data.`);
|
|
19854
|
+
if (blockNumber < BigInt(network.VaultRegistry.startBlock ?? 0)) throw new ExecutionContextError(400, "blockNumber predates the SDK VaultRegistry deployment.");
|
|
19855
|
+
const vaultAddress = getAddress(params.vaultAddress);
|
|
19856
|
+
const details = await publicClient.readContract({
|
|
19857
|
+
address: getAddress(vaultRegistry),
|
|
19858
|
+
abi: VAULT_REGISTRY_ABI,
|
|
19859
|
+
functionName: "getVaultDetails",
|
|
19860
|
+
args: [vaultAddress],
|
|
19861
|
+
blockNumber
|
|
19862
|
+
});
|
|
19863
|
+
if (!details.vaultAddress || getAddress(details.vaultAddress) !== vaultAddress) throw new ExecutionContextError(404, `${vaultAddress} is not registered in the chain VaultRegistry.`);
|
|
19864
|
+
const protocol = getProtocolTypeByBeacon(details.beaconName);
|
|
19865
|
+
if (!protocol) throw new ExecutionContextError(422, `Vault beacon "${details.beaconName}" is not mapped to a supported SDK protocol.`);
|
|
19866
|
+
const beaconAddress = getAddress(await publicClient.readContract({
|
|
19867
|
+
address: getAddress(vaultRegistry),
|
|
19868
|
+
abi: VAULT_REGISTRY_ABI,
|
|
19869
|
+
functionName: "beaconAddresses",
|
|
19870
|
+
args: [details.beaconName],
|
|
19871
|
+
blockNumber
|
|
19872
|
+
}));
|
|
19873
|
+
if (beaconAddress === "0x0000000000000000000000000000000000000000") throw new ExecutionContextError(422, `Vault beacon "${details.beaconName}" is not registered.`);
|
|
19874
|
+
const family = resolvePoolFamily(protocol);
|
|
19875
|
+
const explicitPoolKey = params.poolKey ? assertPoolKey(params.poolKey) : void 0;
|
|
19876
|
+
const [rawPositions, rawTotals] = await Promise.all([publicClient.readContract({
|
|
19877
|
+
address: vaultAddress,
|
|
19878
|
+
abi: family === "uniswap-v4" ? V4_VAULT_ABI : VAULT_EXECUTION_ABI,
|
|
19879
|
+
functionName: "getPositions",
|
|
19880
|
+
blockNumber
|
|
19881
|
+
}), publicClient.readContract({
|
|
19882
|
+
address: vaultAddress,
|
|
19883
|
+
abi: family === "uniswap-v4" ? V4_VAULT_ABI : VAULT_EXECUTION_ABI,
|
|
19884
|
+
functionName: "getTotalAmounts",
|
|
19885
|
+
blockNumber
|
|
19886
|
+
})]);
|
|
19887
|
+
let poolAddress = null;
|
|
19888
|
+
let poolId = null;
|
|
19889
|
+
let factoryAddress = null;
|
|
19890
|
+
let poolManagerAddress = null;
|
|
19891
|
+
let poolKey = null;
|
|
19892
|
+
let currentTick;
|
|
19893
|
+
let tickSpacing;
|
|
19894
|
+
if (family === "uniswap-v4") {
|
|
19895
|
+
let rawPoolKey;
|
|
19896
|
+
try {
|
|
19897
|
+
rawPoolKey = await publicClient.readContract({
|
|
19898
|
+
address: vaultAddress,
|
|
19899
|
+
abi: V4_VAULT_ABI,
|
|
19900
|
+
functionName: "poolKey",
|
|
19901
|
+
blockNumber
|
|
19902
|
+
});
|
|
19903
|
+
} catch {
|
|
19904
|
+
throw new ExecutionContextError(422, "A complete Uniswap v4 pool key cannot be proven from vault poolKey(); refusing partial metadata.");
|
|
19905
|
+
}
|
|
19906
|
+
poolKey = normalizeRawPoolKey(rawPoolKey);
|
|
19907
|
+
if (explicitPoolKey && !poolKeysEqual(explicitPoolKey, poolKey)) throw new ExecutionContextError(409, "The explicit Uniswap v4 poolKey does not match vault poolKey().");
|
|
19908
|
+
poolId = getPoolId(poolKey);
|
|
19909
|
+
const v4Config = getAmmConfig(params.subgraphStudioKey ?? "")[protocol];
|
|
19910
|
+
const poolManager = v4Config?.PoolManager?.[chain];
|
|
19911
|
+
const stateView = v4Config?.StateView?.[chain];
|
|
19912
|
+
if (!poolManager || !stateView || !isAddress(poolManager) || !isAddress(stateView)) throw new ExecutionContextError(422, "Uniswap v4 PoolManager or StateView is missing from SDK config.");
|
|
19913
|
+
poolManagerAddress = getAddress(poolManager);
|
|
19914
|
+
const slot0 = await publicClient.readContract({
|
|
19915
|
+
address: getAddress(stateView),
|
|
19916
|
+
abi: STATE_VIEW_ABI,
|
|
19917
|
+
functionName: "getSlot0",
|
|
19918
|
+
args: [poolId],
|
|
19919
|
+
blockNumber
|
|
19920
|
+
});
|
|
19921
|
+
if (slot0[0] === 0n) throw new ExecutionContextError(422, `Uniswap v4 pool ${poolId} is not initialized in the configured PoolManager.`);
|
|
19922
|
+
currentTick = Number(slot0[1]);
|
|
19923
|
+
tickSpacing = poolKey.tickSpacing;
|
|
19924
|
+
} else {
|
|
19925
|
+
poolAddress = getAddress(await publicClient.readContract({
|
|
19926
|
+
address: vaultAddress,
|
|
19927
|
+
abi: VAULT_EXECUTION_ABI,
|
|
19928
|
+
functionName: "pool",
|
|
19929
|
+
blockNumber
|
|
19930
|
+
}));
|
|
19931
|
+
factoryAddress = protocolFactory(protocol, chain, params.subgraphStudioKey ?? "");
|
|
19932
|
+
const poolAbi = family === "aerodrome-cl" ? AERODROME_POOL_ABI : family === "algebra-directional" ? ALGEBRA_DIRECTIONAL_POOL_ABI : family === "algebra-integral" ? ALGEBRA_INTEGRAL_POOL_ABI : family === "algebra" ? ALGEBRA_POOL_ABI : V3_POOL_ABI;
|
|
19933
|
+
const stateFunction = family.startsWith("algebra") ? "globalState" : "slot0";
|
|
19934
|
+
const [actualFactory, state, spacing] = await Promise.all([
|
|
19935
|
+
publicClient.readContract({
|
|
19936
|
+
address: poolAddress,
|
|
19937
|
+
abi: poolAbi,
|
|
19938
|
+
functionName: "factory",
|
|
19939
|
+
blockNumber
|
|
19940
|
+
}),
|
|
19941
|
+
publicClient.readContract({
|
|
19942
|
+
address: poolAddress,
|
|
19943
|
+
abi: poolAbi,
|
|
19944
|
+
functionName: stateFunction,
|
|
19945
|
+
blockNumber
|
|
19946
|
+
}),
|
|
19947
|
+
publicClient.readContract({
|
|
19948
|
+
address: poolAddress,
|
|
19949
|
+
abi: poolAbi,
|
|
19950
|
+
functionName: "tickSpacing",
|
|
19951
|
+
blockNumber
|
|
19952
|
+
})
|
|
19953
|
+
]);
|
|
19954
|
+
if (getAddress(actualFactory) !== factoryAddress) throw new ExecutionContextError(409, `Pool factory ${actualFactory} does not match SDK ${protocol} factory ${factoryAddress}.`);
|
|
19955
|
+
currentTick = Number(state[1]);
|
|
19956
|
+
tickSpacing = Number(spacing);
|
|
19957
|
+
}
|
|
19958
|
+
const lastExecution = await readLastExecution(publicClient, chainId, vaultAddress, blockNumber, epochTimestamp);
|
|
19959
|
+
const pinned = (detail) => ({
|
|
19960
|
+
source: "onchain-contract",
|
|
19961
|
+
consistency: "block-pinned",
|
|
19962
|
+
status: "verified",
|
|
19963
|
+
blockNumber: blockNumber.toString(),
|
|
19964
|
+
detail
|
|
19965
|
+
});
|
|
19966
|
+
return {
|
|
19967
|
+
success: true,
|
|
19968
|
+
status: 200,
|
|
19969
|
+
data: {
|
|
19970
|
+
chainId,
|
|
19971
|
+
blockNumber: blockNumber.toString(),
|
|
19972
|
+
epochTimestamp: epochTimestamp.toString(),
|
|
19973
|
+
vaultAddress,
|
|
19974
|
+
protocol,
|
|
19975
|
+
beaconName: details.beaconName,
|
|
19976
|
+
beaconAddress,
|
|
19977
|
+
poolFamily: family,
|
|
19978
|
+
poolAddress,
|
|
19979
|
+
poolId,
|
|
19980
|
+
factoryAddress,
|
|
19981
|
+
poolManagerAddress,
|
|
19982
|
+
poolKey,
|
|
19983
|
+
currentTick,
|
|
19984
|
+
tickSpacing,
|
|
19985
|
+
positions: normalizePositions(rawPositions),
|
|
19986
|
+
totalAmount0: rawTotals[0].toString(),
|
|
19987
|
+
totalAmount1: rawTotals[1].toString(),
|
|
19988
|
+
lastExecutionTimestamp: lastExecution.timestamp?.toString() ?? null,
|
|
19989
|
+
lastExecutionTimeSeconds: lastExecution.elapsed?.toString() ?? null,
|
|
19990
|
+
provenance: {
|
|
19991
|
+
identity: pinned("VaultRegistry getVaultDetails and SDK beacon mapping."),
|
|
19992
|
+
poolState: pinned(family === "uniswap-v4" ? "Vault poolKey and SDK StateView getSlot0." : "Vault pool, SDK factory validation, pool state, and tickSpacing."),
|
|
19993
|
+
positions: pinned("Vault getPositions."),
|
|
19994
|
+
totals: pinned("Vault getTotalAmounts; pending uncollected fees follow vault contract semantics."),
|
|
19995
|
+
lastExecution: lastExecution.provenance
|
|
19996
|
+
}
|
|
19997
|
+
}
|
|
19998
|
+
};
|
|
19999
|
+
} catch (error) {
|
|
20000
|
+
return {
|
|
20001
|
+
success: false,
|
|
20002
|
+
status: error instanceof ExecutionContextError ? error.status : 500,
|
|
20003
|
+
data: null,
|
|
20004
|
+
error: error instanceof Error ? error.message : "Failed to build vault execution context."
|
|
20005
|
+
};
|
|
20006
|
+
}
|
|
20007
|
+
}
|
|
20008
|
+
//#endregion
|
|
19649
20009
|
//#region src/base/VaultClient.ts
|
|
19650
20010
|
const VAULT_ABI = abis.QuickSwapUniv3MultiPositionLiquidityManager;
|
|
19651
20011
|
const REWARD_FUNCTIONS_ABI = [{
|
|
@@ -19767,6 +20127,17 @@ var VaultClient = class extends SubgraphClient {
|
|
|
19767
20127
|
this.subgraphVaultClient = new SubgraphVaultClient();
|
|
19768
20128
|
this.subgraphStudioKey = subgraphStudioKey || "";
|
|
19769
20129
|
}
|
|
20130
|
+
/**
|
|
20131
|
+
* Returns normalized strategy execution inputs from one explicitly pinned block.
|
|
20132
|
+
* `epochTimestamp` is a Unix timestamp in seconds and is never derived from wall-clock time.
|
|
20133
|
+
*/
|
|
20134
|
+
async getExecutionContext(params) {
|
|
20135
|
+
return getVaultExecutionContext({
|
|
20136
|
+
publicClient: this.publicClient,
|
|
20137
|
+
subgraphStudioKey: this.subgraphStudioKey,
|
|
20138
|
+
...params
|
|
20139
|
+
});
|
|
20140
|
+
}
|
|
19770
20141
|
normalizeProtocolValue(value) {
|
|
19771
20142
|
return value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
19772
20143
|
}
|
|
@@ -23743,6 +24114,6 @@ var FeeManagerClient = class extends SubgraphClient {
|
|
|
23743
24114
|
* See {@link SmartRewards} for detailed API documentation.
|
|
23744
24115
|
*/
|
|
23745
24116
|
//#endregion
|
|
23746
|
-
export { AERODROME_PROTOCOLS, ALGEBRA_INTEGRAL_PROTOCOLS, ALGEBRA_INTEGRAL_V_2_0_PROTOCOLS, ALGEBRA_PROTOCOLS, AMMType, API_URLS, AlgebgraHookBeacons, Chain, ChainId, DIRECTIONAL_ALGEBRA_PROTOCOLS, FEE_MANAGER_ABI, FeeManagerClient, MultiPositionManagers, POOLSHARK_PROTOCOLS, PoolClient, Protocol, QuickSwapQuoterV2, QuoterV2AlgebgraIntegral, QuoterV2AlgebgraIntegral21, QuoterV2Factory, QuoterV2Shadow, QuoterV2Thick, SHADOW_PROTOCOLS, SingleAssetDepositClient, SmartRewards, StakingClient, StakingProtocol, SteerClient, StrykePositionManagers, SubgraphClient, SubgraphVaultClient, TEST_UNISWAP_JIT_HOOK_BEACON, UNISWAP_V4_BEACON_NAMES, UNISWAP_V4_HOOK_BEACON_NAMES, UNISWAP_V4_NO_ORACLE_BEACON, UniswapHookBeacons, UniswapV3PoolABI, UniswapV3QuoterABI, UniswapV4Beacons, VAULT_FEES_ABI, VaultClient, abis, apechainAddresses, arbitrumAddresses, arbitrumgoerliAddresses, arthswapConfig, astarAddresses, astarzkevmAddresses, avalancheAddresses, bartiotestAddresses, baseAddresses, baseSwapConfig, basexConfig, beraAddresses, bittensorAddresses, bittensorUniV3Config, blastAddresses, bscAddresses, calculateLimitPrice, calculateSwapAmount, camelotConfig, celoAddresses, chainIdToName, chainNameToId, crustConfig, deprecatedBundlesURL, determineSwapDirection, equilibreConfig, erc1155Abi, erc20Abi, erc721Abi, estimateLpTokens, ethAddresses, evmosAddresses, fantomAddresses, fenixConfig, filecoinAddresses, flareAddresses, forgeConfig, fusionxConfig, getAmmConfig, getAmmConfigByChainId, getApiUrl, getBeaconNameByProtocol, getContractAddressByChainIdAndContractName, getExpectedParamType, getFactoryAddress, getInitCodeHash, getNFTManagerAddress, getNetworkByChainId, getPoolHelperByChainId, getPoolSlot0, getProtcolTypeByAmmType, getProtocolBySubgraph, getProtocolConfigByBeacon, getProtocolContractAddresses, getProtocolInfoByChainId, getProtocolInfoByName, getProtocolSubgraphURL, getProtocolTypeByBeacon, getProtocolsForChainId, getQuoterV2Address, getStabilityVaultsPeripheryAddress, getStabilityVaultsSubgraphUrl, getSubgraphUrlByChainId, getSupportedChainByChainId, getSupportedChainIds, getSupportedChains, getSwapRouterAddress, getTheGraphResolverUrl, getTickLensAddress, getUniswapV4BeaconSupportedChains, getVaultReserves, glyphConfig, goerliAddresses, hemiAddresses, henjinConfig, herculesConfig, horizaConfig, isAerodromeVault, isAlgebraDirectionProtocol, isAlgebraIntegral21QuoteParams, isAlgebraIntegralProtocol, isAlgebraIntegralV2Protocol, isAlgebraProtocol, isAlgebraProtocolBySubgraph, isAlgebraQuoteParams, isPoolSharkProtocol, isShadowProtocol, isShadowQuoteParams, isSingleAssetDepositSupported, isThickQuoteParams, isThickV2Protocol, isUniswapQuoteParams, isUniswapV4Beacon, isUniswapV4BeaconAvailableOnChain, isUniswapV4HookBeacon, isValidStakingProtocol, katanaAddresses, katanaConfig, kavaAddresses, kimConfig, kinetixConfig, lineaAddresses, linehubConfig, localhostAddresses, lynexConfig, maiaConfig, mantaAddresses, mantleAddresses, metaVaultConfig, metisAddresses, modeAddresses, moonbeamAddresses, mumbaiAddresses, nestVaultConfig, networks, normalizeProtocol, novaswapConfig, okxtestnetAddresses, optimismAddresses, optimismgoerliAddresses, pancakeSwapConfig, polygonAddresses, polyzkevmAddresses, poolsharkConfig, quickSwapAlgebraConfig, quickSwapConfig, quickSwapIntegralConfig, quickSwapUniv3Config, retroConfig, robinhoodAddresses, rootstockAddresses, sagaAddresses, scrollAddresses, seiAddresses, shadowConfig, shouldValidateUniswapV4VaultHook, simulateSwap, singleTokenDepositAbi, soneiumAddresses, sonicAddresses, spark32Config, sparkConfig, stabilityVaultsConfig, steerSubgraphConfig, supswapConfig, sushiConfig, swapmodeConfig, swapsicleConfig, taikoAddresses, telosAddresses, thenaConfig, thickConfig, thrusterConfig, thundercoreAddresses, uniAddresses, uniswapConfig, validateQuoteParams, validateSwapParams, xlayerAddresses, zetaAddresses, zircuitAddresses };
|
|
24117
|
+
export { AERODROME_PROTOCOLS, ALGEBRA_INTEGRAL_PROTOCOLS, ALGEBRA_INTEGRAL_V_2_0_PROTOCOLS, ALGEBRA_PROTOCOLS, AMMType, API_URLS, AlgebgraHookBeacons, Chain, ChainId, DIRECTIONAL_ALGEBRA_PROTOCOLS, FEE_MANAGER_ABI, FeeManagerClient, MultiPositionManagers, POOLSHARK_PROTOCOLS, PoolClient, Protocol, QuickSwapQuoterV2, QuoterV2AlgebgraIntegral, QuoterV2AlgebgraIntegral21, QuoterV2Factory, QuoterV2Shadow, QuoterV2Thick, SHADOW_PROTOCOLS, SingleAssetDepositClient, SmartRewards, StakingClient, StakingProtocol, SteerClient, StrykePositionManagers, SubgraphClient, SubgraphVaultClient, TEST_UNISWAP_JIT_HOOK_BEACON, UNISWAP_V4_BEACON_NAMES, UNISWAP_V4_HOOK_BEACON_NAMES, UNISWAP_V4_NO_ORACLE_BEACON, UniswapHookBeacons, UniswapV3PoolABI, UniswapV3QuoterABI, UniswapV4Beacons, VAULT_FEES_ABI, VaultClient, abis, apechainAddresses, arbitrumAddresses, arbitrumgoerliAddresses, arthswapConfig, astarAddresses, astarzkevmAddresses, avalancheAddresses, bartiotestAddresses, baseAddresses, baseSwapConfig, basexConfig, beraAddresses, bittensorAddresses, bittensorUniV3Config, blastAddresses, bscAddresses, calculateLimitPrice, calculateSwapAmount, camelotConfig, celoAddresses, chainIdToName, chainNameToId, crustConfig, deprecatedBundlesURL, determineSwapDirection, equilibreConfig, erc1155Abi, erc20Abi, erc721Abi, estimateLpTokens, ethAddresses, evmosAddresses, fantomAddresses, fenixConfig, filecoinAddresses, flareAddresses, forgeConfig, fusionxConfig, getAmmConfig, getAmmConfigByChainId, getApiUrl, getBeaconNameByProtocol, getContractAddressByChainIdAndContractName, getExpectedParamType, getFactoryAddress, getInitCodeHash, getNFTManagerAddress, getNetworkByChainId, getPoolHelperByChainId, getPoolSlot0, getProtcolTypeByAmmType, getProtocolBySubgraph, getProtocolConfigByBeacon, getProtocolContractAddresses, getProtocolInfoByChainId, getProtocolInfoByName, getProtocolSubgraphURL, getProtocolTypeByBeacon, getProtocolsForChainId, getQuoterV2Address, getStabilityVaultsPeripheryAddress, getStabilityVaultsSubgraphUrl, getSubgraphUrlByChainId, getSupportedChainByChainId, getSupportedChainIds, getSupportedChains, getSwapRouterAddress, getTheGraphResolverUrl, getTickLensAddress, getUniswapV4BeaconSupportedChains, getVaultExecutionContext, getVaultReserves, glyphConfig, goerliAddresses, hemiAddresses, henjinConfig, herculesConfig, horizaConfig, isAerodromeVault, isAlgebraDirectionProtocol, isAlgebraIntegral21QuoteParams, isAlgebraIntegralProtocol, isAlgebraIntegralV2Protocol, isAlgebraProtocol, isAlgebraProtocolBySubgraph, isAlgebraQuoteParams, isPoolSharkProtocol, isShadowProtocol, isShadowQuoteParams, isSingleAssetDepositSupported, isThickQuoteParams, isThickV2Protocol, isUniswapQuoteParams, isUniswapV4Beacon, isUniswapV4BeaconAvailableOnChain, isUniswapV4HookBeacon, isValidStakingProtocol, katanaAddresses, katanaConfig, kavaAddresses, kimConfig, kinetixConfig, lineaAddresses, linehubConfig, localhostAddresses, lynexConfig, maiaConfig, mantaAddresses, mantleAddresses, metaVaultConfig, metisAddresses, modeAddresses, moonbeamAddresses, mumbaiAddresses, nestVaultConfig, networks, normalizeProtocol, novaswapConfig, okxtestnetAddresses, optimismAddresses, optimismgoerliAddresses, pancakeSwapConfig, polygonAddresses, polyzkevmAddresses, poolsharkConfig, quickSwapAlgebraConfig, quickSwapConfig, quickSwapIntegralConfig, quickSwapUniv3Config, retroConfig, robinhoodAddresses, rootstockAddresses, sagaAddresses, scrollAddresses, seiAddresses, shadowConfig, shouldValidateUniswapV4VaultHook, simulateSwap, singleTokenDepositAbi, soneiumAddresses, sonicAddresses, spark32Config, sparkConfig, stabilityVaultsConfig, steerSubgraphConfig, supswapConfig, sushiConfig, swapmodeConfig, swapsicleConfig, taikoAddresses, telosAddresses, thenaConfig, thickConfig, thrusterConfig, thundercoreAddresses, uniAddresses, uniswapConfig, validateQuoteParams, validateSwapParams, xlayerAddresses, zetaAddresses, zircuitAddresses };
|
|
23747
24118
|
|
|
23748
24119
|
//# sourceMappingURL=index.browser.mjs.map
|