@scallop-io/sui-scallop-sdk 2.1.9 → 2.2.1-sponsored-feeds-alpha.1
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/dist/index.d.mts +38 -8
- package/dist/index.d.ts +38 -8
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +7 -3
- package/src/builders/oracles/index.ts +40 -9
- package/src/builders/vescaBuilder.ts +43 -36
- package/src/models/scallopBuilder.ts +3 -0
- package/src/models/scallopClient.ts +5 -2
- package/src/types/builder/vesca.ts +37 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scallop-io/sui-scallop-sdk",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.2.1-sponsored-feeds-alpha.1",
|
|
4
4
|
"description": "Typescript sdk for interacting with Scallop contract on SUI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sui",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@mysten/sui": "1.28.2",
|
|
42
42
|
"@pythnetwork/pyth-sui-js": "2.1.0",
|
|
43
|
-
"@scallop-io/sui-kit": "1.4.
|
|
43
|
+
"@scallop-io/sui-kit": "1.4.1",
|
|
44
44
|
"@tanstack/query-core": "5.59.16",
|
|
45
45
|
"axios": "^1.9.0",
|
|
46
46
|
"bignumber.js": "^9.1.2",
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
"@commitlint/cli": "^18.2.0",
|
|
51
51
|
"@commitlint/config-conventional": "^18.1.0",
|
|
52
52
|
"@commitlint/prompt-cli": "^18.2.0",
|
|
53
|
+
"@mysten/bcs": "^1.6.1",
|
|
54
|
+
"@mysten/utils": "^0.0.0",
|
|
53
55
|
"@pythnetwork/price-service-client": "^1.9.0",
|
|
54
56
|
"@pythnetwork/price-service-sdk": "^1.8.0",
|
|
55
57
|
"@types/node": "^20.4.2",
|
|
@@ -71,11 +73,13 @@
|
|
|
71
73
|
"tsup": "^7.2.0",
|
|
72
74
|
"typedoc": "^0.26.3",
|
|
73
75
|
"typescript": "5.5.4",
|
|
76
|
+
"valibot": "^1.1.0",
|
|
77
|
+
"vite": "^6.3.5",
|
|
74
78
|
"vitest": "^3.1.1"
|
|
75
79
|
},
|
|
76
80
|
"peerDependencies": {
|
|
77
81
|
"@mysten/sui": "1.28.2",
|
|
78
|
-
"@scallop-io/sui-kit": "1.4.
|
|
82
|
+
"@scallop-io/sui-kit": "1.4.1",
|
|
79
83
|
"bn.js": "^5.2.1"
|
|
80
84
|
},
|
|
81
85
|
"lint-staged": {
|
|
@@ -25,8 +25,24 @@ export const updateOracles = async (
|
|
|
25
25
|
options: {
|
|
26
26
|
usePythPullModel: boolean;
|
|
27
27
|
useOnChainXOracleList: boolean;
|
|
28
|
-
|
|
28
|
+
sponsoredFeeds: string[];
|
|
29
|
+
} = {
|
|
30
|
+
usePythPullModel: true,
|
|
31
|
+
useOnChainXOracleList: true,
|
|
32
|
+
sponsoredFeeds: [],
|
|
33
|
+
}
|
|
29
34
|
) => {
|
|
35
|
+
const sponsoredFeeds = new Set(
|
|
36
|
+
builder.sponsoredFeeds ?? options.sponsoredFeeds
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Validate the sponsoredFeeds content.
|
|
40
|
+
sponsoredFeeds.forEach((feed) => {
|
|
41
|
+
if (!builder.constants.whitelist.lending.has(feed)) {
|
|
42
|
+
throw new Error(`${feed} is not valid feed`);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
30
46
|
const usePythPullModel = builder.usePythPullModel ?? options.usePythPullModel;
|
|
31
47
|
const useOnChainXOracleList =
|
|
32
48
|
builder.useOnChainXOracleList ?? options.useOnChainXOracleList;
|
|
@@ -55,17 +71,32 @@ export const updateOracles = async (
|
|
|
55
71
|
);
|
|
56
72
|
};
|
|
57
73
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
74
|
+
const updateAssetCoinNames = [...new Set(assetCoinNames)];
|
|
75
|
+
const pythAssetCoinNames = updateAssetCoinNames.filter((assetCoinName) =>
|
|
76
|
+
filterAssetCoinNames(assetCoinName, 'pyth')
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (flattenedRules.has('pyth')) {
|
|
80
|
+
const needToUpdatePythPriceFeeds: string[] = [];
|
|
81
|
+
for (const pythAssetCoinName of pythAssetCoinNames) {
|
|
82
|
+
/**
|
|
83
|
+
* Check if the Pyth pull model is not used but the feed is not sponsored.
|
|
84
|
+
* This is used to determine if we should update the Pyth price feeds.
|
|
85
|
+
*/
|
|
86
|
+
const notUsingPullButNotSponsored =
|
|
87
|
+
!usePythPullModel && !sponsoredFeeds.has(pythAssetCoinName);
|
|
88
|
+
|
|
89
|
+
if (usePythPullModel || notUsingPullButNotSponsored) {
|
|
90
|
+
needToUpdatePythPriceFeeds.push(pythAssetCoinName);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (needToUpdatePythPriceFeeds.length > 0) {
|
|
95
|
+
await updatePythPriceFeeds(builder, needToUpdatePythPriceFeeds, txBlock);
|
|
96
|
+
}
|
|
65
97
|
}
|
|
66
98
|
|
|
67
99
|
// Remove duplicate coin names.
|
|
68
|
-
const updateAssetCoinNames = [...new Set(assetCoinNames)];
|
|
69
100
|
for (const assetCoinName of updateAssetCoinNames) {
|
|
70
101
|
updateOracle(builder, txBlock, assetCoinName, xOracleList[assetCoinName]);
|
|
71
102
|
}
|
|
@@ -47,7 +47,7 @@ export const requireVeSca = async (
|
|
|
47
47
|
...params: [
|
|
48
48
|
builder: ScallopBuilder,
|
|
49
49
|
SuiTxBlock: SuiTxBlock,
|
|
50
|
-
veScaKey?: SuiObjectData,
|
|
50
|
+
veScaKey?: SuiObjectData | string,
|
|
51
51
|
]
|
|
52
52
|
) => {
|
|
53
53
|
const [builder, txBlock, veScaKey] = params;
|
|
@@ -259,12 +259,12 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
259
259
|
txBlock,
|
|
260
260
|
}) => {
|
|
261
261
|
return {
|
|
262
|
-
lockScaQuick: async (
|
|
262
|
+
lockScaQuick: async ({
|
|
263
263
|
amountOrCoin,
|
|
264
264
|
lockPeriodInDays,
|
|
265
|
+
autoCheck = true,
|
|
265
266
|
veScaKey,
|
|
266
|
-
|
|
267
|
-
) => {
|
|
267
|
+
}) => {
|
|
268
268
|
const sender = requireSender(txBlock);
|
|
269
269
|
const veSca = await requireVeSca(builder, txBlock, veScaKey);
|
|
270
270
|
|
|
@@ -334,11 +334,11 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
334
334
|
txBlock.transferObjects(transferObjects, sender);
|
|
335
335
|
}
|
|
336
336
|
},
|
|
337
|
-
extendLockPeriodQuick: async (
|
|
338
|
-
lockPeriodInDays
|
|
339
|
-
veScaKey
|
|
340
|
-
autoCheck = true
|
|
341
|
-
) => {
|
|
337
|
+
extendLockPeriodQuick: async ({
|
|
338
|
+
lockPeriodInDays,
|
|
339
|
+
veScaKey,
|
|
340
|
+
autoCheck = true,
|
|
341
|
+
}) => {
|
|
342
342
|
const veSca = await requireVeSca(builder, txBlock, veScaKey);
|
|
343
343
|
const newUnlockAt = builder.utils.getUnlockAt(
|
|
344
344
|
lockPeriodInDays,
|
|
@@ -352,11 +352,11 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
352
352
|
txBlock.extendLockPeriod(veSca.keyId, newUnlockAt);
|
|
353
353
|
}
|
|
354
354
|
},
|
|
355
|
-
extendLockAmountQuick: async (
|
|
356
|
-
scaAmount
|
|
357
|
-
veScaKey
|
|
358
|
-
autoCheck = true
|
|
359
|
-
) => {
|
|
355
|
+
extendLockAmountQuick: async ({
|
|
356
|
+
scaAmount,
|
|
357
|
+
veScaKey,
|
|
358
|
+
autoCheck = true,
|
|
359
|
+
}) => {
|
|
360
360
|
const sender = requireSender(txBlock);
|
|
361
361
|
const veSca = await requireVeSca(builder, txBlock, veScaKey);
|
|
362
362
|
|
|
@@ -377,12 +377,12 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
377
377
|
txBlock.transferObjects([leftCoin], sender);
|
|
378
378
|
}
|
|
379
379
|
},
|
|
380
|
-
renewExpiredVeScaQuick: async (
|
|
381
|
-
scaAmount
|
|
382
|
-
lockPeriodInDays
|
|
383
|
-
veScaKey
|
|
384
|
-
autoCheck = true
|
|
385
|
-
) => {
|
|
380
|
+
renewExpiredVeScaQuick: async ({
|
|
381
|
+
scaAmount,
|
|
382
|
+
lockPeriodInDays,
|
|
383
|
+
veScaKey,
|
|
384
|
+
autoCheck = true,
|
|
385
|
+
}) => {
|
|
386
386
|
const sender = requireSender(txBlock);
|
|
387
387
|
const veSca = await requireVeSca(builder, txBlock, veScaKey);
|
|
388
388
|
|
|
@@ -414,10 +414,13 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
414
414
|
txBlock.transferObjects(transferObjects, sender);
|
|
415
415
|
}
|
|
416
416
|
},
|
|
417
|
-
redeemScaQuick: async <
|
|
418
|
-
veScaKey
|
|
419
|
-
transferSca
|
|
420
|
-
|
|
417
|
+
redeemScaQuick: async <T extends boolean>({
|
|
418
|
+
veScaKey,
|
|
419
|
+
transferSca,
|
|
420
|
+
}: {
|
|
421
|
+
veScaKey?: SuiObjectData | string;
|
|
422
|
+
transferSca?: T;
|
|
423
|
+
}) => {
|
|
421
424
|
const sender = requireSender(txBlock);
|
|
422
425
|
const veSca = await requireVeSca(builder, txBlock, veScaKey);
|
|
423
426
|
|
|
@@ -429,14 +432,18 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
429
432
|
txBlock.transferObjects([sca], sender);
|
|
430
433
|
return;
|
|
431
434
|
}
|
|
432
|
-
return sca as QuickMethodReturnType<
|
|
435
|
+
return sca as QuickMethodReturnType<T>;
|
|
433
436
|
}
|
|
434
437
|
},
|
|
435
|
-
splitVeScaQuick: async <S extends boolean>(
|
|
436
|
-
splitAmount
|
|
437
|
-
veScaKey
|
|
438
|
-
transferVeScaKey
|
|
439
|
-
|
|
438
|
+
splitVeScaQuick: async <S extends boolean>({
|
|
439
|
+
splitAmount,
|
|
440
|
+
veScaKey,
|
|
441
|
+
transferVeScaKey = true as S,
|
|
442
|
+
}: {
|
|
443
|
+
splitAmount: string;
|
|
444
|
+
veScaKey: string;
|
|
445
|
+
transferVeScaKey?: S;
|
|
446
|
+
}) => {
|
|
440
447
|
const isKeyInSubTable = await isInSubsTable(
|
|
441
448
|
builder,
|
|
442
449
|
veScaKey,
|
|
@@ -465,12 +472,12 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
465
472
|
return newVeScaKey as QuickMethodReturnType<S>;
|
|
466
473
|
}
|
|
467
474
|
},
|
|
468
|
-
mergeVeScaQuick: async (
|
|
475
|
+
mergeVeScaQuick: async ({ targetVeScaKey, sourceVeScaKey }) => {
|
|
469
476
|
// check targetKey and sourceKey
|
|
470
477
|
const table = builder.address.get('vesca.subsTableId');
|
|
471
478
|
const [isTargetInSubTable, isSourceInSubTable] = await Promise.all([
|
|
472
|
-
isInSubsTable(builder,
|
|
473
|
-
isInSubsTable(builder,
|
|
479
|
+
isInSubsTable(builder, targetVeScaKey, table),
|
|
480
|
+
isInSubsTable(builder, sourceVeScaKey, table),
|
|
474
481
|
]);
|
|
475
482
|
|
|
476
483
|
const unstakeObligationBeforeStake =
|
|
@@ -491,8 +498,8 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
491
498
|
}
|
|
492
499
|
|
|
493
500
|
const [sourceVesca, targetVesca] = await Promise.all([
|
|
494
|
-
getVeSca(builder.utils,
|
|
495
|
-
getVeSca(builder.utils,
|
|
501
|
+
getVeSca(builder.utils, sourceVeScaKey),
|
|
502
|
+
getVeSca(builder.utils, targetVeScaKey),
|
|
496
503
|
]);
|
|
497
504
|
|
|
498
505
|
if (!sourceVesca || !targetVesca) {
|
|
@@ -512,7 +519,7 @@ const generateQuickVeScaMethod: GenerateVeScaQuickMethod = ({
|
|
|
512
519
|
);
|
|
513
520
|
}
|
|
514
521
|
|
|
515
|
-
return txBlock.mergeVeSca(
|
|
522
|
+
return txBlock.mergeVeSca(targetVeScaKey, sourceVeScaKey);
|
|
516
523
|
},
|
|
517
524
|
};
|
|
518
525
|
};
|
|
@@ -18,6 +18,7 @@ import { ScallopBuilderInterface } from './interface';
|
|
|
18
18
|
export type ScallopBuilderParams = {
|
|
19
19
|
query?: ScallopQuery;
|
|
20
20
|
usePythPullModel?: boolean;
|
|
21
|
+
sponsoredFeeds?: string[];
|
|
21
22
|
useOnChainXOracleList?: boolean;
|
|
22
23
|
} & ScallopQueryParams;
|
|
23
24
|
|
|
@@ -36,11 +37,13 @@ class ScallopBuilder implements ScallopBuilderInterface {
|
|
|
36
37
|
public readonly query: ScallopQuery;
|
|
37
38
|
public readonly usePythPullModel: boolean;
|
|
38
39
|
public readonly useOnChainXOracleList: boolean;
|
|
40
|
+
public readonly sponsoredFeeds: string[];
|
|
39
41
|
|
|
40
42
|
public constructor(params: ScallopBuilderParams) {
|
|
41
43
|
this.query = params.query ?? new ScallopQuery(params);
|
|
42
44
|
this.usePythPullModel = params.usePythPullModel ?? true;
|
|
43
45
|
this.useOnChainXOracleList = params.useOnChainXOracleList ?? true;
|
|
46
|
+
this.sponsoredFeeds = params.sponsoredFeeds ?? [];
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
get utils() {
|
|
@@ -1085,9 +1085,12 @@ class ScallopClient implements ScallopClientInterface {
|
|
|
1085
1085
|
tx.setSender(sender);
|
|
1086
1086
|
|
|
1087
1087
|
await Promise.all(
|
|
1088
|
-
veScaKeys.map(async (
|
|
1088
|
+
veScaKeys.map(async (veScaKey) => {
|
|
1089
1089
|
try {
|
|
1090
|
-
const scaCoin = await tx.redeemScaQuick(
|
|
1090
|
+
const scaCoin = await tx.redeemScaQuick({
|
|
1091
|
+
veScaKey,
|
|
1092
|
+
transferSca: false,
|
|
1093
|
+
});
|
|
1091
1094
|
if (!scaCoin) return;
|
|
1092
1095
|
scaCoins.push(scaCoin);
|
|
1093
1096
|
} catch (_e) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SuiTxBlock as SuiKitTxBlock, SuiObjectArg } from '@scallop-io/sui-kit';
|
|
2
2
|
import type { TransactionResult } from '@mysten/sui/transactions';
|
|
3
3
|
import { ScallopBuilder } from 'src/models';
|
|
4
|
+
import { SuiObjectData } from '@mysten/sui/client';
|
|
4
5
|
|
|
5
6
|
export type VeScaNormalMethods = {
|
|
6
7
|
lockSca: (
|
|
@@ -31,7 +32,7 @@ export type VeScaNormalMethods = {
|
|
|
31
32
|
|
|
32
33
|
export type QuickMethodReturnType<T extends boolean> = T extends true
|
|
33
34
|
? void
|
|
34
|
-
: TransactionResult
|
|
35
|
+
: TransactionResult;
|
|
35
36
|
|
|
36
37
|
export type VeScaQuickMethods = {
|
|
37
38
|
/**
|
|
@@ -50,41 +51,41 @@ export type VeScaQuickMethods = {
|
|
|
50
51
|
* @param lockPeriodInDays
|
|
51
52
|
* @param autoCheck
|
|
52
53
|
*/
|
|
53
|
-
lockScaQuick(
|
|
54
|
-
amountOrCoin?: SuiObjectArg | number
|
|
55
|
-
lockPeriodInDays?: number
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
): Promise<void>;
|
|
59
|
-
extendLockPeriodQuick: (
|
|
60
|
-
lockPeriodInDays: number
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
) => Promise<void>;
|
|
64
|
-
extendLockAmountQuick: (
|
|
65
|
-
scaAmount: number
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
) => Promise<void>;
|
|
69
|
-
renewExpiredVeScaQuick: (
|
|
70
|
-
scaAmount: number
|
|
71
|
-
lockPeriodInDays: number
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
) => Promise<void>;
|
|
75
|
-
redeemScaQuick: <T extends boolean>(
|
|
76
|
-
veScaKey?:
|
|
77
|
-
transferSca?: T
|
|
78
|
-
) => Promise<QuickMethodReturnType<T
|
|
79
|
-
splitVeScaQuick: <T extends boolean>(
|
|
80
|
-
splitAmount: string
|
|
81
|
-
veScaKey: string
|
|
82
|
-
transferVeScaKey?: T
|
|
83
|
-
) => Promise<QuickMethodReturnType<T
|
|
84
|
-
mergeVeScaQuick: (
|
|
85
|
-
targetVeScaKey: string
|
|
86
|
-
sourceVeScaKey: string
|
|
87
|
-
) => Promise<void>;
|
|
54
|
+
lockScaQuick(params: {
|
|
55
|
+
amountOrCoin?: SuiObjectArg | number;
|
|
56
|
+
lockPeriodInDays?: number;
|
|
57
|
+
autoCheck?: boolean;
|
|
58
|
+
veScaKey?: SuiObjectData | string;
|
|
59
|
+
}): Promise<void>;
|
|
60
|
+
extendLockPeriodQuick: (params: {
|
|
61
|
+
lockPeriodInDays: number;
|
|
62
|
+
autoCheck?: boolean;
|
|
63
|
+
veScaKey?: SuiObjectData | string;
|
|
64
|
+
}) => Promise<void>;
|
|
65
|
+
extendLockAmountQuick: (params: {
|
|
66
|
+
scaAmount: number;
|
|
67
|
+
autoCheck?: boolean;
|
|
68
|
+
veScaKey?: SuiObjectData | string;
|
|
69
|
+
}) => Promise<void>;
|
|
70
|
+
renewExpiredVeScaQuick: (params: {
|
|
71
|
+
scaAmount: number;
|
|
72
|
+
lockPeriodInDays: number;
|
|
73
|
+
autoCheck?: boolean;
|
|
74
|
+
veScaKey?: SuiObjectData | string;
|
|
75
|
+
}) => Promise<void>;
|
|
76
|
+
redeemScaQuick: <T extends boolean>(params: {
|
|
77
|
+
veScaKey?: SuiObjectData | string;
|
|
78
|
+
transferSca?: T;
|
|
79
|
+
}) => Promise<QuickMethodReturnType<T> | undefined>;
|
|
80
|
+
splitVeScaQuick: <T extends boolean>(params: {
|
|
81
|
+
splitAmount: string;
|
|
82
|
+
veScaKey: string;
|
|
83
|
+
transferVeScaKey?: T;
|
|
84
|
+
}) => Promise<QuickMethodReturnType<T> | undefined>;
|
|
85
|
+
mergeVeScaQuick: (params: {
|
|
86
|
+
targetVeScaKey: string;
|
|
87
|
+
sourceVeScaKey: string;
|
|
88
|
+
}) => Promise<void>;
|
|
88
89
|
};
|
|
89
90
|
|
|
90
91
|
export type SuiTxBlockWithVeScaNormalMethods = SuiKitTxBlock &
|