@subwallet/extension-base 1.3.20-0 → 1.3.22-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/background/KoniTypes.d.ts +8 -1
- package/cjs/defaults.js +1 -1
- package/cjs/koni/background/handlers/Extension.js +519 -90
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/chain-service/constants.js +8 -3
- package/cjs/services/chain-service/handler/EvmApi.js +1 -3
- package/cjs/services/chain-service/handler/SubstrateChainHandler.js +3 -2
- package/cjs/services/chain-service/index.js +9 -0
- package/cjs/services/chain-service/utils/patch.js +1 -1
- package/cjs/services/earning-service/constants/chains.js +2 -1
- package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +19 -8
- package/cjs/services/earning-service/handlers/native-staking/mythos.js +337 -0
- package/cjs/services/earning-service/handlers/special.js +16 -10
- package/cjs/services/earning-service/service.js +4 -0
- package/cjs/services/earning-service/utils/index.js +2 -0
- package/cjs/services/history-service/helpers/recoverHistoryStatus.js +14 -5
- package/cjs/services/history-service/index.js +15 -3
- package/cjs/services/inapp-notification-service/index.js +78 -0
- package/cjs/services/inapp-notification-service/interfaces.js +2 -0
- package/cjs/services/keyring-service/context/state.js +2 -1
- package/cjs/services/migration-service/scripts/databases/ClearMetadataDatabase.js +3 -23
- package/cjs/services/migration-service/scripts/databases/ClearMetadataForChains.js +40 -0
- package/cjs/services/migration-service/scripts/databases/ClearMetadataForMythos.js +15 -0
- package/cjs/services/migration-service/scripts/index.js +6 -2
- package/cjs/services/request-service/handler/EvmRequestHandler.js +10 -0
- package/cjs/services/request-service/handler/SubstrateRequestHandler.js +4 -3
- package/cjs/services/request-service/index.js +2 -2
- package/cjs/services/setting-service/constants.js +5 -2
- package/cjs/services/storage-service/DatabaseService.js +101 -2
- package/cjs/services/storage-service/databases/index.js +3 -0
- package/cjs/services/storage-service/db-stores/Metadata.js +3 -0
- package/cjs/services/storage-service/db-stores/Migration.js +6 -1
- package/cjs/services/storage-service/db-stores/ProcessTransaction.js +47 -0
- package/cjs/services/storage-service/db-stores/Transaction.js +2 -0
- package/cjs/services/storage-service/db-stores/index.js +8 -1
- package/cjs/services/swap-service/handler/asset-hub/handler.js +30 -11
- package/cjs/services/swap-service/handler/hydradx-handler.js +18 -10
- package/cjs/services/swap-service/index.js +3 -0
- package/cjs/services/swap-service/utils.js +1 -0
- package/cjs/services/transaction-service/index.js +218 -9
- package/cjs/types/index.js +11 -0
- package/cjs/types/setting.js +1 -0
- package/cjs/types/swap/index.js +4 -1
- package/cjs/types/transaction/index.js +11 -0
- package/cjs/types/transaction/process.js +28 -0
- package/cjs/types/yield/actions/join/submit.js +16 -1
- package/defaults.d.ts +1 -1
- package/defaults.js +1 -1
- package/koni/background/handlers/Extension.d.ts +5 -0
- package/koni/background/handlers/Extension.js +437 -12
- package/package.json +52 -22
- package/packageInfo.js +1 -1
- package/services/chain-service/constants.js +8 -3
- package/services/chain-service/handler/EvmApi.js +1 -3
- package/services/chain-service/handler/SubstrateChainHandler.js +3 -2
- package/services/chain-service/index.d.ts +1 -0
- package/services/chain-service/index.js +9 -0
- package/services/chain-service/utils/patch.js +1 -1
- package/services/earning-service/constants/chains.d.ts +1 -0
- package/services/earning-service/constants/chains.js +2 -1
- package/services/earning-service/handlers/liquid-staking/stella-swap.js +19 -8
- package/services/earning-service/handlers/native-staking/mythos.d.ts +35 -0
- package/services/earning-service/handlers/native-staking/mythos.js +329 -0
- package/services/earning-service/handlers/special.js +18 -12
- package/services/earning-service/service.js +4 -0
- package/services/earning-service/utils/index.js +2 -0
- package/services/history-service/helpers/recoverHistoryStatus.js +14 -5
- package/services/history-service/index.d.ts +6 -5
- package/services/history-service/index.js +16 -5
- package/services/inapp-notification-service/index.d.ts +2 -0
- package/services/inapp-notification-service/index.js +79 -1
- package/services/inapp-notification-service/interfaces.d.ts +8 -1
- package/services/inapp-notification-service/interfaces.js +2 -0
- package/services/keyring-service/context/state.d.ts +1 -1
- package/services/keyring-service/context/state.js +3 -2
- package/services/migration-service/scripts/databases/ClearMetadataDatabase.d.ts +3 -3
- package/services/migration-service/scripts/databases/ClearMetadataDatabase.js +3 -23
- package/services/migration-service/scripts/databases/ClearMetadataForChains.d.ts +5 -0
- package/services/migration-service/scripts/databases/ClearMetadataForChains.js +32 -0
- package/services/migration-service/scripts/databases/ClearMetadataForMythos.d.ts +4 -0
- package/services/migration-service/scripts/databases/ClearMetadataForMythos.js +7 -0
- package/services/migration-service/scripts/index.d.ts +1 -0
- package/services/migration-service/scripts/index.js +4 -1
- package/services/request-service/handler/EvmRequestHandler.js +10 -0
- package/services/request-service/handler/SubstrateRequestHandler.d.ts +1 -1
- package/services/request-service/handler/SubstrateRequestHandler.js +4 -3
- package/services/request-service/index.d.ts +1 -1
- package/services/request-service/index.js +2 -2
- package/services/setting-service/constants.d.ts +1 -0
- package/services/setting-service/constants.js +3 -1
- package/services/storage-service/DatabaseService.d.ts +13 -3
- package/services/storage-service/DatabaseService.js +103 -4
- package/services/storage-service/databases/index.d.ts +2 -1
- package/services/storage-service/databases/index.js +3 -0
- package/services/storage-service/db-stores/Metadata.d.ts +1 -0
- package/services/storage-service/db-stores/Metadata.js +3 -0
- package/services/storage-service/db-stores/Migration.d.ts +1 -0
- package/services/storage-service/db-stores/Migration.js +6 -1
- package/services/storage-service/db-stores/ProcessTransaction.d.ts +14 -0
- package/services/storage-service/db-stores/ProcessTransaction.js +39 -0
- package/services/storage-service/db-stores/Transaction.js +2 -0
- package/services/storage-service/db-stores/index.d.ts +1 -0
- package/services/storage-service/db-stores/index.js +2 -1
- package/services/swap-service/handler/asset-hub/handler.js +30 -11
- package/services/swap-service/handler/hydradx-handler.js +18 -10
- package/services/swap-service/index.js +3 -0
- package/services/swap-service/utils.js +1 -0
- package/services/transaction-service/index.d.ts +19 -1
- package/services/transaction-service/index.js +220 -11
- package/services/transaction-service/types.d.ts +13 -4
- package/types/index.d.ts +1 -0
- package/types/index.js +1 -0
- package/types/setting.d.ts +3 -0
- package/types/setting.js +1 -0
- package/types/swap/index.d.ts +3 -2
- package/types/swap/index.js +4 -1
- package/types/transaction/index.d.ts +1 -0
- package/types/transaction/index.js +1 -0
- package/types/transaction/process.d.ts +84 -0
- package/types/transaction/process.js +20 -0
- package/types/transaction/request.d.ts +3 -1
- package/types/yield/actions/join/submit.d.ts +18 -3
- package/types/yield/actions/join/submit.js +11 -1
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
5
|
+
import { APIItemState, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
6
|
+
import { getCommission } 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';
|
|
8
|
+
import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
|
|
9
|
+
import { BasicTxErrorType, EarningStatus, UnstakingStatus } from '@subwallet/extension-base/types';
|
|
10
|
+
import { balanceFormatter, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
|
|
11
|
+
export default class MythosNativeStakingPoolHandler extends BaseParaStakingPoolHandler {
|
|
12
|
+
availableMethod = {
|
|
13
|
+
join: true,
|
|
14
|
+
defaultUnstake: true,
|
|
15
|
+
fastUnstake: false,
|
|
16
|
+
cancelUnstake: false,
|
|
17
|
+
withdraw: true,
|
|
18
|
+
claimReward: true
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/* Subscribe pool info */
|
|
22
|
+
|
|
23
|
+
async subscribePoolInfo(callback) {
|
|
24
|
+
let cancel = false;
|
|
25
|
+
const substrateApi = this.substrateApi;
|
|
26
|
+
const nativeToken = this.nativeToken;
|
|
27
|
+
const defaultCallback = async () => {
|
|
28
|
+
const data = {
|
|
29
|
+
...this.baseInfo,
|
|
30
|
+
type: this.type,
|
|
31
|
+
metadata: {
|
|
32
|
+
...this.metadataInfo,
|
|
33
|
+
description: this.getDescription()
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const poolInfo = await this.getPoolInfo();
|
|
37
|
+
!poolInfo && callback(data);
|
|
38
|
+
};
|
|
39
|
+
if (!this.isActive) {
|
|
40
|
+
await defaultCallback();
|
|
41
|
+
return () => {
|
|
42
|
+
cancel = true;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
await defaultCallback();
|
|
46
|
+
await substrateApi.isReady;
|
|
47
|
+
const unsub = await substrateApi.api.query.collatorStaking.currentSession(async _session => {
|
|
48
|
+
if (cancel) {
|
|
49
|
+
unsub();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const currentSession = _session.toString();
|
|
53
|
+
const maxStakers = substrateApi.api.consts.collatorStaking.maxStakers.toString();
|
|
54
|
+
const unstakeDelay = substrateApi.api.consts.collatorStaking.stakeUnlockDelay.toString();
|
|
55
|
+
const maxStakedCandidates = substrateApi.api.consts.collatorStaking.maxStakedCandidates.toString();
|
|
56
|
+
const sessionTime = _STAKING_ERA_LENGTH_MAP[this.chain] || _STAKING_ERA_LENGTH_MAP.default; // in hours
|
|
57
|
+
const blockTime = _EXPECTED_BLOCK_TIME[this.chain];
|
|
58
|
+
const unstakingPeriod = parseInt(unstakeDelay) * blockTime / 60 / 60;
|
|
59
|
+
const _minStake = await substrateApi.api.query.collatorStaking.minStake();
|
|
60
|
+
const minStake = _minStake.toString();
|
|
61
|
+
const minStakeToHuman = formatNumber(minStake, nativeToken.decimals || 0, balanceFormatter);
|
|
62
|
+
const data = {
|
|
63
|
+
...this.baseInfo,
|
|
64
|
+
type: this.type,
|
|
65
|
+
metadata: {
|
|
66
|
+
...this.metadataInfo,
|
|
67
|
+
description: this.getDescription(minStakeToHuman)
|
|
68
|
+
},
|
|
69
|
+
statistic: {
|
|
70
|
+
assetEarning: [{
|
|
71
|
+
slug: this.nativeToken.slug
|
|
72
|
+
}],
|
|
73
|
+
maxCandidatePerFarmer: parseInt(maxStakedCandidates),
|
|
74
|
+
maxWithdrawalRequestPerFarmer: 3,
|
|
75
|
+
earningThreshold: {
|
|
76
|
+
join: minStake,
|
|
77
|
+
defaultUnstake: '0',
|
|
78
|
+
fastUnstake: '0'
|
|
79
|
+
},
|
|
80
|
+
era: parseInt(currentSession),
|
|
81
|
+
eraTime: sessionTime,
|
|
82
|
+
unstakingPeriod: unstakingPeriod,
|
|
83
|
+
totalApy: undefined
|
|
84
|
+
// tvl: totalStake.toString(),
|
|
85
|
+
// inflation
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
maxPoolMembers: parseInt(maxStakers)
|
|
89
|
+
};
|
|
90
|
+
callback(data);
|
|
91
|
+
});
|
|
92
|
+
return () => {
|
|
93
|
+
cancel = true;
|
|
94
|
+
unsub();
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Subscribe pool info */
|
|
99
|
+
|
|
100
|
+
/* Subscribe pool position */
|
|
101
|
+
|
|
102
|
+
async subscribePoolPosition(useAddresses, resultCallback) {
|
|
103
|
+
let cancel = false;
|
|
104
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
105
|
+
const defaultInfo = this.baseInfo;
|
|
106
|
+
const unsub = await substrateApi.api.query.collatorStaking.userStake.multi(useAddresses, async userStakes => {
|
|
107
|
+
if (cancel) {
|
|
108
|
+
unsub();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (userStakes) {
|
|
112
|
+
await Promise.all(userStakes.map(async (_userStake, i) => {
|
|
113
|
+
const userStake = _userStake.toPrimitive();
|
|
114
|
+
const owner = reformatAddress(useAddresses[i], 42);
|
|
115
|
+
if (userStake) {
|
|
116
|
+
const nominatorMetadata = await this.parseCollatorMetadata(this.chainInfo, useAddresses[i], substrateApi, userStake);
|
|
117
|
+
resultCallback({
|
|
118
|
+
...defaultInfo,
|
|
119
|
+
...nominatorMetadata,
|
|
120
|
+
address: owner,
|
|
121
|
+
type: this.type
|
|
122
|
+
});
|
|
123
|
+
} else {
|
|
124
|
+
resultCallback({
|
|
125
|
+
...defaultInfo,
|
|
126
|
+
type: this.type,
|
|
127
|
+
address: owner,
|
|
128
|
+
balanceToken: this.nativeToken.slug,
|
|
129
|
+
totalStake: '0',
|
|
130
|
+
activeStake: '0',
|
|
131
|
+
unstakeBalance: '0',
|
|
132
|
+
status: EarningStatus.NOT_STAKING,
|
|
133
|
+
isBondedBefore: false,
|
|
134
|
+
nominations: [],
|
|
135
|
+
unstakings: []
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return () => {
|
|
142
|
+
cancel = true;
|
|
143
|
+
unsub();
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async parseCollatorMetadata(chainInfo, stakerAddress, substrateApi, userStake) {
|
|
147
|
+
const nominationList = [];
|
|
148
|
+
const unstakingList = [];
|
|
149
|
+
let unstakingBalance = BigInt(0);
|
|
150
|
+
const {
|
|
151
|
+
candidates,
|
|
152
|
+
stake
|
|
153
|
+
} = userStake;
|
|
154
|
+
const [_minStake, _unstaking, _currentBlock, _currentTimestamp] = await Promise.all([substrateApi.api.query.collatorStaking.minStake(), substrateApi.api.query.collatorStaking.releaseQueues(stakerAddress), substrateApi.api.query.system.number(), substrateApi.api.query.timestamp.now()]);
|
|
155
|
+
const minStake = _minStake.toPrimitive();
|
|
156
|
+
const stakingStatus = candidates && !!candidates.length ? EarningStatus.EARNING_REWARD : EarningStatus.NOT_EARNING;
|
|
157
|
+
const isBondedBefore = candidates && !!candidates.length;
|
|
158
|
+
const unstakings = _unstaking.toPrimitive();
|
|
159
|
+
const currentBlock = _currentBlock.toPrimitive();
|
|
160
|
+
const currentTimestamp = _currentTimestamp.toPrimitive();
|
|
161
|
+
const blockDuration = _EXPECTED_BLOCK_TIME[chainInfo.slug];
|
|
162
|
+
if (candidates.length) {
|
|
163
|
+
await Promise.all(candidates.map(async collatorAddress => {
|
|
164
|
+
const _stakeInfo = await substrateApi.api.query.collatorStaking.candidateStake(collatorAddress, stakerAddress);
|
|
165
|
+
const stakeInfo = _stakeInfo.toPrimitive();
|
|
166
|
+
const activeStake = stakeInfo.stake.toString();
|
|
167
|
+
const earningStatus = BigInt(activeStake) > BigInt(0) && BigInt(activeStake) >= BigInt(minStake) ? EarningStatus.EARNING_REWARD : EarningStatus.NOT_EARNING;
|
|
168
|
+
nominationList.push({
|
|
169
|
+
status: earningStatus,
|
|
170
|
+
chain: chainInfo.slug,
|
|
171
|
+
validatorAddress: collatorAddress,
|
|
172
|
+
activeStake,
|
|
173
|
+
validatorMinStake: minStake,
|
|
174
|
+
hasUnstaking: !!unstakings.length
|
|
175
|
+
});
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
if (unstakings.length) {
|
|
179
|
+
unstakings.forEach(unstaking => {
|
|
180
|
+
const releaseBlock = unstaking.block;
|
|
181
|
+
const unstakeAmount = unstaking.amount;
|
|
182
|
+
const isClaimable = currentBlock >= releaseBlock;
|
|
183
|
+
const targetTimestampMs = (releaseBlock - currentBlock) * blockDuration * 1000 + currentTimestamp;
|
|
184
|
+
unstakingBalance = unstakingBalance + BigInt(unstakeAmount);
|
|
185
|
+
unstakingList.push({
|
|
186
|
+
chain: chainInfo.slug,
|
|
187
|
+
status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
|
|
188
|
+
claimable: unstakeAmount,
|
|
189
|
+
targetTimestampMs
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
status: stakingStatus,
|
|
195
|
+
balanceToken: this.nativeToken.slug,
|
|
196
|
+
totalStake: (BigInt(stake) + unstakingBalance).toString(),
|
|
197
|
+
activeStake: stake,
|
|
198
|
+
unstakeBalance: unstakingBalance.toString() || '0',
|
|
199
|
+
isBondedBefore: isBondedBefore,
|
|
200
|
+
nominations: nominationList,
|
|
201
|
+
unstakings: unstakingList
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Subscribe pool position */
|
|
206
|
+
|
|
207
|
+
/* Get pool targets */
|
|
208
|
+
|
|
209
|
+
async getPoolTargets() {
|
|
210
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
211
|
+
const [_allCollators, _minStake, _commission] = await Promise.all([substrateApi.api.query.collatorStaking.candidates.entries(), substrateApi.api.query.collatorStaking.minStake(), substrateApi.api.query.collatorStaking.collatorRewardPercentage()]);
|
|
212
|
+
const maxStakersPerCollator = substrateApi.api.consts.collatorStaking.maxStakers.toPrimitive();
|
|
213
|
+
return _allCollators.map(_collator => {
|
|
214
|
+
const _collatorAddress = _collator[0].toHuman();
|
|
215
|
+
const collatorAddress = _collatorAddress[0];
|
|
216
|
+
const collatorInfo = _collator[1].toPrimitive();
|
|
217
|
+
const bnTotalStake = BigInt(collatorInfo.stake);
|
|
218
|
+
const numOfStakers = parseInt(collatorInfo.stakers);
|
|
219
|
+
const isCrowded = numOfStakers >= maxStakersPerCollator;
|
|
220
|
+
return {
|
|
221
|
+
address: collatorAddress,
|
|
222
|
+
chain: this.chain,
|
|
223
|
+
totalStake: bnTotalStake.toString(),
|
|
224
|
+
ownStake: '0',
|
|
225
|
+
otherStake: bnTotalStake.toString(),
|
|
226
|
+
minBond: _minStake.toPrimitive(),
|
|
227
|
+
nominatorCount: numOfStakers,
|
|
228
|
+
commission: getCommission(_commission.toString()),
|
|
229
|
+
blocked: false,
|
|
230
|
+
isVerified: false,
|
|
231
|
+
isCrowded
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Get pool targets */
|
|
237
|
+
|
|
238
|
+
/* Join pool action */
|
|
239
|
+
|
|
240
|
+
async createJoinExtrinsic(data, positionInfo) {
|
|
241
|
+
var _substrateApi$api$cal, _substrateApi$api$cal2;
|
|
242
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
243
|
+
const {
|
|
244
|
+
address,
|
|
245
|
+
amount,
|
|
246
|
+
selectedValidators
|
|
247
|
+
} = data;
|
|
248
|
+
const selectedValidatorInfo = selectedValidators[0];
|
|
249
|
+
const _hasReward = await ((_substrateApi$api$cal = substrateApi.api.call) === null || _substrateApi$api$cal === void 0 ? void 0 : (_substrateApi$api$cal2 = _substrateApi$api$cal.collatorStakingApi) === null || _substrateApi$api$cal2 === void 0 ? void 0 : _substrateApi$api$cal2.shouldClaim(address));
|
|
250
|
+
const hasReward = _hasReward === null || _hasReward === void 0 ? void 0 : _hasReward.toPrimitive();
|
|
251
|
+
const extrinsicList = [];
|
|
252
|
+
if (positionInfo !== null && positionInfo !== void 0 && positionInfo.isBondedBefore && hasReward) {
|
|
253
|
+
extrinsicList.push(substrateApi.api.tx.collatorStaking.claimRewards());
|
|
254
|
+
}
|
|
255
|
+
extrinsicList.push(...[substrateApi.api.tx.collatorStaking.lock(amount), substrateApi.api.tx.collatorStaking.stake([{
|
|
256
|
+
candidate: selectedValidatorInfo.address,
|
|
257
|
+
stake: amount
|
|
258
|
+
}])]);
|
|
259
|
+
return [substrateApi.api.tx.utility.batchAll(extrinsicList), {
|
|
260
|
+
slug: this.nativeToken.slug,
|
|
261
|
+
amount: '0'
|
|
262
|
+
}];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* Join pool action */
|
|
266
|
+
|
|
267
|
+
/* Leave pool action */
|
|
268
|
+
|
|
269
|
+
async handleYieldUnstake(amount, address, selectedTarget) {
|
|
270
|
+
var _substrateApi$api$cal3, _substrateApi$api$cal4;
|
|
271
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
272
|
+
const _hasReward = await ((_substrateApi$api$cal3 = substrateApi.api.call) === null || _substrateApi$api$cal3 === void 0 ? void 0 : (_substrateApi$api$cal4 = _substrateApi$api$cal3.collatorStakingApi) === null || _substrateApi$api$cal4 === void 0 ? void 0 : _substrateApi$api$cal4.shouldClaim(address));
|
|
273
|
+
const hasReward = _hasReward === null || _hasReward === void 0 ? void 0 : _hasReward.toPrimitive();
|
|
274
|
+
const extrinsicList = [];
|
|
275
|
+
if (hasReward) {
|
|
276
|
+
extrinsicList.push(substrateApi.api.tx.collatorStaking.claimRewards());
|
|
277
|
+
}
|
|
278
|
+
extrinsicList.push(...[substrateApi.api.tx.collatorStaking.unstakeFrom(selectedTarget), substrateApi.api.tx.collatorStaking.unlock(null) // ignore amount to unlock all
|
|
279
|
+
]);
|
|
280
|
+
|
|
281
|
+
return [ExtrinsicType.STAKING_UNBOND, substrateApi.api.tx.utility.batchAll(extrinsicList)];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* Leave pool action */
|
|
285
|
+
|
|
286
|
+
/* Get pool reward */
|
|
287
|
+
async getPoolReward(useAddresses, callback) {
|
|
288
|
+
let cancel = false;
|
|
289
|
+
const substrateApi = this.substrateApi;
|
|
290
|
+
await substrateApi.isReady;
|
|
291
|
+
if (substrateApi.api.call.collatorStakingApi) {
|
|
292
|
+
await Promise.all(useAddresses.map(async address => {
|
|
293
|
+
if (!cancel) {
|
|
294
|
+
const _unclaimedReward = await substrateApi.api.call.collatorStakingApi.totalRewards(address);
|
|
295
|
+
const earningRewardItem = {
|
|
296
|
+
...this.baseInfo,
|
|
297
|
+
address: address,
|
|
298
|
+
type: this.type,
|
|
299
|
+
unclaimedReward: (_unclaimedReward === null || _unclaimedReward === void 0 ? void 0 : _unclaimedReward.toString()) || '0',
|
|
300
|
+
state: APIItemState.READY
|
|
301
|
+
};
|
|
302
|
+
if (_unclaimedReward.toString() !== '0') {
|
|
303
|
+
await this.createClaimNotification(earningRewardItem, this.nativeToken);
|
|
304
|
+
}
|
|
305
|
+
callback(earningRewardItem);
|
|
306
|
+
}
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
return () => {
|
|
310
|
+
cancel = false;
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
/* Get pool reward */
|
|
314
|
+
|
|
315
|
+
/* Other action */
|
|
316
|
+
|
|
317
|
+
async handleYieldCancelUnstake() {
|
|
318
|
+
return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
|
|
319
|
+
}
|
|
320
|
+
async handleYieldWithdraw(address, unstakingInfo) {
|
|
321
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
322
|
+
return substrateApi.api.tx.collatorStaking.release();
|
|
323
|
+
}
|
|
324
|
+
async handleYieldClaimReward(address, bondReward) {
|
|
325
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
326
|
+
return substrateApi.api.tx.collatorStaking.claimRewards();
|
|
327
|
+
}
|
|
328
|
+
/* Other action */
|
|
329
|
+
}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
5
5
|
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
6
|
-
import { ALL_ACCOUNT_KEY, XCM_FEE_RATIO } from '@subwallet/extension-base/constants';
|
|
6
|
+
import { ALL_ACCOUNT_KEY, XCM_FEE_RATIO, XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
|
|
7
7
|
import { YIELD_POOL_STAT_REFRESH_INTERVAL } from '@subwallet/extension-base/koni/api/yield/helper/utils';
|
|
8
8
|
import { createXcmExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
|
|
9
|
-
import { _getAssetDecimals, _getAssetExistentialDeposit, _getAssetName, _getAssetSymbol, _getChainNativeTokenSlug } from '@subwallet/extension-base/services/chain-service/utils';
|
|
9
|
+
import { _getAssetDecimals, _getAssetExistentialDeposit, _getAssetName, _getAssetSymbol, _getChainNativeTokenSlug, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
10
10
|
import { BasicTxErrorType, YieldStepType, YieldValidationStatus } from '@subwallet/extension-base/types';
|
|
11
11
|
import { createPromiseHandler, formatNumber } from '@subwallet/extension-base/utils';
|
|
12
12
|
import { getId } from '@subwallet/extension-base/utils/getId';
|
|
@@ -216,15 +216,6 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
|
|
|
216
216
|
const altChainInfo = this.state.getChainInfo(altInputTokenInfo.originChain);
|
|
217
217
|
const symbol = altInputTokenInfo.symbol;
|
|
218
218
|
const networkName = altChainInfo.name;
|
|
219
|
-
const step = {
|
|
220
|
-
metadata: {
|
|
221
|
-
sendingValue: bnAmount.toString(),
|
|
222
|
-
originTokenInfo: altInputTokenInfo,
|
|
223
|
-
destinationTokenInfo: inputTokenInfo
|
|
224
|
-
},
|
|
225
|
-
name: `Transfer ${symbol} from ${networkName}`,
|
|
226
|
-
type: YieldStepType.XCM
|
|
227
|
-
};
|
|
228
219
|
const xcmOriginSubstrateApi = await this.state.getSubstrateApi(altInputTokenInfo.originChain).isReady;
|
|
229
220
|
const id = getId();
|
|
230
221
|
const feeInfo = await this.state.feeService.subscribeChainFee(id, altChainInfo.slug, 'substrate');
|
|
@@ -245,9 +236,24 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
|
|
|
245
236
|
|
|
246
237
|
const fee = {
|
|
247
238
|
slug: altInputTokenSlug,
|
|
248
|
-
amount: Math.round(xcmFeeInfo.partialFee *
|
|
239
|
+
amount: Math.round(xcmFeeInfo.partialFee * XCM_MIN_AMOUNT_RATIO).toString() // TODO
|
|
249
240
|
};
|
|
250
241
|
|
|
242
|
+
let bnTransferAmount = bnAmount.sub(bnInputTokenBalance);
|
|
243
|
+
if (_isNativeToken(altInputTokenInfo)) {
|
|
244
|
+
const bnXcmFee = new BN(fee.amount || 0); // xcm fee is paid in native token but swap token is not always native token
|
|
245
|
+
|
|
246
|
+
bnTransferAmount = bnTransferAmount.add(bnXcmFee);
|
|
247
|
+
}
|
|
248
|
+
const step = {
|
|
249
|
+
metadata: {
|
|
250
|
+
sendingValue: bnTransferAmount.toString(),
|
|
251
|
+
originTokenInfo: altInputTokenInfo,
|
|
252
|
+
destinationTokenInfo: inputTokenInfo
|
|
253
|
+
},
|
|
254
|
+
name: `Transfer ${symbol} from ${networkName}`,
|
|
255
|
+
type: YieldStepType.XCM
|
|
256
|
+
};
|
|
251
257
|
return [step, fee];
|
|
252
258
|
}
|
|
253
259
|
}
|
|
@@ -8,6 +8,7 @@ import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
|
|
|
8
8
|
import { _isChainEnabled, _isChainEvmCompatible } 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 BaseLiquidStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/liquid-staking/base';
|
|
11
|
+
import MythosNativeStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/mythos';
|
|
11
12
|
import { BasicTxErrorType, YieldPoolType } from '@subwallet/extension-base/types';
|
|
12
13
|
import { addLazy, categoryAddresses, createPromiseHandler, removeLazy } from '@subwallet/extension-base/utils';
|
|
13
14
|
import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache';
|
|
@@ -68,6 +69,9 @@ export default class EarningService {
|
|
|
68
69
|
if (_STAKING_CHAIN_GROUP.bittensor.includes(chain)) {
|
|
69
70
|
handlers.push(new TaoNativeStakingPoolHandler(this.state, chain));
|
|
70
71
|
}
|
|
72
|
+
if (_STAKING_CHAIN_GROUP.mythos.includes(chain)) {
|
|
73
|
+
handlers.push(new MythosNativeStakingPoolHandler(this.state, chain));
|
|
74
|
+
}
|
|
71
75
|
if (_STAKING_CHAIN_GROUP.nominationPool.includes(chain)) {
|
|
72
76
|
handlers.push(new NominationPoolHandler(this.state, chain));
|
|
73
77
|
}
|
|
@@ -105,6 +105,8 @@ export function isActionFromValidator(stakingType, chain) {
|
|
|
105
105
|
return true;
|
|
106
106
|
} else if (_STAKING_CHAIN_GROUP.bittensor.includes(chain)) {
|
|
107
107
|
return true;
|
|
108
|
+
} else if (_STAKING_CHAIN_GROUP.mythos.includes(chain)) {
|
|
109
|
+
return true;
|
|
108
110
|
}
|
|
109
111
|
return false;
|
|
110
112
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import { isSameAddress } from '@subwallet/extension-base/utils';
|
|
5
|
+
import { isHex } from '@polkadot/util';
|
|
5
6
|
export let HistoryRecoverStatus;
|
|
6
7
|
(function (HistoryRecoverStatus) {
|
|
7
8
|
HistoryRecoverStatus["SUCCESS"] = "SUCCESS";
|
|
@@ -31,7 +32,7 @@ const substrateRecover = async (history, chainService) => {
|
|
|
31
32
|
const _api = await substrateApi.isReady;
|
|
32
33
|
const api = _api.api;
|
|
33
34
|
if (!blockHash) {
|
|
34
|
-
if (
|
|
35
|
+
if (nonce === undefined || startBlock === undefined) {
|
|
35
36
|
console.log(`Fail to find extrinsic for ${address} on ${chain}: With nonce ${nonce || 'undefined'} from block ${startBlock || 'undefined'}`);
|
|
36
37
|
return {
|
|
37
38
|
status: HistoryRecoverStatus.LACK_INFO
|
|
@@ -41,7 +42,7 @@ const substrateRecover = async (history, chainService) => {
|
|
|
41
42
|
for (let i = 1, found = false; i < BLOCK_LIMIT && !found && startBlock + i <= currentBlock; i++) {
|
|
42
43
|
const blockHash = (await api.rpc.chain.getBlockHash(startBlock + i)).toHex();
|
|
43
44
|
const block = await api.rpc.chain.getBlock(blockHash);
|
|
44
|
-
const extrinsics = block.block.extrinsics;
|
|
45
|
+
const extrinsics = block.block.extrinsics.toArray();
|
|
45
46
|
let index;
|
|
46
47
|
for (const [idx, extrinsic] of Object.entries(extrinsics)) {
|
|
47
48
|
if (extrinsic.signer && isSameAddress(from, extrinsic.signer.toString()) && nonce === extrinsic.nonce.toNumber()) {
|
|
@@ -142,16 +143,24 @@ const evmRecover = async (history, chainService) => {
|
|
|
142
143
|
try {
|
|
143
144
|
const evmApi = chainService.getEvmApi(chain);
|
|
144
145
|
if (evmApi) {
|
|
145
|
-
const _api = await evmApi.isReady
|
|
146
|
+
const _api = await Promise.race([evmApi.isReady, new Promise((resolve, reject) => {
|
|
147
|
+
const createTimeout = callback => {
|
|
148
|
+
setTimeout(callback, 10000);
|
|
149
|
+
};
|
|
150
|
+
createTimeout(() => {
|
|
151
|
+
const api = chainService.getEvmApi(chain);
|
|
152
|
+
Promise.race([api.isReady, new Promise((resolve, reject) => createTimeout(() => reject(new Error('Timeout'))))]).then(resolve).catch(reject);
|
|
153
|
+
});
|
|
154
|
+
})]);
|
|
146
155
|
const api = _api.api;
|
|
147
|
-
if (extrinsicHash) {
|
|
156
|
+
if (extrinsicHash && isHex(extrinsicHash)) {
|
|
148
157
|
const transactionReceipt = await api.eth.getTransactionReceipt(extrinsicHash);
|
|
149
158
|
return {
|
|
150
159
|
...result,
|
|
151
160
|
status: transactionReceipt.status ? HistoryRecoverStatus.SUCCESS : HistoryRecoverStatus.FAILED
|
|
152
161
|
};
|
|
153
162
|
} else {
|
|
154
|
-
if (
|
|
163
|
+
if (nonce === undefined || startBlock === undefined) {
|
|
155
164
|
console.log(`Fail to find extrinsic for ${address} on ${chain}: With nonce ${nonce || 'undefined'} from block ${startBlock || 'undefined'}`);
|
|
156
165
|
return {
|
|
157
166
|
...result,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
|
|
1
|
+
import { ExtrinsicType, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
|
|
2
2
|
import { PersistDataServiceInterface, ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
|
|
3
3
|
import { ChainService } from '@subwallet/extension-base/services/chain-service';
|
|
4
4
|
import { EventService } from '@subwallet/extension-base/services/event-service';
|
|
@@ -18,18 +18,18 @@ export declare class HistoryService implements StoppableServiceInterface, Persis
|
|
|
18
18
|
private fetchPromise;
|
|
19
19
|
private recoverInterval;
|
|
20
20
|
private fetchAndLoadHistories;
|
|
21
|
-
getHistories(): Promise<TransactionHistoryItem<
|
|
22
|
-
getHistorySubject(): Promise<BehaviorSubject<TransactionHistoryItem<
|
|
21
|
+
getHistories(): Promise<TransactionHistoryItem<ExtrinsicType.TRANSFER_BALANCE>[]>;
|
|
22
|
+
getHistorySubject(): Promise<BehaviorSubject<TransactionHistoryItem<ExtrinsicType.TRANSFER_BALANCE>[]>>;
|
|
23
23
|
/**
|
|
24
24
|
* @todo: Must improve performance of this function
|
|
25
25
|
* */
|
|
26
26
|
private fetchSubscanTransactionHistory;
|
|
27
27
|
subscribeHistories(chain: string, proxyId: string, cb: (items: TransactionHistoryItem[]) => void): {
|
|
28
28
|
unsubscribe: () => void;
|
|
29
|
-
value: TransactionHistoryItem<
|
|
29
|
+
value: TransactionHistoryItem<ExtrinsicType.TRANSFER_BALANCE>[];
|
|
30
30
|
};
|
|
31
31
|
updateHistories(chain: string, extrinsicHash: string, updateData: Partial<TransactionHistoryItem>): Promise<void>;
|
|
32
|
-
updateHistoryByExtrinsicHash(extrinsicHash: string, updateData: Partial<TransactionHistoryItem
|
|
32
|
+
updateHistoryByExtrinsicHash(extrinsicHash: string, updateData: Partial<TransactionHistoryItem>, isRecover?: boolean): Promise<void>;
|
|
33
33
|
insertHistories(historyItems: TransactionHistoryItem[]): Promise<void>;
|
|
34
34
|
addHistoryItems(historyItems: TransactionHistoryItem[]): Promise<void>;
|
|
35
35
|
removeHistoryByAddress(address: string): Promise<void>;
|
|
@@ -45,6 +45,7 @@ export declare class HistoryService implements StoppableServiceInterface, Persis
|
|
|
45
45
|
promise: Promise<void>;
|
|
46
46
|
};
|
|
47
47
|
init(): Promise<void>;
|
|
48
|
+
restoreProcessTransaction(): Promise<void>;
|
|
48
49
|
recoverProcessingHistory(): Promise<void>;
|
|
49
50
|
start(): Promise<void>;
|
|
50
51
|
waitForStarted(): Promise<void>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
import { ExtrinsicStatus } from '@subwallet/extension-base/background/KoniTypes';
|
|
4
|
+
import { ExtrinsicStatus, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
5
5
|
import { CRON_RECOVER_HISTORY_INTERVAL } from '@subwallet/extension-base/constants';
|
|
6
6
|
import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
|
|
7
7
|
import { _isChainEvmCompatible, _isChainSubstrateCompatible } from '@subwallet/extension-base/services/chain-service/utils';
|
|
@@ -177,8 +177,8 @@ export class HistoryService {
|
|
|
177
177
|
});
|
|
178
178
|
await this.addHistoryItems(updatedRecords);
|
|
179
179
|
}
|
|
180
|
-
async updateHistoryByExtrinsicHash(extrinsicHash, updateData) {
|
|
181
|
-
await this.dbService.updateHistoryByExtrinsicHash(extrinsicHash, updateData);
|
|
180
|
+
async updateHistoryByExtrinsicHash(extrinsicHash, updateData, isRecover = false) {
|
|
181
|
+
await this.dbService.updateHistoryByExtrinsicHash(extrinsicHash, updateData, isRecover);
|
|
182
182
|
this.historySubject.next(await this.dbService.getHistories());
|
|
183
183
|
}
|
|
184
184
|
|
|
@@ -253,11 +253,11 @@ export class HistoryService {
|
|
|
253
253
|
case HistoryRecoverStatus.FAILED:
|
|
254
254
|
case HistoryRecoverStatus.SUCCESS:
|
|
255
255
|
updateData.status = recoverResult.status === HistoryRecoverStatus.SUCCESS ? ExtrinsicStatus.SUCCESS : ExtrinsicStatus.FAIL;
|
|
256
|
-
this.updateHistoryByExtrinsicHash(currentExtrinsicHash, updateData).catch(console.error);
|
|
256
|
+
this.updateHistoryByExtrinsicHash(currentExtrinsicHash, updateData, true).catch(console.error);
|
|
257
257
|
delete this.#needRecoveryHistories[currentExtrinsicHash];
|
|
258
258
|
break;
|
|
259
259
|
default:
|
|
260
|
-
this.updateHistoryByExtrinsicHash(currentExtrinsicHash, updateData).catch(console.error);
|
|
260
|
+
this.updateHistoryByExtrinsicHash(currentExtrinsicHash, updateData, true).catch(console.error);
|
|
261
261
|
delete this.#needRecoveryHistories[currentExtrinsicHash];
|
|
262
262
|
}
|
|
263
263
|
});
|
|
@@ -269,6 +269,7 @@ export class HistoryService {
|
|
|
269
269
|
async init() {
|
|
270
270
|
this.status = ServiceStatus.INITIALIZING;
|
|
271
271
|
await this.eventService.waitCryptoReady;
|
|
272
|
+
this.restoreProcessTransaction().catch(console.error);
|
|
272
273
|
await this.loadData();
|
|
273
274
|
Promise.all([this.eventService.waitKeyringReady, this.eventService.waitChainReady]).then(() => {
|
|
274
275
|
this.getHistories().catch(console.log);
|
|
@@ -279,11 +280,21 @@ export class HistoryService {
|
|
|
279
280
|
}).catch(console.error);
|
|
280
281
|
this.status = ServiceStatus.INITIALIZED;
|
|
281
282
|
}
|
|
283
|
+
async restoreProcessTransaction() {
|
|
284
|
+
await this.dbService.restoreProcessTransaction();
|
|
285
|
+
}
|
|
282
286
|
async recoverProcessingHistory() {
|
|
283
287
|
const histories = await this.dbService.getHistories();
|
|
284
288
|
this.#needRecoveryHistories = {};
|
|
285
289
|
histories.filter(history => {
|
|
286
290
|
return [ExtrinsicStatus.PROCESSING, ExtrinsicStatus.SUBMITTING].includes(history.status);
|
|
291
|
+
}).filter(history => {
|
|
292
|
+
if (history.type === ExtrinsicType.TRANSFER_XCM) {
|
|
293
|
+
const data = history.additionalInfo;
|
|
294
|
+
return data.originalChain === history.chain;
|
|
295
|
+
} else {
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
287
298
|
}).forEach(history => {
|
|
288
299
|
this.#needRecoveryHistories[history.extrinsicHash] = history;
|
|
289
300
|
});
|
|
@@ -6,6 +6,7 @@ import { _BaseNotificationInfo, _NotificationInfo, NotificationActionType } from
|
|
|
6
6
|
import { AvailBridgeTransaction, PolygonTransaction } from '@subwallet/extension-base/services/inapp-notification-service/utils';
|
|
7
7
|
import { KeyringService } from '@subwallet/extension-base/services/keyring-service';
|
|
8
8
|
import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
|
|
9
|
+
import { ProcessTransactionData } from '@subwallet/extension-base/types';
|
|
9
10
|
import { GetNotificationParams, RequestSwitchStatusParams } from '@subwallet/extension-base/types/notification';
|
|
10
11
|
export declare class InappNotificationService implements CronServiceInterface {
|
|
11
12
|
private readonly dbService;
|
|
@@ -36,6 +37,7 @@ export declare class InappNotificationService implements CronServiceInterface {
|
|
|
36
37
|
processWriteAvailBridgeClaim(address: string, transactions: AvailBridgeTransaction[], token: _ChainAsset): Promise<void>;
|
|
37
38
|
createPolygonClaimableTransactions(): Promise<void>;
|
|
38
39
|
processPolygonClaimNotification(address: string, transactions: PolygonTransaction[], token: _ChainAsset): Promise<void>;
|
|
40
|
+
createProcessNotification(process: ProcessTransactionData): Promise<void>;
|
|
39
41
|
start(): Promise<void>;
|
|
40
42
|
startCron(): Promise<void>;
|
|
41
43
|
stop(): Promise<void>;
|