@augustdigital/sdk 9.2.2 → 9.4.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.
Files changed (58) hide show
  1. package/lib/adapters/evm/getters.js +40 -0
  2. package/lib/adapters/evm/index.d.ts +106 -2
  3. package/lib/adapters/evm/index.js +125 -0
  4. package/lib/adapters/solana/index.d.ts +12 -5
  5. package/lib/adapters/solana/index.js +12 -4
  6. package/lib/adapters/solana/pricing.d.ts +173 -0
  7. package/lib/adapters/solana/pricing.js +223 -0
  8. package/lib/adapters/solana/types.d.ts +45 -0
  9. package/lib/adapters/solana/vault.actions.d.ts +33 -8
  10. package/lib/adapters/solana/vault.actions.js +185 -28
  11. package/lib/adapters/stellar/actions.d.ts +2 -2
  12. package/lib/adapters/stellar/actions.js +2 -2
  13. package/lib/adapters/stellar/getters.d.ts +1 -1
  14. package/lib/adapters/stellar/getters.js +2 -2
  15. package/lib/adapters/stellar/index.d.ts +1 -1
  16. package/lib/adapters/stellar/index.js +1 -1
  17. package/lib/adapters/stellar/types.d.ts +1 -2
  18. package/lib/core/analytics/method-taxonomy.js +7 -0
  19. package/lib/core/analytics/version.d.ts +1 -1
  20. package/lib/core/analytics/version.js +1 -1
  21. package/lib/core/base.class.d.ts +2 -2
  22. package/lib/core/base.class.js +2 -2
  23. package/lib/core/constants/core.d.ts +17 -3
  24. package/lib/core/constants/core.js +17 -3
  25. package/lib/core/constants/vaults.js +4 -0
  26. package/lib/core/fetcher.js +112 -45
  27. package/lib/core/helpers/concurrency.d.ts +37 -0
  28. package/lib/core/helpers/concurrency.js +58 -0
  29. package/lib/core/helpers/core.d.ts +9 -0
  30. package/lib/core/helpers/core.js +47 -0
  31. package/lib/core/helpers/vaults.d.ts +1 -1
  32. package/lib/core/helpers/vaults.js +1 -1
  33. package/lib/core/helpers/web3.js +14 -1
  34. package/lib/core/logger/curator-alert.d.ts +2 -2
  35. package/lib/core/logger/curator-alert.js +2 -2
  36. package/lib/evm/methods/crossChainVaultRegistry.d.ts +2 -3
  37. package/lib/evm/methods/crossChainVaultRegistry.js +2 -3
  38. package/lib/evm/types/crossChain.d.ts +1 -1
  39. package/lib/main.d.ts +7 -5
  40. package/lib/main.js +7 -5
  41. package/lib/modules/vaults/getters.d.ts +10 -3
  42. package/lib/modules/vaults/getters.js +220 -72
  43. package/lib/modules/vaults/main.d.ts +4 -4
  44. package/lib/modules/vaults/main.js +7 -4
  45. package/lib/modules/vaults/read.actions.d.ts +181 -0
  46. package/lib/modules/vaults/read.actions.js +331 -36
  47. package/lib/modules/vaults/types.d.ts +13 -0
  48. package/lib/modules/vaults/utils.js +5 -1
  49. package/lib/modules/vaults/write.actions.d.ts +74 -6
  50. package/lib/modules/vaults/write.actions.js +133 -23
  51. package/lib/sdk.d.ts +9827 -9332
  52. package/lib/services/subgraph/schema.d.ts +1 -1
  53. package/lib/services/subgraph/schema.js +1 -1
  54. package/lib/services/untangled/utils.d.ts +30 -1
  55. package/lib/services/untangled/utils.js +87 -13
  56. package/lib/types/pools.d.ts +1 -1
  57. package/lib/types/vaults.d.ts +14 -4
  58. package/package.json +1 -1
