@subwallet/extension-base 1.1.40-1 → 1.1.41-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.
Files changed (94) hide show
  1. package/background/KoniTypes.d.ts +3 -1
  2. package/cjs/constants/index.js +1 -1
  3. package/cjs/koni/api/dotsama/transfer.js +1 -1
  4. package/cjs/koni/api/nft/bit.country/index.js +2 -0
  5. package/cjs/koni/api/nft/config.js +3 -1
  6. package/cjs/koni/api/tokens/evm/transfer.js +4 -4
  7. package/cjs/koni/background/handlers/Extension.js +32 -17
  8. package/cjs/koni/background/handlers/State.js +41 -9
  9. package/cjs/packageInfo.js +1 -1
  10. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +58 -0
  11. package/cjs/services/chain-service/constants.js +11 -7
  12. package/cjs/services/chain-service/handler/chain-spec/goldberg.js +75 -8
  13. package/cjs/services/chain-service/index.js +71 -59
  14. package/cjs/services/chain-service/utils.js +11 -6
  15. package/cjs/services/earning-service/constants/chains.js +2 -2
  16. package/cjs/services/earning-service/handlers/liquid-staking/acala.js +9 -3
  17. package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +8 -1
  18. package/cjs/services/earning-service/handlers/liquid-staking/parallel.js +6 -1
  19. package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +25 -17
  20. package/cjs/services/earning-service/handlers/native-staking/amplitude.js +4 -0
  21. package/cjs/services/earning-service/handlers/native-staking/astar.js +6 -2
  22. package/cjs/services/earning-service/handlers/native-staking/para-chain.js +5 -0
  23. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +14 -16
  24. package/cjs/services/earning-service/handlers/nomination-pool/index.js +9 -11
  25. package/cjs/services/earning-service/handlers/special.js +2 -0
  26. package/cjs/services/earning-service/service.js +51 -18
  27. package/cjs/services/fee-service/service.js +70 -0
  28. package/cjs/services/fee-service/utils/index.js +209 -0
  29. package/cjs/services/migration-service/scripts/DeleteChainStaking.js +23 -0
  30. package/cjs/services/migration-service/scripts/index.js +3 -1
  31. package/cjs/services/transaction-service/index.js +37 -37
  32. package/cjs/types/fee/index.js +1 -0
  33. package/cjs/types/index.js +11 -0
  34. package/cjs/utils/eth.js +2 -105
  35. package/cjs/utils/index.js +12 -0
  36. package/cjs/utils/reportError.js +31 -0
  37. package/constants/index.d.ts +1 -1
  38. package/constants/index.js +1 -1
  39. package/koni/api/dotsama/transfer.js +1 -1
  40. package/koni/api/nft/bit.country/index.js +3 -1
  41. package/koni/api/nft/config.d.ts +1 -0
  42. package/koni/api/nft/config.js +1 -0
  43. package/koni/api/tokens/evm/transfer.js +1 -1
  44. package/koni/background/handlers/Extension.d.ts +1 -0
  45. package/koni/background/handlers/Extension.js +18 -3
  46. package/koni/background/handlers/State.d.ts +4 -1
  47. package/koni/background/handlers/State.js +32 -1
  48. package/package.json +31 -6
  49. package/packageInfo.js +1 -1
  50. package/services/balance-service/helpers/subscribe/substrate/index.js +59 -1
  51. package/services/chain-service/constants.d.ts +2 -0
  52. package/services/chain-service/constants.js +11 -7
  53. package/services/chain-service/handler/chain-spec/goldberg.d.ts +70 -1
  54. package/services/chain-service/handler/chain-spec/goldberg.js +75 -8
  55. package/services/chain-service/index.d.ts +7 -3
  56. package/services/chain-service/index.js +62 -51
  57. package/services/chain-service/types.d.ts +4 -0
  58. package/services/chain-service/utils.d.ts +1 -0
  59. package/services/chain-service/utils.js +10 -6
  60. package/services/earning-service/constants/chains.js +2 -2
  61. package/services/earning-service/handlers/liquid-staking/acala.js +9 -3
  62. package/services/earning-service/handlers/liquid-staking/bifrost.js +8 -1
  63. package/services/earning-service/handlers/liquid-staking/parallel.d.ts +1 -1
  64. package/services/earning-service/handlers/liquid-staking/parallel.js +6 -1
  65. package/services/earning-service/handlers/liquid-staking/stella-swap.js +25 -17
  66. package/services/earning-service/handlers/native-staking/amplitude.js +4 -0
  67. package/services/earning-service/handlers/native-staking/astar.js +6 -2
  68. package/services/earning-service/handlers/native-staking/para-chain.js +5 -0
  69. package/services/earning-service/handlers/native-staking/relay-chain.js +15 -17
  70. package/services/earning-service/handlers/nomination-pool/index.js +10 -12
  71. package/services/earning-service/handlers/special.d.ts +1 -0
  72. package/services/earning-service/handlers/special.js +2 -0
  73. package/services/earning-service/service.d.ts +4 -1
  74. package/services/earning-service/service.js +52 -19
  75. package/services/fee-service/service.d.ts +12 -0
  76. package/services/fee-service/service.js +63 -0
  77. package/services/fee-service/utils/index.d.ts +8 -0
  78. package/services/fee-service/utils/index.js +193 -0
  79. package/services/migration-service/scripts/DeleteChainStaking.d.ts +4 -0
  80. package/services/migration-service/scripts/DeleteChainStaking.js +15 -0
  81. package/services/migration-service/scripts/index.js +3 -1
  82. package/services/transaction-service/index.js +2 -2
  83. package/types/fee/index.d.ts +49 -0
  84. package/types/fee/index.js +1 -0
  85. package/types/index.d.ts +1 -0
  86. package/types/index.js +1 -0
  87. package/types/yield/info/account/unstake.d.ts +2 -0
  88. package/types/yield/info/pallet.d.ts +4 -0
  89. package/utils/eth.d.ts +0 -15
  90. package/utils/eth.js +0 -101
  91. package/utils/index.d.ts +1 -0
  92. package/utils/index.js +1 -0
  93. package/utils/reportError.d.ts +1 -0
  94. package/utils/reportError.js +23 -0
