@subwallet/extension-base 1.2.25-0 → 1.2.25-1
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 +9 -0
- package/background/errors/EvmProviderError.d.ts +1 -1
- package/background/errors/EvmProviderError.js +2 -2
- package/background/errors/SWError.d.ts +1 -1
- package/background/errors/SWError.js +4 -1
- package/background/errors/TransactionError.d.ts +1 -1
- package/background/errors/TransactionError.js +2 -2
- package/cjs/background/errors/EvmProviderError.js +2 -2
- package/cjs/background/errors/SWError.js +4 -1
- package/cjs/background/errors/TransactionError.js +2 -2
- package/cjs/core/logic-validation/index.js +49 -0
- package/cjs/core/logic-validation/request.js +488 -0
- package/cjs/core/logic-validation/transfer.js +25 -8
- package/cjs/koni/api/staking/bonding/utils.js +2 -2
- package/cjs/koni/background/handlers/Extension.js +33 -8
- package/cjs/koni/background/handlers/State.js +41 -160
- package/cjs/koni/background/handlers/Tabs.js +35 -33
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +16 -8
- package/cjs/services/chain-service/constants.js +6 -1
- package/cjs/services/chain-service/index.js +32 -2
- package/cjs/services/chain-service/utils/index.js +2 -2
- package/cjs/services/earning-service/constants/chains.js +2 -2
- package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +4 -3
- package/cjs/services/earning-service/service.js +1 -1
- package/cjs/services/event-service/index.js +1 -0
- package/cjs/services/request-service/handler/EvmRequestHandler.js +2 -1
- package/cjs/services/transaction-service/index.js +11 -7
- package/cjs/services/wallet-connect-service/handler/Eip155RequestHandler.js +12 -36
- package/core/logic-validation/index.d.ts +4 -0
- package/core/logic-validation/index.js +7 -0
- package/core/logic-validation/request.d.ts +23 -0
- package/core/logic-validation/request.js +475 -0
- package/core/logic-validation/transfer.d.ts +1 -1
- package/core/logic-validation/transfer.js +25 -8
- package/koni/api/staking/bonding/utils.js +2 -2
- package/koni/background/handlers/Extension.d.ts +1 -0
- package/koni/background/handlers/Extension.js +33 -8
- package/koni/background/handlers/State.d.ts +2 -2
- package/koni/background/handlers/State.js +42 -161
- package/koni/background/handlers/Tabs.d.ts +0 -1
- package/koni/background/handlers/Tabs.js +36 -34
- package/package.json +16 -6
- package/packageInfo.js +1 -1
- package/services/balance-service/helpers/subscribe/substrate/index.js +16 -8
- package/services/chain-service/constants.js +6 -1
- package/services/chain-service/index.d.ts +9 -0
- package/services/chain-service/index.js +32 -2
- package/services/chain-service/utils/index.js +2 -2
- package/services/earning-service/constants/chains.js +2 -2
- package/services/earning-service/handlers/native-staking/relay-chain.js +4 -3
- package/services/earning-service/service.js +1 -1
- 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/request-service/handler/EvmRequestHandler.js +2 -1
- package/services/transaction-service/index.js +11 -7
- package/services/wallet-connect-service/handler/Eip155RequestHandler.js +9 -33
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.convertErrorMessage = convertErrorMessage;
|
|
8
|
+
exports.generateValidationProcess = generateValidationProcess;
|
|
9
|
+
exports.validationAuthMiddleware = validationAuthMiddleware;
|
|
10
|
+
exports.validationAuthWCMiddleware = validationAuthWCMiddleware;
|
|
11
|
+
exports.validationConnectMiddleware = validationConnectMiddleware;
|
|
12
|
+
exports.validationEvmDataTransactionMiddleware = validationEvmDataTransactionMiddleware;
|
|
13
|
+
exports.validationEvmSignMessageMiddleware = validationEvmSignMessageMiddleware;
|
|
14
|
+
var _EvmProviderError = require("@subwallet/extension-base/background/errors/EvmProviderError");
|
|
15
|
+
var _TransactionError = require("@subwallet/extension-base/background/errors/TransactionError");
|
|
16
|
+
var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
|
|
17
|
+
var _utils = require("@subwallet/extension-base/services/fee-service/utils");
|
|
18
|
+
var _utils2 = require("@subwallet/extension-base/utils");
|
|
19
|
+
var _parseTransaction = require("@subwallet/extension-base/utils/eth/parseTransaction");
|
|
20
|
+
var _uiKeyring = require("@subwallet/ui-keyring");
|
|
21
|
+
var _utils3 = require("@walletconnect/utils");
|
|
22
|
+
var _bignumber = _interopRequireDefault(require("bignumber.js"));
|
|
23
|
+
var _bn = _interopRequireDefault(require("bn.js"));
|
|
24
|
+
var _i18next = require("i18next");
|
|
25
|
+
var _util = require("@polkadot/util");
|
|
26
|
+
var _utilCrypto = require("@polkadot/util-crypto");
|
|
27
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
28
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
29
|
+
|
|
30
|
+
async function generateValidationProcess(koni, url, payloadValidate, validationMiddlewareSteps, topic) {
|
|
31
|
+
let resultValidated = payloadValidate;
|
|
32
|
+
for (const step of validationMiddlewareSteps) {
|
|
33
|
+
resultValidated = await step(koni, url, resultValidated, topic);
|
|
34
|
+
if (resultValidated.errorPosition === 'dApp') {
|
|
35
|
+
throw resultValidated.errors[0];
|
|
36
|
+
} else if (resultValidated.errorPosition === 'ui') {
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return resultValidated;
|
|
41
|
+
}
|
|
42
|
+
async function validationAuthMiddleware(koni, url, payload) {
|
|
43
|
+
const {
|
|
44
|
+
address,
|
|
45
|
+
errors
|
|
46
|
+
} = payload;
|
|
47
|
+
if (!address || !(0, _util.isString)(address)) {
|
|
48
|
+
payload.errorPosition = 'dApp';
|
|
49
|
+
const [message] = convertErrorMessage('Not found address to sign');
|
|
50
|
+
errors.push(new Error(message));
|
|
51
|
+
} else {
|
|
52
|
+
try {
|
|
53
|
+
payload.pair = _uiKeyring.keyring.getPair(address);
|
|
54
|
+
if (!payload.pair) {
|
|
55
|
+
payload.errorPosition = 'dApp';
|
|
56
|
+
const [message] = convertErrorMessage('Unable to find account');
|
|
57
|
+
errors.push(new Error(message));
|
|
58
|
+
} else {
|
|
59
|
+
const authList = await koni.getAuthList();
|
|
60
|
+
const authInfo = authList[(0, _utils2.stripUrl)(url)];
|
|
61
|
+
if (!authInfo || !authInfo.isAllowed || !authInfo.isAllowedMap[payload.pair.address]) {
|
|
62
|
+
payload.errorPosition = 'dApp';
|
|
63
|
+
const [message] = convertErrorMessage('Account not in allowed list', '');
|
|
64
|
+
errors.push(new Error(message));
|
|
65
|
+
}
|
|
66
|
+
payload.authInfo = authInfo;
|
|
67
|
+
}
|
|
68
|
+
} catch (e) {
|
|
69
|
+
const [message] = convertErrorMessage(e.message);
|
|
70
|
+
payload.errorPosition = 'dApp';
|
|
71
|
+
errors.push(new Error(message));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return payload;
|
|
75
|
+
}
|
|
76
|
+
async function validationConnectMiddleware(koni, url, payload) {
|
|
77
|
+
let currentChain;
|
|
78
|
+
let autoActiveChain = false;
|
|
79
|
+
let {
|
|
80
|
+
address,
|
|
81
|
+
authInfo,
|
|
82
|
+
errors,
|
|
83
|
+
networkKey
|
|
84
|
+
} = {
|
|
85
|
+
...payload
|
|
86
|
+
};
|
|
87
|
+
const handleError = message_ => {
|
|
88
|
+
payload.errorPosition = 'ui';
|
|
89
|
+
payload.confirmationType = 'errorConnectNetwork';
|
|
90
|
+
const [message, name] = convertErrorMessage(message_);
|
|
91
|
+
const error = new _EvmProviderError.EvmProviderError(_KoniTypes.EvmProviderErrorType.CHAIN_DISCONNECTED, message, undefined, name);
|
|
92
|
+
console.error(error);
|
|
93
|
+
errors.push(error);
|
|
94
|
+
};
|
|
95
|
+
if (authInfo !== null && authInfo !== void 0 && authInfo.currentEvmNetworkKey) {
|
|
96
|
+
currentChain = authInfo === null || authInfo === void 0 ? void 0 : authInfo.currentEvmNetworkKey;
|
|
97
|
+
}
|
|
98
|
+
if (authInfo !== null && authInfo !== void 0 && authInfo.isAllowed) {
|
|
99
|
+
autoActiveChain = true;
|
|
100
|
+
}
|
|
101
|
+
const currentEvmNetwork = koni.requestService.getDAppChainInfo({
|
|
102
|
+
autoActive: autoActiveChain,
|
|
103
|
+
accessType: 'evm',
|
|
104
|
+
defaultChain: currentChain,
|
|
105
|
+
url
|
|
106
|
+
});
|
|
107
|
+
networkKey = networkKey || (currentEvmNetwork === null || currentEvmNetwork === void 0 ? void 0 : currentEvmNetwork.slug) || '';
|
|
108
|
+
if (networkKey) {
|
|
109
|
+
const chainStatus = koni.getChainStateByKey(networkKey);
|
|
110
|
+
const chainInfo = koni.getChainInfo(networkKey);
|
|
111
|
+
if (!chainStatus.active) {
|
|
112
|
+
try {
|
|
113
|
+
await koni.chainService.enableChain(networkKey);
|
|
114
|
+
} catch (e) {
|
|
115
|
+
handleError('Can not active chain: ' + chainInfo.name);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const evmApi = koni.getEvmApi(networkKey);
|
|
119
|
+
const web3 = evmApi === null || evmApi === void 0 ? void 0 : evmApi.api;
|
|
120
|
+
let currentProviderConnected = false;
|
|
121
|
+
const checkProviderConnected = async () => {
|
|
122
|
+
try {
|
|
123
|
+
currentProviderConnected = !!(await web3.eth.getBalance(address));
|
|
124
|
+
} catch (e) {
|
|
125
|
+
handleError(e.message);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Calculate transaction data
|
|
130
|
+
try {
|
|
131
|
+
await Promise.race([checkProviderConnected(), (0, _utils2.wait)(3000).then(async () => {
|
|
132
|
+
if (!currentProviderConnected) {
|
|
133
|
+
await koni.chainService.initSingleApi(networkKey);
|
|
134
|
+
await checkProviderConnected();
|
|
135
|
+
}
|
|
136
|
+
})]);
|
|
137
|
+
} catch (e) {
|
|
138
|
+
handleError(e.message);
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
handleError('This network is currently not supported');
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
...payload,
|
|
145
|
+
networkKey,
|
|
146
|
+
errors
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async function validationEvmDataTransactionMiddleware(koni, url, payload) {
|
|
150
|
+
const errors = payload.errors || [];
|
|
151
|
+
let estimateGas = '';
|
|
152
|
+
const transactionParams = payload.payloadAfterValidated;
|
|
153
|
+
const {
|
|
154
|
+
address: fromAddress,
|
|
155
|
+
networkKey,
|
|
156
|
+
pair
|
|
157
|
+
} = payload;
|
|
158
|
+
const evmApi = koni.getEvmApi(networkKey || '');
|
|
159
|
+
const web3 = evmApi === null || evmApi === void 0 ? void 0 : evmApi.api;
|
|
160
|
+
const autoFormatNumber = val => {
|
|
161
|
+
if (typeof val === 'string' && val.startsWith('0x')) {
|
|
162
|
+
return new _bn.default(val.replace('0x', ''), 16).toString();
|
|
163
|
+
} else if (typeof val === 'number') {
|
|
164
|
+
return val.toString();
|
|
165
|
+
}
|
|
166
|
+
return val;
|
|
167
|
+
};
|
|
168
|
+
const handleError = message_ => {
|
|
169
|
+
payload.errorPosition = 'ui';
|
|
170
|
+
payload.confirmationType = 'evmWatchTransactionRequest';
|
|
171
|
+
const [message, name] = convertErrorMessage(message_);
|
|
172
|
+
const error = new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.INVALID_PARAMS, message, undefined, name);
|
|
173
|
+
console.error(error);
|
|
174
|
+
errors.push(error);
|
|
175
|
+
};
|
|
176
|
+
if (!web3) {
|
|
177
|
+
handleError('connection error');
|
|
178
|
+
}
|
|
179
|
+
const transaction = {
|
|
180
|
+
from: transactionParams.from,
|
|
181
|
+
to: transactionParams.to,
|
|
182
|
+
value: autoFormatNumber(transactionParams.value),
|
|
183
|
+
gas: autoFormatNumber(transactionParams.gas),
|
|
184
|
+
gasPrice: autoFormatNumber(transactionParams.gasPrice || transactionParams.gasLimit),
|
|
185
|
+
maxPriorityFeePerGas: autoFormatNumber(transactionParams.maxPriorityFeePerGas),
|
|
186
|
+
maxFeePerGas: autoFormatNumber(transactionParams.maxFeePerGas),
|
|
187
|
+
data: transactionParams.data
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Address is validated in before step
|
|
191
|
+
if (!fromAddress || !(0, _utilCrypto.isEthereumAddress)(fromAddress)) {
|
|
192
|
+
handleError('the sender address must be the ethereum address type');
|
|
193
|
+
}
|
|
194
|
+
if (transaction.to && !(0, _utilCrypto.isEthereumAddress)(transaction.to)) {
|
|
195
|
+
handleError('invalid recipient address');
|
|
196
|
+
}
|
|
197
|
+
if (fromAddress === transaction.to) {
|
|
198
|
+
handleError('receiving address must be different from sending address');
|
|
199
|
+
}
|
|
200
|
+
if (!transaction.to) {
|
|
201
|
+
if (transaction.data) {
|
|
202
|
+
if (transaction.value) {
|
|
203
|
+
try {
|
|
204
|
+
const valueBn = new _bignumber.default(transaction.value.toString());
|
|
205
|
+
if (!valueBn.eq(_utils2.BN_ZERO)) {
|
|
206
|
+
handleError('Recipient address not found');
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
handleError('invalid number');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
handleError('Recipient address not found');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (!transaction.gas) {
|
|
217
|
+
const getTransactionGas = async () => {
|
|
218
|
+
try {
|
|
219
|
+
transaction.gas = await web3.eth.estimateGas({
|
|
220
|
+
...transaction
|
|
221
|
+
});
|
|
222
|
+
} catch (e) {
|
|
223
|
+
handleError(e.message);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// Calculate transaction data
|
|
228
|
+
try {
|
|
229
|
+
await Promise.race([getTransactionGas(), (0, _utils2.wait)(3000).then(async () => {
|
|
230
|
+
if (!transaction.gas) {
|
|
231
|
+
await koni.chainService.initSingleApi(networkKey || '');
|
|
232
|
+
await getTransactionGas();
|
|
233
|
+
}
|
|
234
|
+
})]);
|
|
235
|
+
} catch (e) {
|
|
236
|
+
handleError(e.message);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (!transaction.gas) {
|
|
240
|
+
handleError(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.INTERNAL_ERROR).message);
|
|
241
|
+
} else {
|
|
242
|
+
if (transactionParams.maxPriorityFeePerGas && transactionParams.maxFeePerGas) {
|
|
243
|
+
const maxFee = new _bignumber.default(transactionParams.maxFeePerGas);
|
|
244
|
+
estimateGas = maxFee.multipliedBy(transaction.gas).toFixed(0);
|
|
245
|
+
} else if (transactionParams.gasPrice) {
|
|
246
|
+
estimateGas = new _bignumber.default(transactionParams.gasPrice).multipliedBy(transaction.gas).toFixed(0);
|
|
247
|
+
} else {
|
|
248
|
+
try {
|
|
249
|
+
const priority = await (0, _utils.calculateGasFeeParams)(evmApi, networkKey || '');
|
|
250
|
+
if (priority.baseGasFee) {
|
|
251
|
+
transaction.maxPriorityFeePerGas = priority.maxPriorityFeePerGas.toString();
|
|
252
|
+
transaction.maxFeePerGas = priority.maxFeePerGas.toString();
|
|
253
|
+
const maxFee = priority.maxFeePerGas;
|
|
254
|
+
estimateGas = maxFee.multipliedBy(transaction.gas).toFixed(0);
|
|
255
|
+
} else {
|
|
256
|
+
transaction.gasPrice = priority.gasPrice;
|
|
257
|
+
estimateGas = new _bignumber.default(priority.gasPrice).multipliedBy(transaction.gas).toFixed(0);
|
|
258
|
+
}
|
|
259
|
+
} catch (e) {
|
|
260
|
+
handleError(e.message);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
// Validate balance
|
|
265
|
+
const balance = new _bn.default((await web3.eth.getBalance(fromAddress)) || 0);
|
|
266
|
+
if (!estimateGas) {
|
|
267
|
+
handleError('Can\'t calculate estimate gas fee');
|
|
268
|
+
} else if (balance.lt(new _bn.default(estimateGas).add(new _bn.default(autoFormatNumber(transactionParams.value) || '0')))) {
|
|
269
|
+
handleError('Insufficient balance');
|
|
270
|
+
}
|
|
271
|
+
} catch (e) {
|
|
272
|
+
handleError(e.message);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const pair_ = pair || _uiKeyring.keyring.getPair(fromAddress);
|
|
276
|
+
const account = {
|
|
277
|
+
address: fromAddress,
|
|
278
|
+
...(pair_ === null || pair_ === void 0 ? void 0 : pair_.meta)
|
|
279
|
+
};
|
|
280
|
+
try {
|
|
281
|
+
transaction.nonce = await web3.eth.getTransactionCount(fromAddress);
|
|
282
|
+
} catch (e) {
|
|
283
|
+
handleError(e.message);
|
|
284
|
+
}
|
|
285
|
+
const hasError = errors && errors.length > 0 || !networkKey;
|
|
286
|
+
const evmNetwork = koni.getChainInfo(networkKey || '');
|
|
287
|
+
let isToContract = false;
|
|
288
|
+
let hashPayload = '';
|
|
289
|
+
let parseData = '';
|
|
290
|
+
try {
|
|
291
|
+
hashPayload = hasError ? '' : koni.transactionService.generateHashPayload(networkKey, transaction);
|
|
292
|
+
isToContract = await (0, _parseTransaction.isContractAddress)(transaction.to || '', evmApi);
|
|
293
|
+
parseData = isToContract ? transaction.data && !hasError ? (await (0, _parseTransaction.parseContractInput)(transaction.data, transaction.to || '', evmNetwork)).result : '' : transaction.data || '';
|
|
294
|
+
} catch (e) {
|
|
295
|
+
handleError(e.message);
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
...payload,
|
|
299
|
+
errors,
|
|
300
|
+
payloadAfterValidated: {
|
|
301
|
+
...transaction,
|
|
302
|
+
account,
|
|
303
|
+
estimateGas,
|
|
304
|
+
hashPayload,
|
|
305
|
+
isToContract,
|
|
306
|
+
parseData,
|
|
307
|
+
canSign: !hasError
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
async function validationEvmSignMessageMiddleware(koni, url, payload_) {
|
|
312
|
+
const {
|
|
313
|
+
address,
|
|
314
|
+
errors,
|
|
315
|
+
method,
|
|
316
|
+
pair: pair_
|
|
317
|
+
} = payload_;
|
|
318
|
+
let payload = payload_.payloadAfterValidated;
|
|
319
|
+
const {
|
|
320
|
+
promise,
|
|
321
|
+
resolve
|
|
322
|
+
} = (0, _utils2.createPromiseHandler)();
|
|
323
|
+
let hashPayload = '';
|
|
324
|
+
let canSign = false;
|
|
325
|
+
const handleError = message_ => {
|
|
326
|
+
payload_.errorPosition = 'ui';
|
|
327
|
+
payload_.confirmationType = 'evmSignatureRequest';
|
|
328
|
+
const [message, name] = convertErrorMessage(message_);
|
|
329
|
+
const error = new _EvmProviderError.EvmProviderError(_KoniTypes.EvmProviderErrorType.INVALID_PARAMS, message, undefined, name);
|
|
330
|
+
console.error(error);
|
|
331
|
+
errors.push(new _EvmProviderError.EvmProviderError(_KoniTypes.EvmProviderErrorType.INVALID_PARAMS, message, undefined, name));
|
|
332
|
+
};
|
|
333
|
+
if (address === '' || !payload) {
|
|
334
|
+
handleError('Not found address or payload to sign');
|
|
335
|
+
}
|
|
336
|
+
const pair = pair_ || _uiKeyring.keyring.getPair(address);
|
|
337
|
+
const account = {
|
|
338
|
+
address: pair.address,
|
|
339
|
+
...pair.meta
|
|
340
|
+
};
|
|
341
|
+
if (method) {
|
|
342
|
+
if (['eth_sign', 'personal_sign', 'eth_signTypedData', 'eth_signTypedData_v1', 'eth_signTypedData_v3', 'eth_signTypedData_v4'].indexOf(method) < 0) {
|
|
343
|
+
handleError('Unsupported action');
|
|
344
|
+
}
|
|
345
|
+
if (['eth_signTypedData_v3', 'eth_signTypedData_v4'].indexOf(method) > -1) {
|
|
346
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-assignment
|
|
347
|
+
payload = JSON.parse(payload);
|
|
348
|
+
}
|
|
349
|
+
switch (method) {
|
|
350
|
+
case 'personal_sign':
|
|
351
|
+
canSign = true;
|
|
352
|
+
hashPayload = payload;
|
|
353
|
+
break;
|
|
354
|
+
case 'eth_sign':
|
|
355
|
+
case 'eth_signTypedData':
|
|
356
|
+
case 'eth_signTypedData_v1':
|
|
357
|
+
case 'eth_signTypedData_v3':
|
|
358
|
+
case 'eth_signTypedData_v4':
|
|
359
|
+
if (!account.isExternal) {
|
|
360
|
+
canSign = true;
|
|
361
|
+
}
|
|
362
|
+
break;
|
|
363
|
+
default:
|
|
364
|
+
handleError('Unsupported action');
|
|
365
|
+
}
|
|
366
|
+
} else {
|
|
367
|
+
handleError('Unsupported method');
|
|
368
|
+
}
|
|
369
|
+
const payloadAfterValidated = {
|
|
370
|
+
account: account,
|
|
371
|
+
type: method || '',
|
|
372
|
+
payload: payload,
|
|
373
|
+
hashPayload: hashPayload,
|
|
374
|
+
canSign: canSign,
|
|
375
|
+
id: ''
|
|
376
|
+
};
|
|
377
|
+
resolve({
|
|
378
|
+
...payload_,
|
|
379
|
+
errors,
|
|
380
|
+
payloadAfterValidated
|
|
381
|
+
});
|
|
382
|
+
return promise;
|
|
383
|
+
}
|
|
384
|
+
function validationAuthWCMiddleware(koni, url, payload, topic) {
|
|
385
|
+
const {
|
|
386
|
+
promise,
|
|
387
|
+
resolve
|
|
388
|
+
} = (0, _utils2.createPromiseHandler)();
|
|
389
|
+
const {
|
|
390
|
+
address,
|
|
391
|
+
errors
|
|
392
|
+
} = payload;
|
|
393
|
+
if (!topic) {
|
|
394
|
+
payload.errorPosition = 'dApp';
|
|
395
|
+
errors.push(new Error((0, _utils3.getSdkError)('UNAUTHORIZED_EXTEND_REQUEST').message));
|
|
396
|
+
} else {
|
|
397
|
+
const requestSession = koni.walletConnectService.getSession(topic);
|
|
398
|
+
let sessionAccounts = [];
|
|
399
|
+
if ((0, _utilCrypto.isEthereumAddress)(address)) {
|
|
400
|
+
var _requestSession$names;
|
|
401
|
+
sessionAccounts = ((_requestSession$names = requestSession.namespaces.eip155.accounts) === null || _requestSession$names === void 0 ? void 0 : _requestSession$names.map(account => account.split(':')[2])) || sessionAccounts;
|
|
402
|
+
} else {
|
|
403
|
+
var _requestSession$names2;
|
|
404
|
+
sessionAccounts = ((_requestSession$names2 = requestSession.namespaces.polkadot.accounts) === null || _requestSession$names2 === void 0 ? void 0 : _requestSession$names2.map(account => account.split(':')[2])) || sessionAccounts;
|
|
405
|
+
}
|
|
406
|
+
if (!address || !(0, _util.isString)(address)) {
|
|
407
|
+
payload.errorPosition = 'dApp';
|
|
408
|
+
const [message] = convertErrorMessage('Unable to find account');
|
|
409
|
+
errors.push(new Error(message));
|
|
410
|
+
} else {
|
|
411
|
+
try {
|
|
412
|
+
payload.pair = _uiKeyring.keyring.getPair(address);
|
|
413
|
+
if (!payload.pair) {
|
|
414
|
+
payload.errorPosition = 'dApp';
|
|
415
|
+
const [message] = convertErrorMessage('Unable to find account');
|
|
416
|
+
errors.push(new Error(message));
|
|
417
|
+
}
|
|
418
|
+
const isExitsAccount = sessionAccounts.find(account => (0, _utils2.isSameAddress)(account, address));
|
|
419
|
+
if (!isExitsAccount) {
|
|
420
|
+
payload.errorPosition = 'dApp';
|
|
421
|
+
const [message] = convertErrorMessage('Account not in allowed list');
|
|
422
|
+
errors.push(new Error(message));
|
|
423
|
+
}
|
|
424
|
+
} catch (e) {
|
|
425
|
+
const [message] = convertErrorMessage(e.message);
|
|
426
|
+
payload.errorPosition = 'dApp';
|
|
427
|
+
errors.push(new Error(message));
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
resolve({
|
|
432
|
+
...payload,
|
|
433
|
+
errors
|
|
434
|
+
});
|
|
435
|
+
return promise;
|
|
436
|
+
}
|
|
437
|
+
function convertErrorMessage(message_, name) {
|
|
438
|
+
const message = message_.toLowerCase();
|
|
439
|
+
|
|
440
|
+
// Network error
|
|
441
|
+
if (message.includes('connection error') || message.includes('connection not open') || message.includes('connection timeout') || message.includes('can not active chain') || message.includes('invalid json rpc')) {
|
|
442
|
+
return [(0, _i18next.t)('Re-enable the network or change RPC on the extension and try again'), (0, _i18next.t)('Unstable network connection')];
|
|
443
|
+
}
|
|
444
|
+
if (message.includes('network is currently not supported')) {
|
|
445
|
+
return [(0, _i18next.t)('This network is not yet supported on SubWallet. |Import the network|https://docs.subwallet.app/main/extension-user-guide/customize-your-networks#import-networks| on SubWallet and try again'), (0, _i18next.t)('Network not supported')];
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Authentication
|
|
449
|
+
if (message.includes('not found address to sign') || message.includes('unable to find account') || message.includes('unable to retrieve keypair')) {
|
|
450
|
+
return ['Address not found on SubWallet. Re-check the address information in the extension then try again'];
|
|
451
|
+
}
|
|
452
|
+
if (message.includes('account not in allowed list')) {
|
|
453
|
+
return ['Account disconnected from the dApp. Open the extension to re-connect the account and try again'];
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Transaction
|
|
457
|
+
|
|
458
|
+
if (message.includes('recipient address not found')) {
|
|
459
|
+
return [(0, _i18next.t)('Enter recipient address and try again'), (0, _i18next.t)('Recipient address not found')];
|
|
460
|
+
}
|
|
461
|
+
if (message.includes('is not a number') || message.includes('invalid number value') || message.includes('invalid bignumberish')) {
|
|
462
|
+
return [(0, _i18next.t)('Amount must be an integer. Enter an integer and try again'), (0, _i18next.t)('Invalid amount')];
|
|
463
|
+
}
|
|
464
|
+
if (message.includes('calculate estimate gas fee') || message.includes('invalidcode')) {
|
|
465
|
+
return [(0, _i18next.t)('Unable to calculate estimated gas for this transaction. Try again or contact support at agent@subwallet.app'), (0, _i18next.t)('Gas calculation error')];
|
|
466
|
+
}
|
|
467
|
+
if (message.includes('invalid recipient address')) {
|
|
468
|
+
return [(0, _i18next.t)('Make sure the recipient address is valid and in the same type as the sender address, then try again'), (0, _i18next.t)('Invalid recipient address')];
|
|
469
|
+
}
|
|
470
|
+
if (message.includes('must be different from sending address')) {
|
|
471
|
+
return [(0, _i18next.t)('The recipient address must be different from the sender address'), (0, _i18next.t)('Invalid recipient address')];
|
|
472
|
+
}
|
|
473
|
+
if (message.includes('the sender address must be the ethereum address type')) {
|
|
474
|
+
return [(0, _i18next.t)('The sender address must be the ethereum address type'), (0, _i18next.t)('Invalid address type')];
|
|
475
|
+
}
|
|
476
|
+
if (message.includes('insufficient balance') || message.includes('insufficient funds')) {
|
|
477
|
+
return [(0, _i18next.t)('Insufficient balance on the sender address. Top up your balance and try again'), (0, _i18next.t)('Unable to sign transaction')];
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Sign Message
|
|
481
|
+
if (message.includes('not found address or payload to sign')) {
|
|
482
|
+
return [(0, _i18next.t)('An error occurred when signing this request. Try again or contact support at agent@subwallet.app'), (0, _i18next.t)('Unable to sign message')];
|
|
483
|
+
}
|
|
484
|
+
if (message.includes('unsupported method') || message.includes('unsupported action')) {
|
|
485
|
+
return [(0, _i18next.t)('This sign method is not supported by SubWallet. Try again or contact support at agent@subwallet.app'), (0, _i18next.t)('Method not supported')];
|
|
486
|
+
}
|
|
487
|
+
return [message, name || ''];
|
|
488
|
+
}
|
|
@@ -50,32 +50,49 @@ function validateTransferRequest(tokenInfo, from, to, value, transferAll) {
|
|
|
50
50
|
}
|
|
51
51
|
return [errors, keypair, transferValue];
|
|
52
52
|
}
|
|
53
|
-
function additionalValidateTransfer(tokenInfo, extrinsicType, receiverTransferTokenFreeBalance, transferAmount, senderTransferTokenTransferable) {
|
|
53
|
+
function additionalValidateTransfer(tokenInfo, nativeTokenInfo, extrinsicType, receiverTransferTokenFreeBalance, transferAmount, senderTransferTokenTransferable, receiverNativeTransferable) {
|
|
54
54
|
const minAmount = (0, _utils._getTokenMinAmount)(tokenInfo);
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const nativeMinAmount = (0, _utils._getTokenMinAmount)(nativeTokenInfo);
|
|
56
|
+
const warnings = [];
|
|
57
|
+
const errors = [];
|
|
57
58
|
|
|
58
|
-
// Check ed of not native token for sender
|
|
59
|
+
// Check ed of not native token for sender after sending
|
|
59
60
|
if (extrinsicType === _KoniTypes.ExtrinsicType.TRANSFER_TOKEN && senderTransferTokenTransferable) {
|
|
60
61
|
if (new _bignumber.default(senderTransferTokenTransferable).minus(transferAmount).lt(minAmount)) {
|
|
61
|
-
warning = new _TransactionWarning.TransactionWarning(_KoniTypes.BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT);
|
|
62
|
+
const warning = new _TransactionWarning.TransactionWarning(_KoniTypes.BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT);
|
|
63
|
+
warnings.push(warning);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Check ed for receiver before sending
|
|
68
|
+
if (extrinsicType === _KoniTypes.ExtrinsicType.TRANSFER_TOKEN && receiverNativeTransferable) {
|
|
69
|
+
if (new _bignumber.default(receiverNativeTransferable).lt(nativeMinAmount)) {
|
|
70
|
+
const error = new _TransactionError.TransactionError(_KoniTypes.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)('The recipient account has {{amount}} {{nativeSymbol}} which can lead to your {{localSymbol}} being lost. Change recipient account and try again', {
|
|
71
|
+
replace: {
|
|
72
|
+
amount: receiverNativeTransferable,
|
|
73
|
+
nativeSymbol: nativeTokenInfo.symbol,
|
|
74
|
+
localSymbol: tokenInfo.symbol
|
|
75
|
+
}
|
|
76
|
+
}));
|
|
77
|
+
errors.push(error);
|
|
62
78
|
}
|
|
63
79
|
}
|
|
64
80
|
|
|
65
|
-
// Check ed for receiver
|
|
81
|
+
// Check ed for receiver after sending
|
|
66
82
|
if (new _bignumber.default(receiverTransferTokenFreeBalance).plus(transferAmount).lt(minAmount)) {
|
|
67
83
|
const atLeast = new _bignumber.default(minAmount).minus(receiverTransferTokenFreeBalance).plus((tokenInfo.decimals || 0) === 0 ? 0 : 1);
|
|
68
84
|
const atLeastStr = (0, _utils3.formatNumber)(atLeast, tokenInfo.decimals || 0, _utils3.balanceFormatter, {
|
|
69
85
|
maxNumberFormat: tokenInfo.decimals || 6
|
|
70
86
|
});
|
|
71
|
-
error = new _TransactionError.TransactionError(_KoniTypes.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
|
|
87
|
+
const error = new _TransactionError.TransactionError(_KoniTypes.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
|
|
72
88
|
replace: {
|
|
73
89
|
amount: atLeastStr,
|
|
74
90
|
symbol: tokenInfo.symbol
|
|
75
91
|
}
|
|
76
92
|
}));
|
|
93
|
+
errors.push(error);
|
|
77
94
|
}
|
|
78
|
-
return [
|
|
95
|
+
return [warnings, errors];
|
|
79
96
|
}
|
|
80
97
|
|
|
81
98
|
// xcm transfer
|
|
@@ -129,7 +129,7 @@ function calculateChainStakedReturnV2(chainInfo, totalIssuance, erasPerDay, last
|
|
|
129
129
|
const multiplier = dayRewardRate.dividedBy(100).plus(1).exponentiatedBy(365);
|
|
130
130
|
inflationToStakers = new _bignumber.default(100).multipliedBy(multiplier).minus(100);
|
|
131
131
|
}
|
|
132
|
-
const averageRewardRate = (['avail_mainnet'].includes(chainInfo.slug) ? inflation : inflationToStakers).dividedBy(supplyStaked);
|
|
132
|
+
const averageRewardRate = (['avail_mainnet', 'dentnet'].includes(chainInfo.slug) ? inflation : inflationToStakers).dividedBy(supplyStaked);
|
|
133
133
|
return averageRewardRate.toNumber();
|
|
134
134
|
}
|
|
135
135
|
function calculateAlephZeroValidatorReturn(chainStakedReturn, commission) {
|
|
@@ -388,7 +388,7 @@ function getAvgValidatorEraReward(supportedDays, eraRewardHistory) {
|
|
|
388
388
|
return sumEraReward.dividedBy(new _bignumber.default(supportedDays - failEra));
|
|
389
389
|
}
|
|
390
390
|
function getSupportedDaysByHistoryDepth(erasPerDay, maxSupportedEras, liveDay) {
|
|
391
|
-
const maxSupportDay = maxSupportedEras / erasPerDay;
|
|
391
|
+
const maxSupportDay = Math.floor(maxSupportedEras / erasPerDay);
|
|
392
392
|
if (liveDay && liveDay <= 30) {
|
|
393
393
|
return Math.min(liveDay - 1, maxSupportDay);
|
|
394
394
|
}
|
|
@@ -1706,18 +1706,23 @@ class KoniExtension {
|
|
|
1706
1706
|
const transferNativeAmount = isTransferNativeToken ? transferAmount.value : '0';
|
|
1707
1707
|
const additionalValidator = async inputTransaction => {
|
|
1708
1708
|
let senderTransferTokenTransferable;
|
|
1709
|
+
let receiverNativeTransferable;
|
|
1709
1710
|
|
|
1710
1711
|
// Check ed for sender
|
|
1711
1712
|
if (!isTransferNativeToken) {
|
|
1712
|
-
const {
|
|
1713
|
-
value
|
|
1714
|
-
} = await this.getAddressTransferableBalance({
|
|
1713
|
+
const [_senderTransferTokenTransferable, _receiverNativeTransferable] = await Promise.all([this.getAddressTransferableBalance({
|
|
1715
1714
|
address: from,
|
|
1716
1715
|
networkKey,
|
|
1717
1716
|
token: tokenSlug,
|
|
1718
1717
|
extrinsicType
|
|
1719
|
-
})
|
|
1720
|
-
|
|
1718
|
+
}), this.getAddressTransferableBalance({
|
|
1719
|
+
address: to,
|
|
1720
|
+
networkKey,
|
|
1721
|
+
token: nativeTokenSlug,
|
|
1722
|
+
extrinsicType: _KoniTypes.ExtrinsicType.TRANSFER_BALANCE
|
|
1723
|
+
})]);
|
|
1724
|
+
senderTransferTokenTransferable = _senderTransferTokenTransferable.value;
|
|
1725
|
+
receiverNativeTransferable = _receiverNativeTransferable.value;
|
|
1721
1726
|
}
|
|
1722
1727
|
const {
|
|
1723
1728
|
value: receiverTransferTokenTransferable
|
|
@@ -1728,9 +1733,9 @@ class KoniExtension {
|
|
|
1728
1733
|
extrinsicType
|
|
1729
1734
|
}); // todo: shouldn't be just transferable, locked also counts
|
|
1730
1735
|
|
|
1731
|
-
const [
|
|
1732
|
-
|
|
1733
|
-
|
|
1736
|
+
const [warnings, errors] = (0, _transfer.additionalValidateTransfer)(transferTokenInfo, nativeTokenInfo, extrinsicType, receiverTransferTokenTransferable, transferAmount.value, senderTransferTokenTransferable, receiverNativeTransferable);
|
|
1737
|
+
warnings.length && inputTransaction.warnings.push(...warnings);
|
|
1738
|
+
errors.length && inputTransaction.errors.push(...errors);
|
|
1734
1739
|
};
|
|
1735
1740
|
return this.#koniState.transactionService.handleTransaction({
|
|
1736
1741
|
errors,
|
|
@@ -4251,6 +4256,21 @@ class KoniExtension {
|
|
|
4251
4256
|
}
|
|
4252
4257
|
/* Swap service */
|
|
4253
4258
|
|
|
4259
|
+
/* Ledger */
|
|
4260
|
+
|
|
4261
|
+
async subscribeLedgerGenericAllowChains(id, port) {
|
|
4262
|
+
const cb = (0, _subscriptions.createSubscription)(id, port);
|
|
4263
|
+
await this.#koniState.eventService.waitLedgerReady;
|
|
4264
|
+
const subscription = this.#koniState.chainService.observable.ledgerGenericAllowChains.subscribe(cb);
|
|
4265
|
+
this.createUnsubscriptionHandle(id, subscription.unsubscribe);
|
|
4266
|
+
port.onDisconnect.addListener(() => {
|
|
4267
|
+
this.cancelSubscription(id);
|
|
4268
|
+
});
|
|
4269
|
+
return this.#koniState.chainService.value.ledgerGenericAllowChains;
|
|
4270
|
+
}
|
|
4271
|
+
|
|
4272
|
+
/* Ledger */
|
|
4273
|
+
|
|
4254
4274
|
// --------------------------------------------------------------
|
|
4255
4275
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
4256
4276
|
async handle(id, type, request, port) {
|
|
@@ -4815,6 +4835,11 @@ class KoniExtension {
|
|
|
4815
4835
|
case 'pri(swapService.handleSwapStep)':
|
|
4816
4836
|
return this.handleSwapStep(request);
|
|
4817
4837
|
/* Swap service */
|
|
4838
|
+
|
|
4839
|
+
/* Ledger */
|
|
4840
|
+
case 'pri(ledger.generic.allow)':
|
|
4841
|
+
return this.subscribeLedgerGenericAllowChains(id, port);
|
|
4842
|
+
/* Ledger */
|
|
4818
4843
|
// Default
|
|
4819
4844
|
default:
|
|
4820
4845
|
throw new Error(`Unable to handle message of type ${type}`);
|