@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
|
@@ -835,6 +835,7 @@ class TransactionService {
|
|
|
835
835
|
const payload = transaction;
|
|
836
836
|
const evmApi = this.state.chainService.getEvmApi(chain);
|
|
837
837
|
const chainInfo = this.state.chainService.getChainInfoByKey(chain);
|
|
838
|
+
const hasError = !!(payload.errors && payload.errors.length > 0);
|
|
838
839
|
const accountPair = _uiKeyring.default.getPair(address);
|
|
839
840
|
const account = {
|
|
840
841
|
address,
|
|
@@ -849,9 +850,9 @@ class TransactionService {
|
|
|
849
850
|
|
|
850
851
|
// Fill contract info
|
|
851
852
|
if (!payload.parseData) {
|
|
852
|
-
const isToContract = await (0, _parseTransaction.isContractAddress)(payload.to || '', evmApi);
|
|
853
|
-
payload.isToContract = isToContract;
|
|
854
853
|
try {
|
|
854
|
+
const isToContract = await (0, _parseTransaction.isContractAddress)(payload.to || '', evmApi);
|
|
855
|
+
payload.isToContract = isToContract;
|
|
855
856
|
payload.parseData = isToContract ? payload.data ? (await (0, _parseTransaction.parseContractInput)(payload.data || '', payload.to || '', chainInfo)).result : '' : payload.data || '';
|
|
856
857
|
} catch (e) {
|
|
857
858
|
console.warn('Unable to parse contract input data');
|
|
@@ -865,11 +866,13 @@ class TransactionService {
|
|
|
865
866
|
// Set unique nonce to avoid transaction errors
|
|
866
867
|
if (!payload.nonce) {
|
|
867
868
|
const evmApi = this.state.chainService.getEvmApi(chain);
|
|
868
|
-
|
|
869
|
+
if (evmApi.isApiConnected) {
|
|
870
|
+
payload.nonce = await (evmApi === null || evmApi === void 0 ? void 0 : evmApi.api.eth.getTransactionCount(address));
|
|
871
|
+
}
|
|
869
872
|
}
|
|
870
873
|
if (!payload.chainId) {
|
|
871
874
|
var _chainInfo$evmInfo$ev, _chainInfo$evmInfo;
|
|
872
|
-
payload.chainId = (_chainInfo$evmInfo$ev = (_chainInfo$evmInfo = chainInfo.evmInfo) === null || _chainInfo$evmInfo === void 0 ? void 0 : _chainInfo$evmInfo.evmChainId) !== null && _chainInfo$evmInfo$ev !== void 0 ? _chainInfo$evmInfo$ev : 1;
|
|
875
|
+
payload.chainId = (_chainInfo$evmInfo$ev = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$evmInfo = chainInfo.evmInfo) === null || _chainInfo$evmInfo === void 0 ? void 0 : _chainInfo$evmInfo.evmChainId) !== null && _chainInfo$evmInfo$ev !== void 0 ? _chainInfo$evmInfo$ev : 1;
|
|
873
876
|
}
|
|
874
877
|
|
|
875
878
|
// Autofill from
|
|
@@ -878,9 +881,10 @@ class TransactionService {
|
|
|
878
881
|
}
|
|
879
882
|
const isExternal = !!account.isExternal;
|
|
880
883
|
const isInjected = !!account.isInjected;
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
+
if (!hasError) {
|
|
885
|
+
// generate hashPayload for EVM transaction
|
|
886
|
+
payload.hashPayload = this.generateHashPayload(chain, payload);
|
|
887
|
+
}
|
|
884
888
|
const emitter = new _eventemitter.default();
|
|
885
889
|
const txObject = {
|
|
886
890
|
nonce: (_payload$nonce = payload.nonce) !== null && _payload$nonce !== void 0 ? _payload$nonce : 0,
|
|
@@ -10,22 +10,17 @@ var _classPrivateFieldLooseKey2 = _interopRequireDefault(require("@babel/runtime
|
|
|
10
10
|
var _utils = require("@json-rpc-tools/utils");
|
|
11
11
|
var _helpers = require("@subwallet/extension-base/services/wallet-connect-service/helpers");
|
|
12
12
|
var _types = require("@subwallet/extension-base/services/wallet-connect-service/types");
|
|
13
|
-
var _utils2 = require("@
|
|
14
|
-
var _utils3 = require("@walletconnect/utils");
|
|
13
|
+
var _utils2 = require("@walletconnect/utils");
|
|
15
14
|
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
|
|
16
15
|
// SPDX-License-Identifier: Apache-2.0
|
|
17
16
|
var _walletConnectService = /*#__PURE__*/(0, _classPrivateFieldLooseKey2.default)("walletConnectService");
|
|
18
17
|
var _koniState = /*#__PURE__*/(0, _classPrivateFieldLooseKey2.default)("koniState");
|
|
19
|
-
var _checkAccount = /*#__PURE__*/(0, _classPrivateFieldLooseKey2.default)("checkAccount");
|
|
20
18
|
var _handleError = /*#__PURE__*/(0, _classPrivateFieldLooseKey2.default)("handleError");
|
|
21
19
|
class Eip155RequestHandler {
|
|
22
20
|
constructor(koniState, walletConnectService) {
|
|
23
21
|
Object.defineProperty(this, _handleError, {
|
|
24
22
|
value: _handleError2
|
|
25
23
|
});
|
|
26
|
-
Object.defineProperty(this, _checkAccount, {
|
|
27
|
-
value: _checkAccount2
|
|
28
|
-
});
|
|
29
24
|
Object.defineProperty(this, _walletConnectService, {
|
|
30
25
|
writable: true,
|
|
31
26
|
value: void 0
|
|
@@ -50,11 +45,8 @@ class Eip155RequestHandler {
|
|
|
50
45
|
const method = request.method;
|
|
51
46
|
const requestSession = (0, _classPrivateFieldLooseBase2.default)(this, _walletConnectService)[_walletConnectService].getSession(topic);
|
|
52
47
|
const url = requestSession.peer.metadata.url;
|
|
53
|
-
const sessionAccounts = requestSession.namespaces.eip155.accounts.map(account => account.split(':')[2]);
|
|
54
48
|
if ([_types.EIP155_SIGNING_METHODS.PERSONAL_SIGN, _types.EIP155_SIGNING_METHODS.ETH_SIGN, _types.EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA, _types.EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V3, _types.EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V4].includes(method)) {
|
|
55
|
-
|
|
56
|
-
(0, _classPrivateFieldLooseBase2.default)(this, _checkAccount)[_checkAccount](address, sessionAccounts);
|
|
57
|
-
(0, _classPrivateFieldLooseBase2.default)(this, _koniState)[_koniState].evmSign((0, _helpers.getWCId)(id), url, method === _types.EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA ? _types.EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V4 : method, request.params, sessionAccounts).then(async signature => {
|
|
49
|
+
(0, _classPrivateFieldLooseBase2.default)(this, _koniState)[_koniState].evmSign((0, _helpers.getWCId)(id), url, method === _types.EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA ? _types.EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V4 : method, request.params, topic).then(async signature => {
|
|
58
50
|
await (0, _classPrivateFieldLooseBase2.default)(this, _walletConnectService)[_walletConnectService].responseRequest({
|
|
59
51
|
topic: topic,
|
|
60
52
|
response: (0, _utils.formatJsonRpcResult)(id, signature)
|
|
@@ -65,46 +57,30 @@ class Eip155RequestHandler {
|
|
|
65
57
|
} else if (method === _types.EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION) {
|
|
66
58
|
const [tx] = (0, _helpers.parseRequestParams)(request.params);
|
|
67
59
|
const address = tx.from;
|
|
68
|
-
(0, _classPrivateFieldLooseBase2.default)(this, _checkAccount)[_checkAccount](address, sessionAccounts);
|
|
69
60
|
const chainId = parseInt(_chainId.split(':')[1]);
|
|
70
61
|
const [networkKey, chainInfo] = (0, _classPrivateFieldLooseBase2.default)(this, _koniState)[_koniState].findNetworkKeyByChainId(chainId);
|
|
71
62
|
if (!networkKey || !chainInfo) {
|
|
72
|
-
throw new Error((0,
|
|
63
|
+
throw new Error((0, _utils2.getSdkError)('UNSUPPORTED_CHAINS').message + ' ' + address);
|
|
73
64
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
topic: topic,
|
|
79
|
-
response: (0, _utils.formatJsonRpcResult)(id, signature)
|
|
80
|
-
});
|
|
81
|
-
}).catch(e => {
|
|
82
|
-
(0, _classPrivateFieldLooseBase2.default)(this, _handleError)[_handleError](topic, id, e);
|
|
83
|
-
});
|
|
84
|
-
};
|
|
85
|
-
if (!chainState.active) {
|
|
86
|
-
(0, _classPrivateFieldLooseBase2.default)(this, _koniState)[_koniState].chainService.enableChain(networkKey).then(createRequest).catch(() => {
|
|
87
|
-
throw new Error((0, _utils3.getSdkError)('USER_REJECTED').message + ' Can not active chain: ' + chainInfo.name);
|
|
65
|
+
(0, _classPrivateFieldLooseBase2.default)(this, _koniState)[_koniState].evmSendTransaction((0, _helpers.getWCId)(id), url, tx, networkKey, topic).then(async signature => {
|
|
66
|
+
await (0, _classPrivateFieldLooseBase2.default)(this, _walletConnectService)[_walletConnectService].responseRequest({
|
|
67
|
+
topic: topic,
|
|
68
|
+
response: (0, _utils.formatJsonRpcResult)(id, signature)
|
|
88
69
|
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
}
|
|
70
|
+
}).catch(e => {
|
|
71
|
+
(0, _classPrivateFieldLooseBase2.default)(this, _handleError)[_handleError](topic, id, e);
|
|
72
|
+
});
|
|
92
73
|
} else {
|
|
93
|
-
throw Error((0,
|
|
74
|
+
throw Error((0, _utils2.getSdkError)('INVALID_METHOD').message + ' ' + method);
|
|
94
75
|
}
|
|
95
76
|
}
|
|
96
77
|
}
|
|
97
78
|
exports.default = Eip155RequestHandler;
|
|
98
|
-
function _checkAccount2(address, accounts) {
|
|
99
|
-
if (!accounts.find(account => (0, _utils2.isSameAddress)(account, address))) {
|
|
100
|
-
throw new Error((0, _utils3.getSdkError)('UNSUPPORTED_ACCOUNTS').message + ' ' + address);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
79
|
function _handleError2(topic, id, e) {
|
|
104
80
|
console.log(e);
|
|
105
81
|
let message = e.message;
|
|
106
82
|
if (message.includes('User Rejected Request')) {
|
|
107
|
-
message = (0,
|
|
83
|
+
message = (0, _utils2.getSdkError)('USER_REJECTED').message;
|
|
108
84
|
}
|
|
109
85
|
(0, _classPrivateFieldLooseBase2.default)(this, _walletConnectService)[_walletConnectService].responseRequest({
|
|
110
86
|
topic: topic,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ConfirmationType } from '@subwallet/extension-base/background/KoniTypes';
|
|
2
|
+
import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
|
|
3
|
+
import { AuthUrlInfo } from '@subwallet/extension-base/services/request-service/types';
|
|
4
|
+
import { KeyringPair } from '@subwallet/keyring/types';
|
|
5
|
+
export declare type ValidateStepFunction = (koni: KoniState, url: string, payload: PayloadValidated, topic?: string) => Promise<PayloadValidated>;
|
|
6
|
+
export interface PayloadValidated {
|
|
7
|
+
networkKey: string;
|
|
8
|
+
address: string;
|
|
9
|
+
pair?: KeyringPair;
|
|
10
|
+
authInfo?: AuthUrlInfo;
|
|
11
|
+
method?: string;
|
|
12
|
+
payloadAfterValidated: any;
|
|
13
|
+
errorPosition?: 'dApp' | 'ui';
|
|
14
|
+
confirmationType?: ConfirmationType;
|
|
15
|
+
errors: Error[];
|
|
16
|
+
}
|
|
17
|
+
export declare function generateValidationProcess(koni: KoniState, url: string, payloadValidate: PayloadValidated, validationMiddlewareSteps: ValidateStepFunction[], topic?: string): Promise<PayloadValidated>;
|
|
18
|
+
export declare function validationAuthMiddleware(koni: KoniState, url: string, payload: PayloadValidated): Promise<PayloadValidated>;
|
|
19
|
+
export declare function validationConnectMiddleware(koni: KoniState, url: string, payload: PayloadValidated): Promise<PayloadValidated>;
|
|
20
|
+
export declare function validationEvmDataTransactionMiddleware(koni: KoniState, url: string, payload: PayloadValidated): Promise<PayloadValidated>;
|
|
21
|
+
export declare function validationEvmSignMessageMiddleware(koni: KoniState, url: string, payload_: PayloadValidated): Promise<PayloadValidated>;
|
|
22
|
+
export declare function validationAuthWCMiddleware(koni: KoniState, url: string, payload: PayloadValidated, topic?: string): Promise<PayloadValidated>;
|
|
23
|
+
export declare function convertErrorMessage(message_: string, name?: string): string[];
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { EvmProviderError } from '@subwallet/extension-base/background/errors/EvmProviderError';
|
|
5
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
6
|
+
import { BasicTxErrorType, EvmProviderErrorType } from '@subwallet/extension-base/background/KoniTypes';
|
|
7
|
+
import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils';
|
|
8
|
+
import { BN_ZERO, createPromiseHandler, isSameAddress, stripUrl, wait } from '@subwallet/extension-base/utils';
|
|
9
|
+
import { isContractAddress, parseContractInput } from '@subwallet/extension-base/utils/eth/parseTransaction';
|
|
10
|
+
import { keyring } from '@subwallet/ui-keyring';
|
|
11
|
+
import { getSdkError } from '@walletconnect/utils';
|
|
12
|
+
import BigN from 'bignumber.js';
|
|
13
|
+
import BN from 'bn.js';
|
|
14
|
+
import { t } from 'i18next';
|
|
15
|
+
import { isString } from '@polkadot/util';
|
|
16
|
+
import { isEthereumAddress } from '@polkadot/util-crypto';
|
|
17
|
+
export async function generateValidationProcess(koni, url, payloadValidate, validationMiddlewareSteps, topic) {
|
|
18
|
+
let resultValidated = payloadValidate;
|
|
19
|
+
for (const step of validationMiddlewareSteps) {
|
|
20
|
+
resultValidated = await step(koni, url, resultValidated, topic);
|
|
21
|
+
if (resultValidated.errorPosition === 'dApp') {
|
|
22
|
+
throw resultValidated.errors[0];
|
|
23
|
+
} else if (resultValidated.errorPosition === 'ui') {
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return resultValidated;
|
|
28
|
+
}
|
|
29
|
+
export async function validationAuthMiddleware(koni, url, payload) {
|
|
30
|
+
const {
|
|
31
|
+
address,
|
|
32
|
+
errors
|
|
33
|
+
} = payload;
|
|
34
|
+
if (!address || !isString(address)) {
|
|
35
|
+
payload.errorPosition = 'dApp';
|
|
36
|
+
const [message] = convertErrorMessage('Not found address to sign');
|
|
37
|
+
errors.push(new Error(message));
|
|
38
|
+
} else {
|
|
39
|
+
try {
|
|
40
|
+
payload.pair = keyring.getPair(address);
|
|
41
|
+
if (!payload.pair) {
|
|
42
|
+
payload.errorPosition = 'dApp';
|
|
43
|
+
const [message] = convertErrorMessage('Unable to find account');
|
|
44
|
+
errors.push(new Error(message));
|
|
45
|
+
} else {
|
|
46
|
+
const authList = await koni.getAuthList();
|
|
47
|
+
const authInfo = authList[stripUrl(url)];
|
|
48
|
+
if (!authInfo || !authInfo.isAllowed || !authInfo.isAllowedMap[payload.pair.address]) {
|
|
49
|
+
payload.errorPosition = 'dApp';
|
|
50
|
+
const [message] = convertErrorMessage('Account not in allowed list', '');
|
|
51
|
+
errors.push(new Error(message));
|
|
52
|
+
}
|
|
53
|
+
payload.authInfo = authInfo;
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
const [message] = convertErrorMessage(e.message);
|
|
57
|
+
payload.errorPosition = 'dApp';
|
|
58
|
+
errors.push(new Error(message));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return payload;
|
|
62
|
+
}
|
|
63
|
+
export async function validationConnectMiddleware(koni, url, payload) {
|
|
64
|
+
let currentChain;
|
|
65
|
+
let autoActiveChain = false;
|
|
66
|
+
let {
|
|
67
|
+
address,
|
|
68
|
+
authInfo,
|
|
69
|
+
errors,
|
|
70
|
+
networkKey
|
|
71
|
+
} = {
|
|
72
|
+
...payload
|
|
73
|
+
};
|
|
74
|
+
const handleError = message_ => {
|
|
75
|
+
payload.errorPosition = 'ui';
|
|
76
|
+
payload.confirmationType = 'errorConnectNetwork';
|
|
77
|
+
const [message, name] = convertErrorMessage(message_);
|
|
78
|
+
const error = new EvmProviderError(EvmProviderErrorType.CHAIN_DISCONNECTED, message, undefined, name);
|
|
79
|
+
console.error(error);
|
|
80
|
+
errors.push(error);
|
|
81
|
+
};
|
|
82
|
+
if (authInfo !== null && authInfo !== void 0 && authInfo.currentEvmNetworkKey) {
|
|
83
|
+
currentChain = authInfo === null || authInfo === void 0 ? void 0 : authInfo.currentEvmNetworkKey;
|
|
84
|
+
}
|
|
85
|
+
if (authInfo !== null && authInfo !== void 0 && authInfo.isAllowed) {
|
|
86
|
+
autoActiveChain = true;
|
|
87
|
+
}
|
|
88
|
+
const currentEvmNetwork = koni.requestService.getDAppChainInfo({
|
|
89
|
+
autoActive: autoActiveChain,
|
|
90
|
+
accessType: 'evm',
|
|
91
|
+
defaultChain: currentChain,
|
|
92
|
+
url
|
|
93
|
+
});
|
|
94
|
+
networkKey = networkKey || (currentEvmNetwork === null || currentEvmNetwork === void 0 ? void 0 : currentEvmNetwork.slug) || '';
|
|
95
|
+
if (networkKey) {
|
|
96
|
+
const chainStatus = koni.getChainStateByKey(networkKey);
|
|
97
|
+
const chainInfo = koni.getChainInfo(networkKey);
|
|
98
|
+
if (!chainStatus.active) {
|
|
99
|
+
try {
|
|
100
|
+
await koni.chainService.enableChain(networkKey);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
handleError('Can not active chain: ' + chainInfo.name);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const evmApi = koni.getEvmApi(networkKey);
|
|
106
|
+
const web3 = evmApi === null || evmApi === void 0 ? void 0 : evmApi.api;
|
|
107
|
+
let currentProviderConnected = false;
|
|
108
|
+
const checkProviderConnected = async () => {
|
|
109
|
+
try {
|
|
110
|
+
currentProviderConnected = !!(await web3.eth.getBalance(address));
|
|
111
|
+
} catch (e) {
|
|
112
|
+
handleError(e.message);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Calculate transaction data
|
|
117
|
+
try {
|
|
118
|
+
await Promise.race([checkProviderConnected(), wait(3000).then(async () => {
|
|
119
|
+
if (!currentProviderConnected) {
|
|
120
|
+
await koni.chainService.initSingleApi(networkKey);
|
|
121
|
+
await checkProviderConnected();
|
|
122
|
+
}
|
|
123
|
+
})]);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
handleError(e.message);
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
handleError('This network is currently not supported');
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
...payload,
|
|
132
|
+
networkKey,
|
|
133
|
+
errors
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export async function validationEvmDataTransactionMiddleware(koni, url, payload) {
|
|
137
|
+
const errors = payload.errors || [];
|
|
138
|
+
let estimateGas = '';
|
|
139
|
+
const transactionParams = payload.payloadAfterValidated;
|
|
140
|
+
const {
|
|
141
|
+
address: fromAddress,
|
|
142
|
+
networkKey,
|
|
143
|
+
pair
|
|
144
|
+
} = payload;
|
|
145
|
+
const evmApi = koni.getEvmApi(networkKey || '');
|
|
146
|
+
const web3 = evmApi === null || evmApi === void 0 ? void 0 : evmApi.api;
|
|
147
|
+
const autoFormatNumber = val => {
|
|
148
|
+
if (typeof val === 'string' && val.startsWith('0x')) {
|
|
149
|
+
return new BN(val.replace('0x', ''), 16).toString();
|
|
150
|
+
} else if (typeof val === 'number') {
|
|
151
|
+
return val.toString();
|
|
152
|
+
}
|
|
153
|
+
return val;
|
|
154
|
+
};
|
|
155
|
+
const handleError = message_ => {
|
|
156
|
+
payload.errorPosition = 'ui';
|
|
157
|
+
payload.confirmationType = 'evmWatchTransactionRequest';
|
|
158
|
+
const [message, name] = convertErrorMessage(message_);
|
|
159
|
+
const error = new TransactionError(BasicTxErrorType.INVALID_PARAMS, message, undefined, name);
|
|
160
|
+
console.error(error);
|
|
161
|
+
errors.push(error);
|
|
162
|
+
};
|
|
163
|
+
if (!web3) {
|
|
164
|
+
handleError('connection error');
|
|
165
|
+
}
|
|
166
|
+
const transaction = {
|
|
167
|
+
from: transactionParams.from,
|
|
168
|
+
to: transactionParams.to,
|
|
169
|
+
value: autoFormatNumber(transactionParams.value),
|
|
170
|
+
gas: autoFormatNumber(transactionParams.gas),
|
|
171
|
+
gasPrice: autoFormatNumber(transactionParams.gasPrice || transactionParams.gasLimit),
|
|
172
|
+
maxPriorityFeePerGas: autoFormatNumber(transactionParams.maxPriorityFeePerGas),
|
|
173
|
+
maxFeePerGas: autoFormatNumber(transactionParams.maxFeePerGas),
|
|
174
|
+
data: transactionParams.data
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Address is validated in before step
|
|
178
|
+
if (!fromAddress || !isEthereumAddress(fromAddress)) {
|
|
179
|
+
handleError('the sender address must be the ethereum address type');
|
|
180
|
+
}
|
|
181
|
+
if (transaction.to && !isEthereumAddress(transaction.to)) {
|
|
182
|
+
handleError('invalid recipient address');
|
|
183
|
+
}
|
|
184
|
+
if (fromAddress === transaction.to) {
|
|
185
|
+
handleError('receiving address must be different from sending address');
|
|
186
|
+
}
|
|
187
|
+
if (!transaction.to) {
|
|
188
|
+
if (transaction.data) {
|
|
189
|
+
if (transaction.value) {
|
|
190
|
+
try {
|
|
191
|
+
const valueBn = new BigN(transaction.value.toString());
|
|
192
|
+
if (!valueBn.eq(BN_ZERO)) {
|
|
193
|
+
handleError('Recipient address not found');
|
|
194
|
+
}
|
|
195
|
+
} catch (e) {
|
|
196
|
+
handleError('invalid number');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
handleError('Recipient address not found');
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (!transaction.gas) {
|
|
204
|
+
const getTransactionGas = async () => {
|
|
205
|
+
try {
|
|
206
|
+
transaction.gas = await web3.eth.estimateGas({
|
|
207
|
+
...transaction
|
|
208
|
+
});
|
|
209
|
+
} catch (e) {
|
|
210
|
+
handleError(e.message);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// Calculate transaction data
|
|
215
|
+
try {
|
|
216
|
+
await Promise.race([getTransactionGas(), wait(3000).then(async () => {
|
|
217
|
+
if (!transaction.gas) {
|
|
218
|
+
await koni.chainService.initSingleApi(networkKey || '');
|
|
219
|
+
await getTransactionGas();
|
|
220
|
+
}
|
|
221
|
+
})]);
|
|
222
|
+
} catch (e) {
|
|
223
|
+
handleError(e.message);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!transaction.gas) {
|
|
227
|
+
handleError(new TransactionError(BasicTxErrorType.INTERNAL_ERROR).message);
|
|
228
|
+
} else {
|
|
229
|
+
if (transactionParams.maxPriorityFeePerGas && transactionParams.maxFeePerGas) {
|
|
230
|
+
const maxFee = new BigN(transactionParams.maxFeePerGas);
|
|
231
|
+
estimateGas = maxFee.multipliedBy(transaction.gas).toFixed(0);
|
|
232
|
+
} else if (transactionParams.gasPrice) {
|
|
233
|
+
estimateGas = new BigN(transactionParams.gasPrice).multipliedBy(transaction.gas).toFixed(0);
|
|
234
|
+
} else {
|
|
235
|
+
try {
|
|
236
|
+
const priority = await calculateGasFeeParams(evmApi, networkKey || '');
|
|
237
|
+
if (priority.baseGasFee) {
|
|
238
|
+
transaction.maxPriorityFeePerGas = priority.maxPriorityFeePerGas.toString();
|
|
239
|
+
transaction.maxFeePerGas = priority.maxFeePerGas.toString();
|
|
240
|
+
const maxFee = priority.maxFeePerGas;
|
|
241
|
+
estimateGas = maxFee.multipliedBy(transaction.gas).toFixed(0);
|
|
242
|
+
} else {
|
|
243
|
+
transaction.gasPrice = priority.gasPrice;
|
|
244
|
+
estimateGas = new BigN(priority.gasPrice).multipliedBy(transaction.gas).toFixed(0);
|
|
245
|
+
}
|
|
246
|
+
} catch (e) {
|
|
247
|
+
handleError(e.message);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
// Validate balance
|
|
252
|
+
const balance = new BN((await web3.eth.getBalance(fromAddress)) || 0);
|
|
253
|
+
if (!estimateGas) {
|
|
254
|
+
handleError('Can\'t calculate estimate gas fee');
|
|
255
|
+
} else if (balance.lt(new BN(estimateGas).add(new BN(autoFormatNumber(transactionParams.value) || '0')))) {
|
|
256
|
+
handleError('Insufficient balance');
|
|
257
|
+
}
|
|
258
|
+
} catch (e) {
|
|
259
|
+
handleError(e.message);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const pair_ = pair || keyring.getPair(fromAddress);
|
|
263
|
+
const account = {
|
|
264
|
+
address: fromAddress,
|
|
265
|
+
...(pair_ === null || pair_ === void 0 ? void 0 : pair_.meta)
|
|
266
|
+
};
|
|
267
|
+
try {
|
|
268
|
+
transaction.nonce = await web3.eth.getTransactionCount(fromAddress);
|
|
269
|
+
} catch (e) {
|
|
270
|
+
handleError(e.message);
|
|
271
|
+
}
|
|
272
|
+
const hasError = errors && errors.length > 0 || !networkKey;
|
|
273
|
+
const evmNetwork = koni.getChainInfo(networkKey || '');
|
|
274
|
+
let isToContract = false;
|
|
275
|
+
let hashPayload = '';
|
|
276
|
+
let parseData = '';
|
|
277
|
+
try {
|
|
278
|
+
hashPayload = hasError ? '' : koni.transactionService.generateHashPayload(networkKey, transaction);
|
|
279
|
+
isToContract = await isContractAddress(transaction.to || '', evmApi);
|
|
280
|
+
parseData = isToContract ? transaction.data && !hasError ? (await parseContractInput(transaction.data, transaction.to || '', evmNetwork)).result : '' : transaction.data || '';
|
|
281
|
+
} catch (e) {
|
|
282
|
+
handleError(e.message);
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
...payload,
|
|
286
|
+
errors,
|
|
287
|
+
payloadAfterValidated: {
|
|
288
|
+
...transaction,
|
|
289
|
+
account,
|
|
290
|
+
estimateGas,
|
|
291
|
+
hashPayload,
|
|
292
|
+
isToContract,
|
|
293
|
+
parseData,
|
|
294
|
+
canSign: !hasError
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
export async function validationEvmSignMessageMiddleware(koni, url, payload_) {
|
|
299
|
+
const {
|
|
300
|
+
address,
|
|
301
|
+
errors,
|
|
302
|
+
method,
|
|
303
|
+
pair: pair_
|
|
304
|
+
} = payload_;
|
|
305
|
+
let payload = payload_.payloadAfterValidated;
|
|
306
|
+
const {
|
|
307
|
+
promise,
|
|
308
|
+
resolve
|
|
309
|
+
} = createPromiseHandler();
|
|
310
|
+
let hashPayload = '';
|
|
311
|
+
let canSign = false;
|
|
312
|
+
const handleError = message_ => {
|
|
313
|
+
payload_.errorPosition = 'ui';
|
|
314
|
+
payload_.confirmationType = 'evmSignatureRequest';
|
|
315
|
+
const [message, name] = convertErrorMessage(message_);
|
|
316
|
+
const error = new EvmProviderError(EvmProviderErrorType.INVALID_PARAMS, message, undefined, name);
|
|
317
|
+
console.error(error);
|
|
318
|
+
errors.push(new EvmProviderError(EvmProviderErrorType.INVALID_PARAMS, message, undefined, name));
|
|
319
|
+
};
|
|
320
|
+
if (address === '' || !payload) {
|
|
321
|
+
handleError('Not found address or payload to sign');
|
|
322
|
+
}
|
|
323
|
+
const pair = pair_ || keyring.getPair(address);
|
|
324
|
+
const account = {
|
|
325
|
+
address: pair.address,
|
|
326
|
+
...pair.meta
|
|
327
|
+
};
|
|
328
|
+
if (method) {
|
|
329
|
+
if (['eth_sign', 'personal_sign', 'eth_signTypedData', 'eth_signTypedData_v1', 'eth_signTypedData_v3', 'eth_signTypedData_v4'].indexOf(method) < 0) {
|
|
330
|
+
handleError('Unsupported action');
|
|
331
|
+
}
|
|
332
|
+
if (['eth_signTypedData_v3', 'eth_signTypedData_v4'].indexOf(method) > -1) {
|
|
333
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-assignment
|
|
334
|
+
payload = JSON.parse(payload);
|
|
335
|
+
}
|
|
336
|
+
switch (method) {
|
|
337
|
+
case 'personal_sign':
|
|
338
|
+
canSign = true;
|
|
339
|
+
hashPayload = payload;
|
|
340
|
+
break;
|
|
341
|
+
case 'eth_sign':
|
|
342
|
+
case 'eth_signTypedData':
|
|
343
|
+
case 'eth_signTypedData_v1':
|
|
344
|
+
case 'eth_signTypedData_v3':
|
|
345
|
+
case 'eth_signTypedData_v4':
|
|
346
|
+
if (!account.isExternal) {
|
|
347
|
+
canSign = true;
|
|
348
|
+
}
|
|
349
|
+
break;
|
|
350
|
+
default:
|
|
351
|
+
handleError('Unsupported action');
|
|
352
|
+
}
|
|
353
|
+
} else {
|
|
354
|
+
handleError('Unsupported method');
|
|
355
|
+
}
|
|
356
|
+
const payloadAfterValidated = {
|
|
357
|
+
account: account,
|
|
358
|
+
type: method || '',
|
|
359
|
+
payload: payload,
|
|
360
|
+
hashPayload: hashPayload,
|
|
361
|
+
canSign: canSign,
|
|
362
|
+
id: ''
|
|
363
|
+
};
|
|
364
|
+
resolve({
|
|
365
|
+
...payload_,
|
|
366
|
+
errors,
|
|
367
|
+
payloadAfterValidated
|
|
368
|
+
});
|
|
369
|
+
return promise;
|
|
370
|
+
}
|
|
371
|
+
export function validationAuthWCMiddleware(koni, url, payload, topic) {
|
|
372
|
+
const {
|
|
373
|
+
promise,
|
|
374
|
+
resolve
|
|
375
|
+
} = createPromiseHandler();
|
|
376
|
+
const {
|
|
377
|
+
address,
|
|
378
|
+
errors
|
|
379
|
+
} = payload;
|
|
380
|
+
if (!topic) {
|
|
381
|
+
payload.errorPosition = 'dApp';
|
|
382
|
+
errors.push(new Error(getSdkError('UNAUTHORIZED_EXTEND_REQUEST').message));
|
|
383
|
+
} else {
|
|
384
|
+
const requestSession = koni.walletConnectService.getSession(topic);
|
|
385
|
+
let sessionAccounts = [];
|
|
386
|
+
if (isEthereumAddress(address)) {
|
|
387
|
+
var _requestSession$names;
|
|
388
|
+
sessionAccounts = ((_requestSession$names = requestSession.namespaces.eip155.accounts) === null || _requestSession$names === void 0 ? void 0 : _requestSession$names.map(account => account.split(':')[2])) || sessionAccounts;
|
|
389
|
+
} else {
|
|
390
|
+
var _requestSession$names2;
|
|
391
|
+
sessionAccounts = ((_requestSession$names2 = requestSession.namespaces.polkadot.accounts) === null || _requestSession$names2 === void 0 ? void 0 : _requestSession$names2.map(account => account.split(':')[2])) || sessionAccounts;
|
|
392
|
+
}
|
|
393
|
+
if (!address || !isString(address)) {
|
|
394
|
+
payload.errorPosition = 'dApp';
|
|
395
|
+
const [message] = convertErrorMessage('Unable to find account');
|
|
396
|
+
errors.push(new Error(message));
|
|
397
|
+
} else {
|
|
398
|
+
try {
|
|
399
|
+
payload.pair = keyring.getPair(address);
|
|
400
|
+
if (!payload.pair) {
|
|
401
|
+
payload.errorPosition = 'dApp';
|
|
402
|
+
const [message] = convertErrorMessage('Unable to find account');
|
|
403
|
+
errors.push(new Error(message));
|
|
404
|
+
}
|
|
405
|
+
const isExitsAccount = sessionAccounts.find(account => isSameAddress(account, address));
|
|
406
|
+
if (!isExitsAccount) {
|
|
407
|
+
payload.errorPosition = 'dApp';
|
|
408
|
+
const [message] = convertErrorMessage('Account not in allowed list');
|
|
409
|
+
errors.push(new Error(message));
|
|
410
|
+
}
|
|
411
|
+
} catch (e) {
|
|
412
|
+
const [message] = convertErrorMessage(e.message);
|
|
413
|
+
payload.errorPosition = 'dApp';
|
|
414
|
+
errors.push(new Error(message));
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
resolve({
|
|
419
|
+
...payload,
|
|
420
|
+
errors
|
|
421
|
+
});
|
|
422
|
+
return promise;
|
|
423
|
+
}
|
|
424
|
+
export function convertErrorMessage(message_, name) {
|
|
425
|
+
const message = message_.toLowerCase();
|
|
426
|
+
|
|
427
|
+
// Network error
|
|
428
|
+
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')) {
|
|
429
|
+
return [t('Re-enable the network or change RPC on the extension and try again'), t('Unstable network connection')];
|
|
430
|
+
}
|
|
431
|
+
if (message.includes('network is currently not supported')) {
|
|
432
|
+
return [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'), t('Network not supported')];
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Authentication
|
|
436
|
+
if (message.includes('not found address to sign') || message.includes('unable to find account') || message.includes('unable to retrieve keypair')) {
|
|
437
|
+
return ['Address not found on SubWallet. Re-check the address information in the extension then try again'];
|
|
438
|
+
}
|
|
439
|
+
if (message.includes('account not in allowed list')) {
|
|
440
|
+
return ['Account disconnected from the dApp. Open the extension to re-connect the account and try again'];
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Transaction
|
|
444
|
+
|
|
445
|
+
if (message.includes('recipient address not found')) {
|
|
446
|
+
return [t('Enter recipient address and try again'), t('Recipient address not found')];
|
|
447
|
+
}
|
|
448
|
+
if (message.includes('is not a number') || message.includes('invalid number value') || message.includes('invalid bignumberish')) {
|
|
449
|
+
return [t('Amount must be an integer. Enter an integer and try again'), t('Invalid amount')];
|
|
450
|
+
}
|
|
451
|
+
if (message.includes('calculate estimate gas fee') || message.includes('invalidcode')) {
|
|
452
|
+
return [t('Unable to calculate estimated gas for this transaction. Try again or contact support at agent@subwallet.app'), t('Gas calculation error')];
|
|
453
|
+
}
|
|
454
|
+
if (message.includes('invalid recipient address')) {
|
|
455
|
+
return [t('Make sure the recipient address is valid and in the same type as the sender address, then try again'), t('Invalid recipient address')];
|
|
456
|
+
}
|
|
457
|
+
if (message.includes('must be different from sending address')) {
|
|
458
|
+
return [t('The recipient address must be different from the sender address'), t('Invalid recipient address')];
|
|
459
|
+
}
|
|
460
|
+
if (message.includes('the sender address must be the ethereum address type')) {
|
|
461
|
+
return [t('The sender address must be the ethereum address type'), t('Invalid address type')];
|
|
462
|
+
}
|
|
463
|
+
if (message.includes('insufficient balance') || message.includes('insufficient funds')) {
|
|
464
|
+
return [t('Insufficient balance on the sender address. Top up your balance and try again'), t('Unable to sign transaction')];
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Sign Message
|
|
468
|
+
if (message.includes('not found address or payload to sign')) {
|
|
469
|
+
return [t('An error occurred when signing this request. Try again or contact support at agent@subwallet.app'), t('Unable to sign message')];
|
|
470
|
+
}
|
|
471
|
+
if (message.includes('unsupported method') || message.includes('unsupported action')) {
|
|
472
|
+
return [t('This sign method is not supported by SubWallet. Try again or contact support at agent@subwallet.app'), t('Method not supported')];
|
|
473
|
+
}
|
|
474
|
+
return [message, name || ''];
|
|
475
|
+
}
|
|
@@ -7,7 +7,7 @@ import { OptionalSWTransaction, SWTransactionInput, SWTransactionResponse } from
|
|
|
7
7
|
import { KeyringPair } from '@subwallet/keyring/types';
|
|
8
8
|
import BigN from 'bignumber.js';
|
|
9
9
|
export declare function validateTransferRequest(tokenInfo: _ChainAsset, from: _Address, to: _Address, value: string | undefined, transferAll: boolean | undefined): [TransactionError[], KeyringPair | undefined, BigN | undefined];
|
|
10
|
-
export declare function additionalValidateTransfer(tokenInfo: _ChainAsset, extrinsicType: ExtrinsicType, receiverTransferTokenFreeBalance: string, transferAmount: string, senderTransferTokenTransferable?: string): [TransactionWarning
|
|
10
|
+
export declare function additionalValidateTransfer(tokenInfo: _ChainAsset, nativeTokenInfo: _ChainAsset, extrinsicType: ExtrinsicType, receiverTransferTokenFreeBalance: string, transferAmount: string, senderTransferTokenTransferable?: string, receiverNativeTransferable?: string): [TransactionWarning[], TransactionError[]];
|
|
11
11
|
export declare function validateXcmTransferRequest(destTokenInfo: _ChainAsset | undefined, sender: _Address, sendingValue: string): [TransactionError[], KeyringPair | undefined, BigN | undefined];
|
|
12
12
|
export declare function additionalValidateXcmTransfer(originTokenInfo: _ChainAsset, destinationTokenInfo: _ChainAsset, sendingAmount: string, senderTransferable: string, receiverNativeBalance: string, destChainInfo: _ChainInfo, isSnowBridge?: boolean): [TransactionWarning | undefined, TransactionError | undefined];
|
|
13
13
|
export declare function checkSupportForTransaction(validationResponse: SWTransactionResponse, transaction: OptionalSWTransaction): void;
|