@subwallet/extension-base 1.3.62-0 → 1.3.63-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/transfer/smart-contract.js +14 -10
- package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +0 -6
- package/cjs/services/balance-service/transfer/xcm/utils.js +2 -0
- package/cjs/services/chain-service/constants.js +16 -0
- package/cjs/services/chain-service/utils/index.js +24 -4
- 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/native-staking/base-para.js +6 -3
- package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +4 -1
- package/cjs/services/earning-service/handlers/native-staking/tanssi.js +496 -0
- package/cjs/services/earning-service/service.js +4 -0
- package/cjs/services/earning-service/utils/index.js +2 -0
- package/cjs/services/swap-service/handler/base-handler.js +4 -1
- package/cjs/services/swap-service/handler/chainflip-handler.js +1 -17
- package/cjs/services/swap-service/handler/optimex-handler.js +421 -0
- package/cjs/services/swap-service/handler/simpleswap-handler.js +4 -2
- package/cjs/services/swap-service/index.js +38 -140
- package/cjs/services/swap-service/utils.js +16 -157
- package/cjs/services/transaction-service/helpers/index.js +2 -1
- package/cjs/types/service-base.js +0 -1
- package/cjs/types/swap/index.js +5 -8
- package/cjs/utils/account/common.js +1 -2
- package/package.json +16 -6
- package/packageInfo.js +1 -1
- package/services/balance-service/transfer/smart-contract.d.ts +3 -2
- package/services/balance-service/transfer/smart-contract.js +35 -29
- package/services/balance-service/transfer/xcm/acrossBridge/index.d.ts +0 -4
- package/services/balance-service/transfer/xcm/acrossBridge/index.js +0 -4
- package/services/balance-service/transfer/xcm/utils.js +2 -0
- package/services/chain-service/constants.js +16 -0
- package/services/chain-service/utils/index.d.ts +3 -2
- package/services/chain-service/utils/index.js +20 -1
- package/services/chain-service/utils/patch.d.ts +1 -1
- 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/native-staking/base-para.js +6 -3
- package/services/earning-service/handlers/native-staking/relay-chain.js +4 -1
- package/services/earning-service/handlers/native-staking/tanssi.d.ts +16 -0
- package/services/earning-service/handlers/native-staking/tanssi.js +478 -0
- package/services/earning-service/service.js +4 -0
- package/services/earning-service/utils/index.js +2 -0
- package/services/swap-service/handler/base-handler.js +6 -3
- package/services/swap-service/handler/chainflip-handler.d.ts +0 -2
- package/services/swap-service/handler/chainflip-handler.js +2 -18
- package/services/swap-service/handler/optimex-handler.d.ts +43 -0
- package/services/swap-service/handler/optimex-handler.js +410 -0
- package/services/swap-service/handler/simpleswap-handler.js +5 -3
- package/services/swap-service/index.d.ts +0 -1
- package/services/swap-service/index.js +21 -123
- package/services/swap-service/utils.d.ts +6 -12
- package/services/swap-service/utils.js +8 -138
- package/services/transaction-service/helpers/index.js +2 -1
- package/types/service-base.d.ts +3 -4
- package/types/service-base.js +0 -2
- package/types/swap/index.d.ts +3 -1
- package/types/swap/index.js +7 -6
- package/types/yield/info/account/info.d.ts +5 -0
- package/utils/account/common.js +2 -3
|
@@ -0,0 +1,478 @@
|
|
|
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 { BasicTxErrorType, EarningStatus } from '@subwallet/extension-base/types';
|
|
7
|
+
import BigN from 'bignumber.js';
|
|
8
|
+
import { parseIdentity } from "../../utils/index.js";
|
|
9
|
+
import BaseParaNativeStakingPoolHandler from "./base-para.js";
|
|
10
|
+
function perbillToPercentBn(perbill) {
|
|
11
|
+
const raw = new BigN((perbill === null || perbill === void 0 ? void 0 : perbill.toString()) || '0');
|
|
12
|
+
const bnPercent = raw.multipliedBy(new BigN(100)).div(new BigN(1000000000));
|
|
13
|
+
return bnPercent.toNumber();
|
|
14
|
+
}
|
|
15
|
+
async function getOwnStakes(chainApi, candidates, delegator) {
|
|
16
|
+
const queries = [];
|
|
17
|
+
for (const candidate of candidates) {
|
|
18
|
+
// Auto-compounding
|
|
19
|
+
queries.push([candidate, {
|
|
20
|
+
AutoCompoundingShares: {
|
|
21
|
+
delegator
|
|
22
|
+
}
|
|
23
|
+
}]);
|
|
24
|
+
queries.push([candidate, 'AutoCompoundingSharesSupply']);
|
|
25
|
+
queries.push([candidate, 'AutoCompoundingSharesTotalStaked']);
|
|
26
|
+
|
|
27
|
+
// Manual rewards
|
|
28
|
+
queries.push([candidate, {
|
|
29
|
+
ManualRewardsShares: {
|
|
30
|
+
delegator
|
|
31
|
+
}
|
|
32
|
+
}]);
|
|
33
|
+
queries.push([candidate, 'ManualRewardsSharesSupply']);
|
|
34
|
+
queries.push([candidate, 'ManualRewardsSharesTotalStaked']);
|
|
35
|
+
|
|
36
|
+
// Joining
|
|
37
|
+
queries.push([candidate, {
|
|
38
|
+
JoiningShares: {
|
|
39
|
+
delegator
|
|
40
|
+
}
|
|
41
|
+
}]);
|
|
42
|
+
queries.push([candidate, 'JoiningSharesSupply']);
|
|
43
|
+
queries.push([candidate, 'JoiningSharesTotalStaked']);
|
|
44
|
+
|
|
45
|
+
// Leaving
|
|
46
|
+
queries.push([candidate, {
|
|
47
|
+
LeavingShares: {
|
|
48
|
+
delegator
|
|
49
|
+
}
|
|
50
|
+
}]);
|
|
51
|
+
queries.push([candidate, 'LeavingSharesSupply']);
|
|
52
|
+
queries.push([candidate, 'LeavingSharesTotalStaked']);
|
|
53
|
+
|
|
54
|
+
// Claimable reward
|
|
55
|
+
queries.push([candidate, 'ManualRewardsCounter']);
|
|
56
|
+
queries.push([candidate, {
|
|
57
|
+
ManualRewardsCheckpoint: {
|
|
58
|
+
delegator
|
|
59
|
+
}
|
|
60
|
+
}]);
|
|
61
|
+
}
|
|
62
|
+
const results = await chainApi.api.query.pooledStaking.pools.multi(queries);
|
|
63
|
+
const stakes = {};
|
|
64
|
+
const stride = 14;
|
|
65
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
66
|
+
const base = i * stride;
|
|
67
|
+
|
|
68
|
+
// Auto-compounding
|
|
69
|
+
const acShares = new BigN(results[base + 0].toString());
|
|
70
|
+
const acSupply = new BigN(results[base + 1].toString());
|
|
71
|
+
const acTotal = new BigN(results[base + 2].toString());
|
|
72
|
+
const autoCompounding = acSupply.isZero() ? new BigN(0) : acShares.multipliedBy(acTotal).div(acSupply);
|
|
73
|
+
|
|
74
|
+
// Manual rewards
|
|
75
|
+
const mrShares = new BigN(results[base + 3].toString());
|
|
76
|
+
const mrSupply = new BigN(results[base + 4].toString());
|
|
77
|
+
const mrTotal = new BigN(results[base + 5].toString());
|
|
78
|
+
const manualRewards = mrSupply.isZero() ? new BigN(0) : mrShares.multipliedBy(mrTotal).div(mrSupply);
|
|
79
|
+
|
|
80
|
+
// Joining
|
|
81
|
+
const jShares = new BigN(results[base + 6].toString());
|
|
82
|
+
const jSupply = new BigN(results[base + 7].toString());
|
|
83
|
+
const jTotal = new BigN(results[base + 8].toString());
|
|
84
|
+
const joining = jSupply.isZero() ? new BigN(0) : jShares.multipliedBy(jTotal).div(jSupply);
|
|
85
|
+
|
|
86
|
+
// Leaving
|
|
87
|
+
const lShares = new BigN(results[base + 9].toString());
|
|
88
|
+
const lSupply = new BigN(results[base + 10].toString());
|
|
89
|
+
const lTotal = new BigN(results[base + 11].toString());
|
|
90
|
+
const leaving = lSupply.isZero() ? new BigN(0) : lShares.multipliedBy(lTotal).div(lSupply);
|
|
91
|
+
|
|
92
|
+
// Claimable rewards
|
|
93
|
+
const counter = new BigN(results[base + 12].toString());
|
|
94
|
+
const checkpoint = new BigN(results[base + 13].toString());
|
|
95
|
+
const claimable = counter.minus(checkpoint).multipliedBy(mrShares);
|
|
96
|
+
|
|
97
|
+
// Total stake
|
|
98
|
+
const totalStake = autoCompounding.plus(manualRewards).plus(joining).plus(leaving);
|
|
99
|
+
stakes[candidates[i]] = {
|
|
100
|
+
autoCompounding: autoCompounding.toFixed(0),
|
|
101
|
+
autoCompoundingShares: acShares.toFixed(0),
|
|
102
|
+
manualRewards: manualRewards.toFixed(0),
|
|
103
|
+
joining: joining.toFixed(0),
|
|
104
|
+
leaving: leaving.toFixed(0),
|
|
105
|
+
totalStake: totalStake.toFixed(0),
|
|
106
|
+
claimable: claimable.toFixed(0)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return stakes;
|
|
110
|
+
}
|
|
111
|
+
export default class TanssiNativeStakingPoolHandler extends BaseParaNativeStakingPoolHandler {
|
|
112
|
+
availableMethod = {
|
|
113
|
+
join: true,
|
|
114
|
+
defaultUnstake: true,
|
|
115
|
+
fastUnstake: false,
|
|
116
|
+
cancelUnstake: false,
|
|
117
|
+
withdraw: false,
|
|
118
|
+
claimReward: true,
|
|
119
|
+
changeValidator: false
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/* Subscribe pool info */
|
|
123
|
+
|
|
124
|
+
async subscribePoolInfo(callback) {
|
|
125
|
+
let cancel = false;
|
|
126
|
+
const defaultCallback = async () => {
|
|
127
|
+
const api = await this.substrateApi.isReady;
|
|
128
|
+
const activeConfig = (await api.api.query.collatorConfiguration.activeConfig()).toPrimitive();
|
|
129
|
+
const maxCollators = activeConfig.maxCollators;
|
|
130
|
+
const data = {
|
|
131
|
+
...this.baseInfo,
|
|
132
|
+
type: this.type,
|
|
133
|
+
metadata: {
|
|
134
|
+
...this.metadataInfo,
|
|
135
|
+
description: this.getDescription()
|
|
136
|
+
},
|
|
137
|
+
statistic: {
|
|
138
|
+
assetEarning: [{
|
|
139
|
+
slug: this.nativeToken.slug
|
|
140
|
+
}],
|
|
141
|
+
maxCandidatePerFarmer: maxCollators,
|
|
142
|
+
maxWithdrawalRequestPerFarmer: 1,
|
|
143
|
+
earningThreshold: {
|
|
144
|
+
join: '0',
|
|
145
|
+
defaultUnstake: '0',
|
|
146
|
+
fastUnstake: '0'
|
|
147
|
+
},
|
|
148
|
+
era: 0,
|
|
149
|
+
eraTime: 6 / 3600,
|
|
150
|
+
unstakingPeriod: 12
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
if (!cancel) {
|
|
154
|
+
callback(data);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
await defaultCallback();
|
|
158
|
+
return () => {
|
|
159
|
+
cancel = true;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* Subscribe pool info */
|
|
164
|
+
|
|
165
|
+
/* Subscribe pool position */
|
|
166
|
+
|
|
167
|
+
async subscribePoolPosition(useAddresses, onUpdate) {
|
|
168
|
+
const substrateApi = this.substrateApi;
|
|
169
|
+
await substrateApi.isReady;
|
|
170
|
+
let cancel = false;
|
|
171
|
+
const intervalIds = [];
|
|
172
|
+
for (const delegator of useAddresses) {
|
|
173
|
+
const fetchAndUpdate = async () => {
|
|
174
|
+
if (cancel) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const entries = await substrateApi.api.query.pooledStaking.delegatorCandidateSummaries.entries(delegator);
|
|
178
|
+
if (!entries || entries.length === 0) {
|
|
179
|
+
onUpdate({
|
|
180
|
+
...this.baseInfo,
|
|
181
|
+
type: this.type,
|
|
182
|
+
address: delegator,
|
|
183
|
+
balanceToken: this.nativeToken.slug,
|
|
184
|
+
totalStake: '0',
|
|
185
|
+
activeStake: '0',
|
|
186
|
+
unstakeBalance: '0',
|
|
187
|
+
status: EarningStatus.NOT_STAKING,
|
|
188
|
+
isBondedBefore: false,
|
|
189
|
+
nominations: [],
|
|
190
|
+
unstakings: []
|
|
191
|
+
});
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const candidates = entries.map(([storageKey]) => storageKey.args[1].toString());
|
|
195
|
+
const ownStakesMap = await getOwnStakes(substrateApi, candidates, delegator);
|
|
196
|
+
const nominations = [];
|
|
197
|
+
let bnTotalStake = new BigN(0);
|
|
198
|
+
let bnActiveStake = new BigN(0);
|
|
199
|
+
let bnUnstakeBalance = new BigN(0);
|
|
200
|
+
let bnJoiningStake = new BigN(0);
|
|
201
|
+
let bnCompoundingStake = new BigN(0);
|
|
202
|
+
let bnManualStake = new BigN(0);
|
|
203
|
+
for (const candidate of candidates) {
|
|
204
|
+
const ownStake = ownStakesMap[candidate];
|
|
205
|
+
if (!ownStake) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const autoCompounding = new BigN(ownStake.autoCompounding);
|
|
209
|
+
const manualRewards = new BigN(ownStake.manualRewards);
|
|
210
|
+
const joining = new BigN(ownStake.joining);
|
|
211
|
+
const leaving = new BigN(ownStake.leaving);
|
|
212
|
+
const totalStake = new BigN(ownStake.totalStake);
|
|
213
|
+
if (totalStake.isZero()) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
bnTotalStake = bnTotalStake.plus(totalStake);
|
|
217
|
+
bnActiveStake = bnActiveStake.plus(autoCompounding).plus(manualRewards).plus(joining);
|
|
218
|
+
bnUnstakeBalance = bnUnstakeBalance.plus(leaving);
|
|
219
|
+
bnJoiningStake = bnJoiningStake.plus(joining);
|
|
220
|
+
bnCompoundingStake = bnCompoundingStake.plus(autoCompounding);
|
|
221
|
+
bnManualStake = bnManualStake.plus(manualRewards);
|
|
222
|
+
const [identity] = await parseIdentity(this.substrateIdentityApi, candidate);
|
|
223
|
+
nominations.push({
|
|
224
|
+
chain: this.chain,
|
|
225
|
+
status: EarningStatus.EARNING_REWARD,
|
|
226
|
+
validatorAddress: candidate,
|
|
227
|
+
validatorIdentity: identity,
|
|
228
|
+
activeStake: new BigN(autoCompounding).plus(manualRewards).toFixed(),
|
|
229
|
+
hasUnstaking: !leaving.isZero(),
|
|
230
|
+
validatorMinStake: '0'
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
onUpdate({
|
|
234
|
+
...this.baseInfo,
|
|
235
|
+
type: this.type,
|
|
236
|
+
address: delegator,
|
|
237
|
+
balanceToken: this.nativeToken.slug,
|
|
238
|
+
totalStake: bnTotalStake.toString(),
|
|
239
|
+
activeStake: bnActiveStake.toString(),
|
|
240
|
+
unstakeBalance: bnUnstakeBalance.toString(),
|
|
241
|
+
status: nominations.length > 0 ? EarningStatus.EARNING_REWARD : EarningStatus.NOT_STAKING,
|
|
242
|
+
isBondedBefore: nominations.length > 0,
|
|
243
|
+
nominations,
|
|
244
|
+
unstakings: [],
|
|
245
|
+
metadata: {
|
|
246
|
+
pendingStake: bnJoiningStake.toString(),
|
|
247
|
+
compoundingStake: bnCompoundingStake.toString(),
|
|
248
|
+
manualStake: bnManualStake.toString()
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
fetchAndUpdate().catch(console.error);
|
|
253
|
+
const intervalId = setInterval(() => {
|
|
254
|
+
fetchAndUpdate().catch(console.error);
|
|
255
|
+
}, 30000);
|
|
256
|
+
intervalIds.push(intervalId);
|
|
257
|
+
}
|
|
258
|
+
return () => {
|
|
259
|
+
cancel = true;
|
|
260
|
+
intervalIds.forEach(id => clearInterval(id));
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
async checkAccountHaveStake(addresses) {
|
|
264
|
+
const stakedAddresses = [];
|
|
265
|
+
const api = await this.substrateApi.isReady;
|
|
266
|
+
const candidateSummariesByAddress = await Promise.all(addresses.map(address => api.api.query.pooledStaking.delegatorCandidateSummaries.entries(address)));
|
|
267
|
+
for (let i = 0; i < addresses.length; i++) {
|
|
268
|
+
const candidateSummaries = candidateSummariesByAddress[i];
|
|
269
|
+
if (candidateSummaries && candidateSummaries.length > 0) {
|
|
270
|
+
stakedAddresses.push(addresses[i]);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return stakedAddresses;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* Subscribe pool position */
|
|
277
|
+
|
|
278
|
+
/* Get pool targets */
|
|
279
|
+
|
|
280
|
+
async getPoolTargets() {
|
|
281
|
+
const chainApi = await this.substrateApi.isReady;
|
|
282
|
+
const commissionRaw = chainApi.api.consts.pooledStaking.rewardsCollatorCommission.toJSON();
|
|
283
|
+
const commission = perbillToPercentBn(commissionRaw);
|
|
284
|
+
const candidates = await chainApi.api.query.pooledStaking.sortedEligibleCandidates();
|
|
285
|
+
const candidateSummaries = await chainApi.api.query.pooledStaking.candidateSummaries.entries();
|
|
286
|
+
const candidateSummariesMap = {};
|
|
287
|
+
candidateSummaries.forEach(([key, summary]) => {
|
|
288
|
+
const address = key.args[0].toString();
|
|
289
|
+
candidateSummariesMap[address] = summary.toJSON();
|
|
290
|
+
});
|
|
291
|
+
const candidateAddresses = candidates.map(c => c.candidate.toString());
|
|
292
|
+
const targets = await Promise.all(candidates.map(async c => {
|
|
293
|
+
const address = c.candidate.toString();
|
|
294
|
+
const totalStake = new BigN(c.stake.toString());
|
|
295
|
+
const candidateInfo = candidateSummariesMap[address];
|
|
296
|
+
const nominatorCount = (candidateInfo === null || candidateInfo === void 0 ? void 0 : candidateInfo.delegators) || 0;
|
|
297
|
+
const ownStakesMap = await getOwnStakes(chainApi, candidateAddresses, address);
|
|
298
|
+
const ownStakeInfo = ownStakesMap[address];
|
|
299
|
+
const ownStake = ownStakeInfo ? new BigN(ownStakeInfo.totalStake) : new BigN(0);
|
|
300
|
+
const otherStake = BigN.max(totalStake.minus(ownStake), 0);
|
|
301
|
+
const [identity, isReasonable] = await parseIdentity(this.substrateApi, address);
|
|
302
|
+
const validator = {
|
|
303
|
+
address,
|
|
304
|
+
chain: this.chain,
|
|
305
|
+
totalStake: totalStake.toFixed(),
|
|
306
|
+
ownStake: ownStake.toFixed(),
|
|
307
|
+
otherStake: otherStake.toFixed(),
|
|
308
|
+
minBond: '0',
|
|
309
|
+
nominatorCount,
|
|
310
|
+
commission,
|
|
311
|
+
blocked: false,
|
|
312
|
+
isVerified: isReasonable,
|
|
313
|
+
isCrowded: false,
|
|
314
|
+
identity
|
|
315
|
+
};
|
|
316
|
+
return validator;
|
|
317
|
+
}));
|
|
318
|
+
return targets;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* Get pool targets */
|
|
322
|
+
|
|
323
|
+
/* Join pool action */
|
|
324
|
+
|
|
325
|
+
async createJoinExtrinsic(data, positionInfo, bondDest, netuid) {
|
|
326
|
+
const {
|
|
327
|
+
amount,
|
|
328
|
+
selectedValidators
|
|
329
|
+
} = data;
|
|
330
|
+
const substrateApi = this.substrateApi;
|
|
331
|
+
const api = await substrateApi.isReady;
|
|
332
|
+
const binaryAmount = new BigN(amount);
|
|
333
|
+
const selectedCollatorInfo = selectedValidators[0];
|
|
334
|
+
const {
|
|
335
|
+
address: selectedCollatorAddress
|
|
336
|
+
} = selectedCollatorInfo;
|
|
337
|
+
const extrinsic = api.api.tx.pooledStaking.requestDelegate(selectedCollatorAddress, 'AutoCompounding',
|
|
338
|
+
// 'ManualRewards'
|
|
339
|
+
binaryAmount.toFixed());
|
|
340
|
+
return [extrinsic, {
|
|
341
|
+
slug: this.nativeToken.slug,
|
|
342
|
+
amount
|
|
343
|
+
}];
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Join pool action */
|
|
347
|
+
|
|
348
|
+
/* Leave pool action */
|
|
349
|
+
|
|
350
|
+
async handleYieldUnstake(amount, address, selectedTarget) {
|
|
351
|
+
if (!selectedTarget) {
|
|
352
|
+
return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
|
|
353
|
+
}
|
|
354
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
355
|
+
const txs = [];
|
|
356
|
+
const stakesMap = await getOwnStakes(substrateApi, [selectedTarget], address);
|
|
357
|
+
const stakeInfo = stakesMap[selectedTarget];
|
|
358
|
+
const manualRewards = new BigN(stakeInfo.manualRewards);
|
|
359
|
+
const autoCompounding = new BigN(stakeInfo.autoCompounding);
|
|
360
|
+
const unstakeAmount = new BigN(amount);
|
|
361
|
+
if (manualRewards.gt(0)) {
|
|
362
|
+
if (unstakeAmount.lte(manualRewards)) {
|
|
363
|
+
txs.push(substrateApi.api.tx.pooledStaking.requestUndelegate(selectedTarget, 'ManualRewards', {
|
|
364
|
+
Stake: unstakeAmount.toFixed()
|
|
365
|
+
}));
|
|
366
|
+
} else {
|
|
367
|
+
txs.push(substrateApi.api.tx.pooledStaking.requestUndelegate(selectedTarget, 'ManualRewards', {
|
|
368
|
+
Stake: manualRewards.toFixed()
|
|
369
|
+
}));
|
|
370
|
+
const remaining = unstakeAmount.minus(manualRewards);
|
|
371
|
+
if (remaining.gt(0)) {
|
|
372
|
+
const acShares = new BigN(stakeInfo.autoCompoundingShares || '0');
|
|
373
|
+
// Unstake all: use Shares to avoid small leftovers as rewards are automatically compounded every 6 seconds
|
|
374
|
+
const isUnstakeAll = remaining.gte(autoCompounding.multipliedBy(0.9999));
|
|
375
|
+
txs.push(substrateApi.api.tx.pooledStaking.requestUndelegate(selectedTarget, 'AutoCompounding', isUnstakeAll ? {
|
|
376
|
+
Shares: acShares.toFixed(0)
|
|
377
|
+
} : {
|
|
378
|
+
Stake: remaining.toFixed(0)
|
|
379
|
+
}));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
const acShares = new BigN(stakeInfo.autoCompoundingShares || '0');
|
|
384
|
+
const isUnstakeAll = unstakeAmount.gte(autoCompounding.multipliedBy(0.9999));
|
|
385
|
+
txs.push(substrateApi.api.tx.pooledStaking.requestUndelegate(selectedTarget, 'AutoCompounding', isUnstakeAll ? {
|
|
386
|
+
Shares: acShares.toFixed(0)
|
|
387
|
+
} : {
|
|
388
|
+
Stake: unstakeAmount.toFixed(0)
|
|
389
|
+
}));
|
|
390
|
+
}
|
|
391
|
+
const extrinsic = txs.length === 1 ? txs[0] : substrateApi.api.tx.utility.batchAll(txs);
|
|
392
|
+
return [ExtrinsicType.STAKING_UNBOND, extrinsic];
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/* Leave pool action */
|
|
396
|
+
|
|
397
|
+
/* Get pool reward */
|
|
398
|
+
async getPoolReward(useAddresses, callback) {
|
|
399
|
+
let cancel = false;
|
|
400
|
+
const substrateApi = this.substrateApi;
|
|
401
|
+
await substrateApi.isReady;
|
|
402
|
+
await Promise.all(useAddresses.map(async address => {
|
|
403
|
+
if (cancel) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const delegatorSummaries = await substrateApi.api.query.pooledStaking.delegatorCandidateSummaries.entries(address);
|
|
407
|
+
if (!delegatorSummaries || delegatorSummaries.length === 0) {
|
|
408
|
+
const earningRewardItem = {
|
|
409
|
+
...this.baseInfo,
|
|
410
|
+
address,
|
|
411
|
+
type: this.type,
|
|
412
|
+
unclaimedReward: '0',
|
|
413
|
+
state: APIItemState.READY
|
|
414
|
+
};
|
|
415
|
+
callback(earningRewardItem);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
const candidates = delegatorSummaries.map(([key]) => key.args[1].toString());
|
|
419
|
+
const ownStakesMap = await getOwnStakes(substrateApi, candidates, address);
|
|
420
|
+
let totalClaimable = new BigN(0);
|
|
421
|
+
for (const candidate of candidates) {
|
|
422
|
+
const ownStake = ownStakesMap[candidate];
|
|
423
|
+
if (ownStake) {
|
|
424
|
+
totalClaimable = totalClaimable.plus(ownStake.claimable || 0);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
const _unclaimedReward = totalClaimable.toFixed();
|
|
428
|
+
const earningRewardItem = {
|
|
429
|
+
...this.baseInfo,
|
|
430
|
+
address,
|
|
431
|
+
type: this.type,
|
|
432
|
+
unclaimedReward: _unclaimedReward,
|
|
433
|
+
state: APIItemState.READY
|
|
434
|
+
};
|
|
435
|
+
if (_unclaimedReward !== '0') {
|
|
436
|
+
await this.createClaimNotification(earningRewardItem, this.nativeToken);
|
|
437
|
+
}
|
|
438
|
+
callback(earningRewardItem);
|
|
439
|
+
}));
|
|
440
|
+
return () => {
|
|
441
|
+
cancel = true;
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/* Get pool reward */
|
|
446
|
+
|
|
447
|
+
/* Other actions */
|
|
448
|
+
|
|
449
|
+
async handleYieldClaimReward(address, bondReward) {
|
|
450
|
+
const api = await this.substrateApi.isReady;
|
|
451
|
+
const delegatorSummaries = await api.api.query.pooledStaking.delegatorCandidateSummaries.entries(address);
|
|
452
|
+
if (!delegatorSummaries || delegatorSummaries.length === 0) {
|
|
453
|
+
return Promise.reject(new TransactionError(BasicTxErrorType.INTERNAL_ERROR));
|
|
454
|
+
}
|
|
455
|
+
const candidates = delegatorSummaries.map(([key]) => key.args[1].toString());
|
|
456
|
+
const ownStakesMap = await getOwnStakes(api, candidates, address);
|
|
457
|
+
const claimablePairs = [];
|
|
458
|
+
for (const candidate of candidates) {
|
|
459
|
+
const ownStake = ownStakesMap[candidate];
|
|
460
|
+
if (ownStake && new BigN(ownStake.claimable).gt(0)) {
|
|
461
|
+
claimablePairs.push([candidate, address]);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
if (claimablePairs.length === 0) {
|
|
465
|
+
return Promise.reject(new TransactionError(BasicTxErrorType.INTERNAL_ERROR));
|
|
466
|
+
}
|
|
467
|
+
const extrinsic = api.api.tx.pooledStaking.claimManualRewards(claimablePairs);
|
|
468
|
+
return extrinsic;
|
|
469
|
+
}
|
|
470
|
+
handleYieldWithdraw(address, unstakingInfo) {
|
|
471
|
+
throw new Error('Method not implemented.');
|
|
472
|
+
}
|
|
473
|
+
handleYieldCancelUnstake(params) {
|
|
474
|
+
throw new Error('Method not implemented.');
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/* Other actions */
|
|
478
|
+
}
|
|
@@ -13,6 +13,7 @@ import { BasicTxErrorType, YieldPoolType } from '@subwallet/extension-base/types
|
|
|
13
13
|
import { addLazy, createPromiseHandler, filterAddressByChainInfo, removeLazy } from '@subwallet/extension-base/utils';
|
|
14
14
|
import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache';
|
|
15
15
|
import { BehaviorSubject, combineLatest } from 'rxjs';
|
|
16
|
+
import TanssiNativeStakingPoolHandler from "./handlers/native-staking/tanssi.js";
|
|
16
17
|
import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, EnergyNativeStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, SubnetTaoStakingPoolHandler, TaoNativeStakingPoolHandler } from "./handlers/index.js";
|
|
17
18
|
export const fetchPoolsData = async () => {
|
|
18
19
|
const fetchData = await fetchStaticCache('earning/yield-pools.json', {
|
|
@@ -100,6 +101,9 @@ export default class EarningService {
|
|
|
100
101
|
if (_STAKING_CHAIN_GROUP.energy.includes(chain)) {
|
|
101
102
|
handlers.push(new EnergyNativeStakingPoolHandler(this.state, chain));
|
|
102
103
|
}
|
|
104
|
+
if (_STAKING_CHAIN_GROUP.tanssi.includes(chain)) {
|
|
105
|
+
handlers.push(new TanssiNativeStakingPoolHandler(this.state, chain));
|
|
106
|
+
}
|
|
103
107
|
if (_STAKING_CHAIN_GROUP.nominationPool.includes(chain)) {
|
|
104
108
|
const ahMigratedChain = ahMigratedChainMap[chain];
|
|
105
109
|
if (ahMigratedChain) {
|
|
@@ -109,6 +109,8 @@ export function isActionFromValidator(stakingType, chain) {
|
|
|
109
109
|
return true;
|
|
110
110
|
} else if (_STAKING_CHAIN_GROUP.energy.includes(chain)) {
|
|
111
111
|
return true;
|
|
112
|
+
} else if (_STAKING_CHAIN_GROUP.tanssi.includes(chain)) {
|
|
113
|
+
return true;
|
|
112
114
|
}
|
|
113
115
|
return false;
|
|
114
116
|
}
|
|
@@ -8,10 +8,10 @@ import { _isAccountActive } from '@subwallet/extension-base/core/substrate/syste
|
|
|
8
8
|
import { _isAcrossBridgeXcm, _isSnowBridgeXcm, _isXcmWithinSameConsensus } from '@subwallet/extension-base/core/substrate/xcm-parser';
|
|
9
9
|
import { _isSufficientToken } from '@subwallet/extension-base/core/utils';
|
|
10
10
|
import { createXcmExtrinsicV2, dryRunXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
|
|
11
|
-
import { _isAcrossChainBridge
|
|
11
|
+
import { _isAcrossChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
|
|
12
12
|
import { estimateXcmFee } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils';
|
|
13
13
|
import { _getAssetDecimals, _getAssetOriginChain, _getAssetSymbol, _getChainNativeTokenSlug, _getTokenMinAmount, _isChainEvmCompatible, _isNativeToken, _isPureBitcoinChain } from '@subwallet/extension-base/services/chain-service/utils';
|
|
14
|
-
import { DEFAULT_EXCESS_AMOUNT_WEIGHT, FEE_RATE_MULTIPLIER } from '@subwallet/extension-base/services/swap-service/utils';
|
|
14
|
+
import { DEFAULT_EXCESS_AMOUNT_WEIGHT, DetectedGenOptimalProcessErrMsg, FEE_RATE_MULTIPLIER } from '@subwallet/extension-base/services/swap-service/utils';
|
|
15
15
|
import { BasicTxErrorType, SwapStepType, TransferTxErrorType } from '@subwallet/extension-base/types';
|
|
16
16
|
import { CommonStepType, DEFAULT_FIRST_STEP, MOCK_STEP_FEE } from '@subwallet/extension-base/types/service-base';
|
|
17
17
|
import { DynamicSwapType, SwapErrorType, SwapFeeType } from '@subwallet/extension-base/types/swap';
|
|
@@ -56,7 +56,10 @@ export class SwapBaseHandler {
|
|
|
56
56
|
return result;
|
|
57
57
|
} catch (e) {
|
|
58
58
|
const errorMessage = e.message;
|
|
59
|
-
if (errorMessage.toLowerCase().startsWith(
|
|
59
|
+
if (errorMessage.toLowerCase().startsWith(DetectedGenOptimalProcessErrMsg.AMOUNT_TOO_LOW) || errorMessage.toLowerCase().startsWith(DetectedGenOptimalProcessErrMsg.AMOUNT_TOO_HIGH)) {
|
|
60
|
+
throw new Error(errorMessage);
|
|
61
|
+
}
|
|
62
|
+
if (errorMessage.toLowerCase().includes(DetectedGenOptimalProcessErrMsg.NOT_ENOUGHT_BITCOIN)) {
|
|
60
63
|
throw new Error(errorMessage);
|
|
61
64
|
}
|
|
62
65
|
return result;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { COMMON_ASSETS } from '@subwallet/chain-list';
|
|
2
1
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
3
2
|
import { BalanceService } from '@subwallet/extension-base/services/balance-service';
|
|
4
3
|
import { ChainService } from '@subwallet/extension-base/services/chain-service';
|
|
@@ -15,7 +14,6 @@ export declare class ChainflipSwapHandler implements SwapBaseInterface {
|
|
|
15
14
|
get providerInfo(): import("@subwallet/extension-base/types").SwapProvider;
|
|
16
15
|
get name(): string;
|
|
17
16
|
get slug(): string;
|
|
18
|
-
get intermediaryAssetSlug(): COMMON_ASSETS.USDC_ETHEREUM | COMMON_ASSETS.USDC_SEPOLIA;
|
|
19
17
|
handleSubmitStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
20
18
|
handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
21
19
|
getSubmitStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
-
import { COMMON_ASSETS } from '@subwallet/chain-list';
|
|
5
4
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
6
5
|
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
7
6
|
import { createBitcoinTransaction } from '@subwallet/extension-base/services/balance-service/transfer/bitcoin-transfer';
|
|
8
7
|
import { getERC20TransactionObject, getEVMTransactionObject } from '@subwallet/extension-base/services/balance-service/transfer/smart-contract';
|
|
9
8
|
import { createSubstrateExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/token';
|
|
10
|
-
import {
|
|
9
|
+
import { _chainInfoToChainType, _getContractAddressOfToken, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
11
10
|
import { SwapBaseHandler } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
|
|
12
11
|
import { BasicTxErrorType, CommonStepType, DynamicSwapType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
13
12
|
import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment';
|
|
@@ -15,12 +14,7 @@ import { _reformatAddressWithChain, fetchFromProxyService } from '@subwallet/ext
|
|
|
15
14
|
import { getId } from '@subwallet/extension-base/utils/getId';
|
|
16
15
|
import BigNumber from 'bignumber.js';
|
|
17
16
|
import * as bitcoin from 'bitcoinjs-lib';
|
|
18
|
-
const INTERMEDIARY_MAINNET_ASSET_SLUG = COMMON_ASSETS.USDC_ETHEREUM;
|
|
19
|
-
const INTERMEDIARY_TESTNET_ASSET_SLUG = COMMON_ASSETS.USDC_SEPOLIA;
|
|
20
17
|
export class ChainflipSwapHandler {
|
|
21
|
-
// private baseUrl: string;
|
|
22
|
-
// private assetsUrl: string;
|
|
23
|
-
|
|
24
18
|
constructor(chainService, balanceService, feeService, isTestnet = true) {
|
|
25
19
|
this.swapBaseHandler = new SwapBaseHandler({
|
|
26
20
|
chainService,
|
|
@@ -31,10 +25,7 @@ export class ChainflipSwapHandler {
|
|
|
31
25
|
});
|
|
32
26
|
this.isTestnet = isTestnet;
|
|
33
27
|
this.providerSlug = isTestnet ? SwapProviderId.CHAIN_FLIP_TESTNET : SwapProviderId.CHAIN_FLIP_MAINNET;
|
|
34
|
-
// this.baseUrl = getChainflipSwap(isTestnet);
|
|
35
|
-
// this.assetsUrl = getAssetsUrl(isTestnet);
|
|
36
28
|
}
|
|
37
|
-
|
|
38
29
|
get chainService() {
|
|
39
30
|
return this.swapBaseHandler.chainService;
|
|
40
31
|
}
|
|
@@ -50,13 +41,6 @@ export class ChainflipSwapHandler {
|
|
|
50
41
|
get slug() {
|
|
51
42
|
return this.swapBaseHandler.slug;
|
|
52
43
|
}
|
|
53
|
-
get intermediaryAssetSlug() {
|
|
54
|
-
if (this.isTestnet) {
|
|
55
|
-
return INTERMEDIARY_TESTNET_ASSET_SLUG;
|
|
56
|
-
} else {
|
|
57
|
-
return INTERMEDIARY_MAINNET_ASSET_SLUG;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
44
|
async handleSubmitStep(params) {
|
|
61
45
|
const {
|
|
62
46
|
address,
|
|
@@ -70,7 +54,7 @@ export class ChainflipSwapHandler {
|
|
|
70
54
|
const fromAsset = this.chainService.getAssetBySlug(pair.from);
|
|
71
55
|
const chainInfo = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
72
56
|
const toChainInfo = this.chainService.getChainInfoByKey(fromAsset.originChain);
|
|
73
|
-
const chainType =
|
|
57
|
+
const chainType = _chainInfoToChainType(chainInfo);
|
|
74
58
|
const receiver = _reformatAddressWithChain(recipient !== null && recipient !== void 0 ? recipient : address, toChainInfo);
|
|
75
59
|
const minReceive = new BigNumber(quote.rate).times(1 - slippage).toString();
|
|
76
60
|
const processMetadata = process.steps[currentStep].metadata;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
2
|
+
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
3
|
+
import { BalanceService } from '@subwallet/extension-base/services/balance-service';
|
|
4
|
+
import { ChainService } from '@subwallet/extension-base/services/chain-service';
|
|
5
|
+
import FeeService from '@subwallet/extension-base/services/fee-service/service';
|
|
6
|
+
import { SwapBaseInterface } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
|
|
7
|
+
import { BaseStepDetail, CommonOptimalSwapPath, CommonStepFeeInfo, OptimalSwapPathParamsV2, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
|
|
8
|
+
interface OptimexTradeMetadata {
|
|
9
|
+
trade_id: string;
|
|
10
|
+
deposit_address: string;
|
|
11
|
+
payload: string;
|
|
12
|
+
need_approve: boolean;
|
|
13
|
+
approve_address: string;
|
|
14
|
+
approve_payload: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class OptimexHandler implements SwapBaseInterface {
|
|
17
|
+
private readonly baseUrl;
|
|
18
|
+
private currentTradeMetadata;
|
|
19
|
+
private swapBaseHandler;
|
|
20
|
+
private isTestnet;
|
|
21
|
+
providerSlug: SwapProviderId;
|
|
22
|
+
constructor(chainService: ChainService, balanceService: BalanceService, feeService: FeeService, isTestnet?: boolean);
|
|
23
|
+
get chainService(): ChainService;
|
|
24
|
+
get providerInfo(): import("@subwallet/extension-base/types").SwapProvider;
|
|
25
|
+
get name(): string;
|
|
26
|
+
get slug(): string;
|
|
27
|
+
generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
|
|
28
|
+
initTrade(request: OptimalSwapPathParamsV2): Promise<OptimexTradeMetadata | undefined>;
|
|
29
|
+
getApprovalStep(params: OptimalSwapPathParamsV2): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
30
|
+
getSubmitStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
31
|
+
validateSwapProcessV2(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
|
|
32
|
+
handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
33
|
+
handleApproveStep(params: SwapSubmitParams): {
|
|
34
|
+
txChain: string;
|
|
35
|
+
txData: string;
|
|
36
|
+
extrinsic: {};
|
|
37
|
+
extrinsicType: ExtrinsicType;
|
|
38
|
+
transferNativeAmount: string;
|
|
39
|
+
chainType: ChainType;
|
|
40
|
+
};
|
|
41
|
+
handleSubmitStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
42
|
+
}
|
|
43
|
+
export {};
|