@augustdigital/sdk 8.16.1 → 8.19.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.
@@ -29,9 +29,23 @@ const MISSING_SUBGRAPH_ALERT_TTL_MS = 60 * 60 * 1000; // 1 hour
29
29
  * would flood the webhook for every metadata-less vault. Deduping per pool
30
30
  * surfaces a genuinely-missing subgraph without the flood.
31
31
  *
32
+ * This is the durable signal for BOTH ways a vault's subgraph can be broken — no
33
+ * URL configured, and a URL that answers non-200 (a deleted subgraph 404s). The
34
+ * readers deliberately log those per-request at `warn` rather than `error`: at
35
+ * `error` each one became a billed Sentry issue on every portfolio read, which
36
+ * cost over 2M events in 30 days across a handful of vaults. The volume is
37
+ * per-request, but the condition is per-vault, so this alert is where it belongs.
38
+ *
32
39
  * @param args.source - Reader function name, for the alert body.
33
40
  * @param args.pool - Vault address (used as the dedupe key, lowercased).
34
- * @param args.chainId - Chain id for the alert context.
41
+ * @param args.chainId - Chain id for the alert context, or a thunk resolving
42
+ * it. Every current caller has the id in scope and passes it directly. The
43
+ * thunk form exists for a caller that would otherwise have to resolve the id
44
+ * eagerly on every non-200 response — it is invoked only after the dedupe
45
+ * gate passes, so a suppressed alert costs nothing. No such caller exists
46
+ * today; if none appears, this union and the deferred branch below can go.
47
+ * @param args.reason - Why the subgraph is unusable. Defaults to the
48
+ * missing-URL case; pass the HTTP status for a URL that resolved but failed.
35
49
  * @param args.slackWebookUrl - Optional override webhook URL.
36
50
  */
