@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.
- package/background/KoniTypes.d.ts +5 -1
- package/cjs/constants/index.js +7 -1
- package/cjs/koni/api/nft/assethub_nft/index.js +30 -7
- package/cjs/koni/api/nft/config.js +11 -1
- package/cjs/koni/api/nft/index.js +9 -0
- package/cjs/koni/api/nft/ternoa_nft/index.js +174 -0
- package/cjs/koni/api/staking/bonding/utils.js +1 -1
- package/cjs/koni/background/handlers/Extension.js +67 -32
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +9 -0
- package/cjs/services/chain-service/constants.js +2 -1
- package/cjs/services/chain-service/index.js +11 -14
- package/cjs/services/earning-service/constants/chains.js +2 -1
- package/cjs/services/earning-service/handlers/base.js +2 -1
- package/cjs/services/earning-service/handlers/native-staking/index.js +8 -1
- package/cjs/services/earning-service/handlers/native-staking/tao.js +394 -0
- package/cjs/services/earning-service/service.js +3 -0
- package/cjs/services/earning-service/utils/index.js +2 -0
- package/cjs/services/keyring-service/context/handlers/Modify.js +11 -3
- package/cjs/services/keyring-service/context/state.js +2 -3
- package/cjs/services/keyring-service/index.js +1 -1
- package/cjs/services/swap-service/handler/chainflip-handler.js +13 -5
- package/cjs/services/transaction-service/utils.js +6 -0
- package/cjs/types/swap/index.js +4 -2
- package/cjs/utils/account/derive/info/solo.js +2 -0
- package/cjs/utils/account/derive/info/unified.js +2 -0
- package/cjs/utils/account/transform.js +4 -4
- package/constants/index.d.ts +2 -0
- package/constants/index.js +2 -0
- package/koni/api/nft/assethub_nft/index.d.ts +2 -0
- package/koni/api/nft/assethub_nft/index.js +30 -7
- package/koni/api/nft/config.d.ts +4 -0
- package/koni/api/nft/config.js +6 -0
- package/koni/api/nft/index.js +9 -0
- package/koni/api/nft/ternoa_nft/index.d.ts +32 -0
- package/koni/api/nft/ternoa_nft/index.js +167 -0
- package/koni/api/staking/bonding/utils.js +1 -1
- package/koni/background/handlers/Extension.d.ts +1 -0
- package/koni/background/handlers/Extension.js +38 -3
- package/package.json +16 -6
- package/packageInfo.js +1 -1
- package/services/balance-service/helpers/subscribe/substrate/index.js +9 -0
- package/services/chain-service/constants.d.ts +1 -0
- package/services/chain-service/constants.js +2 -1
- package/services/chain-service/index.js +11 -14
- package/services/earning-service/constants/chains.d.ts +1 -0
- package/services/earning-service/constants/chains.js +2 -1
- package/services/earning-service/handlers/base.js +2 -1
- package/services/earning-service/handlers/native-staking/index.d.ts +1 -0
- package/services/earning-service/handlers/native-staking/index.js +2 -1
- package/services/earning-service/handlers/native-staking/tao.d.ts +49 -0
- package/services/earning-service/handlers/native-staking/tao.js +378 -0
- package/services/earning-service/service.js +4 -1
- package/services/earning-service/utils/index.js +2 -0
- package/services/keyring-service/context/handlers/Modify.js +11 -3
- package/services/keyring-service/context/state.js +2 -3
- package/services/keyring-service/index.d.ts +1 -1
- package/services/keyring-service/index.js +1 -1
- package/services/swap-service/handler/chainflip-handler.js +13 -5
- package/services/transaction-service/utils.js +6 -0
- package/types/swap/index.d.ts +1 -0
- package/types/swap/index.js +2 -1
- package/utils/account/derive/info/solo.js +2 -0
- package/utils/account/derive/info/unified.js +2 -0
- 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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/types/swap/index.d.ts
CHANGED
package/types/swap/index.js
CHANGED
|
@@ -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
|
-
//
|
|
399
|
-
|
|
400
|
-
|
|
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))) {
|