@scallop-io/sui-scallop-sdk 1.5.3 → 2.0.0-alpha.2
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 +451 -602
- package/dist/index.d.ts +451 -602
- package/dist/index.js +29 -60
- package/dist/index.mjs +6 -6
- package/package.json +1 -1
- package/src/builders/loyaltyProgramBuilder.ts +5 -3
- package/src/builders/oracle.ts +10 -24
- package/src/builders/referralBuilder.ts +5 -9
- package/src/builders/sCoinBuilder.ts +9 -8
- package/src/builders/spoolBuilder.ts +4 -6
- package/src/constants/common.ts +114 -126
- package/src/constants/index.ts +0 -5
- package/src/constants/pyth.ts +25 -34
- package/src/constants/queryKeys.ts +2 -0
- package/src/models/index.ts +1 -0
- package/src/models/scallop.ts +23 -19
- package/src/models/scallopAddress.ts +7 -4
- package/src/models/scallopBuilder.ts +36 -41
- package/src/models/scallopCache.ts +1 -1
- package/src/models/scallopClient.ts +93 -94
- package/src/models/scallopConstants.ts +342 -0
- package/src/models/scallopIndexer.ts +11 -24
- package/src/models/scallopQuery.ts +70 -77
- package/src/models/scallopUtils.ts +122 -249
- package/src/queries/borrowIncentiveQuery.ts +21 -56
- package/src/queries/borrowLimitQuery.ts +3 -6
- package/src/queries/coreQuery.ts +94 -112
- package/src/queries/flashloanFeeQuery.ts +86 -0
- package/src/queries/isolatedAssetQuery.ts +12 -11
- package/src/queries/poolAddressesQuery.ts +187 -112
- package/src/queries/portfolioQuery.ts +65 -67
- package/src/queries/priceQuery.ts +16 -22
- package/src/queries/sCoinQuery.ts +15 -16
- package/src/queries/spoolQuery.ts +49 -59
- package/src/queries/supplyLimitQuery.ts +2 -6
- package/src/queries/xOracleQuery.ts +4 -15
- package/src/types/address.ts +12 -18
- package/src/types/builder/borrowIncentive.ts +2 -3
- package/src/types/builder/core.ts +20 -27
- package/src/types/builder/index.ts +1 -2
- package/src/types/builder/referral.ts +4 -8
- package/src/types/builder/sCoin.ts +4 -8
- package/src/types/builder/spool.ts +7 -10
- package/src/types/constant/common.ts +43 -49
- package/src/types/constant/enum.ts +15 -27
- package/src/types/constant/xOracle.ts +3 -5
- package/src/types/model.ts +49 -28
- package/src/types/query/borrowIncentive.ts +7 -24
- package/src/types/query/core.ts +8 -18
- package/src/types/query/portfolio.ts +8 -17
- package/src/types/query/spool.ts +5 -11
- package/src/types/utils.ts +1 -21
- package/src/utils/core.ts +1 -1
- package/src/utils/query.ts +13 -20
- package/src/utils/util.ts +6 -84
- package/src/constants/coinGecko.ts +0 -34
- package/src/constants/enum.ts +0 -268
- package/src/constants/flashloan.ts +0 -18
- package/src/constants/poolAddress.ts +0 -898
- package/src/models/scallopPrice.ts +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { SuiObjectData } from '@mysten/sui/client';
|
|
2
|
+
import { ScallopUtils } from 'src/models';
|
|
3
|
+
import { ScallopConstants } from 'src/models/scallopConstants';
|
|
4
|
+
|
|
5
|
+
const FLASHLOAN_FEES_TABLE_ID =
|
|
6
|
+
'0x00481a93b819d744a7d79ecdc6c62c74f2f7cb4779316c4df640415817ac61bb' as const;
|
|
7
|
+
|
|
8
|
+
export const queryFlashLoanFees = async (
|
|
9
|
+
utils: ScallopUtils,
|
|
10
|
+
assetNames: string[],
|
|
11
|
+
feeRate: number
|
|
12
|
+
) => {
|
|
13
|
+
const assetNamesSet = new Set(assetNames);
|
|
14
|
+
const assetTypeMap = Object.fromEntries(
|
|
15
|
+
Object.entries(utils.constants.coinTypeToCoinNameMap).filter(([_, value]) =>
|
|
16
|
+
assetNamesSet.has(value!)
|
|
17
|
+
)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
let cursor: string | null | undefined = null;
|
|
21
|
+
let nextPage: boolean = false;
|
|
22
|
+
const flashloanFeeObjects: SuiObjectData[] = [];
|
|
23
|
+
do {
|
|
24
|
+
const resp = await utils.cache.queryGetDynamicFields({
|
|
25
|
+
parentId: FLASHLOAN_FEES_TABLE_ID,
|
|
26
|
+
limit: 10,
|
|
27
|
+
cursor,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (!resp) break;
|
|
31
|
+
const { data, hasNextPage, nextCursor } = resp;
|
|
32
|
+
// get the dynamic object ids
|
|
33
|
+
const dynamicFieldObjectIds =
|
|
34
|
+
data
|
|
35
|
+
.filter((field) => {
|
|
36
|
+
const assetType = `0x${(field.name.value as any).name as string}`;
|
|
37
|
+
return !!assetTypeMap[assetType];
|
|
38
|
+
})
|
|
39
|
+
.map((field) => field.objectId) ?? [];
|
|
40
|
+
|
|
41
|
+
flashloanFeeObjects.push(
|
|
42
|
+
...(await utils.cache.queryGetObjects(dynamicFieldObjectIds))
|
|
43
|
+
);
|
|
44
|
+
nextPage = hasNextPage;
|
|
45
|
+
cursor = nextCursor;
|
|
46
|
+
} while (nextPage);
|
|
47
|
+
|
|
48
|
+
return flashloanFeeObjects.reduce(
|
|
49
|
+
(prev, curr) => {
|
|
50
|
+
if (curr.content?.dataType === 'moveObject') {
|
|
51
|
+
const assetType = `0x${(curr.content.fields as any).name.fields.name}`;
|
|
52
|
+
const assetName = assetTypeMap[assetType];
|
|
53
|
+
if (!assetName) return prev;
|
|
54
|
+
|
|
55
|
+
const objectFields = curr.content.fields as any;
|
|
56
|
+
const feeNumerator = +objectFields.value;
|
|
57
|
+
prev[assetName] = feeNumerator / feeRate;
|
|
58
|
+
}
|
|
59
|
+
return prev;
|
|
60
|
+
},
|
|
61
|
+
{} as Record<string, number>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const parseFlashloanFeeObjects = (
|
|
66
|
+
constants: ScallopConstants,
|
|
67
|
+
objects: SuiObjectData[],
|
|
68
|
+
feeRate: number
|
|
69
|
+
) => {
|
|
70
|
+
const assetTypeMap = constants.coinTypeToCoinNameMap;
|
|
71
|
+
return objects.reduce(
|
|
72
|
+
(prev, curr) => {
|
|
73
|
+
if (curr.content?.dataType === 'moveObject') {
|
|
74
|
+
const assetType = `0x${(curr.content.fields as any).name.fields.name}`;
|
|
75
|
+
const assetName = assetTypeMap[assetType];
|
|
76
|
+
if (!assetName) return prev;
|
|
77
|
+
|
|
78
|
+
const objectFields = curr.content.fields as any;
|
|
79
|
+
const feeNumerator = +objectFields.value;
|
|
80
|
+
prev[assetName] = feeNumerator / feeRate;
|
|
81
|
+
}
|
|
82
|
+
return prev;
|
|
83
|
+
},
|
|
84
|
+
{} as Record<string, number>
|
|
85
|
+
);
|
|
86
|
+
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { DynamicFieldInfo, DynamicFieldName } from '@mysten/sui/client';
|
|
2
2
|
import { ScallopQuery, ScallopUtils } from '../models';
|
|
3
|
-
import { SupportPoolCoins } from '../types';
|
|
4
3
|
import { z as zod } from 'zod';
|
|
5
|
-
import { POOL_ADDRESSES, SUPPORT_POOLS } from 'src/constants';
|
|
6
4
|
|
|
7
5
|
const isolatedAssetZod = zod.object({
|
|
8
6
|
dataType: zod.string(),
|
|
@@ -28,14 +26,16 @@ const isolatedAssetKeyType = `0xe7dbb371a9595631f7964b7ece42255ad0e738cc85fe6da2
|
|
|
28
26
|
* @returns list of isolated assets coin types
|
|
29
27
|
*/
|
|
30
28
|
export const getIsolatedAssets = async (
|
|
31
|
-
query: ScallopQuery
|
|
29
|
+
query: ScallopQuery,
|
|
30
|
+
useOnChainQuery: boolean = false
|
|
32
31
|
): Promise<string[]> => {
|
|
33
|
-
if (
|
|
34
|
-
return
|
|
35
|
-
(
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
if (!useOnChainQuery) {
|
|
33
|
+
return query.utils
|
|
34
|
+
.getSupportedPoolAddresses()
|
|
35
|
+
.filter((t) => !!t.isolatedAssetKey)
|
|
36
|
+
.map((t) => t.coinName);
|
|
38
37
|
}
|
|
38
|
+
|
|
39
39
|
try {
|
|
40
40
|
const marketObject = query.address.get('core.market');
|
|
41
41
|
const isolatedAssets: string[] = [];
|
|
@@ -86,10 +86,11 @@ export const getIsolatedAssets = async (
|
|
|
86
86
|
*/
|
|
87
87
|
export const isIsolatedAsset = async (
|
|
88
88
|
utils: ScallopUtils,
|
|
89
|
-
coinName:
|
|
89
|
+
coinName: string
|
|
90
90
|
): Promise<boolean> => {
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
const assetInPoolAddresses = utils.constants.poolAddresses[coinName];
|
|
92
|
+
if (assetInPoolAddresses) {
|
|
93
|
+
return !!assetInPoolAddresses.isolatedAssetKey;
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
const marketObject = utils.address.get('core.market');
|
|
@@ -1,59 +1,118 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { OptionalKeys, SupportPoolCoins } from 'src/types';
|
|
1
|
+
import { getFullnodeUrl, SuiClient } from '@mysten/sui/client';
|
|
2
|
+
import { AddressesInterface, OptionalKeys, PoolAddress } from 'src/types';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const RPC_PROVIDERS = [
|
|
5
|
+
getFullnodeUrl('mainnet'),
|
|
6
|
+
'https://sui-mainnet.public.blastapi.io',
|
|
7
|
+
'https://sui-mainnet-ca-2.cosmostation.io',
|
|
8
|
+
'https://sui-mainnet-eu-4.cosmostation.io',
|
|
9
|
+
'https://sui-mainnet-endpoint.blockvision.org',
|
|
10
|
+
'https://sui-rpc.publicnode.com',
|
|
11
|
+
'https://sui-mainnet-rpc.allthatnode.com',
|
|
12
|
+
'https://mainnet.suiet.app',
|
|
13
|
+
'https://mainnet.sui.rpcpool.com',
|
|
14
|
+
'https://sui1mainnet-rpc.chainode.tech',
|
|
15
|
+
'https://fullnode.mainnet.apis.scallop.io',
|
|
16
|
+
'https://sui-mainnet-us-2.cosmostation.io',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const tryRequest = async <T>(fn: (client: SuiClient) => T) => {
|
|
20
|
+
for (const rpc of RPC_PROVIDERS) {
|
|
21
|
+
try {
|
|
22
|
+
const res = await fn(new SuiClient({ url: rpc }));
|
|
23
|
+
return res;
|
|
24
|
+
} catch (e: any) {
|
|
25
|
+
if (e.status !== 429) {
|
|
26
|
+
throw e;
|
|
27
|
+
}
|
|
28
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
throw new Error('Failed to fetch data');
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const queryFlashloanFeeObjectIds = async (
|
|
35
|
+
client: SuiClient,
|
|
36
|
+
coinTypeMap: Set<string>, // set of coin types
|
|
37
|
+
flashloanFeeTableId: string = '0x00481a93b819d744a7d79ecdc6c62c74f2f7cb4779316c4df640415817ac61bb'
|
|
8
38
|
) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
borrowFeeKey?: string;
|
|
27
|
-
supplyLimitKey?: string;
|
|
28
|
-
borrowLimitKey?: string;
|
|
29
|
-
isolatedAssetKey?: string;
|
|
30
|
-
coinMetadataId?: string;
|
|
31
|
-
borrowIncentivePoolId?: string;
|
|
32
|
-
coinType?: string;
|
|
33
|
-
sCoinMetadataId?: string;
|
|
34
|
-
spoolName?: string;
|
|
35
|
-
decimals: number;
|
|
36
|
-
pythFeed?: string;
|
|
37
|
-
pythFeedObjectId?: string;
|
|
39
|
+
let cursor: string | null | undefined = null;
|
|
40
|
+
let nextPage: boolean = false;
|
|
41
|
+
const flashloanFeeObjectIds: Record<string, string> = {}; // <coinType, flashloanFeeObjectId>
|
|
42
|
+
|
|
43
|
+
do {
|
|
44
|
+
const resp = await client.getDynamicFields({
|
|
45
|
+
parentId: flashloanFeeTableId,
|
|
46
|
+
limit: 10,
|
|
47
|
+
cursor,
|
|
48
|
+
});
|
|
49
|
+
if (!resp) break;
|
|
50
|
+
const { data, hasNextPage, nextCursor } = resp;
|
|
51
|
+
// get the dynamic object ids
|
|
52
|
+
data.forEach((field) => {
|
|
53
|
+
const assetType = `0x${(field.name.value as any).name as string}`;
|
|
54
|
+
if (coinTypeMap.has(assetType)) {
|
|
55
|
+
flashloanFeeObjectIds[assetType] = field.objectId;
|
|
38
56
|
}
|
|
39
|
-
|
|
40
|
-
|
|
57
|
+
});
|
|
58
|
+
nextPage = hasNextPage;
|
|
59
|
+
cursor = nextCursor;
|
|
60
|
+
} while (nextPage);
|
|
61
|
+
|
|
62
|
+
return flashloanFeeObjectIds;
|
|
63
|
+
};
|
|
41
64
|
|
|
42
|
-
|
|
43
|
-
|
|
65
|
+
export const getPoolAddresses = async (
|
|
66
|
+
addressId: string,
|
|
67
|
+
poolNames: string[] = []
|
|
68
|
+
) => {
|
|
69
|
+
const poolNameSet = new Set(poolNames);
|
|
70
|
+
const results: OptionalKeys<Record<string, PoolAddress>> = {};
|
|
44
71
|
|
|
45
|
-
|
|
46
|
-
|
|
72
|
+
// fetch the Address API
|
|
73
|
+
const URL = 'https://sui.apis.scallop.io';
|
|
74
|
+
const addressApiResponse = (
|
|
75
|
+
await fetch(`${URL}/addresses/${addressId}`).then((res) => res.json())
|
|
76
|
+
).mainnet as unknown as AddressesInterface;
|
|
47
77
|
|
|
48
|
-
|
|
78
|
+
if (!addressApiResponse) throw new Error('Failed to fetch addresses');
|
|
79
|
+
|
|
80
|
+
// Compose pools based on addresses
|
|
81
|
+
const pools = Object.keys(addressApiResponse.core.coins);
|
|
82
|
+
if (pools.length === 0) throw new Error('Pools empty');
|
|
49
83
|
|
|
50
84
|
const coinTypesPairs = pools.reduce(
|
|
51
|
-
(acc,
|
|
52
|
-
|
|
85
|
+
(acc, poolName) => {
|
|
86
|
+
if (poolNameSet.size > 0 && !poolNameSet.has(poolName)) return acc;
|
|
87
|
+
const value =
|
|
88
|
+
addressApiResponse.core.coins[
|
|
89
|
+
poolName as keyof typeof addressApiResponse.core.coins
|
|
90
|
+
];
|
|
91
|
+
if (value && value.coinType) {
|
|
92
|
+
acc.push([poolName, value.coinType]);
|
|
93
|
+
}
|
|
53
94
|
return acc;
|
|
54
95
|
},
|
|
55
|
-
[] as [
|
|
96
|
+
[] as [string, string][]
|
|
56
97
|
);
|
|
98
|
+
if (coinTypesPairs.length === 0) throw new Error('No coinTypesPairs');
|
|
99
|
+
|
|
100
|
+
const marketId = addressApiResponse.core.market;
|
|
101
|
+
const marketObject = (
|
|
102
|
+
await tryRequest(async (client) => {
|
|
103
|
+
return await client.getObject({
|
|
104
|
+
id: marketId,
|
|
105
|
+
options: {
|
|
106
|
+
showContent: true,
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
})
|
|
110
|
+
).data;
|
|
111
|
+
|
|
112
|
+
if (!(marketObject && marketObject.content?.dataType === 'moveObject'))
|
|
113
|
+
throw new Error(`Failed to fetch marketObject`);
|
|
114
|
+
|
|
115
|
+
const fields = marketObject.content.fields as any;
|
|
57
116
|
|
|
58
117
|
const balanceSheetParentId =
|
|
59
118
|
fields.vault.fields.balance_sheets.fields.table.fields.id.id;
|
|
@@ -79,111 +138,127 @@ export const getAllAddresses = async (
|
|
|
79
138
|
type: string,
|
|
80
139
|
value: any
|
|
81
140
|
) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
await
|
|
141
|
+
return (
|
|
142
|
+
await tryRequest(async (client) => {
|
|
143
|
+
return await client.getDynamicFieldObject({
|
|
85
144
|
parentId,
|
|
86
145
|
name: {
|
|
87
146
|
type,
|
|
88
147
|
value,
|
|
89
148
|
},
|
|
90
|
-
})
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
console.error(e.message);
|
|
94
|
-
return undefined;
|
|
95
|
-
}
|
|
149
|
+
});
|
|
150
|
+
})
|
|
151
|
+
).data?.objectId;
|
|
96
152
|
};
|
|
97
153
|
|
|
154
|
+
// query flashloan fee objects first
|
|
155
|
+
const flashloanFeeObjectIds = await tryRequest(async (client) => {
|
|
156
|
+
return await queryFlashloanFeeObjectIds(
|
|
157
|
+
client,
|
|
158
|
+
new Set(coinTypesPairs.map(([, coinType]) => coinType))
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
|
|
98
162
|
await Promise.all(
|
|
99
163
|
coinTypesPairs.map(async ([coinName, coinType]) => {
|
|
164
|
+
const coinTypeKey = coinType.slice(2);
|
|
100
165
|
const addresses = await Promise.all([
|
|
101
166
|
fetchDynamicObject(balanceSheetParentId, ADDRESS_TYPE, {
|
|
102
|
-
name:
|
|
167
|
+
name: coinTypeKey,
|
|
103
168
|
}),
|
|
104
169
|
fetchDynamicObject(collateralStatsParentId, ADDRESS_TYPE, {
|
|
105
|
-
name:
|
|
170
|
+
name: coinTypeKey,
|
|
106
171
|
}),
|
|
107
172
|
fetchDynamicObject(borrowDynamicsParentid, ADDRESS_TYPE, {
|
|
108
|
-
name:
|
|
173
|
+
name: coinTypeKey,
|
|
109
174
|
}),
|
|
110
175
|
fetchDynamicObject(interestModelParentId, ADDRESS_TYPE, {
|
|
111
|
-
name:
|
|
176
|
+
name: coinTypeKey,
|
|
112
177
|
}),
|
|
113
178
|
fetchDynamicObject(riskModelParentId, ADDRESS_TYPE, {
|
|
114
|
-
name:
|
|
179
|
+
name: coinTypeKey,
|
|
115
180
|
}),
|
|
116
|
-
fetchDynamicObject(marketId, BORROW_FEE_TYPE,
|
|
117
|
-
fetchDynamicObject(marketId, SUPPLY_LIMIT_TYPE,
|
|
118
|
-
fetchDynamicObject(marketId, BORROW_LIMIT_TYPE,
|
|
119
|
-
fetchDynamicObject(marketId, ISOLATED_ASSET_KEY,
|
|
181
|
+
fetchDynamicObject(marketId, BORROW_FEE_TYPE, coinTypeKey),
|
|
182
|
+
fetchDynamicObject(marketId, SUPPLY_LIMIT_TYPE, coinTypeKey),
|
|
183
|
+
fetchDynamicObject(marketId, BORROW_LIMIT_TYPE, coinTypeKey),
|
|
184
|
+
fetchDynamicObject(marketId, ISOLATED_ASSET_KEY, coinTypeKey),
|
|
120
185
|
]);
|
|
121
186
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
)
|
|
130
|
-
const sCoinType = query.address.get(
|
|
131
|
-
// @ts-ignore
|
|
132
|
-
`scoin.coins.s${coinName}.coinType`
|
|
133
|
-
);
|
|
134
|
-
const sCoinName = sCoinType
|
|
135
|
-
? query.utils.parseSCoinName(coinName)
|
|
136
|
-
: undefined;
|
|
137
|
-
const sCoinSymbol = sCoinName
|
|
138
|
-
? query.utils.parseSymbol(sCoinName)
|
|
139
|
-
: undefined;
|
|
140
|
-
const sCoinTreasury = query.address.get(
|
|
141
|
-
// @ts-ignore
|
|
142
|
-
`scoin.coins.s${coinName}.treasury`
|
|
143
|
-
);
|
|
144
|
-
const coinMetadataId = query.address.get(
|
|
145
|
-
`core.coins.${coinName}.metaData`
|
|
146
|
-
);
|
|
147
|
-
const sCoinMetadataId = query.address.get(
|
|
187
|
+
// @ts-ignore
|
|
188
|
+
const { symbol, metaData: coinMetadataId } =
|
|
189
|
+
addressApiResponse.core.coins[coinName];
|
|
190
|
+
|
|
191
|
+
let spoolData = undefined;
|
|
192
|
+
const _spoolData = addressApiResponse.spool.pools[`s${coinName}`];
|
|
193
|
+
// @ts-ignore
|
|
194
|
+
if (_spoolData) {
|
|
148
195
|
// @ts-ignore
|
|
149
|
-
|
|
150
|
-
|
|
196
|
+
const { id: spool, rewardPoolId: spoolReward } = _spoolData;
|
|
197
|
+
spoolData = {
|
|
198
|
+
spool,
|
|
199
|
+
spoolReward,
|
|
200
|
+
coinMetadataId,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
151
203
|
|
|
152
|
-
|
|
153
|
-
const
|
|
204
|
+
let sCoinData = undefined;
|
|
205
|
+
const sCoinName = `s${coinName}`;
|
|
206
|
+
const _sCoinData = addressApiResponse.scoin.coins[sCoinName];
|
|
207
|
+
if (_sCoinData) {
|
|
208
|
+
const {
|
|
209
|
+
coinType: sCoinType,
|
|
210
|
+
treasury: sCoinTreasury,
|
|
211
|
+
metaData: sCoinMetadataId,
|
|
212
|
+
symbol: sCoinSymbol,
|
|
213
|
+
} = _sCoinData;
|
|
214
|
+
sCoinData = {
|
|
215
|
+
sCoinType,
|
|
216
|
+
sCoinTreasury,
|
|
217
|
+
sCoinMetadataId,
|
|
218
|
+
sCoinSymbol,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const { feed: pythFeed, feedObject: pythFeedObjectId } =
|
|
154
223
|
//@ts-ignore
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const decimals =
|
|
158
|
-
|
|
159
|
-
|
|
224
|
+
addressApiResponse.core.coins[coinName].oracle.pyth;
|
|
225
|
+
|
|
226
|
+
const decimals =
|
|
227
|
+
(
|
|
228
|
+
await tryRequest(async (client) => {
|
|
229
|
+
return await client.getCoinMetadata({
|
|
230
|
+
coinType: coinType,
|
|
231
|
+
});
|
|
232
|
+
})
|
|
233
|
+
)?.decimals ?? 0;
|
|
234
|
+
const spoolName = spoolData ? `s${coinName}` : undefined;
|
|
235
|
+
|
|
236
|
+
// @TODO: add query for flashloanFeeObject
|
|
237
|
+
results[coinName] = {
|
|
160
238
|
coinName,
|
|
161
|
-
symbol
|
|
162
|
-
lendingPoolAddress: addresses[0],
|
|
163
|
-
collateralPoolAddress: addresses[1],
|
|
164
|
-
borrowDynamic: addresses[2],
|
|
165
|
-
interestModel: addresses[3],
|
|
239
|
+
symbol,
|
|
240
|
+
lendingPoolAddress: addresses[0] ?? '',
|
|
241
|
+
collateralPoolAddress: addresses[1] ?? '',
|
|
242
|
+
borrowDynamic: addresses[2] ?? '',
|
|
243
|
+
interestModel: addresses[3] ?? '',
|
|
166
244
|
riskModel: addresses[4],
|
|
167
|
-
borrowFeeKey: addresses[5],
|
|
245
|
+
borrowFeeKey: addresses[5] ?? '',
|
|
168
246
|
supplyLimitKey: addresses[6],
|
|
169
247
|
borrowLimitKey: addresses[7],
|
|
170
248
|
isolatedAssetKey: addresses[8],
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
sCoinTreasury,
|
|
174
|
-
sCoinType,
|
|
249
|
+
...(spoolData ?? {}),
|
|
250
|
+
...(sCoinData ?? {}),
|
|
175
251
|
sCoinName,
|
|
176
|
-
sCoinSymbol,
|
|
177
252
|
coinMetadataId,
|
|
178
|
-
coinType
|
|
179
|
-
sCoinMetadataId,
|
|
253
|
+
coinType,
|
|
180
254
|
spoolName,
|
|
181
255
|
decimals,
|
|
182
256
|
pythFeed,
|
|
183
257
|
pythFeedObjectId,
|
|
258
|
+
flashloanFeeObject: flashloanFeeObjectIds[coinType] ?? '',
|
|
184
259
|
};
|
|
185
260
|
|
|
186
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
261
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
187
262
|
})
|
|
188
263
|
);
|
|
189
264
|
|