@@ -5,8 +5,8 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
5
5
  import { BasicTxErrorType, ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { getERC20Contract } from '@subwallet/extension-base/koni/api/tokens/evm/web3';
7
7
  import { _getAssetDecimals, _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils';
8
+ import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils';
8
9
  import { EarningStatus, UnstakingStatus, YieldStepType } from '@subwallet/extension-base/types';
9
- import { recalculateGasPrice } from '@subwallet/extension-base/utils/eth';
10
10
  import fetch from 'cross-fetch';
11
11
  import { BN, BN_TEN, BN_ZERO } from '@polkadot/util';
12
12
  import { ST_LIQUID_TOKEN_ABI } from "../../constants/index.js";
@@ -248,6 +248,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
248
248
  return Promise.resolve([]);
249
249
  }
250
250
  async handleTokenApproveStep(data, path) {
251
+ var _priority$maxFeePerGa, _priority$maxPriority;
251
252
  const {
252
253
  address
253
254
  } = data;
@@ -266,14 +267,15 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
266
267
  const gasLimit = await approveCall.estimateGas({
267
268
  from: address
268
269
  });
269
- const _price = await evmApi.api.eth.getGasPrice();
270
- const gasPrice = recalculateGasPrice(_price, this.chain);
270
+ const priority = await calculateGasFeeParams(evmApi, this.chain);
271
271
  const transactionObject = {
272
272
  from: address,
273
273
  to: _getContractAddressOfToken(inputTokenInfo),
274
274
  data: approveEncodedCall,
275
- gasPrice: gasPrice,
276
- gas: gasLimit
275
+ gas: gasLimit,
276
+ gasPrice: priority.gasPrice,
277
+ maxFeePerGas: (_priority$maxFeePerGa = priority.maxFeePerGas) === null || _priority$maxFeePerGa === void 0 ? void 0 : _priority$maxFeePerGa.toString(),
278
+ maxPriorityFeePerGas: (_priority$maxPriority = priority.maxPriorityFeePerGas) === null || _priority$maxPriority === void 0 ? void 0 : _priority$maxPriority.toString()
277
279
  };
278
280
  const _data = {
279
281
  inputTokenSlug: inputTokenSlug,
@@ -289,6 +291,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
289
291
  });
290
292
  }
