@subwallet/extension-base 1.3.1 → 1.3.3-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 (65) hide show
  1. package/background/KoniTypes.d.ts +5 -1
  2. package/cjs/constants/index.js +7 -1
  3. package/cjs/koni/api/nft/assethub_nft/index.js +30 -7
  4. package/cjs/koni/api/nft/config.js +11 -1
  5. package/cjs/koni/api/nft/index.js +9 -0
  6. package/cjs/koni/api/nft/ternoa_nft/index.js +174 -0
  7. package/cjs/koni/api/staking/bonding/utils.js +1 -1
  8. package/cjs/koni/background/handlers/Extension.js +67 -32
  9. package/cjs/packageInfo.js +1 -1
  10. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +9 -0
  11. package/cjs/services/chain-service/constants.js +2 -1
  12. package/cjs/services/chain-service/index.js +11 -14
  13. package/cjs/services/earning-service/constants/chains.js +2 -1
  14. package/cjs/services/earning-service/handlers/base.js +2 -1
  15. package/cjs/services/earning-service/handlers/native-staking/index.js +8 -1
  16. package/cjs/services/earning-service/handlers/native-staking/tao.js +394 -0
  17. package/cjs/services/earning-service/service.js +3 -0
  18. package/cjs/services/earning-service/utils/index.js +2 -0
  19. package/cjs/services/keyring-service/context/handlers/Modify.js +11 -3
  20. package/cjs/services/keyring-service/context/state.js +2 -3
  21. package/cjs/services/keyring-service/index.js +1 -1
  22. package/cjs/services/swap-service/handler/chainflip-handler.js +13 -5
  23. package/cjs/services/transaction-service/utils.js +6 -0
  24. package/cjs/types/swap/index.js +4 -2
  25. package/cjs/utils/account/derive/info/solo.js +2 -0
  26. package/cjs/utils/account/derive/info/unified.js +2 -0
  27. package/cjs/utils/account/transform.js +4 -4
  28. package/constants/index.d.ts +2 -0
  29. package/constants/index.js +2 -0
  30. package/koni/api/nft/assethub_nft/index.d.ts +2 -0
  31. package/koni/api/nft/assethub_nft/index.js +30 -7
  32. package/koni/api/nft/config.d.ts +4 -0
  33. package/koni/api/nft/config.js +6 -0
  34. package/koni/api/nft/index.js +9 -0
  35. package/koni/api/nft/ternoa_nft/index.d.ts +32 -0
  36. package/koni/api/nft/ternoa_nft/index.js +167 -0
  37. package/koni/api/staking/bonding/utils.js +1 -1
  38. package/koni/background/handlers/Extension.d.ts +1 -0
  39. package/koni/background/handlers/Extension.js +38 -3
  40. package/package.json +16 -6
  41. package/packageInfo.js +1 -1
  42. package/services/balance-service/helpers/subscribe/substrate/index.js +9 -0
  43. package/services/chain-service/constants.d.ts +1 -0
  44. package/services/chain-service/constants.js +2 -1
  45. package/services/chain-service/index.js +11 -14
  46. package/services/earning-service/constants/chains.d.ts +1 -0
  47. package/services/earning-service/constants/chains.js +2 -1
  48. package/services/earning-service/handlers/base.js +2 -1
  49. package/services/earning-service/handlers/native-staking/index.d.ts +1 -0
  50. package/services/earning-service/handlers/native-staking/index.js +2 -1
  51. package/services/earning-service/handlers/native-staking/tao.d.ts +49 -0
  52. package/services/earning-service/handlers/native-staking/tao.js +378 -0
  53. package/services/earning-service/service.js +4 -1
  54. package/services/earning-service/utils/index.js +2 -0
  55. package/services/keyring-service/context/handlers/Modify.js +11 -3
  56. package/services/keyring-service/context/state.js +2 -3
  57. package/services/keyring-service/index.d.ts +1 -1
  58. package/services/keyring-service/index.js +1 -1
  59. package/services/swap-service/handler/chainflip-handler.js +13 -5
  60. package/services/transaction-service/utils.js +6 -0
  61. package/types/swap/index.d.ts +1 -0
  62. package/types/swap/index.js +2 -1
  63. package/utils/account/derive/info/solo.js +2 -0
  64. package/utils/account/derive/info/unified.js +2 -0
  65. package/utils/account/transform.js +4 -4
