@upshiftfinance/sdk 0.3.0 → 0.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 (54) hide show
  1. package/README.md +1 -1
  2. package/lib/abis/KycRegistry.d.ts +109 -0
  3. package/lib/abis/KycRegistry.js +73 -0
  4. package/lib/abis/index.d.ts +1 -0
  5. package/lib/abis/index.js +1 -0
  6. package/lib/adapters/sui/actions.d.ts +174 -0
  7. package/lib/adapters/sui/actions.js +382 -0
  8. package/lib/adapters/sui/getters.d.ts +166 -0
  9. package/lib/adapters/sui/getters.js +391 -0
  10. package/lib/adapters/sui/index.d.ts +95 -2
  11. package/lib/adapters/sui/index.js +92 -2
  12. package/lib/adapters/sui/targets.d.ts +35 -0
  13. package/lib/adapters/sui/targets.js +35 -0
  14. package/lib/core/analytics/method-taxonomy.d.ts +1 -1
  15. package/lib/core/analytics/method-taxonomy.js +7 -0
  16. package/lib/core/analytics/version.d.ts +1 -1
  17. package/lib/core/analytics/version.js +1 -1
  18. package/lib/core/constants/core.d.ts +5 -0
  19. package/lib/core/constants/core.js +5 -0
  20. package/lib/core/constants/kyc.d.ts +9 -0
  21. package/lib/core/constants/kyc.js +12 -0
  22. package/lib/core/constants/web3.d.ts +2 -2
  23. package/lib/core/constants/web3.js +9 -2
  24. package/lib/core/errors/index.d.ts +77 -1
  25. package/lib/core/errors/index.js +94 -1
  26. package/lib/core/fetcher.d.ts +5 -0
  27. package/lib/core/fetcher.js +1 -1
  28. package/lib/core/helpers/chain-support.d.ts +2 -2
  29. package/lib/core/helpers/chain-support.js +3 -3
  30. package/lib/core/helpers/kyc.d.ts +47 -0
  31. package/lib/core/helpers/kyc.js +111 -0
  32. package/lib/core/helpers/revert-decode.js +3 -2
  33. package/lib/core/index.d.ts +2 -0
  34. package/lib/core/index.js +2 -0
  35. package/lib/main.d.ts +31 -3
  36. package/lib/main.js +32 -0
  37. package/lib/modules/api/kyc.d.ts +4 -0
  38. package/lib/modules/api/kyc.js +148 -0
  39. package/lib/modules/api/main.d.ts +63 -1
  40. package/lib/modules/api/main.js +64 -0
  41. package/lib/modules/vaults/getters.d.ts +3 -1
  42. package/lib/modules/vaults/getters.js +53 -9
  43. package/lib/modules/vaults/main.d.ts +39 -3
  44. package/lib/modules/vaults/main.js +79 -5
  45. package/lib/modules/vaults/types.d.ts +7 -1
  46. package/lib/modules/vaults/utils.js +4 -1
  47. package/lib/sdk.d.ts +15131 -14393
  48. package/lib/types/index.d.ts +1 -0
  49. package/lib/types/index.js +1 -0
  50. package/lib/types/kyc.d.ts +61 -0
  51. package/lib/types/kyc.js +3 -0
  52. package/lib/types/vaults.d.ts +2 -0
  53. package/lib/types/webserver.d.ts +5 -0
  54. package/package.json +1 -1
