@upshiftfinance/sdk 0.3.0 → 0.5.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 (61) hide show
  1. package/README.md +6 -2
  2. package/esm/index.d.mts +15 -0
  3. package/esm/index.mjs +18 -0
  4. package/lib/abis/KycRegistry.d.ts +109 -0
  5. package/lib/abis/KycRegistry.js +73 -0
  6. package/lib/abis/index.d.ts +1 -0
  7. package/lib/abis/index.js +1 -0
  8. package/lib/adapters/sui/actions.d.ts +420 -0
  9. package/lib/adapters/sui/actions.js +701 -0
  10. package/lib/adapters/sui/client.d.ts +3 -3
  11. package/lib/adapters/sui/client.js +27 -9
  12. package/lib/adapters/sui/getters.d.ts +268 -0
  13. package/lib/adapters/sui/getters.js +669 -0
  14. package/lib/adapters/sui/index.d.ts +243 -3
  15. package/lib/adapters/sui/index.js +250 -3
  16. package/lib/adapters/sui/targets.d.ts +42 -1
  17. package/lib/adapters/sui/targets.js +42 -1
  18. package/lib/core/analytics/method-taxonomy.d.ts +1 -1
  19. package/lib/core/analytics/method-taxonomy.js +9 -0
  20. package/lib/core/analytics/version.d.ts +1 -1
  21. package/lib/core/analytics/version.js +1 -1
  22. package/lib/core/constants/core.d.ts +5 -0
  23. package/lib/core/constants/core.js +5 -0
  24. package/lib/core/constants/kyc.d.ts +9 -0
  25. package/lib/core/constants/kyc.js +12 -0
  26. package/lib/core/constants/web3.d.ts +2 -2
  27. package/lib/core/constants/web3.js +9 -2
  28. package/lib/core/errors/index.d.ts +90 -1
  29. package/lib/core/errors/index.js +94 -1
  30. package/lib/core/fetcher.d.ts +5 -0
  31. package/lib/core/fetcher.js +1 -1
  32. package/lib/core/helpers/chain-support.d.ts +2 -2
  33. package/lib/core/helpers/chain-support.js +3 -3
  34. package/lib/core/helpers/kyc.d.ts +47 -0
  35. package/lib/core/helpers/kyc.js +111 -0
  36. package/lib/core/helpers/revert-decode.js +3 -2
  37. package/lib/core/index.d.ts +2 -0
  38. package/lib/core/index.js +2 -0
  39. package/lib/evm/methods/crossChainVault.js +25 -43
  40. package/lib/index.d.ts +4 -0
  41. package/lib/index.js +4 -0
  42. package/lib/main.d.ts +33 -3
  43. package/lib/main.js +32 -0
  44. package/lib/modules/api/kyc.d.ts +4 -0
  45. package/lib/modules/api/kyc.js +148 -0
  46. package/lib/modules/api/main.d.ts +63 -1
  47. package/lib/modules/api/main.js +64 -0
  48. package/lib/modules/vaults/getters.d.ts +3 -1
  49. package/lib/modules/vaults/getters.js +82 -10
  50. package/lib/modules/vaults/main.d.ts +41 -3
  51. package/lib/modules/vaults/main.js +82 -6
  52. package/lib/modules/vaults/types.d.ts +7 -1
  53. package/lib/modules/vaults/utils.js +4 -1
  54. package/lib/sdk.d.ts +16363 -14615
  55. package/lib/types/index.d.ts +1 -0
  56. package/lib/types/index.js +1 -0
  57. package/lib/types/kyc.d.ts +61 -0
  58. package/lib/types/kyc.js +3 -0
  59. package/lib/types/vaults.d.ts +2 -0
  60. package/lib/types/webserver.d.ts +5 -0
  61. package/package.json +21 -2
@@ -88,6 +88,8 @@ const SolanaConstants = __importStar(require("../../adapters/solana/constants"))
88
88
  const withdrawal_queue_1 = require("../../adapters/solana/withdrawal-queue");
89
89
  const web3_js_1 = require("@solana/web3.js");
90
90
  const StellarGetters = __importStar(require("../../adapters/stellar/getters"));
91
+ const SuiGetters = __importStar(require("../../adapters/sui/getters"));
92
+ const chain_address_1 = require("../../core/helpers/chain-address");
91
93
  const utils_3 = require("../../adapters/stellar/utils");
92
94
  const constants_1 = require("../../adapters/stellar/constants");
93
95
  const EVM = __importStar(require("../../adapters/evm"));