@@ -4,4 +4,5 @@
4
4
  export { default as AmplitudeNativeStakingPoolHandler } from "./amplitude.js";
5
5
  export { default as AstarNativeStakingPoolHandler } from "./astar.js";
6
6
  export { default as RelayNativeStakingPoolHandler } from "./relay-chain.js";
7
- export { default as ParaNativeStakingPoolHandler } from "./para-chain.js";
7
+ export { default as ParaNativeStakingPoolHandler } from "./para-chain.js";
8
+ export { default as TaoNativeStakingPoolHandler } from "./tao.js";
@@ -0,0 +1,49 @@
1
+ import { _ChainInfo } from '@subwallet/chain-list/types';
2
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
3
+ import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
4
+ import { BaseYieldPositionInfo, StakeCancelWithdrawalParams, SubmitJoinNativeStaking, TransactionData, UnstakingInfo, ValidatorInfo, YieldPoolInfo, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
5
+ interface TaoStakingStakeOption {
6
+ owner: string;
7
+ amount: string;
8
+ }
9
+ export interface RawDelegateState {
10
+ data: Array<{
11
+ delegate: {
12
+ ss58: string;
13
+ };
14
+ balance: string;
15
+ }>;
16
+ }
17
+ interface ValidatorResponse {
18
+ data: Validator[];
19
+ }
20
+ interface Validator {
21
+ hotkey: {
22
+ ss58: string;
23
+ };
24
+ name: string;
25
+ nominators: number;
26
+ stake: string;
27
+ validator_stake: string;
28
+ take: string;
29
+ apr: string;
30
+ }
31
+ export declare const BITTENSOR_API_KEY_1: string;
32
+ export declare const BITTENSOR_API_KEY_2: string;
33
+ export declare const bittensorApiKey: () => string;
34
+ export declare function fetchDelegates(): Promise<ValidatorResponse>;
35
+ export declare function fetchTaoDelegateState(address: string): Promise<RawDelegateState>;
36
+ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHandler {
37
+ handleYieldWithdraw(address: string, unstakingInfo: UnstakingInfo): Promise<TransactionData>;
38
+ handleYieldCancelUnstake(params: StakeCancelWithdrawalParams): Promise<TransactionData>;
39
+ get maintainBalance(): string;
40
+ subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
41
+ parseNominatorMetadata(chainInfo: _ChainInfo, address: string, delegatorState: TaoStakingStakeOption[]): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
42
+ subscribePoolPosition(useAddresses: string[], rsCallback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
43
+ private getDevnetPoolTargets;
44
+ private getMainnetPoolTargets;
45
+ getPoolTargets(): Promise<ValidatorInfo[]>;
46
+ createJoinExtrinsic(data: SubmitJoinNativeStaking, positionInfo?: YieldPositionInfo, bondDest?: string): Promise<[TransactionData, YieldTokenBaseInfo]>;
47
+ handleYieldUnstake(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
48
+ }
49
+ export {};
@@ -0,0 +1,378 @@
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 { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { BITTENSOR_REFRESH_STAKE_APY, BITTENSOR_REFRESH_STAKE_INFO } from '@subwallet/extension-base/constants';
7
+ import { getEarningStatusByNominations } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
8
+ import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
9
+ import { BasicTxErrorType, EarningStatus } from '@subwallet/extension-base/types';
10
+ import { reformatAddress } from '@subwallet/extension-base/utils';
11
+ import BigN from 'bignumber.js';
12
+ import { BN, BN_TEN, BN_ZERO } from '@polkadot/util';
13
+ import { calculateReward } from "../../utils/index.js";
14
+ export const BITTENSOR_API_KEY_1 = process.env.BITTENSOR_API_KEY_1 || '';
15
+ export const BITTENSOR_API_KEY_2 = process.env.BITTENSOR_API_KEY_2 || '';
16
+ function random(...keys) {
17
+ const validKeys = keys.filter(key => key);
18
+ const randomIndex = Math.floor(Math.random() * validKeys.length);
19
+ return validKeys[randomIndex];
20
+ }
21
+ export const bittensorApiKey = () => {
22
+ return random(BITTENSOR_API_KEY_1, BITTENSOR_API_KEY_2);
23
+ };
24
+
25
+ /* Fetch data */
26
+
27
+ export async function fetchDelegates() {
28
+ const apiKey = bittensorApiKey();
29
+ return new Promise(function (resolve) {
30
+ fetch('https://api-prod-v2.taostats.io/api/validator/latest/v1', {
31
+ method: 'GET',
32
+ headers: {
33
+ 'Content-Type': 'application/json',
34
+ Authorization: `${apiKey}`
35
+ }
36
+ }).then(resp => {
37
+ resolve(resp.json());
38
+ }).catch(console.error);
39
+ });
40
+ }
41
+ export async function fetchTaoDelegateState(address) {
42
+ const apiKey = bittensorApiKey();
43
+ return new Promise(function (resolve) {
44
+ fetch(`https://api-prod-v2.taostats.io/api/delegation/balance/latest/v1?nominator=${address}`, {
45
+ method: 'GET',
46
+ headers: {
47
+ 'Content-Type': 'application/json',
48
+ Authorization: `${apiKey}`
49
+ }
50
+ }).then(resp => {
51
+ resolve(resp.json());
52
+ }).catch(console.error);
53
+ });
54
+ }
55
+
56
+ /* Fetch data */
57
+
58
+ const testnetDelegate = {
59
+ '5G6wdAdS7hpBuH1tjuZDhpzrGw9Wf71WEVakDCxHDm1cxEQ2': {
60
+ name: '0x436c6f776e4e616d65f09fa4a1',
61
+ url: 'https://example.com ',
62
+ image: 'https://example.com/image.png',
63
+ discord: '0xe28094446973636f7264',
64
+ description: 'This is an example identity.',
65
+ additional: ''
66
+ }
67
+ };
68
+ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHandler {
69
+ /* Unimplemented function */
70
+ handleYieldWithdraw(address, unstakingInfo) {
71
+ return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
72
+ }
73
+ handleYieldCancelUnstake(params) {
74
+ return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
75
+ }
76
+ /* Unimplemented function */
77
+
78
+ get maintainBalance() {
79
+ const ed = new BN(this.nativeToken.minAmount || '0');
80
+ const calculateMaintainBalance = new BN(15).mul(ed).div(BN_TEN);
81
+ const maintainBalance = calculateMaintainBalance;
82
+ return maintainBalance.toString();
83
+ }
84
+
85
+ /* Subscribe pool info */
86
+
87
+ async subscribePoolInfo(callback) {
88
+ let cancel = false;
89
+ const substrateApi = this.substrateApi;
90
+ const updateStakingInfo = async () => {
91
+ try {
92
+ if (cancel) {
93
+ return;
94
+ }
95
+ const minDelegatorStake = await substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
96
+ const BNminDelegatorStake = new BigN(minDelegatorStake.toString());
97
+ const data = {
98
+ ...this.baseInfo,
99
+ type: this.type,
100
+ metadata: {
101
+ ...this.metadataInfo,
102
+ description: this.getDescription('0')
103
+ },
104
+ statistic: {
105
+ assetEarning: [{
106
+ slug: this.nativeToken.slug
107
+ }],
108
+ maxCandidatePerFarmer: 16,
109
+ maxWithdrawalRequestPerFarmer: 1,
110
+ earningThreshold: {
111
+ join: BNminDelegatorStake.toString(),
112
+ defaultUnstake: '0',
113
+ fastUnstake: '0'
114
+ },
115
+ eraTime: 1.2,
116
+ era: 0,
117
+ unstakingPeriod: 1.2
118
+ }
119
+ };
120
+ callback(data);
121
+ } catch (error) {
122
+ console.log(error);
123
+ }
124
+ };
125
+ const subscribeStakingMetadataInterval = () => {
126
+ updateStakingInfo().catch(console.error);
127
+ };
128
+ await substrateApi.isReady;
129
+ subscribeStakingMetadataInterval();
130
+ const interval = setInterval(subscribeStakingMetadataInterval, BITTENSOR_REFRESH_STAKE_APY);
131
+ return () => {
132
+ cancel = true;
133
+ clearInterval(interval);
134
+ };
135
+ }
136
+
137
+ /* Subscribe pool position */
138
+
139
+ async parseNominatorMetadata(chainInfo, address, delegatorState) {
140
+ const nominationList = [];
141
+ const getMinDelegatorStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
142
+ const minDelegatorStake = (await getMinDelegatorStake).toString();
143
+ let allActiveStake = BN_ZERO;
144
+ for (const delegate of delegatorState) {
145
+ const activeStake = delegate.amount;
146
+ const bnActiveStake = new BN(activeStake);
147
+ if (bnActiveStake.gt(BN_ZERO)) {
148
+ const delegationStatus = EarningStatus.EARNING_REWARD;
149
+ allActiveStake = allActiveStake.add(bnActiveStake);
150
+ nominationList.push({
151
+ status: delegationStatus,
152
+ chain: chainInfo.slug,
153
+ validatorAddress: delegate.owner,
154
+ activeStake: activeStake,
155
+ validatorMinStake: minDelegatorStake
156
+ });
157
+ }
158
+ }
159
+ const stakingStatus = getEarningStatusByNominations(allActiveStake, nominationList);
160
+ return {
161
+ status: stakingStatus,
162
+ balanceToken: this.nativeToken.slug,
163
+ totalStake: allActiveStake.toString(),
164
+ activeStake: allActiveStake.toString(),
165
+ unstakeBalance: '0',
166
+ isBondedBefore: true,
167
+ nominations: nominationList,
168
+ unstakings: []
169
+ };
170
+ }
171
+ async subscribePoolPosition(useAddresses, rsCallback) {
172
+ let cancel = false;
173
+ const substrateApi = await this.substrateApi.isReady;
174
+ const defaultInfo = this.baseInfo;
175
+ const chainInfo = this.chainInfo;
176
+ const getDevnetPoolPosition = async () => {
177
+ const testnetAddress = Object.keys(testnetDelegate)[0];
178
+ const delegatorState = [];
179
+ let bnTotalBalance = BN_ZERO;
180
+ const stakePromises = useAddresses.map(async address => {
181
+ const stakeAmount = (await substrateApi.api.query.subtensorModule.stake(testnetAddress, address)).toString();
182
+ const bnStakeAmount = new BN(stakeAmount);
183
+ bnTotalBalance = bnTotalBalance.add(bnStakeAmount);
184
+ delegatorState.push({
185
+ owner: testnetAddress,
186
+ amount: bnStakeAmount.toString()
187
+ });
188
+ rsCallback({
189
+ ...defaultInfo,
190
+ type: this.type,
191
+ address: address,
192
+ balanceToken: this.nativeToken.slug,
193
+ totalStake: bnTotalBalance.toString(),
194
+ activeStake: bnStakeAmount.toString(),
195
+ unstakeBalance: '0',
196
+ status: EarningStatus.EARNING_REWARD,
197
+ isBondedBefore: true,
198
+ nominations: delegatorState.map(delegate => ({
199
+ chain: this.chain,
200
+ validatorAddress: delegate.owner,
201
+ activeStake: delegate.amount,
202
+ status: EarningStatus.EARNING_REWARD
203
+ })),
204
+ unstakings: []
205
+ });
206
+ });
207
+ await Promise.all(stakePromises);
208
+ };
209
+ const getMainnetPoolPosition = async () => {
210
+ const rawDelegateStateInfos = await Promise.all(useAddresses.map(address => fetchTaoDelegateState(address)));
211
+ if (rawDelegateStateInfos.length > 0) {
212
+ rawDelegateStateInfos.forEach((rawDelegateStateInfo, i) => {
213
+ const owner = reformatAddress(useAddresses[i], 42);
214
+ const delegatorState = [];
215
+ let bnTotalBalance = BN_ZERO;
216
+ const delegateStateInfo = rawDelegateStateInfo.data;
217
+ for (const delegate of delegateStateInfo) {
218
+ bnTotalBalance = bnTotalBalance.add(new BN(delegate.balance));
219
+ delegatorState.push({
220
+ owner: delegate.delegate.ss58,
221
+ amount: delegate.balance.toString()
222
+ });
223
+ }
224
+ if (delegateStateInfo && delegateStateInfo.length > 0) {
225
+ this.parseNominatorMetadata(chainInfo, owner, delegatorState).then(nominatorMetadata => {
226
+ rsCallback({
227
+ ...defaultInfo,
228
+ ...nominatorMetadata,
229
+ address: owner,
230
+ type: this.type
231
+ });
232
+ }).catch(console.error);
233
+ } else {
234
+ rsCallback({
235
+ ...defaultInfo,
236
+ type: this.type,
237
+ address: owner,
238
+ balanceToken: this.nativeToken.slug,
239
+ totalStake: '0',
240
+ activeStake: '0',
241
+ unstakeBalance: '0',
242
+ status: EarningStatus.NOT_STAKING,
243
+ isBondedBefore: false,
244
+ nominations: [],
245
+ unstakings: []
246
+ });
247
+ }
248
+ });
249
+ }
250
+ };
251
+ const getStakingPositionInterval = async () => {
252
+ if (cancel) {
253
+ return;
254
+ }
255
+ if (this.chain === 'bittensor_devnet') {
256
+ await getDevnetPoolPosition();
257
+ } else {
258
+ await getMainnetPoolPosition();
259
+ }
260
+ };
261
+ getStakingPositionInterval().catch(console.error);
262
+ const intervalId = setInterval(() => {
263
+ getStakingPositionInterval().catch(console.error);
264
+ }, BITTENSOR_REFRESH_STAKE_INFO);
265
+ return () => {
266
+ cancel = true;
267
+ clearInterval(intervalId);
268
+ };
269
+ }
270
+
271
+ /* Subscribe pool position */
272
+
273
+ /* Get pool targets */
274
+
275
+ // eslint-disable-next-line @typescript-eslint/require-await
276
+ async getDevnetPoolTargets() {
277
+ const _topValidator = testnetDelegate;
278
+ const validatorAddresses = Object.keys(_topValidator);
279
+ return validatorAddresses.map(address => {
280
+ return {
281
+ address: address,
282
+ totalStake: '0',
283
+ ownStake: '0',
284
+ otherStake: '0',
285
+ minBond: '0',
286
+ nominatorCount: 0,
287
+ commission: '0',
288
+ expectedReturn: 0,
289
+ blocked: false,
290
+ isVerified: false,
291
+ chain: this.chain,
292
+ isCrowded: false,
293
+ identity: address
294
+ };
295
+ });
296
+ }
297
+ async getMainnetPoolTargets() {
298
+ const _topValidator = await fetchDelegates();
299
+ const topValidator = _topValidator;
300
+ const getNominatorMinRequiredStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
301
+ const nominatorMinRequiredStake = (await getNominatorMinRequiredStake).toString();
302
+ const bnMinBond = new BN(nominatorMinRequiredStake);
303
+ const validatorList = topValidator.data;
304
+ const validatorAddresses = Object.keys(validatorList);
305
+ const results = await Promise.all(validatorAddresses.map(i => {
306
+ const address = validatorList[i].hotkey.ss58;
307
+ const bnTotalStake = new BN(validatorList[i].stake);
308
+ const bnOwnStake = new BN(validatorList[i].validator_stake);
309
+ const otherStake = bnTotalStake.sub(bnOwnStake);
310
+ const nominatorCount = validatorList[i].nominators;
311
+ const commission = validatorList[i].take;
312
+ const roundedCommission = (parseFloat(commission) * 100).toFixed(0);
313
+ const apr = (parseFloat(validatorList[i].apr) / 10 ** 9 * 100).toFixed(2);
314
+ const apyCalculate = calculateReward(parseFloat(apr));
315
+ const name = validatorList[i].name || address;
316
+ return {
317
+ address: address,
318
+ totalStake: bnTotalStake.toString(),
319
+ ownStake: bnOwnStake.toString(),
320
+ otherStake: otherStake.toString(),
321
+ minBond: bnMinBond.toString(),
322
+ nominatorCount: nominatorCount,
323
+ commission: roundedCommission,
324
+ expectedReturn: apyCalculate.apy,
325
+ blocked: false,
326
+ isVerified: false,
327
+ chain: this.chain,
328
+ isCrowded: false,
329
+ identity: name
330
+ };
331
+ }));
332
+ return results;
333
+ }
334
+ async getPoolTargets() {
335
+ if (this.chain === 'bittensor_devnet') {
336
+ return this.getDevnetPoolTargets();
337
+ } else {
338
+ return this.getMainnetPoolTargets();
339
+ }
340
+ }
341
+
342
+ /* Get pool targets */
343
+
344
+ /* Join pool action */
345
+
346
+ async createJoinExtrinsic(data, positionInfo, bondDest = 'Staked') {
347
+ const {
348
+ amount,
349
+ selectedValidators: targetValidators
350
+ } = data;
351
+ const chainApi = await this.substrateApi.isReady;
352
+ const binaryAmount = new BN(amount);
353
+ const selectedValidatorInfo = targetValidators[0];
354
+ const hotkey = selectedValidatorInfo.address;
355
+ const extrinsic = chainApi.api.tx.subtensorModule.addStake(hotkey, binaryAmount);
356
+ return [extrinsic, {
357
+ slug: this.nativeToken.slug,
358
+ amount: '0'
359
+ }];
360
+ }
361
+
362
+ /* Join pool action */
363
+
364
+ /* Leave pool action */
365
+
366
+ async handleYieldUnstake(amount, address, selectedTarget) {
367
+ const apiPromise = await this.substrateApi.isReady;
368
+ const binaryAmount = new BN(amount);
369
+ const poolPosition = await this.getPoolPosition(address);
370
+ if (!selectedTarget || !poolPosition) {
371
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
372
+ }
373
+ const extrinsic = apiPromise.api.tx.subtensorModule.removeStake(selectedTarget, binaryAmount);
374
+ return [ExtrinsicType.STAKING_LEAVE_POOL, extrinsic];
375
+ }
376
+
377
+ /* Leave pool action */
378
+ }
@@ -12,7 +12,7 @@ import { BasicTxErrorType, YieldPoolType } from '@subwallet/extension-base/types
12
12
  import { addLazy, categoryAddresses, createPromiseHandler, removeLazy } from '@subwallet/extension-base/utils';
13
13
  import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache';
14
14
  import { BehaviorSubject } from 'rxjs';
15
- import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler } from "./handlers/index.js";
15
+ import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, TaoNativeStakingPoolHandler } from "./handlers/index.js";
16
16
  const fetchPoolsData = async () => {
17
17
  const fetchData = await fetchStaticCache('earning/yield-pools.json', {
18
18
  data: {}
@@ -65,6 +65,9 @@ export default class EarningService {
65
65
  if (_STAKING_CHAIN_GROUP.amplitude.includes(chain)) {
66
66
  handlers.push(new AmplitudeNativeStakingPoolHandler(this.state, chain));
67
67
  }
68
+ if (_STAKING_CHAIN_GROUP.bittensor.includes(chain)) {
69
+ handlers.push(new TaoNativeStakingPoolHandler(this.state, chain));
70
+ }
68
71
  if (_STAKING_CHAIN_GROUP.nominationPool.includes(chain)) {
69
72
  handlers.push(new NominationPoolHandler(this.state, chain));
70
73
  }
@@ -103,6 +103,8 @@ export function isActionFromValidator(stakingType, chain) {
103
103
  return true;
104
104
  } else if (_STAKING_CHAIN_GROUP.para.includes(chain)) {
105
105
  return true;
106
+ } else if (_STAKING_CHAIN_GROUP.bittensor.includes(chain)) {
107
+ return true;
106
108
  }
107
109
  return false;
108
110
  }
@@ -114,14 +114,16 @@ export class AccountModifyHandler extends AccountBaseHandler {
114
114
  }) {
115
115
  const modifyPairs = this.state.modifyPairs;
116
116
  const isUnified = this.state.isUnifiedAccount(proxyId);
117
+ const oldAccounts = Object.keys(this.state.accounts);
118
+ const afterDeleteAccounts = oldAccounts.filter(id => id !== proxyId);
117
119
  let addresses;
118
120
  if (!isUnified) {
119
121
  addresses = [proxyId];
120
122
  } else {
121
123
  addresses = Object.keys(modifyPairs).filter(address => modifyPairs[address].accountProxyId === proxyId);
122
- this.state.deleteAccountProxy(proxyId);
123
- this.parentService.eventRemoveAccount(proxyId);
124
124
  }
125
+ this.state.deleteAccountProxy(proxyId);
126
+ this.parentService.eventRemoveAccountProxy(proxyId);
125
127
  for (const address of addresses) {
126
128
  delete modifyPairs[address];
127
129
  }
@@ -130,7 +132,13 @@ export class AccountModifyHandler extends AccountBaseHandler {
130
132
  keyring.forgetAccount(address);
131
133
  }
132
134
  await Promise.all(addresses.map(address => new Promise(resolve => this.state.removeAccountRef(address, resolve))));
133
- this.state.saveCurrentAccountProxyId(ALL_ACCOUNT_KEY);
135
+
136
+ // Cannot use `this.state.accounts` because it is not completely updated yet
137
+ if (afterDeleteAccounts.length > 1) {
138
+ this.state.saveCurrentAccountProxyId(ALL_ACCOUNT_KEY);
139
+ } else {
140
+ this.state.saveCurrentAccountProxyId(afterDeleteAccounts[0]);
141
+ }
134
142
  return addresses;
135
143
  }
136
144
  tonGetAllTonWalletContractVersion(request) {
@@ -437,12 +437,11 @@ export class AccountState {
437
437
  if (proxyId === ALL_ACCOUNT_KEY) {
438
438
  return allowGetAllAccount ? this.getAllAddresses() : [];
439
439
  }
440
- const accountProxies = this._accountProxy.value;
441
- const modifyPairs = this._modifyPair.value;
440
+ const accountProxies = this.accounts;
442
441
  if (!accountProxies[proxyId]) {
443
442
  return [proxyId];
444
443
  } else {
445
- return Object.keys(modifyPairs).filter(address => modifyPairs[address].accountProxyId === proxyId);
444
+ return accountProxies[proxyId].accounts.map(account => account.address);
446
445
  }
447
446
  }
448
447
 
@@ -9,7 +9,7 @@ export declare class KeyringService {
9
9
  get keyringState(): KeyringState;
10
10
  keyringStateSubscribe(callback: (state: KeyringState) => void): import("rxjs").Subscription;
11
11
  eventInjectReady(): void;
12
- eventRemoveAccount(proxyId: string): void;
12
+ eventRemoveAccountProxy(proxyId: string): void;
13
13
  updateKeyringState(isReady?: boolean): void;
14
14
  lock(): void;
15
15
  resetWallet(resetAll: boolean): Promise<void>;
@@ -23,7 +23,7 @@ export class KeyringService {
23
23
  eventInjectReady() {
24
24
  this.state.eventService.emit('inject.ready', true);
25
25
  }
26
- eventRemoveAccount(proxyId) {
26
+ eventRemoveAccountProxy(proxyId) {
27
27
  this.state.eventService.emit('accountProxy.remove', proxyId);
28
28
  }
29
29
  updateKeyringState(isReady = true) {
@@ -230,7 +230,6 @@ export class ChainflipSwapHandler {
230
230
  switch (fee.type) {
231
231
  case ChainflipFeeType.INGRESS:
232
232
  {
233
- console.log('ingress', fee);
234
233
  feeComponent.push({
235
234
  tokenSlug: fromAsset.slug,
236
235
  amount: fee.amount,
@@ -242,7 +241,6 @@ export class ChainflipSwapHandler {
242
241
  // eslint-disable-next-line no-fallthrough
243
242
  case ChainflipFeeType.EGRESS:
244
243
  {
245
- console.log('egress', fee);
246
244
  feeComponent.push({
247
245
  tokenSlug: toAsset.slug,
248
246
  amount: fee.amount,
@@ -258,7 +256,6 @@ export class ChainflipSwapHandler {
258
256
  // eslint-disable-next-line no-fallthrough
259
257
  case ChainflipFeeType.BROKER:
260
258
  {
261
- console.log('broker fee', fee);
262
259
  feeComponent.push({
263
260
  tokenSlug: this.intermediaryAssetSlug,
264
261
  amount: fee.amount,
@@ -335,7 +332,8 @@ export class ChainflipSwapHandler {
335
332
  const {
336
333
  address,
337
334
  quote,
338
- recipient
335
+ recipient,
336
+ slippage
339
337
  } = params;
340
338
  const pair = quote.pair;
341
339
  const fromAsset = this.chainService.getAssetBySlug(pair.from);
@@ -347,14 +345,24 @@ export class ChainflipSwapHandler {
347
345
  const destChainId = this.chainMapping[toAsset.originChain];
348
346
  const fromAssetId = _getAssetSymbol(fromAsset);
349
347
  const toAssetId = _getAssetSymbol(toAsset);
348
+ const minReceive = new BigNumber(quote.rate).times(1 - slippage).toString();
350
349
  const depositAddressResponse = await this.swapSdk.requestDepositAddress({
351
350
  srcChain: srcChainId,
352
351
  destChain: destChainId,
353
352
  srcAsset: fromAssetId,
354
353
  destAsset: toAssetId,
355
354
  destAddress: receiver,
356
- amount: quote.fromAmount
355
+ amount: quote.fromAmount,
356
+ fillOrKillParams: {
357
+ minPrice: minReceive,
358
+ // minimum accepted price for swaps through the channel
359
+ refundAddress: address,
360
+ // address to which assets are refunded
361
+ retryDurationBlocks: 100 // 100 blocks * 6 seconds = 10 minutes before deposits are refunded
362
+ }
357
363
  });
364
+
365
+ console.log('depositAddressResp', depositAddressResponse);
358
366
  const txData = {
359
367
  address,
360
368
  provider: this.providerInfo,
@@ -28,6 +28,9 @@ function getBlockExplorerAccountRoute(explorerLink) {
28
28
  if (explorerLink.includes('invarch.statescan.io')) {
29
29
  return '#/accounts';
30
30
  }
31
+ if (explorerLink.includes('explorer.zkverify.io')) {
32
+ return 'account';
33
+ }
31
34
  return 'address';
32
35
  }
33
36
  function getBlockExplorerTxRoute(chainInfo) {
@@ -49,6 +52,9 @@ export function getExplorerLink(chainInfo, value, type) {
49
52
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${value}`;
50
53
  }
51
54
  if (explorerLink && value.startsWith('0x')) {
55
+ if (chainInfo.slug === 'bittensor') {
56
+ return undefined;
57
+ }
52
58
  const route = getBlockExplorerTxRoute(chainInfo);
53
59
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${value}`;
54
60
  }
@@ -157,3 +157,4 @@ export interface SlippageType {
157
157
  slippage: BigN;
158
158
  isCustomType: boolean;
159
159
  }
160
+ export declare const CHAINFLIP_SLIPPAGE = 0.02;
@@ -38,4 +38,5 @@ export let SwapFeeType;
38
38
  SwapFeeType["PLATFORM_FEE"] = "PLATFORM_FEE";
39
39
  SwapFeeType["NETWORK_FEE"] = "NETWORK_FEE";
40
40
  SwapFeeType["WALLET_FEE"] = "WALLET_FEE";
41
- })(SwapFeeType || (SwapFeeType = {}));
41
+ })(SwapFeeType || (SwapFeeType = {}));
42
+ export const CHAINFLIP_SLIPPAGE = 0.02; // Example: 0.01 for 1%
@@ -185,6 +185,8 @@ export const findSoloNextDerive = parentAddress => {
185
185
  }
186
186
  if (deriveIndex === index) {
187
187
  index++;
188
+ } else if (currentDepth === 0 && deriveIndex === 0 && index > deriveIndex) {
189
+ // Special case for the first account on the root
188
190
  } else {
189
191
  break;
190
192
  }
@@ -86,6 +86,8 @@ export const findUnifiedNextDerive = (proxyId, accounts) => {
86
86
  }
87
87
  if (deriveIndex === index) {
88
88
  index++;
89
+ } else if (currentDepth === 0 && deriveIndex === 0 && index > deriveIndex) {
90
+ // Special case for the first account on the root
89
91
  } else {
90
92
  break;
91
93
  }
@@ -395,10 +395,10 @@ export const _combineAccounts = (accounts, modifyPairs, accountProxies) => {
395
395
  accountActions.push(AccountActions.EXPORT_MNEMONIC);
396
396
  }
397
397
 
398
- // // Json
399
- // if (value.accounts.every((account) => account.accountActions.includes(AccountActions.EXPORT_JSON))) {
400
- // accountActions.push(AccountActions.EXPORT_JSON);
401
- // }
398
+ // Json
399
+ if (value.accounts.every(account => account.accountActions.includes(AccountActions.EXPORT_JSON))) {
400
+ accountActions.push(AccountActions.EXPORT_JSON);
401
+ }
402
402
 
403
403
  // Derive
404
404
  if (value.accounts.every(account => account.accountActions.includes(AccountActions.DERIVE))) {