@scallop-io/sui-scallop-sdk 2.0.0-alpha.6 → 2.0.0-alpha.7
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 +17 -5
- package/dist/index.d.ts +17 -5
- package/dist/index.js +29 -27
- package/dist/index.mjs +6 -4
- package/package.json +4 -1
- package/src/builders/coreBuilder.ts +33 -33
- package/src/builders/{oracle.ts → oracles/index.ts} +45 -43
- package/src/builders/oracles/pyth.ts +44 -0
- package/src/builders/oracles/switchboard.ts +270 -0
- package/src/constants/testAddress.ts +36 -487
- package/src/models/scallopAddress.ts +10 -1
- package/src/models/scallopQuery.ts +13 -9
- package/src/queries/coreQuery.ts +4 -2
- package/src/queries/index.ts +1 -0
- package/src/queries/poolAddressesQuery.ts +0 -1
- package/src/queries/switchboardQuery.ts +64 -0
- package/src/queries/xOracleQuery.ts +29 -21
- package/src/types/address.ts +11 -3
- package/src/types/constant/xOracle.ts +5 -2
|
@@ -43,15 +43,9 @@ import {
|
|
|
43
43
|
getUserPortfolio,
|
|
44
44
|
getPriceUpdatePolicies,
|
|
45
45
|
getAssetOracles,
|
|
46
|
+
getOnDemandAggObjectIds,
|
|
46
47
|
} from '../queries';
|
|
47
48
|
import {
|
|
48
|
-
// string,
|
|
49
|
-
// string,
|
|
50
|
-
// string,
|
|
51
|
-
// string,
|
|
52
|
-
// string,
|
|
53
|
-
// string,
|
|
54
|
-
// string,
|
|
55
49
|
ScallopQueryParams,
|
|
56
50
|
StakePools,
|
|
57
51
|
StakeRewardPools,
|
|
@@ -61,6 +55,7 @@ import {
|
|
|
61
55
|
MarketPools,
|
|
62
56
|
MarketCollaterals,
|
|
63
57
|
xOracleRules,
|
|
58
|
+
SupportOracleType,
|
|
64
59
|
} from '../types';
|
|
65
60
|
import { ScallopAddress } from './scallopAddress';
|
|
66
61
|
import { ScallopUtils } from './scallopUtils';
|
|
@@ -911,12 +906,21 @@ export class ScallopQuery {
|
|
|
911
906
|
return [...this.constants.whitelist.lending].reduce(
|
|
912
907
|
(acc, pool) => {
|
|
913
908
|
acc[pool] = {
|
|
914
|
-
primary: primary?.[pool] ?? [],
|
|
915
|
-
secondary: secondary?.[pool] ?? [],
|
|
909
|
+
primary: (primary?.[pool] ?? []) as SupportOracleType[],
|
|
910
|
+
secondary: (secondary?.[pool] ?? []) as SupportOracleType[],
|
|
916
911
|
};
|
|
917
912
|
return acc;
|
|
918
913
|
},
|
|
919
914
|
{} as Record<string, xOracleRules>
|
|
920
915
|
);
|
|
921
916
|
}
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Get switchboard on-demand aggregator object id based on coinType
|
|
920
|
+
* @param coinType
|
|
921
|
+
* @returns
|
|
922
|
+
*/
|
|
923
|
+
public async getSwitchboardOnDemandAggregatorObjectIds(coinName: string[]) {
|
|
924
|
+
return await getOnDemandAggObjectIds(this, coinName);
|
|
925
|
+
}
|
|
922
926
|
}
|
package/src/queries/coreQuery.ts
CHANGED
|
@@ -496,7 +496,7 @@ const parseMarketPoolObjects = ({
|
|
|
496
496
|
collateralStat?: SuiObjectData;
|
|
497
497
|
interestModel: SuiObjectData;
|
|
498
498
|
riskModel?: SuiObjectData;
|
|
499
|
-
borrowFeeKey
|
|
499
|
+
borrowFeeKey?: SuiObjectData;
|
|
500
500
|
supplyLimitKey?: SuiObjectData;
|
|
501
501
|
borrowLimitKey?: SuiObjectData;
|
|
502
502
|
isolatedAssetKey: SuiObjectData;
|
|
@@ -506,7 +506,9 @@ const parseMarketPoolObjects = ({
|
|
|
506
506
|
const _balanceSheet = parseObjectAs<BalanceSheet>(balanceSheet);
|
|
507
507
|
const _interestModel = parseObjectAs<InterestModel>(interestModel);
|
|
508
508
|
const _borrowDynamic = parseObjectAs<BorrowDynamic>(borrowDynamic);
|
|
509
|
-
const _borrowFee =
|
|
509
|
+
const _borrowFee = borrowFeeKey
|
|
510
|
+
? parseObjectAs<BorrowFee>(borrowFeeKey)
|
|
511
|
+
: { value: '0' };
|
|
510
512
|
const _supplyLimit = supplyLimitKey
|
|
511
513
|
? parseObjectAs<string>(supplyLimitKey)
|
|
512
514
|
: '0';
|
package/src/queries/index.ts
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ScallopQuery } from 'src/models';
|
|
2
|
+
|
|
3
|
+
export const getOnDemandAggObjectIds = async (
|
|
4
|
+
query: ScallopQuery,
|
|
5
|
+
coinNames: string[],
|
|
6
|
+
switchboardRegistryTableId: string = query.address.get(
|
|
7
|
+
'core.oracles.switchboard.registryTableId'
|
|
8
|
+
)
|
|
9
|
+
): Promise<string[]> => {
|
|
10
|
+
const missingAgg: Array<{
|
|
11
|
+
idx: number;
|
|
12
|
+
coinName: string;
|
|
13
|
+
}> = [];
|
|
14
|
+
|
|
15
|
+
// Check if Aggregator is already registered in Address API
|
|
16
|
+
const registeredAggs = coinNames.map((coinName, idx) => {
|
|
17
|
+
const registeredAgg = query.utils.address.get(
|
|
18
|
+
`core.coins.${coinName}.oracle.switchboard`
|
|
19
|
+
);
|
|
20
|
+
if (registeredAgg) {
|
|
21
|
+
return registeredAgg;
|
|
22
|
+
} else {
|
|
23
|
+
missingAgg.push({
|
|
24
|
+
idx,
|
|
25
|
+
coinName,
|
|
26
|
+
});
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (missingAgg.length === 0) return registeredAggs;
|
|
32
|
+
|
|
33
|
+
// If not, query from the registry table
|
|
34
|
+
const missingCoinNames = missingAgg.map((agg) => agg.coinName);
|
|
35
|
+
const coinTypes = missingCoinNames.map((coinName) => {
|
|
36
|
+
const coinType = query.utils.parseCoinType(coinName);
|
|
37
|
+
if (!coinType) throw new Error(`Invalid coin name: ${coinName}`);
|
|
38
|
+
return coinType;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
await Promise.all(
|
|
42
|
+
coinTypes.map(async (coinType, idx) => {
|
|
43
|
+
const dfName = {
|
|
44
|
+
type: '0x1::type_name::TypeName',
|
|
45
|
+
value: {
|
|
46
|
+
name: coinType.slice(2),
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const resp = await query.cache.queryGetDynamicFieldObject({
|
|
51
|
+
parentId: switchboardRegistryTableId,
|
|
52
|
+
name: dfName,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (!resp?.data?.content || resp.data.content.dataType !== 'moveObject')
|
|
56
|
+
throw new Error(`No on-demand aggregator found for ${coinType}`);
|
|
57
|
+
|
|
58
|
+
const content = resp.data.content;
|
|
59
|
+
registeredAggs[idx] = (content.fields as any).value;
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return registeredAggs;
|
|
64
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { SuiObjectResponse } from '@mysten/sui/client';
|
|
2
2
|
import { ScallopAddress, ScallopUtils } from 'src/models';
|
|
3
|
-
import { xOracleRuleType } from 'src/types';
|
|
3
|
+
import { SupportOracleType, xOracleRuleType } from 'src/types';
|
|
4
4
|
|
|
5
|
-
const PRIMARY_PRICE_UPDATE_POLICY =
|
|
6
|
-
|
|
7
|
-
const SECONDARY_PRICE_UPDDATE_POLICY =
|
|
8
|
-
|
|
5
|
+
// const PRIMARY_PRICE_UPDATE_POLICY =
|
|
6
|
+
// '0x56e48a141f20a3a6a6d3fc43e58b01fc63f756c08224870e7890c80ec9d2afee';
|
|
7
|
+
// const SECONDARY_PRICE_UPDDATE_POLICY =
|
|
8
|
+
// '0xef4d9430ae42c1b24199ac55e87ddd7262622447ee3c7de8868efe839b3d8705';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Query the price update policy table ids. Usually the value for these table will be constant.
|
|
@@ -22,14 +22,14 @@ export const getPriceUpdatePolicies = async (
|
|
|
22
22
|
const [primaryPriceUpdatePolicyTable, secondaryPriceUpdatePolicyTable] =
|
|
23
23
|
await Promise.all([
|
|
24
24
|
address.cache.queryGetDynamicFieldObject({
|
|
25
|
-
parentId:
|
|
25
|
+
parentId: address.get('core.oracles.primaryPriceUpdatePolicyObject'),
|
|
26
26
|
name: {
|
|
27
27
|
type: priceUpdatePolicyRulesKeyType,
|
|
28
28
|
value: { dummy_field: false },
|
|
29
29
|
},
|
|
30
30
|
}),
|
|
31
31
|
address.cache.queryGetDynamicFieldObject({
|
|
32
|
-
parentId:
|
|
32
|
+
parentId: address.get('core.oracles.secondaryPriceUpdatePolicyObject'),
|
|
33
33
|
name: {
|
|
34
34
|
type: priceUpdatePolicyRulesKeyType,
|
|
35
35
|
value: { dummy_field: false },
|
|
@@ -43,39 +43,47 @@ export const getPriceUpdatePolicies = async (
|
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
const PRIMARY_PRICE_UPDATE_POLICY_VECSET_ID =
|
|
47
|
-
|
|
48
|
-
const SECONDARY_PRICE_UPDATE_POLICY_VECSET_ID =
|
|
49
|
-
|
|
46
|
+
// const PRIMARY_PRICE_UPDATE_POLICY_VECSET_ID =
|
|
47
|
+
// '0xc22c9d691ee4c780de09db91d8b487d863211ebf08720772144bcf716318826c';
|
|
48
|
+
// const SECONDARY_PRICE_UPDATE_POLICY_VECSET_ID =
|
|
49
|
+
// '0x3b184ff859f5de30eeaf186898e5224925be6bb6d2baa74347ef471a8cd1c0d3';
|
|
50
50
|
|
|
51
51
|
export const getAssetOracles = async (
|
|
52
52
|
utils: ScallopUtils,
|
|
53
53
|
ruleType: xOracleRuleType
|
|
54
54
|
): Promise<Record<string, string[]> | null> => {
|
|
55
|
-
if (
|
|
55
|
+
if (
|
|
56
|
+
ruleType === 'primary' &&
|
|
57
|
+
!utils.address.get('core.oracles.primaryPriceUpdatePolicyVecsetId')
|
|
58
|
+
) {
|
|
56
59
|
console.error('Primary price update policy vecset id is not set');
|
|
57
60
|
return null;
|
|
58
61
|
}
|
|
59
|
-
if (
|
|
62
|
+
if (
|
|
63
|
+
ruleType === 'secondary' &&
|
|
64
|
+
!utils.address.get('core.oracles.secondaryPriceUpdatePolicyVecsetId')
|
|
65
|
+
) {
|
|
60
66
|
console.error('Secondary price update policy vecset id is not set');
|
|
61
67
|
return null;
|
|
62
68
|
}
|
|
63
69
|
|
|
64
|
-
const ruleTypeNameToOracleType: Record<string,
|
|
70
|
+
const ruleTypeNameToOracleType: Record<string, SupportOracleType> = {
|
|
65
71
|
[`${utils.address.get('core.packages.pyth.object')}::rule::Rule`]: 'pyth',
|
|
66
72
|
[`${utils.address.get('core.packages.supra.object')}::rule::Rule`]: 'supra',
|
|
67
73
|
[`${utils.address.get('core.packages.switchboard.object')}::rule::Rule`]:
|
|
68
74
|
'switchboard',
|
|
69
75
|
};
|
|
70
76
|
|
|
71
|
-
const
|
|
77
|
+
const assetOracles = {} as Record<string, SupportOracleType[]>;
|
|
72
78
|
let cursor = null;
|
|
73
79
|
do {
|
|
74
80
|
const response = await utils.cache.queryGetDynamicFields({
|
|
75
81
|
parentId:
|
|
76
82
|
ruleType === 'primary'
|
|
77
|
-
?
|
|
78
|
-
:
|
|
83
|
+
? utils.address.get('core.oracles.primaryPriceUpdatePolicyVecsetId')
|
|
84
|
+
: utils.address.get(
|
|
85
|
+
'core.oracles.secondaryPriceUpdatePolicyVecsetId'
|
|
86
|
+
),
|
|
79
87
|
cursor,
|
|
80
88
|
limit: 10,
|
|
81
89
|
});
|
|
@@ -97,8 +105,8 @@ export const getAssetOracles = async (
|
|
|
97
105
|
|
|
98
106
|
const assetName = utils.parseCoinNameFromType(`0x${typeName}`);
|
|
99
107
|
if (!assetName) throw new Error(`Invalid asset name: ${assetName}`);
|
|
100
|
-
if (!
|
|
101
|
-
|
|
108
|
+
if (!assetOracles[assetName]) {
|
|
109
|
+
assetOracles[assetName] = [];
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
const value = fields.value as {
|
|
@@ -109,7 +117,7 @@ export const getAssetOracles = async (
|
|
|
109
117
|
};
|
|
110
118
|
|
|
111
119
|
value.fields.contents.forEach((content) => {
|
|
112
|
-
|
|
120
|
+
assetOracles[assetName].push(
|
|
113
121
|
ruleTypeNameToOracleType[`0x${content.fields.name}`]
|
|
114
122
|
);
|
|
115
123
|
});
|
|
@@ -117,5 +125,5 @@ export const getAssetOracles = async (
|
|
|
117
125
|
if (!hasNextPage) break;
|
|
118
126
|
} while (cursor);
|
|
119
127
|
|
|
120
|
-
return
|
|
128
|
+
return assetOracles;
|
|
121
129
|
};
|
package/src/types/address.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
type SupportOracleType = (typeof _SUPPORT_ORACLES)[number];
|
|
1
|
+
import { _SUPPORT_ORACLES, SupportOracleType } from './constant/xOracle';
|
|
3
2
|
|
|
4
3
|
export interface AddressesInterface {
|
|
5
4
|
core: {
|
|
@@ -46,6 +45,8 @@ export interface AddressesInterface {
|
|
|
46
45
|
? {
|
|
47
46
|
registry: string;
|
|
48
47
|
registryCap: string;
|
|
48
|
+
registryTableId: string;
|
|
49
|
+
state: string;
|
|
49
50
|
}
|
|
50
51
|
: K extends (typeof _SUPPORT_ORACLES)[2]
|
|
51
52
|
? {
|
|
@@ -56,7 +57,14 @@ export interface AddressesInterface {
|
|
|
56
57
|
wormholeState: string;
|
|
57
58
|
}
|
|
58
59
|
: never;
|
|
59
|
-
} & {
|
|
60
|
+
} & {
|
|
61
|
+
xOracle: string;
|
|
62
|
+
xOracleCap: string;
|
|
63
|
+
primaryPriceUpdatePolicyObject: string;
|
|
64
|
+
secondaryPriceUpdatePolicyObject: string;
|
|
65
|
+
primaryPriceUpdatePolicyVecsetId: string;
|
|
66
|
+
secondaryPriceUpdatePolicyVecsetId: string;
|
|
67
|
+
};
|
|
60
68
|
packages: Partial<
|
|
61
69
|
Record<
|
|
62
70
|
string,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
export const _SUPPORT_ORACLES = ['supra', 'switchboard', 'pyth'] as const;
|
|
2
|
+
export type SupportOracleType = (typeof _SUPPORT_ORACLES)[number];
|
|
3
|
+
|
|
1
4
|
export type xOracleRules = {
|
|
2
|
-
primary:
|
|
3
|
-
secondary:
|
|
5
|
+
primary: SupportOracleType[];
|
|
6
|
+
secondary: SupportOracleType[];
|
|
4
7
|
};
|
|
5
8
|
export type xOracleRuleType = keyof xOracleRules;
|
|
6
9
|
|