@exodus/web3-ethereum 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,153 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to
7
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
+
9
+ ## [Unreleased]
10
+
11
+ ## [2.5.0] - 2023-06-07
12
+
13
+ ### Changed
14
+
15
+ - Use a simplified `getNonce` dependency (doesn't require arguments)
16
+
17
+ ## [2.4.1] - 2023-06-05
18
+
19
+ ### Added
20
+
21
+ - chore(ethereum): build ethereum dependencies based on hydra modules (#502)
22
+
23
+ ### Fixed
24
+
25
+ - fix(ethereum): harden typed data validation (#508)
26
+ - fix(ethereum): untangle balance weirdness (#506)
27
+
28
+ ## [2.4.0] - 2023-05-29
29
+
30
+ ### Fixed
31
+
32
+ - fix(ethereum): TS compilation errors (#498)
33
+ - fix: rename ethereum:provider to eip1193:provider (#499)
34
+
35
+ ## [2.3.0] - 2023-05-18
36
+
37
+ ### Fixed
38
+
39
+ - fix(web3): resolve error on approving token for swap (#485)
40
+ - fix: rename ethereum:provider to eip1193:provider (#499)
41
+
42
+ ## [2.1.1] - 2023-05-11
43
+
44
+ ### Fixed
45
+
46
+ - Validation for signing typed data.
47
+
48
+ ### Changed
49
+
50
+ - Ensure mainnet (`0x1`) is always a first supported chain ID
51
+
52
+ ## [2.0.0] - 2023-05-11
53
+
54
+ ### Changed
55
+
56
+ - Breaking: accept `getAsset` dependency instead of `asset`.
57
+ - Breaking: make RPC validate parsed requests.
58
+
59
+ ## [1.5.1] - 2023-04-06
60
+
61
+ ### Fixed
62
+
63
+ - Convert methods in the provider to properties with arrow functions.
64
+ - Convert chain ID from `getDefaultChainId` to lower case
65
+
66
+ ## [1.5.0] - 2023-04-05
67
+
68
+ ### Changed
69
+
70
+ - Supply simulated changes to the approval function
71
+
72
+ ## [1.4.6] - 2023-03-27
73
+
74
+ ### Fixed
75
+
76
+ - `eth_getLogs` method validation (allow null in an array)
77
+
78
+ ## [1.4.4] - 2023-03-26
79
+
80
+ ### Fixed
81
+
82
+ - Don't change the Approve Transaction title if no token symbol found
83
+ - `eth_getLogs` method validation
84
+
85
+ ## [1.4.2] - 2023-03-22
86
+
87
+ ### Fixed
88
+
89
+ - Returning a possibly mutated object in `validateRequestWithPrefix`
90
+
91
+ ## [1.4.1] - 2023-03-15
92
+
93
+ ### Changed
94
+
95
+ - Properly check if `getDefaultChainId` is undefined in provider constructor
96
+
97
+ ## [1.4.0] - 2023-03-01
98
+
99
+ ### Changed
100
+
101
+ - Unpin `ethereum-api` package version
102
+
103
+ ## [1.3.0] - 2023-02-28
104
+
105
+ ### Changed
106
+
107
+ - Use arrow functions for compatibility with React bundler
108
+
109
+ ## [1.2.0] - 2023-02-27
110
+
111
+ ### Added
112
+
113
+ - Implement RPC functions
114
+
115
+ ## [1.1.0] - 2023-02-22
116
+
117
+ ### Changed
118
+
119
+ - Rework simulate transaction api
120
+ - Package structure
121
+
122
+ ## [1.0.0] - 2023-02-20
123
+
124
+ Initial release.
125
+
126
+ [unreleased]:
127
+ https://github.com/ExodusMovement/exodus-web3/compare/db3e8cfd7d2f3cb908bb675cff1ca7981bbd1b09...master
128
+ [1.0.0]:
129
+ (https://github.com/ExodusMovement/exodus-web3/commit/c220026347ce27cfc25bacc083d61b1aae5c876b)
130
+ [1.1.0]:
131
+ (https://github.com/ExodusMovement/exodus-web3/commit/75254d697e3ffd2d95759e30425c30c7fb7fa654)
132
+ [1.2.0]:
133
+ (https://github.com/ExodusMovement/exodus-web3/commit/39137384d78bfa3e008b92e47e106a7be1df071e)
134
+ [1.3.0]:
135
+ (https://github.com/ExodusMovement/exodus-web3/commit/91de31ee30652f2f8acc66f6e1d909fd27174a36)
136
+ [1.4.0]:
137
+ (https://github.com/ExodusMovement/exodus-web3/commit/bbba5c8aa7d663deec5f649250421777c855341a)
138
+ [1.4.1]:
139
+ (https://github.com/ExodusMovement/exodus-web3/commit/cd3382acdb92fd0dafbb2f2f49b0cc9a648d6e2c)
140
+ [1.4.2]:
141
+ (https://github.com/ExodusMovement/exodus-web3/commit/c414d2c359ecbd25fe1b4d244f6fb51f633a4284)
142
+ [1.4.4]:
143
+ (https://github.com/ExodusMovement/exodus-web3/commit/e48f74f32e040de9e86ef77ea48058d5c0b36c86)
144
+ [1.4.6]:
145
+ (https://github.com/ExodusMovement/exodus-web3/commit/4d9d6eed59fbe201c1e6f2abb4b50f1f336bc690)
146
+ [1.5.0]:
147
+ (https://github.com/ExodusMovement/exodus-web3/commit/4a0c077d0175fe3c6a35e2f9a459f8cad214e8f6)
148
+ [1.5.1]:
149
+ (https://github.com/ExodusMovement/exodus-web3/commit/0576160a36d260f5f63789ddd28c18c9d8885e7b)
150
+ [2.0.0]:
151
+ (https://github.com/ExodusMovement/exodus-web3/commit/54f84cf089d1dffd5dafd443fc2aacb8dd0fc962)
152
+ [2.1.1]:
153
+ (https://github.com/ExodusMovement/exodus-web3/commit/db3e8cfd7d2f3cb908bb675cff1ca7981bbd1b09)
@@ -0,0 +1,3 @@
1
+ import type { createEvmDepsFactoryParams, EVMFactory } from '../types.js';
2
+ declare const createEvmDepsFactory: ({ analytics, activeWalletAccountAtom, assetsModule, blockchainMetadata, feeMonitors, wallet, walletAccounts, }: createEvmDepsFactoryParams) => EVMFactory;
3
+ export default createEvmDepsFactory;
@@ -0,0 +1,113 @@
1
+ import { fetchGasLimit, getNonce as apiGetNonce, getServer, } from '@exodus/ethereum-api';
2
+ import BN from 'bn.js';
3
+ const createEvmDepsFactory = ({ analytics, activeWalletAccountAtom, assetsModule, blockchainMetadata, feeMonitors, wallet, walletAccounts, }) => {
4
+ return (assetName, origin) => {
5
+ const asset = assetsModule.getAsset(assetName);
6
+ const server = getServer(asset);
7
+ const forwardRequest = async ({ method, params }) => {
8
+ if (server.proxyToCoinNode) {
9
+ return server.proxyToCoinNode({ method, params });
10
+ }
11
+ const request = server.buildRequest({ method, params });
12
+ return server.sendRequest(request);
13
+ };
14
+ const sendRawTransaction = async (rawTransaction) => {
15
+ return server.sendRawTransaction(rawTransaction);
16
+ };
17
+ const _getAccountIndexForActiveWalletAccount = async () => {
18
+ const walletAccount = await activeWalletAccountAtom.get();
19
+ const walletAccountData = walletAccounts.get(walletAccount);
20
+ if (!walletAccountData ||
21
+ walletAccountData.isHardware ||
22
+ walletAccountData.is2FA) {
23
+ throw new Error('Invalid walletAccount');
24
+ }
25
+ const accountIndex = walletAccountData.index;
26
+ return accountIndex;
27
+ };
28
+ const getAddress = async () => {
29
+ const accountIndex = await _getAccountIndexForActiveWalletAccount();
30
+ const { publicKey } = await wallet.getPublicKey({
31
+ baseAssetName: assetName,
32
+ accountIndex,
33
+ });
34
+ return '0x' + publicKey.toString('hex');
35
+ };
36
+ const getPrivateKey = async () => {
37
+ const accountIndex = await _getAccountIndexForActiveWalletAccount();
38
+ const { privateKey } = await wallet.getPrivateKey({
39
+ baseAssetName: assetName,
40
+ accountIndex,
41
+ });
42
+ return privateKey;
43
+ };
44
+ const getNonce = async () => {
45
+ const [baseAssetTxLog, blockchainNonce] = await Promise.all([
46
+ blockchainMetadata.getTxLog({
47
+ assetName,
48
+ walletAccount: await activeWalletAccountAtom.get(),
49
+ }),
50
+ apiGetNonce({ asset, address: await getAddress() }),
51
+ ]);
52
+ const walletNonce = Array.from(baseAssetTxLog)
53
+ .filter((tx) => tx.sent && !tx.dropped && tx.data.nonce != null)
54
+ .reduce((nonce, tx) => Math.max(tx.data.nonce + 1, nonce), 0);
55
+ return `0x${Math.max(walletNonce, blockchainNonce).toString(16)}`;
56
+ };
57
+ const getEstimatedGas = async (transaction) => {
58
+ const EXTRA_PERCENTAGE_GAS_LIMIT = 20;
59
+ const { data: txInput, from: fromAddress, to: toAddress, value: amount, } = transaction;
60
+ const gasLimit = await fetchGasLimit({
61
+ asset,
62
+ amount: amount
63
+ ? asset.currency.baseUnit(new BN(amount.slice(2), 'hex'))
64
+ : asset.currency.ZERO,
65
+ fromAddress,
66
+ toAddress,
67
+ txInput,
68
+ extraPercentage: EXTRA_PERCENTAGE_GAS_LIMIT,
69
+ });
70
+ return `0x${gasLimit.toString(16)}`;
71
+ };
72
+ const getFeeData = async () => {
73
+ const { eip1559Enabled, tipGasPrice, gasPrice: _gasPrice, } = await feeMonitors.getFeeData({
74
+ assetName,
75
+ });
76
+ const gasPrice = `0x${_gasPrice.toBaseNumber().toString(16)}`;
77
+ const feeData = {
78
+ gasPrice,
79
+ };
80
+ if (eip1559Enabled) {
81
+ feeData.maxPriorityFeePerGas = `0x${tipGasPrice
82
+ .toBaseNumber()
83
+ .toString(16)}`;
84
+ feeData.maxFeePerGas = gasPrice;
85
+ }
86
+ return feeData;
87
+ };
88
+ const trackWalletWatchAssetUse = async (assetDetails) => {
89
+ // TODO: do we still need this? If yes, this ...assetDetails expansion is no bueno
90
+ // why is this not always returning true in browser?
91
+ analytics.track({
92
+ event: 'DappWalletWatchAsset',
93
+ properties: {
94
+ ...assetDetails,
95
+ dappDomain: origin,
96
+ },
97
+ });
98
+ return true;
99
+ };
100
+ return {
101
+ chainId: 'undefined',
102
+ forwardRequest,
103
+ sendRawTransaction,
104
+ getAddress,
105
+ getPrivateKey,
106
+ getNonce,
107
+ getFeeData,
108
+ getEstimatedGas,
109
+ onEthWalletWatchAssetRequest: trackWalletWatchAssetUse,
110
+ };
111
+ };
112
+ };
113
+ export default createEvmDepsFactory;
@@ -59,7 +59,7 @@ export function exposeHandlers(rpc, deps) {
59
59
  async function prepareTransaction(transaction) {
60
60
  const { gasPrice, maxFeePerGas, maxPriorityFeePerGas } = await getFeeData();
61
61
  const preparedTransaction = { ...transaction };
62
- preparedTransaction.nonce = await getNonce(transaction.from);
62
+ preparedTransaction.nonce = await getNonce();
63
63
  if (!transaction.value) {
64
64
  preparedTransaction.value = '0x0';
65
65
  }
@@ -1,3 +1,4 @@
1
+ export { default as createEvmDepsFactory } from './createEvmDeps.js';
1
2
  import type { EthRequestArguments } from '../types.js';
2
3
  import type { Dependencies } from '../types.js';
3
4
  import type RPC from '@exodus/json-rpc';
@@ -11,4 +12,3 @@ export declare const registerRPCHandlers: ({ deps, RPC, transport, }: {
11
12
  RPC: RpcConstructor;
12
13
  transport: Transport;
13
14
  }) => any;
14
- export {};
@@ -2,6 +2,7 @@ import { RPC_REQUEST_TIMEOUT } from '@exodus/web3-constants';
2
2
  import { validate as validateDeps, validateCommonDeps, } from '@exodus/web3-rpc-handlers';
3
3
  import { exposeHandlers } from './exposeHandlers.js';
4
4
  import { validateRequest } from './validator.js';
5
+ export { default as createEvmDepsFactory } from './createEvmDeps.js';
5
6
  const validateEVMDeps = (evm) => {
6
7
  const requiredKeys = [
7
8
  'chainId',
@@ -20,6 +20,17 @@ export function parseAndValidateTypedData(typedData, { chainId: activeChainId })
20
20
  catch (e) {
21
21
  throw new InvalidInputError();
22
22
  }
23
+ // Security: checking if the 'message' property includes fields that don't belong to the primary type.
24
+ if (!Object.hasOwnProperty.call(parsedTypedData.types, parsedTypedData.primaryType)) {
25
+ throw new InvalidInputError();
26
+ }
27
+ const allowedFieldsSet = new Set(parsedTypedData.types[parsedTypedData.primaryType].map(({ name }) => name));
28
+ for (const field in parsedTypedData.message) {
29
+ if (!allowedFieldsSet.has(field)) {
30
+ throw new InvalidInputError(`field '${field}' is not defined in the primary type definition`);
31
+ }
32
+ }
33
+ // Security: checking if the requested chain matches the active chain ID.
23
34
  if (parsedTypedData?.domain?.chainId) {
24
35
  const suppliedChainIdHex = convertChainIdToHex(`${parsedTypedData.domain.chainId}`);
25
36
  if (activeChainId.toLowerCase() !== suppliedChainIdHex) {
@@ -611,7 +611,7 @@ export function validateRequest(value) {
611
611
  }
612
612
  return true
613
613
  }
614
- const format5 = new RegExp('^(?!_)[\\s\\w!?.,/()[\\]]+$', '')
614
+ const format5 = new RegExp('^(?![\\s_])[\\s\\w!?.,/()[\\]]+$', '')
615
615
  const ref9 = function validate(data) {
616
616
  validate.errors = null
617
617
  if (!Array.isArray(data)) {
@@ -2348,7 +2348,7 @@ export function parseAndValidateTypedData(value) {
2348
2348
  /[\uD800-\uDFFF]/.test(string) ? [...string].length : string.length
2349
2349
  const pointerPart = (s) =>
2350
2350
  /~\//.test(s) ? `${s}`.replace(/~/g, '~0').replace(/\//g, '~1') : s
2351
- const format0 = new RegExp('^(?!_)[\\s\\w!?.,/()[\\]]+$', '')
2351
+ const format0 = new RegExp('^(?![\\s_])[\\s\\w!?.,/()[\\]]+$', '')
2352
2352
  const ref2 = function validate(data) {
2353
2353
  validate.errors = null
2354
2354
  if (!(typeof data === 'object' && data && !Array.isArray(data))) {
@@ -1,6 +1,6 @@
1
1
  import { retrieveSideEffects } from '@exodus/ethereum-api';
2
2
  import { SIMULATION_SUPPORTED_ASSET_NAMES } from './constant.js';
3
- import { createCurrency, formatAccounts, getEthereumDisplayInfo, hexToBN, isEthTransferTx, } from './utils.js';
3
+ import { formatAccounts, getEthereumDisplayInfo, hexToBN, isEthTransferTx, } from './utils.js';
4
4
  const computeBalanceChanges = async (asset, shouldSimulate, transaction) => {
5
5
  let balanceChanges = {
6
6
  willReceive: [],
@@ -10,11 +10,7 @@ const computeBalanceChanges = async (asset, shouldSimulate, transaction) => {
10
10
  if (isEthTransferTx(transaction)) {
11
11
  const txValue = hexToBN(transaction.value).toString();
12
12
  balanceChanges.willSend.push({
13
- balance: createCurrency({
14
- amount: txValue,
15
- denominator: asset.currency.defaultUnit.power,
16
- symbol: asset.displayTicker,
17
- }),
13
+ balance: asset.currency.baseUnit(txValue),
18
14
  });
19
15
  }
20
16
  else {
package/lib/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import type { EthTransaction, EthTransactionHash, EthWalletWatchAsset } from '@exodus/web3-ethereum-utils';
3
3
  import type { CommonDeps } from '@exodus/web3-rpc-handlers';
4
+ import type { IAnalyticsModule, IActiveWalletAccountAtom, IAssetsModule, IBlockchainMetadataModule, IFeeDataModule, IWalletModule, IWalletAccountsModule } from '@exodus/web3-types';
4
5
  /**
5
6
  * EVM-compatible chains.
6
7
  */
@@ -8,11 +9,21 @@ export interface EthRequestArguments {
8
9
  method: string;
9
10
  params?: unknown[] | Record<string, unknown>;
10
11
  }
11
- interface FeeData {
12
+ export interface FeeData {
12
13
  gasPrice: string;
13
14
  maxFeePerGas?: string;
14
15
  maxPriorityFeePerGas?: string;
15
16
  }
17
+ export interface createEvmDepsFactoryParams {
18
+ activeWalletAccountAtom: IActiveWalletAccountAtom;
19
+ analytics: IAnalyticsModule;
20
+ assetsModule: IAssetsModule;
21
+ blockchainMetadata: IBlockchainMetadataModule;
22
+ feeMonitors: IFeeDataModule;
23
+ wallet: IWalletModule;
24
+ walletAccounts: IWalletAccountsModule;
25
+ }
26
+ export declare type EVMFactory = (assetName: string, origin: string) => EVMDeps;
16
27
  export declare type EVMDeps = {
17
28
  chainId: string;
18
29
  getAddress: () => Promise<string>;
@@ -20,11 +31,10 @@ export declare type EVMDeps = {
20
31
  sendRawTransaction: (rawTransaction: string) => Promise<EthTransactionHash>;
21
32
  getEstimatedGas: (transaction: EthTransaction) => Promise<string>;
22
33
  getFeeData: () => Promise<FeeData>;
23
- getNonce: (account: string) => Promise<string>;
34
+ getNonce: () => Promise<string>;
24
35
  forwardRequest: (args: EthRequestArguments) => Promise<unknown>;
25
36
  onEthWalletWatchAssetRequest?: (assetDetails: EthWalletWatchAsset) => Promise<boolean>;
26
37
  };
27
38
  export declare type Dependencies = {
28
39
  evms: EVMDeps[];
29
40
  } & CommonDeps;
30
- export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@exodus/web3-ethereum",
3
3
  "description": "Apps connectivity library for EVM-compatible chains.",
4
- "version": "2.4.0",
4
+ "version": "2.5.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "module": "lib/index.js",
@@ -33,22 +33,22 @@
33
33
  "dependencies": {
34
34
  "@exodus/currency": "^2.1.2",
35
35
  "@exodus/ethereum-api": "^6.0.0",
36
- "@exodus/web3-constants": "^1.18.0",
36
+ "@exodus/web3-constants": "^1.19.0",
37
37
  "@exodus/web3-ethereum-utils": "^1.8.0",
38
- "@exodus/web3-provider": "^2.16.0",
39
- "@exodus/web3-rpc-handlers": "^0.13.0",
38
+ "@exodus/web3-provider": "^2.17.0",
39
+ "@exodus/web3-rpc-handlers": "^0.14.0",
40
+ "bn.js": "^5.2.0",
40
41
  "eth-rpc-errors": "^4.0.3"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@exodus/assets": "^8.0.72",
44
45
  "@exodus/json-rpc": "^1.11.0",
45
46
  "@exodus/schemasafe": "^1.0.0",
46
- "@exodus/web3-types": "^1.14.0",
47
+ "@exodus/web3-types": "^1.15.0",
47
48
  "@exodus/web3-validation": "^1.33.0",
48
49
  "@wallet-standard/base": "^1.0.1"
49
50
  },
50
51
  "peerDependencies": {
51
52
  "@exodus/assets": "^8.0.72"
52
- },
53
- "gitHead": "3bfe3ffd37584b844b60cef81a2d951cb867438e"
53
+ }
54
54
  }