@exodus/web3-ethereum-utils 3.38.0 → 4.0.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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2024 Exodus Movement, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -5,4 +5,4 @@ export declare const createSimulateMessage: ({ apiEndpoint, headers, }?: {
5
5
  headers?: {
6
6
  'X-Api-Version': string;
7
7
  } | undefined;
8
- }) => ({ message, origin, asset, address, }: EthSimulateMessageParams) => Promise<MessageSimulationResult>;
8
+ }) => ({ message, url, asset, address, }: EthSimulateMessageParams) => Promise<MessageSimulationResult>;
@@ -1,9 +1,11 @@
1
+ import assert from 'minimalistic-assert';
1
2
  import { getMessageType } from './simulation/getMessageType.js';
2
3
  import { simulateMessage } from './simulation/simulateMessage.js';
3
4
  import { tryParsingSIWE } from './simulation/tryParsingSIWE.js';
4
5
  export const createSimulateMessage = ({ apiEndpoint = 'https://simulation.a.exodus.io/simulateMessage', headers = {
5
6
  'X-Api-Version': '2023-06-05',
6
- }, } = {}) => async ({ message, origin, asset, address, }) => {
7
+ }, } = {}) => async ({ message, url, asset, address, }) => {
8
+ assert(url instanceof URL, "'url' should be an instance of the URL object.");
7
9
  const simulationResult = {
8
10
  baseAssetName: asset.baseAssetName,
9
11
  action: 'NONE',
@@ -15,7 +17,7 @@ export const createSimulateMessage = ({ apiEndpoint = 'https://simulation.a.exod
15
17
  tryParsingSIWE({
16
18
  message,
17
19
  messageType,
18
- origin,
20
+ url,
19
21
  simulationResult,
20
22
  });
21
23
  await simulateMessage({
@@ -24,7 +26,7 @@ export const createSimulateMessage = ({ apiEndpoint = 'https://simulation.a.exod
24
26
  message,
25
27
  messageType,
26
28
  },
27
- origin,
29
+ url,
28
30
  apiEndpoint,
29
31
  headers,
30
32
  simulationResult,
@@ -1,6 +1,6 @@
1
1
  import { createEmptySimulationResult } from '@exodus/web3-utils';
2
2
  import { estimateFee } from './simulation/estimateFee.js';
3
- import { simulateTransactions, } from './simulation/simulateTransactions.js';
3
+ import { simulateTransactions } from './simulation/simulateTransactions.js';
4
4
  import { tryEstimatingChangesLocally } from './simulation/tryEstimatingChangesLocally.js';
5
5
  import { getDisplayDetails, getTxFeeDetails } from './transactions.js';
6
6
  export const createSimulateTransactions = ({ apiEndpoint, headers }) => async ({ transactions, asset, origin, overrideApiEndpoint, }) => {
@@ -37,6 +37,9 @@ export const createSimulateTransactions = ({ apiEndpoint, headers }) => async ({
37
37
  message: 'Balance changes cannot be estimated.',
38
38
  });
39
39
  }
40
+ if (simulationTransactionInternalResult.errorMessage) {
41
+ simulationResult.metadata.humanReadableError = simulationTransactionInternalResult.errorMessage;
42
+ }
40
43
  return simulationResult;
41
44
  }
42
45
  simulationResult.displayDetails = getDisplayDetails(simulationResult.balanceChanges.willApprove);
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
2
3
  import { SignTypedDataVersion } from '@metamask/eth-sig-util';
3
4
  import type { EthTransactionParams } from './types.js';
4
5
  import type { MessageTypes, TypedDataV1, TypedMessage } from '@metamask/eth-sig-util';
package/lib/signatures.js CHANGED
@@ -1,6 +1,7 @@
1
- import Common, { Hardfork } from '@exodus/ethereumjs-common';
2
- import { FeeMarketEIP1559Transaction, Transaction as LegacyTransaction, } from '@exodus/ethereumjs-tx';
1
+ import { Common, Hardfork } from '@exodus/ethereumjs/common';
2
+ import { FeeMarketEIP1559Transaction, Transaction as LegacyTransaction, } from '@exodus/ethereumjs/tx';
3
3
  import { SignTypedDataVersion, personalSign, signTypedData as ethSigUtilSignTypedData, } from '@metamask/eth-sig-util';
4
+ const custom = Common.default?.custom || Common.custom;
4
5
  export function signMessage(message, privateKey) {
5
6
  return personalSign({ privateKey, data: message });
6
7
  }
@@ -12,10 +13,10 @@ export function signTransaction(transactionParams, privateKey) {
12
13
  const isEIP1559Enabled = !!transactionParams.maxFeePerGas;
13
14
  const transaction = isEIP1559Enabled
14
15
  ? FeeMarketEIP1559Transaction.fromTxData(transactionData, {
15
- common: Common.custom({ chainId }, { hardfork: Hardfork.London }),
16
+ common: custom({ chainId }, { hardfork: Hardfork.London }),
16
17
  })
17
18
  : LegacyTransaction.fromTxData(transactionData, {
18
- common: Common.custom({ chainId }),
19
+ common: custom({ chainId }),
19
20
  });
20
21
  const signedTransaction = transaction.sign(privateKey);
21
22
  return signedTransaction.serialize();
@@ -4,4 +4,4 @@ export declare const handleActionResponse: ({ simulationResult, response, }: {
4
4
  simulationResult: MessageSimulationResult;
5
5
  response: ScanMessageEvm200Response;
6
6
  }) => void;
7
- export declare const simulateMessage: ({ address, apiEndpoint, message, origin, headers, simulationResult, }: SimulateMessageParams) => Promise<void>;
7
+ export declare const simulateMessage: ({ address, apiEndpoint, message, url, headers, simulationResult, }: SimulateMessageParams) => Promise<void>;
@@ -1,8 +1,8 @@
1
1
  import { makeSimulationAPICall } from '@exodus/web3-utils';
2
2
  import { BLOWFISH_EVM_CHAINS } from './common.js';
3
- const convertToAPIPayload = ({ origin, address, message, }) => {
3
+ const convertToAPIPayload = ({ address, message, url, }) => {
4
4
  const restParameters = {
5
- metadata: { origin },
5
+ metadata: { origin: url.href },
6
6
  userAccount: address,
7
7
  };
8
8
  if (message.messageType === 1 /* MessageTypeEnum.TypedData */) {
@@ -29,9 +29,9 @@ export const handleActionResponse = ({ simulationResult, response, }) => {
29
29
  simulationResult.action = response.action;
30
30
  }
31
31
  };
32
- export const simulateMessage = async ({ address, apiEndpoint, message, origin, headers, simulationResult, }) => {
32
+ export const simulateMessage = async ({ address, apiEndpoint, message, url, headers, simulationResult, }) => {
33
33
  const { network, chain } = BLOWFISH_EVM_CHAINS[simulationResult.baseAssetName];
34
- const payload = convertToAPIPayload({ address, origin, message });
34
+ const payload = convertToAPIPayload({ address, message, url });
35
35
  const response = await makeSimulationAPICall({
36
36
  url: apiEndpoint,
37
37
  chain,
@@ -1,12 +1,13 @@
1
1
  import type { EthAggregatedTransactionSimulationResult, EthSimulateTransactionParams } from '../types.js';
2
2
  import type { CreateSimulateTransactionsParams, SimulateTransactionsInternalResult } from '@exodus/web3-types';
3
- declare type SimulateTransactionParams = Required<Pick<CreateSimulateTransactionsParams, 'apiEndpoint'>> & Required<Pick<EthSimulateTransactionParams, 'asset' | 'transactions' | 'origin'>> & {
3
+ type SimulateTransactionParams = Required<Pick<CreateSimulateTransactionsParams, 'apiEndpoint'>> & Required<Pick<EthSimulateTransactionParams, 'asset' | 'transactions' | 'origin'>> & {
4
4
  simulationResult: EthAggregatedTransactionSimulationResult;
5
5
  headers?: Record<string, string>;
6
6
  };
7
7
  export declare const enum SimulationErrorMessages {
8
- 'SimulationNotSupported' = 0,
9
- 'APICallFailed' = 1
8
+ 'APICallFailed' = 0,
9
+ 'SimulationFailed' = 1,
10
+ 'SimulationNotSupported' = 2
10
11
  }
11
12
  export declare const simulateTransactions: ({ transactions, apiEndpoint, origin, simulationResult, headers, asset, }: SimulateTransactionParams) => SimulateTransactionsInternalResult<undefined, SimulationErrorMessages>;
12
13
  export {};
@@ -127,7 +127,7 @@ export const simulateTransactions = async ({ transactions, apiEndpoint, origin,
127
127
  if (!BLOWFISH_EVM_CHAINS[asset.name]) {
128
128
  return {
129
129
  kind: 'error',
130
- error: 0 /* SimulationErrorMessages.SimulationNotSupported */,
130
+ error: 2 /* SimulationErrorMessages.SimulationNotSupported */,
131
131
  };
132
132
  }
133
133
  const userAddress = transactions[0].from;
@@ -147,15 +147,20 @@ export const simulateTransactions = async ({ transactions, apiEndpoint, origin,
147
147
  if (!response) {
148
148
  return {
149
149
  kind: 'error',
150
- error: 1 /* SimulationErrorMessages.APICallFailed */,
150
+ error: 0 /* SimulationErrorMessages.APICallFailed */,
151
151
  };
152
152
  }
153
153
  simulationResult.metadata.simulatedLocally = false;
154
154
  const { expectedStateChanges = {}, error } = response.simulationResults.aggregated;
155
155
  if (error) {
156
+ const { humanReadableError } = response.simulationResults.aggregated;
156
157
  // ToDo: accept a logger dep and log the error
157
158
  // ToDo: consider pushing an error to the "warnings" list
158
- return successDefaultResult;
159
+ return {
160
+ kind: 'error',
161
+ error: 1 /* SimulationErrorMessages.SimulationFailed */,
162
+ errorMessage: humanReadableError
163
+ };
159
164
  }
160
165
  const noExpectedStateChangesDetected = Object.keys(expectedStateChanges).length === 0;
161
166
  // This is a self-send transaction, adding a zero "transfer" so that the UI can display it.
@@ -1,8 +1,8 @@
1
1
  import { MessageTypeEnum } from './getMessageType.js';
2
2
  import type { MessageSimulationResult } from '@exodus/web3-types';
3
- export declare const tryParsingSIWE: ({ message, messageType, origin: _origin, simulationResult, }: {
3
+ export declare const tryParsingSIWE: ({ message, messageType, url, simulationResult, }: {
4
4
  message: string;
5
5
  messageType: MessageTypeEnum;
6
- origin: string;
6
+ url: URL;
7
7
  simulationResult: MessageSimulationResult;
8
8
  }) => void;
@@ -1,31 +1,11 @@
1
- const createURL = (origin) => {
2
- try {
3
- return new URL(origin);
4
- }
5
- catch (err) {
6
- try {
7
- // During this attempt we're checking if a scheme was missing in the origin as
8
- // Platforms may or may nor include it.
9
- return new URL(`https://${origin}`);
10
- }
11
- catch (err) {
12
- // ToDo: accept a logger dep and log an error here
13
- return null;
14
- }
15
- }
16
- };
17
- export const tryParsingSIWE = ({ message, messageType, origin: _origin, simulationResult, }) => {
1
+ export const tryParsingSIWE = ({ message, messageType, url, simulationResult, }) => {
18
2
  if (messageType === 1 /* MessageTypeEnum.TypedData */) {
19
3
  return;
20
4
  }
21
- const origin = createURL(_origin);
22
- if (!origin) {
23
- return;
24
- }
25
5
  /*
26
6
  Some dApps don't comply with EIP-4361 and use their custom Sign-In messages. This code block detects such known custom SIWE messages.
27
7
  */
28
- if (origin.hostname === 'rarible.com' &&
8
+ if (url.hostname === 'rarible.com' &&
29
9
  message.includes('I want to login on Rarible')) {
30
10
  simulationResult.kind = {
31
11
  kind: 'SIWE',
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
2
3
  import type { EthTransaction } from './types.js';
3
4
  import type { ApprovalBalanceChange } from '@exodus/web3-types';
4
5
  export declare function getTransactionId(serializedTransaction: Buffer, isEIP1559Transaction?: boolean): string;
@@ -1,4 +1,4 @@
1
- import { FeeMarketEIP1559Transaction, Transaction as LegacyTransaction, } from '@exodus/ethereumjs-tx';
1
+ import { FeeMarketEIP1559Transaction, Transaction as LegacyTransaction, } from '@exodus/ethereumjs/tx';
2
2
  export function getTransactionId(serializedTransaction, isEIP1559Transaction = false) {
3
3
  const Transaction = isEIP1559Transaction
4
4
  ? FeeMarketEIP1559Transaction
package/lib/types.d.ts CHANGED
@@ -25,15 +25,15 @@ export interface EthTransaction {
25
25
  maxPriorityFeePerGas?: string;
26
26
  maxFeePerGas?: string;
27
27
  }
28
- export declare type EthTransactionHash = string;
29
- export declare type EthParentCapability = 'eth_accounts';
28
+ export type EthTransactionHash = string;
29
+ export type EthParentCapability = 'eth_accounts';
30
30
  export interface EthWalletPermission {
31
31
  parentCapability: EthParentCapability;
32
32
  }
33
33
  export interface EthWalletSwitchEthereumChain {
34
34
  chainId: string;
35
35
  }
36
- export declare type EthWalletWatchAssetOptions = {
36
+ export type EthWalletWatchAssetOptions = {
37
37
  address: string;
38
38
  symbol?: string;
39
39
  decimals?: number;
@@ -52,11 +52,11 @@ export interface EthFeeDetails {
52
52
  maxFeePerGas: BN;
53
53
  gasPrice: BN;
54
54
  }
55
- export declare type EthAggregatedTransactionSimulationResult = AggregatedTransactionSimulationResult<EthFeeDetails>;
55
+ export type EthAggregatedTransactionSimulationResult = AggregatedTransactionSimulationResult<EthFeeDetails>;
56
56
  export interface EthSimulateMessageParams {
57
57
  asset: Asset;
58
58
  message: string;
59
- origin: string;
59
+ url: URL;
60
60
  address: string;
61
61
  }
62
62
  export interface SimulateMessageParams {
@@ -65,7 +65,7 @@ export interface SimulateMessageParams {
65
65
  message: string;
66
66
  messageType: MessageTypeEnum.RawMessage | MessageTypeEnum.TypedData;
67
67
  };
68
- origin: EthSimulateMessageParams['origin'];
68
+ url: EthSimulateMessageParams['url'];
69
69
  apiEndpoint: string;
70
70
  headers: Record<string, string>;
71
71
  simulationResult: MessageSimulationResult;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@exodus/web3-ethereum-utils",
3
3
  "description": "Web3 Ethereum utils.",
4
- "version": "3.38.0",
4
+ "version": "4.0.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "module": "lib/index.js",
@@ -18,23 +18,35 @@
18
18
  "lib/**/*.js"
19
19
  ],
20
20
  "publishConfig": {
21
- "access": "restricted"
21
+ "access": "public"
22
22
  },
23
- "repository": "https://github.com/ExodusMovement/exodus-web3/tree/master/libs/ethereum-utils",
24
- "license": "UNLICENSED",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/ExodusMovement/assets.git"
26
+ },
27
+ "license": "MIT",
25
28
  "scripts": {
26
29
  "clean": "run -T rimraf lib",
27
- "build": "yarn clean && run -T tsc"
30
+ "build": "yarn clean && run -T tsc",
31
+ "lint": "run -T eslintc .",
32
+ "lint:fix": "yarn lint --fix",
33
+ "prepublishOnly": "yarn run -T build --scope @exodus/web3-ethereum-utils",
34
+ "test": "run -T exodus-test --jest --esbuild"
28
35
  },
29
36
  "devDependencies": {
30
- "@exodus/web3-types": "1.52.0"
37
+ "@exodus/web3-types": "1.53.0"
31
38
  },
32
39
  "dependencies": {
33
40
  "@exodus/basic-utils": "^3.0.1",
34
- "@exodus/ethereumjs-common": "^2.4.0-exodus.6",
35
- "@exodus/ethereumjs-tx": "^3.3.0-exodus.6",
36
- "@exodus/web3-utils": "^1.48.2",
37
- "@metamask/eth-sig-util": "^4.0.1"
41
+ "@exodus/ethereumjs": "^1.0.0",
42
+ "@exodus/web3-utils": "^1.48.3",
43
+ "@metamask/eth-sig-util": "^4.0.1",
44
+ "minimalistic-assert": "^1.0.1"
45
+ },
46
+ "author": "Exodus Movement, Inc.",
47
+ "bugs": {
48
+ "url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Aweb3-ethereum-utils"
38
49
  },
39
- "gitHead": "212dd8249e074525316708335355fda305aa691f"
50
+ "homepage": "https://github.com/ExodusMovement/assets/tree/master/web3/web3-ethereum-utils",
51
+ "gitHead": "9cc59fb6f6de9bdee27a48a9695763d46d3bc07b"
40
52
  }