@scallop-io/sui-scallop-sdk 1.3.0-alpha.3 → 1.3.0-alpha.4
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.js +102 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +102 -17
- package/dist/index.mjs.map +1 -1
- package/dist/models/scallopQuery.d.ts +8 -0
- package/dist/queries/isolatedAsset.d.ts +14 -0
- package/dist/types/query/core.d.ts +1 -0
- package/dist/types/query/portfolio.d.ts +1 -1
- package/package.json +1 -1
- package/src/constants/common.ts +2 -2
- package/src/models/scallopQuery.ts +15 -0
- package/src/queries/coreQuery.ts +3 -0
- package/src/queries/isolatedAsset.ts +105 -0
- package/src/queries/portfolioQuery.ts +1 -0
- package/src/queries/supplyLimit.ts +2 -2
- package/src/types/query/core.ts +1 -0
- package/src/types/query/portfolio.ts +1 -0
- package/src/utils/tokenBucket.ts +1 -1
- package/dist/test.d.ts +0 -1
- package/src/test.ts +0 -26
|
@@ -457,4 +457,12 @@ export declare class ScallopQuery {
|
|
|
457
457
|
* Get supply limit of supply pool
|
|
458
458
|
*/
|
|
459
459
|
getPoolSupplyLimit(poolName: SupportPoolCoins): Promise<string | null>;
|
|
460
|
+
/**
|
|
461
|
+
* Get list of isolated assets
|
|
462
|
+
*/
|
|
463
|
+
getIsolatedAssets(): Promise<string[]>;
|
|
464
|
+
/**
|
|
465
|
+
* Check if asset is an isolated asset
|
|
466
|
+
*/
|
|
467
|
+
isIsolatedAsset(assetCoinName: SupportAssetCoins): Promise<boolean>;
|
|
460
468
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ScallopAddress, ScallopUtils } from 'src/models';
|
|
2
|
+
import { SupportPoolCoins } from 'src/types';
|
|
3
|
+
/**
|
|
4
|
+
* Return list of isolated assets coin types
|
|
5
|
+
* @param utils ScallopUtils
|
|
6
|
+
* @returns list of isolated assets coin types
|
|
7
|
+
*/
|
|
8
|
+
export declare const getIsolatedAssets: (address: ScallopAddress) => Promise<string[]>;
|
|
9
|
+
/**
|
|
10
|
+
* Check if the coin type is an isolated asset
|
|
11
|
+
* @param coinName coin name
|
|
12
|
+
* @returns true if the coin type is an isolated asset
|
|
13
|
+
*/
|
|
14
|
+
export declare const isIsolatedAsset: (utils: ScallopUtils, coinName: SupportPoolCoins) => Promise<boolean>;
|
|
@@ -123,6 +123,7 @@ export type MarketPool = {
|
|
|
123
123
|
coinDecimal: number;
|
|
124
124
|
coinPrice: number;
|
|
125
125
|
maxSupplyCoin: number;
|
|
126
|
+
isIsolated: boolean;
|
|
126
127
|
} & Required<Pick<ParsedMarketPoolData, 'highKink' | 'midKink' | 'reserveFactor' | 'borrowWeight' | 'borrowFee' | 'marketCoinSupplyAmount' | 'minBorrowAmount'>> & CalculatedMarketPoolData;
|
|
127
128
|
export type MarketCollateral = {
|
|
128
129
|
coinName: SupportCollateralCoins;
|
|
@@ -6,7 +6,7 @@ type OptionalKeys<T> = {
|
|
|
6
6
|
};
|
|
7
7
|
export type Lendings = OptionalKeys<Record<SupportPoolCoins, Lending>>;
|
|
8
8
|
export type ObligationAccounts = OptionalKeys<Record<string, ObligationAccount>>;
|
|
9
|
-
export type Lending = Required<Pick<MarketPool, 'coinName' | 'symbol' | 'coinType' | 'marketCoinType' | 'coinDecimal' | 'coinPrice' | 'conversionRate'> & Pick<Spool, 'marketCoinPrice'>> & {
|
|
9
|
+
export type Lending = Required<Pick<MarketPool, 'coinName' | 'symbol' | 'coinType' | 'marketCoinType' | 'coinDecimal' | 'coinPrice' | 'conversionRate' | 'isIsolated'> & Pick<Spool, 'marketCoinPrice'>> & {
|
|
10
10
|
supplyApr: number;
|
|
11
11
|
supplyApy: number;
|
|
12
12
|
rewardApr: number;
|
package/package.json
CHANGED
package/src/constants/common.ts
CHANGED
|
@@ -32,7 +32,7 @@ export const OLD_BORROW_INCENTIVE_PROTOCOL_ID =
|
|
|
32
32
|
|
|
33
33
|
export const SUPPORT_POOLS = [
|
|
34
34
|
'usdc', // native USDC
|
|
35
|
-
'sbeth', //
|
|
35
|
+
'sbeth', // sui bridge ETH
|
|
36
36
|
'weth',
|
|
37
37
|
'wbtc',
|
|
38
38
|
'wusdc',
|
|
@@ -49,7 +49,7 @@ export const SUPPORT_POOLS = [
|
|
|
49
49
|
|
|
50
50
|
export const SUPPORT_COLLATERALS = [
|
|
51
51
|
'usdc', // native USDC
|
|
52
|
-
'sbeth', //
|
|
52
|
+
'sbeth', // sui bridge ETH
|
|
53
53
|
'weth',
|
|
54
54
|
'wbtc',
|
|
55
55
|
'wusdc',
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
import { normalizeSuiAddress } from '@mysten/sui/utils';
|
|
64
64
|
import { getSupplyLimit } from 'src/queries/supplyLimit';
|
|
65
65
|
import { withIndexerFallback } from 'src/utils/indexer';
|
|
66
|
+
import { getIsolatedAssets, isIsolatedAsset } from 'src/queries/isolatedAsset';
|
|
66
67
|
|
|
67
68
|
/**
|
|
68
69
|
* @description
|
|
@@ -739,4 +740,18 @@ export class ScallopQuery {
|
|
|
739
740
|
public async getPoolSupplyLimit(poolName: SupportPoolCoins) {
|
|
740
741
|
return await getSupplyLimit(this.utils, poolName);
|
|
741
742
|
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Get list of isolated assets
|
|
746
|
+
*/
|
|
747
|
+
public async getIsolatedAssets() {
|
|
748
|
+
return await getIsolatedAssets(this.address);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Check if asset is an isolated asset
|
|
753
|
+
*/
|
|
754
|
+
public async isIsolatedAsset(assetCoinName: SupportAssetCoins) {
|
|
755
|
+
return isIsolatedAsset(this.utils, assetCoinName);
|
|
756
|
+
}
|
|
742
757
|
}
|
package/src/queries/coreQuery.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
} from '../types';
|
|
39
39
|
import BigNumber from 'bignumber.js';
|
|
40
40
|
import { getSupplyLimit } from './supplyLimit';
|
|
41
|
+
import { isIsolatedAsset } from './isolatedAsset';
|
|
41
42
|
|
|
42
43
|
/**
|
|
43
44
|
* Query market data.
|
|
@@ -155,6 +156,7 @@ export const queryMarket = async (
|
|
|
155
156
|
borrowFee: parsedMarketPoolData.borrowFee,
|
|
156
157
|
marketCoinSupplyAmount: parsedMarketPoolData.marketCoinSupplyAmount,
|
|
157
158
|
minBorrowAmount: parsedMarketPoolData.minBorrowAmount,
|
|
159
|
+
isIsolated: await isIsolatedAsset(query.utils, poolCoinName),
|
|
158
160
|
maxSupplyCoin,
|
|
159
161
|
...calculatedMarketPoolData,
|
|
160
162
|
};
|
|
@@ -492,6 +494,7 @@ export const getMarketPool = async (
|
|
|
492
494
|
marketCoinSupplyAmount: parsedMarketPoolData.marketCoinSupplyAmount,
|
|
493
495
|
minBorrowAmount: parsedMarketPoolData.minBorrowAmount,
|
|
494
496
|
maxSupplyCoin,
|
|
497
|
+
isIsolated: await isIsolatedAsset(query.utils, poolCoinName),
|
|
495
498
|
...calculatedMarketPoolData,
|
|
496
499
|
};
|
|
497
500
|
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { DynamicFieldInfo, DynamicFieldName } from '@mysten/sui/client';
|
|
2
|
+
import { ScallopAddress, ScallopUtils } from 'src/models';
|
|
3
|
+
import { SupportPoolCoins } from 'src/types';
|
|
4
|
+
import { z as zod } from 'zod';
|
|
5
|
+
|
|
6
|
+
const isolatedAssetZod = zod.object({
|
|
7
|
+
dataType: zod.string(),
|
|
8
|
+
type: zod.string(),
|
|
9
|
+
hasPublicTransfer: zod.boolean(),
|
|
10
|
+
fields: zod.object({
|
|
11
|
+
id: zod.object({
|
|
12
|
+
id: zod.string(),
|
|
13
|
+
}),
|
|
14
|
+
name: zod.object({
|
|
15
|
+
type: zod.string(),
|
|
16
|
+
}),
|
|
17
|
+
value: zod.boolean(),
|
|
18
|
+
}),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const ISOLATED_ASSET_KEY =
|
|
22
|
+
'0x6e641f0dca8aedab3101d047e96439178f16301bf0b57fe8745086ff1195eb3e::market_dynamic_keys::IsolatedAssetKey';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Return list of isolated assets coin types
|
|
26
|
+
* @param utils ScallopUtils
|
|
27
|
+
* @returns list of isolated assets coin types
|
|
28
|
+
*/
|
|
29
|
+
export const getIsolatedAssets = async (
|
|
30
|
+
address: ScallopAddress
|
|
31
|
+
): Promise<string[]> => {
|
|
32
|
+
const marketObject = address.get('core.market');
|
|
33
|
+
const isolatedAssets: string[] = [];
|
|
34
|
+
if (!marketObject) return isolatedAssets;
|
|
35
|
+
|
|
36
|
+
let hasNextPage = false;
|
|
37
|
+
let nextCursor: string | null | undefined = null;
|
|
38
|
+
|
|
39
|
+
const isIsolatedDynamicField = (
|
|
40
|
+
dynamicField: DynamicFieldInfo
|
|
41
|
+
): dynamicField is DynamicFieldInfo & {
|
|
42
|
+
name: DynamicFieldName & { value: { type: { name: string } } };
|
|
43
|
+
} => {
|
|
44
|
+
return dynamicField.name.type === ISOLATED_ASSET_KEY;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
do {
|
|
48
|
+
const response = await address.cache.queryGetDynamicFields({
|
|
49
|
+
parentId: marketObject,
|
|
50
|
+
cursor: nextCursor,
|
|
51
|
+
limit: 10,
|
|
52
|
+
});
|
|
53
|
+
if (!response) break;
|
|
54
|
+
|
|
55
|
+
const isolatedAssetCoinTypes = response.data
|
|
56
|
+
.filter(isIsolatedDynamicField)
|
|
57
|
+
.map(({ name }) => `0x${name.value.type.name}`);
|
|
58
|
+
isolatedAssets.push(...isolatedAssetCoinTypes);
|
|
59
|
+
|
|
60
|
+
if (response && response.hasNextPage && response.nextCursor) {
|
|
61
|
+
hasNextPage = true;
|
|
62
|
+
nextCursor = response.nextCursor;
|
|
63
|
+
} else {
|
|
64
|
+
hasNextPage = false;
|
|
65
|
+
}
|
|
66
|
+
} while (hasNextPage);
|
|
67
|
+
return isolatedAssets;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if the coin type is an isolated asset
|
|
72
|
+
* @param coinName coin name
|
|
73
|
+
* @returns true if the coin type is an isolated asset
|
|
74
|
+
*/
|
|
75
|
+
export const isIsolatedAsset = async (
|
|
76
|
+
utils: ScallopUtils,
|
|
77
|
+
coinName: SupportPoolCoins
|
|
78
|
+
): Promise<boolean> => {
|
|
79
|
+
const marketObject = utils.address.get('core.market');
|
|
80
|
+
|
|
81
|
+
// check if the coin type is in the list
|
|
82
|
+
const cachedData = utils.address.cache.queryClient.getQueryData<string[]>([
|
|
83
|
+
'getDynamicFields',
|
|
84
|
+
marketObject,
|
|
85
|
+
]);
|
|
86
|
+
if (cachedData) {
|
|
87
|
+
const coinType = utils.parseCoinType(coinName);
|
|
88
|
+
return cachedData.includes(coinType);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// fetch dynamic field object
|
|
92
|
+
const coinType = utils.parseCoinType(coinName).slice(2);
|
|
93
|
+
|
|
94
|
+
const object = await utils.cache.queryGetDynamicFieldObject({
|
|
95
|
+
parentId: marketObject,
|
|
96
|
+
name: {
|
|
97
|
+
type: ISOLATED_ASSET_KEY,
|
|
98
|
+
value: coinType,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const parsedData = isolatedAssetZod.safeParse(object?.data?.content);
|
|
103
|
+
if (!parsedData.success) return false;
|
|
104
|
+
return parsedData.data.fields.value;
|
|
105
|
+
};
|
|
@@ -269,6 +269,7 @@ export const getLending = async (
|
|
|
269
269
|
availableUnstakeCoin: availableUnstakeCoin.toNumber(),
|
|
270
270
|
availableClaimAmount: availableClaimAmount.toNumber(),
|
|
271
271
|
availableClaimCoin: availableClaimCoin.toNumber(),
|
|
272
|
+
isIsolated: marketPool ? marketPool.isIsolated : false,
|
|
272
273
|
};
|
|
273
274
|
|
|
274
275
|
return lending;
|
|
@@ -17,7 +17,7 @@ const supplyLimitZod = zod.object({
|
|
|
17
17
|
}),
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const SUPPLY_LIMIT_KEY =
|
|
21
21
|
'0x6e641f0dca8aedab3101d047e96439178f16301bf0b57fe8745086ff1195eb3e::market_dynamic_keys::SupplyLimitKey';
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -37,7 +37,7 @@ export const getSupplyLimit = async (
|
|
|
37
37
|
const object = await utils.cache.queryGetDynamicFieldObject({
|
|
38
38
|
parentId: marketObject,
|
|
39
39
|
name: {
|
|
40
|
-
type:
|
|
40
|
+
type: SUPPLY_LIMIT_KEY,
|
|
41
41
|
value: poolCoinType,
|
|
42
42
|
},
|
|
43
43
|
});
|
package/src/types/query/core.ts
CHANGED
package/src/utils/tokenBucket.ts
CHANGED
|
@@ -65,7 +65,7 @@ const callWithRateLimit = async <T>(
|
|
|
65
65
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
66
66
|
return tryRequest();
|
|
67
67
|
} else {
|
|
68
|
-
console.error('An error occurred:', error);
|
|
68
|
+
console.error('An error occurred:', error.message);
|
|
69
69
|
return null;
|
|
70
70
|
}
|
|
71
71
|
}
|
package/dist/test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/src/test.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ScallopQuery } from './models';
|
|
2
|
-
|
|
3
|
-
const query = new ScallopQuery({
|
|
4
|
-
walletAddress:
|
|
5
|
-
'0xe78704e7c188b1902dbb630dc4c3ef7f46740c8cf121e38b3438ac1daea09f2d',
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
const main = async () => {
|
|
9
|
-
try {
|
|
10
|
-
await query.init();
|
|
11
|
-
const result = await query.suiKit.client().getObject({
|
|
12
|
-
id: '0xaa72bd551b25715b8f9d72f226fa02526bdf2e085a86faec7184230c5209bb6e',
|
|
13
|
-
options: {
|
|
14
|
-
showContent: true,
|
|
15
|
-
showType: true,
|
|
16
|
-
},
|
|
17
|
-
});
|
|
18
|
-
console.dir(result.data, { depth: null });
|
|
19
|
-
} catch (e) {
|
|
20
|
-
console.error(e);
|
|
21
|
-
} finally {
|
|
22
|
-
process.exit(0);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
main();
|