@subwallet/extension-base 1.1.32-beta.0 → 1.1.33-beta.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 (43) hide show
  1. package/background/KoniTypes.d.ts +1 -0
  2. package/background/KoniTypes.js +1 -0
  3. package/cjs/background/KoniTypes.js +1 -0
  4. package/cjs/koni/api/staking/bonding/amplitude.js +97 -62
  5. package/cjs/koni/api/staking/paraChain.js +31 -5
  6. package/cjs/koni/api/xcm/xTokens.js +1 -1
  7. package/cjs/koni/background/handlers/Tabs.js +19 -2
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/chain-service/constants.js +3 -2
  10. package/cjs/services/earning-service/constants/chains.js +3 -2
  11. package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +2 -2
  12. package/cjs/services/earning-service/handlers/native-staking/amplitude.js +110 -65
  13. package/cjs/services/earning-service/service.js +32 -12
  14. package/cjs/services/history-service/index.js +12 -8
  15. package/cjs/services/transaction-service/index.js +62 -13
  16. package/cjs/utils/fetchEvmChainInfo.js +20 -0
  17. package/cjs/utils/index.js +24 -0
  18. package/koni/api/staking/bonding/amplitude.d.ts +1 -1
  19. package/koni/api/staking/bonding/amplitude.js +97 -62
  20. package/koni/api/staking/bonding/utils.d.ts +4 -0
  21. package/koni/api/staking/paraChain.js +31 -5
  22. package/koni/api/xcm/xTokens.js +1 -1
  23. package/koni/background/handlers/Tabs.js +20 -3
  24. package/package.json +11 -6
  25. package/packageInfo.js +1 -1
  26. package/services/chain-service/constants.js +3 -2
  27. package/services/earning-service/constants/chains.d.ts +1 -0
  28. package/services/earning-service/constants/chains.js +3 -2
  29. package/services/earning-service/handlers/liquid-staking/bifrost.js +2 -2
  30. package/services/earning-service/handlers/native-staking/amplitude.d.ts +1 -1
  31. package/services/earning-service/handlers/native-staking/amplitude.js +110 -65
  32. package/services/earning-service/service.d.ts +2 -1
  33. package/services/earning-service/service.js +33 -13
  34. package/services/event-service/types.d.ts +1 -0
  35. package/services/history-service/index.js +12 -8
  36. package/services/transaction-service/index.d.ts +5 -0
  37. package/services/transaction-service/index.js +49 -1
  38. package/services/transaction-service/types.d.ts +1 -0
  39. package/types/yield/info/chain/info.d.ts +1 -0
  40. package/utils/fetchEvmChainInfo.d.ts +17 -0
  41. package/utils/fetchEvmChainInfo.js +14 -0
  42. package/utils/index.d.ts +2 -0
  43. package/utils/index.js +3 -1
@@ -13,7 +13,7 @@ import { PHISHING_PAGE_REDIRECT } from '@subwallet/extension-base/defaults';
13
13
  import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chain-service/handler/types';
14
14
  import { _generateCustomProviderKey } from '@subwallet/extension-base/services/chain-service/utils';
15
15
  import { DEFAULT_CHAIN_PATROL_ENABLE } from '@subwallet/extension-base/services/setting-service/constants';
16
- import { canDerive, stripUrl } from '@subwallet/extension-base/utils';
16
+ import { canDerive, getEVMChainInfo, stripUrl } from '@subwallet/extension-base/utils';
17
17
  import keyring from '@subwallet/ui-keyring';
18
18
  import { t } from 'i18next';
19
19
  import Web3 from 'web3';
@@ -382,15 +382,32 @@ export default class KoniTabs {
382
382
  }) {
383
383
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
384
384
  const chainId = params[0].chainId;
385
+ const chainIdDec = parseInt(chainId, 16);
385
386
  const evmState = await this.getEvmState(url);
386
387
  if (evmState.chainId === chainId) {
387
388
  return null;
388
389
  }
389
- const [networkKey] = this.#koniState.findNetworkKeyByChainId(parseInt(chainId, 16));
390
+ const [networkKey] = this.#koniState.findNetworkKeyByChainId(chainIdDec);
390
391
  if (networkKey) {
391
392
  await this.#koniState.switchEvmNetworkByUrl(stripUrl(url), networkKey);
392
393
  } else {
393
- throw new EvmProviderError(EvmProviderErrorType.INVALID_PARAMS, 'This network is currently not supported');
394
+ const onlineData = await getEVMChainInfo(chainIdDec);
395
+ if (onlineData) {
396
+ const chainData = {
397
+ chainId: chainId,
398
+ rpcUrls: onlineData.rpc.filter(url => url.startsWith('https://')),
399
+ chainName: onlineData.name,
400
+ blockExplorerUrls: onlineData.explorers.map(explorer => explorer.url),
401
+ nativeCurrency: onlineData.nativeCurrency,
402
+ requestId: id
403
+ };
404
+ await this.addEvmChain(id, url, {
405
+ method: 'wallet_addEthereumChain',
406
+ params: [chainData]
407
+ });
408
+ } else {
409
+ throw new EvmProviderError(EvmProviderErrorType.INVALID_PARAMS, 'This network is currently not supported');
410
+ }
394
411
  }
395
412
  return null;
396
413
  }
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.1.32-beta.0",
20
+ "version": "1.1.33-beta.0",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -1620,6 +1620,11 @@
1620
1620
  "require": "./cjs/utils/eth/parseTransaction/base.js",
