@exodus/web3-ethereum 0.1.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/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @exodus/web3-ethereum
2
+
3
+ Apps connectivity library for Ethereum and EVM-compatible chains.
4
+
5
+ ## Usage
6
+
7
+ ```js
8
+ const EventEmitter = require('events')
9
+
10
+ // Separate entry points are supported
11
+ const { EthereumProvider } = require('@exodus/web3-ethereum/provider')
12
+ const { registerRPCHandlers } = require('@exodus/web3-ethereum/rpc')
13
+
14
+ // Create transport.
15
+ const transport = new EventEmitter()
16
+ transport.write = (data) => {
17
+ setTimeout(() => {
18
+ transport.emit('data', data)
19
+ })
20
+ }
21
+
22
+ // Create Exodus global API.
23
+ const accountsObservable = new Observable()
24
+ const storage = new Storage()
25
+ const supportedChainIDs = ['0x1']
26
+ const exodus = {
27
+ ethereum: new EthereumProvider({
28
+ accountsObservable,
29
+ storage,
30
+ supportedChainIDs,
31
+ transport,
32
+ }),
33
+ }
34
+
35
+ // Inject the Exodus object into the app.
36
+ window.exodus = exodus
37
+
38
+ // Register RPC handlers for requests the Provider can call.
39
+ registerRPCHandlers({
40
+ transport,
41
+ deps: {}, // required deps
42
+ })
43
+ ```
package/lib/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './simulation/index.js';
package/lib/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './simulation/index.js';
@@ -0,0 +1,5 @@
1
+ import type { EVMConstants } from './types.js';
2
+ export declare const CHAIN_IDS: {
3
+ [key: string]: number;
4
+ };
5
+ export declare const ENABLED_EVMS: EVMConstants[];
@@ -0,0 +1,32 @@
1
+ export const CHAIN_IDS = {
2
+ avalanchec: 43114,
3
+ bsc: 56,
4
+ ethereum: 1,
5
+ ethereumclassic: 61,
6
+ ethereumgoerli: 5,
7
+ fantommainnet: 250,
8
+ harmonymainnet: 1666600000,
9
+ matic: 137,
10
+ };
11
+ export const ENABLED_EVMS = [
12
+ {
13
+ assetName: 'ethereum',
14
+ shouldSimulate: true,
15
+ },
16
+ {
17
+ assetName: 'matic',
18
+ shouldSimulate: false,
19
+ },
20
+ {
21
+ assetName: 'bsc',
22
+ shouldSimulate: false,
23
+ },
24
+ {
25
+ assetName: 'avalanchec',
26
+ shouldSimulate: false,
27
+ },
28
+ {
29
+ assetName: 'fantommainnet',
30
+ shouldSimulate: false,
31
+ },
32
+ ];
@@ -0,0 +1,16 @@
1
+ import type { EthTransaction } from '@exodus/web3-ethereum-utils';
2
+ import type { Asset, EthBalanceChanges } from './types.js';
3
+ export declare const simulateTransaction: (assets: Record<string, Asset>, transaction: EthTransaction, network: string) => Promise<{
4
+ assetName: string;
5
+ advancedDetails: never[];
6
+ balanceChanges: EthBalanceChanges;
7
+ displayInfo: {
8
+ title: string;
9
+ };
10
+ txFee: unknown;
11
+ txFeeDetails: {
12
+ gasLimit: number;
13
+ maxFeePerGas: number | undefined;
14
+ gasPrice: number;
15
+ };
16
+ }>;
@@ -0,0 +1,70 @@
1
+ import { retrieveSideEffects } from '@exodus/ethereum-api';
2
+ import { createCurrency, formatAccounts, getEthereumDisplayInfo, supportedNetworkEvms, hexToBN, isEthTransferTx, } from './utils.js';
3
+ const computeBalanceChanges = async (asset, shouldSimulate, transaction) => {
4
+ const assetName = asset.name;
5
+ let balanceChanges = {
6
+ willReceive: [],
7
+ willSend: [],
8
+ willApprove: [],
9
+ };
10
+ if (isEthTransferTx(transaction)) {
11
+ const txValue = hexToBN(transaction.value).toString();
12
+ balanceChanges.willSend.push({
13
+ balance: createCurrency({
14
+ amount: txValue,
15
+ denominator: asset.currency.defaultUnit.power,
16
+ symbol: asset.displayTicker,
17
+ }),
18
+ });
19
+ }
20
+ else {
21
+ try {
22
+ const sideEffect = await retrieveSideEffects({
23
+ assetName,
24
+ shouldSimulate,
25
+ transaction,
26
+ });
27
+ if (sideEffect) {
28
+ balanceChanges = formatAccounts(sideEffect);
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.error('Ethereum transaction simulation failed.', error);
33
+ }
34
+ }
35
+ return balanceChanges;
36
+ };
37
+ const getTxFeeDetails = (asset, transaction) => {
38
+ const maxFeePerGasBn = transaction.maxFeePerGas
39
+ ? hexToBN(transaction.maxFeePerGas)
40
+ : undefined;
41
+ const gasPriceBn = hexToBN(transaction.gasPrice);
42
+ const gasBn = hexToBN(transaction.gas);
43
+ return {
44
+ txFee: asset.currency.baseUnit(gasBn.mul(maxFeePerGasBn || gasPriceBn).toString()),
45
+ txFeeDetails: {
46
+ gasLimit: gasBn.toNumber(),
47
+ maxFeePerGas: maxFeePerGasBn?.toNumber(),
48
+ gasPrice: gasPriceBn.toNumber(),
49
+ },
50
+ };
51
+ };
52
+ export const simulateTransaction = async (assets, transaction, network) => {
53
+ const evm = supportedNetworkEvms.get(network);
54
+ if (!evm) {
55
+ throw new Error(`unsupported network, ${network}`);
56
+ }
57
+ const { assetName, shouldSimulate } = evm;
58
+ const asset = assets[assetName];
59
+ const balanceChanges = await computeBalanceChanges(asset, shouldSimulate, transaction);
60
+ const { txFee, txFeeDetails } = getTxFeeDetails(asset, transaction);
61
+ const displayInfo = getEthereumDisplayInfo(balanceChanges);
62
+ return {
63
+ assetName,
64
+ advancedDetails: [],
65
+ balanceChanges,
66
+ displayInfo,
67
+ txFee,
68
+ txFeeDetails,
69
+ };
70
+ };
@@ -0,0 +1,36 @@
1
+ export interface EVMConstants {
2
+ assetName: string;
3
+ shouldSimulate: boolean;
4
+ }
5
+ export interface CurrencyParams {
6
+ amount: string;
7
+ symbol: string;
8
+ denominator: number;
9
+ }
10
+ export interface Asset {
11
+ name: string;
12
+ displayTicker: string;
13
+ currency: {
14
+ defaultUnit: {
15
+ power: number;
16
+ };
17
+ baseUnit: (args: unknown) => unknown;
18
+ };
19
+ }
20
+ export interface EthBalanceChanges {
21
+ willReceive: Array<EthBalanceChange>;
22
+ willSend: Array<EthBalanceChange>;
23
+ willApprove: Array<EthBalanceChange>;
24
+ }
25
+ export interface EthBalanceChange {
26
+ unitName?: string;
27
+ balance: EthNumberUnit;
28
+ }
29
+ export interface EthNumberUnit {
30
+ unitName: string;
31
+ }
32
+ export interface EthAccount {
33
+ balance: number;
34
+ symbol: string;
35
+ decimal: number;
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import BN from 'bn.js';
2
+ import type { CurrencyParams, EthBalanceChange, EthBalanceChanges } from './types.js';
3
+ import type { EthTransaction } from '@exodus/web3-ethereum-utils';
4
+ export declare const hexToBN: (hexValue?: string) => BN;
5
+ export declare const supportedNetworkEvms: Map<string, {
6
+ chainId: string;
7
+ network: string;
8
+ assetName: string;
9
+ shouldSimulate: boolean;
10
+ }>;
11
+ export declare const isEthTransferTx: (transaction: EthTransaction) => boolean;
12
+ export declare function getEthereumDisplayInfo(balanceChanges: EthBalanceChanges): {
13
+ title: string;
14
+ };
15
+ export declare const createCurrency: ({ amount, symbol, denominator, }: CurrencyParams) => any;
16
+ export declare const formatAccounts: ({ willSend, willReceive, willApprove, }: {
17
+ willSend?: never[] | undefined;
18
+ willReceive?: never[] | undefined;
19
+ willApprove?: never[] | undefined;
20
+ }) => {
21
+ willSend: EthBalanceChange[];
22
+ willReceive: EthBalanceChange[];
23
+ willApprove: never[];
24
+ };
@@ -0,0 +1,44 @@
1
+ import { UnitType } from '@exodus/currency';
2
+ import BN from 'bn.js';
3
+ import { CHAIN_IDS, ENABLED_EVMS } from './constant.js';
4
+ export const hexToBN = (hexValue) => new BN((hexValue || '').slice(2), 'hex');
5
+ const getEvmNetwork = (chainId) => `evm:${chainId}`;
6
+ export const supportedNetworkEvms = new Map(ENABLED_EVMS.map((constant) => {
7
+ const chainId = '0x' + CHAIN_IDS[constant.assetName].toString(16);
8
+ const network = getEvmNetwork(chainId);
9
+ return [network, { ...constant, chainId, network }];
10
+ }));
11
+ export const isEthTransferTx = (transaction) => {
12
+ return (['0x', null, undefined].includes(transaction.data) &&
13
+ [undefined, '0x5208'].includes(transaction.gas));
14
+ };
15
+ export function getEthereumDisplayInfo(balanceChanges) {
16
+ let title = 'Approve Transaction?';
17
+ const isApproveTransaction = balanceChanges.willApprove.length;
18
+ if (isApproveTransaction) {
19
+ const tokenName = balanceChanges.willApprove[0].unitName;
20
+ title = `Approve ${tokenName} Transactions?`;
21
+ }
22
+ return { title };
23
+ }
24
+ export const createCurrency = ({ amount, symbol, denominator, }) => UnitType.create({
25
+ base: 0,
26
+ [symbol]: denominator,
27
+ }).base(amount);
28
+ const convertToNumberUnit = (account) => ({
29
+ ...account,
30
+ balance: createCurrency({
31
+ amount: new BN(account.balance).abs().toString(),
32
+ symbol: account.symbol,
33
+ denominator: account.decimal,
34
+ }),
35
+ });
36
+ export const formatAccounts = ({ willSend = [], willReceive = [], willApprove = [], }) => {
37
+ const newWillSend = willSend.map(convertToNumberUnit);
38
+ const newWillReceive = willReceive.map(convertToNumberUnit);
39
+ return {
40
+ willSend: newWillSend,
41
+ willReceive: newWillReceive,
42
+ willApprove,
43
+ };
44
+ };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@exodus/web3-ethereum",
3
+ "description": "Apps connectivity library for EVM-compatible chains.",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "module": "lib/index.js",
8
+ "types": "lib/index.d.ts",
9
+ "exports": {
10
+ ".": "./lib/index.js",
11
+ "./package.json": "./package.json",
12
+ "./provider": "./lib/provider/index.js",
13
+ "./rpc": "./lib/rpc-handlers/index.js",
14
+ "./utils": "./lib/rpc-handlers/index.js"
15
+ },
16
+ "react-native": "./lib/index.js",
17
+ "files": [
18
+ "lib/**/*.d.ts",
19
+ "lib/**/*.mjs",
20
+ "lib/**/*.js"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "restricted"
24
+ },
25
+ "repository": "https://github.com/ExodusMovement/exodus-web3/tree/master/packages/ethereum",
26
+ "license": "UNLICENSED",
27
+ "scripts": {
28
+ "clean": "rimraf lib",
29
+ "build": "yarn clean && tsc"
30
+ },
31
+ "dependencies": {
32
+ "@exodus/currency": "^2.1.2",
33
+ "@exodus/ethereum-api": "3.2.4",
34
+ "@exodus/web3-ethereum-utils": "1.7.0"
35
+ },
36
+ "devDependencies": {
37
+ "@exodus/assets": "^8.0.72",
38
+ "@exodus/schemasafe": "^1.0.0-rc.7",
39
+ "@exodus/web3-types": "^1.6.0"
40
+ },
41
+ "peerDependencies": {
42
+ "@exodus/assets": "^8.0.72"
43
+ },
44
+ "gitHead": "9c988db57f3b4a18feb2038480e3466b93f2d06e"
45
+ }