@@ -0,0 +1,382 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.suiExecutionErrorToSdkError = suiExecutionErrorToSdkError;
37
+ exports.buildSuiDepositTransaction = buildSuiDepositTransaction;
38
+ exports.buildSuiRedeemTransaction = buildSuiRedeemTransaction;
39
+ exports.submitSuiTransaction = submitSuiTransaction;
40
+ const errors_1 = require("../../core/errors");
41
+ const chain_address_1 = require("../../core/helpers/chain-address");
42
+ const curator_alert_1 = require("../../core/logger/curator-alert");
43
+ const client_1 = require("./client");
44
+ const constants_1 = require("./constants");
45
+ const getters_1 = require("./getters");
46
+ const targets_1 = require("./targets");
47
+ const U64_MAX = 2n ** 64n - 1n;
48
+ /** Contract errors with a stable SDK reason, keyed `module::constant`. */
49
+ const ABORT_REASONS = {
50
+ 'vault::EPaused': 'paused',
51
+ 'vault::EBelowMinDeposit': 'below_min_deposit',
52
+ 'vault::EAboveMaxDeposit': 'above_max_deposit',
53
+ 'vault::EDepositCapExceeded': 'deposit_cap_exceeded',
54
+ 'vault::EAboveMaxWithdrawal': 'above_max_withdrawal',
55
+ 'vault::EInsufficientLiquidity': 'insufficient_liquidity',
56
+ 'vault::EQueueAttached': 'queue_attached',
57
+ 'vault::ESlippageExceeded': 'slippage',
58
+ 'vault::EZeroShares': 'zero_output',
59
+ 'vault::EZeroAssets': 'zero_output',
60
+ 'versioning::EVersionRetired': 'version_retired',
61
+ };
62
+ /**
63
+ * Map a failed Sui execution to an SDK error: a contract abort becomes an
64
+ * {@link UpshiftVaultAbortError} with a stable reason, anything else an
65
+ * {@link UpshiftSDKError} (`UNKNOWN`).
66
+ *
67
+ * @param executionError - `effects.status.error` of a failed transaction, or
68
+ * the `executionError` of a `SimulationError`.
69
+ * @param context - Structured context for the error (e.g. network, digest).
70
+ * @internal
71
+ */
72
+ function suiExecutionErrorToSdkError(executionError, context = {}) {
73
+ const abort = executionError?.MoveAbort;
74
+ if (abort) {
75
+ const module = abort.location?.module;
76
+ const constant = abort.cleverError?.constantName;
77
+ const reason = ABORT_REASONS[`${module}::${constant}`] ?? 'other';
78
+ return new errors_1.UpshiftVaultAbortError(reason, `Sui vault rejected the transaction: ${reason}${constant ? ` (${module}::${constant})` : ` (abort ${abort.abortCode})`}.`, { module, constant }, { context: { ...context, abortCode: abort.abortCode } });
79
+ }
80
+ return new errors_1.UpshiftSDKError('UNKNOWN', `Sui transaction failed: ${executionError?.message ?? 'unknown error'}`, { context });
81
+ }
82
+ function assertSender(sender, method) {
83
+ if (!(0, chain_address_1.isSuiAddress)(sender)) {
84
+ throw new errors_1.UpshiftValidationError('INVALID_ADDRESS', `${method}: sender must be a Sui address (0x + 64 hex chars).`);
85
+ }
86
+ }
87
+ function assertAmount(value, method, name, positive) {
88
+ if (value === undefined)
89
+ return;
90
+ if (typeof value !== 'bigint' ||
91
+ value < (positive ? 1n : 0n) ||
92
+ value > U64_MAX) {
93
+ throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${method}: ${name} must be a bigint between ${positive ? 1 : 0} and 2^64 - 1.`);
94
+ }
95
+ }
96
+ /** Move-call helper bound to one vault and its contracts. */
97
+ function vaultCalls(tx, ref, contracts) {
98
+ const typeArguments = (0, targets_1.suiVaultTypeArguments)(ref.assetCoinType, ref.shareCoinType);
99
+ return (target, args) => tx.moveCall({
100
+ target: (0, targets_1.suiMoveCallTarget)(contracts, target),
101
+ typeArguments,
102
+ arguments: [
103
+ tx.object(ref.vaultId),
104
+ tx.object(contracts.registryId),
105
+ ...args,
106
+ ],
107
+ });
108
+ }
109
+ /**
110
+ * Dry-run `tx` against the network and return each command's return values.
111
+ * An abort, at build (gas estimation) or in the simulation, becomes a typed
112
+ * SDK error; `onAbort` sees it first.
113
+ */
114
+ async function dryRun(config, build, method, onAbort) {
115
+ const context = { network: config.network, method };
116
+ try {
117
+ return await (0, client_1.withSuiClient)((0, client_1.resolveSuiNetworkConfig)(config), async (client) => {
118
+ const result = await client.core.simulateTransaction({
119
+ transaction: await build(),
120
+ include: { commandResults: true, effects: true },
121
+ });
122
+ if (result.$kind !== 'Transaction') {
123
+ throw suiExecutionErrorToSdkError(result.FailedTransaction.effects?.status.error ?? undefined, context);
124
+ }
125
+ return result.commandResults.map((c) => c.returnValues.map((v) => v.bcs));
126
+ });
127
+ }
128
+ catch (err) {
129
+ const sdkError = err instanceof errors_1.UpshiftSDKError
130
+ ? err
131
+ : err?.executionError
132
+ ? suiExecutionErrorToSdkError(err.executionError, context)
133
+ : new errors_1.UpshiftValidationError('INVALID_INPUT', `${method}: could not build the transaction: ${err instanceof Error ? err.message : String(err)}`, { cause: err, context });
134
+ if (sdkError instanceof errors_1.UpshiftVaultAbortError)
135
+ onAbort?.(sdkError);
136
+ throw sdkError;
137
+ }
138
+ }
139
+ /**
140
+ * Build an unsigned deposit: charge the management fee, deposit with a minimum
141
+ * share amount, and send the shares to the sender — one transaction.
142
+ *
143
+ * The payment is `coinWithBalance(Asset)`: the wallet selects and merges the
144
+ * sender's coins when it signs. The fee is charged first so the deposit is
145
+ * priced on a current NAV.
146
+ *
147
+ * RPC cost: one dry run (plus the coin lookup it needs).
148
+ *
149
+ * @param params - Vault, amount, sender and optional minimum shares.
150
+ * @param sui - The SDK's `sui` config; applied only for `params.vault.network`.
151
+ * @returns The unsigned transaction, the shares the dry run minted and the
152
+ * minimum it enforces.
153
+ * @throws {@link UpshiftValidationError} for a malformed sender or vault, an
154
+ * out-of-range amount, unknown contract IDs, or a transaction that cannot be
155
+ * built (e.g. the sender lacks the asset).
156
+ * @throws {@link UpshiftVaultAbortError} when the vault would reject the
157
+ * deposit (`paused`, `below_min_deposit`, `above_max_deposit`,
158
+ * `deposit_cap_exceeded`, `zero_output`, `slippage`, `version_retired`).
159
+ * @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
160
+ * @example
161
+ * ```ts
162
+ * const { transaction } = await buildSuiDepositTransaction(
163
+ * { vault: ref, amount: 1_000_000n, sender: account.address },
164
+ * sdkSuiConfig,
165
+ * );
166
+ * const { digest } = await dAppKit.signAndExecuteTransaction({ transaction });
167
+ * ```
168
+ */
169
+ async function buildSuiDepositTransaction(params, sui) {
170
+ const method = 'buildSuiDepositTransaction';
171
+ const { vault: ref, amount, sender, minSharesOut } = params;
172
+ assertSender(sender, method);
173
+ if (!(0, chain_address_1.isSuiAddress)(ref?.vaultId)) {
174
+ throw new errors_1.UpshiftValidationError('INVALID_ADDRESS', `${method}: vault.vaultId must be a Sui object ID.`);
175
+ }
176
+ assertAmount(amount, method, 'amount', true);
177
+ assertAmount(minSharesOut, method, 'minSharesOut', false);
178
+ const config = (0, getters_1.suiConfigForNetwork)(ref.network, sui);
179
+ const contracts = (0, targets_1.resolveSuiVaultContracts)(config);
180
+ const { Transaction: SuiTransaction, coinWithBalance } = await Promise.resolve().then(() => __importStar(require('@mysten/sui/transactions')));
181
+ const compose = (min, withPreview) => {
182
+ const tx = new SuiTransaction();
183
+ tx.setSender(sender);
184
+ const call = vaultCalls(tx, ref, contracts);
185
+ call('chargeManagementFee', [tx.object(constants_1.SUI_CLOCK_ID)]);
186
+ if (withPreview)
187
+ call('previewDeposit', [tx.pure.u64(amount)]);
188
+ const payment = tx.add(coinWithBalance({ type: ref.assetCoinType, balance: amount }));
189
+ const shares = call('depositChecked', [payment, tx.pure.u64(min)]);
190
+ tx.transferObjects([shares], sender);
191
+ return tx;
192
+ };
193
+ // The preview runs after the fee charge, so it matches the deposit exactly.
194
+ const results = await dryRun(config, async () => compose(0n, true), method);
195
+ const expectedShares = (0, getters_1.decodeSuiUint)(results[1][0], 8);
196
+ const min = minSharesOut ?? expectedShares;
197
+ return {
198
+ transaction: compose(min, false),
199
+ expectedShares,
200
+ minSharesOut: min,
201
+ };
202
+ }
203
+ /**
204
+ * Build an unsigned instant redemption: redeem shares with a minimum net
205
+ * asset amount and send the assets to the sender — one transaction.
206
+ *
207
+ * The shares are `coinWithBalance(Share)`. A vault with a withdrawal queue
208
+ * attached has instant redemption off; that fails here with `queue_attached`.
209
+ *
210
+ * Side effect on failure: when the vault rejects the dry run, the failure is
211
+ * reported to that vault's curator (fire-and-forget; see
212
+ * `monitoring.curatorAlerts`).
213
+ *
214
+ * RPC cost: one dry run (plus the coin lookup it needs).
215
+ *
216
+ * @param params - Vault, shares, sender and optional minimum assets.
217
+ * @param sui - The SDK's `sui` config; applied only for `params.vault.network`.
218
+ * @returns The unsigned transaction, the dry run's gross and net assets and
219
+ * the minimum it enforces.
220
+ * @throws {@link UpshiftValidationError} for a malformed sender or vault, an
221
+ * out-of-range amount, unknown contract IDs, or a transaction that cannot be
222
+ * built (e.g. the sender lacks the shares).
223
+ * @throws {@link UpshiftVaultAbortError} when the vault would reject the
224
+ * redemption (`queue_attached`, `paused`, `above_max_withdrawal`,
225
+ * `insufficient_liquidity`, `zero_output`, `slippage`, `version_retired`).
226
+ * @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
227
+ */
228
+ async function buildSuiRedeemTransaction(params, sui) {
229
+ const method = 'buildSuiRedeemTransaction';
230
+ const { vault: ref, shares, sender, minAssetsOut } = params;
231
+ assertSender(sender, method);
232
+ if (!(0, chain_address_1.isSuiAddress)(ref?.vaultId)) {
233
+ throw new errors_1.UpshiftValidationError('INVALID_ADDRESS', `${method}: vault.vaultId must be a Sui object ID.`);
234
+ }
235
+ assertAmount(shares, method, 'shares', true);
236
+ assertAmount(minAssetsOut, method, 'minAssetsOut', false);
237
+ const config = (0, getters_1.suiConfigForNetwork)(ref.network, sui);
238
+ const contracts = (0, targets_1.resolveSuiVaultContracts)(config);
239
+ const { Transaction: SuiTransaction, coinWithBalance } = await Promise.resolve().then(() => __importStar(require('@mysten/sui/transactions')));
240
+ const compose = (min, withPreview) => {
241
+ const tx = new SuiTransaction();
242
+ tx.setSender(sender);
243
+ const call = vaultCalls(tx, ref, contracts);
244
+ if (withPreview) {
245
+ call('previewRedemption', [tx.pure.u64(shares), tx.pure.bool(true)]);
246
+ }
247
+ const payment = tx.add(coinWithBalance({ type: ref.shareCoinType, balance: shares }));
248
+ const assets = call('redeemChecked', [payment, tx.pure.u64(min)]);
249
+ tx.transferObjects([assets], sender);
250
+ return tx;
251
+ };
252
+ const results = await dryRun(config, async () => compose(0n, true), method, (err) => (0, curator_alert_1.reportRedeemFailure)({
253
+ phase: 'simulation',
254
+ chain: 'sui',
255
+ network: ref.network,
256
+ contractId: ref.vaultId,
257
+ eoa: sender,
258
+ sharesRaw: shares.toString(),
259
+ error: err.message,
260
+ }));
261
+ const expectedGrossAssets = (0, getters_1.decodeSuiUint)(results[0][0], 8);
262
+ const expectedAssets = (0, getters_1.decodeSuiUint)(results[0][1], 8);
263
+ const min = minAssetsOut ?? expectedAssets;
264
+ return {
265
+ transaction: compose(min, false),
266
+ expectedGrossAssets,
267
+ expectedAssets,
268
+ minAssetsOut: min,
269
+ };
270
+ }
271
+ /**
272
+ * The vault, sender and share amount of an instant redemption in a built
273
+ * transaction, for the curator alert; `null` when it is not one.
274
+ */
275
+ function redemptionOf(data, fromBase64) {
276
+ for (const command of data.commands) {
277
+ const call = command.MoveCall;
278
+ if (call?.module !== 'coin_entry' || call.function !== 'redeem_checked')
279
+ continue;
280
+ const vaultArg = call.arguments[0];
281
+ const vaultInput = vaultArg?.$kind === 'Input' ? data.inputs[vaultArg.Input] : undefined;
282
+ const vaultId = vaultInput?.Object?.SharedObject?.objectId;
283
+ if (!vaultId)
284
+ return null;
285
+ // The shares are usually split off the sender's coins; read that amount.
286
+ let sharesRaw = '0';
287
+ const coinArg = call.arguments[2];
288
+ const source = coinArg?.$kind === 'NestedResult' || coinArg?.$kind === 'Result'
289
+ ? data.commands[coinArg.$kind === 'Result'
290
+ ? coinArg.Result
291
+ : coinArg.NestedResult[0]]
292
+ : undefined;
293
+ const amountArg = source?.SplitCoins?.amounts[0];
294
+ const amountInput = amountArg?.$kind === 'Input' ? data.inputs[amountArg.Input] : undefined;
295
+ const bytes = amountInput?.Pure?.bytes;
296
+ if (bytes) {
297
+ const raw = fromBase64(bytes);
298
+ if (raw.length === 8)
299
+ sharesRaw = (0, getters_1.decodeSuiUint)(raw, 8).toString();
300
+ }
301
+ return { vaultId, sharesRaw };
302
+ }
303
+ return null;
304
+ }
305
+ /**
306
+ * Execute a signed transaction and wait until the network has indexed it.
307
+ *
308
+ * Side effect on failure: a failed instant redemption is reported to that
309
+ * vault's curator with its digest (fire-and-forget; see
310
+ * `monitoring.curatorAlerts`).
311
+ *
312
+ * RPC cost: one execution plus the confirmation poll.
313
+ *
314
+ * @param signed - Bytes and signature from the wallet's `signTransaction`.
315
+ * @param network - Network the transaction was built for.
316
+ * @param sui - The SDK's `sui` config; applied only for `network`.
317
+ * @returns The transaction digest once it succeeded and is indexed.
318
+ * @throws {@link UpshiftVaultAbortError} when the vault aborted it on chain.
319
+ * @throws {@link UpshiftSDKError} (`UNKNOWN`) when it failed for another
320
+ * reason; `context.digest` names it.
321
+ * @throws {@link UpshiftTransactionError} when it executed but was not
322
+ * indexed in time; check `signature` (the digest) before retrying.
323
+ * @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
324
+ */
325
+ async function submitSuiTransaction(signed, network, sui) {
326
+ if (typeof signed?.bytes !== 'string' ||
327
+ typeof signed.signature !== 'string') {
328
+ throw new errors_1.UpshiftValidationError('INVALID_INPUT', 'submitSuiTransaction: pass { bytes, signature } from the wallet, both base64.');
329
+ }
330
+ const config = (0, getters_1.suiConfigForNetwork)(network, sui);
331
+ const networkConfig = (0, client_1.resolveSuiNetworkConfig)(config);
332
+ const { Transaction: SuiTransaction } = await Promise.resolve().then(() => __importStar(require('@mysten/sui/transactions')));
333
+ const { fromBase64 } = await Promise.resolve().then(() => __importStar(require('@mysten/sui/utils')));
334
+ const bytes = fromBase64(signed.bytes);
335
+ // Executing the same signed bytes twice is idempotent, so endpoint failover is safe.
336
+ const result = await (0, client_1.withSuiClient)(networkConfig, (client) => client.core.executeTransaction({
337
+ transaction: bytes,
338
+ signatures: [signed.signature],
339
+ include: { effects: true },
340
+ })).catch((err) => {
341
+ if (err instanceof errors_1.UpshiftSDKError)
342
+ throw err;
343
+ // The node refused it before execution: a bad signature, or inputs that
344
+ // changed since signing (rebuild and sign again).
345
+ throw new errors_1.UpshiftSDKError('UNKNOWN', `submitSuiTransaction: the network rejected the transaction: ${err instanceof Error ? err.message : String(err)}`, { cause: err, context: { network } });
346
+ });
347
+ if (result.$kind !== 'Transaction') {
348
+ const failed = result.FailedTransaction;
349
+ const digest = failed.digest;
350
+ const error = suiExecutionErrorToSdkError(failed.effects?.status.error ?? undefined, { network, digest });
351
+ // Gas was still spent: wait (best effort) until the failure is indexed, so
352
+ // a retry built right after this sees the sender's new coin versions.
353
+ await (0, client_1.withSuiClient)(networkConfig, (client) => client.core.waitForTransaction({ result, timeout: 12_000 })).catch(() => undefined);
354
+ const data = SuiTransaction.from(bytes).getData();
355
+ const redemption = redemptionOf(data, fromBase64);
356
+ if (redemption && data.sender) {
357
+ (0, curator_alert_1.reportRedeemFailure)({
358
+ phase: 'submission',
359
+ chain: 'sui',
360
+ network,
361
+ contractId: redemption.vaultId,
362
+ eoa: data.sender,
363
+ sharesRaw: redemption.sharesRaw,
364
+ txHash: digest,
365
+ error: error.message,
366
+ });
367
+ }
368
+ throw error;
369
+ }
370
+ const digest = result.Transaction.digest;
371
+ try {
372
+ await (0, client_1.withSuiClient)(networkConfig, (client) =>
373
+ // Under the client's 15 s per-call bound, so a slow index is not mistaken
374
+ // for a dead endpoint.
375
+ client.core.waitForTransaction({ result, timeout: 12_000 }));
376
+ }
377
+ catch (err) {
378
+ throw new errors_1.UpshiftTransactionError(`Sui transaction ${digest} executed but was not confirmed in time.`, digest, { cause: err, context: { network } });
379
+ }
380
+ return digest;
381
+ }
382
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1,166 @@
1
+ import type { ISuiConfig, ISuiNetwork, ITokenizedVault, IVault } from '../../types';
2
+ import type { IVaultBaseOptions } from '../../modules/vaults/types';
3
+ /** The vault a read is for: its object ID, coin types and network. */
4
+ export interface ISuiVaultRef {
5
+ /** Vault object ID (`0x` + 64 hex chars). */
6
+ vaultId: string;
7
+ /** Move type of the deposit coin. */
8
+ assetCoinType: string;
9
+ /** Move type of the vault's share coin. */
10
+ shareCoinType: string;
11
+ /** Network the vault lives on. */
12
+ network: ISuiNetwork;
13
+ }
14
+ /**
15
+ * A vault's on-chain state. Amounts are raw base units: assets in the deposit
16
+ * coin's decimals, shares in {@link ISuiVaultState.decimals} (the contract
17
+ * requires the share coin to use the deposit coin's decimals).
18
+ */
19
+ export interface ISuiVaultState {
20
+ /** Net assets: idle + deployed AUM − collectable fees, floored at 0. */
21
+ totalAssets: bigint;
22
+ /** Minted shares, including shares escrowed in withdrawal requests. */
23
+ totalSupply: bigint;
24
+ /** Asset base units per `10^decimals` shares. */
25
+ sharePrice: bigint;
26
+ /** Share (and deposit coin) decimals. */
27
+ decimals: number;
28
+ /** Deposits, redemptions and new requests abort while paused. */
29
+ paused: boolean;
30
+ /** Whether a withdrawal queue is attached; instant `redeem` is off when it is. */
31
+ queueAttached: boolean;
32
+ /** Smallest accepted deposit, in asset base units. */
33
+ minDeposit: bigint;
34
+ /** Ceiling on total assets after a deposit, in asset base units. */
35
+ depositCap: bigint;
36
+ /** Largest single deposit, in asset base units. */
37
+ maxDepositAmount: bigint;
38
+ /** Largest single gross withdrawal, in asset base units. */
39
+ maxWithdrawalAmount: bigint;
40
+ /** Fee charged by instant `redeem`, in basis points of the gross amount. */
41
+ instantRedemptionFeeBps: number;
42
+ }
43
+ /**
44
+ * Decode a little-endian BCS unsigned integer of `size` bytes.
45
+ * @internal
46
+ */
47
+ export declare function decodeSuiUint(bytes: Uint8Array, size: number): bigint;
48
+ /**
49
+ * Decode a BCS `bool`.
50
+ * @internal
51
+ */
52
+ export declare function decodeSuiBool(bytes: Uint8Array): boolean;
53
+ /**
54
+ * Read the instant-redemption fee from the vault object's JSON fields: the fee
55
+ * sits in a nested struct that a transaction cannot return.
56
+ * @internal
57
+ */
58
+ export declare function parseInstantRedemptionFeeBps(json: unknown): number;
59
+ /**
60
+ * The `sui` config to use for a vault on `network`: the consumer's config when
61
+ * it is for that network, else the network alone (built-in endpoint and
62
+ * contract IDs). A testnet override must never serve a mainnet vault.
63
+ * @internal
64
+ */
65
+ export declare function suiConfigForNetwork(network: ISuiNetwork, sui?: ISuiConfig): ISuiConfig;
66
+ /**
67
+ * Read a vault's on-chain state.
68
+ *
69
+ * RPC cost: two requests, run in parallel: one transaction simulation and one
70
+ * object read. `getVaults` makes these two per Sui vault.
71
+ *
72
+ * @param ref - The vault and its coin types and network.
73
+ * @param sui - The SDK's `sui` config; applied only when its network matches
74
+ * `ref.network`.
75
+ * @returns The vault's state; see {@link ISuiVaultState} for units.
76
+ * @throws {@link UpshiftValidationError} (`INVALID_ADDRESS`) for a malformed
77
+ * vault ID, (`INVALID_INPUT`) when the contract IDs for the network are not
78
+ * known or the simulation aborts (wrong vault, coin types or package).
79
+ * @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
80
+ * @example
81
+ * ```ts
82
+ * const state = await readSuiVaultState(
83
+ * { vaultId, assetCoinType, shareCoinType, network: 'testnet' },
84
+ * { network: 'testnet', packageId, originalPackageId, registryId },
85
+ * );
86
+ * ```
87
+ */
88
+ export declare function readSuiVaultState(ref: ISuiVaultRef, sui?: ISuiConfig): Promise<ISuiVaultState>;
89
+ /**
90
+ * Shares a deposit would mint at the current price. Limits are not checked.
91
+ *
92
+ * RPC cost: one transaction simulation.
93
+ *
94
+ * @param ref - The vault and its coin types and network.
95
+ * @param assets - Deposit amount in asset base units.
96
+ * @param sui - The SDK's `sui` config; applied only for `ref.network`.
97
+ * @returns Shares in share base units.
98
+ * @throws {@link UpshiftValidationError} for a malformed vault ID, a negative
99
+ * or out-of-range amount, unknown contract IDs or an aborted simulation.
100
+ * @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
101
+ */
102
+ export declare function previewSuiDeposit(ref: ISuiVaultRef, assets: bigint, sui?: ISuiConfig): Promise<bigint>;
103
+ /**
104
+ * Assets a redemption of `shares` would pay at the current price.
105
+ *
106
+ * RPC cost: one transaction simulation.
107
+ *
108
+ * @param ref - The vault and its coin types and network.
109
+ * @param shares - Shares to redeem, in share base units.
110
+ * @param isInstant - `true` for instant `redeem` (charges the instant fee),
111
+ * `false` for a queued withdrawal (no fee).
112
+ * @param sui - The SDK's `sui` config; applied only for `ref.network`.
113
+ * @returns `gross` and `net` (after the instant fee) in asset base units.
114
+ * @throws {@link UpshiftValidationError} for a malformed vault ID, a negative
115
+ * or out-of-range amount, unknown contract IDs or an aborted simulation.
116
+ * @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
117
+ */
118
+ export declare function previewSuiRedemption(ref: ISuiVaultRef, shares: bigint, isInstant: boolean, sui?: ISuiConfig): Promise<{
119
+ gross: bigint;
120
+ net: bigint;
121
+ }>;
122
+ /**
123
+ * A wallet's balance of a share coin: coin objects plus the address balance.
124
+ *
125
+ * RPC cost: one balance read.
126
+ *
127
+ * @param owner - Wallet address (`0x` + 64 hex chars).
128
+ * @param shareCoinType - Move type of the vault's share coin.
129
+ * @param network - Network to read.
130
+ * @param sui - The SDK's `sui` config; applied only for `network`.
131
+ * @returns Shares in share base units.
132
+ * @throws {@link UpshiftValidationError} (`INVALID_ADDRESS`) for a malformed
133
+ * owner.
134
+ * @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
135
+ */
136
+ export declare function getSuiShareBalance(owner: string, shareCoinType: string, network: ISuiNetwork, sui?: ISuiConfig): Promise<bigint>;
137
+ /**
138
+ * The vault reference for a backend row, or `null` when the row has no usable
139
+ * `sui_vault_metadata`.
140
+ * @internal
141
+ */
142
+ export declare function suiVaultRefFromRow(row: ITokenizedVault): ISuiVaultRef | null;
143
+ /**
144
+ * Build the SDK's `IVault` for a Sui vault from its backend row and, when the
145
+ * read succeeded, its on-chain state. Without state, total assets fall back
146
+ * to the backend's `latest_reported_tvl`, supply to zero, and the vault is
147
+ * marked deposit-paused so no deposit is offered on unread state.
148
+ * @internal
149
+ */
150
+ export declare function buildSuiVault(row: ITokenizedVault, state: ISuiVaultState | null): IVault;
151
+ /**
152
+ * Build a Sui vault's `IVault` from its backend row plus on-chain state.
153
+ *
154
+ * A failed read (unknown contract IDs, every endpoint down, an aborted
155
+ * simulation) does not fail the call: the vault is built from the backend row
156
+ * alone (see {@link buildSuiVault}) and a warning is logged.
157
+ *
158
+ * RPC cost: as {@link readSuiVaultState}.
159
+ *
160
+ * @param row - Backend `tokenized_vault` row with `sui_vault_metadata`.
161
+ * @param options - Vault options; `options.sui` carries the SDK's `sui` config.
162
+ * @returns The vault.
163
+ * @throws {@link UpshiftValidationError} (`INVALID_INPUT`) when the row has no
164
+ * usable `sui_vault_metadata` (e.g. a legacy Ember/Gamma Sui vault).
165
+ */
166
+ export declare function getSuiVault(row: ITokenizedVault, options?: IVaultBaseOptions): Promise<IVault>;