@@ -28,7 +28,7 @@ export declare function isSubgraphSchemaFieldError(errors: {
28
28
  * `august-citrea-earn-ctusd`). A wrong guess made every subgraph read query
29
29
  * non-existent field names, so the subgraph returned GraphQL errors with no
30
30
  * `data` and the SDK silently returned empty sets — emptying the Pending
31
- * Withdrawals and History tabs for that vault (AUGUST-6568).
31
+ * Withdrawals and History tabs for that vault.
32
32
  *
33
33
  * Because the schema is immutable for a fixed subgraph deployment, the result is
34
34
  * cached per URL ({@link SCHEMA_TTL_MS}); across a page's positions/history/
@@ -28,7 +28,7 @@ function isSubgraphSchemaFieldError(errors) {
28
28
  * `august-citrea-earn-ctusd`). A wrong guess made every subgraph read query
29
29
  * non-existent field names, so the subgraph returned GraphQL errors with no
30
30
  * `data` and the SDK silently returned empty sets — emptying the Pending
31
- * Withdrawals and History tabs for that vault (AUGUST-6568).
31
+ * Withdrawals and History tabs for that vault.
32
32
  *
33
33
  * Because the schema is immutable for a fixed subgraph deployment, the result is
34
34
  * cached per URL ({@link SCHEMA_TTL_MS}); across a page's positions/history/
@@ -1,3 +1,4 @@
1
+ import type { IDebankTokenExposure } from '../../types';
1
2
  import type { IDebankNormalizedResponse } from '../debank/utils';
2
3
  import type { IUntangledVaultExposure } from './types';
3
4
  /** Display metadata for an Untangled protocol slug. */
@@ -16,6 +17,31 @@ export interface IUntangledProtocolMetadata {
16
17
  * instead of silently vanishing from the breakdown.
17
18
  */
18
19
  export declare const UNTANGLED_PROTOCOL_REGISTRY: Record<string, IUntangledProtocolMetadata>;
20
+ /**
21
+ * The vault's asset composition, as vault-level token exposure.
22
+ *
23
+ * This is the one asset breakdown Untangled actually publishes, and it is
24
+ * authoritative: `byAsset` decomposes the same `tvlUsd` that `byProtocol` does.
25
+ * It is returned separately from {@link transformUntangledToDebank} because it
26
+ * cannot be folded into that structure — attributing an asset to a position
27
+ * would require a join the API does not provide, and adding these on top of the
28
+ * synthesized position tokens would double-count the vault.
29
+ *
30
+ * Negative rows are kept. A vault that has moved capital into another Upshift
31
+ * vault is reported holding the receipt token and owing the asset it spent —
32
+ * earnXLM carries `earnUSDC +$1,170,913` against `USDC -$1,170,271` — and those
33
+ * only sum back to `tvlUsd` together. Dropping the liability would overstate the
34
+ * vault's assets by the full size of the position.
35
+ *
36
+ * @param exposure - A resolved Untangled report, or `null`/`undefined` when the
37
+ * fetch failed.
38
+ * @returns One row per asset clearing `filterOutBySize` in absolute terms,
39
+ * largest first, with `amount` denominated in USD. Empty when `exposure` is
40
+ * absent. `id` carries the asset symbol rather than an address — Untangled
41
+ * reports assets by ticker and publishes no contract address for them — so it
42
+ * is safe as a display key and must not be read as an on-chain address.
43
+ */
44
+ export declare function untangledAssetExposure(exposure: IUntangledVaultExposure | null | undefined): IDebankTokenExposure[];
19
45
  /**
20
46
  * Transform an Untangled vault exposure report into the DeBank-normalized shape
21
47
  * that `parseVaultLevelDebank` and `parseLoanLevelDebank` consume.
@@ -29,7 +55,10 @@ export declare const UNTANGLED_PROTOCOL_REGISTRY: Record<string, IUntangledProto
29
55
  * Mapping:
30
56
  * - Each `byProtocol` entry becomes one position with a single supplying token,
31
57
  * valued in USD (`price: 1`), on the chain from
32
- * {@link UNTANGLED_PROTOCOL_REGISTRY}.
58
+ * {@link UNTANGLED_PROTOCOL_REGISTRY}. The token is labelled with the vault's
59
+ * asset only when one asset covers essentially all of it (see
60
+ * {@link vaultAssetSymbol}); otherwise it carries the value with no symbol,
61
+ * and {@link untangledAssetExposure} supplies the composition separately.
33
62
  * - `stellar-wallet` becomes a wallet token, because custody cash is undeployed
34
63
  * capital rather than protocol exposure.
35
64
  * - `upshift` is split: the vault's own idle buffer (the `idle` location) joins
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UNTANGLED_PROTOCOL_REGISTRY = void 0;
4
+ exports.untangledAssetExposure = untangledAssetExposure;
4
5
  exports.transformUntangledToDebank = transformUntangledToDebank;
6
+ const core_1 = require("../../core/helpers/core");
5
7
  /**
6
8
  * Display metadata for the protocol slugs Untangled reports today.
7
9
  *
@@ -42,6 +44,17 @@ const ASSET_MATCH_TOLERANCE = 0.001;
42
44
  * values and orders of magnitude below any holding worth naming.
43
45
  */
44
46
  const MIN_POSITION_USD = 0.01;
47
+ /**
48
+ * Share of `tvlUsd` the largest `byAsset` entry must cover before a synthesized
49
+ * position may be labelled with it.
50
+ *
51
+ * `byProtocol` and `byAsset` are two orthogonal decompositions of the same TVL,
52
+ * and Untangled publishes no join between them, so which venue holds which asset
53
+ * is genuinely unknown. Tagging every position with the largest asset is only
54
+ * honest when there is effectively nothing else in the vault; below that, the
55
+ * label would assert a holding the report does not support.
56
+ */
57
+ const SINGLE_ASSET_SHARE = 0.99;
45
58
  /**
46
59
  * USD the vault holds in its own contract, summed from the `idle` locations.
47
60
  *
@@ -107,14 +120,19 @@ const SYNTHETIC_TOKEN_DECIMALS = 7;
107
120
  *
108
121
  * `parseVaultLevelDebank` computes USD as `price * amount`, so a value already
109
122
  * denominated in dollars is expressed as `price: 1, amount: <usd>`.
123
+ *
124
+ * @param symbol - The asset this slice holds, or `null` when the report cannot
125
+ * say. A null symbol still produces a token — the value has to reach
126
+ * `netValue` and the protocol totals either way — but carries no asset label,
127
+ * so consumers render the slice's value without naming an asset.
110
128
  */
111
129
  function toDebankToken(symbol, chain, valueUsd, exposureType, protocolId) {
112
130
  return {
113
- id: symbol,
131
+ id: symbol ?? '',
114
132
  chain,
115
- name: symbol,
116
- symbol,
117
- optimized_symbol: symbol,
133
+ name: symbol ?? '',
134
+ symbol: symbol ?? '',
135
+ optimized_symbol: symbol ?? '',
118
136
  decimals: SYNTHETIC_TOKEN_DECIMALS,
119
137
  logo_url: '',
120
138
  amount: valueUsd,
@@ -124,18 +142,71 @@ function toDebankToken(symbol, chain, valueUsd, exposureType, protocolId) {
124
142
  };
125
143
  }
126
144
  /**
127
- * The asset holding most of the vault's value.
145
+ * The symbol every synthesized position may be tagged with, or `null` when the
146
+ * report cannot support tagging them at all.
128
147
  *
129
- * Untangled splits assets vault-wide rather than per protocol, so every
130
- * synthesized position is tagged with this one symbol. For the Gami vaults it is
131
- * an exact description (earnUSDC is ~100% USDC); an exact per-protocol split
132
- * needs `byProtocol[].assets[]` from Untangled.
148
+ * Untangled splits assets vault-wide rather than per protocol, so the only
149
+ * defensible label is the dominant asset, and only while it covers essentially
150
+ * the whole vault ({@link SINGLE_ASSET_SHARE}). Gami earnXLM qualifies (99.98%
151
+ * XLM); earnUSDC does not (84.18% USDC, 15.82% deJTRSY), and labelling its
152
+ * positions USDC claimed the whole $25.3M was USDC while $4.0M of deJTRSY went
153
+ * unmentioned. Callers that get `null` emit no asset label and let
154
+ * {@link untangledAssetExposure} carry the composition instead.
155
+ *
156
+ * An exact per-protocol split needs `byProtocol[].assets[]` from Untangled.
133
157
  */
134
- function dominantAssetSymbol(exposure) {
158
+ function vaultAssetSymbol(exposure) {
135
159
  const dominant = (exposure.byAsset || []).reduce((best, asset) => !best || Number(asset?.valueUsd || 0) > Number(best.valueUsd || 0)
136
160
  ? asset
137
161
  : best, null);
138
- return dominant?.symbol || 'UNKNOWN';
162
+ if (!dominant?.symbol)
163
+ return null;
164
+ const tvlUsd = Number(exposure.tvlUsd) || 0;
165
+ if (tvlUsd <= 0)
166
+ return null;
167
+ const share = (Number(dominant.valueUsd) || 0) / tvlUsd;
168
+ return share >= SINGLE_ASSET_SHARE ? dominant.symbol : null;
169
+ }
170
+ /**
171
+ * The vault's asset composition, as vault-level token exposure.
172
+ *
173
+ * This is the one asset breakdown Untangled actually publishes, and it is
174
+ * authoritative: `byAsset` decomposes the same `tvlUsd` that `byProtocol` does.
175
+ * It is returned separately from {@link transformUntangledToDebank} because it
176
+ * cannot be folded into that structure — attributing an asset to a position
177
+ * would require a join the API does not provide, and adding these on top of the
178
+ * synthesized position tokens would double-count the vault.
179
+ *
180
+ * Negative rows are kept. A vault that has moved capital into another Upshift
181
+ * vault is reported holding the receipt token and owing the asset it spent —
182
+ * earnXLM carries `earnUSDC +$1,170,913` against `USDC -$1,170,271` — and those
183
+ * only sum back to `tvlUsd` together. Dropping the liability would overstate the
184
+ * vault's assets by the full size of the position.
185
+ *
186
+ * @param exposure - A resolved Untangled report, or `null`/`undefined` when the
187
+ * fetch failed.
188
+ * @returns One row per asset clearing `filterOutBySize` in absolute terms,
189
+ * largest first, with `amount` denominated in USD. Empty when `exposure` is
190
+ * absent. `id` carries the asset symbol rather than an address — Untangled
191
+ * reports assets by ticker and publishes no contract address for them — so it
192
+ * is safe as a display key and must not be read as an on-chain address.
193
+ */
194
+ function untangledAssetExposure(exposure) {
195
+ if (!exposure)
196
+ return [];
197
+ const chain = exposure.vault?.chain || DEFAULT_CHAIN;
198
+ return (exposure.byAsset || [])
199
+ .filter((asset) => asset?.symbol && (0, core_1.filterOutBySize)(Math.abs(Number(asset.valueUsd) || 0)))
200
+ .map((asset) => ({
201
+ amount: Number(asset.valueUsd) || 0,
202
+ chain,
203
+ decimals: SYNTHETIC_TOKEN_DECIMALS,
204
+ id: asset.symbol,
205
+ logoUrl: '',
206
+ name: asset.symbol,
207
+ symbol: asset.symbol,
208
+ }))
209
+ .sort((a, b) => b.amount - a.amount);
139
210
  }
140
211
  /**
141
212
  * Transform an Untangled vault exposure report into the DeBank-normalized shape
@@ -150,7 +221,10 @@ function dominantAssetSymbol(exposure) {
150
221
  * Mapping:
151
222
  * - Each `byProtocol` entry becomes one position with a single supplying token,
152
223
  * valued in USD (`price: 1`), on the chain from
153
- * {@link UNTANGLED_PROTOCOL_REGISTRY}.
224
+ * {@link UNTANGLED_PROTOCOL_REGISTRY}. The token is labelled with the vault's
225
+ * asset only when one asset covers essentially all of it (see
226
+ * {@link vaultAssetSymbol}); otherwise it carries the value with no symbol,
227
+ * and {@link untangledAssetExposure} supplies the composition separately.
154
228
  * - `stellar-wallet` becomes a wallet token, because custody cash is undeployed
155
229
  * capital rather than protocol exposure.
156
230
  * - `upshift` is split: the vault's own idle buffer (the `idle` location) joins
@@ -184,7 +258,7 @@ function transformUntangledToDebank(exposure) {
184
258
  if (!exposure) {
185
259
  return { subaccount: { positions: [], tokens: [] } };
186
260
  }
187
- const symbol = dominantAssetSymbol(exposure);
261
+ const symbol = vaultAssetSymbol(exposure);
188
262
  const vaultChain = exposure.vault?.chain || DEFAULT_CHAIN;
189
263
  const idleUsd = idleLocationUsd(exposure);
190
264
  const positions = [];
@@ -111,7 +111,7 @@ export type IPoolWithPositions = IPoolWithUnderlying & {
111
111
  redeemable: INormalizedNumber;
112
112
  walletBalance: string;
113
113
  };
114
- export type IPoolFunctions = 'decimals' | 'symbol' | 'name' | 'asset' | 'totalSupply' | 'maxSupply' | 'totalAssets' | 'globalLoansAmount' | 'loansOperator' | 'getTotalLoansDeployed' | 'withdrawalFee' | 'lagDuration' | 'withdrawalsPaused' | 'assetsWhitelistAddress' | 'getWhitelistedAssets' | 'maxDepositAmount' | 'getTotalAssets' | 'lpTokenAddress' | 'depositCap';
114
+ export type IPoolFunctions = 'decimals' | 'symbol' | 'name' | 'asset' | 'totalSupply' | 'maxSupply' | 'totalAssets' | 'globalLoansAmount' | 'loansOperator' | 'getTotalLoansDeployed' | 'withdrawalFee' | 'lagDuration' | 'withdrawalsPaused' | 'depositsPaused' | 'assetsWhitelistAddress' | 'getWhitelistedAssets' | 'maxDepositAmount' | 'getTotalAssets' | 'lpTokenAddress' | 'depositCap';
115
115
  export type IPoolAction = 'deposit' | 'withdraw' | 'claim' | 'stake' | 'getReward' | 'unstake';
116
116
  export type IPoolModal = {
117
117
  isOpen: boolean;
@@ -143,6 +143,16 @@ export type IExposurePerCategory = {
143
143
  */
144
144
  export interface IVaultAllocations {
145
145
  defi: IDebankProtocolExposure[];
146
+ /**
147
+ * The vault's asset composition, in USD (`amount` is a dollar value).
148
+ *
149
+ * On Stellar this is Untangled's `byAsset` breakdown, which decomposes the
150
+ * same `tvlUsd` that `defi` does along a different axis — assets rather than
151
+ * venues. The two do not join: which venue holds which asset is not published,
152
+ * so this is the only place a Stellar vault's assets are stated, and reading a
153
+ * per-venue asset split out of `exposurePerCategory` is not supported for
154
+ * multi-asset Stellar vaults.
155
+ */
146
156
  tokens: IDebankTokenExposure[];
147
157
  cefi: IWSSubaccountCefi[];
148
158
  unfilteredTokens: IDebankTokenExposure[];
@@ -166,7 +176,7 @@ export interface IVaultAllocations {
166
176
  *
167
177
  * This is stated explicitly because the convention going undocumented let a
168
178
  * consumer scale a subset of these fields twice, making them contribute 1/100th of
169
- * their value to a displayed total (AUGUST-6967). The unit is uniform here by
179
+ * their value to a displayed total. The unit is uniform here by
170
180
  * design; treating some of these fields as decimals and others as percentages is
171
181
  * always a bug on the consumer side.
172
182
  */
@@ -457,16 +467,16 @@ export interface IVaultPnl {
457
467
  * Supported Vaults: cUSDO, tETH, wstETH, rsETH
458
468
  *
459
469
  * @deprecated The `hgETH30dLiquidAPY` and `hgETH7dLiquidAPY` fields are deprecated.
460
- * These fields will be removed on 2026-01-01.
470
+ * These fields will be removed in the next major release.
461
471
  * Use `liquidAPY30Day` and `liquidAPY7Day` fields instead.
462
472
  */
463
473
  export interface IVaultAnnualizedApy {
464
474
  vaultAddress: IAddress;
465
475
  liquidityApy: number;
466
476
  annualizedApy: number;
467
- /** @deprecated Use `liquidAPY7Day` instead. Will be removed on 2026-01-01. */
477
+ /** @deprecated Use `liquidAPY7Day` instead. Will be removed in the next major release. */
468
478
  hgETH7dLiquidAPY?: number;
469
- /** @deprecated Use `liquidAPY30Day` instead. Will be removed on 2026-01-01. */
479
+ /** @deprecated Use `liquidAPY30Day` instead. Will be removed in the next major release. */
470
480
  hgETH30dLiquidAPY?: number;
471
481
  liquidAPY7Day?: number;
472
482
  liquidAPY30Day?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augustdigital/sdk",
3
- "version": "9.2.2",
3
+ "version": "9.4.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/sdk.d.ts",
6
6
  "keywords": [