@steerprotocol/sdk 3.2.7 → 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 +375 -4
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.cjs +374 -2
- 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 +375 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -14450,7 +14450,7 @@ const novaswapConfig = () => ({
|
|
|
14450
14450
|
const pancakeSwapConfig = (theGraphApiKey) => ({
|
|
14451
14451
|
beaconContract: MultiPositionManagers.MultiPositionPancake,
|
|
14452
14452
|
subgraph: {
|
|
14453
|
-
[Chain.BSC]: getTheGraphResolverUrl("
|
|
14453
|
+
[Chain.BSC]: getTheGraphResolverUrl("ChmxqA9bX71cB2cQTRRULbWUBKoMRk7oh3JnpZShDQ2V", false, theGraphApiKey),
|
|
14454
14454
|
[Chain.Arbitrum]: getTheGraphResolverUrl("251MHFNN1rwjErXD2efWMpNS73SANZN8Ua192zw6iXve", false, theGraphApiKey)
|
|
14455
14455
|
},
|
|
14456
14456
|
factoryAddress: {
|
|
@@ -14946,7 +14946,7 @@ const kodiakConfig = () => ({
|
|
|
14946
14946
|
beaconContract: MultiPositionManagers.MultiPositionKodiak,
|
|
14947
14947
|
subgraph: {
|
|
14948
14948
|
[Chain.BeraChainBartio]: "https://api.goldsky.com/api/public/project_clpx84oel0al201r78jsl0r3i/subgraphs/kodiak-v3-berachain-bartio/latest/gn",
|
|
14949
|
-
[Chain.Bera]: "https://api.
|
|
14949
|
+
[Chain.Bera]: "https://api.subgraph.ormilabs.com/api/public/d7eed6cc-ad4a-4862-8017-89893c4095d3/subgraphs/kodiak-v3/latest/gn"
|
|
14950
14950
|
},
|
|
14951
14951
|
factoryAddress: {
|
|
14952
14952
|
[Chain.BeraChainBartio]: "0x217Cd80795EfCa5025d47023da5c03a24fA95356",
|
|
@@ -19647,6 +19647,366 @@ var VaultWithdrawClient = class {
|
|
|
19647
19647
|
}
|
|
19648
19648
|
};
|
|
19649
19649
|
//#endregion
|
|
19650
|
+
//#region src/base/vault/execution-context.ts
|
|
19651
|
+
const VAULT_REGISTRY_ABI = (0, viem.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)"]);
|
|
19652
|
+
const VAULT_EXECUTION_ABI = (0, viem.parseAbi)([
|
|
19653
|
+
"function pool() view returns (address)",
|
|
19654
|
+
"function getPositions() view returns (int24[] lowerTicks,int24[] upperTicks,uint16[] relativeWeights)",
|
|
19655
|
+
"function getTotalAmounts() view returns (uint256 total0,uint256 total1)"
|
|
19656
|
+
]);
|
|
19657
|
+
const V4_VAULT_ABI = (0, viem.parseAbi)([
|
|
19658
|
+
"function poolKey() view returns (address currency0,address currency1,uint24 fee,int24 tickSpacing,address hooks)",
|
|
19659
|
+
"function getPositions() view returns (int24[] lowerTicks,int24[] upperTicks,uint16[] relativeWeights)",
|
|
19660
|
+
"function getTotalAmounts() view returns (uint256 total0,uint256 total1)"
|
|
19661
|
+
]);
|
|
19662
|
+
const V3_POOL_ABI = (0, viem.parseAbi)([
|
|
19663
|
+
"function factory() view returns (address)",
|
|
19664
|
+
"function slot0() view returns (uint160 sqrtPriceX96,int24 tick,uint16 observationIndex,uint16 observationCardinality,uint16 observationCardinalityNext,uint8 feeProtocol,bool unlocked)",
|
|
19665
|
+
"function tickSpacing() view returns (int24)"
|
|
19666
|
+
]);
|
|
19667
|
+
const AERODROME_POOL_ABI = (0, viem.parseAbi)([
|
|
19668
|
+
"function factory() view returns (address)",
|
|
19669
|
+
"function slot0() view returns (uint160 sqrtPriceX96,int24 tick,uint16 observationIndex,uint16 observationCardinality,uint16 observationCardinalityNext,bool unlocked)",
|
|
19670
|
+
"function tickSpacing() view returns (int24)"
|
|
19671
|
+
]);
|
|
19672
|
+
const ALGEBRA_POOL_ABI = (0, viem.parseAbi)([
|
|
19673
|
+
"function factory() view returns (address)",
|
|
19674
|
+
"function globalState() view returns (uint160 price,int24 tick,int24 prevInitializedTick,uint16 fee,uint16 timepointIndex,uint8 communityFee,bool unlocked)",
|
|
19675
|
+
"function tickSpacing() view returns (int24)"
|
|
19676
|
+
]);
|
|
19677
|
+
const ALGEBRA_INTEGRAL_POOL_ABI = (0, viem.parseAbi)([
|
|
19678
|
+
"function factory() view returns (address)",
|
|
19679
|
+
"function globalState() view returns (uint160 price,int24 tick,uint16 lastFee,uint8 pluginConfig,uint16 communityFee,bool unlocked)",
|
|
19680
|
+
"function tickSpacing() view returns (int24)"
|
|
19681
|
+
]);
|
|
19682
|
+
const ALGEBRA_DIRECTIONAL_POOL_ABI = (0, viem.parseAbi)([
|
|
19683
|
+
"function factory() view returns (address)",
|
|
19684
|
+
"function globalState() view returns (uint160 price,int24 tick,uint16 feeZto,uint16 feeOtz,uint16 timepointIndex,uint8 communityFeeToken0,uint8 communityFeeToken1,bool unlocked)",
|
|
19685
|
+
"function tickSpacing() view returns (int24)"
|
|
19686
|
+
]);
|
|
19687
|
+
const STATE_VIEW_ABI = (0, viem.parseAbi)(["function getSlot0(bytes32 poolId) view returns (uint160 sqrtPriceX96,int24 tick,uint24 protocolFee,uint24 lpFee)"]);
|
|
19688
|
+
const V4_DYNAMIC_FEE_FLAG = 8388608;
|
|
19689
|
+
const V4_MAX_STATIC_FEE = 1e6;
|
|
19690
|
+
const V4_MAX_TICK_SPACING = 32767;
|
|
19691
|
+
const V4_ALL_HOOK_MASK = (1n << 14n) - 1n;
|
|
19692
|
+
const V4_BEFORE_SWAP_FLAG = 1n << 7n;
|
|
19693
|
+
const V4_AFTER_SWAP_FLAG = 1n << 6n;
|
|
19694
|
+
const V4_AFTER_ADD_LIQUIDITY_FLAG = 1n << 10n;
|
|
19695
|
+
const V4_AFTER_REMOVE_LIQUIDITY_FLAG = 1n << 8n;
|
|
19696
|
+
const V4_BEFORE_SWAP_RETURNS_DELTA_FLAG = 1n << 3n;
|
|
19697
|
+
const V4_AFTER_SWAP_RETURNS_DELTA_FLAG = 1n << 2n;
|
|
19698
|
+
const V4_AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1n << 1n;
|
|
19699
|
+
const V4_AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1n;
|
|
19700
|
+
var ExecutionContextError = class extends Error {
|
|
19701
|
+
constructor(status, message) {
|
|
19702
|
+
super(message);
|
|
19703
|
+
this.status = status;
|
|
19704
|
+
}
|
|
19705
|
+
};
|
|
19706
|
+
function resolvePoolFamily(protocol) {
|
|
19707
|
+
if (isPoolSharkProtocol(protocol)) throw new ExecutionContextError(422, "PoolShark vault execution context is not supported.");
|
|
19708
|
+
if (protocol === Protocol.UniswapV4) return "uniswap-v4";
|
|
19709
|
+
if (isAlgebraDirectionProtocol(protocol)) return "algebra-directional";
|
|
19710
|
+
if (isAlgebraIntegralProtocol(protocol)) return "algebra-integral";
|
|
19711
|
+
if (isAlgebraProtocol(protocol)) return "algebra";
|
|
19712
|
+
if (isAerodromeVault(protocol)) return "aerodrome-cl";
|
|
19713
|
+
return "uniswap-v3-compatible";
|
|
19714
|
+
}
|
|
19715
|
+
function assertPoolKey(poolKey, invalidStatus = 400) {
|
|
19716
|
+
if (!(0, viem.isAddress)(poolKey.currency0) || !(0, viem.isAddress)(poolKey.currency1) || !(0, viem.isAddress)(poolKey.hooks)) throw new ExecutionContextError(invalidStatus, "Uniswap v4 poolKey contains an invalid address.");
|
|
19717
|
+
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.");
|
|
19718
|
+
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.");
|
|
19719
|
+
const normalized = {
|
|
19720
|
+
currency0: (0, viem.getAddress)(poolKey.currency0),
|
|
19721
|
+
currency1: (0, viem.getAddress)(poolKey.currency1),
|
|
19722
|
+
fee: poolKey.fee,
|
|
19723
|
+
tickSpacing: poolKey.tickSpacing,
|
|
19724
|
+
hooks: (0, viem.getAddress)(poolKey.hooks)
|
|
19725
|
+
};
|
|
19726
|
+
if (BigInt(normalized.currency0) >= BigInt(normalized.currency1)) throw new ExecutionContextError(invalidStatus, "Uniswap v4 poolKey currencies are not canonically ordered.");
|
|
19727
|
+
const hooks = BigInt(normalized.hooks);
|
|
19728
|
+
const isDynamicFee = normalized.fee === V4_DYNAMIC_FEE_FLAG;
|
|
19729
|
+
const hasFlag = (flag) => (hooks & flag) !== 0n;
|
|
19730
|
+
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.");
|
|
19731
|
+
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.");
|
|
19732
|
+
return normalized;
|
|
19733
|
+
}
|
|
19734
|
+
function normalizeRawPoolKey(raw) {
|
|
19735
|
+
return assertPoolKey({
|
|
19736
|
+
currency0: raw[0],
|
|
19737
|
+
currency1: raw[1],
|
|
19738
|
+
fee: Number(raw[2]),
|
|
19739
|
+
tickSpacing: Number(raw[3]),
|
|
19740
|
+
hooks: raw[4]
|
|
19741
|
+
}, 422);
|
|
19742
|
+
}
|
|
19743
|
+
function poolKeysEqual(a, b) {
|
|
19744
|
+
return (0, viem.getAddress)(a.currency0) === (0, viem.getAddress)(b.currency0) && (0, viem.getAddress)(a.currency1) === (0, viem.getAddress)(b.currency1) && a.fee === b.fee && a.tickSpacing === b.tickSpacing && (0, viem.getAddress)(a.hooks) === (0, viem.getAddress)(b.hooks);
|
|
19745
|
+
}
|
|
19746
|
+
function getPoolId(poolKey) {
|
|
19747
|
+
return (0, viem.keccak256)((0, viem.encodeAbiParameters)([{
|
|
19748
|
+
type: "tuple",
|
|
19749
|
+
components: [
|
|
19750
|
+
{
|
|
19751
|
+
name: "currency0",
|
|
19752
|
+
type: "address"
|
|
19753
|
+
},
|
|
19754
|
+
{
|
|
19755
|
+
name: "currency1",
|
|
19756
|
+
type: "address"
|
|
19757
|
+
},
|
|
19758
|
+
{
|
|
19759
|
+
name: "fee",
|
|
19760
|
+
type: "uint24"
|
|
19761
|
+
},
|
|
19762
|
+
{
|
|
19763
|
+
name: "tickSpacing",
|
|
19764
|
+
type: "int24"
|
|
19765
|
+
},
|
|
19766
|
+
{
|
|
19767
|
+
name: "hooks",
|
|
19768
|
+
type: "address"
|
|
19769
|
+
}
|
|
19770
|
+
]
|
|
19771
|
+
}], [poolKey]));
|
|
19772
|
+
}
|
|
19773
|
+
function normalizePositions(raw) {
|
|
19774
|
+
const [lowerTicks, upperTicks, relativeWeights] = raw;
|
|
19775
|
+
if (lowerTicks.length !== upperTicks.length || lowerTicks.length !== relativeWeights.length) throw new ExecutionContextError(422, "Vault returned malformed position arrays.");
|
|
19776
|
+
return lowerTicks.map((lowerTick, index) => ({
|
|
19777
|
+
lowerTick: Number(lowerTick),
|
|
19778
|
+
upperTick: Number(upperTicks[index]),
|
|
19779
|
+
relativeWeight: Number(relativeWeights[index])
|
|
19780
|
+
}));
|
|
19781
|
+
}
|
|
19782
|
+
function protocolFactory(protocol, chain, subgraphStudioKey) {
|
|
19783
|
+
if (!chain) throw new ExecutionContextError(422, "Chain is absent from the SDK network registry.");
|
|
19784
|
+
const address = getAmmConfig(subgraphStudioKey)[protocol]?.factoryAddress?.[chain];
|
|
19785
|
+
if (!address || !(0, viem.isAddress)(address)) throw new ExecutionContextError(422, `${protocol} factory is missing from the SDK protocol registry on ${chain}.`);
|
|
19786
|
+
return (0, viem.getAddress)(address);
|
|
19787
|
+
}
|
|
19788
|
+
async function readLastExecution(publicClient, chainId, vaultAddress, blockNumber, epochTimestamp) {
|
|
19789
|
+
const pinnedBlock = await publicClient.getBlock({ blockNumber });
|
|
19790
|
+
const timestampUpperBound = pinnedBlock.timestamp < epochTimestamp ? pinnedBlock.timestamp : epochTimestamp;
|
|
19791
|
+
const subgraphUrl = getSubgraphUrlByChainId(chainId);
|
|
19792
|
+
if (!subgraphUrl) throw new ExecutionContextError(422, `Chain ${chainId} has no Steer subgraph configuration.`);
|
|
19793
|
+
const response = await fetch(subgraphUrl, {
|
|
19794
|
+
method: "POST",
|
|
19795
|
+
headers: { "Content-Type": "application/json" },
|
|
19796
|
+
body: JSON.stringify({ query: `{
|
|
19797
|
+
vaultSnapshots(
|
|
19798
|
+
where: { vaultAddress: "${vaultAddress.toLowerCase()}", timestamp_lte: "${timestampUpperBound}" }
|
|
19799
|
+
orderDirection: desc
|
|
19800
|
+
orderBy: timestamp
|
|
19801
|
+
first: 1
|
|
19802
|
+
) { timestamp }
|
|
19803
|
+
}` })
|
|
19804
|
+
});
|
|
19805
|
+
if (!response.ok) throw new ExecutionContextError(502, `Steer subgraph returned HTTP ${response.status}.`);
|
|
19806
|
+
const result = await response.json();
|
|
19807
|
+
if (result.errors?.length) throw new ExecutionContextError(502, `Steer subgraph error: ${result.errors[0].message}`);
|
|
19808
|
+
const rawTimestamp = result.data?.vaultSnapshots?.[0]?.timestamp;
|
|
19809
|
+
if (!rawTimestamp) return {
|
|
19810
|
+
timestamp: null,
|
|
19811
|
+
elapsed: null,
|
|
19812
|
+
provenance: {
|
|
19813
|
+
source: "steer-subgraph",
|
|
19814
|
+
consistency: "timestamp-bounded",
|
|
19815
|
+
status: "not-found",
|
|
19816
|
+
blockNumber: null,
|
|
19817
|
+
detail: `No indexed vaultSnapshot exists through timestamp ${timestampUpperBound}.`
|
|
19818
|
+
}
|
|
19819
|
+
};
|
|
19820
|
+
let timestamp;
|
|
19821
|
+
try {
|
|
19822
|
+
timestamp = BigInt(rawTimestamp);
|
|
19823
|
+
} catch {
|
|
19824
|
+
throw new ExecutionContextError(502, "Steer subgraph returned a malformed vaultSnapshot timestamp.");
|
|
19825
|
+
}
|
|
19826
|
+
if (timestamp > timestampUpperBound) throw new ExecutionContextError(502, "Steer subgraph returned a vaultSnapshot beyond the query bound.");
|
|
19827
|
+
return {
|
|
19828
|
+
timestamp,
|
|
19829
|
+
elapsed: epochTimestamp - timestamp,
|
|
19830
|
+
provenance: {
|
|
19831
|
+
source: "steer-subgraph",
|
|
19832
|
+
consistency: "timestamp-bounded",
|
|
19833
|
+
status: "indexed",
|
|
19834
|
+
blockNumber: null,
|
|
19835
|
+
detail: `Latest indexed vaultSnapshot bounded by epoch and pinned-block timestamp ${timestampUpperBound}; the entity does not expose its block number.`
|
|
19836
|
+
}
|
|
19837
|
+
};
|
|
19838
|
+
}
|
|
19839
|
+
/**
|
|
19840
|
+
* Builds the normalized read-only state consumed by strategy execution.
|
|
19841
|
+
* Every contract read is evaluated at `blockNumber`; `epochTimestamp` is the sole time reference.
|
|
19842
|
+
*/
|
|
19843
|
+
async function getVaultExecutionContext(params) {
|
|
19844
|
+
try {
|
|
19845
|
+
const { publicClient, blockNumber, epochTimestamp } = params;
|
|
19846
|
+
if (blockNumber < 0n) throw new ExecutionContextError(400, "blockNumber must be non-negative.");
|
|
19847
|
+
if (epochTimestamp < 0n) throw new ExecutionContextError(400, "epochTimestamp must be a non-negative Unix timestamp.");
|
|
19848
|
+
if (!(0, viem.isAddress)(params.vaultAddress)) throw new ExecutionContextError(400, "vaultAddress must be a valid EVM address.");
|
|
19849
|
+
const chainId = publicClient.chain?.id;
|
|
19850
|
+
if (!chainId) throw new ExecutionContextError(400, "publicClient must have an active chain.");
|
|
19851
|
+
const chain = chainIdToName(chainId);
|
|
19852
|
+
const network = getNetworkByChainId(chainId);
|
|
19853
|
+
const vaultRegistry = getContractAddressByChainIdAndContractName(chainId, "VaultRegistry");
|
|
19854
|
+
if (!chain || !network || !vaultRegistry || !(0, viem.isAddress)(vaultRegistry)) throw new ExecutionContextError(422, `Chain ${chainId} is missing required SDK deployment data.`);
|
|
19855
|
+
if (blockNumber < BigInt(network.VaultRegistry.startBlock ?? 0)) throw new ExecutionContextError(400, "blockNumber predates the SDK VaultRegistry deployment.");
|
|
19856
|
+
const vaultAddress = (0, viem.getAddress)(params.vaultAddress);
|
|
19857
|
+
const details = await publicClient.readContract({
|
|
19858
|
+
address: (0, viem.getAddress)(vaultRegistry),
|
|
19859
|
+
abi: VAULT_REGISTRY_ABI,
|
|
19860
|
+
functionName: "getVaultDetails",
|
|
19861
|
+
args: [vaultAddress],
|
|
19862
|
+
blockNumber
|
|
19863
|
+
});
|
|
19864
|
+
if (!details.vaultAddress || (0, viem.getAddress)(details.vaultAddress) !== vaultAddress) throw new ExecutionContextError(404, `${vaultAddress} is not registered in the chain VaultRegistry.`);
|
|
19865
|
+
const protocol = getProtocolTypeByBeacon(details.beaconName);
|
|
19866
|
+
if (!protocol) throw new ExecutionContextError(422, `Vault beacon "${details.beaconName}" is not mapped to a supported SDK protocol.`);
|
|
19867
|
+
const beaconAddress = (0, viem.getAddress)(await publicClient.readContract({
|
|
19868
|
+
address: (0, viem.getAddress)(vaultRegistry),
|
|
19869
|
+
abi: VAULT_REGISTRY_ABI,
|
|
19870
|
+
functionName: "beaconAddresses",
|
|
19871
|
+
args: [details.beaconName],
|
|
19872
|
+
blockNumber
|
|
19873
|
+
}));
|
|
19874
|
+
if (beaconAddress === "0x0000000000000000000000000000000000000000") throw new ExecutionContextError(422, `Vault beacon "${details.beaconName}" is not registered.`);
|
|
19875
|
+
const family = resolvePoolFamily(protocol);
|
|
19876
|
+
const explicitPoolKey = params.poolKey ? assertPoolKey(params.poolKey) : void 0;
|
|
19877
|
+
const [rawPositions, rawTotals] = await Promise.all([publicClient.readContract({
|
|
19878
|
+
address: vaultAddress,
|
|
19879
|
+
abi: family === "uniswap-v4" ? V4_VAULT_ABI : VAULT_EXECUTION_ABI,
|
|
19880
|
+
functionName: "getPositions",
|
|
19881
|
+
blockNumber
|
|
19882
|
+
}), publicClient.readContract({
|
|
19883
|
+
address: vaultAddress,
|
|
19884
|
+
abi: family === "uniswap-v4" ? V4_VAULT_ABI : VAULT_EXECUTION_ABI,
|
|
19885
|
+
functionName: "getTotalAmounts",
|
|
19886
|
+
blockNumber
|
|
19887
|
+
})]);
|
|
19888
|
+
let poolAddress = null;
|
|
19889
|
+
let poolId = null;
|
|
19890
|
+
let factoryAddress = null;
|
|
19891
|
+
let poolManagerAddress = null;
|
|
19892
|
+
let poolKey = null;
|
|
19893
|
+
let currentTick;
|
|
19894
|
+
let tickSpacing;
|
|
19895
|
+
if (family === "uniswap-v4") {
|
|
19896
|
+
let rawPoolKey;
|
|
19897
|
+
try {
|
|
19898
|
+
rawPoolKey = await publicClient.readContract({
|
|
19899
|
+
address: vaultAddress,
|
|
19900
|
+
abi: V4_VAULT_ABI,
|
|
19901
|
+
functionName: "poolKey",
|
|
19902
|
+
blockNumber
|
|
19903
|
+
});
|
|
19904
|
+
} catch {
|
|
19905
|
+
throw new ExecutionContextError(422, "A complete Uniswap v4 pool key cannot be proven from vault poolKey(); refusing partial metadata.");
|
|
19906
|
+
}
|
|
19907
|
+
poolKey = normalizeRawPoolKey(rawPoolKey);
|
|
19908
|
+
if (explicitPoolKey && !poolKeysEqual(explicitPoolKey, poolKey)) throw new ExecutionContextError(409, "The explicit Uniswap v4 poolKey does not match vault poolKey().");
|
|
19909
|
+
poolId = getPoolId(poolKey);
|
|
19910
|
+
const v4Config = getAmmConfig(params.subgraphStudioKey ?? "")[protocol];
|
|
19911
|
+
const poolManager = v4Config?.PoolManager?.[chain];
|
|
19912
|
+
const stateView = v4Config?.StateView?.[chain];
|
|
19913
|
+
if (!poolManager || !stateView || !(0, viem.isAddress)(poolManager) || !(0, viem.isAddress)(stateView)) throw new ExecutionContextError(422, "Uniswap v4 PoolManager or StateView is missing from SDK config.");
|
|
19914
|
+
poolManagerAddress = (0, viem.getAddress)(poolManager);
|
|
19915
|
+
const slot0 = await publicClient.readContract({
|
|
19916
|
+
address: (0, viem.getAddress)(stateView),
|
|
19917
|
+
abi: STATE_VIEW_ABI,
|
|
19918
|
+
functionName: "getSlot0",
|
|
19919
|
+
args: [poolId],
|
|
19920
|
+
blockNumber
|
|
19921
|
+
});
|
|
19922
|
+
if (slot0[0] === 0n) throw new ExecutionContextError(422, `Uniswap v4 pool ${poolId} is not initialized in the configured PoolManager.`);
|
|
19923
|
+
currentTick = Number(slot0[1]);
|
|
19924
|
+
tickSpacing = poolKey.tickSpacing;
|
|
19925
|
+
} else {
|
|
19926
|
+
poolAddress = (0, viem.getAddress)(await publicClient.readContract({
|
|
19927
|
+
address: vaultAddress,
|
|
19928
|
+
abi: VAULT_EXECUTION_ABI,
|
|
19929
|
+
functionName: "pool",
|
|
19930
|
+
blockNumber
|
|
19931
|
+
}));
|
|
19932
|
+
factoryAddress = protocolFactory(protocol, chain, params.subgraphStudioKey ?? "");
|
|
19933
|
+
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;
|
|
19934
|
+
const stateFunction = family.startsWith("algebra") ? "globalState" : "slot0";
|
|
19935
|
+
const [actualFactory, state, spacing] = await Promise.all([
|
|
19936
|
+
publicClient.readContract({
|
|
19937
|
+
address: poolAddress,
|
|
19938
|
+
abi: poolAbi,
|
|
19939
|
+
functionName: "factory",
|
|
19940
|
+
blockNumber
|
|
19941
|
+
}),
|
|
19942
|
+
publicClient.readContract({
|
|
19943
|
+
address: poolAddress,
|
|
19944
|
+
abi: poolAbi,
|
|
19945
|
+
functionName: stateFunction,
|
|
19946
|
+
blockNumber
|
|
19947
|
+
}),
|
|
19948
|
+
publicClient.readContract({
|
|
19949
|
+
address: poolAddress,
|
|
19950
|
+
abi: poolAbi,
|
|
19951
|
+
functionName: "tickSpacing",
|
|
19952
|
+
blockNumber
|
|
19953
|
+
})
|
|
19954
|
+
]);
|
|
19955
|
+
if ((0, viem.getAddress)(actualFactory) !== factoryAddress) throw new ExecutionContextError(409, `Pool factory ${actualFactory} does not match SDK ${protocol} factory ${factoryAddress}.`);
|
|
19956
|
+
currentTick = Number(state[1]);
|
|
19957
|
+
tickSpacing = Number(spacing);
|
|
19958
|
+
}
|
|
19959
|
+
const lastExecution = await readLastExecution(publicClient, chainId, vaultAddress, blockNumber, epochTimestamp);
|
|
19960
|
+
const pinned = (detail) => ({
|
|
19961
|
+
source: "onchain-contract",
|
|
19962
|
+
consistency: "block-pinned",
|
|
19963
|
+
status: "verified",
|
|
19964
|
+
blockNumber: blockNumber.toString(),
|
|
19965
|
+
detail
|
|
19966
|
+
});
|
|
19967
|
+
return {
|
|
19968
|
+
success: true,
|
|
19969
|
+
status: 200,
|
|
19970
|
+
data: {
|
|
19971
|
+
chainId,
|
|
19972
|
+
blockNumber: blockNumber.toString(),
|
|
19973
|
+
epochTimestamp: epochTimestamp.toString(),
|
|
19974
|
+
vaultAddress,
|
|
19975
|
+
protocol,
|
|
19976
|
+
beaconName: details.beaconName,
|
|
19977
|
+
beaconAddress,
|
|
19978
|
+
poolFamily: family,
|
|
19979
|
+
poolAddress,
|
|
19980
|
+
poolId,
|
|
19981
|
+
factoryAddress,
|
|
19982
|
+
poolManagerAddress,
|
|
19983
|
+
poolKey,
|
|
19984
|
+
currentTick,
|
|
19985
|
+
tickSpacing,
|
|
19986
|
+
positions: normalizePositions(rawPositions),
|
|
19987
|
+
totalAmount0: rawTotals[0].toString(),
|
|
19988
|
+
totalAmount1: rawTotals[1].toString(),
|
|
19989
|
+
lastExecutionTimestamp: lastExecution.timestamp?.toString() ?? null,
|
|
19990
|
+
lastExecutionTimeSeconds: lastExecution.elapsed?.toString() ?? null,
|
|
19991
|
+
provenance: {
|
|
19992
|
+
identity: pinned("VaultRegistry getVaultDetails and SDK beacon mapping."),
|
|
19993
|
+
poolState: pinned(family === "uniswap-v4" ? "Vault poolKey and SDK StateView getSlot0." : "Vault pool, SDK factory validation, pool state, and tickSpacing."),
|
|
19994
|
+
positions: pinned("Vault getPositions."),
|
|
19995
|
+
totals: pinned("Vault getTotalAmounts; pending uncollected fees follow vault contract semantics."),
|
|
19996
|
+
lastExecution: lastExecution.provenance
|
|
19997
|
+
}
|
|
19998
|
+
}
|
|
19999
|
+
};
|
|
20000
|
+
} catch (error) {
|
|
20001
|
+
return {
|
|
20002
|
+
success: false,
|
|
20003
|
+
status: error instanceof ExecutionContextError ? error.status : 500,
|
|
20004
|
+
data: null,
|
|
20005
|
+
error: error instanceof Error ? error.message : "Failed to build vault execution context."
|
|
20006
|
+
};
|
|
20007
|
+
}
|
|
20008
|
+
}
|
|
20009
|
+
//#endregion
|
|
19650
20010
|
//#region src/base/VaultClient.ts
|
|
19651
20011
|
const VAULT_ABI = abis.QuickSwapUniv3MultiPositionLiquidityManager;
|
|
19652
20012
|
const REWARD_FUNCTIONS_ABI = [{
|
|
@@ -19768,6 +20128,17 @@ var VaultClient = class extends SubgraphClient {
|
|
|
19768
20128
|
this.subgraphVaultClient = new SubgraphVaultClient();
|
|
19769
20129
|
this.subgraphStudioKey = subgraphStudioKey || "";
|
|
19770
20130
|
}
|
|
20131
|
+
/**
|
|
20132
|
+
* Returns normalized strategy execution inputs from one explicitly pinned block.
|
|
20133
|
+
* `epochTimestamp` is a Unix timestamp in seconds and is never derived from wall-clock time.
|
|
20134
|
+
*/
|
|
20135
|
+
async getExecutionContext(params) {
|
|
20136
|
+
return getVaultExecutionContext({
|
|
20137
|
+
publicClient: this.publicClient,
|
|
20138
|
+
subgraphStudioKey: this.subgraphStudioKey,
|
|
20139
|
+
...params
|
|
20140
|
+
});
|
|
20141
|
+
}
|
|
19771
20142
|
normalizeProtocolValue(value) {
|
|
19772
20143
|
return value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
19773
20144
|
}
|
|
@@ -23856,6 +24227,7 @@ exports.getSwapRouterAddress = getSwapRouterAddress;
|
|
|
23856
24227
|
exports.getTheGraphResolverUrl = getTheGraphResolverUrl;
|
|
23857
24228
|
exports.getTickLensAddress = getTickLensAddress;
|
|
23858
24229
|
exports.getUniswapV4BeaconSupportedChains = getUniswapV4BeaconSupportedChains;
|
|
24230
|
+
exports.getVaultExecutionContext = getVaultExecutionContext;
|
|
23859
24231
|
exports.getVaultReserves = getVaultReserves;
|
|
23860
24232
|
exports.glyphConfig = glyphConfig;
|
|
23861
24233
|
exports.goerliAddresses = goerliAddresses;
|