37
51
  function alertMissingSubgraphOnce(args) {
@@ -39,13 +53,31 @@ function alertMissingSubgraphOnce(args) {
39
53
  if (core_1.CACHE.has(key))
40
54
  return;
41
55
  core_1.CACHE.set(key, true, { ttl: MISSING_SUBGRAPH_ALERT_TTL_MS });
42
- slack_1.SLACK.error({
56
+ const send = (chainId) => slack_1.SLACK.error({
43
57
  title: 'Missing Subgraph',
44
- error: `#${args.source}: goldsky url is undefined`,
58
+ error: `#${args.source}: ${args.reason ?? 'goldsky url is undefined'}`,
45
59
  poolAddress: args.pool,
46
- chainId: args.chainId,
60
+ chainId,
47
61
  slackWebookUrl: args.slackWebookUrl || '',
48
62
  });
63
+ if (typeof args.chainId === 'number') {
64
+ send(args.chainId);
65
+ return;
66
+ }
67
+ // Deferred id: the dedupe key is already set, so a rejection here would mute
68
+ // this pool for the full TTL without ever alerting. Release the key instead,
69
+ // leaving the next non-200 free to try again.
70
+ void args
71
+ .chainId()
72
+ .then(send, (e) => {
73
+ core_1.CACHE.delete(key);
74
+ core_1.Logger.log.warn('alertMissingSubgraphOnce', `chain id unresolved, alert skipped: ${e}`);
75
+ })
76
+ // `send` itself can reject (SLACK.error does its own fetch). Without this
77
+ // it escapes as an unhandled rejection instead of being contained here.
78
+ .catch((e) => {
79
+ core_1.Logger.log.warn('alertMissingSubgraphOnce', `alert send failed: ${e}`);
80
+ });
49
81
  }
50
82
  /**
51
83
  * earnAUSD exists on both Ethereum and Monad, so it needs a _monad suffix
@@ -395,7 +427,16 @@ async function getSubgraphWithdrawRequests(pool, provider, slackWebookUrl = slac
395
427
  }
396
428
  }`, GOLDSKY_API_KEY);
397
429
  if (result.status !== 200) {
398
- core_1.Logger.log.error('getSubgraphWithdrawRequests', `${result.statusText}::${result.status}: ${vaultSymbol}::${pool}`);
430
+ core_1.Logger.log.warn('getSubgraphWithdrawRequests', `${result.statusText}::${result.status}: ${vaultSymbol}::${pool}`);
431
+ alertMissingSubgraphOnce({
432
+ source: 'getSubgraphWithdrawRequests',
433
+ pool,
434
+ // Already resolved at the top of this function — no re-fetch, and the
435
+ // alert fires synchronously.
436
+ chainId: network,
437
+ reason: `subgraph returned ${result.status} ${result.statusText}`,
438
+ slackWebookUrl,
439
+ });
399
440
  return [];
400
441
  }
401
442
  const json = (await result.json());
@@ -428,7 +469,7 @@ async function getSubgraphWithdrawProccessed(pool, provider, slackWebookUrl = sl
428
469
  const requests = [];
429
470
  if (!goldskyUrl) {
430
471
  const chainId = await (0, core_1.getChainId)(provider);
431
- core_1.Logger.log.error('getSubgraphWithdrawProccessed.missing-subgraph-url', new Error('goldsky url is undefined'), { chainId, vaultSymbol, pool });
472
+ core_1.Logger.log.warn('getSubgraphWithdrawProccessed.missing-subgraph-url', `goldsky url is undefined: ${vaultSymbol}::${pool}`, { chainId });
432
473
  alertMissingSubgraphOnce({
433
474
  source: 'getSubgraphWithdrawProccessed',
434
475
  pool,
@@ -458,7 +499,16 @@ async function getSubgraphWithdrawProccessed(pool, provider, slackWebookUrl = sl
458
499
  }
459
500
  }`, GOLDSKY_API_KEY);
460
501
  if (result.status !== 200) {
461
- core_1.Logger.log.error('getSubgraphWithdrawProccessed', new Error(`HTTP ${result.status} ${result.statusText}`), { status: result.status, statusText: result.statusText, pool });
502
+ core_1.Logger.log.warn('getSubgraphWithdrawProccessed', `${result.statusText}::${result.status}: ${vaultSymbol}::${pool}`);
503
+ alertMissingSubgraphOnce({
504
+ source: 'getSubgraphWithdrawProccessed',
505
+ pool,
506
+ // Already resolved at the top of this function — no re-fetch, and the
507
+ // alert fires synchronously.
508
+ chainId: network,
509
+ reason: `subgraph returned ${result.status} ${result.statusText}`,
510
+ slackWebookUrl,
511
+ });
462
512
  return [];
463
513
  }
464
514
  const json = (await result.json());
@@ -506,7 +556,7 @@ async function getSubgraphAllWithdrawals(pool, provider, slackWebookUrl = slack_
506
556
  (0, core_1.getDefaultSubgraphUrl)(networkValue.name, vaultSymbol);
507
557
  if (!goldskyUrl) {
508
558
  const chainId = await (0, core_1.getChainId)(provider);
509
- core_1.Logger.log.error('getSubgraphAllWithdrawals', `goldsky url is undefined: ${vaultSymbol}::${pool}`);
559
+ core_1.Logger.log.warn('getSubgraphAllWithdrawals', `goldsky url is undefined: ${vaultSymbol}::${pool}`);
510
560
  alertMissingSubgraphOnce({
511
561
  source: 'getSubgraphAllWithdrawals',
512
562
  pool,
@@ -552,7 +602,14 @@ async function getSubgraphAllWithdrawals(pool, provider, slackWebookUrl = slack_
552
602
  }`;
553
603
  const result = await (0, fetcher_1.fetchSubgraph)(goldskyUrl, query, GOLDSKY_API_KEY);
554
604
  if (result.status !== 200) {
555
- core_1.Logger.log.error('getSubgraphAllWithdrawals', `${result.statusText}::${result.status}: ${vaultSymbol}::${pool}`);
605
+ core_1.Logger.log.warn('getSubgraphAllWithdrawals', `${result.statusText}::${result.status}: ${vaultSymbol}::${pool}`);
606
+ alertMissingSubgraphOnce({
607
+ source: 'getSubgraphAllWithdrawals',
608
+ pool,
609
+ chainId: network,
610
+ reason: `subgraph returned ${result.status} ${result.statusText}`,
611
+ slackWebookUrl,
612
+ });
556
613
  return errorReturnObj;
557
614
  }
558
615
  const json = (await result.json());
@@ -681,7 +738,7 @@ async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = sla
681
738
  core_1.SUBGRAPH_VAULT_URLS[vaultSymbol?.toLowerCase()] ||
682
739
  (0, core_1.getDefaultSubgraphUrl)(networkValue.name, vaultSymbol);
683
740
  if (!goldskyUrl) {
684
- core_1.Logger.log.error('getSubgraphUserHistory', `goldsky url is undefined: ${vaultSymbol}::${pool}`);
741
+ core_1.Logger.log.warn('getSubgraphUserHistory', `goldsky url is undefined: ${vaultSymbol}::${pool}`);
685
742
  alertMissingSubgraphOnce({
686
743
  source: 'getSubgraphUserHistory',
687
744
  pool,
@@ -766,7 +823,14 @@ async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = sla
766
823
  }`;
767
824
  const result = await (0, fetcher_1.fetchSubgraph)(goldskyUrl, fullRequest, GOLDSKY_API_KEY);
768
825
  if (result.status !== 200) {
769
- core_1.Logger.log.error('getSubgraphUserHistory', `${result.statusText}::${result.status}: ${vaultSymbol}::${pool}`);
826
+ core_1.Logger.log.warn('getSubgraphUserHistory', `${result.statusText}::${result.status}: ${vaultSymbol}::${pool}`);
827
+ alertMissingSubgraphOnce({
828
+ source: 'getSubgraphUserHistory',
829
+ pool,
830
+ chainId,
831
+ reason: `subgraph returned ${result.status} ${result.statusText}`,
832
+ slackWebookUrl,
833
+ });
770
834
  return requests;
771
835
  }
772
836
  const json = (await result.json());
@@ -807,7 +871,7 @@ async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = slack_1.
807
871
  (0, core_1.getDefaultSubgraphUrl)(networkValue.name, vaultSymbol);
808
872
  if (!goldskyUrl) {
809
873
  const chainId = await (0, core_1.getChainId)(provider);
810
- core_1.Logger.log.error('getSubgraphVaultHistory', `goldsky url is undefined: ${vaultSymbol}::${pool}`);
874
+ core_1.Logger.log.warn('getSubgraphVaultHistory', `goldsky url is undefined: ${vaultSymbol}::${pool}`);
811
875
  alertMissingSubgraphOnce({
812
876
  source: 'getSubgraphVaultHistory',
813
877
  pool,
@@ -892,7 +956,14 @@ async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = slack_1.
892
956
  }
893
957
  }`, GOLDSKY_API_KEY);
894
958
  if (result.status !== 200) {
895
- core_1.Logger.log.error('getSubgraphVaultHistory', new Error(`HTTP ${result.status} ${result.statusText}`), { status: result.status, statusText: result.statusText, skip });
959
+ core_1.Logger.log.warn('getSubgraphVaultHistory', `${result.statusText}::${result.status}: ${vaultSymbol}::${pool}`, { skip });
960
+ alertMissingSubgraphOnce({
961
+ source: 'getSubgraphVaultHistory',
962
+ pool,
963
+ chainId: network,
964
+ reason: `subgraph returned ${result.status} ${result.statusText}`,
965
+ slackWebookUrl,
966
+ });
896
967
  // First page failed → nothing to return. A later page failing still
897
968
  // yields whatever earlier pages accumulated.
898
969
  if (skip === 0)
@@ -966,7 +1037,7 @@ async function getSubgraphUserTransfers(user, provider, pool, slackWebookUrl = s
966
1037
  (0, core_1.getDefaultSubgraphUrl)(networkValue.name, vaultSymbol);
967
1038
  if (!goldskyUrl) {
968
1039
  const chainId = await (0, core_1.getChainId)(provider);
969
- core_1.Logger.log.error('getSubgraphUserTransfers', `goldsky url is undefined: ${vaultSymbol}::${pool}`);
1040
+ core_1.Logger.log.warn('getSubgraphUserTransfers', `goldsky url is undefined: ${vaultSymbol}::${pool}`);
970
1041
  alertMissingSubgraphOnce({
971
1042
  source: 'getSubgraphUserTransfers',
972
1043
  pool,
@@ -333,6 +333,18 @@ export interface IVault {
333
333
  performanceFeeWaivedUntilTvl: number | null;
334
334
  };
335
335
  lagDuration: number;
336
+ /**
337
+ * Backend-configured display buffer in seconds added on top of
338
+ * `lagDuration` for the withdrawal period shown to users. Null when the
339
+ * backend has not set a value — consumers apply their own default.
340
+ */
341
+ withdrawalMarginSeconds?: number | null;
342
+ /**
343
+ * IAT trader wallet addresses for the vault, from the backend
344
+ * `iat_traders` field. Address format follows the vault's chain
345
+ * (EVM hex / Solana base58 / Stellar). Null when not configured.
346
+ */
347
+ iatTraders?: string[] | null;
336
348
  maxDailyDrawdown: number;
337
349
  risk: string;
338
350
  isWithdrawalPaused: boolean;
@@ -624,6 +624,17 @@ export interface ITokenizedVault {
624
624
  solana_vault_metadata?: ISolanaVaultMetadata | null;
625
625
  stellar_vault_metadata?: IStellarVaultMetadata | null;
626
626
  lagDuration: number;
627
+ /**
628
+ * Display buffer in seconds added on top of the on-chain lag for the
629
+ * withdrawal period shown to users. Null when not configured.
630
+ */
631
+ withdrawal_margin_seconds?: number | null;
632
+ /**
633
+ * IAT trader wallet addresses for the vault. Address format follows the
634
+ * vault's chain (EVM hex / Solana base58 / Stellar). Null when not
635
+ * configured.
636
+ */
637
+ iat_traders?: string[] | null;
627
638
  historical_apy: Record<number, number> | null;
628
639
  /**
629
640
  * Compound-annualized historical APY keyed by horizon in days (1/7/30), as
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augustdigital/sdk",
3
- "version": "8.16.1",
3
+ "version": "8.19.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/sdk.d.ts",
6
6
  "keywords": [