291
293
  async handleSubmitStep(data, path) {
294
+ var _priority$maxFeePerGa2, _priority$maxPriority2;
292
295
  const {
293
296
  address,
294
297
  amount
@@ -307,14 +310,15 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
307
310
  const gasLimit = await depositCall.estimateGas({
308
311
  from: address
309
312
  });
310
- const _price = await evmApi.api.eth.getGasPrice();
311
- const gasPrice = recalculateGasPrice(_price, this.chain);
313
+ const priority = await calculateGasFeeParams(evmApi, this.chain);
312
314
  const transactionObject = {
313
315
  from: address,
314
316
  to: _getContractAddressOfToken(derivativeTokenInfo),
315
317
  data: depositEncodedCall,
316
- gasPrice: gasPrice,
317
- gas: gasLimit
318
+ gas: gasLimit,
319
+ gasPrice: priority.gasPrice,
320
+ maxFeePerGas: (_priority$maxFeePerGa2 = priority.maxFeePerGas) === null || _priority$maxFeePerGa2 === void 0 ? void 0 : _priority$maxFeePerGa2.toString(),
321
+ maxPriorityFeePerGas: (_priority$maxPriority2 = priority.maxPriorityFeePerGas) === null || _priority$maxPriority2 === void 0 ? void 0 : _priority$maxPriority2.toString()
318
322
  };
319
323
  return {
320
324
  txChain: this.chain,
@@ -334,6 +338,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
334
338
  return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
335
339
  }
336
340
  async handleYieldUnstake(amount, address, selectedTarget) {
341
+ var _priority$maxFeePerGa3, _priority$maxPriority3;
337
342
  const evmApi = this.evmApi;
338
343
  const derivativeTokenSlug = this.derivativeAssets[0];
339
344
  const derivativeTokenInfo = this.state.getAssetBySlug(derivativeTokenSlug);
@@ -348,14 +353,15 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
348
353
  const gasLimit = await redeemCall.estimateGas({
349
354
  from: address
350
355
  });
351
- const _price = await evmApi.api.eth.getGasPrice();
352
- const gasPrice = recalculateGasPrice(_price, this.chain);
356
+ const priority = await calculateGasFeeParams(evmApi, this.chain);
353
357
  const transaction = {
354
358
  from: address,
355
359
  to: _getContractAddressOfToken(derivativeTokenInfo),
356
360
  data: redeemEncodedCall,
357
- gasPrice: gasPrice,
358
- gas: gasLimit
361
+ gas: gasLimit,
362
+ gasPrice: priority.gasPrice,
363
+ maxFeePerGas: (_priority$maxFeePerGa3 = priority.maxFeePerGas) === null || _priority$maxFeePerGa3 === void 0 ? void 0 : _priority$maxFeePerGa3.toString(),
364
+ maxPriorityFeePerGas: (_priority$maxPriority3 = priority.maxPriorityFeePerGas) === null || _priority$maxPriority3 === void 0 ? void 0 : _priority$maxPriority3.toString()
359
365
  };
360
366
  return [ExtrinsicType.UNSTAKE_STDOT, transaction];
361
367
  }
@@ -365,6 +371,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
365
371
  /* Other actions */
366
372
 
367
373
  async handleYieldWithdraw(address, unstakingInfo) {
374
+ var _priority$maxFeePerGa4, _priority$maxPriority4;
368
375
  const evmApi = this.evmApi;
369
376
  const derivativeTokenSlug = this.derivativeAssets[0];
370
377
  const derivativeTokenInfo = this.state.getAssetBySlug(derivativeTokenSlug);
@@ -379,14 +386,15 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
379
386
  const gasLimit = await withdrawCall.estimateGas({
380
387
  from: address
381
388
  });
382
- const _price = await evmApi.api.eth.getGasPrice();
383
- const gasPrice = recalculateGasPrice(_price, this.chain);
389
+ const priority = await calculateGasFeeParams(evmApi, this.chain);
384
390
  return {
385
391
  from: address,
386
392
  to: _getContractAddressOfToken(derivativeTokenInfo),
387
393
  data: withdrawEncodedCall,
388
- gasPrice: gasPrice,
389
- gas: gasLimit
394
+ gas: gasLimit,
395
+ gasPrice: priority.gasPrice,
396
+ maxFeePerGas: (_priority$maxFeePerGa4 = priority.maxFeePerGas) === null || _priority$maxFeePerGa4 === void 0 ? void 0 : _priority$maxFeePerGa4.toString(),
397
+ maxPriorityFeePerGas: (_priority$maxPriority4 = priority.maxPriorityFeePerGas) === null || _priority$maxPriority4 === void 0 ? void 0 : _priority$maxPriority4.toString()
390
398
  }; // TODO: check tx history parsing
391
399
  }
392
400
 
@@ -141,12 +141,16 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
141
141
  const isClaimable = parseInt(unstakingBlock) - currentBlockNumber < 0;
142
142
  const remainingBlock = parseInt(unstakingBlock) - currentBlockNumber;
143
143
  const waitingTime = remainingBlock * blockDuration;
144
+ // const currentTimestampMs = Date.now();
145
+ // const targetTimestampMs = currentTimestampMs + waitingTime * 60 * 60 * 1000;
146
+
144
147
  unstakingBalance = unstakingAmount.toString();
145
148
  unstakingList.push({
146
149
  chain: chainInfo.slug,
147
150
  status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
148
151
  claimable: unstakingAmount.toString(),
149
152
  waitingTime,
153
+ // targetTimestampMs: targetTimestampMs,
150
154
  validatorAddress: undefined
151
155
  });
152
156
  }
@@ -18,8 +18,7 @@ export function getAstarWithdrawable(yieldPosition) {
18
18
  const unstakingInfo = {
19
19
  chain: yieldPosition.chain,
20
20
  status: UnstakingStatus.CLAIMABLE,
21
- claimable: '0',
22
- waitingTime: 0
21
+ claimable: '0'
23
22
  };
24
23
  let bnWithdrawable = BN_ZERO;
25
24
  for (const unstaking of yieldPosition.unstakings) {
@@ -200,14 +199,19 @@ export default class AstarNativeStakingPoolHandler extends BaseParaNativeStaking
200
199
  const isClaimable = unlockingChunk.unlockEra - parseInt(currentEra) < 0;
201
200
  const remainingEra = unlockingChunk.unlockEra - parseInt(currentEra);
202
201
  const waitingTime = remainingEra * _STAKING_ERA_LENGTH_MAP[chainInfo.slug];
202
+ // const currentTimestampMs = Date.now();
203
+ // const targetTimestampMs = currentTimestampMs + waitingTime * 60 * 60 * 1000;
204
+
203
205
  unstakingList.push({
204
206
  chain: chainInfo.slug,
205
207
  status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
206
208
  claimable: unlockingChunk.amount.toString(),
207
209
  waitingTime
210
+ // targetTimestampMs: targetTimestampMs
208
211
  });
209
212
  }
210
213
  }
214
+
211
215
  if (nominationList.length === 0 && unstakingList.length === 0) {
212
216
  return {
213
217
  balanceToken: this.nativeToken.slug,
@@ -137,13 +137,18 @@ export default class ParaNativeStakingPoolHandler extends BaseParaNativeStakingP
137
137
  const remainingEra = scheduledRequest.whenExecutable - currentRound;
138
138
  const waitingTime = remainingEra * _STAKING_ERA_LENGTH_MAP[chainInfo.slug];
139
139
  const claimable = Object.values(scheduledRequest.action)[0];
140
+ // const currentTimestampMs = Date.now();
141
+ // const targetTimestampMs = currentTimestampMs + waitingTime * 60 * 60 * 1000;
142
+
140
143
  unstakingMap[delegation.owner] = {
141
144
  chain: chainInfo.slug,
142
145
  status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
143
146
  validatorAddress: delegation.owner,
144
147
  claimable: claimable.toString(),
145
148
  waitingTime
149
+ // targetTimestampMs: targetTimestampMs
146
150
  };
151
+
147
152
  hasUnstaking = true;
148
153
  break; // only handle 1 scheduledRequest per collator
149
154
  }
@@ -4,7 +4,7 @@
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { BasicTxErrorType, ExtrinsicType, StakingTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { calculateAlephZeroValidatorReturn, calculateChainStakedReturnV2, calculateInflation, calculateTernoaValidatorReturn, calculateValidatorStakedReturn, getAvgValidatorEraReward, getCommission, getMaxValidatorErrorMessage, getMinStakeErrorMessage, getSupportedDaysByHistoryDepth } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
7
- import { _EXPECTED_BLOCK_TIME, _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
7
+ import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
8
8
  import { _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils';
9
9
  import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning-service/constants';
10
10
  import { parseIdentity } from '@subwallet/extension-base/services/earning-service/utils';
@@ -122,9 +122,9 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
122
122
  /* Subscribe pool position */
123
123
 
124
124
  async parseNominatorMetadata(chainInfo, address, substrateApi, ledger, currentEra, minStake, _deriveSessionProgress) {
125
- var _substrateApi$api$que7, _substrateApi$api$que8, _substrateApi$api$que9, _substrateApi$api$que10;
125
+ var _substrateApi$api$que7, _substrateApi$api$que8, _substrateApi$api$que9, _substrateApi$api$que10, _substrateApi$api$que11, _substrateApi$api$que12;
126
126
  const chain = chainInfo.slug;
127
- const [_nominations, _bonded] = await Promise.all([(_substrateApi$api$que7 = substrateApi.api.query) === null || _substrateApi$api$que7 === void 0 ? void 0 : (_substrateApi$api$que8 = _substrateApi$api$que7.staking) === null || _substrateApi$api$que8 === void 0 ? void 0 : _substrateApi$api$que8.nominators(address), (_substrateApi$api$que9 = substrateApi.api.query) === null || _substrateApi$api$que9 === void 0 ? void 0 : (_substrateApi$api$que10 = _substrateApi$api$que9.staking) === null || _substrateApi$api$que10 === void 0 ? void 0 : _substrateApi$api$que10.bonded(address)]);
127
+ const [_nominations, _bonded, _activeEra] = await Promise.all([(_substrateApi$api$que7 = substrateApi.api.query) === null || _substrateApi$api$que7 === void 0 ? void 0 : (_substrateApi$api$que8 = _substrateApi$api$que7.staking) === null || _substrateApi$api$que8 === void 0 ? void 0 : _substrateApi$api$que8.nominators(address), (_substrateApi$api$que9 = substrateApi.api.query) === null || _substrateApi$api$que9 === void 0 ? void 0 : (_substrateApi$api$que10 = _substrateApi$api$que9.staking) === null || _substrateApi$api$que10 === void 0 ? void 0 : _substrateApi$api$que10.bonded(address), (_substrateApi$api$que11 = substrateApi.api.query) === null || _substrateApi$api$que11 === void 0 ? void 0 : (_substrateApi$api$que12 = _substrateApi$api$que11.staking) === null || _substrateApi$api$que12 === void 0 ? void 0 : _substrateApi$api$que12.activeEra()]);
128
128
  const unlimitedNominatorRewarded = substrateApi.api.consts.staking.maxExposurePageSize !== undefined;
129
129
  const _maxNominatorRewardedPerValidator = (substrateApi.api.consts.staking.maxNominatorRewardedPerValidator || 0).toString();
130
130
  const maxNominatorRewardedPerValidator = parseInt(_maxNominatorRewardedPerValidator);
@@ -181,21 +181,19 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
181
181
  }
182
182
  }
183
183
  ledger.unlocking.forEach(unlockingChunk => {
184
- // Calculate the remaining time for current era ending
185
- const isClaimable = unlockingChunk.era - parseInt(currentEra) < 0;
186
- const remainingEra = unlockingChunk.era - parseInt(currentEra);
187
- const expectedBlockTime = _EXPECTED_BLOCK_TIME[chain];
188
- const eraLength = _deriveSessionProgress.eraLength.toNumber();
189
- const eraProgress = _deriveSessionProgress.eraProgress.toNumber();
190
- const remainingSlots = eraLength - eraProgress;
191
- const remainingHours = expectedBlockTime * remainingSlots / 60 / 60;
184
+ const activeEra = _activeEra.toPrimitive();
185
+ const era = parseInt(activeEra.index);
186
+ const startTimestampMs = parseInt(activeEra.start);
187
+ const remainingEra = unlockingChunk.era - era;
192
188
  const eraTime = _STAKING_ERA_LENGTH_MAP[chainInfo.slug] || _STAKING_ERA_LENGTH_MAP.default; // in hours
193
- const waitingTime = remainingEra * eraTime + remainingHours;
189
+ const remaningTimestampMs = remainingEra * eraTime * 60 * 60 * 1000;
190
+ const targetTimestampMs = startTimestampMs + remaningTimestampMs;
191
+ const isClaimable = targetTimestampMs - Date.now() <= 0;
194
192
  unstakingList.push({
195
193
  chain,
196
194
  status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
197
195
  claimable: unlockingChunk.value.toString(),
198
- waitingTime: waitingTime
196
+ targetTimestampMs: targetTimestampMs
199
197
  });
200
198
  });
201
199
  return {
@@ -210,19 +208,19 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
210
208
  };
211
209
  }
212
210
  async subscribePoolPosition(useAddresses, resultCallback) {
213
- var _substrateApi$api$que11;
211
+ var _substrateApi$api$que13;
214
212
  let cancel = false;
215
213
  const substrateApi = await this.substrateApi.isReady;
216
214
  const defaultInfo = this.baseInfo;
217
215
  const chainInfo = this.chainInfo;
218
- const unsub = await ((_substrateApi$api$que11 = substrateApi.api.query.staking) === null || _substrateApi$api$que11 === void 0 ? void 0 : _substrateApi$api$que11.ledger.multi(useAddresses, async ledgers => {
216
+ const unsub = await ((_substrateApi$api$que13 = substrateApi.api.query.staking) === null || _substrateApi$api$que13 === void 0 ? void 0 : _substrateApi$api$que13.ledger.multi(useAddresses, async ledgers => {
219
217
  if (cancel) {
220
218
  unsub();
221
219
  return;
222
220
  }
223
221
  if (ledgers) {
224
- var _substrateApi$api$que12, _substrateApi$api$que13, _substrateApi$api$que14, _substrateApi$api$que15, _substrateApi$api$que16, _substrateApi$api$que17, _substrateApi$api$que18, _substrateApi$api$que19, _substrateApi$api$der, _substrateApi$api$der2;
225
- const [_currentEra, _minimumActiveStake, _minNominatorBond, _deriveSessionProgress] = await Promise.all([(_substrateApi$api$que12 = substrateApi.api.query) === null || _substrateApi$api$que12 === void 0 ? void 0 : (_substrateApi$api$que13 = _substrateApi$api$que12.staking) === null || _substrateApi$api$que13 === void 0 ? void 0 : _substrateApi$api$que13.currentEra(), ((_substrateApi$api$que14 = substrateApi.api.query) === null || _substrateApi$api$que14 === void 0 ? void 0 : (_substrateApi$api$que15 = _substrateApi$api$que14.staking) === null || _substrateApi$api$que15 === void 0 ? void 0 : _substrateApi$api$que15.minimumActiveStake) && ((_substrateApi$api$que16 = substrateApi.api.query) === null || _substrateApi$api$que16 === void 0 ? void 0 : (_substrateApi$api$que17 = _substrateApi$api$que16.staking) === null || _substrateApi$api$que17 === void 0 ? void 0 : _substrateApi$api$que17.minimumActiveStake()), (_substrateApi$api$que18 = substrateApi.api.query) === null || _substrateApi$api$que18 === void 0 ? void 0 : (_substrateApi$api$que19 = _substrateApi$api$que18.staking) === null || _substrateApi$api$que19 === void 0 ? void 0 : _substrateApi$api$que19.minNominatorBond(), (_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()]);
222
+ var _substrateApi$api$que14, _substrateApi$api$que15, _substrateApi$api$que16, _substrateApi$api$que17, _substrateApi$api$que18, _substrateApi$api$que19, _substrateApi$api$que20, _substrateApi$api$que21, _substrateApi$api$der, _substrateApi$api$der2;
223
+ const [_currentEra, _minimumActiveStake, _minNominatorBond, _deriveSessionProgress] = await Promise.all([(_substrateApi$api$que14 = substrateApi.api.query) === null || _substrateApi$api$que14 === void 0 ? void 0 : (_substrateApi$api$que15 = _substrateApi$api$que14.staking) === null || _substrateApi$api$que15 === void 0 ? void 0 : _substrateApi$api$que15.currentEra(), ((_substrateApi$api$que16 = substrateApi.api.query) === null || _substrateApi$api$que16 === void 0 ? void 0 : (_substrateApi$api$que17 = _substrateApi$api$que16.staking) === null || _substrateApi$api$que17 === void 0 ? void 0 : _substrateApi$api$que17.minimumActiveStake) && ((_substrateApi$api$que18 = substrateApi.api.query) === null || _substrateApi$api$que18 === void 0 ? void 0 : (_substrateApi$api$que19 = _substrateApi$api$que18.staking) === null || _substrateApi$api$que19 === void 0 ? void 0 : _substrateApi$api$que19.minimumActiveStake()), (_substrateApi$api$que20 = substrateApi.api.query) === null || _substrateApi$api$que20 === void 0 ? void 0 : (_substrateApi$api$que21 = _substrateApi$api$que20.staking) === null || _substrateApi$api$que21 === void 0 ? void 0 : _substrateApi$api$que21.minNominatorBond(), (_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()]);
226
224
  const currentEra = _currentEra.toString();
227
225
  const minActiveStake = (_minimumActiveStake === null || _minimumActiveStake === void 0 ? void 0 : _minimumActiveStake.toString()) || '0';
228
226
  const minNominatorBond = _minNominatorBond.toString();
@@ -4,7 +4,7 @@
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { APIItemState, BasicTxErrorType, ChainType, ExtrinsicType, StakingTxErrorType, StakingType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { calculateChainStakedReturnV2, calculateInflation, getAvgValidatorEraReward, getExistUnstakeErrorMessage, getMinStakeErrorMessage, getSupportedDaysByHistoryDepth, parsePoolStashAddress } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
7
- import { _EXPECTED_BLOCK_TIME, _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
7
+ import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
8
8
  import { _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils';
9
9
  import { EarningStatus, UnstakingStatus, YieldPoolType, YieldStepType } from '@subwallet/extension-base/types';
10
10
  import { balanceFormatter, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
@@ -150,7 +150,7 @@ export default class NominationPoolHandler extends BasePoolHandler {
150
150
  const maxNominatorRewardedPerValidator = parseInt(_maxNominatorRewardedPerValidator);
151
151
  const poolsPalletId = substrateApi.api.consts.nominationPools.palletId.toString();
152
152
  const poolStashAccount = parsePoolStashAddress(substrateApi.api, 0, poolMemberInfo.poolId, poolsPalletId);
153
- const [_nominations, _poolMetadata] = await Promise.all([substrateApi.api.query.staking.nominators(poolStashAccount), substrateApi.api.query.nominationPools.metadata(poolMemberInfo.poolId)]);
153
+ const [_nominations, _poolMetadata, _activeEra] = await Promise.all([substrateApi.api.query.staking.nominators(poolStashAccount), substrateApi.api.query.nominationPools.metadata(poolMemberInfo.poolId), substrateApi.api.query.staking.activeEra()]);
154
154
  const poolMetadata = _poolMetadata.toPrimitive();
155
155
  const nominations = _nominations.toJSON();
156
156
  const poolName = isHex(poolMetadata) ? hexToString(poolMetadata) : poolMetadata;
@@ -184,22 +184,20 @@ export default class NominationPoolHandler extends BasePoolHandler {
184
184
  const unstakings = [];
185
185
  let unstakingBalance = BN_ZERO;
186
186
  Object.entries(poolMemberInfo.unbondingEras).forEach(([unlockingEra, amount]) => {
187
- // Calculate the remaining time for current era ending
188
- const isClaimable = parseInt(unlockingEra) - parseInt(currentEra) < 0;
189
- const remainingEra = parseInt(unlockingEra) - parseInt(currentEra);
190
- const expectedBlockTime = _EXPECTED_BLOCK_TIME[this.chain];
191
- const eraLength = _deriveSessionProgress.eraLength.toNumber();
192
- const eraProgress = _deriveSessionProgress.eraProgress.toNumber();
193
- const remainingSlots = eraLength - eraProgress;
194
- const remainingHours = expectedBlockTime * remainingSlots / 60 / 60;
187
+ const activeEra = _activeEra.toPrimitive();
188
+ const era = parseInt(activeEra.index);
189
+ const startTimestampMs = parseInt(activeEra.start);
190
+ const remainingEra = parseInt(unlockingEra) - era;
195
191
  const eraTime = _STAKING_ERA_LENGTH_MAP[chainInfo.slug] || _STAKING_ERA_LENGTH_MAP.default; // in hours
196
- const waitingTime = remainingEra * eraTime + remainingHours;
192
+ const remaningTimestampMs = remainingEra * eraTime * 60 * 60 * 1000;
193
+ const targetTimestampMs = startTimestampMs + remaningTimestampMs;
194
+ const isClaimable = targetTimestampMs - Date.now() <= 0;
197
195
  unstakingBalance = unstakingBalance.add(new BN(amount));
198
196
  unstakings.push({
199
197
  chain: chainInfo.slug,
200
198
  status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
201
199
  claimable: amount.toString(),
202
- waitingTime: waitingTime
200
+ targetTimestampMs: targetTimestampMs
203
201
  });
204
202
  });
205
203
  const bnActiveStake = new BN(poolMemberInfo.points.toString());
@@ -19,6 +19,7 @@ export default abstract class BaseSpecialStakingPoolHandler extends BasePoolHand
19
19
  protected constructor(state: KoniState, chain: string);
20
20
  get metadataInfo(): Omit<SpecialYieldPoolMetadata, 'description'>;
21
21
  protected updateExchangeRate(rate: number): void;
22
+ /** Exchange rate before divine with decimals */
22
23
  protected getExchangeRate(): Promise<number>;
23
24
  get isPoolSupportAlternativeFee(): boolean;
24
25
  earlyValidate(request: RequestEarlyValidateYield): Promise<ResponseEarlyValidateYield>;
@@ -41,6 +41,8 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
41
41
  this.rate = rate;
42
42
  this.exchangeRatePromise.resolve(true);
43
43
  }
44
+
45
+ /** Exchange rate before divine with decimals */
44
46
  async getExchangeRate() {
45
47
  await this.exchangeRatePromise.promise;
46
48
  return this.rate;
@@ -18,12 +18,15 @@ export default class EarningService implements StoppableServiceInterface, Persis
18
18
  readonly yieldPositionListSubject: BehaviorSubject<YieldPositionInfo[]>;
19
19
  private dbService;
20
20
  private eventService;
21
+ private useOnlineCacheOnly;
21
22
  constructor(state: KoniState);
23
+ disableOnlineCacheOnly(): void;
22
24
  private initHandlers;
23
25
  startPromiseHandler: PromiseHandler<void>;
24
26
  stopPromiseHandler: PromiseHandler<void>;
25
27
  status: ServiceStatus;
26
28
  init(): Promise<void>;
29
+ private delayReloadTimeout;
27
30
  handleActions(): void;
28
31
  loadData(): Promise<void>;
29
32
  persistData(): Promise<void>;
@@ -36,7 +39,7 @@ export default class EarningService implements StoppableServiceInterface, Persis
36
39
  subscribeMinAmountPercent(): BehaviorSubject<Record<string, number>>;
37
40
  getMinAmountPercent(): Record<string, number>;
38
41
  getYieldPool(slug: string): Promise<YieldPoolInfo | undefined>;
39
- subscribePoolsInfo(callback: (rs: YieldPoolInfo) => void): Promise<VoidFunction>;
42
+ subscribePoolsInfo(onlineData: Record<string, YieldPoolInfo>, callback: (rs: YieldPoolInfo) => void): Promise<VoidFunction>;
40
43
  private getYieldPoolInfoFromDB;
41
44
  subscribeYieldPoolInfo(): BehaviorSubject<Record<string, YieldPoolInfo>>;
42
45
  getYieldPoolInfo(): Promise<YieldPoolInfo[]>;
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
- import { BasicTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { BasicTxErrorType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { CRON_REFRESH_CHAIN_STAKING_METADATA, CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL, CRON_REFRESH_STAKING_REWARD_FAST_INTERVAL } from '@subwallet/extension-base/constants';
7
7
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
8
8
  import { _isChainEnabled, _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
@@ -33,11 +33,15 @@ export default class EarningService {
33
33
  yieldPositionSubject = new BehaviorSubject({});
34
34
  yieldPositionListSubject = new BehaviorSubject([]); // virtual list of yieldPositionSubject with filter values
35
35
 
36
+ useOnlineCacheOnly = true;
36
37
  constructor(state) {
37
38
  this.state = state;
38
39
  this.dbService = state.dbService;
39
40
  this.eventService = state.eventService;
40
41
  }
42
+ disableOnlineCacheOnly() {
43
+ this.useOnlineCacheOnly = false;
44
+ }
41
45
  async initHandlers() {
42
46
  await this.eventService.waitChainReady;
43
47
  const chains = [];
@@ -125,6 +129,7 @@ export default class EarningService {
125
129
  }
126
130
  handleActions() {
127
131
  this.eventService.onLazy((events, eventTypes) => {
132
+ let delayReload = false;
128
133
  (async () => {
129
134
  const removedAddresses = [];
130
135
  const removeChains = [];
@@ -138,6 +143,13 @@ export default class EarningService {
138
143
  removeChains.push(event.data[0]);
139
144
  }
140
145
  }
146
+ if (event.type === 'transaction.done') {
147
+ const transactionData = event.data[0];
148
+ const notRequireReloadTypes = [ExtrinsicType.TRANSFER_BALANCE, ExtrinsicType.TRANSFER_TOKEN, ExtrinsicType.TRANSFER_XCM, ExtrinsicType.SEND_NFT, ExtrinsicType.CROWDLOAN];
149
+ if (notRequireReloadTypes.indexOf(transactionData.extrinsicType) === -1) {
150
+ delayReload = true;
151
+ }
152
+ }
141
153
  });
142
154
  if (removeChains.length || removedAddresses.length) {
143
155
  await this.removeYieldPositions(removeChains, removedAddresses);
@@ -146,8 +158,16 @@ export default class EarningService {
146
158
  // Account changed or chain changed (active or inactive)
147
159
  // Chain changed (active or inactive)
148
160
  // Todo: Optimize performance of chain active or inactive in the future
149
- if (eventTypes.includes('account.updateCurrent') || eventTypes.includes('account.remove') || eventTypes.includes('chain.updateState')) {
150
- await this.reloadEarning();
161
+ if (eventTypes.includes('account.updateCurrent') || eventTypes.includes('account.remove') || eventTypes.includes('chain.updateState') || delayReload) {
162
+ if (delayReload) {
163
+ this.delayReloadTimeout = setTimeout(() => {
164
+ this.reloadEarning().catch(console.error); // Timeout is removed inside reloadEarning > runUnsubscribePoolsPosition
165
+ }, 3000);
166
+ } else {
167
+ this.delayReloadTimeout && clearTimeout(this.delayReloadTimeout);
168
+ this.delayReloadTimeout = undefined;
169
+ await this.reloadEarning();
170
+ }
151
171
  }
152
172
  })().catch(console.error);
153
173
  });
@@ -241,20 +261,25 @@ export default class EarningService {
241
261
  }
242
262
  async getYieldPool(slug) {
243
263
  await this.eventService.waitEarningReady;
244
- return this.yieldPoolInfoSubject.getValue()[slug];
264
+ const poolInfoMap = this.yieldPoolInfoSubject.getValue();
265
+ return poolInfoMap[slug];
245
266
  }
246
- async subscribePoolsInfo(callback) {
267
+ async subscribePoolsInfo(onlineData, callback) {
247
268
  let cancel = false;
248
269
  await this.eventService.waitChainReady;
249
270
  const unsubList = [];
250
271
  for (const handler of Object.values(this.handlers)) {
251
- handler.subscribePoolInfo(callback).then(unsub => {
252
- if (!cancel) {
253
- unsubList.push(unsub);
254
- } else {
255
- unsub();
256
- }
257
- }).catch(console.error);
272
+ // Force subscribe onchain data
273
+ const forceSubscribe = handler.type === YieldPoolType.LIQUID_STAKING || handler.type === YieldPoolType.LENDING;
274
+ if (!this.useOnlineCacheOnly || forceSubscribe) {
275
+ handler.subscribePoolInfo(callback).then(unsub => {
276
+ if (!cancel) {
277
+ unsubList.push(unsub);
278
+ } else {
279
+ unsub();
280
+ }
281
+ }).catch(console.error);
282
+ }
258
283
  }
259
284
  return () => {
260
285
  cancel = true;
@@ -306,19 +331,20 @@ export default class EarningService {
306
331
  Object.values(onlineData).forEach(item => {
307
332
  this.updateYieldPoolInfo(item);
308
333
  });
334
+ return onlineData;
309
335
  }
310
336
  async runSubscribePoolsInfo() {
311
337
  await this.eventService.waitChainReady;
312
338
  this.runUnsubscribePoolsInfo();
313
339
 
314
340
  // Fetching online data
315
- this.fetchingPoolsInfoOnline().catch(console.error);
341
+ const onlineData = await this.fetchingPoolsInfoOnline();
316
342
  const interval = setInterval(() => {
317
343
  this.fetchingPoolsInfoOnline().catch(console.error);
318
344
  }, CRON_REFRESH_CHAIN_STAKING_METADATA);
319
345
 
320
346
  // Fetching from chains
321
- this.subscribePoolsInfo(data => {
347
+ this.subscribePoolsInfo(onlineData, data => {
322
348
  data.lastUpdated = Date.now();
323
349
  this.updateYieldPoolInfo(data);
324
350
  }).then(rs => {
@@ -460,6 +486,10 @@ export default class EarningService {
460
486
  (_this$yieldPositionUn = this.yieldPositionUnsub) === null || _this$yieldPositionUn === void 0 ? void 0 : _this$yieldPositionUn.call(this);
461
487
  removeLazy('persistYieldPositionInfo');
462
488
  this.yieldPositionPersistQueue = [];
489
+
490
+ // Remove delay reload
491
+ this.delayReloadTimeout && clearTimeout(this.delayReloadTimeout);
492
+ this.delayReloadTimeout = undefined;
463
493
  }
464
494
 
465
495
  /* Pools' position methods */
@@ -608,13 +638,16 @@ export default class EarningService {
608
638
  * @return {Promise<YieldPoolTarget[]>} List of pool's target
609
639
  * */
610
640
  async getPoolTargets(slug) {
611
- await this.eventService.waitChainReady;
641
+ let targets = [];
642
+ if (this.useOnlineCacheOnly) {
643
+ targets = await fetchStaticCache(`earning/targets/${slug}.json`, []);
644
+ }
612
645
  const handler = this.getPoolHandler(slug);
613
- if (handler) {
614
- return await handler.getPoolTargets();
615
- } else {
616
- return [];
646
+ if (!targets.length && handler) {
647
+ await this.eventService.waitChainReady;
648
+ targets = await handler.getPoolTargets();
617
649
  }
650
+ return targets;
618
651
  }
619
652
 
620
653
  /* Get pool's targets */
@@ -0,0 +1,12 @@
1
+ import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
2
+ import { EvmFeeInfo } from '@subwallet/extension-base/types';
3
+ export default class FeeService {
4
+ protected readonly state: KoniState;
5
+ private evmFeeSubject;
6
+ private useInfura;
7
+ constructor(state: KoniState);
8
+ changeMode(useInfura: boolean): void;
9
+ private updateFees;
10
+ private updateChainFee;
11
+ subscribeFees(callback: (data: Record<string, EvmFeeInfo>) => void): () => void;
12
+ }
@@ -0,0 +1,63 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
5
+ import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils';
6
+ import { BehaviorSubject } from 'rxjs';
7
+ export default class FeeService {
8
+ evmFeeSubject = new BehaviorSubject({});
9
+ constructor(state) {
10
+ this.state = state;
11
+ this.useInfura = true;
12
+ }
13
+ changeMode(useInfura) {
14
+ this.useInfura = useInfura;
15
+ }
16
+ async updateFees() {
17
+ await this.state.eventService.waitChainReady;
18
+ const activeNetworks = this.state.activeNetworks;
19
+ const chains = Object.values(activeNetworks).filter(chainInfo => _isChainEvmCompatible(chainInfo)).map(chainInfo => chainInfo.slug);
20
+ const promises = [];
21
+ for (const chain of chains) {
22
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises,no-async-promise-executor
23
+ const promise = new Promise(async resolve => {
24
+ const api = this.state.getEvmApi(chain);
25
+ const result = await calculateGasFeeParams(api, chain, this.useInfura);
26
+ this.updateChainFee(chain, result);
27
+ resolve();
28
+ });
29
+ promises.push(promise);
30
+ }
31
+ await Promise.all(promises);
32
+ }
33
+ updateChainFee(chain, info) {
34
+ const rs = Object.assign({}, this.evmFeeSubject.getValue());
35
+ rs[chain] = info;
36
+ this.evmFeeSubject.next(rs);
37
+ }
38
+ subscribeFees(callback) {
39
+ let cancel = false;
40
+
41
+ // eslint-disable-next-line prefer-const
42
+
43
+ const fetchData = () => {
44
+ this.updateFees().finally(() => {
45
+ if (!cancel) {
46
+ callback(this.evmFeeSubject.getValue());
47
+ }
48
+ });
49
+ };
50
+ fetchData();
51
+ const interval = setInterval(() => {
52
+ if (cancel) {
53
+ clearInterval(interval);
54
+ } else {
55
+ fetchData();
56
+ }
57
+ }, 30 * 1000);
58
+ return () => {
59
+ cancel = true;
60
+ clearInterval(interval);
61
+ };
62
+ }
63
+ }
@@ -0,0 +1,8 @@
1
+ import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types';
2
+ import { EvmFeeInfo, InfuraFeeInfo } from '@subwallet/extension-base/types';
3
+ export declare const parseInfuraFee: (info: InfuraFeeInfo) => EvmFeeInfo;
4
+ export declare const fetchInfuraFeeData: (chainId: number, infuraAuth?: string) => Promise<EvmFeeInfo | null>;
5
+ export declare const fetchSubWalletFeeData: (chainId: number, networkKey: string) => Promise<EvmFeeInfo | null>;
6
+ export declare const fetchOnlineFeeData: (chainId: number, networkKey: string, useInfura?: boolean) => Promise<EvmFeeInfo | null>;
7
+ export declare const recalculateGasPrice: (_price: string, chain: string) => string;
8
+ export declare const calculateGasFeeParams: (web3: _EvmApi, networkKey: string, useOnline?: boolean, useInfura?: boolean) => Promise<EvmFeeInfo>;