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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -101,6 +101,7 @@ interface VaultMetadata {
101
101
 
102
102
  This replaces address-only pages. Use `item.id` when passing a listed result to a vault getter.
103
103
  `decimals` and `createdAt` retain their indexed string representation. Null fields remain null;
104
+ Unavailable indexed pool/token address fields represented by empty strings become `null`; the native zero address remains unchanged.
104
105
  `poolKey` is omitted when the subgraph schema does not expose it. Only an explicit rejection of
105
106
  that optional field permits querying without it; other GraphQL and transport errors propagate.
106
107
 
@@ -206,6 +207,26 @@ snapshots[0]?.total.token0.formatted;
206
207
  snapshots[0]?.fees.net.token1.raw;
207
208
  ```
208
209
 
210
+ Opt in to independent vault failures with `allowFailure: true`:
211
+
212
+ ```ts
213
+ const results = await steer.getVaultSnapshots(ChainId.Base, vaultAddresses, {
214
+ blockNumber,
215
+ allowFailure: true,
216
+ });
217
+ for (const [index, result] of results.entries()) {
218
+ if (result.status === "success") consume(vaultAddresses[index], result.snapshot);
219
+ else report(vaultAddresses[index], result.error);
220
+ }
221
+ ```
222
+
223
+ This mode preserves an outcome for every input, including duplicates. Preflight and snapshot
224
+ reverts, decoding errors and vault validation failures stay with that vault. Registered readers
225
+ and overrides still run their original identity checks. Shared RPC/HTTP failures, malformed batch
226
+ responses and invalid shared contexts still reject the call. Provider feature rejection alone
227
+ selects the existing compatibility path. Ordinary bounded override pages still use two RPCs;
228
+ there is no batch splitting to locate a failed vault. Calls without this option remain atomic.
229
+
209
230
  The deployment-level `steer.getDeployment(chainId).getVaultSnapshots(addresses, options)` is
210
231
  identical. Results use the same `LiquidityVaultSnapshot` model as `vault.getSnapshot()`, in input
211
232
  order, including duplicates. This method resolves identity and reads accounting; `getVaults()`
@@ -1346,9 +1367,11 @@ for (const key of page.items) {
1346
1367
 
1347
1368
  A pool key contains `currency0`, `currency1`, `fee`, `tickSpacing`, and `hooks`. Currencies must be
1348
1369
  sorted numerically. Key validation includes V4 fee flags and hook permission relationships.
1349
- Pool IDs are `keccak256(abi.encode(key))`; the hash cannot be reversed. ID-only reads require the
1350
- configured indexer to recover metadata and verify the complete key against its ID. Missing keys
1351
- fail clearly; supplying a complete key avoids that dependency. Per-request HTTP overrides are
1370
+ Pool IDs are `keccak256(abi.encode(key))`; the hash cannot be reversed. ID-only reads use the
1371
+ configured data adapter to recover metadata and verify the complete key against its ID. Indexed
1372
+ adapters query their configured endpoint; RPC adapters use the onchain key index or initialization
1373
+ event recovery with an archival provider. Missing evidence fails clearly; a complete key avoids
1374
+ that dependency. Per-request HTTP overrides are
1352
1375
  accepted by `getPoolKey`, ID-based `getPool`, `quote`, and `listPools`, including
1353
1376
  ID-based family discovery through `steer.getPool`.
1354
1377
 
@@ -1727,7 +1750,8 @@ This initial family implementation uses original contract reads and the existing
1727
1750
  reader with its deployless/override/Multicall fallback. A pinned resolved snapshot takes
1728
1751
  16 RPCs normally or 19 through compatibility; latest adds one. Bulk reads use bounded
1729
1752
  compatibility orchestration, not the optimized two-RPC V3/Algebra vault readers. BNB AMM
1730
- listing/ID lookup is explicitly unavailable without a qualified indexer; full-key reads work.
1753
+ listing is unavailable without a qualified indexer. ID-only and full-key reads work through
1754
+ the configured onchain data adapter; missing historical key-index entries need archival RPC.
1731
1755
  Steer indexed V4 beacon candidates are available, but token metadata is incomplete and
1732
1756
  V4 token search is not qualified. Direct address-based reads are independently verified.
1733
1757
  See [deployment qualification and budgets](src/vault/adapters/uniswap-v4/qualification.md).
@@ -1851,3 +1875,164 @@ standalone claim, signing or broadcasting occurs. Empty vaults require explicit
1851
1875
  Aerodrome's qualified helper accepts one raw initial share. One-sided vaults quote only the held asset.
1852
1876
 
1853
1877
  See [vault qualification, accounting and budgets](src/vault/adapters/aerodrome/qualification.md).
1878
+
1879
+
1880
+ ### Robinhood standalone Uniswap V4 snapshots
1881
+
1882
+ `MultiPositionUniswapV4NoOracle` uses the same standalone V4 snapshot reader as the qualified
1883
+ BNB Reserve deployment. The oracle difference belongs to tend validation, not snapshot accounting.
1884
+ Use `steer.getVaultSnapshots(ChainId.Robinhood, addresses, { blockNumber })` or a resolved vault's
1885
+ `getSnapshot()`. Exact proxy/beacon/implementation/helper identities, stored registry, pool routing
1886
+ and fees are checked at the selected block. Full pool keys are read from vault contracts; indexed
1887
+ pool listing remains unavailable; ID-only lookup uses the shared onchain key resolver. See the [deployment qualification](src/vault/adapters/uniswap-v4/qualification.md#robinhood-shared-snapshot-deployment).
1888
+
1889
+ V4 wallet discovery uses `listUserVaults()` with indexed candidates and onchain share balances,
1890
+ including shares acquired by transfer. Transfer-aware subgraph holdings are not required.
1891
+ Live tests cover BSC Reserve and Robinhood NoOracle holders for both ERC20 and native pairs,
1892
+ including pagination and compatibility reads. Follow every `nextCursor`, even when `items`
1893
+ is empty. Incomplete indexed token metadata still limits token-filtered discovery.
1894
+
1895
+
1896
+ ### V4 pool-ID lookup without a pool indexer
1897
+
1898
+ `amm.getPool({ poolId })`, `amm.getPoolKey(poolId)` and client/bulk ID getters share the
1899
+ family data adapter's key resolution. The RPC adapter is reusable on any configured canonical
1900
+ Uniswap V4 deployment. It verifies the configured PositionManager and the full key hash.
1901
+ Pools absent from that contract's key index are recovered from their original initialization
1902
+ event using historical RPC state. Recovery searches recent history first; older pools require
1903
+ an archival provider. Missing history
1904
+ is an error, not a fabricated key. Pool browsing remains separate and requires an indexed adapter.
1905
+ Base retains its existing indexed adapter by default. BNB and Robinhood use RPC key resolution.
1906
+
1907
+
1908
+ ### BSC PancakeSwap V3 vault snapshots
1909
+
1910
+ `MultiPositionPancake` vaults on BSC use the shared `UniswapV3Vault` implementation and
1911
+ existing fixed-fee reader. Resolve by address with `getLiquidityVault(ChainId.BSC, address)`
1912
+ or use `getVaultSnapshots`. Pool factory, registry, beacon, implementation and proxy runtime
1913
+ are checked at the operation block. Only the exact qualified deployment is supported.
1914
+
1915
+ This implementation reserves accrued Steer and strategist fees separately and takes a fixed
1916
+ 30% cut of earned fees. Its fee cut is rounded once over all ranges, matching original
1917
+ `poke()` followed by `getTotalAmounts()` in a single read-only simulation. Other V3 deployments
1918
+ keep their existing rounding policy. BSC bulk vault reads retain bounded compatibility
1919
+ orchestration; this addition does not introduce a two-RPC bulk optimization.
1920
+
1921
+ See [Pancake vault qualification](src/vault/adapters/uniswap-v3/pancake-qualification.md) for
1922
+ identities, funded fixtures, retained-response regressions and live test coverage. Separate funded user-flow qualification now covers deposit quotes/preparation, partial/full
1923
+ withdrawals, user positions and indexed wallet balance scanning.
1924
+
1925
+
1926
+ ### Camelot legacy vault snapshots on Arbitrum
1927
+
1928
+ `MultiPositionCamelot` vaults on Arbitrum use the shared `AlgebraLegacyVault` implementation.
1929
+ Resolve with `getLiquidityVault(ChainId.Arbitrum, address)` or call `getVaultSnapshots`.
1930
+ The exact beacon/implementation, proxy code, stored registry, pool factory/deployer and
1931
+ currencies are checked at the snapshot block. This covers the qualified legacy directional
1932
+ Algebra deployment; Camelot Integral and other beacon types are separate registrations.
1933
+
1934
+ A directional override reader preserves both pool swap fees and community shares while
1935
+ reusing existing position/fee accounting. Vault fees are fixed at 15% with aggregate rounding.
1936
+ Normal resolved snapshots take two RPC calls. Unsupported overrides use original-contract
1937
+ compatibility reads and the AMM's existing pool-reader fallbacks. Live checks cover funded
1938
+ three-range and five-range vaults. Bulk snapshots use bounded existing orchestration.
1939
+ See [Camelot qualification](src/vault/adapters/algebra-legacy/camelot-qualification.md).
1940
+ Funded simulations now also verify deposit quotes/preparation, partial/full withdrawals, user
1941
+ positions and wallet discovery. Arbitrum deposit accounting uses the verified Multicall3 deployment.
1942
+
1943
+
1944
+ ### Blackhole CL on Avalanche
1945
+
1946
+ Select pools with `{ protocol: AmmProtocol.Blackhole, version: BlackholeVersion.CL }`.
1947
+ Blackhole uses Integral-compatible pool reads with custom-deployer identity preserved.
1948
+ Pool and vault searches support token addresses, symbols, names and pagination.
1949
+
1950
+ The exact qualified `MultiPositionBlackHole` deployment resolves to `BlackholeVault` through
1951
+ `getLiquidityVault(ChainId.Avalanche, address)`. Snapshots include separate immutable `rewardAssets`
1952
+ and position-level `nftTokensOwed` diagnostics excluded from LP entitlement. Wallet discovery uses
1953
+ indexed vault candidates plus on-chain share balances. User positions and prepared ERC20 deposit
1954
+ and withdrawal flows have passed live simulations, including partial/full withdrawal rewards.
1955
+ AVAX inputs use an explicit WAVAX wrap before deposit. Native exits use a separate unwrap after
1956
+ withdrawal confirmation; standalone reward claims are not exposed. Vault reads use bounded
1957
+ compatibility calls, without a two-RPC guarantee.
1958
+
1959
+ See [qualification](src/vault/adapters/blackhole/qualification.md) for exact identities and evidence.
1960
+ Run `npm run test:integration:blackhole` with `AVALANCHE_RPC_URL` for the paced historical live suite.
1961
+
1962
+
1963
+ #### Blackhole AVAX deposit and exit
1964
+
1965
+ Use the zero address as the native AVAX input when the vault holds WAVAX:
1966
+
1967
+ ```ts
1968
+ const plan = await vault.prepareDeposit({
1969
+ account,
1970
+ receiver,
1971
+ assets: [
1972
+ { asset: zeroAddress, amount: avaxMaximum },
1973
+ { asset: otherToken, amount: otherMaximum },
1974
+ ],
1975
+ slippageBps: 50,
1976
+ });
1977
+ ```
1978
+
1979
+ The ordered unsigned transactions wrap AVAX, approve tokens if necessary, then deposit.
1980
+ Submit them in order from `account`. Only the wrap transaction carries AVAX. Unused input
1981
+ remains WAVAX, as shown in the preview's underlying-token `unusedAmounts`. Other assets are
1982
+ not swapped. Avoid providing both AVAX and WAVAX in the same request.
1983
+
1984
+ Withdraw normally with `prepareWithdraw`. After confirmation, the WAVAX recipient can call
1985
+ `prepareUnwrapNative({ account: recipient, amount: actualWavaxReceived })` on `BlackholeVault`.
1986
+ This prepares a separate WAVAX withdrawal transaction that pays AVAX to `recipient` after
1987
+ checking its balance. Use actual received amounts rather than the earlier withdrawal preview.
1988
+ Both stages are separate wallet operations; preparation sends nothing.
1989
+
1990
+
1991
+ ### Pancake V3 and Camelot user-flow verification
1992
+
1993
+ Run `npm run test:integration:vault-flows` with BSC and Arbitrum archival RPC URLs. This suite
1994
+ repeats actual-contract deposits/withdrawals and balance-based discovery at retained pinned blocks.
1995
+ It uses pinned public indexer responses and paces live RPC calls by 1.5 seconds. No Graph API
1996
+ credentials or Base RPC are needed for this isolated runner. Full historical state and temporary
1997
+ EOA code overrides must be supported. Native BNB/ETH wrapping helpers remain separate work.
1998
+ ### Partial vault loading and pool reads
1999
+
2000
+ Strict calls still reject the whole batch. Opt in to ordered, immutable per-input outcomes:
2001
+
2002
+ ```ts
2003
+ const vaults = await steer.getVaults(chainId, addresses, {
2004
+ blockNumber,
2005
+ metadata, // optional complete indexed VaultMetadata records
2006
+ allowFailure: true,
2007
+ });
2008
+ for (const result of vaults) {
2009
+ if (result.status === "success") console.log(result.vault.address);
2010
+ else console.log(result.error);
2011
+ }
2012
+
2013
+ const pools = await amm.getPools(references, { blockNumber, allowFailure: true });
2014
+ for (const result of pools) {
2015
+ if (result.status === "success") console.log(result.pool);
2016
+ else console.log(result.error);
2017
+ }
2018
+ ```
2019
+
2020
+ These methods preserve input order and duplicates. Unsupported implementations, absent V4 keys,
2021
+ and contract member failures do not discard successful members or trigger recursive splitting.
2022
+ Native readers retain their page sizes and RPC counts. Explicitly unsupported provider execution
2023
+ uses the existing bounded compatibility path. Shared RPC failures, invalid request context,
2024
+ malformed shared RPC responses, and shared vault metadata request failures still reject the call.
2025
+ `SteerClient.getPools(request)` discovery remains strict; partial pool reads use the selected
2026
+ AMM's `getPools(references, options)`.
2027
+
2028
+
2029
+ V4 partial ID reads isolate `V4PoolKeyNotFoundError` for a verified absent indexed key or
2030
+ uninitialized onchain pool. Shared indexer, JSON/schema, RPC, and unexpected key-adapter errors
2031
+ reject the request, including through registered adapter overrides. Custom V4 data adapters
2032
+ can throw `V4PoolKeyNotFoundError` to report an absent key explicitly.
2033
+
2034
+ Blackhole reward assets expose `unattributedReservedFees`: stored fee reserves not attributed
2035
+ to the current fee identifiers after a fee-policy replacement. These remain part of
2036
+ `reservedFees`, fully excluded from LP holdings. Current-recipient unpaid fees plus
2037
+ `unattributedReservedFees` reconcile to the stored reserve; current unclaimed fee cuts still
2038
+ reconcile exactly to the current policy.