@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.
Files changed (208) hide show
  1. package/background/KoniTypes.d.ts +11 -0
  2. package/background/KoniTypes.js +68 -8
  3. package/cjs/background/KoniTypes.js +68 -8
  4. package/cjs/constants/blocked-actions.js +3 -0
  5. package/cjs/core/logic-validation/swap.js +0 -3
  6. package/cjs/core/substrate/system-pallet.js +0 -2
  7. package/cjs/koni/api/nft/wasm_nft/index.js +0 -1
  8. package/cjs/koni/api/staking/bonding/astar.js +0 -2
  9. package/cjs/koni/api/staking/bonding/paraChain.js +0 -3
  10. package/cjs/koni/api/staking/bonding/relayChain.js +2 -4
  11. package/cjs/koni/api/staking/bonding/utils.js +0 -4
  12. package/cjs/koni/background/cron.js +0 -1
  13. package/cjs/koni/background/handlers/Extension.js +216 -158
  14. package/cjs/koni/background/handlers/State.js +59 -54
  15. package/cjs/koni/background/handlers/Tabs.js +39 -34
  16. package/cjs/packageInfo.js +1 -1
  17. package/cjs/page/index.js +7 -0
  18. package/cjs/page/substrate/PostMessageProvider.js +3 -0
  19. package/cjs/services/balance-service/helpers/subscribe/cardano/utils.js +0 -1
  20. package/cjs/services/balance-service/helpers/subscribe/substrate/gear.js +0 -2
  21. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +2 -3
  22. package/cjs/services/balance-service/helpers/subscribe/ton/utils.js +0 -3
  23. package/cjs/services/balance-service/index.js +103 -7
  24. package/cjs/services/balance-service/transfer/bitcoin-transfer.js +0 -1
  25. package/cjs/services/balance-service/transfer/cardano-transfer.js +1 -2
  26. package/cjs/services/balance-service/transfer/smart-contract.js +0 -1
  27. package/cjs/services/balance-service/transfer/token.js +0 -2
  28. package/cjs/services/balance-service/transfer/ton-transfer.js +0 -1
  29. package/cjs/services/balance-service/transfer/xcm/snowBridge.js +0 -1
  30. package/cjs/services/chain-service/constants.js +15 -4
  31. package/cjs/services/chain-service/handler/CardanoApi.js +3 -1
  32. package/cjs/services/chain-service/handler/SubstrateApi.js +0 -2
  33. package/cjs/services/chain-service/handler/light-client/index.js +1 -2
  34. package/cjs/services/chain-service/health-check/index.js +0 -1
  35. package/cjs/services/chain-service/health-check/utils/new-utils/chain-asset-validate.js +0 -1
  36. package/cjs/services/chain-service/index.js +18 -26
  37. package/cjs/services/chain-service/utils/index.js +34 -30
  38. package/cjs/services/earning-service/handlers/base.js +32 -0
  39. package/cjs/services/earning-service/handlers/lending/base.js +0 -2
  40. package/cjs/services/earning-service/handlers/liquid-staking/acala.js +0 -1
  41. package/cjs/services/earning-service/handlers/liquid-staking/base.js +0 -2
  42. package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +0 -2
  43. package/cjs/services/earning-service/handlers/liquid-staking/parallel.js +0 -1
  44. package/cjs/services/earning-service/handlers/native-staking/astar.js +0 -2
  45. package/cjs/services/earning-service/handlers/native-staking/dtao.js +43 -2
  46. package/cjs/services/earning-service/handlers/native-staking/energy.js +0 -1
  47. package/cjs/services/earning-service/handlers/native-staking/mythos.js +0 -2
  48. package/cjs/services/earning-service/handlers/native-staking/para-chain.js +0 -2
  49. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +8 -9
  50. package/cjs/services/earning-service/handlers/special.js +7 -0
  51. package/cjs/services/event-service/index.js +1 -0
  52. package/cjs/services/history-service/subsquid-multi-chain-history.js +0 -1
  53. package/cjs/services/keyring-service/context/handlers/Derive.js +1 -1
  54. package/cjs/services/keyring-service/context/handlers/Migration.js +11 -9
  55. package/cjs/services/keyring-service/context/handlers/Mnemonic.js +18 -13
  56. package/cjs/services/keyring-service/context/state.js +21 -3
  57. package/cjs/services/keyring-service/utils.js +12 -2
  58. package/cjs/services/migration-service/index.js +1 -2
  59. package/cjs/services/mint-campaign-service/campaigns/UnlockDotCampaign.js +0 -1
  60. package/cjs/services/nft-service/index.js +5 -0
  61. package/cjs/services/open-gov/handler.js +561 -0
  62. package/cjs/services/open-gov/index.js +273 -0
  63. package/cjs/services/open-gov/interface.js +31 -0
  64. package/cjs/services/open-gov/utils.js +66 -0
  65. package/cjs/services/request-service/handler/BitcoinRequestHandler.js +1 -2
  66. package/cjs/services/request-service/handler/CardanoRequestHandler.js +0 -1
  67. package/cjs/services/request-service/handler/EvmRequestHandler.js +0 -1
  68. package/cjs/services/request-service/handler/TonRequestHandler.js +0 -1
  69. package/cjs/services/request-service/helper/index.js +1 -2
  70. package/cjs/services/storage-service/DatabaseService.js +19 -3
  71. package/cjs/services/storage-service/databases/index.js +5 -0
  72. package/cjs/services/storage-service/db-stores/GovLockedInfoStore.js +35 -0
  73. package/cjs/services/swap-service/handler/asset-hub/handler.js +0 -1
  74. package/cjs/services/swap-service/handler/asset-hub/router.js +0 -1
  75. package/cjs/services/swap-service/handler/chainflip-handler.js +1 -4
  76. package/cjs/services/swap-service/handler/hydradx-handler.js +0 -1
  77. package/cjs/services/swap-service/handler/kyber-handler.js +0 -1
  78. package/cjs/services/swap-service/handler/optimex-handler.js +1 -2
  79. package/cjs/services/swap-service/handler/simpleswap-handler.js +1 -3
  80. package/cjs/services/swap-service/handler/uniswap-handler.js +0 -3
  81. package/cjs/services/transaction-service/event-parser/index.js +6 -6
  82. package/cjs/services/transaction-service/helpers/index.js +6 -0
  83. package/cjs/services/transaction-service/index.js +71 -28
  84. package/cjs/services/wallet-connect-service/index.js +21 -18
  85. package/cjs/services/wallet-connect-service/types.js +1 -1
  86. package/cjs/types/account/info/keyring.js +9 -1
  87. package/cjs/types/balance/index.js +5 -1
  88. package/cjs/types/swap/index.js +2 -1
  89. package/cjs/types/transaction/process.js +2 -0
  90. package/cjs/types/yield/actions/join/step.js +17 -1
  91. package/cjs/utils/account/common.js +0 -26
  92. package/cjs/utils/account/derive/info/solo.js +7 -4
  93. package/cjs/utils/account/derive/validate.js +1 -1
  94. package/cjs/utils/account/transform.js +10 -5
  95. package/cjs/utils/auth.js +1 -1
  96. package/cjs/utils/bitcoin/utxo-management.js +0 -1
  97. package/cjs/utils/environment.js +2 -1
  98. package/cjs/utils/fee/transfer.js +1 -2
  99. package/cjs/utils/index.js +1 -2
  100. package/constants/blocked-actions.js +3 -0
  101. package/core/logic-validation/swap.js +0 -3
  102. package/core/substrate/system-pallet.js +0 -2
  103. package/koni/api/nft/wasm_nft/index.js +0 -1
  104. package/koni/api/staking/bonding/astar.js +0 -2
  105. package/koni/api/staking/bonding/paraChain.js +0 -3
  106. package/koni/api/staking/bonding/relayChain.js +2 -4
  107. package/koni/api/staking/bonding/utils.js +0 -4
  108. package/koni/background/cron.js +0 -1
  109. package/koni/background/handlers/Extension.d.ts +4 -0
  110. package/koni/background/handlers/Extension.js +70 -11
  111. package/koni/background/handlers/State.d.ts +2 -0
  112. package/koni/background/handlers/State.js +46 -40
  113. package/koni/background/handlers/Tabs.js +9 -3
  114. package/package.json +44 -20
  115. package/packageInfo.js +1 -1
  116. package/page/substrate/PostMessageProvider.js +3 -0
  117. package/services/balance-service/helpers/subscribe/cardano/utils.js +0 -1
  118. package/services/balance-service/helpers/subscribe/substrate/gear.js +0 -2
  119. package/services/balance-service/helpers/subscribe/substrate/index.js +0 -1
  120. package/services/balance-service/helpers/subscribe/ton/utils.js +0 -3
  121. package/services/balance-service/index.d.ts +8 -0
  122. package/services/balance-service/index.js +105 -9
  123. package/services/balance-service/transfer/bitcoin-transfer.js +0 -1
  124. package/services/balance-service/transfer/smart-contract.js +0 -1
  125. package/services/balance-service/transfer/token.js +0 -2
  126. package/services/balance-service/transfer/ton-transfer.js +0 -1
  127. package/services/balance-service/transfer/xcm/snowBridge.js +0 -1
  128. package/services/chain-service/constants.d.ts +8 -0
  129. package/services/chain-service/constants.js +12 -2
  130. package/services/chain-service/handler/CardanoApi.js +3 -1
  131. package/services/chain-service/handler/SubstrateApi.js +0 -2
  132. package/services/chain-service/health-check/index.js +0 -1
  133. package/services/chain-service/health-check/utils/new-utils/chain-asset-validate.js +0 -1
  134. package/services/chain-service/index.d.ts +0 -1
  135. package/services/chain-service/index.js +15 -23
  136. package/services/chain-service/utils/index.js +35 -31
  137. package/services/earning-service/handlers/base.js +32 -0
  138. package/services/earning-service/handlers/lending/base.js +0 -2
  139. package/services/earning-service/handlers/liquid-staking/acala.js +0 -1
  140. package/services/earning-service/handlers/liquid-staking/base.js +0 -2
  141. package/services/earning-service/handlers/liquid-staking/bifrost.js +0 -2
  142. package/services/earning-service/handlers/liquid-staking/parallel.js +0 -1
  143. package/services/earning-service/handlers/native-staking/astar.js +0 -2
  144. package/services/earning-service/handlers/native-staking/dtao.js +43 -0
  145. package/services/earning-service/handlers/native-staking/energy.js +0 -1
  146. package/services/earning-service/handlers/native-staking/mythos.js +0 -2
  147. package/services/earning-service/handlers/native-staking/para-chain.js +0 -2
  148. package/services/earning-service/handlers/native-staking/relay-chain.js +8 -9
  149. package/services/earning-service/handlers/special.js +7 -0
  150. package/services/event-service/index.d.ts +1 -0
  151. package/services/event-service/index.js +1 -0
  152. package/services/event-service/types.d.ts +1 -0
  153. package/services/history-service/subsquid-multi-chain-history.js +0 -1
  154. package/services/keyring-service/context/handlers/Derive.js +2 -2
  155. package/services/keyring-service/context/handlers/Migration.js +3 -1
  156. package/services/keyring-service/context/handlers/Mnemonic.d.ts +1 -1
  157. package/services/keyring-service/context/handlers/Mnemonic.js +16 -10
  158. package/services/keyring-service/context/state.d.ts +3 -0
  159. package/services/keyring-service/context/state.js +21 -3
  160. package/services/keyring-service/utils.d.ts +1 -0
  161. package/services/keyring-service/utils.js +9 -0
  162. package/services/mint-campaign-service/campaigns/UnlockDotCampaign.js +0 -1
  163. package/services/nft-service/index.js +6 -0
  164. package/services/open-gov/handler.d.ts +27 -0
  165. package/services/open-gov/handler.js +545 -0
  166. package/services/open-gov/index.d.ts +45 -0
  167. package/services/open-gov/index.js +265 -0
  168. package/services/open-gov/interface.d.ts +141 -0
  169. package/services/open-gov/interface.js +24 -0
  170. package/services/open-gov/utils.d.ts +14 -0
  171. package/services/open-gov/utils.js +52 -0
  172. package/services/request-service/handler/CardanoRequestHandler.js +0 -1
  173. package/services/request-service/handler/EvmRequestHandler.js +0 -1
  174. package/services/request-service/handler/TonRequestHandler.js +0 -1
  175. package/services/setting-service/constants.js +0 -1
  176. package/services/storage-service/DatabaseService.d.ts +7 -0
  177. package/services/storage-service/DatabaseService.js +19 -3
  178. package/services/storage-service/databases/index.d.ts +2 -0
  179. package/services/storage-service/databases/index.js +6 -0
  180. package/services/storage-service/db-stores/GovLockedInfoStore.d.ts +10 -0
  181. package/services/storage-service/db-stores/GovLockedInfoStore.js +27 -0
  182. package/services/swap-service/handler/asset-hub/handler.js +0 -1
  183. package/services/swap-service/handler/asset-hub/router.js +0 -1
  184. package/services/swap-service/handler/chainflip-handler.js +0 -2
  185. package/services/swap-service/handler/hydradx-handler.js +0 -1
  186. package/services/swap-service/handler/kyber-handler.js +0 -1
  187. package/services/swap-service/handler/simpleswap-handler.js +0 -1
  188. package/services/swap-service/handler/uniswap-handler.js +0 -3
  189. package/services/transaction-service/event-parser/index.js +6 -6
  190. package/services/transaction-service/helpers/index.js +6 -0
  191. package/services/transaction-service/index.js +43 -0
  192. package/services/wallet-connect-service/index.js +21 -18
  193. package/services/wallet-connect-service/types.js +1 -1
  194. package/types/account/action/add/mnemonic.d.ts +3 -2
  195. package/types/account/info/keyring.js +9 -1
  196. package/types/balance/index.js +5 -1
  197. package/types/swap/index.js +2 -1
  198. package/types/transaction/process.js +3 -1
  199. package/types/yield/actions/join/step.js +17 -1
  200. package/utils/account/common.d.ts +0 -3
  201. package/utils/account/common.js +0 -24
  202. package/utils/account/derive/info/solo.js +8 -5
  203. package/utils/account/derive/validate.d.ts +2 -2
  204. package/utils/account/derive/validate.js +1 -1
  205. package/utils/account/transform.js +10 -5
  206. package/utils/auth.js +2 -2
  207. package/utils/bitcoin/utxo-management.js +0 -1
  208. 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;