@augustdigital/sdk 9.7.1 → 9.9.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.
@@ -9,6 +9,8 @@ export declare const LAYERZERO_VAULTS: {
9
9
  receiptToken: "coreusdc";
10
10
  decimals: number;
11
11
  hubChainId: number;
12
+ hubComposer: IAddress;
13
+ hubShareOFT: IAddress;
12
14
  spokeChains: Record<number, IAddress>;
13
15
  subgraphEndpoints: string[];
14
16
  };
@@ -17,6 +19,8 @@ export declare const LAYERZERO_VAULTS: {
17
19
  receiptToken: "upusdc";
18
20
  decimals: number;
19
21
  hubChainId: number;
22
+ hubComposer: IAddress;
23
+ hubShareOFT: IAddress;
20
24
  spokeChains: Record<number, IAddress>;
21
25
  subgraphEndpoints: string[];
22
26
  };
@@ -25,6 +29,8 @@ export declare const LAYERZERO_VAULTS: {
25
29
  receiptToken: "earnausd";
26
30
  decimals: number;
27
31
  hubChainId: number;
32
+ hubComposer: IAddress;
33
+ hubShareOFT: IAddress;
28
34
  spokeChains: Record<number, IAddress>;
29
35
  subgraphEndpoints: string[];
30
36
  };
@@ -11,12 +11,16 @@ const fetcher_1 = require("../subgraph/fetcher");
11
11
  const utils_1 = require("./utils");
12
12
  // LayerZero vault addresses and their corresponding receipt tokens
13
13
  // spokeChains maps chainId -> shareOFT address (receipt token on that chain)
