@subwallet/extension-base 1.3.51-0 → 1.3.53-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/cjs/constants/environment.js +3 -1
- package/cjs/koni/background/handlers/State.js +1 -5
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/index.js +3 -4
- package/cjs/services/balance-service/transfer/cardano-transfer.js +43 -11
- package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +13 -92
- package/cjs/services/balance-service/transfer/xcm/index.js +12 -4
- package/cjs/services/chain-service/utils/patch.js +3 -2
- package/cjs/services/earning-service/handlers/native-staking/dtao.js +28 -301
- package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +4 -4
- package/cjs/services/earning-service/handlers/native-staking/tao.js +174 -148
- package/cjs/services/earning-service/handlers/nomination-pool/index.js +11 -5
- package/cjs/services/earning-service/service.js +5 -2
- package/cjs/services/fee-service/utils/tokenPayFee.js +17 -13
- package/cjs/services/keyring-service/context/handlers/Json.js +28 -3
- package/cjs/services/price-service/coingecko.js +3 -3
- package/cjs/services/swap-service/handler/hydradx-handler.js +19 -13
- package/cjs/services/swap-service/index.js +8 -5
- package/cjs/services/transaction-service/utils.js +31 -22
- package/cjs/services/wallet-connect-service/constants.js +6 -2
- package/cjs/services/wallet-connect-service/index.js +62 -45
- package/cjs/utils/index.js +12 -0
- package/cjs/utils/setup-api-sdk.js +27 -0
- package/constants/environment.d.ts +1 -0
- package/constants/environment.js +1 -0
- package/koni/background/handlers/State.js +3 -7
- package/package.json +34 -29
- package/packageInfo.js +1 -1
- package/services/balance-service/index.js +3 -4
- package/services/balance-service/transfer/cardano-transfer.js +42 -10
- package/services/balance-service/transfer/xcm/acrossBridge/index.js +14 -93
- package/services/balance-service/transfer/xcm/index.js +12 -4
- package/services/chain-service/utils/patch.d.ts +1 -0
- package/services/chain-service/utils/patch.js +1 -1
- package/services/earning-service/handlers/native-staking/dtao.d.ts +4 -36
- package/services/earning-service/handlers/native-staking/dtao.js +24 -298
- package/services/earning-service/handlers/native-staking/relay-chain.d.ts +1 -2
- package/services/earning-service/handlers/native-staking/relay-chain.js +4 -4
- package/services/earning-service/handlers/native-staking/tao.d.ts +25 -5
- package/services/earning-service/handlers/native-staking/tao.js +169 -149
- package/services/earning-service/handlers/nomination-pool/index.d.ts +1 -2
- package/services/earning-service/handlers/nomination-pool/index.js +11 -5
- package/services/earning-service/service.d.ts +1 -0
- package/services/earning-service/service.js +4 -2
- package/services/fee-service/utils/tokenPayFee.js +17 -13
- package/services/keyring-service/context/handlers/Json.js +28 -3
- package/services/price-service/coingecko.js +2 -3
- package/services/swap-service/handler/hydradx-handler.js +19 -13
- package/services/swap-service/index.js +8 -5
- package/services/transaction-service/utils.d.ts +0 -1
- package/services/transaction-service/utils.js +31 -21
- package/services/wallet-connect-service/constants.d.ts +2 -0
- package/services/wallet-connect-service/constants.js +3 -1
- package/services/wallet-connect-service/index.js +50 -33
- package/types/swap/index.d.ts +1 -1
- package/types/yield/info/chain/info.d.ts +1 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +2 -1
- package/utils/setup-api-sdk.d.ts +1 -0
- package/utils/setup-api-sdk.js +20 -0
|
@@ -7,12 +7,16 @@ import { BITTENSOR_REFRESH_STAKE_APY, BITTENSOR_REFRESH_STAKE_INFO } from '@subw
|
|
|
7
7
|
import { getEarningStatusByNominations } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
|
|
8
8
|
import { _getAssetDecimals, _getAssetSymbol } from '@subwallet/extension-base/services/chain-service/utils';
|
|
9
9
|
import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
|
|
10
|
-
import { BasicTxErrorType, EarningStatus, StakingTxErrorType } from '@subwallet/extension-base/types';
|
|
10
|
+
import { BasicTxErrorType, EarningStatus, StakingTxErrorType, YieldPoolType } from '@subwallet/extension-base/types';
|
|
11
11
|
import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment';
|
|
12
12
|
import { fetchFromProxyService, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
|
|
13
13
|
import BigN from 'bignumber.js';
|
|
14
14
|
import { t } from 'i18next';
|
|
15
|
+
import { BehaviorSubject, combineLatest } from 'rxjs';
|
|
15
16
|
import { BN, BN_ZERO } from '@polkadot/util';
|
|
17
|
+
import { fetchPoolsData } from "../../service.js";
|
|
18
|
+
const DEFAULT_BITTENSOR_SLIPPAGE = 0.005;
|
|
19
|
+
export const DEFAULT_DTAO_MINBOND = '21000000';
|
|
16
20
|
/* Fetch data */
|
|
17
21
|
export class BittensorCache {
|
|
18
22
|
static instance = null;
|
|
@@ -129,6 +133,15 @@ export class BittensorCache {
|
|
|
129
133
|
// }
|
|
130
134
|
// };
|
|
131
135
|
|
|
136
|
+
export const getAlphaToTaoRate = async (substrateApi, netuid) => {
|
|
137
|
+
const subnetInfo = (await substrateApi.api.call.subnetInfoRuntimeApi.getDynamicInfo(netuid)).toJSON();
|
|
138
|
+
if (!subnetInfo) {
|
|
139
|
+
return '1';
|
|
140
|
+
}
|
|
141
|
+
const taoIn = subnetInfo.taoIn ? new BigN(subnetInfo.taoIn) : new BigN(0);
|
|
142
|
+
const alphaIn = subnetInfo.alphaIn ? new BigN(subnetInfo.alphaIn) : new BigN(0);
|
|
143
|
+
return netuid === 0 || alphaIn.lte(0) ? '1' : taoIn.dividedBy(alphaIn).toString();
|
|
144
|
+
};
|
|
132
145
|
export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHandler {
|
|
133
146
|
availableMethod = {
|
|
134
147
|
join: true,
|
|
@@ -139,6 +152,36 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
139
152
|
claimReward: false,
|
|
140
153
|
changeValidator: true
|
|
141
154
|
};
|
|
155
|
+
async getMinBond(netuid) {
|
|
156
|
+
var _cachedPool$metadata2, _cachedPool$statistic, _cachedPool$statistic2, _onlinePool$metadata2, _onlinePool$statistic, _onlinePool$statistic2;
|
|
157
|
+
// @ts-ignore
|
|
158
|
+
if (this.type === YieldPoolType.SUBNET_STAKING) {
|
|
159
|
+
var _cachedPool$metadata, _onlinePool$metadata;
|
|
160
|
+
if (!netuid) {
|
|
161
|
+
return new BigN(DEFAULT_DTAO_MINBOND);
|
|
162
|
+
}
|
|
163
|
+
const subnetSlug = `${this.slug}__subnet_${netuid.toString().padStart(2, '0')}`;
|
|
164
|
+
const cachedPool = await this.getPoolInfo(subnetSlug);
|
|
165
|
+
if (cachedPool !== null && cachedPool !== void 0 && (_cachedPool$metadata = cachedPool.metadata) !== null && _cachedPool$metadata !== void 0 && _cachedPool$metadata.minValidate) {
|
|
166
|
+
return new BigN(cachedPool.metadata.minValidate);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// If can't get from cached -> get data online
|
|
170
|
+
const onlineData = await fetchPoolsData();
|
|
171
|
+
const onlinePool = onlineData[subnetSlug];
|
|
172
|
+
return new BigN((onlinePool === null || onlinePool === void 0 ? void 0 : (_onlinePool$metadata = onlinePool.metadata) === null || _onlinePool$metadata === void 0 ? void 0 : _onlinePool$metadata.minValidate) || DEFAULT_DTAO_MINBOND);
|
|
173
|
+
}
|
|
174
|
+
const cachedPool = await this.getPoolInfo(this.slug);
|
|
175
|
+
if (cachedPool !== null && cachedPool !== void 0 && (_cachedPool$metadata2 = cachedPool.metadata) !== null && _cachedPool$metadata2 !== void 0 && _cachedPool$metadata2.minValidate || cachedPool !== null && cachedPool !== void 0 && (_cachedPool$statistic = cachedPool.statistic) !== null && _cachedPool$statistic !== void 0 && (_cachedPool$statistic2 = _cachedPool$statistic.earningThreshold) !== null && _cachedPool$statistic2 !== void 0 && _cachedPool$statistic2.join) {
|
|
176
|
+
var _cachedPool$metadata3, _cachedPool$statistic3, _cachedPool$statistic4;
|
|
177
|
+
return new BigN(((_cachedPool$metadata3 = cachedPool.metadata) === null || _cachedPool$metadata3 === void 0 ? void 0 : _cachedPool$metadata3.minValidate) || ((_cachedPool$statistic3 = cachedPool.statistic) === null || _cachedPool$statistic3 === void 0 ? void 0 : (_cachedPool$statistic4 = _cachedPool$statistic3.earningThreshold) === null || _cachedPool$statistic4 === void 0 ? void 0 : _cachedPool$statistic4.join) || 0);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// If can get from cached -> get data online
|
|
181
|
+
const onlineData = await fetchPoolsData();
|
|
182
|
+
const onlinePool = onlineData[this.slug];
|
|
183
|
+
return new BigN((onlinePool === null || onlinePool === void 0 ? void 0 : (_onlinePool$metadata2 = onlinePool.metadata) === null || _onlinePool$metadata2 === void 0 ? void 0 : _onlinePool$metadata2.minValidate) || (onlinePool === null || onlinePool === void 0 ? void 0 : (_onlinePool$statistic = onlinePool.statistic) === null || _onlinePool$statistic === void 0 ? void 0 : (_onlinePool$statistic2 = _onlinePool$statistic.earningThreshold) === null || _onlinePool$statistic2 === void 0 ? void 0 : _onlinePool$statistic2.join) || 0);
|
|
184
|
+
}
|
|
142
185
|
constructor(state, chain) {
|
|
143
186
|
super(state, chain);
|
|
144
187
|
this.bittensorCache = BittensorCache.getInstance();
|
|
@@ -164,83 +207,96 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
164
207
|
|
|
165
208
|
async subscribePoolInfo(callback) {
|
|
166
209
|
let cancel = false;
|
|
167
|
-
const substrateApi = this.substrateApi;
|
|
168
|
-
const
|
|
210
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
211
|
+
const aprSubject = new BehaviorSubject(0);
|
|
212
|
+
const fetchAPR = async () => {
|
|
169
213
|
try {
|
|
214
|
+
const _topValidator = await this.bittensorCache.fetchApr(0);
|
|
215
|
+
const validators = _topValidator.data;
|
|
216
|
+
const highestApr = validators === null || validators === void 0 ? void 0 : validators[0];
|
|
217
|
+
const apr = this.chain === 'bittensor' ? Number((highestApr === null || highestApr === void 0 ? void 0 : highestApr.thirty_day_apy) || 0) * 100 : 0;
|
|
218
|
+
aprSubject.next(apr);
|
|
219
|
+
} catch (e) {
|
|
220
|
+
console.error('Fetch APR error:', e);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
await fetchAPR();
|
|
224
|
+
const interval = setInterval(() => {
|
|
225
|
+
fetchAPR().catch(console.error);
|
|
226
|
+
}, BITTENSOR_REFRESH_STAKE_APY);
|
|
227
|
+
const rxSubnetTAO = substrateApi.api.rx.query.subtensorModule.subnetTAO(0);
|
|
228
|
+
const rxMinDelegatorStake = substrateApi.api.rx.query.subtensorModule.nominatorMinRequiredStake();
|
|
229
|
+
const rxMaxValidators = substrateApi.api.rx.query.subtensorModule.maxAllowedValidators(0);
|
|
230
|
+
const subscription = combineLatest([rxMinDelegatorStake, rxMaxValidators, rxSubnetTAO, aprSubject]).subscribe({
|
|
231
|
+
next: ([minDelegatorStake, maxValidators, taoIn, apr]) => {
|
|
170
232
|
if (cancel) {
|
|
171
233
|
return;
|
|
172
234
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
type: this.type,
|
|
185
|
-
metadata: {
|
|
186
|
-
...this.metadataInfo,
|
|
187
|
-
description: this.getDescription(formatNumber(BNminDelegatorStake, _getAssetDecimals(this.nativeToken)))
|
|
188
|
-
},
|
|
189
|
-
statistic: {
|
|
190
|
-
assetEarning: [{
|
|
191
|
-
slug: this.nativeToken.slug
|
|
192
|
-
}],
|
|
193
|
-
maxCandidatePerFarmer: Number(maxValidatorPerNominator),
|
|
194
|
-
maxWithdrawalRequestPerFarmer: 1,
|
|
195
|
-
earningThreshold: {
|
|
196
|
-
join: BNminDelegatorStake.toString(),
|
|
197
|
-
defaultUnstake: '0',
|
|
198
|
-
fastUnstake: '0'
|
|
235
|
+
try {
|
|
236
|
+
const bnTaoIn = new BigN(taoIn.toString());
|
|
237
|
+
const bnMinStake = new BigN(minDelegatorStake.toString());
|
|
238
|
+
const minStake = bnMinStake.toString();
|
|
239
|
+
const data = {
|
|
240
|
+
...this.baseInfo,
|
|
241
|
+
type: this.type,
|
|
242
|
+
metadata: {
|
|
243
|
+
...this.metadataInfo,
|
|
244
|
+
description: this.getDescription(formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken))),
|
|
245
|
+
minValidate: minStake
|
|
199
246
|
},
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
247
|
+
statistic: {
|
|
248
|
+
assetEarning: [{
|
|
249
|
+
slug: this.nativeToken.slug
|
|
250
|
+
}],
|
|
251
|
+
maxCandidatePerFarmer: Number(maxValidators.toString()),
|
|
252
|
+
maxWithdrawalRequestPerFarmer: 1,
|
|
253
|
+
earningThreshold: {
|
|
254
|
+
join: minStake,
|
|
255
|
+
defaultUnstake: '0',
|
|
256
|
+
fastUnstake: '0'
|
|
257
|
+
},
|
|
258
|
+
eraTime: 24,
|
|
259
|
+
era: 0,
|
|
260
|
+
unstakingPeriod: 1.2,
|
|
261
|
+
tvl: bnTaoIn.toString(),
|
|
262
|
+
totalApy: apr
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
callback(data);
|
|
266
|
+
} catch (err) {
|
|
267
|
+
console.error(err);
|
|
268
|
+
}
|
|
210
269
|
}
|
|
211
|
-
};
|
|
212
|
-
const subscribeStakingMetadataInterval = () => {
|
|
213
|
-
updateStakingInfo().catch(console.error);
|
|
214
|
-
};
|
|
215
|
-
await substrateApi.isReady;
|
|
216
|
-
subscribeStakingMetadataInterval();
|
|
217
|
-
const interval = setInterval(subscribeStakingMetadataInterval, BITTENSOR_REFRESH_STAKE_APY);
|
|
270
|
+
});
|
|
218
271
|
return () => {
|
|
219
272
|
cancel = true;
|
|
273
|
+
aprSubject.complete();
|
|
274
|
+
subscription.unsubscribe();
|
|
220
275
|
clearInterval(interval);
|
|
221
276
|
};
|
|
222
277
|
}
|
|
223
278
|
|
|
224
279
|
/* Subscribe pool position */
|
|
225
280
|
|
|
226
|
-
|
|
281
|
+
parseNominatorMetadataBase(chainInfo, delegatorState, minBond, applyRate = false) {
|
|
227
282
|
const nominationList = [];
|
|
228
|
-
const getMinDelegatorStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
|
|
229
|
-
const minDelegatorStake = (await getMinDelegatorStake).toString();
|
|
230
283
|
let allActiveStake = BN_ZERO;
|
|
231
284
|
for (const delegate of delegatorState) {
|
|
232
|
-
const
|
|
233
|
-
const
|
|
285
|
+
const stake = new BigN(delegate.amount);
|
|
286
|
+
const originActiveStake = applyRate ? stake.multipliedBy(delegate.rate || 1).toFixed(0) : stake.toFixed(0);
|
|
287
|
+
const bnActiveStake = new BN(originActiveStake);
|
|
234
288
|
if (bnActiveStake.gt(BN_ZERO)) {
|
|
235
|
-
const delegationStatus = EarningStatus.EARNING_REWARD;
|
|
236
289
|
allActiveStake = allActiveStake.add(bnActiveStake);
|
|
237
290
|
nominationList.push({
|
|
238
|
-
status:
|
|
291
|
+
status: EarningStatus.EARNING_REWARD,
|
|
239
292
|
chain: chainInfo.slug,
|
|
240
293
|
validatorAddress: delegate.owner,
|
|
241
|
-
activeStake:
|
|
242
|
-
validatorMinStake:
|
|
243
|
-
validatorIdentity: delegate.identity
|
|
294
|
+
activeStake: delegate.amount,
|
|
295
|
+
validatorMinStake: minBond,
|
|
296
|
+
validatorIdentity: delegate.identity,
|
|
297
|
+
...(applyRate ? {
|
|
298
|
+
originActiveStake
|
|
299
|
+
} : {})
|
|
244
300
|
});
|
|
245
301
|
}
|
|
246
302
|
}
|
|
@@ -256,6 +312,10 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
256
312
|
unstakings: []
|
|
257
313
|
};
|
|
258
314
|
}
|
|
315
|
+
async parseNominatorMetadata(chainInfo, delegatorState) {
|
|
316
|
+
const bnMinBond = await this.getMinBond();
|
|
317
|
+
return this.parseNominatorMetadataBase(chainInfo, delegatorState, bnMinBond.toString());
|
|
318
|
+
}
|
|
259
319
|
async subscribePoolPosition(useAddresses, rsCallback) {
|
|
260
320
|
let cancel = false;
|
|
261
321
|
const substrateApi = await this.substrateApi.isReady;
|
|
@@ -298,7 +358,7 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
298
358
|
});
|
|
299
359
|
}
|
|
300
360
|
if (delegateStateInfo && delegateStateInfo.length > 0) {
|
|
301
|
-
this.parseNominatorMetadata(chainInfo,
|
|
361
|
+
this.parseNominatorMetadata(chainInfo, delegatorState).then(nominatorMetadata => {
|
|
302
362
|
rsCallback({
|
|
303
363
|
...defaultInfo,
|
|
304
364
|
...nominatorMetadata,
|
|
@@ -324,61 +384,6 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
324
384
|
});
|
|
325
385
|
}
|
|
326
386
|
};
|
|
327
|
-
|
|
328
|
-
// const getMainnetPoolPosition = async () => {
|
|
329
|
-
// const rawDelegateStateInfos = await Promise.all(
|
|
330
|
-
// useAddresses.map((address) => fetchTaoDelegateState(address))
|
|
331
|
-
// );
|
|
332
|
-
|
|
333
|
-
// if (rawDelegateStateInfos.length > 0) {
|
|
334
|
-
// rawDelegateStateInfos.forEach((rawDelegateStateInfo, i) => {
|
|
335
|
-
// const owner = reformatAddress(useAddresses[i], 42);
|
|
336
|
-
// const delegatorState: TaoStakingStakeOption[] = [];
|
|
337
|
-
// let bnTotalBalance = BN_ZERO;
|
|
338
|
-
// const delegateStateInfo = rawDelegateStateInfo.data;
|
|
339
|
-
|
|
340
|
-
// for (const delegate of delegateStateInfo) {
|
|
341
|
-
// const name = delegate.hotkey_name || delegate.hotkey.ss58;
|
|
342
|
-
|
|
343
|
-
// bnTotalBalance = bnTotalBalance.add(new BN(delegate.stake));
|
|
344
|
-
|
|
345
|
-
// delegatorState.push({
|
|
346
|
-
// owner: delegate.hotkey.ss58,
|
|
347
|
-
// amount: delegate.stake,
|
|
348
|
-
// identity: name
|
|
349
|
-
// });
|
|
350
|
-
// }
|
|
351
|
-
|
|
352
|
-
// if (delegateStateInfo && delegateStateInfo.length > 0) {
|
|
353
|
-
// this.parseNominatorMetadata(chainInfo, owner, delegatorState)
|
|
354
|
-
// .then((nominatorMetadata) => {
|
|
355
|
-
// rsCallback({
|
|
356
|
-
// ...defaultInfo,
|
|
357
|
-
// ...nominatorMetadata,
|
|
358
|
-
// address: owner,
|
|
359
|
-
// type: this.type
|
|
360
|
-
// });
|
|
361
|
-
// })
|
|
362
|
-
// .catch(console.error);
|
|
363
|
-
// } else {
|
|
364
|
-
// rsCallback({
|
|
365
|
-
// ...defaultInfo,
|
|
366
|
-
// type: this.type,
|
|
367
|
-
// address: owner,
|
|
368
|
-
// balanceToken: this.nativeToken.slug,
|
|
369
|
-
// totalStake: '0',
|
|
370
|
-
// activeStake: '0',
|
|
371
|
-
// unstakeBalance: '0',
|
|
372
|
-
// status: EarningStatus.NOT_STAKING,
|
|
373
|
-
// isBondedBefore: false,
|
|
374
|
-
// nominations: [],
|
|
375
|
-
// unstakings: []
|
|
376
|
-
// });
|
|
377
|
-
// }
|
|
378
|
-
// });
|
|
379
|
-
// }
|
|
380
|
-
// };
|
|
381
|
-
|
|
382
387
|
const getStakingPositionInterval = async () => {
|
|
383
388
|
if (cancel) {
|
|
384
389
|
return;
|
|
@@ -403,14 +408,14 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
403
408
|
/* Subscribe pool position */
|
|
404
409
|
|
|
405
410
|
/* Get pool targets */
|
|
406
|
-
|
|
407
411
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
408
|
-
async getDevnetPoolTargets() {
|
|
412
|
+
async getDevnetPoolTargets(netuid) {
|
|
409
413
|
const testnetDelegate = (await this.substrateApi.api.call.delegateInfoRuntimeApi.getDelegates()).toJSON();
|
|
410
|
-
const
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
+
const bnMinBond = await this.getMinBond(netuid);
|
|
415
|
+
const filteredDelegates = testnetDelegate.filter(delegate => {
|
|
416
|
+
return delegate.returnPer1000 !== 0;
|
|
417
|
+
});
|
|
418
|
+
return filteredDelegates.map(delegate => ({
|
|
414
419
|
address: delegate.delegateSs58,
|
|
415
420
|
totalStake: '0',
|
|
416
421
|
ownStake: '0',
|
|
@@ -424,14 +429,12 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
424
429
|
isCrowded: false
|
|
425
430
|
}));
|
|
426
431
|
}
|
|
427
|
-
async getMainnetPoolTargets() {
|
|
432
|
+
async getMainnetPoolTargets(netuid) {
|
|
428
433
|
const _topValidator = await this.bittensorCache.get();
|
|
429
434
|
const topValidator = _topValidator;
|
|
430
|
-
const
|
|
431
|
-
const nominatorMinRequiredStake = (await getNominatorMinRequiredStake).toString();
|
|
432
|
-
const bnMinBond = new BigN(nominatorMinRequiredStake);
|
|
435
|
+
const bnMinBond = await this.getMinBond();
|
|
433
436
|
const validatorList = topValidator.data;
|
|
434
|
-
const aprResponse = await this.bittensorCache.fetchApr(
|
|
437
|
+
const aprResponse = await this.bittensorCache.fetchApr(netuid);
|
|
435
438
|
const aprMap = {};
|
|
436
439
|
aprResponse.data.forEach(item => {
|
|
437
440
|
aprMap[item.hotkey.ss58] = item.thirty_day_apy;
|
|
@@ -466,11 +469,11 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
466
469
|
}));
|
|
467
470
|
return results;
|
|
468
471
|
}
|
|
469
|
-
async getPoolTargets() {
|
|
472
|
+
async getPoolTargets(netuid) {
|
|
470
473
|
if (this.chain === 'bittensor') {
|
|
471
|
-
return this.getMainnetPoolTargets();
|
|
474
|
+
return this.getMainnetPoolTargets(netuid !== null && netuid !== void 0 ? netuid : 0);
|
|
472
475
|
} else {
|
|
473
|
-
return this.getDevnetPoolTargets();
|
|
476
|
+
return this.getDevnetPoolTargets(netuid);
|
|
474
477
|
}
|
|
475
478
|
}
|
|
476
479
|
|
|
@@ -479,15 +482,22 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
479
482
|
/* Join pool action */
|
|
480
483
|
|
|
481
484
|
async createJoinExtrinsic(data, positionInfo, bondDest = 'Staked') {
|
|
485
|
+
var _subnetData$netuid, _subnetData$slippage;
|
|
482
486
|
const {
|
|
483
487
|
amount,
|
|
484
|
-
selectedValidators: targetValidators
|
|
488
|
+
selectedValidators: targetValidators,
|
|
489
|
+
subnetData
|
|
485
490
|
} = data;
|
|
486
491
|
const chainApi = await this.substrateApi.isReady;
|
|
487
492
|
const binaryAmount = new BigN(amount);
|
|
488
493
|
const selectedValidatorInfo = targetValidators[0];
|
|
489
494
|
const hotkey = selectedValidatorInfo.address;
|
|
490
|
-
const
|
|
495
|
+
const netuid = (_subnetData$netuid = subnetData === null || subnetData === void 0 ? void 0 : subnetData.netuid) !== null && _subnetData$netuid !== void 0 ? _subnetData$netuid : 0;
|
|
496
|
+
const slippage = (_subnetData$slippage = subnetData === null || subnetData === void 0 ? void 0 : subnetData.slippage) !== null && _subnetData$slippage !== void 0 ? _subnetData$slippage : DEFAULT_BITTENSOR_SLIPPAGE;
|
|
497
|
+
const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid));
|
|
498
|
+
const limitPrice = alphaToTaoPrice.multipliedBy(10 ** _getAssetDecimals(this.nativeToken)).multipliedBy(1 + slippage);
|
|
499
|
+
const BNlimitPrice = new BigN(limitPrice.integerValue(BigN.ROUND_CEIL).toFixed());
|
|
500
|
+
const extrinsic = chainApi.api.tx.subtensorModule.addStakeLimit(hotkey, netuid, binaryAmount.toFixed(), BNlimitPrice.toFixed(), false);
|
|
491
501
|
return [extrinsic, {
|
|
492
502
|
slug: this.nativeToken.slug,
|
|
493
503
|
amount: '0'
|
|
@@ -501,10 +511,10 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
501
511
|
return baseErrors;
|
|
502
512
|
}
|
|
503
513
|
const {
|
|
504
|
-
amount
|
|
514
|
+
amount,
|
|
515
|
+
subnetData
|
|
505
516
|
} = data;
|
|
506
|
-
const
|
|
507
|
-
const bnMinStake = minDelegatorStake.toString();
|
|
517
|
+
const bnMinStake = await this.getMinBond(subnetData === null || subnetData === void 0 ? void 0 : subnetData.netuid);
|
|
508
518
|
if (new BigN(amount).lt(bnMinStake)) {
|
|
509
519
|
return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Insufficient stake. You need to stake at least ${formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)} to earn rewards`))];
|
|
510
520
|
}
|
|
@@ -515,17 +525,20 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
515
525
|
|
|
516
526
|
/* Leave pool action */
|
|
517
527
|
|
|
518
|
-
async handleYieldUnstake(amount, address, selectedTarget) {
|
|
528
|
+
async handleYieldUnstake(amount, address, selectedTarget, netuid = 0, slippage = DEFAULT_BITTENSOR_SLIPPAGE) {
|
|
519
529
|
const apiPromise = await this.substrateApi.isReady;
|
|
520
|
-
|
|
521
|
-
const poolPosition = await this.getPoolPosition(address);
|
|
522
|
-
if (!selectedTarget || !poolPosition) {
|
|
530
|
+
if (!selectedTarget) {
|
|
523
531
|
return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
|
|
524
532
|
}
|
|
525
|
-
const
|
|
533
|
+
const binaryAmount = new BigN(amount);
|
|
534
|
+
const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid));
|
|
535
|
+
const limitPrice = alphaToTaoPrice.multipliedBy(10 ** _getAssetDecimals(this.nativeToken)).multipliedBy(1 - slippage);
|
|
536
|
+
const BNlimitPrice = new BigN(limitPrice.integerValue(BigN.ROUND_CEIL).toFixed());
|
|
537
|
+
const extrinsic = apiPromise.api.tx.subtensorModule.removeStakeLimit(selectedTarget, netuid, binaryAmount.toFixed(), BNlimitPrice.toFixed(), false);
|
|
526
538
|
return [ExtrinsicType.STAKING_UNBOND, extrinsic];
|
|
527
539
|
}
|
|
528
540
|
async validateYieldLeave(amount, address, fastLeave, selectedTarget, slug, poolInfo) {
|
|
541
|
+
var _poolInfo$metadata$su;
|
|
529
542
|
const baseErrors = await super.validateYieldLeave(amount, address, fastLeave, selectedTarget, slug);
|
|
530
543
|
if (baseErrors.length > 0) {
|
|
531
544
|
return baseErrors;
|
|
@@ -533,10 +546,13 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
533
546
|
if (!poolInfo) {
|
|
534
547
|
return [new TransactionError(BasicTxErrorType.INVALID_PARAMS)];
|
|
535
548
|
}
|
|
536
|
-
const
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
549
|
+
const netuid = (_poolInfo$metadata$su = poolInfo.metadata.subnetData) === null || _poolInfo$metadata$su === void 0 ? void 0 : _poolInfo$metadata$su.netuid;
|
|
550
|
+
const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid || 0));
|
|
551
|
+
const minDelegatorStake = await this.getMinBond(netuid);
|
|
552
|
+
const minUnstake = minDelegatorStake.dividedBy(alphaToTaoPrice);
|
|
553
|
+
if (new BigN(amount).lt(minUnstake)) {
|
|
554
|
+
var _poolInfo$metadata$su2;
|
|
555
|
+
return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Amount too low. You need to unstake at least ${formatNumber(minUnstake, _getAssetDecimals(this.nativeToken))} ${((_poolInfo$metadata$su2 = poolInfo.metadata.subnetData) === null || _poolInfo$metadata$su2 === void 0 ? void 0 : _poolInfo$metadata$su2.subnetSymbol) || _getAssetSymbol(this.nativeToken)}`))];
|
|
540
556
|
}
|
|
541
557
|
return baseErrors;
|
|
542
558
|
}
|
|
@@ -549,14 +565,15 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
549
565
|
const {
|
|
550
566
|
amount,
|
|
551
567
|
maxAmount,
|
|
568
|
+
metadata,
|
|
552
569
|
originValidator,
|
|
553
|
-
selectedValidators: targetValidators
|
|
570
|
+
selectedValidators: targetValidators,
|
|
571
|
+
subnetData
|
|
554
572
|
} = data;
|
|
555
573
|
if (!originValidator) {
|
|
556
574
|
return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
|
|
557
575
|
}
|
|
558
|
-
|
|
559
|
-
// Bittensor only supports changing 1 validator at a time, not multiple
|
|
576
|
+
const netuid = (subnetData === null || subnetData === void 0 ? void 0 : subnetData.netuid) || 0;
|
|
560
577
|
const selectedValidatorInfo = targetValidators[0];
|
|
561
578
|
const destValidator = selectedValidatorInfo.address;
|
|
562
579
|
if (new BigN(amount).lte(0)) {
|
|
@@ -565,17 +582,20 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
|
|
|
565
582
|
if (originValidator === destValidator) {
|
|
566
583
|
return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'From validator is the same with to validator'));
|
|
567
584
|
}
|
|
568
|
-
const
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
|
|
585
|
+
const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid));
|
|
586
|
+
const bnMinStake = await this.getMinBond(netuid);
|
|
587
|
+
const minUnstake = bnMinStake.dividedBy(alphaToTaoPrice);
|
|
588
|
+
const formattedMinUnstake = minUnstake.dividedBy(1000000).integerValue(BigN.ROUND_CEIL).dividedBy(1000);
|
|
589
|
+
const bnMinMoveStake = formattedMinUnstake.multipliedBy(10 ** _getAssetDecimals(this.nativeToken));
|
|
590
|
+
if (new BigN(amount).lt(bnMinMoveStake)) {
|
|
591
|
+
return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Amount too low. You need to move at least ${formattedMinUnstake.toString()} ${(metadata === null || metadata === void 0 ? void 0 : metadata.subnetSymbol) || ''}`)));
|
|
572
592
|
}
|
|
573
593
|
|
|
574
594
|
// Avoid remaining amount too low -> can't do anything with that amount
|
|
575
595
|
if (!(maxAmount === amount) && new BigN(maxAmount).minus(new BigN(amount)).lt(bnMinMoveStake)) {
|
|
576
|
-
return Promise.reject(new TransactionError(StakingTxErrorType.REMAINING_AMOUNT_TOO_LOW, t(`Your remaining stake on the initial validator will fall below minimum active stake and cannot be unstaked if you proceed with the chosen amount. Hit "Move all" to move all ${formatNumber(maxAmount, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)} to the new validator, or "Cancel" and lower the amount, then try again`)));
|
|
596
|
+
return Promise.reject(new TransactionError(StakingTxErrorType.REMAINING_AMOUNT_TOO_LOW, t(`Your remaining stake on the initial validator will fall below minimum active stake and cannot be unstaked if you proceed with the chosen amount. Hit "Move all" to move all ${formatNumber(maxAmount, _getAssetDecimals(this.nativeToken))} ${(metadata === null || metadata === void 0 ? void 0 : metadata.subnetSymbol) || _getAssetSymbol(this.nativeToken)} to the new validator, or "Cancel" and lower the amount, then try again`)));
|
|
577
597
|
}
|
|
578
|
-
const extrinsic = chainApi.api.tx.subtensorModule.moveStake(originValidator, destValidator,
|
|
598
|
+
const extrinsic = chainApi.api.tx.subtensorModule.moveStake(originValidator, destValidator, netuid, netuid, amount);
|
|
579
599
|
return extrinsic;
|
|
580
600
|
}
|
|
581
601
|
}
|
|
@@ -4,7 +4,6 @@ import { PalletNominationPoolsPoolMember } from '@subwallet/extension-base/core/
|
|
|
4
4
|
import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
|
|
5
5
|
import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
6
6
|
import { BaseYieldPositionInfo, EarningRewardHistoryItem, EarningRewardItem, HandleYieldStepData, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, StakeCancelWithdrawalParams, SubmitChangeValidatorStaking, SubmitJoinNominationPool, SubmitYieldJoinData, TransactionData, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
|
|
7
|
-
import { DeriveSessionProgress } from '@polkadot/api-derive/types';
|
|
8
7
|
import BasePoolHandler from '../base';
|
|
9
8
|
export default class NominationPoolHandler extends BasePoolHandler {
|
|
10
9
|
readonly type = YieldPoolType.NOMINATION_POOL;
|
|
@@ -16,7 +15,7 @@ export default class NominationPoolHandler extends BasePoolHandler {
|
|
|
16
15
|
constructor(state: KoniState, chain: string);
|
|
17
16
|
protected getDescription(amount?: string): string;
|
|
18
17
|
subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
|
|
19
|
-
parsePoolMemberMetadata(substrateApi: _SubstrateApi, poolMemberInfo: PalletNominationPoolsPoolMember, currentEra: string,
|
|
18
|
+
parsePoolMemberMetadata(substrateApi: _SubstrateApi, poolMemberInfo: PalletNominationPoolsPoolMember, currentEra: string, address: string): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
|
|
20
19
|
subscribePoolPosition(useAddresses: string[], resultCallback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
|
|
21
20
|
getPoolReward(useAddresses: string[], callBack: (rs: EarningRewardItem) => void): Promise<VoidFunction>;
|
|
22
21
|
getPoolRewardHistory(useAddresses: string[], callBack: (rs: EarningRewardHistoryItem) => void): Promise<VoidFunction>;
|
|
@@ -150,7 +150,7 @@ export default class NominationPoolHandler extends BasePoolHandler {
|
|
|
150
150
|
|
|
151
151
|
/* Subscribe pool position */
|
|
152
152
|
|
|
153
|
-
async parsePoolMemberMetadata(substrateApi, poolMemberInfo, currentEra,
|
|
153
|
+
async parsePoolMemberMetadata(substrateApi, poolMemberInfo, currentEra, address) {
|
|
154
154
|
const chainInfo = this.chainInfo;
|
|
155
155
|
const unlimitedNominatorRewarded = substrateApi.api.consts.staking.maxExposurePageSize !== undefined;
|
|
156
156
|
const _maxNominatorRewardedPerValidator = (substrateApi.api.consts.staking.maxNominatorRewardedPerValidator || 0).toString();
|
|
@@ -245,14 +245,13 @@ export default class NominationPoolHandler extends BasePoolHandler {
|
|
|
245
245
|
return;
|
|
246
246
|
}
|
|
247
247
|
if (ledgers) {
|
|
248
|
-
|
|
249
|
-
const [_currentEra, _deriveSessionProgress] = await Promise.all([substrateApi.api.query.staking.currentEra(), (_substrateApi$api$der = substrateApi.api.derive) === null || _substrateApi$api$der === void 0 ? void 0 : (_substrateApi$api$der2 = _substrateApi$api$der.session) === null || _substrateApi$api$der2 === void 0 ? void 0 : _substrateApi$api$der2.progress()]);
|
|
248
|
+
const _currentEra = await substrateApi.api.query.staking.currentEra();
|
|
250
249
|
const currentEra = _currentEra.toString();
|
|
251
250
|
await Promise.all(ledgers.map(async (_poolMemberInfo, i) => {
|
|
252
251
|
const poolMemberInfo = _poolMemberInfo.toPrimitive();
|
|
253
252
|
const owner = reformatAddress(useAddresses[i], 42);
|
|
254
253
|
if (poolMemberInfo) {
|
|
255
|
-
const nominatorMetadata = await this.parsePoolMemberMetadata(substrateApi, poolMemberInfo, currentEra,
|
|
254
|
+
const nominatorMetadata = await this.parsePoolMemberMetadata(substrateApi, poolMemberInfo, currentEra, owner);
|
|
256
255
|
resultCallback({
|
|
257
256
|
...defaultInfo,
|
|
258
257
|
...nominatorMetadata,
|
|
@@ -565,7 +564,14 @@ export default class NominationPoolHandler extends BasePoolHandler {
|
|
|
565
564
|
async handleYieldWithdraw(address, unstakingInfo) {
|
|
566
565
|
const chainApi = await this.substrateApi.isReady;
|
|
567
566
|
if (chainApi.api.tx.nominationPools.withdrawUnbonded.meta.args.length === 2) {
|
|
568
|
-
|
|
567
|
+
var _chainApi$api$call, _chainApi$api$call$no;
|
|
568
|
+
let slashingSpanCount;
|
|
569
|
+
if ((_chainApi$api$call = chainApi.api.call) !== null && _chainApi$api$call !== void 0 && (_chainApi$api$call$no = _chainApi$api$call.nominationPoolsApi) !== null && _chainApi$api$call$no !== void 0 && _chainApi$api$call$no.memberPendingSlash) {
|
|
570
|
+
slashingSpanCount = await chainApi.api.call.nominationPoolsApi.memberPendingSlash(address);
|
|
571
|
+
} else {
|
|
572
|
+
// Incase api call not exists
|
|
573
|
+
slashingSpanCount = chainApi.api.consts.staking.historyDepth.toPrimitive();
|
|
574
|
+
}
|
|
569
575
|
return chainApi.api.tx.nominationPools.withdrawUnbonded({
|
|
570
576
|
Id: address
|
|
571
577
|
}, slashingSpanCount);
|
|
@@ -8,6 +8,7 @@ import { PromiseHandler } from '@subwallet/extension-base/utils';
|
|
|
8
8
|
import { BehaviorSubject } from 'rxjs';
|
|
9
9
|
import { EarningSlippageResult } from './handlers/native-staking/dtao';
|
|
10
10
|
import { BasePoolHandler } from './handlers';
|
|
11
|
+
export declare const fetchPoolsData: () => Promise<Record<string, YieldPoolInfo>>;
|
|
11
12
|
export default class EarningService implements StoppableServiceInterface, PersistDataServiceInterface {
|
|
12
13
|
protected readonly state: KoniState;
|
|
13
14
|
protected handlers: Record<string, BasePoolHandler>;
|
|
@@ -14,7 +14,7 @@ import { addLazy, createPromiseHandler, filterAddressByChainInfo, removeLazy } f
|
|
|
14
14
|
import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache';
|
|
15
15
|
import { BehaviorSubject, combineLatest } from 'rxjs';
|
|
16
16
|
import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, SubnetTaoStakingPoolHandler, TaoNativeStakingPoolHandler } from "./handlers/index.js";
|
|
17
|
-
const fetchPoolsData = async () => {
|
|
17
|
+
export const fetchPoolsData = async () => {
|
|
18
18
|
const fetchData = await fetchStaticCache('earning/yield-pools.json', {
|
|
19
19
|
data: {}
|
|
20
20
|
});
|
|
@@ -350,7 +350,9 @@ export default class EarningService {
|
|
|
350
350
|
const unsubList = [];
|
|
351
351
|
for (const handler of Object.values(this.handlers)) {
|
|
352
352
|
// Force subscribe onchain data
|
|
353
|
-
const forceSubscribe = handler.type === YieldPoolType.LIQUID_STAKING || handler.type === YieldPoolType.LENDING ||
|
|
353
|
+
const forceSubscribe = handler.type === YieldPoolType.LIQUID_STAKING || handler.type === YieldPoolType.LENDING ||
|
|
354
|
+
// Skip subscribing for subnet staking handlers because subnet staking slugs are not included in the online cache (only slugs with netuid are cached)
|
|
355
|
+
!onlineData[handler.slug] && handler.type !== YieldPoolType.SUBNET_STAKING;
|
|
354
356
|
if (!this.useOnlineCacheOnly || forceSubscribe) {
|
|
355
357
|
handler.subscribePoolInfo(callback).then(unsub => {
|
|
356
358
|
if (!cancel) {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { _AssetType } from '@subwallet/chain-list/types';
|
|
5
5
|
import { _getAssetDecimals, _getAssetPriceId, _getTokenOnChainAssetId } from '@subwallet/extension-base/services/chain-service/utils';
|
|
6
6
|
import { checkLiquidityForPool, estimateTokensForPool, getReserveForPool } from '@subwallet/extension-base/services/swap-service/handler/asset-hub/utils';
|
|
7
|
-
import subwalletApiSdk from '@subwallet/subwallet-
|
|
7
|
+
import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk';
|
|
8
8
|
import BigN from 'bignumber.js';
|
|
9
9
|
export async function getAssetHubTokensCanPayFee(request) {
|
|
10
10
|
const {
|
|
@@ -122,20 +122,24 @@ export function batchExtrinsicSetFeeHydration(substrateApi, tx, feeSetting, asse
|
|
|
122
122
|
return tx;
|
|
123
123
|
}
|
|
124
124
|
export async function getHydrationRate(address, hdx, desToken) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
125
|
+
let quoteRate;
|
|
126
|
+
try {
|
|
127
|
+
const quote = await subwalletApiSdk.swapApi.getHydrationRate({
|
|
128
|
+
address,
|
|
129
|
+
pair: {
|
|
130
|
+
slug: `${hdx.slug}___${desToken.slug}`,
|
|
131
|
+
from: hdx.slug,
|
|
132
|
+
to: desToken.slug
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
quoteRate = quote.rate;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error(`Failed to fetch swap quote: ${error.message}`);
|
|
138
|
+
}
|
|
139
|
+
if (quoteRate) {
|
|
137
140
|
const hdxDecimal = _getAssetDecimals(hdx);
|
|
138
141
|
const desTokenDecimal = _getAssetDecimals(desToken);
|
|
139
142
|
return new BigN(quoteRate).multipliedBy(10 ** (desTokenDecimal - hdxDecimal)).toFixed();
|
|
140
143
|
}
|
|
144
|
+
return undefined;
|
|
141
145
|
}
|