@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.
Files changed (58) hide show
  1. package/background/KoniTypes.d.ts +9 -0
  2. package/background/errors/EvmProviderError.d.ts +1 -1
  3. package/background/errors/EvmProviderError.js +2 -2
  4. package/background/errors/SWError.d.ts +1 -1
  5. package/background/errors/SWError.js +4 -1
  6. package/background/errors/TransactionError.d.ts +1 -1
  7. package/background/errors/TransactionError.js +2 -2
  8. package/cjs/background/errors/EvmProviderError.js +2 -2
  9. package/cjs/background/errors/SWError.js +4 -1
  10. package/cjs/background/errors/TransactionError.js +2 -2
  11. package/cjs/core/logic-validation/index.js +49 -0
  12. package/cjs/core/logic-validation/request.js +488 -0
  13. package/cjs/core/logic-validation/transfer.js +25 -8
  14. package/cjs/koni/api/staking/bonding/utils.js +2 -2
  15. package/cjs/koni/background/handlers/Extension.js +33 -8
  16. package/cjs/koni/background/handlers/State.js +41 -160
  17. package/cjs/koni/background/handlers/Tabs.js +35 -33
  18. package/cjs/packageInfo.js +1 -1
  19. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +16 -8
  20. package/cjs/services/chain-service/constants.js +6 -1
  21. package/cjs/services/chain-service/index.js +32 -2
  22. package/cjs/services/chain-service/utils/index.js +2 -2
  23. package/cjs/services/earning-service/constants/chains.js +2 -2
  24. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +4 -3
  25. package/cjs/services/earning-service/service.js +1 -1
  26. package/cjs/services/event-service/index.js +1 -0
  27. package/cjs/services/request-service/handler/EvmRequestHandler.js +2 -1
  28. package/cjs/services/transaction-service/index.js +11 -7
  29. package/cjs/services/wallet-connect-service/handler/Eip155RequestHandler.js +12 -36
  30. package/core/logic-validation/index.d.ts +4 -0
  31. package/core/logic-validation/index.js +7 -0
  32. package/core/logic-validation/request.d.ts +23 -0
  33. package/core/logic-validation/request.js +475 -0
  34. package/core/logic-validation/transfer.d.ts +1 -1
  35. package/core/logic-validation/transfer.js +25 -8
  36. package/koni/api/staking/bonding/utils.js +2 -2
  37. package/koni/background/handlers/Extension.d.ts +1 -0
  38. package/koni/background/handlers/Extension.js +33 -8
  39. package/koni/background/handlers/State.d.ts +2 -2
  40. package/koni/background/handlers/State.js +42 -161
  41. package/koni/background/handlers/Tabs.d.ts +0 -1
  42. package/koni/background/handlers/Tabs.js +36 -34
  43. package/package.json +16 -6
  44. package/packageInfo.js +1 -1
  45. package/services/balance-service/helpers/subscribe/substrate/index.js +16 -8
  46. package/services/chain-service/constants.js +6 -1
  47. package/services/chain-service/index.d.ts +9 -0
  48. package/services/chain-service/index.js +32 -2
  49. package/services/chain-service/utils/index.js +2 -2
  50. package/services/earning-service/constants/chains.js +2 -2
  51. package/services/earning-service/handlers/native-staking/relay-chain.js +4 -3
  52. package/services/earning-service/service.js +1 -1
  53. package/services/event-service/index.d.ts +1 -0
  54. package/services/event-service/index.js +1 -0
  55. package/services/event-service/types.d.ts +1 -0
  56. package/services/request-service/handler/EvmRequestHandler.js +2 -1
  57. package/services/transaction-service/index.js +11 -7
  58. 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
- payload.nonce = await evmApi.api.eth.getTransactionCount(address);
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
- // generate hashPayload for EVM transaction
883
- payload.hashPayload = this.generateHashPayload(chain, payload);
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("@subwallet/extension-base/utils");
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
- const address = (0, _helpers.getEip155MessageAddress)(method, request.params);
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, _utils3.getSdkError)('UNSUPPORTED_CHAINS').message + ' ' + address);
63
+ throw new Error((0, _utils2.getSdkError)('UNSUPPORTED_CHAINS').message + ' ' + address);
73
64
  }
74
- const chainState = (0, _classPrivateFieldLooseBase2.default)(this, _koniState)[_koniState].getChainStateByKey(networkKey);
75
- const createRequest = () => {
76
- (0, _classPrivateFieldLooseBase2.default)(this, _koniState)[_koniState].evmSendTransaction((0, _helpers.getWCId)(id), url, networkKey, sessionAccounts, tx).then(async signature => {
77
- await (0, _classPrivateFieldLooseBase2.default)(this, _walletConnectService)[_walletConnectService].responseRequest({
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
- } else {
90
- createRequest();
91
- }
70
+ }).catch(e => {
71
+ (0, _classPrivateFieldLooseBase2.default)(this, _handleError)[_handleError](topic, id, e);
72
+ });
92
73
  } else {
93
- throw Error((0, _utils3.getSdkError)('INVALID_METHOD').message + ' ' + method);
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, _utils3.getSdkError)('USER_REJECTED').message;
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,4 @@
1
+ export * from './swap';
2
+ export * from './request';
3
+ export * from './earning';
4
+ export * from './transfer';
@@ -0,0 +1,7 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export * from "./swap.js";
5
+ export * from "./request.js";
6
+ export * from "./earning.js";
7
+ export * from "./transfer.js";
@@ -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 | undefined, TransactionError | undefined];
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;