@upshiftfinance/sdk 0.4.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.
- package/README.md +5 -1
- package/esm/index.d.mts +15 -0
- package/esm/index.mjs +18 -0
- package/lib/adapters/sui/actions.d.ts +260 -14
- package/lib/adapters/sui/actions.js +332 -13
- package/lib/adapters/sui/client.d.ts +3 -3
- package/lib/adapters/sui/client.js +27 -9
- package/lib/adapters/sui/getters.d.ts +104 -2
- package/lib/adapters/sui/getters.js +283 -5
- package/lib/adapters/sui/index.d.ts +154 -7
- package/lib/adapters/sui/index.js +166 -9
- package/lib/adapters/sui/targets.d.ts +7 -1
- package/lib/adapters/sui/targets.js +7 -1
- package/lib/core/analytics/method-taxonomy.js +2 -0
- package/lib/core/analytics/version.d.ts +1 -1
- package/lib/core/analytics/version.js +1 -1
- package/lib/core/errors/index.d.ts +15 -2
- package/lib/evm/methods/crossChainVault.js +25 -43
- package/lib/index.d.ts +4 -0
- package/lib/index.js +4 -0
- package/lib/main.d.ts +4 -2
- package/lib/modules/vaults/getters.js +34 -6
- package/lib/modules/vaults/main.d.ts +4 -2
- package/lib/modules/vaults/main.js +3 -1
- package/lib/sdk.d.ts +16359 -15349
- package/package.json +21 -2
|
@@ -41,15 +41,32 @@ exports.readSuiVaultState = readSuiVaultState;
|
|
|
41
41
|
exports.previewSuiDeposit = previewSuiDeposit;
|
|
42
42
|
exports.previewSuiRedemption = previewSuiRedemption;
|
|
43
43
|
exports.getSuiShareBalance = getSuiShareBalance;
|
|
44
|
+
exports.getSuiWithdrawalRequests = getSuiWithdrawalRequests;
|
|
45
|
+
exports.suiPositionRedemptions = suiPositionRedemptions;
|
|
46
|
+
exports.getSuiPositionRedemptions = getSuiPositionRedemptions;
|
|
47
|
+
exports.nextSuiWithdrawalRequestId = nextSuiWithdrawalRequestId;
|
|
48
|
+
exports.deriveSuiWithdrawalRequestId = deriveSuiWithdrawalRequestId;
|
|
44
49
|
exports.suiVaultRefFromRow = suiVaultRefFromRow;
|
|
45
50
|
exports.buildSuiVault = buildSuiVault;
|
|
46
51
|
exports.getSuiVault = getSuiVault;
|
|
52
|
+
const types_1 = require("../../types");
|
|
47
53
|
const core_1 = require("../../core");
|
|
54
|
+
const errors_1 = require("../../core/errors");
|
|
48
55
|
const chain_address_1 = require("../../core/helpers/chain-address");
|
|
49
56
|
const utils_1 = require("../../modules/vaults/utils");
|
|
50
57
|
const client_1 = require("./client");
|
|
51
58
|
const constants_1 = require("./constants");
|
|
52
59
|
const targets_1 = require("./targets");
|
|
60
|
+
/**
|
|
61
|
+
* Re-throw a failed read as a typed SDK error: SDK errors pass through, and
|
|
62
|
+
* anything else (an object that does not exist, a malformed coin type, a
|
|
63
|
+
* package that is not the vault package) becomes `INVALID_INPUT`.
|
|
64
|
+
*/
|
|
65
|
+
function asReadError(err, network) {
|
|
66
|
+
if (err instanceof core_1.UpshiftSDKError)
|
|
67
|
+
throw err;
|
|
68
|
+
throw new core_1.UpshiftValidationError('INVALID_INPUT', `Sui read failed — check the vault ID, its coin types and the contract IDs for this network: ${err instanceof Error ? err.message : String(err)}`, { cause: err, context: { network } });
|
|
69
|
+
}
|
|
53
70
|
/** Simulations need a sender; no signature or gas is involved. */
|
|
54
71
|
const SIMULATION_SENDER = `0x${'0'.repeat(64)}`;
|
|
55
72
|
/** The contract's "no limit" value for `u64` caps. */
|
|
@@ -136,6 +153,17 @@ async function simulateVaultReads(ref, sui, calls) {
|
|
|
136
153
|
// Built per attempt: building resolves object versions against this client.
|
|
137
154
|
const tx = new SuiTransaction();
|
|
138
155
|
tx.setSender(SIMULATION_SENDER);
|
|
156
|
+
// Charge the management fee accrued since the last charge first, so every
|
|
157
|
+
// read sees the current NAV. A simulation persists nothing.
|
|
158
|
+
tx.moveCall({
|
|
159
|
+
target: (0, targets_1.suiMoveCallTarget)(contracts, 'chargeManagementFee'),
|
|
160
|
+
typeArguments,
|
|
161
|
+
arguments: [
|
|
162
|
+
tx.object(ref.vaultId),
|
|
163
|
+
tx.object(contracts.registryId),
|
|
164
|
+
tx.object(constants_1.SUI_CLOCK_ID),
|
|
165
|
+
],
|
|
166
|
+
});
|
|
139
167
|
for (const call of calls) {
|
|
140
168
|
tx.moveCall({
|
|
141
169
|
target: (0, targets_1.suiMoveCallTarget)(contracts, call.target),
|
|
@@ -159,8 +187,11 @@ async function simulateVaultReads(ref, sui, calls) {
|
|
|
159
187
|
},
|
|
160
188
|
});
|
|
161
189
|
}
|
|
162
|
-
|
|
163
|
-
|
|
190
|
+
// Drop the fee charge's (empty) result so indexes match `calls`.
|
|
191
|
+
return result.commandResults
|
|
192
|
+
.slice(1)
|
|
193
|
+
.map((c) => c.returnValues.map((v) => v.bcs));
|
|
194
|
+
}).catch((err) => asReadError(err, ref.network));
|
|
164
195
|
}
|
|
165
196
|
/**
|
|
166
197
|
* Read a vault's on-chain state.
|
|
@@ -192,7 +223,7 @@ async function readSuiVaultState(ref, sui) {
|
|
|
192
223
|
target,
|
|
193
224
|
registry: NEEDS_REGISTRY.has(target),
|
|
194
225
|
}))),
|
|
195
|
-
(0, client_1.withSuiClient)((0, client_1.resolveSuiNetworkConfig)(config), (client) => client.core.getObject({ objectId: ref.vaultId, include: { json: true } })),
|
|
226
|
+
(0, client_1.withSuiClient)((0, client_1.resolveSuiNetworkConfig)(config), (client) => client.core.getObject({ objectId: ref.vaultId, include: { json: true } })).catch((err) => asReadError(err, ref.network)),
|
|
196
227
|
]);
|
|
197
228
|
const at = (i) => {
|
|
198
229
|
const bytes = values[i]?.[0];
|
|
@@ -294,9 +325,256 @@ async function getSuiShareBalance(owner, shareCoinType, network, sui) {
|
|
|
294
325
|
throw new core_1.UpshiftValidationError('INVALID_ADDRESS', 'getSuiShareBalance: owner must be a Sui address (0x + 64 hex chars).');
|
|
295
326
|
}
|
|
296
327
|
const config = suiConfigForNetwork(network, sui);
|
|
297
|
-
const { balance } = await (0, client_1.withSuiClient)((0, client_1.resolveSuiNetworkConfig)(config), (client) => client.core.getBalance({ owner, coinType: shareCoinType }));
|
|
328
|
+
const { balance } = await (0, client_1.withSuiClient)((0, client_1.resolveSuiNetworkConfig)(config), (client) => client.core.getBalance({ owner, coinType: shareCoinType })).catch((err) => asReadError(err, network));
|
|
298
329
|
return BigInt(balance.balance);
|
|
299
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* IDs checked per object read: each needs its claim marker and its request,
|
|
333
|
+
* and the gRPC client sends at most 50 objects per request. The first page
|
|
334
|
+
* also carries the vault object, so it checks one ID fewer.
|
|
335
|
+
*/
|
|
336
|
+
const REQUEST_SCAN_PAGE = 25;
|
|
337
|
+
/**
|
|
338
|
+
* Walk a wallet's request IDs on a vault, `0, 1, 2, …`, and read each one.
|
|
339
|
+
*
|
|
340
|
+
* The contract derives a request's object ID from (vault, owner, request ID)
|
|
341
|
+
* and leaves a permanent claim marker on the vault for every ID ever used,
|
|
342
|
+
* also after the request is claimed or cancelled. The SDK numbers requests
|
|
343
|
+
* sequentially, so the first ID without a marker is the next one to use, and
|
|
344
|
+
* every request below it that still exists is pending. This needs neither an
|
|
345
|
+
* event index (public fullnodes keep about two weeks of events) nor an
|
|
346
|
+
* indexer.
|
|
347
|
+
*
|
|
348
|
+
* Requests made outside the SDK with other IDs are not found.
|
|
349
|
+
*
|
|
350
|
+
* The first read also checks that `ref.vaultId` is a vault of the configured
|
|
351
|
+
* original package, so a wrong vault ID or `sui.originalPackageId` (which
|
|
352
|
+
* names the request IDs) fails loudly instead of finding nothing.
|
|
353
|
+
*
|
|
354
|
+
* RPC cost: one object read for up to 23 used IDs, one more per further 25.
|
|
355
|
+
*/
|
|
356
|
+
async function scanSuiWithdrawalRequests(ref, owner, sui) {
|
|
357
|
+
const config = suiConfigForNetwork(ref.network, sui);
|
|
358
|
+
const contracts = (0, targets_1.resolveSuiVaultContracts)(config);
|
|
359
|
+
const [{ bcs }, { deriveDynamicFieldID }] = await Promise.all([
|
|
360
|
+
Promise.resolve().then(() => __importStar(require('@mysten/sui/bcs'))),
|
|
361
|
+
Promise.resolve().then(() => __importStar(require('@mysten/sui/utils'))),
|
|
362
|
+
]);
|
|
363
|
+
const WithdrawalRequest = bcs.struct('WithdrawalRequest', {
|
|
364
|
+
id: bcs.Address,
|
|
365
|
+
vaultId: bcs.Address,
|
|
366
|
+
owner: bcs.Address,
|
|
367
|
+
requestId: bcs.u64(),
|
|
368
|
+
shares: bcs.u64(),
|
|
369
|
+
payout: bcs.Address,
|
|
370
|
+
finalizer: bcs.option(bcs.Address),
|
|
371
|
+
requestedAtMs: bcs.u64(),
|
|
372
|
+
eligibleAtMs: bcs.u64(),
|
|
373
|
+
expiresAtMs: bcs.option(bcs.u64()),
|
|
374
|
+
});
|
|
375
|
+
const requests = [];
|
|
376
|
+
for (let start = 0n;;) {
|
|
377
|
+
const first = start === 0n;
|
|
378
|
+
const size = first ? REQUEST_SCAN_PAGE - 1 : REQUEST_SCAN_PAGE;
|
|
379
|
+
const ids = Array.from({ length: size }, (_, i) => start + BigInt(i));
|
|
380
|
+
start += BigInt(size);
|
|
381
|
+
const requestIds = await Promise.all(ids.map((requestId) => deriveSuiWithdrawalRequestId(ref.vaultId, owner, requestId, contracts.originalPackageId)));
|
|
382
|
+
// The marker is a dynamic field on the vault keyed by the request ID.
|
|
383
|
+
const markerIds = requestIds.map((id) => deriveDynamicFieldID(ref.vaultId, '0x2::derived_object::Claimed', bcs.Address.serialize(id).toBytes()));
|
|
384
|
+
const { objects } = await (0, client_1.withSuiClient)((0, client_1.resolveSuiNetworkConfig)(config), (client) => client.core.getObjects({
|
|
385
|
+
objectIds: [
|
|
386
|
+
...markerIds,
|
|
387
|
+
...requestIds,
|
|
388
|
+
...(first ? [ref.vaultId] : []),
|
|
389
|
+
],
|
|
390
|
+
include: { content: true },
|
|
391
|
+
})).catch((err) => asReadError(err, ref.network));
|
|
392
|
+
const missing = (o) => {
|
|
393
|
+
if (!(o instanceof Error))
|
|
394
|
+
return false;
|
|
395
|
+
const reason = o.reason;
|
|
396
|
+
if (reason === 'notFound' || reason === 'deleted')
|
|
397
|
+
return true;
|
|
398
|
+
// Any other per-object error means the node did not answer for it.
|
|
399
|
+
throw new errors_1.UpshiftNetworkError(`Sui read: withdrawal request lookup failed: ${o.message}`, { cause: o, context: { network: ref.network } });
|
|
400
|
+
};
|
|
401
|
+
if (first) {
|
|
402
|
+
const vault = objects[2 * size];
|
|
403
|
+
// A missing vault is a wrong ID; any other per-object error is the node.
|
|
404
|
+
assertVaultOfPackage(missing(vault) ? undefined : vault, ref, contracts);
|
|
405
|
+
}
|
|
406
|
+
for (let i = 0; i < size; i += 1) {
|
|
407
|
+
if (missing(objects[i])) {
|
|
408
|
+
return { nextRequestId: ids[i], requests };
|
|
409
|
+
}
|
|
410
|
+
const object = objects[size + i];
|
|
411
|
+
// Claimed but gone: the request was claimed or cancelled.
|
|
412
|
+
if (missing(object) || object instanceof Error)
|
|
413
|
+
continue;
|
|
414
|
+
const parsed = WithdrawalRequest.parse(object.content);
|
|
415
|
+
requests.push({
|
|
416
|
+
request: requestIds[i],
|
|
417
|
+
requestId: BigInt(parsed.requestId),
|
|
418
|
+
owner: parsed.owner,
|
|
419
|
+
shares: BigInt(parsed.shares),
|
|
420
|
+
payout: parsed.payout,
|
|
421
|
+
finalizer: parsed.finalizer ?? null,
|
|
422
|
+
requestedAtMs: Number(parsed.requestedAtMs),
|
|
423
|
+
eligibleAtMs: Number(parsed.eligibleAtMs),
|
|
424
|
+
expiresAtMs: parsed.expiresAtMs == null ? null : Number(parsed.expiresAtMs),
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Throw unless `object` is the vault `ref` names, typed by the configured
|
|
431
|
+
* original package: request IDs are derived from that package, so a wrong one
|
|
432
|
+
* would make every request invisible.
|
|
433
|
+
*/
|
|
434
|
+
function assertVaultOfPackage(object, ref, contracts) {
|
|
435
|
+
const type = object instanceof Error ? undefined : object?.type;
|
|
436
|
+
const expected = `${contracts.originalPackageId}::vault::Vault<`.toLowerCase();
|
|
437
|
+
if (!type) {
|
|
438
|
+
throw new core_1.UpshiftValidationError('INVALID_INPUT', 'Sui read: the vault object was not found — check the vault ID for this network.', { context: { network: ref.network } });
|
|
439
|
+
}
|
|
440
|
+
if (!type.toLowerCase().startsWith(expected)) {
|
|
441
|
+
throw new core_1.UpshiftValidationError('INVALID_INPUT', `Sui read: ${ref.vaultId} is not a vault of the configured original package (its type is ${type}) — check the vault ID and sui.originalPackageId.`, { context: { network: ref.network } });
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
function assertOwner(owner, method) {
|
|
445
|
+
if (!(0, chain_address_1.isSuiAddress)(owner)) {
|
|
446
|
+
throw new core_1.UpshiftValidationError('INVALID_ADDRESS', `${method}: owner must be a Sui address (0x + 64 hex chars).`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* A wallet's pending withdrawal requests on a vault, oldest first.
|
|
451
|
+
*
|
|
452
|
+
* Finds the requests the SDK made (see `buildSuiRequestRedeemTransaction`),
|
|
453
|
+
* however old: requests made outside the SDK with non-sequential IDs are not
|
|
454
|
+
* listed. Claimed and cancelled requests no longer exist and are left out.
|
|
455
|
+
*
|
|
456
|
+
* RPC cost: one object read for a wallet that has made up to 23 requests on
|
|
457
|
+
* the vault (most wallets), one more per further 25.
|
|
458
|
+
*
|
|
459
|
+
* @param ref - The vault and its coin types and network.
|
|
460
|
+
* @param owner - Wallet that made the requests (`0x` + 64 hex chars).
|
|
461
|
+
* @param sui - The SDK's `sui` config; applied only for `ref.network`.
|
|
462
|
+
* @returns The pending requests; empty when there are none.
|
|
463
|
+
* @throws {@link UpshiftValidationError} (`INVALID_ADDRESS`) for a malformed
|
|
464
|
+
* vault ID or owner, (`INVALID_INPUT`) for unknown contract IDs, or a vault
|
|
465
|
+
* ID that is not a vault of the configured `sui.originalPackageId`.
|
|
466
|
+
* @throws {@link UpshiftNetworkError} when every Sui endpoint fails, or the
|
|
467
|
+
* node cannot answer for one of the objects.
|
|
468
|
+
* @example
|
|
469
|
+
* ```ts
|
|
470
|
+
* const pending = await getSuiWithdrawalRequests(ref, account.address, sdkSuiConfig);
|
|
471
|
+
* const now = Date.now();
|
|
472
|
+
* const claimable = pending.filter(
|
|
473
|
+
* (r) => r.eligibleAtMs <= now && (r.expiresAtMs === null || now < r.expiresAtMs),
|
|
474
|
+
* );
|
|
475
|
+
* ```
|
|
476
|
+
*/
|
|
477
|
+
async function getSuiWithdrawalRequests(ref, owner, sui) {
|
|
478
|
+
assertVaultRef(ref, 'getSuiWithdrawalRequests');
|
|
479
|
+
assertOwner(owner, 'getSuiWithdrawalRequests');
|
|
480
|
+
return (await scanSuiWithdrawalRequests(ref, owner, sui)).requests;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Split a wallet's withdrawal requests into position redemptions, the way
|
|
484
|
+
* the EVM and Solana paths do: `availableRedemptions` holds requests still in
|
|
485
|
+
* their cooldown or past their window (cancel-only), `pendingRedemptions` the
|
|
486
|
+
* ones claimable now. Each entry's `amount` is the escrowed shares; `date` is
|
|
487
|
+
* when it becomes claimable, `timestamp` when it was made (Unix seconds).
|
|
488
|
+
* @internal
|
|
489
|
+
*/
|
|
490
|
+
function suiPositionRedemptions(requests, vault, decimals, nowMs) {
|
|
491
|
+
const availableRedemptions = [];
|
|
492
|
+
const pendingRedemptions = [];
|
|
493
|
+
for (const r of requests) {
|
|
494
|
+
const status = r.expiresAtMs !== null && nowMs >= r.expiresAtMs
|
|
495
|
+
? types_1.VaultRedemptionStatus.EXPIRED
|
|
496
|
+
: nowMs >= r.eligibleAtMs
|
|
497
|
+
? types_1.VaultRedemptionStatus.READY_TO_CLAIM
|
|
498
|
+
: types_1.VaultRedemptionStatus.AWAITING_COOLDOWN;
|
|
499
|
+
const date = new Date(r.eligibleAtMs);
|
|
500
|
+
const entry = {
|
|
501
|
+
id: r.request,
|
|
502
|
+
hash: r.request,
|
|
503
|
+
timestamp: Math.floor(r.requestedAtMs / 1000),
|
|
504
|
+
receiver: r.payout,
|
|
505
|
+
day: (0, core_1.toNormalizedBn)(date.getUTCDate(), 0),
|
|
506
|
+
month: (0, core_1.toNormalizedBn)(date.getUTCMonth() + 1, 0),
|
|
507
|
+
year: (0, core_1.toNormalizedBn)(date.getUTCFullYear(), 0),
|
|
508
|
+
amount: (0, core_1.toNormalizedBn)(r.shares, decimals),
|
|
509
|
+
date,
|
|
510
|
+
vault: vault,
|
|
511
|
+
status,
|
|
512
|
+
};
|
|
513
|
+
if (status === types_1.VaultRedemptionStatus.READY_TO_CLAIM) {
|
|
514
|
+
pendingRedemptions.push(entry);
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
availableRedemptions.push(entry);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return { availableRedemptions, pendingRedemptions };
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* A wallet's withdrawal requests on a vault as position redemptions (see
|
|
524
|
+
* {@link suiPositionRedemptions}). Empty when the SDK has no contract IDs for
|
|
525
|
+
* the network: the share balance can still be read without them, so a
|
|
526
|
+
* position should not fail for that.
|
|
527
|
+
*
|
|
528
|
+
* RPC cost: as {@link getSuiWithdrawalRequests}; none without contract IDs.
|
|
529
|
+
* @internal
|
|
530
|
+
*/
|
|
531
|
+
async function getSuiPositionRedemptions(ref, owner, decimals, sui) {
|
|
532
|
+
const config = suiConfigForNetwork(ref.network, sui);
|
|
533
|
+
const defaults = constants_1.SUI_VAULT_CONTRACTS[ref.network];
|
|
534
|
+
const configured = (config.packageId ?? defaults.packageId) &&
|
|
535
|
+
(config.originalPackageId ?? defaults.originalPackageId) &&
|
|
536
|
+
(config.registryId ?? defaults.registryId);
|
|
537
|
+
if (!configured) {
|
|
538
|
+
return suiPositionRedemptions([], ref.vaultId, decimals, Date.now());
|
|
539
|
+
}
|
|
540
|
+
const requests = await getSuiWithdrawalRequests(ref, owner, sui);
|
|
541
|
+
return suiPositionRedemptions(requests, ref.vaultId, decimals, Date.now());
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* The request ID a wallet's next withdrawal request on a vault takes: the
|
|
545
|
+
* lowest it has never used.
|
|
546
|
+
*
|
|
547
|
+
* RPC cost: as {@link getSuiWithdrawalRequests}.
|
|
548
|
+
* @internal
|
|
549
|
+
*/
|
|
550
|
+
async function nextSuiWithdrawalRequestId(ref, owner, sui) {
|
|
551
|
+
assertVaultRef(ref, 'nextSuiWithdrawalRequestId');
|
|
552
|
+
assertOwner(owner, 'nextSuiWithdrawalRequestId');
|
|
553
|
+
return (await scanSuiWithdrawalRequests(ref, owner, sui)).nextRequestId;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* The object ID of a wallet's withdrawal request: derived from the vault, the
|
|
557
|
+
* owner and the request ID, as the contract derives it.
|
|
558
|
+
*
|
|
559
|
+
* @param vaultId - Vault object ID.
|
|
560
|
+
* @param owner - Wallet that made the request.
|
|
561
|
+
* @param requestId - The wallet's numeric request ID on the vault.
|
|
562
|
+
* @param originalPackageId - The original `upshift_vault` package, which
|
|
563
|
+
* names the derivation key type.
|
|
564
|
+
* @returns The request object ID.
|
|
565
|
+
* @internal
|
|
566
|
+
*/
|
|
567
|
+
async function deriveSuiWithdrawalRequestId(vaultId, owner, requestId, originalPackageId) {
|
|
568
|
+
const [{ bcs }, { deriveObjectID, normalizeSuiAddress }] = await Promise.all([
|
|
569
|
+
Promise.resolve().then(() => __importStar(require('@mysten/sui/bcs'))),
|
|
570
|
+
Promise.resolve().then(() => __importStar(require('@mysten/sui/utils'))),
|
|
571
|
+
]);
|
|
572
|
+
const key = bcs
|
|
573
|
+
.struct('RequestKey', { owner: bcs.Address, requestId: bcs.u64() })
|
|
574
|
+
.serialize({ owner: normalizeSuiAddress(owner), requestId })
|
|
575
|
+
.toBytes();
|
|
576
|
+
return deriveObjectID(normalizeSuiAddress(vaultId), `${originalPackageId}::withdrawal::RequestKey`, key);
|
|
577
|
+
}
|
|
300
578
|
/**
|
|
301
579
|
* The vault reference for a backend row, or `null` when the row has no usable
|
|
302
580
|
* `sui_vault_metadata`.
|
|
@@ -360,7 +638,7 @@ function buildSuiVault(row, state) {
|
|
|
360
638
|
*
|
|
361
639
|
* A failed read (unknown contract IDs, every endpoint down, an aborted
|
|
362
640
|
* simulation) does not fail the call: the vault is built from the backend row
|
|
363
|
-
* alone (see
|
|
641
|
+
* alone (see `buildSuiVault`) and a warning is logged.
|
|
364
642
|
*
|
|
365
643
|
* RPC cost: as {@link readSuiVaultState}.
|
|
366
644
|
*
|
|
@@ -10,6 +10,11 @@ import * as SuiConstants from './constants';
|
|
|
10
10
|
import * as SuiGetters from './getters';
|
|
11
11
|
import * as SuiTargets from './targets';
|
|
12
12
|
import * as SuiUtils from './utils';
|
|
13
|
+
/**
|
|
14
|
+
* Sui helpers by area: chain identity (`utils`), constants, the gRPC client
|
|
15
|
+
* with failover (`client`), move-call targets (`targets`), vault reads
|
|
16
|
+
* (`getters`) and deposit / instant-redeem builders (`actions`).
|
|
17
|
+
*/
|
|
13
18
|
export declare const Sui: {
|
|
14
19
|
utils: typeof SuiUtils;
|
|
15
20
|
constants: typeof SuiConstants;
|
|
@@ -45,7 +50,7 @@ export interface ISuiAdapterVault {
|
|
|
45
50
|
* sdk.sui.isSuiAddress(vault.address);
|
|
46
51
|
* ```
|
|
47
52
|
*/
|
|
48
|
-
declare class SuiAdapter {
|
|
53
|
+
export declare class SuiAdapter {
|
|
49
54
|
private readonly _config;
|
|
50
55
|
/**
|
|
51
56
|
* @param config - Optional Sui settings; omit to target Sui mainnet.
|
|
@@ -79,7 +84,8 @@ declare class SuiAdapter {
|
|
|
79
84
|
* RPC cost: one dry run (plus the coin lookup it needs).
|
|
80
85
|
*
|
|
81
86
|
* @param params - The vault, `amount` in asset base units, the `sender`, and
|
|
82
|
-
*
|
|
87
|
+
* optionally `minSharesOut` or `slippageBps` (the minimum defaults to the
|
|
88
|
+
* dry run's preview less 0.1%).
|
|
83
89
|
* @returns The unsigned transaction for the sender's wallet, the shares the
|
|
84
90
|
* dry run minted, and the minimum it enforces.
|
|
85
91
|
* @throws {@link UpshiftValidationError} for malformed input, unknown
|
|
@@ -95,17 +101,21 @@ declare class SuiAdapter {
|
|
|
95
101
|
* amount: 1_000_000n,
|
|
96
102
|
* sender: account.address,
|
|
97
103
|
* });
|
|
98
|
-
* await
|
|
104
|
+
* const digest = await sdk.sui.executeTransaction(
|
|
105
|
+
* await dAppKit.signTransaction({ transaction }),
|
|
106
|
+
* );
|
|
99
107
|
* ```
|
|
100
108
|
*/
|
|
101
109
|
vaultDeposit(params: ISuiAdapterVault & {
|
|
102
110
|
amount: bigint;
|
|
103
111
|
sender: string;
|
|
104
112
|
minSharesOut?: bigint;
|
|
113
|
+
slippageBps?: number;
|
|
105
114
|
}): Promise<SuiActions.ISuiDepositTransaction>;
|
|
106
115
|
/**
|
|
107
|
-
* Build an unsigned instant redemption on the configured network:
|
|
108
|
-
* shares with a minimum net asset amount, send
|
|
116
|
+
* Build an unsigned instant redemption on the configured network: charge
|
|
117
|
+
* the management fee, redeem shares with a minimum net asset amount, send
|
|
118
|
+
* the assets to the sender.
|
|
109
119
|
* Dry-runs it first; a vault with a withdrawal queue attached fails with
|
|
110
120
|
* `queue_attached`.
|
|
111
121
|
*
|
|
@@ -115,8 +125,8 @@ declare class SuiAdapter {
|
|
|
115
125
|
* RPC cost: one dry run (plus the coin lookup it needs).
|
|
116
126
|
*
|
|
117
127
|
* @param params - The vault, `shares` in share base units, the `sender`, and
|
|
118
|
-
*
|
|
119
|
-
* run's
|
|
128
|
+
* optionally `minAssetsOut` (net of the instant fee) or `slippageBps` (the
|
|
129
|
+
* minimum defaults to the dry run's preview less 0.1%).
|
|
120
130
|
* @returns The unsigned transaction, the dry run's gross and net assets, and
|
|
121
131
|
* the minimum it enforces.
|
|
122
132
|
* @throws {@link UpshiftValidationError} for malformed input, unknown
|
|
@@ -128,7 +138,144 @@ declare class SuiAdapter {
|
|
|
128
138
|
shares: bigint;
|
|
129
139
|
sender: string;
|
|
130
140
|
minAssetsOut?: bigint;
|
|
141
|
+
slippageBps?: number;
|
|
131
142
|
}): Promise<SuiActions.ISuiRedeemTransaction>;
|
|
143
|
+
/**
|
|
144
|
+
* Build an unsigned withdrawal request on the configured network, for a
|
|
145
|
+
* vault with a withdrawal queue attached (where instant redemption is off).
|
|
146
|
+
* Escrows the shares in a new request; dry-runs it first, so a vault that
|
|
147
|
+
* would reject it fails here.
|
|
148
|
+
*
|
|
149
|
+
* The request is priced when it is claimed. Once the vault's cooldown has
|
|
150
|
+
* run, claim it with {@link SuiAdapter.claimWithdrawal}; cancel it at any
|
|
151
|
+
* time with {@link SuiAdapter.vaultCancelRedeemRequest}. List a wallet's
|
|
152
|
+
* requests with {@link SuiAdapter.getWithdrawalRequests}.
|
|
153
|
+
*
|
|
154
|
+
* RPC cost: one object read for a wallet with up to 23 earlier requests on
|
|
155
|
+
* the vault (one more per further 25), then one dry run.
|
|
156
|
+
*
|
|
157
|
+
* @param params - The vault, `shares` in share base units, the `sender`, and
|
|
158
|
+
* optionally `payout` (defaults to the sender) and `finalizer`: who besides
|
|
159
|
+
* the owner may claim during the first day the request is claimable
|
|
160
|
+
* (anyone may after). Defaults to the owner alone; pass a keeper address,
|
|
161
|
+
* or `null` to let anyone claim as soon as the cooldown ends.
|
|
162
|
+
* @returns The unsigned transaction, the request ID, the request's object ID
|
|
163
|
+
* (`request`) for claiming or cancelling, and `expectedAssets` at today's
|
|
164
|
+
* price.
|
|
165
|
+
* @throws {@link UpshiftValidationError} for malformed input, unknown
|
|
166
|
+
* contract IDs, or a transaction that cannot be built.
|
|
167
|
+
* @throws {@link UpshiftVaultAbortError} when the vault would reject it,
|
|
168
|
+
* e.g. `queue_not_attached` (redeem instantly instead) or `paused`.
|
|
169
|
+
* @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* const { transaction, request } = await sdk.sui.vaultRequestRedeem({
|
|
173
|
+
* vaultId: vault.address,
|
|
174
|
+
* assetCoinType: vault.depositAssets[0].address,
|
|
175
|
+
* shareCoinType: vault.receipt.address,
|
|
176
|
+
* shares: 1_000_000n,
|
|
177
|
+
* sender: account.address,
|
|
178
|
+
* });
|
|
179
|
+
* await sdk.sui.executeTransaction(await dAppKit.signTransaction({ transaction }));
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
vaultRequestRedeem(params: ISuiAdapterVault & {
|
|
183
|
+
shares: bigint;
|
|
184
|
+
sender: string;
|
|
185
|
+
payout?: string;
|
|
186
|
+
finalizer?: string | null;
|
|
187
|
+
}): Promise<SuiActions.ISuiRequestRedeemTransaction>;
|
|
188
|
+
/**
|
|
189
|
+
* Build an unsigned cancellation of a pending withdrawal request on the
|
|
190
|
+
* configured network; the escrowed shares go back to the sender. Allowed at
|
|
191
|
+
* any time while the request exists, also while the vault is paused. Only
|
|
192
|
+
* the wallet that made the request may cancel it.
|
|
193
|
+
*
|
|
194
|
+
* RPC cost: one dry run.
|
|
195
|
+
*
|
|
196
|
+
* @param params - The vault, the `request` object ID and the `sender`.
|
|
197
|
+
* @returns The unsigned transaction and the shares it returns.
|
|
198
|
+
* @throws {@link UpshiftValidationError} for malformed input, unknown
|
|
199
|
+
* contract IDs, or a request that no longer exists.
|
|
200
|
+
* @throws {@link UpshiftVaultAbortError} when the vault would reject it,
|
|
201
|
+
* e.g. `not_request_owner`.
|
|
202
|
+
* @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* const { transaction } = await sdk.sui.vaultCancelRedeemRequest({
|
|
206
|
+
* vaultId, assetCoinType, shareCoinType, request, sender: account.address,
|
|
207
|
+
* });
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
vaultCancelRedeemRequest(params: ISuiAdapterVault & {
|
|
211
|
+
request: string;
|
|
212
|
+
sender: string;
|
|
213
|
+
}): Promise<SuiActions.ISuiCancelRedeemRequestTransaction>;
|
|
214
|
+
/**
|
|
215
|
+
* Build an unsigned claim of a withdrawal request on the configured
|
|
216
|
+
* network: burns the escrowed shares and pays their current value, with no
|
|
217
|
+
* instant fee, to the request's payout.
|
|
218
|
+
*
|
|
219
|
+
* The payout lands in the payout address's address balance, not as a coin
|
|
220
|
+
* object. A request can be claimed from `eligibleAtMs` until `expiresAtMs`
|
|
221
|
+
* by its owner or finalizer (anyone when it names none), and by anyone from
|
|
222
|
+
* one day after it became eligible.
|
|
223
|
+
*
|
|
224
|
+
* RPC cost: one dry run.
|
|
225
|
+
*
|
|
226
|
+
* @param params - The vault, the `request` object ID, the `sender`, and
|
|
227
|
+
* optionally `minAssetsOut` or `slippageBps` (the minimum defaults to the
|
|
228
|
+
* dry run's payout less 0.1%).
|
|
229
|
+
* @returns The unsigned transaction, the shares it burns, the dry run's
|
|
230
|
+
* payout, and the minimum it enforces.
|
|
231
|
+
* @throws {@link UpshiftValidationError} for malformed input, unknown
|
|
232
|
+
* contract IDs, or a request that no longer exists.
|
|
233
|
+
* @throws {@link UpshiftVaultAbortError} when the vault would reject it,
|
|
234
|
+
* e.g. `not_eligible_yet`, `request_expired` or `insufficient_liquidity`.
|
|
235
|
+
* @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* const [pending] = await sdk.sui.getWithdrawalRequests({ ...vault, owner: account.address });
|
|
239
|
+
* const { transaction } = await sdk.sui.claimWithdrawal({
|
|
240
|
+
* ...vault, request: pending.request, sender: account.address,
|
|
241
|
+
* });
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
claimWithdrawal(params: ISuiAdapterVault & {
|
|
245
|
+
request: string;
|
|
246
|
+
sender: string;
|
|
247
|
+
minAssetsOut?: bigint;
|
|
248
|
+
slippageBps?: number;
|
|
249
|
+
}): Promise<SuiActions.ISuiClaimWithdrawalTransaction>;
|
|
250
|
+
/**
|
|
251
|
+
* A wallet's pending withdrawal requests on a vault, on the configured
|
|
252
|
+
* network, oldest first. Finds every request made through the SDK however
|
|
253
|
+
* old; claimed and cancelled requests are left out.
|
|
254
|
+
*
|
|
255
|
+
* RPC cost: one object read for a wallet that has made up to 23 requests on
|
|
256
|
+
* the vault (most wallets), one more per further 25.
|
|
257
|
+
*
|
|
258
|
+
* @param params - The vault and the `owner` wallet.
|
|
259
|
+
* @returns The pending requests, with shares, payout, and the times they
|
|
260
|
+
* become claimable and expire; empty when there are none.
|
|
261
|
+
* @throws {@link UpshiftValidationError} for malformed input, unknown
|
|
262
|
+
* contract IDs, or a vault ID that is not a vault of the configured
|
|
263
|
+
* `sui.originalPackageId`.
|
|
264
|
+
* @throws {@link UpshiftNetworkError} when every Sui endpoint fails.
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* const pending = await sdk.sui.getWithdrawalRequests({
|
|
268
|
+
* vaultId, assetCoinType, shareCoinType, owner: account.address,
|
|
269
|
+
* });
|
|
270
|
+
* const now = Date.now();
|
|
271
|
+
* const claimable = pending.filter(
|
|
272
|
+
* (r) => r.eligibleAtMs <= now && (r.expiresAtMs === null || now < r.expiresAtMs),
|
|
273
|
+
* );
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
getWithdrawalRequests(params: ISuiAdapterVault & {
|
|
277
|
+
owner: string;
|
|
278
|
+
}): Promise<SuiGetters.ISuiWithdrawalRequest[]>;
|
|
132
279
|
/**
|
|
133
280
|
* Execute a wallet-signed transaction on the configured network and wait
|
|
134
281
|
* until it is indexed. Not needed when the wallet executes the transaction
|