@subwallet/extension-base 1.2.4-0 → 1.2.6-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 (29) hide show
  1. package/cjs/koni/api/staking/bonding/utils.js +38 -6
  2. package/cjs/koni/background/handlers/Mobile.js +2 -1
  3. package/cjs/koni/background/handlers/Tabs.js +3 -2
  4. package/cjs/packageInfo.js +1 -1
  5. package/cjs/page/index.js +4 -2
  6. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +104 -113
  7. package/cjs/services/earning-service/service.js +1 -1
  8. package/cjs/services/earning-service/utils/index.js +6 -1
  9. package/cjs/services/request-service/constants.js +5 -3
  10. package/cjs/services/request-service/handler/AuthRequestHandler.js +32 -12
  11. package/cjs/storage/index.js +1 -1
  12. package/koni/api/staking/bonding/utils.d.ts +6 -2
  13. package/koni/api/staking/bonding/utils.js +33 -4
  14. package/koni/background/handlers/Mobile.js +2 -1
  15. package/koni/background/handlers/Tabs.js +3 -2
  16. package/package.json +5 -5
  17. package/packageInfo.js +1 -1
  18. package/page/index.d.ts +2 -2
  19. package/page/index.js +4 -2
  20. package/services/earning-service/handlers/native-staking/relay-chain.d.ts +5 -2
  21. package/services/earning-service/handlers/native-staking/relay-chain.js +106 -115
  22. package/services/earning-service/service.js +1 -1
  23. package/services/earning-service/utils/index.d.ts +2 -0
  24. package/services/earning-service/utils/index.js +6 -2
  25. package/services/request-service/constants.d.ts +1 -0
  26. package/services/request-service/constants.js +4 -2
  27. package/services/request-service/handler/AuthRequestHandler.d.ts +1 -0
  28. package/services/request-service/handler/AuthRequestHandler.js +22 -3
  29. package/storage/index.js +1 -1
@@ -354,13 +354,12 @@ export function getSupportedDaysByHistoryDepth(erasPerDay, maxSupportedEras, liv
354
354
  return maxSupportDay;
355
355
  }
356
356
  }
