@subwallet/extension-base 1.3.69-0 → 1.3.71-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 +11 -0
- package/background/KoniTypes.js +68 -8
- package/cjs/background/KoniTypes.js +68 -8
- package/cjs/constants/blocked-actions.js +3 -0
- package/cjs/core/logic-validation/swap.js +0 -3
- package/cjs/core/substrate/system-pallet.js +0 -2
- package/cjs/koni/api/nft/wasm_nft/index.js +0 -1
- package/cjs/koni/api/staking/bonding/astar.js +0 -2
- package/cjs/koni/api/staking/bonding/paraChain.js +0 -3
- package/cjs/koni/api/staking/bonding/relayChain.js +2 -4
- package/cjs/koni/api/staking/bonding/utils.js +0 -4
- package/cjs/koni/background/cron.js +0 -1
- package/cjs/koni/background/handlers/Extension.js +216 -158
- package/cjs/koni/background/handlers/State.js +59 -54
- package/cjs/koni/background/handlers/Tabs.js +39 -34
- package/cjs/packageInfo.js +1 -1
- package/cjs/page/index.js +7 -0
- package/cjs/page/substrate/PostMessageProvider.js +3 -0
- package/cjs/services/balance-service/helpers/subscribe/cardano/utils.js +0 -1
- package/cjs/services/balance-service/helpers/subscribe/substrate/gear.js +0 -2
- package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +2 -3
- package/cjs/services/balance-service/helpers/subscribe/ton/utils.js +0 -3
- package/cjs/services/balance-service/index.js +103 -7
- package/cjs/services/balance-service/transfer/bitcoin-transfer.js +0 -1
- package/cjs/services/balance-service/transfer/cardano-transfer.js +1 -2
- package/cjs/services/balance-service/transfer/smart-contract.js +0 -1
- package/cjs/services/balance-service/transfer/token.js +0 -2
- package/cjs/services/balance-service/transfer/ton-transfer.js +0 -1
- package/cjs/services/balance-service/transfer/xcm/snowBridge.js +0 -1
- package/cjs/services/chain-service/constants.js +15 -4
- package/cjs/services/chain-service/handler/CardanoApi.js +3 -1
- package/cjs/services/chain-service/handler/SubstrateApi.js +0 -2
- package/cjs/services/chain-service/handler/light-client/index.js +1 -2
- package/cjs/services/chain-service/health-check/index.js +0 -1
- package/cjs/services/chain-service/health-check/utils/new-utils/chain-asset-validate.js +0 -1
- package/cjs/services/chain-service/index.js +18 -26
- package/cjs/services/chain-service/utils/index.js +34 -30
- package/cjs/services/earning-service/handlers/base.js +32 -0
- package/cjs/services/earning-service/handlers/lending/base.js +0 -2
- package/cjs/services/earning-service/handlers/liquid-staking/acala.js +0 -1
- package/cjs/services/earning-service/handlers/liquid-staking/base.js +0 -2
- package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +0 -2
- package/cjs/services/earning-service/handlers/liquid-staking/parallel.js +0 -1
- package/cjs/services/earning-service/handlers/native-staking/astar.js +0 -2
- package/cjs/services/earning-service/handlers/native-staking/dtao.js +43 -2
- package/cjs/services/earning-service/handlers/native-staking/energy.js +0 -1
- package/cjs/services/earning-service/handlers/native-staking/mythos.js +0 -2
- package/cjs/services/earning-service/handlers/native-staking/para-chain.js +0 -2
- package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +8 -9
- package/cjs/services/earning-service/handlers/special.js +7 -0
- package/cjs/services/event-service/index.js +1 -0
- package/cjs/services/history-service/subsquid-multi-chain-history.js +0 -1
- package/cjs/services/keyring-service/context/handlers/Derive.js +1 -1
- package/cjs/services/keyring-service/context/handlers/Migration.js +11 -9
- package/cjs/services/keyring-service/context/handlers/Mnemonic.js +18 -13
- package/cjs/services/keyring-service/context/state.js +21 -3
- package/cjs/services/keyring-service/utils.js +12 -2
- package/cjs/services/migration-service/index.js +1 -2
- package/cjs/services/mint-campaign-service/campaigns/UnlockDotCampaign.js +0 -1
- package/cjs/services/nft-service/index.js +5 -0
- package/cjs/services/open-gov/handler.js +561 -0
- package/cjs/services/open-gov/index.js +273 -0
- package/cjs/services/open-gov/interface.js +31 -0
- package/cjs/services/open-gov/utils.js +66 -0
- package/cjs/services/request-service/handler/BitcoinRequestHandler.js +1 -2
- package/cjs/services/request-service/handler/CardanoRequestHandler.js +0 -1
- package/cjs/services/request-service/handler/EvmRequestHandler.js +0 -1
- package/cjs/services/request-service/handler/TonRequestHandler.js +0 -1
- package/cjs/services/request-service/helper/index.js +1 -2
- package/cjs/services/storage-service/DatabaseService.js +19 -3
- package/cjs/services/storage-service/databases/index.js +5 -0
- package/cjs/services/storage-service/db-stores/GovLockedInfoStore.js +35 -0
- package/cjs/services/swap-service/handler/asset-hub/handler.js +0 -1
- package/cjs/services/swap-service/handler/asset-hub/router.js +0 -1
- package/cjs/services/swap-service/handler/chainflip-handler.js +1 -4
- package/cjs/services/swap-service/handler/hydradx-handler.js +0 -1
- package/cjs/services/swap-service/handler/kyber-handler.js +0 -1
- package/cjs/services/swap-service/handler/optimex-handler.js +1 -2
- package/cjs/services/swap-service/handler/simpleswap-handler.js +1 -3
- package/cjs/services/swap-service/handler/uniswap-handler.js +0 -3
- package/cjs/services/transaction-service/event-parser/index.js +6 -6
- package/cjs/services/transaction-service/helpers/index.js +6 -0
- package/cjs/services/transaction-service/index.js +71 -28
- package/cjs/services/wallet-connect-service/index.js +21 -18
- package/cjs/services/wallet-connect-service/types.js +1 -1
- package/cjs/types/account/info/keyring.js +9 -1
- package/cjs/types/balance/index.js +5 -1
- package/cjs/types/swap/index.js +2 -1
- package/cjs/types/transaction/process.js +2 -0
- package/cjs/types/yield/actions/join/step.js +17 -1
- package/cjs/utils/account/common.js +0 -26
- package/cjs/utils/account/derive/info/solo.js +7 -4
- package/cjs/utils/account/derive/validate.js +1 -1
- package/cjs/utils/account/transform.js +10 -5
- package/cjs/utils/auth.js +1 -1
- package/cjs/utils/bitcoin/utxo-management.js +0 -1
- package/cjs/utils/environment.js +2 -1
- package/cjs/utils/fee/transfer.js +1 -2
- package/cjs/utils/index.js +1 -2
- package/constants/blocked-actions.js +3 -0
- package/core/logic-validation/swap.js +0 -3
- package/core/substrate/system-pallet.js +0 -2
- package/koni/api/nft/wasm_nft/index.js +0 -1
- package/koni/api/staking/bonding/astar.js +0 -2
- package/koni/api/staking/bonding/paraChain.js +0 -3
- package/koni/api/staking/bonding/relayChain.js +2 -4
- package/koni/api/staking/bonding/utils.js +0 -4
- package/koni/background/cron.js +0 -1
- package/koni/background/handlers/Extension.d.ts +4 -0
- package/koni/background/handlers/Extension.js +70 -11
- package/koni/background/handlers/State.d.ts +2 -0
- package/koni/background/handlers/State.js +46 -40
- package/koni/background/handlers/Tabs.js +9 -3
- package/package.json +44 -20
- package/packageInfo.js +1 -1
- package/page/substrate/PostMessageProvider.js +3 -0
- package/services/balance-service/helpers/subscribe/cardano/utils.js +0 -1
- package/services/balance-service/helpers/subscribe/substrate/gear.js +0 -2
- package/services/balance-service/helpers/subscribe/substrate/index.js +0 -1
- package/services/balance-service/helpers/subscribe/ton/utils.js +0 -3
- package/services/balance-service/index.d.ts +8 -0
- package/services/balance-service/index.js +105 -9
- package/services/balance-service/transfer/bitcoin-transfer.js +0 -1
- package/services/balance-service/transfer/smart-contract.js +0 -1
- package/services/balance-service/transfer/token.js +0 -2
- package/services/balance-service/transfer/ton-transfer.js +0 -1
- package/services/balance-service/transfer/xcm/snowBridge.js +0 -1
- package/services/chain-service/constants.d.ts +8 -0
- package/services/chain-service/constants.js +12 -2
- package/services/chain-service/handler/CardanoApi.js +3 -1
- package/services/chain-service/handler/SubstrateApi.js +0 -2
- package/services/chain-service/health-check/index.js +0 -1
- package/services/chain-service/health-check/utils/new-utils/chain-asset-validate.js +0 -1
- package/services/chain-service/index.d.ts +0 -1
- package/services/chain-service/index.js +15 -23
- package/services/chain-service/utils/index.js +35 -31
- package/services/earning-service/handlers/base.js +32 -0
- package/services/earning-service/handlers/lending/base.js +0 -2
- package/services/earning-service/handlers/liquid-staking/acala.js +0 -1
- package/services/earning-service/handlers/liquid-staking/base.js +0 -2
- package/services/earning-service/handlers/liquid-staking/bifrost.js +0 -2
- package/services/earning-service/handlers/liquid-staking/parallel.js +0 -1
- package/services/earning-service/handlers/native-staking/astar.js +0 -2
- package/services/earning-service/handlers/native-staking/dtao.js +43 -0
- package/services/earning-service/handlers/native-staking/energy.js +0 -1
- package/services/earning-service/handlers/native-staking/mythos.js +0 -2
- package/services/earning-service/handlers/native-staking/para-chain.js +0 -2
- package/services/earning-service/handlers/native-staking/relay-chain.js +8 -9
- package/services/earning-service/handlers/special.js +7 -0
- package/services/event-service/index.d.ts +1 -0
- package/services/event-service/index.js +1 -0
- package/services/event-service/types.d.ts +1 -0
- package/services/history-service/subsquid-multi-chain-history.js +0 -1
- package/services/keyring-service/context/handlers/Derive.js +2 -2
- package/services/keyring-service/context/handlers/Migration.js +3 -1
- package/services/keyring-service/context/handlers/Mnemonic.d.ts +1 -1
- package/services/keyring-service/context/handlers/Mnemonic.js +16 -10
- package/services/keyring-service/context/state.d.ts +3 -0
- package/services/keyring-service/context/state.js +21 -3
- package/services/keyring-service/utils.d.ts +1 -0
- package/services/keyring-service/utils.js +9 -0
- package/services/mint-campaign-service/campaigns/UnlockDotCampaign.js +0 -1
- package/services/nft-service/index.js +6 -0
- package/services/open-gov/handler.d.ts +27 -0
- package/services/open-gov/handler.js +545 -0
- package/services/open-gov/index.d.ts +45 -0
- package/services/open-gov/index.js +265 -0
- package/services/open-gov/interface.d.ts +141 -0
- package/services/open-gov/interface.js +24 -0
- package/services/open-gov/utils.d.ts +14 -0
- package/services/open-gov/utils.js +52 -0
- package/services/request-service/handler/CardanoRequestHandler.js +0 -1
- package/services/request-service/handler/EvmRequestHandler.js +0 -1
- package/services/request-service/handler/TonRequestHandler.js +0 -1
- package/services/setting-service/constants.js +0 -1
- package/services/storage-service/DatabaseService.d.ts +7 -0
- package/services/storage-service/DatabaseService.js +19 -3
- package/services/storage-service/databases/index.d.ts +2 -0
- package/services/storage-service/databases/index.js +6 -0
- package/services/storage-service/db-stores/GovLockedInfoStore.d.ts +10 -0
- package/services/storage-service/db-stores/GovLockedInfoStore.js +27 -0
- package/services/swap-service/handler/asset-hub/handler.js +0 -1
- package/services/swap-service/handler/asset-hub/router.js +0 -1
- package/services/swap-service/handler/chainflip-handler.js +0 -2
- package/services/swap-service/handler/hydradx-handler.js +0 -1
- package/services/swap-service/handler/kyber-handler.js +0 -1
- package/services/swap-service/handler/simpleswap-handler.js +0 -1
- package/services/swap-service/handler/uniswap-handler.js +0 -3
- package/services/transaction-service/event-parser/index.js +6 -6
- package/services/transaction-service/helpers/index.js +6 -0
- package/services/transaction-service/index.js +43 -0
- package/services/wallet-connect-service/index.js +21 -18
- package/services/wallet-connect-service/types.js +1 -1
- package/types/account/action/add/mnemonic.d.ts +3 -2
- package/types/account/info/keyring.js +9 -1
- package/types/balance/index.js +5 -1
- package/types/swap/index.js +2 -1
- package/types/transaction/process.js +3 -1
- package/types/yield/actions/join/step.js +17 -1
- package/utils/account/common.d.ts +0 -3
- package/utils/account/common.js +0 -24
- package/utils/account/derive/info/solo.js +8 -5
- package/utils/account/derive/validate.d.ts +2 -2
- package/utils/account/derive/validate.js +1 -1
- package/utils/account/transform.js +10 -5
- package/utils/auth.js +2 -2
- package/utils/bitcoin/utxo-management.js +0 -1
- package/utils/index.js +2 -5
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _TransactionError = require("@subwallet/extension-base/background/errors/TransactionError");
|
|
9
|
+
var _types = require("@subwallet/extension-base/types");
|
|
10
|
+
var _number = require("@subwallet/extension-base/utils/number");
|
|
11
|
+
var _bignumber = _interopRequireDefault(require("bignumber.js"));
|
|
12
|
+
var _rxjs = require("rxjs");
|
|
13
|
+
var _constants = require("../chain-service/constants");
|
|
14
|
+
var _utils = require("../chain-service/utils");
|
|
15
|
+
var _interface = require("./interface");
|
|
16
|
+
var _utils2 = require("./utils");
|
|
17
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
18
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
19
|
+
|
|
20
|
+
class BaseOpenGovHandler {
|
|
21
|
+
constructor(state, chain) {
|
|
22
|
+
this.state = state;
|
|
23
|
+
this.chain = chain;
|
|
24
|
+
}
|
|
25
|
+
get substrateApi() {
|
|
26
|
+
return this.state.getSubstrateApi(this.chain);
|
|
27
|
+
}
|
|
28
|
+
get chainInfo() {
|
|
29
|
+
return this.state.getChainInfo(this.chain);
|
|
30
|
+
}
|
|
31
|
+
get nativeToken() {
|
|
32
|
+
return this.state.getNativeTokenInfo(this.chain);
|
|
33
|
+
}
|
|
34
|
+
lockPeriod(days) {
|
|
35
|
+
var _EXPECTED_BLOCK_TIME$;
|
|
36
|
+
const blockTime = (_EXPECTED_BLOCK_TIME$ = _constants._EXPECTED_BLOCK_TIME[this.chain]) !== null && _EXPECTED_BLOCK_TIME$ !== void 0 ? _EXPECTED_BLOCK_TIME$ : 6;
|
|
37
|
+
const baseLockedPeriod = 24 * 60 * 60 * days;
|
|
38
|
+
return baseLockedPeriod / blockTime;
|
|
39
|
+
}
|
|
40
|
+
refToTrackMap = new Map();
|
|
41
|
+
|
|
42
|
+
/* Referendum related actions */
|
|
43
|
+
|
|
44
|
+
async handleVote(request) {
|
|
45
|
+
const earlyError = await this.earlyValidateVoting(request);
|
|
46
|
+
if (earlyError) {
|
|
47
|
+
return Promise.reject(earlyError);
|
|
48
|
+
}
|
|
49
|
+
switch (request.type) {
|
|
50
|
+
case _interface.GovVoteType.AYE:
|
|
51
|
+
case _interface.GovVoteType.NAY:
|
|
52
|
+
return this.handleStandardVote(request);
|
|
53
|
+
case _interface.GovVoteType.SPLIT:
|
|
54
|
+
return this.handleSplitVote(request);
|
|
55
|
+
case _interface.GovVoteType.ABSTAIN:
|
|
56
|
+
return this.handleSplitAbstainVote(request);
|
|
57
|
+
default:
|
|
58
|
+
throw new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS, 'Unsupported vote type');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async handleStandardVote(request) {
|
|
62
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
63
|
+
const earlyError = await this.validateConvictionAndBalance(request.address, request.amount, request.conviction);
|
|
64
|
+
if (earlyError) {
|
|
65
|
+
return Promise.reject(earlyError);
|
|
66
|
+
}
|
|
67
|
+
const extrinsic = substrateApi.api.tx.convictionVoting.vote(request.referendumIndex, {
|
|
68
|
+
Standard: {
|
|
69
|
+
vote: {
|
|
70
|
+
aye: request.type === _interface.GovVoteType.AYE,
|
|
71
|
+
conviction: _utils2.numberToConviction[request.conviction]
|
|
72
|
+
},
|
|
73
|
+
balance: request.amount
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return extrinsic;
|
|
77
|
+
}
|
|
78
|
+
async handleSplitVote(request) {
|
|
79
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
80
|
+
const earlyError = await this.validateSplitAbstainAmount(request.address, false, request.ayeAmount, request.nayAmount);
|
|
81
|
+
if (earlyError) {
|
|
82
|
+
return Promise.reject(earlyError);
|
|
83
|
+
}
|
|
84
|
+
const extrinsic = substrateApi.api.tx.convictionVoting.vote(request.referendumIndex, {
|
|
85
|
+
Split: {
|
|
86
|
+
aye: request.ayeAmount,
|
|
87
|
+
nay: request.nayAmount
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return extrinsic;
|
|
91
|
+
}
|
|
92
|
+
async handleSplitAbstainVote(request) {
|
|
93
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
94
|
+
const earlyError = await this.validateSplitAbstainAmount(request.address, true, request.ayeAmount, request.nayAmount, request.abstainAmount);
|
|
95
|
+
if (earlyError) {
|
|
96
|
+
return Promise.reject(earlyError);
|
|
97
|
+
}
|
|
98
|
+
const extrinsic = substrateApi.api.tx.convictionVoting.vote(request.referendumIndex, {
|
|
99
|
+
SplitAbstain: {
|
|
100
|
+
aye: request.ayeAmount,
|
|
101
|
+
nay: request.nayAmount,
|
|
102
|
+
abstain: request.abstainAmount
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return extrinsic;
|
|
106
|
+
}
|
|
107
|
+
async handleRemoveVote(request) {
|
|
108
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
109
|
+
const extrinsic = substrateApi.api.tx.convictionVoting.removeVote(request.trackId, request.referendumIndex);
|
|
110
|
+
return extrinsic;
|
|
111
|
+
}
|
|
112
|
+
async handleUnlockVote(request) {
|
|
113
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
114
|
+
const {
|
|
115
|
+
address,
|
|
116
|
+
referendumIds,
|
|
117
|
+
trackIds
|
|
118
|
+
} = request;
|
|
119
|
+
const extrinsics = [];
|
|
120
|
+
|
|
121
|
+
// 1. Unlock all refs
|
|
122
|
+
for (const refIndex of referendumIds !== null && referendumIds !== void 0 ? referendumIds : []) {
|
|
123
|
+
const trackId = this.refToTrackMap.get(refIndex);
|
|
124
|
+
extrinsics.push(substrateApi.api.tx.convictionVoting.removeVote(trackId !== null && trackId !== void 0 ? trackId : null, refIndex));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 2. Unlock all tracks
|
|
128
|
+
for (const trackId of trackIds !== null && trackIds !== void 0 ? trackIds : []) {
|
|
129
|
+
extrinsics.push(substrateApi.api.tx.convictionVoting.unlock(trackId, address));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 3. Decide whether to batch or not
|
|
133
|
+
if (extrinsics.length === 1) {
|
|
134
|
+
return extrinsics[0];
|
|
135
|
+
}
|
|
136
|
+
if (extrinsics.length === 0) {
|
|
137
|
+
return Promise.reject(new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS));
|
|
138
|
+
}
|
|
139
|
+
return substrateApi.api.tx.utility.batchAll(extrinsics);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* Validate OpengGov Action */
|
|
143
|
+
|
|
144
|
+
async earlyValidateVoting(request) {
|
|
145
|
+
var _locked$delegating;
|
|
146
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
147
|
+
const {
|
|
148
|
+
address,
|
|
149
|
+
trackId
|
|
150
|
+
} = request;
|
|
151
|
+
const locked = (await substrateApi.api.query.convictionVoting.votingFor(address, trackId)).toPrimitive();
|
|
152
|
+
if (!locked) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
if (locked !== null && locked !== void 0 && (_locked$delegating = locked.delegating) !== null && _locked$delegating !== void 0 && _locked$delegating.balance && new _bignumber.default(locked.delegating.balance).gt(0)) {
|
|
156
|
+
return new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS, `Already delegating on track ${trackId}`);
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
async validateConvictionAndBalance(address, balance, conviction) {
|
|
161
|
+
if (!balance) {
|
|
162
|
+
return new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS, 'Amount is required');
|
|
163
|
+
}
|
|
164
|
+
if (conviction < 0 || conviction > 6) {
|
|
165
|
+
return new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS, 'Invalid conviction');
|
|
166
|
+
}
|
|
167
|
+
const totalBalance = await this.state.balanceService.getTotalBalance(address, this.chain);
|
|
168
|
+
const bnBalance = new _bignumber.default(balance);
|
|
169
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
170
|
+
let estimatedFee = new _bignumber.default(0);
|
|
171
|
+
try {
|
|
172
|
+
const dummyTx = substrateApi.api.tx.convictionVoting.vote(0, {
|
|
173
|
+
Standard: {
|
|
174
|
+
vote: {
|
|
175
|
+
aye: true,
|
|
176
|
+
conviction
|
|
177
|
+
},
|
|
178
|
+
balance: bnBalance.toString()
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
const paymentInfo = await dummyTx.paymentInfo(address);
|
|
182
|
+
estimatedFee = new _bignumber.default(paymentInfo.partialFee.toString());
|
|
183
|
+
} catch (e) {
|
|
184
|
+
console.warn('Cannot estimate fee, fallback to default', e);
|
|
185
|
+
const decimals = Number((0, _utils._getAssetDecimals)(this.nativeToken));
|
|
186
|
+
estimatedFee = new _bignumber.default(0.001).multipliedBy(new _bignumber.default(10).pow(decimals)); // fallback 0.001
|
|
187
|
+
}
|
|
188
|
+
const availableBalance = new _bignumber.default(totalBalance.value).minus(estimatedFee);
|
|
189
|
+
if (availableBalance.lte(0)) {
|
|
190
|
+
return new _TransactionError.TransactionError(_types.BasicTxErrorType.NOT_ENOUGH_BALANCE, "You don't have enough tokens to proceed");
|
|
191
|
+
}
|
|
192
|
+
if (bnBalance.gt(availableBalance)) {
|
|
193
|
+
return new _TransactionError.TransactionError(_types.BasicTxErrorType.NOT_ENOUGH_BALANCE, `Amount must be equal or less than ${(0, _number.formatNumber)(availableBalance, (0, _utils._getAssetDecimals)(this.nativeToken))}`);
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
async validateSplitAbstainAmount(address) {
|
|
198
|
+
let isSplitAbstain = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
199
|
+
let aye = arguments.length > 2 ? arguments[2] : undefined;
|
|
200
|
+
let nay = arguments.length > 3 ? arguments[3] : undefined;
|
|
201
|
+
let abstain = arguments.length > 4 ? arguments[4] : undefined;
|
|
202
|
+
if (!nay || !aye) {
|
|
203
|
+
return new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS, 'Amount is required');
|
|
204
|
+
}
|
|
205
|
+
const values = [new _bignumber.default(aye), new _bignumber.default(nay), new _bignumber.default(abstain !== null && abstain !== void 0 ? abstain : '0')];
|
|
206
|
+
const total = values.reduce((acc, val) => acc.plus(val), new _bignumber.default(0));
|
|
207
|
+
const totalBalance = await this.state.balanceService.getTotalBalance(address, this.chain);
|
|
208
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
209
|
+
let dummyTx;
|
|
210
|
+
try {
|
|
211
|
+
dummyTx = substrateApi.api.tx.convictionVoting.vote(1,
|
|
212
|
+
// dummy referendum id
|
|
213
|
+
isSplitAbstain ? {
|
|
214
|
+
SplitAbstain: {
|
|
215
|
+
aye: 1,
|
|
216
|
+
nay: 1,
|
|
217
|
+
abstain: 1
|
|
218
|
+
}
|
|
219
|
+
} : {
|
|
220
|
+
Split: {
|
|
221
|
+
aye: 1,
|
|
222
|
+
nay: 1
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
} catch (e) {
|
|
226
|
+
console.warn('Cannot build dummy tx for fee estimation', e);
|
|
227
|
+
}
|
|
228
|
+
let estimatedFee = new _bignumber.default(0);
|
|
229
|
+
if (dummyTx) {
|
|
230
|
+
try {
|
|
231
|
+
const paymentInfo = await dummyTx.paymentInfo(address);
|
|
232
|
+
estimatedFee = new _bignumber.default(paymentInfo.partialFee.toString());
|
|
233
|
+
} catch (e) {
|
|
234
|
+
console.warn('Cannot get payment info, fallback to default fee', e);
|
|
235
|
+
estimatedFee = new _bignumber.default(0.001 * 10 ** (0, _utils._getAssetDecimals)(this.nativeToken)); // fallback 0.001
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const availableBalance = new _bignumber.default(totalBalance.value).minus(estimatedFee);
|
|
239
|
+
if (availableBalance.lte(0)) {
|
|
240
|
+
return new _TransactionError.TransactionError(_types.BasicTxErrorType.NOT_ENOUGH_BALANCE, "You don't have enough tokens to proceed");
|
|
241
|
+
}
|
|
242
|
+
if (total.gt(availableBalance)) {
|
|
243
|
+
return new _TransactionError.TransactionError(_types.BasicTxErrorType.NOT_ENOUGH_BALANCE, `Amount must be equal or less than ${(0, _number.formatNumber)(availableBalance, (0, _utils._getAssetDecimals)(this.nativeToken))}`);
|
|
244
|
+
}
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* Lock info */
|
|
249
|
+
async subscribeGovLockedInfo(addresses, cb) {
|
|
250
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
251
|
+
const streams = addresses.map(addr => {
|
|
252
|
+
return (0, _rxjs.combineLatest)([substrateApi.api.query.convictionVoting.votingFor.entries(addr), substrateApi.api.query.convictionVoting.classLocksFor(addr)]).pipe((0, _rxjs.mergeMap)(async _ref => {
|
|
253
|
+
let [votingEntries, classLocks] = _ref;
|
|
254
|
+
let totalDelegated = new _bignumber.default(0);
|
|
255
|
+
let totalVoted = new _bignumber.default(0);
|
|
256
|
+
const tracks = [];
|
|
257
|
+
const trackBalances = new Map();
|
|
258
|
+
const trackStates = new Map();
|
|
259
|
+
const trackVotedAmounts = new Map();
|
|
260
|
+
const unlockingReferenda = [];
|
|
261
|
+
const unlockableReferenda = new Set();
|
|
262
|
+
const trackVotes = new Map();
|
|
263
|
+
const trackPriorBlocks = new Map();
|
|
264
|
+
let totalLocked = new _bignumber.default(0);
|
|
265
|
+
|
|
266
|
+
// --- Collect locked balances per track ---
|
|
267
|
+
const classLocksArray = classLocks.toPrimitive();
|
|
268
|
+
for (const [trackId, balance] of classLocksArray) {
|
|
269
|
+
const bnBalance = new _bignumber.default(balance);
|
|
270
|
+
trackBalances.set(trackId, bnBalance);
|
|
271
|
+
totalLocked = _bignumber.default.max(totalLocked, bnBalance);
|
|
272
|
+
}
|
|
273
|
+
let currentBlock;
|
|
274
|
+
if (_utils2.MIGRATED_CHAINS.includes(this.chain) && substrateApi.api.query.parachainSystem && substrateApi.api.query.parachainSystem.lastRelayChainBlockNumber) {
|
|
275
|
+
const blockRootsRaw = await substrateApi.api.query.parachainSystem.lastRelayChainBlockNumber();
|
|
276
|
+
const blockRoots = blockRootsRaw === null || blockRootsRaw === void 0 ? void 0 : blockRootsRaw.toPrimitive();
|
|
277
|
+
if (blockRoots) {
|
|
278
|
+
currentBlock = new _bignumber.default(blockRoots);
|
|
279
|
+
} else {
|
|
280
|
+
const currentBlockInfo = await substrateApi.api.rpc.chain.getHeader();
|
|
281
|
+
currentBlock = new _bignumber.default(currentBlockInfo.toPrimitive().number);
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
// fallback
|
|
285
|
+
const currentBlockInfo = await substrateApi.api.rpc.chain.getHeader();
|
|
286
|
+
currentBlock = new _bignumber.default(currentBlockInfo.toPrimitive().number);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// --- Handle each voting entry per track ---
|
|
290
|
+
for (const [key, voting] of votingEntries) {
|
|
291
|
+
const trackId = key.args[1].toPrimitive();
|
|
292
|
+
const v = voting.toPrimitive();
|
|
293
|
+
if (v.delegating) {
|
|
294
|
+
// Track is delegating → store delegation info
|
|
295
|
+
trackStates.set(trackId, 'delegating');
|
|
296
|
+
const {
|
|
297
|
+
balance,
|
|
298
|
+
conviction,
|
|
299
|
+
target
|
|
300
|
+
} = v.delegating;
|
|
301
|
+
const delegation = {
|
|
302
|
+
balance: balance.toString(),
|
|
303
|
+
target,
|
|
304
|
+
conviction
|
|
305
|
+
};
|
|
306
|
+
tracks.push({
|
|
307
|
+
trackId,
|
|
308
|
+
delegation
|
|
309
|
+
});
|
|
310
|
+
} else if (v.casting) {
|
|
311
|
+
trackStates.set(trackId, 'casting');
|
|
312
|
+
const priorBlock = new _bignumber.default(v.casting.prior[0]);
|
|
313
|
+
const priorBalance = new _bignumber.default(v.casting.prior[1]);
|
|
314
|
+
if (!currentBlock.gte(priorBlock)) {
|
|
315
|
+
var _EXPECTED_BLOCK_TIME$2;
|
|
316
|
+
// --- Still locked → estimate unlock timestamp ---
|
|
317
|
+
const blockTimeSec = (_EXPECTED_BLOCK_TIME$2 = _constants._EXPECTED_BLOCK_TIME[this.chain]) !== null && _EXPECTED_BLOCK_TIME$2 !== void 0 ? _EXPECTED_BLOCK_TIME$2 : 6;
|
|
318
|
+
const remainingBlocks = priorBlock.minus(currentBlock);
|
|
319
|
+
const timestamp = Date.now() + remainingBlocks.multipliedBy(blockTimeSec * 1000).toNumber();
|
|
320
|
+
unlockingReferenda.push({
|
|
321
|
+
id: `track_prior_${trackId}`,
|
|
322
|
+
balance: priorBalance.toFixed(),
|
|
323
|
+
timestamp
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// --- Parse votes and check if referenda are finished ---
|
|
328
|
+
const {
|
|
329
|
+
unlockingReferenda: trackUnlocking,
|
|
330
|
+
votes
|
|
331
|
+
} = await this.parseVotesAndCheckFinished(v.casting.votes || [], unlockableReferenda, currentBlock.toNumber(), substrateApi);
|
|
332
|
+
unlockingReferenda.push(...trackUnlocking);
|
|
333
|
+
trackVotes.set(trackId, votes);
|
|
334
|
+
for (const vote of votes) {
|
|
335
|
+
this.refToTrackMap.set(vote.referendumIndex.toString(), trackId);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// --- Calculate total voted amount per track ---
|
|
339
|
+
const totalCast = votes.reduce((sum, vote) => {
|
|
340
|
+
return sum.plus(new _bignumber.default(vote.ayeAmount || '0')).plus(new _bignumber.default(vote.nayAmount || '0')).plus(new _bignumber.default(vote.abstainAmount || '0'));
|
|
341
|
+
}, new _bignumber.default(0));
|
|
342
|
+
trackVotedAmounts.set(trackId, totalCast);
|
|
343
|
+
if (v.casting.prior && new _bignumber.default(v.casting.prior[0]).gt(0)) {
|
|
344
|
+
trackPriorBlocks.set(trackId, new _bignumber.default(v.casting.prior[0]));
|
|
345
|
+
}
|
|
346
|
+
tracks.push({
|
|
347
|
+
trackId,
|
|
348
|
+
votes: votes.length > 0 ? votes : undefined
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// --- Compute unlockable amounts across all tracks ---
|
|
354
|
+
const {
|
|
355
|
+
totalUnlockable,
|
|
356
|
+
unlockableTrackIds
|
|
357
|
+
} = this.calculateUnlockAmounts(trackBalances, trackStates, unlockableReferenda, trackVotes, trackPriorBlocks, currentBlock);
|
|
358
|
+
|
|
359
|
+
// --- Determine total delegated and voted locked balances ---
|
|
360
|
+
for (const [trackId, lockedBalance] of trackBalances) {
|
|
361
|
+
const state = trackStates.get(trackId) || 'empty';
|
|
362
|
+
if (state === 'delegating') {
|
|
363
|
+
totalDelegated = _bignumber.default.max(totalDelegated, lockedBalance);
|
|
364
|
+
} else if (state === 'casting') {
|
|
365
|
+
const votedAmount = trackVotedAmounts.get(trackId) || new _bignumber.default(0);
|
|
366
|
+
if (votedAmount.gt(0)) {
|
|
367
|
+
totalVoted = _bignumber.default.max(totalVoted, lockedBalance);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const result = {
|
|
372
|
+
chain: this.chain,
|
|
373
|
+
address: addr,
|
|
374
|
+
summary: {
|
|
375
|
+
delegated: totalDelegated.toString(),
|
|
376
|
+
voted: totalVoted.toString(),
|
|
377
|
+
totalLocked: totalLocked.toString(),
|
|
378
|
+
unlocking: {
|
|
379
|
+
unlockingReferenda
|
|
380
|
+
},
|
|
381
|
+
unlockable: {
|
|
382
|
+
balance: totalUnlockable.toFixed(),
|
|
383
|
+
trackIds: unlockableTrackIds,
|
|
384
|
+
unlockableReferenda: Array.from(unlockableReferenda).sort((a, b) => Number(a) - Number(b))
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
tracks
|
|
388
|
+
};
|
|
389
|
+
return result;
|
|
390
|
+
}));
|
|
391
|
+
});
|
|
392
|
+
const sub = (0, _rxjs.merge)(...streams).subscribe(cb);
|
|
393
|
+
return () => sub.unsubscribe();
|
|
394
|
+
}
|
|
395
|
+
async parseVotesAndCheckFinished(votesData, unlockableReferenda, currentBlockNumber, substrateApi) {
|
|
396
|
+
if (!votesData || votesData.length === 0) {
|
|
397
|
+
return {
|
|
398
|
+
votes: [],
|
|
399
|
+
unlockingReferenda: []
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
const votes = [];
|
|
403
|
+
const unlockingReferenda = [];
|
|
404
|
+
|
|
405
|
+
// --- Parse all vote types: standard / split / splitAbstain and normalize data
|
|
406
|
+
for (const [refIndex, vote] of votesData) {
|
|
407
|
+
if ('standard' in vote) {
|
|
408
|
+
const isAye = vote.standard.vote.aye === true;
|
|
409
|
+
votes.push({
|
|
410
|
+
referendumIndex: refIndex,
|
|
411
|
+
type: isAye ? _interface.GovVoteType.AYE : _interface.GovVoteType.NAY,
|
|
412
|
+
conviction: vote.standard.vote.conviction,
|
|
413
|
+
ayeAmount: isAye ? vote.standard.balance : '0',
|
|
414
|
+
nayAmount: !isAye ? vote.standard.balance : '0'
|
|
415
|
+
});
|
|
416
|
+
} else if ('split' in vote) {
|
|
417
|
+
votes.push({
|
|
418
|
+
referendumIndex: refIndex,
|
|
419
|
+
type: _interface.GovVoteType.SPLIT,
|
|
420
|
+
conviction: _interface.Conviction.None,
|
|
421
|
+
ayeAmount: vote.split.aye,
|
|
422
|
+
nayAmount: vote.split.nay
|
|
423
|
+
});
|
|
424
|
+
} else if ('splitAbstain' in vote) {
|
|
425
|
+
votes.push({
|
|
426
|
+
referendumIndex: refIndex,
|
|
427
|
+
type: _interface.GovVoteType.ABSTAIN,
|
|
428
|
+
conviction: _interface.Conviction.None,
|
|
429
|
+
ayeAmount: vote.splitAbstain.aye,
|
|
430
|
+
nayAmount: vote.splitAbstain.nay,
|
|
431
|
+
abstainAmount: vote.splitAbstain.abstain
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const refIndexes = votes.map(v => v.referendumIndex);
|
|
436
|
+
const referendumInfos = await substrateApi.api.query.referenda.referendumInfoFor.multi(refIndexes);
|
|
437
|
+
referendumInfos.forEach((info, i) => {
|
|
438
|
+
if (info.isSome) {
|
|
439
|
+
const referendum = info.unwrap();
|
|
440
|
+
const refIndex = refIndexes[i];
|
|
441
|
+
const voteDetail = votes[i];
|
|
442
|
+
if (referendum.isKilled || referendum.isTimedOut || referendum.isCancelled) {
|
|
443
|
+
unlockableReferenda.add(refIndex.toString());
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (!referendum.isOngoing) {
|
|
447
|
+
const referendumInfo = referendum.toJSON();
|
|
448
|
+
|
|
449
|
+
// 0x conviction (no lock) → unlock immediately
|
|
450
|
+
if (voteDetail.conviction === _interface.Conviction.None) {
|
|
451
|
+
unlockableReferenda.add(refIndex.toString());
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// --- Determine unlock block based on conviction ---
|
|
456
|
+
const statusKey = Object.keys(referendumInfo)[0];
|
|
457
|
+
const statusVal = referendumInfo[statusKey];
|
|
458
|
+
const endBlock = statusVal[0];
|
|
459
|
+
if (endBlock) {
|
|
460
|
+
const days = (0, _utils2.getConvictionDays)(this.chain, voteDetail.conviction);
|
|
461
|
+
const lockBlocks = this.lockPeriod(days);
|
|
462
|
+
const unlockBlock = new _bignumber.default(endBlock).plus(lockBlocks);
|
|
463
|
+
const canUnlock = new _bignumber.default(currentBlockNumber).gte(unlockBlock);
|
|
464
|
+
|
|
465
|
+
// Referendum ended → check if vote side allows unlock
|
|
466
|
+
const shouldUnlock = referendum.isApproved ? voteDetail.type === _interface.GovVoteType.NAY || canUnlock : voteDetail.type === _interface.GovVoteType.AYE || canUnlock;
|
|
467
|
+
if (shouldUnlock) {
|
|
468
|
+
unlockableReferenda.add(refIndex.toString());
|
|
469
|
+
} else {
|
|
470
|
+
var _EXPECTED_BLOCK_TIME$3;
|
|
471
|
+
// Can't unlock → calculate remaining lock time
|
|
472
|
+
const balance = new _bignumber.default(voteDetail.ayeAmount || '0').plus(new _bignumber.default(voteDetail.nayAmount || '0')).plus(new _bignumber.default(voteDetail.abstainAmount || '0'));
|
|
473
|
+
const blockTimeSec = (_EXPECTED_BLOCK_TIME$3 = _constants._EXPECTED_BLOCK_TIME[this.chain]) !== null && _EXPECTED_BLOCK_TIME$3 !== void 0 ? _EXPECTED_BLOCK_TIME$3 : 6;
|
|
474
|
+
const remainingBlocks = unlockBlock.minus(currentBlockNumber);
|
|
475
|
+
const timestamp = Date.now() + remainingBlocks.multipliedBy(blockTimeSec * 1000).toNumber();
|
|
476
|
+
unlockingReferenda.push({
|
|
477
|
+
id: refIndex.toString(),
|
|
478
|
+
balance: balance.toFixed(),
|
|
479
|
+
timestamp: timestamp
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
return {
|
|
487
|
+
votes,
|
|
488
|
+
unlockingReferenda
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
calculateUnlockAmounts(trackBalances, trackStates, unlockableReferenda, trackVotes, trackPriorBlocks, currentBlockNumber) {
|
|
492
|
+
const unlockableTrackIds = [];
|
|
493
|
+
|
|
494
|
+
// Determine which tracks are unlockable:
|
|
495
|
+
// - all votes finished
|
|
496
|
+
// - prior block passed
|
|
497
|
+
// - state is empty
|
|
498
|
+
// Calculate total unlockable amount = max(unlockable balance) - highest still locked balance
|
|
499
|
+
for (const [trackId, balance] of trackBalances) {
|
|
500
|
+
const state = trackStates.get(trackId) || 'empty';
|
|
501
|
+
const votes = trackVotes.get(trackId) || [];
|
|
502
|
+
const priorBlock = trackPriorBlocks.get(trackId) || new _bignumber.default(0);
|
|
503
|
+
if (state === 'casting') {
|
|
504
|
+
const allVotesUnlockable = votes.length === 0 || votes.every(vote => unlockableReferenda.has(vote.referendumIndex.toString()));
|
|
505
|
+
const activeVoteAmount = votes.filter(vote => !unlockableReferenda.has(vote.referendumIndex)).reduce((sum, vote) => {
|
|
506
|
+
return sum.plus(new _bignumber.default(vote.amount || '0')).plus(new _bignumber.default(vote.ayeAmount || '0')).plus(new _bignumber.default(vote.nayAmount || '0')).plus(new _bignumber.default(vote.abstainAmount || '0'));
|
|
507
|
+
}, new _bignumber.default(0));
|
|
508
|
+
if (allVotesUnlockable) {
|
|
509
|
+
if (priorBlock.eq(0) || currentBlockNumber.gte(priorBlock)) {
|
|
510
|
+
unlockableTrackIds.push(trackId);
|
|
511
|
+
}
|
|
512
|
+
} else if (activeVoteAmount.lt(balance)) {
|
|
513
|
+
if (priorBlock.eq(0) || currentBlockNumber.gte(priorBlock)) {
|
|
514
|
+
unlockableTrackIds.push(trackId);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
} else if (state === 'empty') {
|
|
518
|
+
unlockableTrackIds.push(trackId);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
const actualTrackBalances = new Map();
|
|
522
|
+
for (const [trackId, balance] of trackBalances) {
|
|
523
|
+
const state = trackStates.get(trackId) || 'empty';
|
|
524
|
+
const votes = trackVotes.get(trackId) || [];
|
|
525
|
+
if (state === 'casting') {
|
|
526
|
+
const activeVoteAmount = votes.filter(vote => !unlockableReferenda.has(vote.referendumIndex)).reduce((sum, vote) => {
|
|
527
|
+
return sum.plus(new _bignumber.default(vote.amount || '0')).plus(new _bignumber.default(vote.ayeAmount || '0')).plus(new _bignumber.default(vote.nayAmount || '0')).plus(new _bignumber.default(vote.abstainAmount || '0'));
|
|
528
|
+
}, new _bignumber.default(0));
|
|
529
|
+
if (activeVoteAmount.lt(balance)) {
|
|
530
|
+
actualTrackBalances.set(trackId, balance.minus(activeVoteAmount));
|
|
531
|
+
} else {
|
|
532
|
+
actualTrackBalances.set(trackId, balance);
|
|
533
|
+
}
|
|
534
|
+
} else {
|
|
535
|
+
actualTrackBalances.set(trackId, balance);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Sort by actual unlockable balances
|
|
540
|
+
const sortedBalances = Array.from(actualTrackBalances.entries()).sort((a, b) => b[1].comparedTo(a[1]));
|
|
541
|
+
let totalUnlockable = new _bignumber.default(0);
|
|
542
|
+
if (unlockableTrackIds.length > 0) {
|
|
543
|
+
const unlockableBalances = unlockableTrackIds.map(trackId => actualTrackBalances.get(trackId) || new _bignumber.default(0)).sort((a, b) => b.comparedTo(a));
|
|
544
|
+
const maxUnlockableBalance = unlockableBalances[0];
|
|
545
|
+
const lockedTracks = sortedBalances.filter(_ref2 => {
|
|
546
|
+
let [trackId] = _ref2;
|
|
547
|
+
return !unlockableTrackIds.includes(trackId);
|
|
548
|
+
});
|
|
549
|
+
const worstLockedBalance = lockedTracks.length > 0 ? lockedTracks[0][1] : new _bignumber.default(0);
|
|
550
|
+
totalUnlockable = maxUnlockableBalance.minus(worstLockedBalance);
|
|
551
|
+
if (totalUnlockable.lt(0)) {
|
|
552
|
+
totalUnlockable = new _bignumber.default(0);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return {
|
|
556
|
+
unlockableTrackIds,
|
|
557
|
+
totalUnlockable
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
exports.default = BaseOpenGovHandler;
|