@@ -160,6 +162,10 @@ async function getVault({ vault, loans = false, allocations = false, options, lo
160
162
  returnedVault = await StellarGetters.getStellarVault(tokenizedVault, options);
161
163
  break;
162
164
  }
165
+ case 'sui-0': {
166
+ returnedVault = await SuiGetters.getSuiVault(tokenizedVault, options);
167
+ break;
168
+ }
163
169
  case 'evm-2': {
164
170
  returnedVault = await EVM.getEvmVaultV2(tokenizedVault, options);
165
171
  break;
@@ -179,7 +185,15 @@ async function getVault({ vault, loans = false, allocations = false, options, lo
179
185
  // caller sees the same throw either way, so it is recorded as a breadcrumb
180
186
  // rather than a billed Sentry issue. Everything else stays at error.
181
187
  (0, core_1.logChainError)('getVault', err, (0, core_1.isRetryableRpcError)(err) || (0, core_1.isEmptyViewResponse)(err), { vault });
182
- throw new Error(`#getVault::${vault}: ${err?.message}`);
188
+ // Typed SDK errors (rate limit, server, validation, …) pass through
189
+ // unchanged so callers can branch on `instanceof` / `code` and Sentry
190
+ // groups them by class. Anything else is wrapped in a typed error with the
191
+ // original kept as `cause`; the `#getVault::` message is unchanged.
192
+ if (err instanceof errors_1.UpshiftSDKError)
193
+ throw err;
194
+ throw new errors_1.UpshiftSDKError('UNKNOWN', `#getVault::${vault}: ${err?.message}`, {
195
+ cause: err,
196
+ });
183
197
  }
184
198
  // Loans enrichment stays EVM-only — there is no non-EVM loan book to read.
185
199
  // Allocations additionally covers Stellar (Untangled) and Solana (Octav, per
@@ -968,9 +982,9 @@ async function readSolanaRedemptions(input) {
968
982
  }
969
983
  async function getVaultAvailableRedemptions({ vault, wallet, options, prefetchedReads, }) {
970
984
  try {
971
- // Stellar vaults don't support on-chain redemptions yet
972
- if ((0, utils_3.isStellarAddress)(vault)) {
973
- core_1.Logger.log.warn('getVaultAvailableRedemptions', `Available redemptions is not yet supported for Stellar vaults: ${vault}`);
985
+ // Stellar and Sui vaults don't support on-chain redemptions yet
986
+ if ((0, utils_3.isStellarAddress)(vault) || (0, chain_address_1.isSuiAddress)(vault)) {
987
+ core_1.Logger.log.warn('getVaultAvailableRedemptions', `Available redemptions is not yet supported for this vault: ${vault}`);
974
988
  return {
975
989
  availableRedemptions: [],
976
990
  pendingRedemptions: [],
@@ -1305,9 +1319,9 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
1305
1319
  }
1306
1320
  async function getVaultRedemptionHistory({ vault, wallet, lookbackBlocks, options, }) {
1307
1321
  try {
1308
- // Stellar vaults: no on-chain redemption history yet
1309
- if ((0, utils_3.isStellarAddress)(vault)) {
1310
- core_1.Logger.log.warn('getVaultRedemptionHistory', `Redemption history is not yet supported for Stellar vaults: ${vault}`);
1322
+ // Stellar and Sui vaults: no on-chain redemption history yet
1323
+ if ((0, utils_3.isStellarAddress)(vault) || (0, chain_address_1.isSuiAddress)(vault)) {
1324
+ core_1.Logger.log.warn('getVaultRedemptionHistory', `Redemption history is not yet supported for this vault: ${vault}`);
1311
1325
  return [];
1312
1326
  }
1313
1327
  // setup
@@ -1481,7 +1495,7 @@ Object.defineProperty(exports, "getSwapRouterDepositResult", { enumerable: true,
1481
1495
  /**
1482
1496
  * Vault Positions
1483
1497
  */
1484
- async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, options, prefetchedReads, }) {
1498
+ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, suiWallet, options, prefetchedReads, }) {
1485
1499
  try {
1486
1500
  const tokenizedVaults = await (0, core_1.fetchTokenizedVault)(vault ? vault : undefined, options?.headers, false, false);
1487
1501
  if (!tokenizedVaults || tokenizedVaults.length === 0) {
@@ -1594,6 +1608,52 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1594
1608
  walletBalance: balance,
1595
1609
  };
1596
1610
  }
1611
+ if ((0, chain_address_1.isSuiAddress)(v.address)) {
1612
+ // The contract gives shares the deposit coin's decimals.
1613
+ const decimals = v.sui_vault_metadata?.deposit_token_decimals;
1614
+ const shareCoinType = v.sui_vault_metadata?.share_coin_type;
1615
+ const network = v.sui_vault_metadata?.network_name;
1616
+ let balance = (0, core_1.toNormalizedBn)(0, decimals ?? 0);
1617
+ let redemptions = {
1618
+ availableRedemptions: [],
1619
+ pendingRedemptions: [],
1620
+ };
1621
+ // No metadata at all: a legacy Ember/Gamma vault, nothing to read.
1622
+ if (suiWallet && (0, chain_address_1.isSuiAddress)(suiWallet) && v.sui_vault_metadata) {
1623
+ if (decimals == null || !shareCoinType || !network) {
1624
+ // Without the share type or its decimals there is nothing to
1625
+ // read or no way to scale it: fail the row, don't show zero.
1626
+ throw new errors_1.UpshiftValidationError('INVALID_INPUT', 'getVaultPositions: Sui vault is missing sui_vault_metadata share type, decimals or network', { context: { vault: v.address } });
1627
+ }
1628
+ const ref = SuiGetters.suiVaultRefFromRow(v);
1629
+ const [shares, queued] = await Promise.all([
1630
+ SuiGetters.getSuiShareBalance(suiWallet, shareCoinType, network, options.sui),
1631
+ // Shares escrowed in withdrawal requests have left the wallet.
1632
+ // A failed request read keeps the balance, as on Solana.
1633
+ ref
1634
+ ? SuiGetters.getSuiPositionRedemptions(ref, suiWallet, decimals, options.sui).catch((error) => {
1635
+ core_1.Logger.log.warn('getVaultPositions', 'Sui withdrawal requests unread — position shows the share balance only', { vault: v.address, error });
1636
+ return redemptions;
1637
+ })
1638
+ : redemptions,
1639
+ ]);
1640
+ balance = (0, core_1.toNormalizedBn)(shares, decimals);
1641
+ redemptions = queued;
1642
+ }
1643
+ return {
1644
+ vault: v.address,
1645
+ // Any queued request, waiting or claimable, marks the position
1646
+ // REDEEM, as on Solana.
1647
+ status: renderStatus([
1648
+ ...redemptions.availableRedemptions,
1649
+ ...redemptions.pendingRedemptions,
1650
+ ], balance),
1651
+ availableRedemptions: redemptions.availableRedemptions,
1652
+ pendingRedemptions: redemptions.pendingRedemptions,
1653
+ redeemable: (0, core_1.toNormalizedBn)(0),
1654
+ walletBalance: balance,
1655
+ };
1656
+ }
1597
1657
  // create provider
1598
1658
  const provider = (0, core_1.createProvider)(options.rpcUrl);
1599
1659
  // version split logic
@@ -1709,6 +1769,7 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1709
1769
  wallet,
1710
1770
  solanaWallet,
1711
1771
  stellarWallet,
1772
+ suiWallet,
1712
1773
  });
1713
1774
  throw new Error(`#getVaultPositions::${vault}:${e?.message}`);
1714
1775
  }
@@ -1897,6 +1958,14 @@ async function getVaultTvl({ vault, options, historical, }) {
1897
1958
  },
1898
1959
  ];
1899
1960
  }
1961
+ if (version === 'sui-0') {
1962
+ return [
1963
+ {
1964
+ value: (0, utils_1.backendTvlToNormalizedBn)(_vaultExists?.latest_reported_tvl, _vaultExists?.sui_vault_metadata?.deposit_token_decimals ?? 0),
1965
+ timestamp: new Date().toISOString(),
1966
+ },
1967
+ ];
1968
+ }
1900
1969
  if (version === 'stellar-0') {
1901
1970
  const stellarDecimals = _vaultExists?.stellar_vault_metadata?.deposit_token_decimals ??
1902
1971
  constants_1.STELLAR_FALLBACK_DECIMALS;
@@ -1957,7 +2026,9 @@ async function getVaultTvl({ vault, options, historical, }) {
1957
2026
  // historical tvl
1958
2027
  // check vault version early to guard non-EVM chains
1959
2028
  const version = (0, core_1.getVaultVersionV2)(_vaultExists);
1960
- if (version === 'stellar-0' || version === 'sol-0') {
2029
+ if (version === 'stellar-0' ||
2030
+ version === 'sol-0' ||
2031
+ version === 'sui-0') {
1961
2032
  core_1.Logger.log.warn('getVaultTvl:historical', 'Historical TVL not supported for non-EVM vaults', { vault, version });
1962
2033
  return [];
1963
2034
  }
@@ -2349,7 +2420,8 @@ async function getYieldLastRealizedOn({ vault, options, }) {
2349
2420
  break;
2350
2421
  }
2351
2422
  case 'sol-0':
2352
- case 'stellar-0': {
2423
+ case 'stellar-0':
2424
+ case 'sui-0': {
2353
2425
  return 0;
2354
2426
  }
2355
2427
  default: {
@@ -7,7 +7,7 @@
7
7
  * Export getters
8
8
  */
9
9
  export * from './getters';
10
- import type { IAddress, IChainId, IGetOriginInfoOptions, INormalizedNumber, IOriginInfo, IVaultHistoricalParams, IVaultPosition, IVaultUserHistoryItem } from '../../types';
10
+ import type { IAddress, IChainId, IGetOriginInfoOptions, IKycRecord, IKycStatus, IKycWalletOptions, INormalizedNumber, IOriginInfo, IVaultHistoricalParams, IVaultPosition, IVaultUserHistoryItem } from '../../types';
11
11
  import type SolanaAdapter from '../../adapters/solana';
12
12
  import { UpshiftBase, type IUpshiftBase } from '../../core';
13
13
  import { type IContractWriteOptions, type INativeDepositOptions } from './write.actions';
@@ -27,6 +27,8 @@ export declare class UpshiftVaults extends UpshiftBase {
27
27
  * vaults (see `IVaultBaseOptions.stellarRpc`).
28
28
  */
29
29
  private _stellarRpc?;
30
+ /** The SDK's `sui` config, for Sui vault reads (see `IVaultBaseOptions.sui`). */
31
+ private _sui?;
30
32
  constructor(baseConfig: IUpshiftBase, solana: SolanaAdapter);
31
33
  /**
32
34
  * @description deposit underlying token into the specified pool with adapter support. This is for when we cannot pass in a signer in sdk and need to do so as an arg
@@ -240,8 +242,10 @@ export declare class UpshiftVaults extends UpshiftBase {
240
242
  solanaWallet?: string;
241
243
  stellarWallet?: string;
242
244
  /**
243
- * Sui wallet address (`0x` + 64 hex chars). Validated now; Sui positions
244
- * are not read yet, so passing it does not add Sui vaults to the result.
245
+ * Sui wallet address (`0x` + 64 hex chars). Its share balance and its
246
+ * pending withdrawal requests (as redemptions) are read for each Sui vault:
247
+ * one balance read plus, when the SDK has the contract IDs, one object read
248
+ * (one more per further 25 requests the wallet has made on the vault).
245
249
  */
246
250
  suiWallet?: string;
247
251
  options?: IVaultBaseOptions;
@@ -408,6 +412,40 @@ export declare class UpshiftVaults extends UpshiftBase {
408
412
  * ```
409
413
  */
410
414
  getOriginInfo(options: Omit<IGetOriginInfoOptions, 'rpcUrl'>): Promise<IOriginInfo>;
415
+ /**
416
+ * Read a wallet's KYC status through this instance's provider for
417
+ * `chainId`. See {@link getKycStatus}.
418
+ *
419
+ * @param options - `chainId` and `wallet`.
420
+ * @returns The wallet's {@link IKycStatus}.
421
+ * @throws UpshiftValidationError (`INVALID_CHAIN`) when no provider is
422
+ * configured or no registry is deployed for `chainId`;
423
+ * (`INVALID_ADDRESS`) for a malformed wallet.
424
+ * @throws UpshiftSDKError when the `statusOf` read fails.
425
+ * @worstCaseRpcCalls 1
426
+ * @example
427
+ * ```ts
428
+ * const status = await upshiftSdk.getKycStatus({ chainId: 1, wallet });
429
+ * ```
430
+ */
431
+ getKycStatus(options: Omit<IKycWalletOptions, 'rpcUrl'>): Promise<IKycStatus>;
432
+ /**
433
+ * Read a wallet's raw KYC record through this instance's provider for
434
+ * `chainId`. See {@link getKycRecord}.
435
+ *
436
+ * @param options - `chainId` and `wallet`.
437
+ * @returns The wallet's {@link IKycRecord}.
438
+ * @throws UpshiftValidationError (`INVALID_CHAIN`) when no provider is
439
+ * configured or no registry is deployed for `chainId`;
440
+ * (`INVALID_ADDRESS`) for a malformed wallet.
441
+ * @throws UpshiftSDKError when the `getRecord` read fails.
442
+ * @worstCaseRpcCalls 1
443
+ * @example
444
+ * ```ts
445
+ * const record = await upshiftSdk.getKycRecord({ chainId: 1, wallet });
446
+ * ```
447
+ */
448
+ getKycRecord(options: Omit<IKycWalletOptions, 'rpcUrl'>): Promise<IKycRecord>;
411
449
  /**
412
450
  * @function getStakingPositions gets all available reward staking positions
413
451
  * @param wallet optionally passed user wallet address
@@ -77,6 +77,8 @@ class UpshiftVaults extends core_1.UpshiftBase {
77
77
  * vaults (see `IVaultBaseOptions.stellarRpc`).
78
78
  */
79
79
  _stellarRpc;
80
+ /** The SDK's `sui` config, for Sui vault reads (see `IVaultBaseOptions.sui`). */
81
+ _sui;
80
82
  constructor(baseConfig, solana) {
81
83
  super(baseConfig);
82
84
  this.solanaService = solana;
@@ -87,6 +89,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
87
89
  network: baseConfig.stellar.network ?? 'mainnet',
88
90
  }
89
91
  : undefined;
92
+ this._sui = baseConfig.sui;
90
93
  this.headers = {
91
94
  'x-environment': this.monitoring?.['x-environment'],
92
95
  'x-user-id': this.monitoring?.['x-user-id'],
@@ -134,8 +137,10 @@ class UpshiftVaults extends core_1.UpshiftBase {
134
137
  // if (!(this.authorized && this.upshiftKey)) // @todo: commented out for integrators
135
138
  const allVaults = await (0, core_1.fetchTokenizedVaults)(undefined, this.headers, options?.loadSubaccounts, options?.loadSnapshots);
136
139
  const vaultsPerAvailableProviders = allVaults.filter((v) =>
137
- // Stellar vaults are backend-only (no RPC provider required)
140
+ // Stellar and Sui vaults use their own endpoints, not this.providers.
141
+ // Sui rows without sui_vault_metadata are legacy Ember/Gamma vaults.
138
142
  v?.chain_type === 'stellar' ||
143
+ (v?.chain_type === 'sui' && !!v.sui_vault_metadata) ||
139
144
  // Solana vaults use this.solanaService (not this.providers). Without
140
145
  // an explicit pass-through here they get silently dropped on any
141
146
  // instance whose ACTIVE_RPC_URLS() doesn't register chainId -1.
@@ -202,6 +207,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
202
207
  rpcUrl,
203
208
  solanaService: this.solanaService,
204
209
  stellarRpc: this._stellarRpc,
210
+ sui: this._sui,
205
211
  env: this.monitoring?.env,
206
212
  upshiftKey: this.keys?.upshift,
207
213
  subgraphKey: this.keys?.graph,
@@ -294,6 +300,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
294
300
  rpcUrl: this.providers?.[v.chain],
295
301
  solanaService: this.solanaService,
296
302
  stellarRpc: this._stellarRpc,
303
+ sui: this._sui,
297
304
  env: this.monitoring?.env,
298
305
  upshiftKey: this.keys?.upshift,
299
306
  subgraphKey: this.keys?.graph,
@@ -361,7 +368,6 @@ class UpshiftVaults extends core_1.UpshiftBase {
361
368
  // `Vault input parameter is not an address: ${String(vault)}`,
362
369
  // );
363
370
  (0, core_1.assertKnownChainId)(chainId, this.providers, 'getVault');
364
- (0, core_1.assertSuiReadsSupported)(chainId, vault, 'getVault');
365
371
  (0, core_1.assertEvmProviderConfigured)(chainId, this.providers, 'getVault');
366
372
  // get vault data
367
373
  const vaultResponse = await (0, getters_1.getVault)({
@@ -376,6 +382,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
376
382
  : this.activeNetwork?.rpcUrl,
377
383
  solanaService: this.solanaService,
378
384
  stellarRpc: this._stellarRpc,
385
+ sui: this._sui,
379
386
  env: this.monitoring?.env,
380
387
  upshiftKey: this.keys?.upshift,
381
388
  subgraphKey: this.keys?.graph,
@@ -404,6 +411,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
404
411
  : this.activeNetwork?.rpcUrl,
405
412
  solanaService: this.solanaService,
406
413
  stellarRpc: this._stellarRpc,
414
+ sui: this._sui,
407
415
  env: this.monitoring?.env,
408
416
  upshiftKey: this.keys?.upshift,
409
417
  subgraphKey: this.keys?.graph,
@@ -453,6 +461,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
453
461
  chainId: chainId,
454
462
  solanaService: this.solanaService,
455
463
  stellarRpc: this._stellarRpc,
464
+ sui: this._sui,
456
465
  headers: this.headers,
457
466
  });
458
467
  return vaultResponse;
@@ -486,6 +495,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
486
495
  chainId: chainId,
487
496
  solanaService: this.solanaService,
488
497
  stellarRpc: this._stellarRpc,
498
+ sui: this._sui,
489
499
  headers: this.headers,
490
500
  });
491
501
  return vaultResponse;
@@ -519,6 +529,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
519
529
  : this.activeNetwork?.rpcUrl,
520
530
  solanaService: this.solanaService,
521
531
  stellarRpc: this._stellarRpc,
532
+ sui: this._sui,
522
533
  env: this.monitoring?.env,
523
534
  upshiftKey: this.keys?.upshift,
524
535
  subgraphKey: this.keys?.graph,
@@ -601,6 +612,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
601
612
  throw new Error('Vault input parameter is undefined.');
602
613
  if (!(0, ethers_1.isAddress)(vault) &&
603
614
  !(0, utils_2.isStellarAddress)(vault) &&
615
+ !(0, chain_address_1.isSuiAddress)(vault) &&
604
616
  !utils_1.SolanaUtils.isSolanaAddress(vault))
605
617
  throw new Error(`Vault input parameter is not an address: ${String(vault)}`);
606
618
  return await (0, getters_1.getVaultAvailableRedemptions)({
@@ -612,6 +624,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
612
624
  : this.activeNetwork?.rpcUrl,
613
625
  solanaService: this.solanaService,
614
626
  stellarRpc: this._stellarRpc,
627
+ sui: this._sui,
615
628
  env: this.monitoring?.env,
616
629
  upshiftKey: this.keys?.upshift,
617
630
  subgraphKey: this.keys?.graph,
@@ -654,7 +667,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
654
667
  throw new Error('Not authorized.');
655
668
  if (!vault)
656
669
  throw new Error('Vault input parameter is undefined.');
657
- if (!(0, ethers_1.isAddress)(vault) && !(0, utils_2.isStellarAddress)(vault)) {
670
+ if (!(0, ethers_1.isAddress)(vault) && !(0, utils_2.isStellarAddress)(vault) && !(0, chain_address_1.isSuiAddress)(vault)) {
658
671
  throw new Error(`Vault input parameter is not an address: ${String(vault)}`);
659
672
  }
660
673
  return await (0, getters_1.getVaultRedemptionHistory)({
@@ -705,12 +718,14 @@ class UpshiftVaults extends core_1.UpshiftBase {
705
718
  wallet,
706
719
  solanaWallet,
707
720
  stellarWallet,
721
+ suiWallet,
708
722
  options: {
709
723
  rpcUrl: chainId
710
724
  ? this.providers?.[chainId]
711
725
  : this.activeNetwork?.rpcUrl,
712
726
  solanaService: this.solanaService,
713
727
  stellarRpc: this._stellarRpc,
728
+ sui: this._sui,
714
729
  env: this.monitoring?.env,
715
730
  upshiftKey: this.keys?.upshift,
716
731
  subgraphKey: this.keys?.graph,
@@ -723,7 +738,9 @@ class UpshiftVaults extends core_1.UpshiftBase {
723
738
  }
724
739
  const allVaults = await (0, core_1.fetchTokenizedVaults)(undefined, this.headers, false, false);
725
740
  if (chainId) {
726
- const vaultsPerChain = allVaults.filter((v) => v.chain === chainId);
741
+ // Sui rows without sui_vault_metadata are legacy Ember/Gamma vaults.
742
+ const vaultsPerChain = allVaults.filter((v) => v.chain === chainId &&
743
+ !(v.chain_type === 'sui' && !v.sui_vault_metadata));
727
744
  // Batch balanceOf/lagDuration via Multicall3 before the per-vault
728
745
  // fan-out; un-batched vaults fall back to their own reads.
729
746
  const prefetchedReads = await (0, prefetch_1.prefetchVaultPositionReads)({
@@ -735,11 +752,13 @@ class UpshiftVaults extends core_1.UpshiftBase {
735
752
  vault: v.address,
736
753
  solanaWallet,
737
754
  stellarWallet,
755
+ suiWallet,
738
756
  wallet,
739
757
  options: {
740
758
  rpcUrl: this.providers?.[v.chain],
741
759
  solanaService: this.solanaService,
742
760
  stellarRpc: this._stellarRpc,
761
+ sui: this._sui,
743
762
  env: this.monitoring?.env,
744
763
  upshiftKey: this.keys?.upshift,
745
764
  subgraphKey: this.keys?.graph,
@@ -757,8 +776,10 @@ class UpshiftVaults extends core_1.UpshiftBase {
757
776
  return final;
758
777
  }
759
778
  const vaultsPerAvailableProviders = allVaults.filter((v) =>
760
- // Stellar vaults are backend-only (no RPC provider required)
779
+ // Stellar and Sui vaults use their own endpoints, not this.providers.
780
+ // Sui rows without sui_vault_metadata are legacy Ember/Gamma vaults.
761
781
  v?.chain_type === 'stellar' ||
782
+ (v?.chain_type === 'sui' && !!v.sui_vault_metadata) ||
762
783
  // Solana vaults use this.solanaService (not this.providers). Without
763
784
  // this clause every Solana position is dropped on any instance where
764
785
  // ACTIVE_RPC_URLS() doesn't register chainId -1 — which is exactly
@@ -779,11 +800,13 @@ class UpshiftVaults extends core_1.UpshiftBase {
779
800
  vault: v.address,
780
801
  solanaWallet,
781
802
  stellarWallet,
803
+ suiWallet,
782
804
  wallet,
783
805
  options: {
784
806
  rpcUrl: this.providers?.[v.chain],
785
807
  solanaService: this.solanaService,
786
808
  stellarRpc: this._stellarRpc,
809
+ sui: this._sui,
787
810
  env: this.monitoring?.env,
788
811
  upshiftKey: this.keys?.upshift,
789
812
  subgraphKey: this.keys?.graph,
@@ -963,6 +986,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
963
986
  : this.requireActiveNetwork().rpcUrl,
964
987
  solanaService: this.solanaService,
965
988
  stellarRpc: this._stellarRpc,
989
+ sui: this._sui,
966
990
  env: this.monitoring?.env,
967
991
  upshiftKey: this.keys?.upshift,
968
992
  subgraphKey: this.keys?.graph,
@@ -989,6 +1013,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
989
1013
  : this.requireActiveNetwork().rpcUrl,
990
1014
  solanaService: this.solanaService,
991
1015
  stellarRpc: this._stellarRpc,
1016
+ sui: this._sui,
992
1017
  env: this.monitoring?.env,
993
1018
  upshiftKey: this.keys?.upshift,
994
1019
  subgraphKey: this.keys?.graph,
@@ -1208,6 +1233,52 @@ class UpshiftVaults extends core_1.UpshiftBase {
1208
1233
  rpcUrl: this.providers[options.chainId],
1209
1234
  });
1210
1235
  }
1236
+ /**
1237
+ * Read a wallet's KYC status through this instance's provider for
1238
+ * `chainId`. See {@link getKycStatus}.
1239
+ *
1240
+ * @param options - `chainId` and `wallet`.
1241
+ * @returns The wallet's {@link IKycStatus}.
1242
+ * @throws UpshiftValidationError (`INVALID_CHAIN`) when no provider is
1243
+ * configured or no registry is deployed for `chainId`;
1244
+ * (`INVALID_ADDRESS`) for a malformed wallet.
1245
+ * @throws UpshiftSDKError when the `statusOf` read fails.
1246
+ * @worstCaseRpcCalls 1
1247
+ * @example
1248
+ * ```ts
1249
+ * const status = await upshiftSdk.getKycStatus({ chainId: 1, wallet });
1250
+ * ```
1251
+ */
1252
+ async getKycStatus(options) {
1253
+ (0, core_1.assertEvmProviderConfigured)(options.chainId, this.providers, 'getKycStatus');
1254
+ return (0, core_1.getKycStatus)({
1255
+ ...options,
1256
+ rpcUrl: this.providers[options.chainId],
1257
+ });
1258
+ }
1259
+ /**
1260
+ * Read a wallet's raw KYC record through this instance's provider for
1261
+ * `chainId`. See {@link getKycRecord}.
1262
+ *
1263
+ * @param options - `chainId` and `wallet`.
1264
+ * @returns The wallet's {@link IKycRecord}.
1265
+ * @throws UpshiftValidationError (`INVALID_CHAIN`) when no provider is
1266
+ * configured or no registry is deployed for `chainId`;
1267
+ * (`INVALID_ADDRESS`) for a malformed wallet.
1268
+ * @throws UpshiftSDKError when the `getRecord` read fails.
1269
+ * @worstCaseRpcCalls 1
1270
+ * @example
1271
+ * ```ts
1272
+ * const record = await upshiftSdk.getKycRecord({ chainId: 1, wallet });
1273
+ * ```
1274
+ */
1275
+ async getKycRecord(options) {
1276
+ (0, core_1.assertEvmProviderConfigured)(options.chainId, this.providers, 'getKycRecord');
1277
+ return (0, core_1.getKycRecord)({
1278
+ ...options,
1279
+ rpcUrl: this.providers[options.chainId],
1280
+ });
1281
+ }
1211
1282
  /**
1212
1283
  * @function getStakingPositions gets all available reward staking positions
1213
1284
  * @param wallet optionally passed user wallet address
@@ -1243,7 +1314,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
1243
1314
  throw new Error('Not authorized.');
1244
1315
  if (!vault)
1245
1316
  throw new Error('Pool input parameter is undefined.');
1246
- if (!(0, ethers_1.isAddress)(vault) && !(0, utils_2.isStellarAddress)(vault))
1317
+ if (!(0, ethers_1.isAddress)(vault) && !(0, utils_2.isStellarAddress)(vault) && !(0, chain_address_1.isSuiAddress)(vault))
1247
1318
  throw new Error(`Pool input parameter is not an address: ${String(vault)}`);
1248
1319
  const resolvedChainId = chainId ?? this.activeNetwork?.chainId;
1249
1320
  const rpcUrl = chainId
@@ -1256,6 +1327,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
1256
1327
  chainId: resolvedChainId,
1257
1328
  solanaService: this.solanaService,
1258
1329
  stellarRpc: this._stellarRpc,
1330
+ sui: this._sui,
1259
1331
  env: this.monitoring?.env,
1260
1332
  upshiftKey: this.keys?.upshift,
1261
1333
  subgraphKey: this.keys?.graph,
@@ -1280,6 +1352,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
1280
1352
  rpcUrl: rpcUrl,
1281
1353
  solanaService: this.solanaService,
1282
1354
  stellarRpc: this._stellarRpc,
1355
+ sui: this._sui,
1283
1356
  env: this.monitoring?.env,
1284
1357
  upshiftKey: this.keys?.upshift,
1285
1358
  subgraphKey: this.keys?.graph,
@@ -1328,6 +1401,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
1328
1401
  : rpcUrl || this.requireActiveNetwork().rpcUrl,
1329
1402
  solanaService: this.solanaService,
1330
1403
  stellarRpc: this._stellarRpc,
1404
+ sui: this._sui,
1331
1405
  env: this.monitoring?.env,
1332
1406
  upshiftKey: this.keys?.upshift,
1333
1407
  subgraphKey: this.keys?.graph,
@@ -1602,6 +1676,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
1602
1676
  rpcUrl: chainId ? this.providers?.[chainId] : this.activeNetwork.rpcUrl,
1603
1677
  solanaService: this.solanaService,
1604
1678
  stellarRpc: this._stellarRpc,
1679
+ sui: this._sui,
1605
1680
  env: this.monitoring?.env,
1606
1681
  upshiftKey: this.keys?.upshift,
1607
1682
  subgraphKey: this.keys?.graph,
@@ -1655,6 +1730,7 @@ class UpshiftVaults extends core_1.UpshiftBase {
1655
1730
  rpcUrl,
1656
1731
  solanaService: this.solanaService,
1657
1732
  stellarRpc: this._stellarRpc,
1733
+ sui: this._sui,
1658
1734
  env: this.monitoring?.env,
1659
1735
  upshiftKey: this.keys?.upshift,
1660
1736
  subgraphKey: this.keys?.graph,
@@ -1,5 +1,5 @@
1
1
  import type { Connection } from '@solana/web3.js';
2
- import type { IAddress, IEnv, ISolanaNetwork, IStellarNetwork, IWSMonitorHeaders } from '../../types';
2
+ import type { IAddress, IEnv, ISolanaNetwork, IStellarNetwork, ISuiConfig, IWSMonitorHeaders } from '../../types';
3
3
  /**
4
4
  * Structural interface for the Solana adapter surface used by vault operations.
5
5
  * Avoids importing the concrete SolanaAdapter class to prevent circular dependencies.
@@ -63,6 +63,12 @@ export interface IVaultBaseOptions {
63
63
  rpcUrl: string;
64
64
  network: IStellarNetwork;
65
65
  };
66
+ /**
67
+ * The SDK's `sui` config for Sui vault reads: endpoint override and contract
68
+ * IDs. Applied only to vaults on its `network`; other Sui vaults use the
69
+ * built-in endpoint and contract IDs.
70
+ */
71
+ sui?: ISuiConfig;
66
72
  headers?: IWSMonitorHeaders;
67
73
  /**
68
74
  * Portfolio mode: when true, the per-vault EVM getter does NOT null out a
@@ -209,7 +209,8 @@ async function getYieldLastRealizedOn(provider, vaultAddress) {
209
209
  break;
210
210
  }
211
211
  case 'sol-0':
212
- case 'stellar-0': {
212
+ case 'stellar-0':
213
+ case 'sui-0': {
213
214
  return 0;
214
215
  }
215
216
  default: {
@@ -392,6 +393,7 @@ function buildBackendVault(tokenizedVault, overrides) {
392
393
  isFeatured: tokenizedVault.is_featured || false,
393
394
  isSpotlighted: tokenizedVault.is_spotlighted ?? false,
394
395
  withdrawalOnly: tokenizedVault.withdrawal_only ?? false,
396
+ requiresKyc: tokenizedVault.requires_kyc ?? false,
395
397
  isVisible: tokenizedVault.is_visible || false,
396
398
  reserveTarget: tokenizedVault.reserve_target || 0,
397
399
  reserveTolerance: tokenizedVault.reserve_tolerance || 0,
@@ -527,6 +529,7 @@ async function buildFormattedVault(provider, tokenizedVault, contractCalls) {
527
529
  isFeatured: tokenizedVault.is_featured,
528
530
  withdrawalOnly: tokenizedVault.withdrawal_only ?? false,
529
531
  isSpotlighted: tokenizedVault.is_spotlighted ?? false,
532
+ requiresKyc: tokenizedVault.requires_kyc ?? false,
530
533
  isVisible: tokenizedVault.is_visible,
531
534
  reserveTarget: tokenizedVault.reserve_target,
532
535
  reserveTolerance: tokenizedVault.reserve_tolerance,