357
- export function getValidatorPointsMap(eraRewardMap) {
357
+ export function getRelayValidatorPointsMap(eraRewardMap) {
358
358
  // mapping store validator and totalPoints
359
359
  const validatorTotalPointsMap = {};
360
360
  Object.values(eraRewardMap).forEach(info => {
361
361
  const individual = info.individual;
362
- Object.entries(individual).forEach(([validator, rawPoints]) => {
363
- const points = rawPoints.replaceAll(',', '');
362
+ Object.entries(individual).forEach(([validator, points]) => {
364
363
  if (!validatorTotalPointsMap[validator]) {
365
364
  validatorTotalPointsMap[validator] = new BigNumber(points);
366
365
  } else {
@@ -370,7 +369,7 @@ export function getValidatorPointsMap(eraRewardMap) {
370
369
  });
371
370
  return validatorTotalPointsMap;
372
371
  }
373
- export function getTopValidatorByPoints(validatorPointsList) {
372
+ export function getRelayTopValidatorByPoints(validatorPointsList) {
374
373
  const sortValidatorPointsList = Object.fromEntries(Object.entries(validatorPointsList).sort((a, b) => a[1].minus(b[1]).toNumber()).reverse());
375
374
 
376
375
  // keep 50% first validator
@@ -380,6 +379,36 @@ export function getTopValidatorByPoints(validatorPointsList) {
380
379
  const top50PercentRecord = Object.fromEntries(top50PercentEntries);
381
380
  return Object.keys(top50PercentRecord);
382
381
  }
382
+ export function getRelayBlockedValidatorList(validators) {
383
+ const blockValidatorList = [];
384
+ for (const validator of validators) {
385
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
386
+ const validatorAddress = validator[0].toHuman()[0];
387
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
388
+ const validatorPrefs = validator[1].toHuman();
389
+ const isBlocked = validatorPrefs.blocked;
390
+ if (isBlocked) {
391
+ blockValidatorList.push(validatorAddress);
392
+ }
393
+ }
394
+ return blockValidatorList;
395
+ }
396
+ export function getRelayEraRewardMap(eraRewardPointArray, startEraForPoints) {
397
+ const eraRewardMap = {};
398
+ for (const item of eraRewardPointArray) {
399
+ eraRewardMap[startEraForPoints] = item.toPrimitive();
400
+ startEraForPoints++;
401
+ }
402
+ return eraRewardMap;
403
+ }
404
+ export async function getRelayMaxNominations(substrateApi) {
405
+ var _substrateApi$api$con, _substrateApi$api$con2, _substrateApi$api$cal;
406
+ await substrateApi.isReady;
407
+ const maxNominations = ((_substrateApi$api$con = substrateApi.api.consts.staking) === null || _substrateApi$api$con === void 0 ? void 0 : (_substrateApi$api$con2 = _substrateApi$api$con.maxNominations) === null || _substrateApi$api$con2 === void 0 ? void 0 : _substrateApi$api$con2.toString()) || '16';
408
+ const _maxNominationsByNominationQuota = await ((_substrateApi$api$cal = substrateApi.api.call.stakingApi) === null || _substrateApi$api$cal === void 0 ? void 0 : _substrateApi$api$cal.nominationsQuota(0)); // todo: review param. Currently return constant for all param.
409
+ const maxNominationsByNominationQuota = _maxNominationsByNominationQuota === null || _maxNominationsByNominationQuota === void 0 ? void 0 : _maxNominationsByNominationQuota.toString();
410
+ return maxNominationsByNominationQuota || maxNominations;
411
+ }
383
412
  export const getMinStakeErrorMessage = (chainInfo, bnMinStake) => {
384
413
  const tokenInfo = _getChainNativeTokenBasicInfo(chainInfo);
385
414
  const number = formatNumber(bnMinStake.toString(), tokenInfo.decimals || 0, balanceFormatter);
@@ -131,7 +131,8 @@ export default class Mobile {
131
131
  }
132
132
  async _getLocalStorageExportData() {
133
133
  await swStorage.waitReady;
134
- return Promise.resolve(JSON.stringify(swStorage.copy()));
134
+ const storage = await swStorage.copy();
135
+ return Promise.resolve(JSON.stringify(storage));
135
136
  }
136
137
  async _getDexieExportData() {
137
138
  const indexedDB = await this.state.dbService.exportDB();
@@ -237,7 +237,7 @@ export default class KoniTabs {
237
237
  anyType
238
238
  }) {
239
239
  const authInfo = await this.getAuthInfo(url);
240
- return transformAccountsV2(this.#koniState.keyringService.accounts, anyType, authInfo, accountAuthType);
240
+ return transformAccountsV2(this.#koniState.keyringService.accounts, anyType, authInfo, (authInfo === null || authInfo === void 0 ? void 0 : authInfo.accountAuthType) || accountAuthType);
241
241
  }
242
242
  accountsSubscribeV2(url, {
243
243
  accountAuthType
@@ -249,8 +249,9 @@ export default class KoniTabs {
249
249
  this.#accountSubs[id] = {
250
250
  subscription: authInfoSubject.subscribe(infos => {
251
251
  this.getAuthInfo(url, infos).then(authInfo => {
252
+ const accountAuthType_ = (authInfo === null || authInfo === void 0 ? void 0 : authInfo.accountAuthType) || accountAuthType;
252
253
  const accounts = this.#koniState.keyringService.accounts;
253
- return cb(transformAccountsV2(accounts, false, authInfo, accountAuthType));
254
+ return cb(transformAccountsV2(accounts, false, authInfo, accountAuthType_));
254
255
  }).catch(console.error);
255
256
  }),
256
257
  url
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.2.4-0",
20
+ "version": "1.2.6-0",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -1922,10 +1922,10 @@
1922
1922
  "@sora-substrate/type-definitions": "^1.17.7",
1923
1923
  "@substrate/connect": "^0.8.9",
1924
1924
  "@subwallet/chain-list": "0.2.67",
1925
- "@subwallet/extension-base": "^1.2.4-0",
1926
- "@subwallet/extension-chains": "^1.2.4-0",
1927
- "@subwallet/extension-dapp": "^1.2.4-0",
1928
- "@subwallet/extension-inject": "^1.2.4-0",
1925
+ "@subwallet/extension-base": "^1.2.6-0",
1926
+ "@subwallet/extension-chains": "^1.2.6-0",
1927
+ "@subwallet/extension-dapp": "^1.2.6-0",
1928
+ "@subwallet/extension-inject": "^1.2.6-0",
1929
1929
  "@subwallet/keyring": "^0.1.5",
1930
1930
  "@subwallet/ui-keyring": "^0.1.5",
1931
1931
  "@walletconnect/keyvaluestorage": "^1.1.1",
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.2.4-0'
10
+ version: '1.2.6-0'
11
11
  };
package/page/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { MessageTypes, MessageTypesWithNoSubscriptions, MessageTypesWithNullRequest, MessageTypesWithSubscriptions, RequestTypes, ResponseTypes, SubscriptionMessageTypes, TransportResponseMessage } from '../background/types';
2
- import { EvmProvider } from '@subwallet/extension-inject/types';
2
+ import { AuthRequestOption, EvmProvider } from '@subwallet/extension-inject/types';
3
3
  import Injected from './Injected';
4
4
  export interface Handler {
5
5
  resolve: (data?: any) => void;
@@ -10,7 +10,7 @@ export declare type Handlers = Record<string, Handler>;
10
10
  export declare function sendMessage<TMessageType extends MessageTypesWithNullRequest>(message: TMessageType): Promise<ResponseTypes[TMessageType]>;
11
11
  export declare function sendMessage<TMessageType extends MessageTypesWithNoSubscriptions>(message: TMessageType, request: RequestTypes[TMessageType]): Promise<ResponseTypes[TMessageType]>;
12
12
  export declare function sendMessage<TMessageType extends MessageTypesWithSubscriptions>(message: TMessageType, request: RequestTypes[TMessageType], subscriber: (data: SubscriptionMessageTypes[TMessageType]) => void): Promise<ResponseTypes[TMessageType]>;
13
- export declare function enable(origin: string): Promise<Injected>;
13
+ export declare function enable(origin: string, opt?: AuthRequestOption): Promise<Injected>;
14
14
  export declare function handleResponse<TMessageType extends MessageTypes>(data: TransportResponseMessage<TMessageType> & {
15
15
  subscription?: string;
16
16
  }): void;
package/page/index.js CHANGED
@@ -38,9 +38,11 @@ export function sendMessage(message, request, subscriber) {
38
38
  }
39
39
 
40
40
  // the enable function, called by the dapp to allow access
41
- export async function enable(origin) {
41
+
42
+ export async function enable(origin, opt) {
42
43
  await sendMessage('pub(authorize.tabV2)', {
43
- origin
44
+ origin,
45
+ accountAuthType: (opt === null || opt === void 0 ? void 0 : opt.accountAuthType) || 'substrate'
44
46
  });
45
47
  return new Injected(sendMessage);
46
48
  }
@@ -1,16 +1,19 @@
1
1
  import { _ChainInfo } from '@subwallet/chain-list/types';
2
2
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
3
- import { ExtrinsicType, UnstakingInfo } from '@subwallet/extension-base/background/KoniTypes';
3
+ import { ExtrinsicType, NominationInfo, UnstakingInfo } from '@subwallet/extension-base/background/KoniTypes';
4
4
  import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
5
- import { BaseYieldPositionInfo, OptimalYieldPath, PalletStakingStakingLedger, StakeCancelWithdrawalParams, SubmitJoinNativeStaking, SubmitYieldJoinData, TransactionData, ValidatorInfo, YieldPoolInfo, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
5
+ import { BaseYieldPositionInfo, OptimalYieldPath, PalletStakingNominations, PalletStakingStakingLedger, StakeCancelWithdrawalParams, SubmitJoinNativeStaking, SubmitYieldJoinData, TransactionData, ValidatorInfo, YieldPoolInfo, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
6
6
  import { DeriveSessionProgress } from '@polkadot/api-derive/types';
7
7
  import { BN } from '@polkadot/util';
8
8
  import BaseNativeStakingPoolHandler from './base';
9
9
  export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPoolHandler {
10
10
  subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
11
11
  parseNominatorMetadata(chainInfo: _ChainInfo, address: string, substrateApi: _SubstrateApi, ledger: PalletStakingStakingLedger, currentEra: string, minStake: BN, _deriveSessionProgress: DeriveSessionProgress): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
12
+ handleNominationsList(substrateApi: _SubstrateApi, chain: string, nominations: PalletStakingNominations, currentEra: string, address: string, maxNominatorRewardedPerValidator: number | undefined): Promise<NominationInfo[]>;
12
13
  subscribePoolPosition(useAddresses: string[], resultCallback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
13
14
  getPoolTargets(): Promise<ValidatorInfo[]>;
15
+ private getValidatorExpectedReturn;
16
+ private parseEraStakerData;
14
17
  validateYieldJoin(data: SubmitYieldJoinData, path: OptimalYieldPath): Promise<TransactionError[]>;
15
18
  createJoinExtrinsic(data: SubmitJoinNativeStaking, positionInfo?: YieldPositionInfo, bondDest?: string): Promise<[TransactionData, YieldTokenBaseInfo]>;
16
19
  validateYieldLeave(amount: string, address: string, fastLeave: boolean, selectedTarget?: string): Promise<TransactionError[]>;
@@ -3,11 +3,11 @@
3
3
 
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { BasicTxErrorType, ExtrinsicType, StakingTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
- import { calculateAlephZeroValidatorReturn, calculateChainStakedReturnV2, calculateInflation, calculateTernoaValidatorReturn, calculateValidatorStakedReturn, getAvgValidatorEraReward, getCommission, getMaxValidatorErrorMessage, getMinStakeErrorMessage, getSupportedDaysByHistoryDepth, getTopValidatorByPoints, getValidatorPointsMap } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
6
+ import { calculateAlephZeroValidatorReturn, calculateChainStakedReturnV2, calculateInflation, calculateTernoaValidatorReturn, calculateValidatorStakedReturn, getAvgValidatorEraReward, getCommission, getMaxValidatorErrorMessage, getMinStakeErrorMessage, getRelayBlockedValidatorList, getRelayEraRewardMap, getRelayMaxNominations, getRelayTopValidatorByPoints, getRelayValidatorPointsMap, getSupportedDaysByHistoryDepth } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
7
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, _UPDATED_RUNTIME_STAKING_GROUP, MaxEraRewardPointsEras } from '@subwallet/extension-base/services/earning-service/constants';
10
- import { parseIdentity } from '@subwallet/extension-base/services/earning-service/utils';
10
+ import { applyDecimal, parseIdentity } from '@subwallet/extension-base/services/earning-service/utils';
11
11
  import { EarningStatus, UnstakingStatus } from '@subwallet/extension-base/types';
12
12
  import { balanceFormatter, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
13
13
  import BigN from 'bignumber.js';
@@ -44,17 +44,14 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
44
44
  await defaultCallback();
45
45
  await substrateApi.isReady;
46
46
  const unsub = await ((_substrateApi$api$que = substrateApi.api.query.staking) === null || _substrateApi$api$que === void 0 ? void 0 : _substrateApi$api$que.currentEra(async _currentEra => {
47
- var _substrateApi$api$con, _substrateApi$api$con2, _substrateApi$api$con3, _substrateApi$api$cal, _substrateApi$api$que2, _substrateApi$api$que3, _substrateApi$api$que4, _substrateApi$api$que5, _substrateApi$api$que6;
47
+ var _substrateApi$api$con, _substrateApi$api$que2, _substrateApi$api$que3, _substrateApi$api$que4, _substrateApi$api$que5, _substrateApi$api$que6;
48
48
  if (cancel) {
49
49
  unsub();
50
50
  return;
51
51
  }
52
- let maxNominations = ((_substrateApi$api$con = substrateApi.api.consts.staking) === null || _substrateApi$api$con === void 0 ? void 0 : (_substrateApi$api$con2 = _substrateApi$api$con.maxNominations) === null || _substrateApi$api$con2 === void 0 ? void 0 : _substrateApi$api$con2.toString()) || '16';
53
52
  const unlimitedNominatorRewarded = substrateApi.api.consts.staking.maxExposurePageSize !== undefined;
54
- const maxNominatorRewarded = (_substrateApi$api$con3 = substrateApi.api.consts.staking.maxNominatorRewardedPerValidator) === null || _substrateApi$api$con3 === void 0 ? void 0 : _substrateApi$api$con3.toString();
55
- const _maxNominationsByNominationQuota = await ((_substrateApi$api$cal = substrateApi.api.call.stakingApi) === null || _substrateApi$api$cal === void 0 ? void 0 : _substrateApi$api$cal.nominationsQuota(0)); // todo: review param. Currently return constant for all param.
56
- const maxNominationsByNominationQuota = _maxNominationsByNominationQuota === null || _maxNominationsByNominationQuota === void 0 ? void 0 : _maxNominationsByNominationQuota.toString();
57
- maxNominations = maxNominationsByNominationQuota !== null && maxNominationsByNominationQuota !== void 0 ? maxNominationsByNominationQuota : maxNominations;
53
+ const maxNominatorRewarded = (_substrateApi$api$con = substrateApi.api.consts.staking.maxNominatorRewardedPerValidator) === null || _substrateApi$api$con === void 0 ? void 0 : _substrateApi$api$con.toString();
54
+ const maxNominations = await getRelayMaxNominations(substrateApi);
58
55
  const currentEra = _currentEra.toString();
59
56
  const maxUnlockingChunks = substrateApi.api.consts.staking.maxUnlockingChunks.toString();
60
57
  const unlockingEras = substrateApi.api.consts.staking.bondingDuration.toString();
@@ -133,54 +130,15 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
133
130
  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()]);
134
131
  const unlimitedNominatorRewarded = substrateApi.api.consts.staking.maxExposurePageSize !== undefined;
135
132
  const _maxNominatorRewardedPerValidator = (substrateApi.api.consts.staking.maxNominatorRewardedPerValidator || 0).toString();
136
- const maxNominatorRewardedPerValidator = parseInt(_maxNominatorRewardedPerValidator);
133
+ const maxNominatorRewardedPerValidator = unlimitedNominatorRewarded ? undefined : parseInt(_maxNominatorRewardedPerValidator);
137
134
  const nominations = _nominations.toPrimitive();
138
135
  const bonded = _bonded.toHuman();
136
+ const addressFormatted = reformatAddress(address, _getChainSubstrateAddressPrefix(chainInfo));
139
137
  const activeStake = ledger.active.toString();
140
138
  const totalStake = ledger.total.toString();
141
139
  const unstakingBalance = (ledger.total - ledger.active).toString();
142
- const nominationList = [];
143
140
  const unstakingList = [];
144
- if (nominations) {
145
- const validatorList = nominations.targets;
146
- await Promise.all(validatorList.map(async validatorAddress => {
147
- let nominationStatus = EarningStatus.NOT_EARNING;
148
- let eraStakerOtherList = [];
149
- let identity;
150
- if (_UPDATED_RUNTIME_STAKING_GROUP.includes(this.chain)) {
151
- // todo: review all relaychains later
152
- const [[_identity], _eraStaker] = await Promise.all([parseIdentity(substrateApi, validatorAddress), substrateApi.api.query.staking.erasStakersPaged.entries(currentEra, validatorAddress)]);
153
- identity = _identity;
154
- eraStakerOtherList = _eraStaker.flatMap(paged => paged[1].toPrimitive().others);
155
- } else {
156
- const [[_identity], _eraStaker] = await Promise.all([parseIdentity(substrateApi, validatorAddress), substrateApi.api.query.staking.erasStakers(currentEra, validatorAddress)]);
157
- identity = _identity;
158
- const eraStaker = _eraStaker.toPrimitive();
159
- eraStakerOtherList = eraStaker.others;
160
- }
161
- const sortedNominators = eraStakerOtherList.sort((a, b) => {
162
- return new BigN(b.value).minus(a.value).toNumber();
163
- });
164
- const topNominators = sortedNominators.map(nominator => {
165
- return nominator.who;
166
- });
167
- if (!topNominators.includes(reformatAddress(address, _getChainSubstrateAddressPrefix(chainInfo)))) {
168
- // if nominator has target but not in nominator list
169
- nominationStatus = EarningStatus.WAITING;
170
- } else if (topNominators.slice(0, unlimitedNominatorRewarded ? undefined : maxNominatorRewardedPerValidator).includes(reformatAddress(address, _getChainSubstrateAddressPrefix(chainInfo)))) {
171
- // if address in top nominators
172
- nominationStatus = EarningStatus.EARNING_REWARD;
173
- }
174
- nominationList.push({
175
- chain,
176
- validatorAddress,
177
- status: nominationStatus,
178
- validatorIdentity: identity,
179
- activeStake: '0' // relaychain allocates stake accordingly
180
- });
181
- }));
182
- }
183
-
141
+ const nominationList = (await this.handleNominationsList(substrateApi, chain, nominations, currentEra, addressFormatted, maxNominatorRewardedPerValidator)) || [];
184
142
  let stakingStatus = EarningStatus.NOT_EARNING;
185
143
  const bnActiveStake = new BN(activeStake);
186
144
  let waitingNominationCount = 0;
@@ -224,6 +182,51 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
224
182
  unstakings: unstakingList
225
183
  };
226
184
  }
185
+ async handleNominationsList(substrateApi, chain, nominations, currentEra, address, maxNominatorRewardedPerValidator) {
186
+ const nominationList = [];
187
+ if (!nominations) {
188
+ return [];
189
+ }
190
+ const validatorList = nominations.targets;
191
+ await Promise.all(validatorList.map(async validatorAddress => {
192
+ let nominationStatus = EarningStatus.NOT_EARNING;
193
+ let eraStakerOtherList = [];
194
+ let identity;
195
+ if (_UPDATED_RUNTIME_STAKING_GROUP.includes(this.chain)) {
196
+ // todo: review all relaychains later
197
+ const [[_identity], _eraStaker] = await Promise.all([parseIdentity(substrateApi, validatorAddress), substrateApi.api.query.staking.erasStakersPaged.entries(currentEra, validatorAddress)]);
198
+ identity = _identity;
199
+ eraStakerOtherList = _eraStaker.flatMap(paged => paged[1].toPrimitive().others);
200
+ } else {
201
+ const [[_identity], _eraStaker] = await Promise.all([parseIdentity(substrateApi, validatorAddress), substrateApi.api.query.staking.erasStakers(currentEra, validatorAddress)]);
202
+ identity = _identity;
203
+ const eraStaker = _eraStaker.toPrimitive();
204
+ eraStakerOtherList = eraStaker.others;
205
+ }
206
+ const sortedNominators = eraStakerOtherList.sort((a, b) => {
207
+ return new BigN(b.value).minus(a.value).toNumber();
208
+ });
209
+ const topNominators = sortedNominators.map(nominator => {
210
+ return nominator.who;
211
+ });
212
+ if (!topNominators.includes(address)) {
213
+ // if nominator has target but not in nominator list
214
+ nominationStatus = EarningStatus.WAITING;
215
+ } else if (topNominators.slice(0, maxNominatorRewardedPerValidator).includes(address)) {
216
+ // if address in top nominators
217
+ nominationStatus = EarningStatus.EARNING_REWARD;
218
+ }
219
+ nominationList.push({
220
+ chain,
221
+ validatorAddress,
222
+ status: nominationStatus,
223
+ validatorIdentity: identity,
224
+ activeStake: '0' // relaychain allocates stake accordingly
225
+ });
226
+ }));
227
+
228
+ return nominationList;
229
+ }
227
230
  async subscribePoolPosition(useAddresses, resultCallback) {
228
231
  var _substrateApi$api$que13;
229
232
  let cancel = false;
@@ -285,7 +288,6 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
285
288
 
286
289
  async getPoolTargets() {
287
290
  var _chainApi$api$query$s;
288
- const decimals = this.nativeToken.decimals || 0;
289
291
  const chainApi = await this.substrateApi.isReady;
290
292
  const poolInfo = await this.getPoolInfo();
291
293
  if (!poolInfo || !poolInfo.statistic) {
@@ -295,11 +297,9 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
295
297
  const currentEra = _era.toString();
296
298
  const activeEraInfo = _activeEraInfo.toPrimitive();
297
299
  const activeEra = activeEraInfo.index;
298
- const allValidators = [];
299
- const validatorInfoList = [];
300
300
  const maxEraRewardPointsEras = MaxEraRewardPointsEras;
301
301
  const endEraForPoints = parseInt(activeEra) - 1;
302
- let startEraForPoints = Math.max(endEraForPoints - maxEraRewardPointsEras + 1, 0);
302
+ const startEraForPoints = Math.max(endEraForPoints - maxEraRewardPointsEras + 1, 0);
303
303
  let _eraStakersPromise;
304
304
  if (_UPDATED_RUNTIME_STAKING_GROUP.includes(this.chain)) {
305
305
  // todo: review all relaychains later
@@ -308,43 +308,65 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
308
308
  _eraStakersPromise = chainApi.api.query.staking.erasStakers.entries(parseInt(currentEra));
309
309
  }
310
310
  const [_totalEraStake, _eraStakers, _minBond, _stakingRewards, _validators, ..._eraRewardPoints] = await Promise.all([chainApi.api.query.staking.erasTotalStake(parseInt(currentEra)), _eraStakersPromise, chainApi.api.query.staking.minNominatorBond(), ((_chainApi$api$query$s = chainApi.api.query.stakingRewards) === null || _chainApi$api$query$s === void 0 ? void 0 : _chainApi$api$query$s.data) && chainApi.api.query.stakingRewards.data(), chainApi.api.query.staking.validators.entries(), chainApi.api.query.staking.erasRewardPoints.multi([...Array(maxEraRewardPointsEras).keys()].map(i => i + startEraForPoints))]);
311
- const eraRewardMap = {};
312
- for (const item of _eraRewardPoints[0]) {
313
- eraRewardMap[startEraForPoints] = item.toHuman();
314
- startEraForPoints++;
315
- }
316
- const validatorPointsMap = getValidatorPointsMap(eraRewardMap);
317
- const topValidatorList = getTopValidatorByPoints(validatorPointsMap);
318
-
319
- // filter blocked validators
311
+ const eraRewardMap = getRelayEraRewardMap(_eraRewardPoints[0], startEraForPoints);
312
+ const validatorPointsMap = getRelayValidatorPointsMap(eraRewardMap);
313
+ const topValidatorList = getRelayTopValidatorByPoints(validatorPointsMap);
320
314
  const validators = _validators;
321
- const blockValidatorList = [];
322
- for (const validator of validators) {
323
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
324
- const validatorAddress = validator[0].toHuman()[0];
325
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
326
- const validatorPrefs = validator[1].toHuman();
327
- const isBlocked = validatorPrefs.blocked;
328
- if (isBlocked) {
329
- blockValidatorList.push(validatorAddress);
330
- }
331
- }
332
- const stakingRewards = _stakingRewards === null || _stakingRewards === void 0 ? void 0 : _stakingRewards.toPrimitive();
315
+ const blockedValidatorList = getRelayBlockedValidatorList(validators);
333
316
  const unlimitedNominatorRewarded = chainApi.api.consts.staking.maxExposurePageSize !== undefined;
334
317
  const maxNominatorRewarded = (chainApi.api.consts.staking.maxNominatorRewardedPerValidator || 0).toString();
335
318
  const bnTotalEraStake = new BN(_totalEraStake.toString());
336
- const rawMinBond = _minBond.toHuman();
337
- const minBond = rawMinBond.replaceAll(',', '');
319
+ const minBond = _minBond.toPrimitive();
320
+ const [totalStakeMap, allValidatorAddresses, validatorInfoList] = this.parseEraStakerData(_eraStakers, blockedValidatorList, topValidatorList, validatorPointsMap, minBond, maxNominatorRewarded, unlimitedNominatorRewarded);
321
+ const extraInfoMap = {};
322
+ await Promise.all(allValidatorAddresses.map(async address => {
323
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
324
+ const [_commissionInfo, [identity, isVerified]] = await Promise.all([chainApi.api.query.staking.validators(address), parseIdentity(chainApi, address)]);
325
+ const commissionInfo = _commissionInfo.toHuman();
326
+ extraInfoMap[address] = {
327
+ commission: commissionInfo.commission,
328
+ blocked: commissionInfo.blocked,
329
+ identity,
330
+ isVerified: isVerified
331
+ };
332
+ }));
333
+ const decimals = this.nativeToken.decimals || 0;
334
+ const bnAvgStake = applyDecimal(bnTotalEraStake.divn(validatorInfoList.length), decimals);
335
+ for (const validator of validatorInfoList) {
336
+ const commissionString = extraInfoMap[validator.address].commission;
337
+ const commission = getCommission(commissionString);
338
+ validator.expectedReturn = this.getValidatorExpectedReturn(this.chain, validator, poolInfo.statistic.totalApy, commission, _stakingRewards, allValidatorAddresses, decimals, totalStakeMap, bnAvgStake);
339
+ validator.commission = commission;
340
+ validator.blocked = extraInfoMap[validator.address].blocked;
341
+ validator.identity = extraInfoMap[validator.address].identity;
342
+ validator.isVerified = extraInfoMap[validator.address].isVerified;
343
+ }
344
+ return validatorInfoList;
345
+ }
346
+ getValidatorExpectedReturn(chain, validator, totalApy, commission, _stakingRewards, allValidatorAddresses, decimals, totalStakeMap, bnAvgStake) {
347
+ if (_STAKING_CHAIN_GROUP.aleph.includes(chain)) {
348
+ return calculateAlephZeroValidatorReturn(totalApy, commission);
349
+ } else if (_STAKING_CHAIN_GROUP.ternoa.includes(chain)) {
350
+ const stakingRewards = _stakingRewards === null || _stakingRewards === void 0 ? void 0 : _stakingRewards.toPrimitive();
351
+ const rewardPerValidator = applyDecimal(new BN(stakingRewards.sessionExtraRewardPayout).divn(allValidatorAddresses.length), decimals);
352
+ const validatorStake = applyDecimal(totalStakeMap[validator.address], decimals).toNumber();
353
+ return calculateTernoaValidatorReturn(rewardPerValidator.toNumber(), validatorStake, commission);
354
+ } else {
355
+ const bnValidatorStake = applyDecimal(totalStakeMap[validator.address], decimals);
356
+ return calculateValidatorStakedReturn(totalApy, bnValidatorStake, bnAvgStake, commission);
357
+ }
358
+ }
359
+ parseEraStakerData(_eraStakers, blockedValidatorList, topValidatorList, validatorPointsMap, minBond, maxNominatorRewarded, unlimitedNominatorRewarded) {
338
360
  const totalStakeMap = {};
339
- const bnDecimals = new BN((10 ** decimals).toString());
340
- const eraStakers = _eraStakers;
341
- for (const item of eraStakers) {
361
+ const allValidatorAddresses = [];
362
+ const validatorInfoList = [];
363
+ for (const item of _eraStakers) {
342
364
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
343
365
  const rawValidatorInfo = item[0].toHuman();
344
366
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
345
367
  const rawValidatorStat = item[1].toPrimitive();
346
368
  const validatorAddress = rawValidatorInfo[1];
347
- if (!blockValidatorList.includes(validatorAddress)) {
369
+ if (!blockedValidatorList.includes(validatorAddress)) {
348
370
  var _validatorPointsMap$v;
349
371
  let isTopQuartile = false;
350
372
  if (topValidatorList.includes(validatorAddress)) {
@@ -365,7 +387,7 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
365
387
  nominatorCount = others.length;
366
388
  }
367
389
  }
368
- allValidators.push(validatorAddress);
390
+ allValidatorAddresses.push(validatorAddress);
369
391
  validatorInfoList.push({
370
392
  address: validatorAddress,
371
393
  totalStake: bnTotalStake.toString(),
@@ -377,46 +399,15 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
377
399
  expectedReturn: 0,
378
400
  blocked: false,
379
401
  isVerified: false,
380
- minBond,
402
+ minBond: minBond.toString(),
381
403
  isCrowded: unlimitedNominatorRewarded ? false : nominatorCount > parseInt(maxNominatorRewarded),
382
404
  eraRewardPoint: ((_validatorPointsMap$v = validatorPointsMap[validatorAddress]) !== null && _validatorPointsMap$v !== void 0 ? _validatorPointsMap$v : BN_ZERO).toString(),
383
405
  topQuartile: isTopQuartile
384
406
  });
385
407
  }
386
408
  }
387
- const extraInfoMap = {};
388
- await Promise.all(allValidators.map(async address => {
389
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
390
- const [_commissionInfo, [identity, isVerified]] = await Promise.all([chainApi.api.query.staking.validators(address), parseIdentity(chainApi, address)]);
391
- const commissionInfo = _commissionInfo.toHuman();
392
- extraInfoMap[address] = {
393
- commission: commissionInfo.commission,
394
- blocked: commissionInfo.blocked,
395
- identity,
396
- isVerified: isVerified
397
- };
398
- }));
399
- const bnAvgStake = bnTotalEraStake.divn(validatorInfoList.length).div(bnDecimals);
400
- for (const validator of validatorInfoList) {
401
- const commission = extraInfoMap[validator.address].commission;
402
- const bnValidatorStake = totalStakeMap[validator.address].div(bnDecimals);
403
- if (_STAKING_CHAIN_GROUP.aleph.includes(this.chain)) {
404
- validator.expectedReturn = calculateAlephZeroValidatorReturn(poolInfo.statistic.totalApy, getCommission(commission));
405
- } else if (_STAKING_CHAIN_GROUP.ternoa.includes(this.chain)) {
406
- const rewardPerValidator = new BN(stakingRewards.sessionExtraRewardPayout).divn(allValidators.length).div(bnDecimals);
407
- const validatorStake = totalStakeMap[validator.address].div(bnDecimals).toNumber();
408
- validator.expectedReturn = calculateTernoaValidatorReturn(rewardPerValidator.toNumber(), validatorStake, getCommission(commission));
409
- } else {
410
- validator.expectedReturn = calculateValidatorStakedReturn(poolInfo.statistic.totalApy, bnValidatorStake, bnAvgStake, getCommission(commission));
411
- }
412
- validator.commission = parseFloat(commission.split('%')[0]);
413
- validator.blocked = extraInfoMap[validator.address].blocked;
414
- validator.identity = extraInfoMap[validator.address].identity;
415
- validator.isVerified = extraInfoMap[validator.address].isVerified;
416
- }
417
- return validatorInfoList;
409
+ return [totalStakeMap, allValidatorAddresses, validatorInfoList];
418
410
  }
419
-
420
411
  /* Get pool targets */
421
412
 
422
413
  /* Join pool action */
@@ -33,7 +33,7 @@ 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 = false;
36
+ useOnlineCacheOnly = true;
37
37
  constructor(state) {
38
38
  this.state = state;
39
39
  this.dbService = state.dbService;
@@ -1,5 +1,6 @@
1
1
  import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
2
2
  import { LendingYieldPoolInfo, LiquidYieldPoolInfo, NativeYieldPoolInfo, NominationYieldPoolInfo, YieldAssetExpectedEarning, YieldCompoundingPeriod, YieldPoolInfo, YieldPoolType } from '@subwallet/extension-base/types';
3
+ import { BN } from '@polkadot/util';
3
4
  export declare function calculateReward(apr: number, amount?: number, compoundingPeriod?: YieldCompoundingPeriod, isApy?: boolean): YieldAssetExpectedEarning;
4
5
  /**
5
6
  * @returns
@@ -16,3 +17,4 @@ export declare const isNominationPool: (pool: YieldPoolInfo) => pool is Nominati
16
17
  export declare const isNativeStakingPool: (pool: YieldPoolInfo) => pool is NativeYieldPoolInfo;
17
18
  export declare const isLiquidPool: (pool: YieldPoolInfo) => pool is LiquidYieldPoolInfo;
18
19
  export declare const isLendingPool: (pool: YieldPoolInfo) => pool is LendingYieldPoolInfo;
20
+ export declare function applyDecimal(bnNumber: BN, decimals: number): BN;
@@ -3,7 +3,7 @@
3
3
 
4
4
  import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning-service/constants';
5
5
  import { YieldCompoundingPeriod, YieldPoolType } from '@subwallet/extension-base/types';
6
- import { hexToString, isHex } from '@polkadot/util';
6
+ import { BN, hexToString, isHex } from '@polkadot/util';
7
7
  export function calculateReward(apr, amount = 0, compoundingPeriod = YieldCompoundingPeriod.YEARLY, isApy = false) {
8
8
  if (!apr) {
9
9
  return {};
@@ -117,4 +117,8 @@ export const isLiquidPool = pool => {
117
117
  };
118
118
  export const isLendingPool = pool => {
119
119
  return pool.type === YieldPoolType.LENDING;
120
- };
120
+ };
121
+ export function applyDecimal(bnNumber, decimals) {
122
+ const bnDecimals = new BN((10 ** decimals).toString());
123
+ return bnNumber.div(bnDecimals);
124
+ }
@@ -1,3 +1,4 @@
1
1
  export declare const EXTENSION_REQUEST_URL = "extension";
2
2
  export declare const PREDEFINED_CHAIN_DAPP_CHAIN_MAP: Record<string, string[]>;
3
3
  export declare const WEB_APP_URL: string[];
4
+ export declare const DAPP_CONNECT_ALL_TYPE_ACCOUNT_URL: string[];
@@ -13,5 +13,7 @@ export const WEB_APP_URL = [
13
13
  // Local
14
14
  'subwallet-webapp.pages.dev',
15
15
  // Pull request build
16
- 'web.subwallet.app' // Production
17
- ];
16
+ 'web.subwallet.app' // Production,
17
+ ];
18
+
19
+ export const DAPP_CONNECT_ALL_TYPE_ACCOUNT_URL = ['https://polkadot.js.org/apps/', 'https://ipfs.io/ipns/dotapps.io'];
@@ -15,6 +15,7 @@ export default class AuthRequestHandler {
15
15
  private readonly evmChainSubject;
16
16
  readonly authSubjectV2: BehaviorSubject<AuthorizeRequest[]>;
17
17
  constructor(requestService: RequestService, chainService: ChainService, keyringService: KeyringService);
18
+ private init;
18
19
  private getAddressList;
19
20
  get numAuthRequestsV2(): number;
20
21
  private get allAuthRequestsV2();
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
5
- import { PREDEFINED_CHAIN_DAPP_CHAIN_MAP, WEB_APP_URL } from '@subwallet/extension-base/services/request-service/constants';
5
+ import { DAPP_CONNECT_ALL_TYPE_ACCOUNT_URL, PREDEFINED_CHAIN_DAPP_CHAIN_MAP, WEB_APP_URL } from '@subwallet/extension-base/services/request-service/constants';
6
6
  import AuthorizeStore from '@subwallet/extension-base/stores/Authorize';
7
7
  import { createPromiseHandler, getDomainFromUrl, stripUrl } from '@subwallet/extension-base/utils';
8
8
  import { getId } from '@subwallet/extension-base/utils/getId';
@@ -22,6 +22,24 @@ export default class AuthRequestHandler {
22
22
  this.keyringService = keyringService;
23
23
  this.#requestService = requestService;
24
24
  this.#chainService = chainService;
25
+ this.init().catch(console.error);
26
+ }
27
+ async init() {
28
+ const authList = await this.getAuthList();
29
+ let needUpdateAuthList = false;
30
+ Object.entries(authList).forEach(([key, value]) => {
31
+ const existKeyAllBothConnect = DAPP_CONNECT_ALL_TYPE_ACCOUNT_URL.find(url_ => url_.includes(key));
32
+ if (existKeyAllBothConnect && value.accountAuthType !== 'both') {
33
+ needUpdateAuthList = true;
34
+ authList[key] = {
35
+ ...value,
36
+ accountAuthType: 'both'
37
+ };
38
+ }
39
+ });
40
+ if (needUpdateAuthList) {
41
+ this.setAuthorize(authList);
42
+ }
25
43
  }
26
44
  getAddressList(value = false) {
27
45
  const addressList = Object.keys(this.keyringService.accounts);
@@ -202,7 +220,9 @@ export default class AuthRequestHandler {
202
220
  authorizePromiseMap = {};
203
221
  async authorizeUrlV2(url, request) {
204
222
  let authList = await this.getAuthList();
205
- let accountAuthType = request.accountAuthType || 'substrate';
223
+ const idStr = stripUrl(url);
224
+ const isAllowedDappConnectAllType = !!DAPP_CONNECT_ALL_TYPE_ACCOUNT_URL.find(url_ => url.includes(url_));
225
+ let accountAuthType = isAllowedDappConnectAllType ? 'both' : request.accountAuthType || 'substrate';
206
226
  request.accountAuthType = accountAuthType;
207
227
  if (!authList) {
208
228
  authList = {};
@@ -214,7 +234,6 @@ export default class AuthRequestHandler {
214
234
  reject,
215
235
  resolve
216
236
  } = promiseHandler;
217
- const idStr = stripUrl(url);
218
237
  const isExistedAuthBothBefore = Object.entries(this.authorizeUrlSubject.value).find(([key, data]) => key === idStr && data.accountAuthType === 'both');
219
238
  if (isExistedAuthBothBefore) {
220
239
  return true;
package/storage/index.js CHANGED
@@ -122,7 +122,7 @@ export class SWStorage {
122
122
  }
123
123
  async copy() {
124
124
  !this.isReady && (await this.waitReady);
125
- return JSON.parse(JSON.stringify(this._storage));
125
+ return Promise.resolve(JSON.parse(JSON.stringify(this._storage)));
126
126
  }
127
127
  async sync() {
128
128
  if (this.localStorage) {