14
+ // hubComposer / hubShareOFT: the hub-chain OVault composer (VAULT() is the
15
+ // vault) and its SHARE_OFT(), verified on-chain 2026-10-01
14
16
  exports.LAYERZERO_VAULTS = {
15
17
  coreUSDC: {
16
18
  address: '0xE9B725010A9E419412ed67d0fA5f3A5f40159D32',
17
19
  receiptToken: 'coreusdc',
18
20
  decimals: 6, // USDC decimals
19
21
  hubChainId: 1,
22
+ hubComposer: '0xc2637d7721791cc9cb196628d1e5e06887b1d4b9',
23
+ hubShareOFT: '0x4A21dcbA38c3816C78144f33bb42D8fa17F38067',
20
24
  spokeChains: {
21
25
  42161: '0x50a31ff4d57841681011837c17aa201c6a34203c', // Arbitrum
22
26
  43114: '0x1FA931Bf85248aD2eDf0004DD9A284698358e708', // Avalanche
@@ -32,6 +36,8 @@ exports.LAYERZERO_VAULTS = {
32
36
  receiptToken: 'upusdc',
33
37
  decimals: 6, // USDC decimals
34
38
  hubChainId: 1,
39
+ hubComposer: '0xbe82134b95a8e9370e6759f3c8f44087cd9a52be',
40
+ hubShareOFT: '0x81971A3C359cFE74259CfF1b46FB5f2112ddDE34',
35
41
  spokeChains: {
36
42
  42161: '0x81971a3c359cfe74259cff1b46fb5f2112ddde34', // Arbitrum
37
43
  43114: '0x81971A3C359cFE74259CfF1b46FB5f2112ddDE34', // Avalanche
@@ -47,6 +53,8 @@ exports.LAYERZERO_VAULTS = {
47
53
  receiptToken: 'earnausd',
48
54
  decimals: 6,
49
55
  hubChainId: 143,
56
+ hubComposer: '0xd1b1b12533e12badb8ea6d63aedd11922cae5580',
57
+ hubShareOFT: '0x9549Fa3DF579Cca9F3e328695382675F7f1f0F34',
50
58
  spokeChains: {
51
59
  1: '0xa6916b65c5e3fEdf46c0a2F59bff776e872C8992', // Ethereum
52
60
  },
@@ -20,7 +20,9 @@ export declare function isSubgraphSchemaFieldError(errors: {
20
20
  }[] | undefined): boolean;
21
21
  /**
22
22
  * Detects whether a deployed subgraph uses the old or new field schema by probing
23
- * a single field (`blockTimestamp`) that exists only on the new template.
23
+ * a single field (`blockTimestamp`) that exists only on the new template, on
24
+ * `withdrawalRequesteds`, or on `transfers` for a receipt-token subgraph that
25
+ * has no `withdrawalRequesteds` entity.
24
26
  *
25
27
  * This replaces the previous heuristic — "vault symbol present in the deprecated
26
28
  * `SUBGRAPH_VAULT_URLS` map ⇒ old schema, else new" — which mis-guessed any
@@ -34,7 +36,8 @@ export declare function isSubgraphSchemaFieldError(errors: {
34
36
  * cached per URL ({@link SCHEMA_TTL_MS}); across a page's positions/history/
35
37
  * withdrawals reads this amounts to a single extra lightweight query per subgraph.
36
38
  *
37
- * Side effects: at most one HTTP POST to the subgraph per URL per TTL window.
39
+ * Side effects: at most two HTTP POSTs to the subgraph per URL per TTL window
40
+ * (the second only for a subgraph without `withdrawalRequesteds`).
38
41
  *
39
42
  * @param goldskyUrl - Fully-qualified subgraph GraphQL endpoint.
40
43
  * @param apiKey - Optional Goldsky API key sent as a Bearer token.
@@ -18,9 +18,20 @@ const SCHEMA_TTL_MS = 60 * 60 * 1000; // 1 hour
18
18
  function isSubgraphSchemaFieldError(errors) {
19
19
  return Boolean(errors?.some((e) => e?.message?.includes('has no field')));
20
20
  }
21
+ // GraphQL errors from querying `blockTimestamp` on one row of `entity`;
22
+ // undefined on a non-200 response or a clean result.
23
+ async function probeSchemaErrors(goldskyUrl, entity, apiKey) {
24
+ const result = await (0, fetcher_1.fetchSubgraph)(goldskyUrl, `{ ${entity}(first: 1) { blockTimestamp } }`, apiKey);
25
+ if (result.status !== 200)
26
+ return undefined;
27
+ const json = (await result.json());
28
+ return json?.errors;
29
+ }
21
30
  /**
22
31
  * Detects whether a deployed subgraph uses the old or new field schema by probing
23
- * a single field (`blockTimestamp`) that exists only on the new template.
32
+ * a single field (`blockTimestamp`) that exists only on the new template, on
33
+ * `withdrawalRequesteds`, or on `transfers` for a receipt-token subgraph that
34
+ * has no `withdrawalRequesteds` entity.
24
35
  *
25
36
  * This replaces the previous heuristic — "vault symbol present in the deprecated
26
37
  * `SUBGRAPH_VAULT_URLS` map ⇒ old schema, else new" — which mis-guessed any
@@ -34,7 +45,8 @@ function isSubgraphSchemaFieldError(errors) {
34
45
  * cached per URL ({@link SCHEMA_TTL_MS}); across a page's positions/history/
35
46
  * withdrawals reads this amounts to a single extra lightweight query per subgraph.
36
47
  *
37
- * Side effects: at most one HTTP POST to the subgraph per URL per TTL window.
48
+ * Side effects: at most two HTTP POSTs to the subgraph per URL per TTL window
49
+ * (the second only for a subgraph without `withdrawalRequesteds`).
38
50
  *
39
51
  * @param goldskyUrl - Fully-qualified subgraph GraphQL endpoint.
40
52
  * @param apiKey - Optional Goldsky API key sent as a Bearer token.
@@ -53,15 +65,15 @@ async function resolveSubgraphSchema(goldskyUrl, apiKey) {
53
65
  // `blockTimestamp` is a new-schema-only field. If the subgraph rejects it
54
66
  // with an unknown-field error, the deployment is old-schema. Schema
55
67
  // validation is static, so this is authoritative even when the entity has
56
- // zero rows.
57
- const result = await (0, fetcher_1.fetchSubgraph)(goldskyUrl, `{ withdrawalRequesteds(first: 1) { blockTimestamp } }`, apiKey);
58
- let schema = 'new';
59
- if (result.status === 200) {
60
- const json = (await result.json());
61
- if (isSubgraphSchemaFieldError(json?.errors)) {
62
- schema = 'old';
63
- }
68
+ // zero rows. A receipt-token subgraph indexes only `transfers`, so when
69
+ // `withdrawalRequesteds` itself is unknown the probe moves to `transfers`.
70
+ let errors = await probeSchemaErrors(goldskyUrl, 'withdrawalRequesteds', apiKey);
71
+ if (errors?.some((e) => e?.message?.includes('has no field `withdrawalRequesteds`'))) {
72
+ errors = await probeSchemaErrors(goldskyUrl, 'transfers', apiKey);
64
73
  }
74
+ const schema = isSubgraphSchemaFieldError(errors)
75
+ ? 'old'
76
+ : 'new';
65
77
  core_1.CACHE.set(key, schema, { ttl: SCHEMA_TTL_MS });
66
78
  return schema;
67
79
  }
@@ -1,4 +1,4 @@
1
- import type { IAddress, IContractRunner, ISubgraphTransfer, ISubgraphUserHistoryItem, ISubgraphWithdrawProccessed, ISubgraphWithdrawRequest } from '../../types';
1
+ import type { IAddress, IContractRunner, ISubgraphReserveDeposit, ISubgraphTransfer, ISubgraphUserHistoryItem, ISubgraphWithdrawProccessed, ISubgraphWithdrawRequest } from '../../types';
2
2
  export declare function isOldSubgraphSchema(vaultSymbol: string): boolean;
3
3
  /**
4
4
  *
@@ -40,3 +40,25 @@ export declare function getSubgraphVaultHistory(provider: IContractRunner, pool:
40
40
  export declare function getSubgraphUserTransfers(user: IAddress, provider: IContractRunner, pool: IAddress, slackWebookUrl?: string, options?: {
41
41
  receiptSubgraph?: boolean;
42
42
  }): Promise<ISubgraphTransfer[]>;
43
+ /**
44
+ * Fetch the `ReserveDeposit` events that minted vault shares to `user`.
45
+ *
46
+ * Some vaults mint shares without an ERC-4626 `Deposit` event: High Growth ETH
47
+ * emits `ReserveDeposit(account, shares, assets)` for deposits made through
48
+ * Kelp's gain adapter, so {@link getSubgraphUserHistory} never sees them. Its
49
+ * subgraph indexes the event as `reserveDeposits`.
50
+ *
51
+ * Side effects: one `getVaultSymbol` RPC read (cached), the vault metadata and
52
+ * schema probes (cached), and one subgraph query.
53
+ *
54
+ * @param user - The wallet the shares were minted to.
55
+ * @param provider - Contract runner for the vault's chain.
56
+ * @param pool - The vault contract address.
57
+ * @returns Up to 1000 events, oldest first. Empty when the vault's subgraph
58
+ * has no `reserveDeposits` entity, has no URL, or the query fails.
59
+ * @example
60
+ * ```ts
61
+ * const reserveDeposits = await getSubgraphUserReserveDeposits(wallet, provider, vault);
62
+ * ```
63
+ */
64
+ export declare function getSubgraphUserReserveDeposits(user: IAddress, provider: IContractRunner, pool: IAddress): Promise<ISubgraphReserveDeposit[]>;
@@ -7,6 +7,7 @@ exports.getSubgraphAllWithdrawals = getSubgraphAllWithdrawals;
7
7
  exports.getSubgraphUserHistory = getSubgraphUserHistory;
8
8
  exports.getSubgraphVaultHistory = getSubgraphVaultHistory;
9
9
  exports.getSubgraphUserTransfers = getSubgraphUserTransfers;
10
+ exports.getSubgraphUserReserveDeposits = getSubgraphUserReserveDeposits;
10
11
  const ethers_1 = require("ethers");
11
12
  const slack_1 = require("../../core/logger/slack");
12
13
  const fetcher_1 = require("./fetcher");
@@ -1119,4 +1120,68 @@ async function getSubgraphUserTransfers(user, provider, pool, slackWebookUrl = (
1119
1120
  return [];
1120
1121
  }
1121
1122
  }
1123
+ /**
1124
+ * Fetch the `ReserveDeposit` events that minted vault shares to `user`.
1125
+ *
1126
+ * Some vaults mint shares without an ERC-4626 `Deposit` event: High Growth ETH
1127
+ * emits `ReserveDeposit(account, shares, assets)` for deposits made through
1128
+ * Kelp's gain adapter, so {@link getSubgraphUserHistory} never sees them. Its
1129
+ * subgraph indexes the event as `reserveDeposits`.
1130
+ *
1131
+ * Side effects: one `getVaultSymbol` RPC read (cached), the vault metadata and
1132
+ * schema probes (cached), and one subgraph query.
1133
+ *
1134
+ * @param user - The wallet the shares were minted to.
1135
+ * @param provider - Contract runner for the vault's chain.
1136
+ * @param pool - The vault contract address.
1137
+ * @returns Up to 1000 events, oldest first. Empty when the vault's subgraph
1138
+ * has no `reserveDeposits` entity, has no URL, or the query fails.
1139
+ * @example
1140
+ * ```ts
1141
+ * const reserveDeposits = await getSubgraphUserReserveDeposits(wallet, provider, vault);
1142
+ * ```
1143
+ */
1144
+ async function getSubgraphUserReserveDeposits(user, provider, pool) {
1145
+ try {
1146
+ let vaultSymbol = await (0, core_1.getVaultSymbol)(pool, provider);
1147
+ if (vaultSymbol === undefined)
1148
+ return [];
1149
+ const networkValue = await provider.provider.getNetwork();
1150
+ if (needsMonadSuffix(Number(networkValue.chainId), vaultSymbol)) {
1151
+ vaultSymbol = vaultSymbol.concat('_monad');
1152
+ }
1153
+ const vaultsMetadata = await (0, fetcher_2.fetchVaultMetadata)();
1154
+ const { subgraph } = vaultsMetadata?.[vaultSymbol.toLowerCase()] || {};
1155
+ const goldskyUrl = subgraph ||
1156
+ core_1.SUBGRAPH_VAULT_URLS[vaultSymbol.toLowerCase()] ||
1157
+ (0, core_1.getDefaultSubgraphUrl)(networkValue.name, vaultSymbol);
1158
+ if (!goldskyUrl)
1159
+ return [];
1160
+ const useOldSchema = (await (0, schema_1.resolveSubgraphSchema)(goldskyUrl, GOLDSKY_API_KEY)) === 'old';
1161
+ const props = useOldSchema
1162
+ ? 'id account shares assets transactionHash_ timestamp_ block_number'
1163
+ : 'id account shares assets transactionHash_: transactionHash timestamp_: blockTimestamp block_number: blockNumber';
1164
+ const result = await (0, fetcher_1.fetchSubgraph)(goldskyUrl, `{
1165
+ reserveDeposits(
1166
+ first: 1000,
1167
+ orderBy: ${useOldSchema ? 'timestamp_' : 'blockTimestamp'},
1168
+ orderDirection: asc,
1169
+ where: { account: "${user.toLowerCase()}" }
1170
+ ) {
1171
+ ${props}
1172
+ }
1173
+ }`, GOLDSKY_API_KEY);
1174
+ if (result.status !== 200)
1175
+ return [];
1176
+ const json = (await result.json());
1177
+ if (json.errors?.length && !(0, schema_1.isSubgraphSchemaFieldError)(json.errors)) {
1178
+ core_1.Logger.log.warn('getSubgraphUserReserveDeposits', `${pool}::${JSON.stringify(json.errors).slice(0, 200)}`);
1179
+ }
1180
+ return json.data?.reserveDeposits ?? [];
1181
+ }
1182
+ catch (e) {
1183
+ core_1.Logger.log.warn('getSubgraphUserReserveDeposits', `${pool}::${e}`);
1184
+ return [];
1185
+ }
1186
+ }
1122
1187
  //# sourceMappingURL=vaults.js.map
@@ -67,6 +67,16 @@ export interface ISubgraphWithdraw extends ISubgraphBase {
67
67
  sender: string;
68
68
  assets: string;
69
69
  }
70
+ /**
71
+ * A `ReserveDeposit(account, shares, assets)` event: a deposit that mints
72
+ * shares to `account` without an ERC-4626 `Deposit` event. High Growth ETH
73
+ * emits it for deposits made through Kelp's gain adapter.
74
+ */
75
+ export interface ISubgraphReserveDeposit extends ISubgraphBase {
76
+ account: IAddress;
77
+ shares: string;
78
+ assets: string;
79
+ }
70
80
  export interface ISubgraphTransfer extends ISubgraphBase {
71
81
  from: IAddress;
72
82
  to: IAddress;
@@ -459,6 +459,17 @@ export interface IVaultUserLifetimePnl {
459
459
  lifetimePnl: INormalizedNumber;
460
460
  lifetimePnlUsd: number;
461
461
  pnlPercentage: number;
462
+ /**
463
+ * The part of `totalDeposited` that is shares the wallet received from
464
+ * another holder (a migration airdrop, a DEX purchase, a transfer from
465
+ * another wallet), valued at the vault's share ratio on the day each
466
+ * arrived. Zero when no such shares counted. Optional only so objects built
467
+ * before it existed still type-check; `getVaultUserLifetimePnl` always sets
468
+ * it.
469
+ */
470
+ receivedByTransfer?: INormalizedNumber;
471
+ /** `receivedByTransfer` in USD, at the same price as the other USD fields. */
472
+ receivedByTransferUsd?: number;
462
473
  }
463
474
  export interface IVaultPnl {
464
475
  totalPnl: INormalizedNumber;
@@ -636,7 +647,11 @@ export interface ISwapRouterBaseOptions {
636
647
  receiver: IAddress;
637
648
  /**
638
649
  * 32-byte origin/referral code registered via `addOrigin`. Drives the
639
- * origin-fee accrual. Defaults to {@link ORIGIN_CODES.default} when omitted.
650
+ * origin-fee accrual. Defaults to the SDK instance's `attribution.originCode`
651
+ * when omitted on Ethereum mainnet, else {@link ORIGIN_CODES.default}. A code
652
+ * passed here that is not registered throws before any approval; an
653
+ * unregistered instance code falls back to the sentinel with an
654
+ * `attribution-skipped` warning (or throws under `attribution.strictOrigin`).
640
655
  */
641
656
  originCode?: `0x${string}`;
642
657
  /** When `true`, the helper awaits a single confirmation before returning. */
@@ -675,11 +690,10 @@ export interface ISwapRouterNativeDepositOptions extends ISwapRouterBaseOptions
675
690
  * on-chain, then picks the correct router path from `depositAsset`, so callers
676
691
  * do not hand-build swap legs or pre-resolve decimals themselves.
677
692
  *
678
- * Prefer this over relying on the implicit routing inside `vaultDeposit`: here
679
- * the caller opts into the SwapRouter deliberately, so a vault is never
680
- * silently routed through a swap it does not need — the failure mode that broke
681
- * native multi-asset deposits when a multi-asset vault was added to
682
- * `VAULTS_USING_SWAP_ROUTER`.
693
+ * `vaultDeposit` never swaps; this is the explicit, opt-in entry point for
694
+ * swap deposits, so a vault is never silently routed through a swap it does
695
+ * not need — the failure mode that broke native multi-asset deposits when
696
+ * `vaultDeposit` still auto-routed allowlisted vaults.
683
697
  *
684
698
  * Unlike {@link ISwapRouterBaseOptions}, `receiver` is optional here and
685
699
  * defaults to the signer's resolved EOA.
@@ -717,6 +731,24 @@ export interface ISwapRouterDepositResultOptions {
717
731
  /** The vault that was deposited into — isolates its own `Deposit` event from the router's unrelated logs. */
718
732
  vault: IAddress;
719
733
  }
734
+ /** Options for {@link getOriginInfo}. */
735
+ export interface IGetOriginInfoOptions {
736
+ /** EVM chain ID whose `SwapRouter` to read. */
737
+ chainId: number;
738
+ /** The `bytes32` origin code, `0x` + 64 hex chars. */
739
+ originCode: `0x${string}`;
740
+ /** RPC endpoint for `chainId`. */
741
+ rpcUrl: string;
742
+ }
743
+ /** A SwapRouter origin code's registration, from `origins(bytes32)`. */
744
+ export interface IOriginInfo {
745
+ /** `true` when registered via `addOrigin` and not revoked (non-zero collector). */
746
+ registered: boolean;
747
+ /** Origin fee in basis points; `0` for an attribution-only code. */
748
+ originFeeBps: number;
749
+ /** Fee recipient; the zero address when the code is not registered. */
750
+ collector: IAddress;
751
+ }
720
752
  /**
721
753
  * Real, on-chain outcome of a SwapRouter deposit, decoded from the vault's own
722
754
  * `Deposit` event (the SwapRouter contract itself emits no deposit/amount-out
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augustdigital/sdk",
3
- "version": "9.7.1",
3
+ "version": "9.9.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/sdk.d.ts",
6
6
  "keywords": [