1621
1621
  "default": "./utils/eth/parseTransaction/base.js"
1622
1622
  },
1623
+ "./utils/fetchEvmChainInfo": {
1624
+ "types": "./utils/fetchEvmChainInfo.d.ts",
1625
+ "require": "./cjs/utils/fetchEvmChainInfo.js",
1626
+ "default": "./utils/fetchEvmChainInfo.js"
1627
+ },
1623
1628
  "./utils/fetchStaticData": {
1624
1629
  "types": "./utils/fetchStaticData.d.ts",
1625
1630
  "require": "./cjs/utils/fetchStaticData.js",
@@ -1706,11 +1711,11 @@
1706
1711
  "@reduxjs/toolkit": "^1.9.1",
1707
1712
  "@sora-substrate/type-definitions": "^1.17.7",
1708
1713
  "@substrate/connect": "^0.7.26",
1709
- "@subwallet/chain-list": "0.2.38",
1710
- "@subwallet/extension-base": "^1.1.32-0",
1711
- "@subwallet/extension-chains": "^1.1.32-0",
1712
- "@subwallet/extension-dapp": "^1.1.32-0",
1713
- "@subwallet/extension-inject": "^1.1.32-0",
1714
+ "@subwallet/chain-list": "0.2.39",
1715
+ "@subwallet/extension-base": "^1.1.33-0",
1716
+ "@subwallet/extension-chains": "^1.1.33-0",
1717
+ "@subwallet/extension-dapp": "^1.1.33-0",
1718
+ "@subwallet/extension-inject": "^1.1.33-0",
1714
1719
  "@subwallet/keyring": "^0.1.1",
1715
1720
  "@subwallet/ui-keyring": "^0.1.1",
1716
1721
  "@walletconnect/sign-client": "^2.8.4",
package/packageInfo.js CHANGED
@@ -7,5 +7,5 @@ export const packageInfo = {
7
7
  name: '@subwallet/extension-base',
8
8
  path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
9
9
  type: 'esm',
10
- version: '1.1.32-0'
10
+ version: '1.1.33-0'
11
11
  };
@@ -29,7 +29,7 @@ export const _BALANCE_CHAIN_GROUP = {
29
29
  genshiro: ['genshiro_testnet', 'genshiro'],
30
30
  equilibrium_parachain: ['equilibrium_parachain'],
31
31
  bifrost: ['bifrost', 'acala', 'karura', 'acala_testnet', 'pioneer', 'bitcountry', 'bifrost_dot', 'hydradx_main', 'pendulum', 'amplitude'],
32
- statemine: ['statemine', 'astar', 'shiden', 'statemint', 'moonbeam', 'moonbase', 'moonriver', 'crabParachain', 'darwinia2', 'parallel', 'calamari'],
32
+ statemine: ['statemine', 'astar', 'shiden', 'statemint', 'moonbeam', 'moonbase', 'moonriver', 'crabParachain', 'darwinia2', 'parallel', 'calamari', 'manta_network'],
33
33
  kusama: ['kusama', 'kintsugi', 'kintsugi_test', 'interlay', 'acala', 'statemint', 'karura', 'bifrost'],
34
34
  // perhaps there are some runtime updates
35
35
  centrifuge: ['centrifuge']
@@ -84,7 +84,8 @@ export const _STAKING_ERA_LENGTH_MAP = {
84
84
  creditcoin: 24,
85
85
  vara_network: 12,
86
86
  goldberg_testnet: 24,
87
- manta_network: 6
87
+ manta_network: 6,
88
+ krest_network: 4
88
89
  };
89
90
  export const _EXPECTED_BLOCK_TIME = {
90
91
  // in seconds
@@ -10,5 +10,6 @@ export declare const _STAKING_CHAIN_GROUP: {
10
10
  ternoa: string[];
11
11
  liquidStaking: string[];
12
12
  lending: string[];
13
+ krest_network: string[];
13
14
  };
14
15
  export declare const ST_LIQUID_TOKEN_ABI: Record<string, any>;
@@ -5,7 +5,7 @@ export const _STAKING_CHAIN_GROUP = {
5
5
  relay: ['polkadot', 'kusama', 'aleph', 'polkadex', 'ternoa', 'ternoa_alphanet', 'alephTest', 'polkadexTest', 'westend', 'kate', 'edgeware', 'creditcoin', 'vara_network', 'goldberg_testnet'],
6
6
  para: ['moonbeam', 'moonriver', 'moonbase', 'turing', 'turingStaging', 'bifrost', 'bifrost_testnet', 'calamari_test', 'calamari', 'manta_network'],
7
7
  astar: ['astar', 'shiden', 'shibuya'],
8
- amplitude: ['amplitude', 'amplitude_test', 'kilt', 'kilt_peregrine', 'pendulum'],
8
+ amplitude: ['amplitude', 'amplitude_test', 'kilt', 'kilt_peregrine', 'pendulum', 'krest_network'],
9
9
  // amplitude and kilt only share some common logic
10
10
  kilt: ['kilt', 'kilt_peregrine'],
11
11
  nominationPool: ['polkadot', 'kusama', 'westend', 'alephTest', 'aleph', 'kate', 'vara_network', 'goldberg_testnet'],
@@ -14,7 +14,8 @@ export const _STAKING_CHAIN_GROUP = {
14
14
  // A0 has distinct tokenomics
15
15
  ternoa: ['ternoa', 'ternoa_alphanet'],
16
16
  liquidStaking: ['bifrost_dot', 'acala', 'parallel', 'moonbeam'],
17
- lending: ['interlay']
17
+ lending: ['interlay'],
18
+ krest_network: ['krest_network']
18
19
  };
19
20
 
20
21
  // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
@@ -237,7 +237,7 @@ export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPo
237
237
  const inputTokenInfo = this.state.getAssetBySlug(inputTokenSlug);
238
238
  const defaultFeeTokenSlug = this.feeAssets[0];
239
239
  if (new BN(params.amount).gt(BN_ZERO)) {
240
- const _mintFeeInfo = await poolOriginSubstrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), params.amount, null).paymentInfo(fakeAddress);
240
+ const _mintFeeInfo = await poolOriginSubstrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), params.amount, undefined, undefined).paymentInfo(fakeAddress);
241
241
  const mintFeeInfo = _mintFeeInfo.toPrimitive();
242
242
  return {
243
243
  amount: mintFeeInfo.partialFee.toString(),
@@ -254,7 +254,7 @@ export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPo
254
254
  const substrateApi = await this.substrateApi.isReady;
255
255
  const inputTokenSlug = this.inputAsset;
256
256
  const inputTokenInfo = this.state.getAssetBySlug(inputTokenSlug);
257
- const extrinsic = substrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), data.amount, undefined);
257
+ const extrinsic = substrateApi.api.tx.vtokenMinting.mint(_getTokenOnChainInfo(inputTokenInfo), data.amount, undefined, undefined);
258
258
  return {
259
259
  txChain: this.chain,
260
260
  extrinsicType: ExtrinsicType.MINT_VDOT,
@@ -6,7 +6,7 @@ import { SubmittableExtrinsic } from '@polkadot/api/types';
6
6
  import BaseParaNativeStakingPoolHandler from './base-para';
7
7
  export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeStakingPoolHandler {
8
8
  subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
9
- parseNominatorMetadata(chainInfo: _ChainInfo, address: string, substrateApi: _SubstrateApi, delegatorState: ParachainStakingStakeOption, unstakingInfo: Record<string, number>): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
9
+ parseNominatorMetadata(chainInfo: _ChainInfo, address: string, substrateApi: _SubstrateApi, delegatorState: ParachainStakingStakeOption[], unstakingInfo: Record<string, number>): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
10
10
  subscribePoolPosition(useAddresses: string[], resultCallback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
11
11
  getPoolReward(useAddresses: string[], callBack: (rs: EarningRewardItem) => void): Promise<VoidFunction>;
12
12
  getPoolTargets(): Promise<ValidatorInfo[]>;
@@ -48,6 +48,7 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
48
48
  const minDelegatorStake = substrateApi.api.consts.parachainStaking.minDelegatorStake.toString();
49
49
  const unstakingDelay = substrateApi.api.consts.parachainStaking.stakeDuration.toString(); // in blocks
50
50
  const _blockPerRound = substrateApi.api.consts.parachainStaking.defaultBlocksPerRound.toString();
51
+ const maxUnstakeRequests = substrateApi.api.consts.parachainStaking.maxUnstakeRequests.toPrimitive();
51
52
  const blockPerRound = parseFloat(_blockPerRound);
52
53
  const roundTime = _STAKING_ERA_LENGTH_MAP[this.chain] || _STAKING_ERA_LENGTH_MAP.default; // in hours
53
54
  const blockDuration = roundTime / blockPerRound; // in hours
@@ -68,7 +69,7 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
68
69
  slug: this.nativeToken.slug
69
70
  }],
70
71
  maxCandidatePerFarmer: parseInt(maxDelegations),
71
- maxWithdrawalRequestPerFarmer: 1,
72
+ maxWithdrawalRequestPerFarmer: maxUnstakeRequests,
72
73
  // by default
73
74
  earningThreshold: {
74
75
  join: minDelegatorStake,
@@ -102,48 +103,54 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
102
103
  const nominationList = [];
103
104
  const unstakingList = [];
104
105
  const minDelegatorStake = substrateApi.api.consts.parachainStaking.minDelegatorStake.toString();
106
+ const hasUnstakingInfo = unstakingInfo && Object.values(unstakingInfo).length > 0;
105
107
  let activeStake = '0';
106
108
  let unstakingBalance = '0';
107
109
  if (delegatorState) {
108
110
  // delegatorState can be null while unstaking all
109
- const [identity] = await parseIdentity(substrateApi, delegatorState.owner);
110
- activeStake = delegatorState.amount.toString();
111
- const bnActiveStake = new BN(activeStake);
112
- let delegationStatus = EarningStatus.NOT_EARNING;
113
- if (bnActiveStake.gt(BN_ZERO) && bnActiveStake.gte(new BN(minDelegatorStake))) {
114
- delegationStatus = EarningStatus.EARNING_REWARD;
111
+ const identityPromises = delegatorState.map(delegate => parseIdentity(substrateApi, delegate.owner));
112
+ const identities = await Promise.all(identityPromises);
113
+ for (let i = 0; i < delegatorState.length; i++) {
114
+ const delegate = delegatorState[i];
115
+ const [identity] = identities[i];
116
+ activeStake = delegate.amount.toString();
117
+ const bnActiveStake = new BN(activeStake);
118
+ let delegationStatus = EarningStatus.NOT_EARNING;
119
+ if (bnActiveStake.gt(BN_ZERO) && bnActiveStake.gte(new BN(minDelegatorStake))) {
120
+ delegationStatus = EarningStatus.EARNING_REWARD;
121
+ }
122
+ nominationList.push({
123
+ status: delegationStatus,
124
+ chain: chainInfo.slug,
125
+ validatorAddress: delegate.owner,
126
+ activeStake: delegate.amount.toString(),
127
+ validatorMinStake: '0',
128
+ hasUnstaking: hasUnstakingInfo,
129
+ validatorIdentity: identity
130
+ });
115
131
  }
116
- nominationList.push({
117
- status: delegationStatus,
118
- chain: chainInfo.slug,
119
- validatorAddress: delegatorState.owner,
120
- activeStake: delegatorState.amount.toString(),
121
- validatorMinStake: '0',
122
- hasUnstaking: !!unstakingInfo && Object.values(unstakingInfo).length > 0,
123
- validatorIdentity: identity
124
- });
125
- }
126
- if (unstakingInfo && Object.values(unstakingInfo).length > 0) {
127
- const _currentBlockInfo = await substrateApi.api.rpc.chain.getHeader();
128
- const currentBlockInfo = _currentBlockInfo.toPrimitive();
129
- const currentBlockNumber = currentBlockInfo.number;
130
- const _blockPerRound = substrateApi.api.consts.parachainStaking.defaultBlocksPerRound.toString();
131
- const blockPerRound = parseFloat(_blockPerRound);
132
- const nearestUnstakingBlock = Object.keys(unstakingInfo)[0];
133
- const nearestUnstakingAmount = Object.values(unstakingInfo)[0];
134
- const blockDuration = (_STAKING_ERA_LENGTH_MAP[chainInfo.slug] || _STAKING_ERA_LENGTH_MAP.default) / blockPerRound; // in hours
132
+ if (hasUnstakingInfo) {
133
+ const _currentBlockInfo = await substrateApi.api.rpc.chain.getHeader();
134
+ const currentBlockInfo = _currentBlockInfo.toPrimitive();
135
+ const currentBlockNumber = currentBlockInfo.number;
136
+ const _blockPerRound = substrateApi.api.consts.parachainStaking.defaultBlocksPerRound.toString();
137
+ const blockPerRound = parseFloat(_blockPerRound);
138
+ for (const [unstakingBlock, unstakingAmount] of Object.entries(unstakingInfo)) {
139
+ const blockDuration = (_STAKING_ERA_LENGTH_MAP[chainInfo.slug] || _STAKING_ERA_LENGTH_MAP.default) / blockPerRound; // in hours
135
140
 
136
- const isClaimable = parseInt(nearestUnstakingBlock) - currentBlockNumber < 0;
137
- const remainingBlock = parseInt(nearestUnstakingBlock) - currentBlockNumber;
138
- const waitingTime = remainingBlock * blockDuration;
139
- unstakingBalance = nearestUnstakingAmount.toString();
140
- unstakingList.push({
141
- chain: chainInfo.slug,
142
- status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
143
- claimable: nearestUnstakingAmount.toString(),
144
- waitingTime,
145
- validatorAddress: (delegatorState === null || delegatorState === void 0 ? void 0 : delegatorState.owner) || undefined
146
- });
141
+ const isClaimable = parseInt(unstakingBlock) - currentBlockNumber < 0;
142
+ const remainingBlock = parseInt(unstakingBlock) - currentBlockNumber;
143
+ const waitingTime = remainingBlock * blockDuration;
144
+ unstakingBalance = unstakingAmount.toString();
145
+ unstakingList.push({
146
+ chain: chainInfo.slug,
147
+ status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
148
+ claimable: unstakingAmount.toString(),
149
+ waitingTime,
150
+ validatorAddress: undefined
151
+ });
152
+ }
153
+ }
147
154
  }
148
155
  const totalBalance = new BN(activeStake).add(new BN(unstakingBalance));
149
156
  const stakingStatus = getEarningStatusByNominations(new BN(activeStake), nominationList);
@@ -172,8 +179,20 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
172
179
  const _unstakingStates = await substrateApi.api.query.parachainStaking.unstaking.multi(useAddresses);
173
180
  await Promise.all(ledgers.map(async (_delegatorState, i) => {
174
181
  const owner = reformatAddress(useAddresses[i], 42);
175
- const delegatorState = _delegatorState.toPrimitive();
182
+ let delegatorState = [];
176
183
  const unstakingInfo = _unstakingStates[i].toPrimitive();
184
+ if (_STAKING_CHAIN_GROUP.krest_network.includes(this.chain)) {
185
+ const krestDelegatorState = _delegatorState.toPrimitive();
186
+ const delegates = krestDelegatorState === null || krestDelegatorState === void 0 ? void 0 : krestDelegatorState.delegations;
187
+ if (delegates) {
188
+ delegatorState = delegatorState.concat(delegates);
189
+ }
190
+ } else {
191
+ const delegate = _delegatorState.toPrimitive();
192
+ if (delegate) {
193
+ delegatorState.push(delegate);
194
+ }
195
+ }
177
196
  if (!delegatorState && !unstakingInfo) {
178
197
  resultCallback({
179
198
  ...defaultInfo,
@@ -214,7 +233,7 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
214
233
  let cancel = false;
215
234
  const substrateApi = this.substrateApi;
216
235
  await substrateApi.isReady;
217
- if (!_STAKING_CHAIN_GROUP.kilt.includes(this.chain)) {
236
+ if (!_STAKING_CHAIN_GROUP.kilt.includes(this.chain) && !_STAKING_CHAIN_GROUP.krest_network.includes(this.chain)) {
218
237
  await Promise.all(useAddresses.map(async address => {
219
238
  const _unclaimedReward = await substrateApi.api.query.parachainStaking.rewards(address);
220
239
  if (cancel) {
@@ -240,33 +259,59 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
240
259
 
241
260
  async getPoolTargets() {
242
261
  const chainApi = await this.substrateApi.isReady;
243
- const [_allCollators, _inflationConfig] = await Promise.all([chainApi.api.query.parachainStaking.candidatePool.entries(), chainApi.api.query.parachainStaking.inflationConfig()]);
244
- const maxDelegatorsPerCollator = chainApi.api.consts.parachainStaking.maxDelegatorsPerCollator.toString();
245
- const inflationConfig = _inflationConfig.toHuman();
246
- const rawDelegatorReturn = inflationConfig.delegator.rewardRate.annual;
247
- const delegatorReturn = parseFloat(rawDelegatorReturn.split('%')[0]);
248
- const allCollators = [];
249
- for (const _collator of _allCollators) {
250
- const collatorInfo = _collator[1].toPrimitive();
251
- const bnTotalStake = new BN(collatorInfo.total);
252
- const bnOwnStake = new BN(collatorInfo.stake);
253
- const bnOtherStake = bnTotalStake.sub(bnOwnStake);
254
- allCollators.push({
255
- address: collatorInfo.id,
256
- totalStake: bnTotalStake.toString(),
257
- ownStake: bnOwnStake.toString(),
258
- otherStake: bnOtherStake.toString(),
259
- nominatorCount: collatorInfo.delegators.length,
260
- commission: 0,
261
- expectedReturn: delegatorReturn,
262
- blocked: false,
263
- isVerified: false,
264
- minBond: '0',
265
- chain: this.chain,
266
- isCrowded: collatorInfo.delegators.length >= parseInt(maxDelegatorsPerCollator)
267
- });
262
+ if (_STAKING_CHAIN_GROUP.krest_network.includes(this.chain)) {
263
+ const _allCollators = await chainApi.api.query.parachainStaking.candidatePool.entries();
264
+ const maxDelegatorsPerCollator = chainApi.api.consts.parachainStaking.maxDelegatorsPerCollator.toString();
265
+ const allCollators = [];
266
+ for (const _collator of _allCollators) {
267
+ const collatorInfo = _collator[1].toPrimitive();
268
+ const bnTotalStake = new BN(collatorInfo.total);
269
+ const bnOwnStake = new BN(collatorInfo.stake);
270
+ const bnOtherStake = bnTotalStake.sub(bnOwnStake);
271
+ allCollators.push({
272
+ address: collatorInfo.id,
273
+ totalStake: bnTotalStake.toString(),
274
+ ownStake: bnOwnStake.toString(),
275
+ otherStake: bnOtherStake.toString(),
276
+ nominatorCount: collatorInfo.delegators.length,
277
+ commission: 0,
278
+ blocked: false,
279
+ isVerified: false,
280
+ minBond: '0',
281
+ chain: this.chain,
282
+ isCrowded: collatorInfo.delegators.length >= parseInt(maxDelegatorsPerCollator)
283
+ });
284
+ }
285
+ return allCollators;
286
+ } else {
287
+ const [_allCollators, _inflationConfig] = await Promise.all([chainApi.api.query.parachainStaking.candidatePool.entries(), chainApi.api.query.parachainStaking.inflationConfig()]);
288
+ const maxDelegatorsPerCollator = chainApi.api.consts.parachainStaking.maxDelegatorsPerCollator.toString();
289
+ const inflationConfig = _inflationConfig.toHuman();
290
+ const rawDelegatorReturn = inflationConfig.delegator.rewardRate.annual;
291
+ const delegatorReturn = parseFloat(rawDelegatorReturn.split('%')[0]);
292
+ const allCollators = [];
293
+ for (const _collator of _allCollators) {
294
+ const collatorInfo = _collator[1].toPrimitive();
295
+ const bnTotalStake = new BN(collatorInfo.total);
296
+ const bnOwnStake = new BN(collatorInfo.stake);
297
+ const bnOtherStake = bnTotalStake.sub(bnOwnStake);
298
+ allCollators.push({
299
+ address: collatorInfo.id,
300
+ totalStake: bnTotalStake.toString(),
301
+ ownStake: bnOwnStake.toString(),
302
+ otherStake: bnOtherStake.toString(),
303
+ nominatorCount: collatorInfo.delegators.length,
304
+ commission: 0,
305
+ expectedReturn: delegatorReturn,
306
+ blocked: false,
307
+ isVerified: false,
308
+ minBond: '0',
309
+ chain: this.chain,
310
+ isCrowded: collatorInfo.delegators.length >= parseInt(maxDelegatorsPerCollator)
311
+ });
312
+ }
313
+ return allCollators;
268
314
  }
269
- return allCollators;
270
315
  }
271
316
 
272
317
  /* Get pool targets */
@@ -37,11 +37,12 @@ export default class EarningService implements StoppableServiceInterface, Persis
37
37
  getMinAmountPercent(): Record<string, number>;
38
38
  getYieldPool(slug: string): Promise<YieldPoolInfo | undefined>;
39
39
  subscribePoolsInfo(callback: (rs: YieldPoolInfo) => void): Promise<VoidFunction>;
40
- private getYieldPoolInfoFromDBAndOnline;
40
+ private getYieldPoolInfoFromDB;
41
41
  subscribeYieldPoolInfo(): BehaviorSubject<Record<string, YieldPoolInfo>>;
42
42
  getYieldPoolInfo(): Promise<YieldPoolInfo[]>;
43
43
  private yieldPoolPersistQueue;
44
44
  updateYieldPoolInfo(data: YieldPoolInfo): void;
45
+ private fetchingPoolsInfoOnline;
45
46
  private yieldPoolsInfoUnsub;
46
47
  runSubscribePoolsInfo(): Promise<void>;
47
48
  runUnsubscribePoolsInfo(): void;
@@ -3,7 +3,7 @@
3
3
 
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { BasicTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
- import { CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL, CRON_REFRESH_STAKING_REWARD_FAST_INTERVAL } from '@subwallet/extension-base/constants';
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 { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
9
9
  import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning-service/constants';
@@ -148,7 +148,7 @@ export default class EarningService {
148
148
  });
149
149
  }
150
150
  async loadData() {
151
- await this.getYieldPoolInfoFromDBAndOnline();
151
+ await this.getYieldPoolInfoFromDB();
152
152
  await this.getYieldPositionFromDB();
153
153
  }
154
154
  persistData() {
@@ -258,18 +258,12 @@ export default class EarningService {
258
258
  });
259
259
  };
260
260
  }
261
- async getYieldPoolInfoFromDBAndOnline() {
261
+ async getYieldPoolInfoFromDB() {
262
262
  // Get online pool data
263
- const yieldPoolInfo = await Promise.race([fetchPoolsData(), new Promise(resolve => {
264
- setTimeout(() => {
265
- resolve({});
266
- }, 1200);
267
- })]);
263
+ const yieldPoolInfo = {};
268
264
  const existedYieldPoolInfo = await this.dbService.getYieldPools();
269
265
  existedYieldPoolInfo.forEach(info => {
270
- if (!yieldPoolInfo[info.slug]) {
271
- yieldPoolInfo[info.slug] = info;
272
- }
266
+ yieldPoolInfo[info.slug] = info;
273
267
  });
274
268
  this.yieldPoolInfoSubject.next(yieldPoolInfo);
275
269
  }
@@ -290,7 +284,11 @@ export default class EarningService {
290
284
 
291
285
  // Update yield pool info
292
286
  queue.forEach(item => {
293
- yieldPoolInfo[item.slug] = item;
287
+ const existed = yieldPoolInfo[item.slug];
288
+ if (item.statistic && (!(existed !== null && existed !== void 0 && existed.lastUpdated) || existed.lastUpdated < ((item === null || item === void 0 ? void 0 : item.lastUpdated) || 0))) {
289
+ // Only update item has statistic information
290
+ yieldPoolInfo[item.slug] = item;
291
+ }
294
292
  });
295
293
  this.yieldPoolInfoSubject.next(yieldPoolInfo);
296
294
 
@@ -298,13 +296,35 @@ export default class EarningService {
298
296
  this.dbService.updateYieldPoolsStore(queue).catch(console.warn);
299
297
  }, 300, 900);
300
298
  }
299
+ async fetchingPoolsInfoOnline() {
300
+ const onlineData = await Promise.race([fetchPoolsData(), new Promise(resolve => {
301
+ setTimeout(() => {
302
+ resolve({});
303
+ }, 1800);
304
+ })]);
305
+ Object.values(onlineData).forEach(item => {
306
+ this.updateYieldPoolInfo(item);
307
+ });
308
+ }
301
309
  async runSubscribePoolsInfo() {
302
310
  await this.eventService.waitChainReady;
303
311
  this.runUnsubscribePoolsInfo();
312
+
313
+ // Fetching online data
314
+ await this.fetchingPoolsInfoOnline();
315
+ const interval = setInterval(() => {
316
+ this.fetchingPoolsInfoOnline().catch(console.error);
317
+ }, CRON_REFRESH_CHAIN_STAKING_METADATA);
318
+
319
+ // Fetching from chains
304
320
  this.subscribePoolsInfo(data => {
321
+ data.lastUpdated = Date.now();
305
322
  this.updateYieldPoolInfo(data);
306
323
  }).then(rs => {
307
- this.yieldPoolsInfoUnsub = rs;
324
+ this.yieldPoolsInfoUnsub = () => {
325
+ rs();
326
+ clearInterval(interval);
327
+ };
308
328
  }).catch(console.error);
309
329
  }
310
330
  runUnsubscribePoolsInfo() {
@@ -26,6 +26,7 @@ export interface EventRegistry {
26
26
  'asset.updateState': [string];
27
27
  'transaction.done': [SWTransaction];
28
28
  'transaction.failed': [SWTransaction | undefined];
29
+ 'transaction.timeout': [SWTransaction | undefined];
29
30
  'transaction.submitStaking': [string];
30
31
  'transaction.transferNft': [SWTransaction | undefined];
31
32
  'mantaPay.initSync': [string | undefined];
@@ -166,14 +166,18 @@ export class HistoryService {
166
166
 
167
167
  // Insert history with check override origin 'app'
168
168
  async addHistoryItems(historyItems) {
169
- // Prevent override record with original is 'app'
170
- const appRecords = this.historySubject.value.filter(item => item.origin === 'app');
171
- const excludeKeys = appRecords.map(item => {
172
- return `${item.chain}-${item.extrinsicHash}`;
173
- });
174
- const updateRecords = historyItems.filter(item => {
175
- const key = `${item.chain}-${item.extrinsicHash}`;
176
- return item.origin === 'app' || !excludeKeys.includes(key);
169
+ const updateRecords = [];
170
+ const appItems = this.historySubject.value.filter(i => i.origin === 'app');
171
+ historyItems.forEach(item => {
172
+ const needUpdateItem = appItems.find(item_ => item_.extrinsicHash === item.extrinsicHash && item.chain === item_.chain && item.address === item_.address);
173
+ if (needUpdateItem) {
174
+ updateRecords.push({
175
+ ...needUpdateItem,
176
+ status: item.status
177
+ });
178
+ return;
179
+ }
180
+ updateRecords.push(item);
177
181
  });
178
182
  await this.dbService.upsertHistory(updateRecords);
179
183
  this.historySubject.next(await this.dbService.getHistories());
@@ -7,6 +7,10 @@ import { HexString } from '@polkadot/util/types';
7
7
  export default class TransactionService {
8
8
  private readonly state;
9
9
  private readonly transactionSubject;
10
+ private readonly eventService;
11
+ private readonly historyService;
12
+ private readonly notificationService;
13
+ private readonly chainService;
10
14
  private readonly watchTransactionSubscribes;
11
15
  private get transactions();
12
16
  constructor(state: KoniState);
@@ -31,6 +35,7 @@ export default class TransactionService {
31
35
  private handlePostProcessing;
32
36
  private onSuccess;
33
37
  private onFailed;
38
+ private onTimeOut;
34
39
  generateHashPayload(chain: string, transaction: TransactionConfig): HexString;
35
40
  private signAndSendEvmTransaction;
36
41
  private signAndSendSubstrateTransaction;
@@ -35,6 +35,10 @@ export default class TransactionService {
35
35
  }
36
36
  constructor(state) {
37
37
  this.state = state;
38
+ this.eventService = state.eventService;
39
+ this.historyService = state.historyService;
40
+ this.notificationService = state.notificationService;
41
+ this.chainService = state.chainService;
38
42
  }
39
43
  get allTransactions() {
40
44
  return Object.values(this.transactions);
@@ -290,6 +294,12 @@ export default class TransactionService {
290
294
  errors: [...data.errors, new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]
291
295
  });
292
296
  });
297
+ emitter.on('timeout', data => {
298
+ this.onTimeOut({
299
+ ...data,
300
+ errors: [...data.errors, new TransactionError(BasicTxErrorType.TIMEOUT)]
301
+ });
302
+ });
293
303
 
294
304
  // Todo: handle any event with transaction.eventsHandler
295
305
 
@@ -788,6 +798,44 @@ export default class TransactionService {
788
798
  }
789
799
  this.state.eventService.emit('transaction.failed', transaction);
790
800
  }
801
+ onTimeOut({
802
+ blockHash,
803
+ blockNumber,
804
+ errors,
805
+ extrinsicHash,
806
+ id
807
+ }) {
808
+ const transaction = this.getTransaction(id);
809
+ const nextStatus = ExtrinsicStatus.TIMEOUT;
810
+ if (transaction) {
811
+ this.updateTransaction(id, {
812
+ status: nextStatus,
813
+ errors,
814
+ extrinsicHash
815
+ });
816
+ this.historyService.updateHistoryByExtrinsicHash(transaction.extrinsicHash, {
817
+ extrinsicHash: extrinsicHash || transaction.extrinsicHash,
818
+ status: nextStatus,
819
+ blockNumber: blockNumber || 0,
820
+ blockHash: blockHash || ''
821
+ }).catch(console.error);
822
+ const info = isHex(transaction === null || transaction === void 0 ? void 0 : transaction.extrinsicHash) ? transaction === null || transaction === void 0 ? void 0 : transaction.extrinsicHash : getBaseTransactionInfo(transaction, this.chainService.getChainInfoMap());
823
+ this.notificationService.notify({
824
+ type: NotificationType.ERROR,
825
+ title: t('Transaction timed out'),
826
+ message: t('Transaction {{info}} timed out', {
827
+ replace: {
828
+ info
829
+ }
830
+ }),
831
+ action: {
832
+ url: this.getTransactionLink(id)
833
+ },
834
+ notifyViaBrowser: true
835
+ });
836
+ }
837
+ this.eventService.emit('transaction.timeout', transaction);
838
+ }
791
839
  generateHashPayload(chain, transaction) {
792
840
  var _transaction$nonce;
793
841
  const chainInfo = this.state.chainService.getChainInfoByKey(chain);
@@ -1086,7 +1134,7 @@ export default class TransactionService {
1086
1134
  const transaction = this.getTransaction(eventData.id);
1087
1135
  if (transaction.status !== ExtrinsicStatus.SUCCESS && transaction.status !== ExtrinsicStatus.FAIL) {
1088
1136
  eventData.errors.push(new TransactionError(BasicTxErrorType.TIMEOUT, t('Transaction timeout')));
1089
- emitter.emit('error', eventData);
1137
+ emitter.emit('timeout', eventData);
1090
1138
  clearTimeout(timeout);
1091
1139
  }
1092
1140
  }, TRANSACTION_TIMEOUT);
@@ -51,5 +51,6 @@ export interface TransactionEventMap {
51
51
  extrinsicHash: (response: TransactionEventResponse) => void;
52
52
  error: (response: TransactionEventResponse) => void;
53
53
  success: (response: TransactionEventResponse) => void;
54
+ timeout: (response: TransactionEventResponse) => void;
54
55
  }
55
56
  export {};