@exodus/web3-ethereum 3.2.1 → 5.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/lib/provider/provider.d.ts +1 -1
- package/lib/provider/provider.js +2 -9
- package/lib/provider/types.d.ts +2 -3
- package/lib/rpc-handlers/createEvmDeps.js +2 -0
- package/lib/rpc-handlers/exposeHandlers.js +12 -14
- package/lib/rpc-handlers/index.js +1 -0
- package/lib/rpc-handlers/validator.js +1 -46
- package/lib/simulation/simulation.d.ts +4 -5
- package/lib/simulation/simulation.js +10 -33
- package/lib/types.d.ts +2 -2
- package/package.json +7 -7
|
@@ -9,7 +9,7 @@ interface EthereumProviderEvents {
|
|
|
9
9
|
}
|
|
10
10
|
export declare class EthereumProvider extends BaseProvider<EthereumProviderEvents> {
|
|
11
11
|
#private;
|
|
12
|
-
constructor({ accountsObservable, storage, supportedChainIds, transport, getDefaultChainId,
|
|
12
|
+
constructor({ accountsObservable, storage, supportedChainIds, transport, getDefaultChainId, }: Deps);
|
|
13
13
|
protected _callRpcMethod<Params, Response>(method: string, params: Params): Promise<Response>;
|
|
14
14
|
isConnected(): boolean;
|
|
15
15
|
request: (args: RequestArguments) => Promise<unknown>;
|
package/lib/provider/provider.js
CHANGED
|
@@ -5,20 +5,18 @@ export class EthereumProvider extends BaseProvider {
|
|
|
5
5
|
#storage;
|
|
6
6
|
#supportedChainIds = [];
|
|
7
7
|
#getDefaultChainId;
|
|
8
|
-
#walletProviderManager;
|
|
9
8
|
#initializePromise = null;
|
|
10
9
|
#initialized = false;
|
|
11
10
|
#isConnected = false;
|
|
12
11
|
#chainId = null;
|
|
13
12
|
#accounts = [];
|
|
14
13
|
#selectedAddress = null;
|
|
15
|
-
constructor({ accountsObservable, storage, supportedChainIds, transport, getDefaultChainId,
|
|
14
|
+
constructor({ accountsObservable, storage, supportedChainIds, transport, getDefaultChainId, }) {
|
|
16
15
|
if (!supportedChainIds?.length) {
|
|
17
16
|
throw new Error('At least one supported chain must be provided');
|
|
18
17
|
}
|
|
19
18
|
super({ transport });
|
|
20
19
|
this.#storage = createStorageWrapper(storage);
|
|
21
|
-
this.#walletProviderManager = walletProviderManager;
|
|
22
20
|
this.#supportedChainIds = supportedChainIds
|
|
23
21
|
.map((chainId) => chainId.toLowerCase())
|
|
24
22
|
.sort();
|
|
@@ -107,12 +105,7 @@ export class EthereumProvider extends BaseProvider {
|
|
|
107
105
|
};
|
|
108
106
|
#requestAccounts = async () => {
|
|
109
107
|
const permissions = { eth_accounts: {} };
|
|
110
|
-
|
|
111
|
-
this.#walletProviderManager.getWalletProviders().forEach(({ name }) => {
|
|
112
|
-
availableWallets.push(name);
|
|
113
|
-
});
|
|
114
|
-
const { selectedWallet } = await this._callRpcMethod('wallet_requestPermissions', [permissions, availableWallets]);
|
|
115
|
-
this.#walletProviderManager.setDefaultWalletProvider(selectedWallet);
|
|
108
|
+
await this._callRpcMethod('wallet_requestPermissions', [permissions]);
|
|
116
109
|
const accounts = await this._callRpcMethod('eth_accounts', []);
|
|
117
110
|
this.#handleAccountsChanged(accounts);
|
|
118
111
|
if (!(await this.#storage.getChainId())) {
|
package/lib/provider/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Deps as BaseProviderDeps } from '@exodus/web3-provider';
|
|
2
|
-
import type { Observable, Storage
|
|
2
|
+
import type { Observable, Storage } from '@exodus/web3-types';
|
|
3
3
|
export declare type ChainId = string;
|
|
4
4
|
export interface ProviderConnectInfo {
|
|
5
5
|
chainId: ChainId;
|
|
@@ -35,11 +35,10 @@ export declare type Deps = BaseProviderDeps & {
|
|
|
35
35
|
storage: Storage;
|
|
36
36
|
supportedChainIds: string[];
|
|
37
37
|
getDefaultChainId?: () => Promise<string | null>;
|
|
38
|
-
walletProviderManager: WalletProviderManager;
|
|
39
38
|
};
|
|
40
39
|
export interface ProviderStorage {
|
|
41
40
|
getChainId: () => Promise<ChainId | null>;
|
|
42
41
|
setChainId: (chainId: ChainId) => Promise<void>;
|
|
43
42
|
clearChainId: () => Promise<void>;
|
|
44
43
|
}
|
|
45
|
-
export {
|
|
44
|
+
export {};
|
|
@@ -77,6 +77,7 @@ const createEvmDepsFactory = ({ analytics, blockchainMetadata, }) => {
|
|
|
77
77
|
});
|
|
78
78
|
return true;
|
|
79
79
|
};
|
|
80
|
+
const getOrigin = () => origin;
|
|
80
81
|
return {
|
|
81
82
|
chainId: 'undefined',
|
|
82
83
|
forwardRequest,
|
|
@@ -87,6 +88,7 @@ const createEvmDepsFactory = ({ analytics, blockchainMetadata, }) => {
|
|
|
87
88
|
getFeeData,
|
|
88
89
|
getEstimatedGas,
|
|
89
90
|
onEthWalletWatchAssetRequest: trackWalletWatchAssetUse,
|
|
91
|
+
getOrigin,
|
|
90
92
|
};
|
|
91
93
|
};
|
|
92
94
|
};
|
|
@@ -62,7 +62,7 @@ const isValidGasLimitValue = (value) => {
|
|
|
62
62
|
return proposedGasLimit.lte(maximumBlockGasLimit);
|
|
63
63
|
};
|
|
64
64
|
export function exposeHandlers(rpc, deps) {
|
|
65
|
-
const { chainId, isTrusted, isAutoApproved, ensureTrusted, approveConnection, approveMessage, approveTransactions, forwardRequest, getAddress, getPrivateKey, getEstimatedGas, getFeeData, getNonce, sendRawTransaction, onTransactionsSigned = () => { }, onEthWalletWatchAssetRequest = () => { }, isUnlocked = () => true, ensureUnlocked = () => true, getAsset, } = deps;
|
|
65
|
+
const { chainId, isTrusted, isAutoApproved, ensureTrusted, approveConnection, approveMessage, approveTransactions, forwardRequest, getAddress, getPrivateKey, getEstimatedGas, getFeeData, getNonce, sendRawTransaction, onTransactionsSigned = () => { }, onEthWalletWatchAssetRequest = () => { }, isUnlocked = () => true, ensureUnlocked = () => true, getAsset, getOrigin, } = deps;
|
|
66
66
|
const network = `evm:${chainId}`;
|
|
67
67
|
async function assertTrusted() {
|
|
68
68
|
const trusted = await isTrusted();
|
|
@@ -123,7 +123,12 @@ export function exposeHandlers(rpc, deps) {
|
|
|
123
123
|
const asset = await getAsset(network);
|
|
124
124
|
const preparedTransaction = await prepareTransaction(transaction);
|
|
125
125
|
validateTransaction(preparedTransaction);
|
|
126
|
-
const
|
|
126
|
+
const origin = getOrigin();
|
|
127
|
+
const simulatedChanges = await simulateTransaction({
|
|
128
|
+
asset,
|
|
129
|
+
transaction: preparedTransaction,
|
|
130
|
+
origin,
|
|
131
|
+
});
|
|
127
132
|
await approve(approveTransactions, network, simulatedChanges);
|
|
128
133
|
const privateKey = await getPrivateKey();
|
|
129
134
|
const signedTransaction = signTransaction({ ...preparedTransaction, chainId }, privateKey);
|
|
@@ -200,9 +205,8 @@ export function exposeHandlers(rpc, deps) {
|
|
|
200
205
|
}
|
|
201
206
|
return permissions;
|
|
202
207
|
});
|
|
203
|
-
exposeEvmFunction('wallet_requestPermissions', async (requestedPermissions
|
|
208
|
+
exposeEvmFunction('wallet_requestPermissions', async (requestedPermissions) => {
|
|
204
209
|
const parentCapability = Object.keys(requestedPermissions)[0];
|
|
205
|
-
let selectedWallet = null;
|
|
206
210
|
if (parentCapability !== ETH_ACCOUNTS_PERMISSION) {
|
|
207
211
|
// `eth_accounts` is currently the only permission.
|
|
208
212
|
// See: https://docs.metamask.io/guide/rpc-api.html#restricted-methods.
|
|
@@ -214,19 +218,13 @@ export function exposeHandlers(rpc, deps) {
|
|
|
214
218
|
}
|
|
215
219
|
const trusted = await isTrusted();
|
|
216
220
|
if (!trusted) {
|
|
217
|
-
const
|
|
218
|
-
if (!
|
|
221
|
+
const approved = await approveConnection(network);
|
|
222
|
+
if (!approved) {
|
|
219
223
|
throw new UserRejectedRequestError();
|
|
220
224
|
}
|
|
221
|
-
|
|
222
|
-
if (response.selectedWallet === 'exodus') {
|
|
223
|
-
await ensureTrusted(network);
|
|
224
|
-
}
|
|
225
|
+
await ensureTrusted(network);
|
|
225
226
|
}
|
|
226
|
-
return {
|
|
227
|
-
walletPermissions: [{ parentCapability: ETH_ACCOUNTS_PERMISSION }],
|
|
228
|
-
selectedWallet,
|
|
229
|
-
};
|
|
227
|
+
return [{ parentCapability: ETH_ACCOUNTS_PERMISSION }];
|
|
230
228
|
});
|
|
231
229
|
exposeEvmFunction('wallet_watchAsset', async (assetDetails) => {
|
|
232
230
|
await assertTrusted();
|
|
@@ -913,12 +913,6 @@ export function validateRequest(value) {
|
|
|
913
913
|
validate.errors = [{ keywordLocation: '#/type', instanceLocation: '#' }]
|
|
914
914
|
return false
|
|
915
915
|
}
|
|
916
|
-
if (data.length > 2) {
|
|
917
|
-
validate.errors = [
|
|
918
|
-
{ keywordLocation: '#/maxItems', instanceLocation: '#' },
|
|
919
|
-
]
|
|
920
|
-
return false
|
|
921
|
-
}
|
|
922
916
|
if (data.length < 1) {
|
|
923
917
|
validate.errors = [
|
|
924
918
|
{ keywordLocation: '#/minItems', instanceLocation: '#' },
|
|
@@ -935,46 +929,7 @@ export function validateRequest(value) {
|
|
|
935
929
|
return false
|
|
936
930
|
}
|
|
937
931
|
}
|
|
938
|
-
if (
|
|
939
|
-
if (!Array.isArray(data[1])) {
|
|
940
|
-
validate.errors = [
|
|
941
|
-
{ keywordLocation: '#/1/type', instanceLocation: '#/1' },
|
|
942
|
-
]
|
|
943
|
-
return false
|
|
944
|
-
}
|
|
945
|
-
for (let l = 0; l < data[1].length; l++) {
|
|
946
|
-
if (l in data[1] && hasOwn(data[1], l)) {
|
|
947
|
-
if (!(typeof data[1][l] === 'string')) {
|
|
948
|
-
validate.errors = [
|
|
949
|
-
{
|
|
950
|
-
keywordLocation: '#/1/items/type',
|
|
951
|
-
instanceLocation: '#/1/' + l,
|
|
952
|
-
},
|
|
953
|
-
]
|
|
954
|
-
return false
|
|
955
|
-
}
|
|
956
|
-
if (data[1][l].length > 20 && stringLength(data[1][l]) > 20) {
|
|
957
|
-
validate.errors = [
|
|
958
|
-
{
|
|
959
|
-
keywordLocation: '#/1/items/maxLength',
|
|
960
|
-
instanceLocation: '#/1/' + l,
|
|
961
|
-
},
|
|
962
|
-
]
|
|
963
|
-
return false
|
|
964
|
-
}
|
|
965
|
-
if (!format3.test(data[1][l])) {
|
|
966
|
-
validate.errors = [
|
|
967
|
-
{
|
|
968
|
-
keywordLocation: '#/1/items/format',
|
|
969
|
-
instanceLocation: '#/1/' + l,
|
|
970
|
-
},
|
|
971
|
-
]
|
|
972
|
-
return false
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
if (data.length > 2) {
|
|
932
|
+
if (data.length > 1) {
|
|
978
933
|
validate.errors = [
|
|
979
934
|
{ keywordLocation: '#/items', instanceLocation: '#' },
|
|
980
935
|
]
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
export declare const simulateTransaction: (asset: Asset, transaction: EthTransaction) => Promise<{
|
|
1
|
+
import type { EthSimulateTransactionParams } from '@exodus/web3-ethereum-utils';
|
|
2
|
+
import type { NumberUnit } from '@exodus/web3-types';
|
|
3
|
+
export declare const simulateTransaction: ({ asset, transaction, origin, }: EthSimulateTransactionParams) => Promise<{
|
|
5
4
|
baseAssetName: string;
|
|
6
5
|
advancedDetails: never[];
|
|
7
|
-
balanceChanges:
|
|
6
|
+
balanceChanges: import("@exodus/web3-types").BalanceChanges;
|
|
8
7
|
displayInfo: {
|
|
9
8
|
title: string;
|
|
10
9
|
};
|
|
@@ -1,35 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createSimulateTransaction } from '@exodus/web3-ethereum-utils';
|
|
2
2
|
import { SIMULATION_SUPPORTED_ASSET_NAMES } from './constant.js';
|
|
3
|
-
import {
|
|
4
|
-
const
|
|
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: asset.currency.baseUnit(txValue),
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
try {
|
|
18
|
-
const sideEffect = await retrieveSideEffects({
|
|
19
|
-
asset,
|
|
20
|
-
shouldSimulate,
|
|
21
|
-
transaction,
|
|
22
|
-
});
|
|
23
|
-
if (sideEffect) {
|
|
24
|
-
balanceChanges = formatAccounts(sideEffect);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
console.error('Ethereum transaction simulation failed.', error);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return balanceChanges;
|
|
32
|
-
};
|
|
3
|
+
import { getEthereumDisplayInfo, hexToBN } from './utils.js';
|
|
4
|
+
const simulateTransactionV2 = createSimulateTransaction();
|
|
33
5
|
const getTxFeeDetails = (asset, transaction) => {
|
|
34
6
|
const maxFeePerGasBn = transaction.maxFeePerGas
|
|
35
7
|
? hexToBN(transaction.maxFeePerGas)
|
|
@@ -45,10 +17,15 @@ const getTxFeeDetails = (asset, transaction) => {
|
|
|
45
17
|
},
|
|
46
18
|
};
|
|
47
19
|
};
|
|
48
|
-
export const simulateTransaction = async (asset, transaction) => {
|
|
20
|
+
export const simulateTransaction = async ({ asset, transaction, origin, }) => {
|
|
49
21
|
const baseAssetName = asset.name;
|
|
50
22
|
const shouldSimulate = SIMULATION_SUPPORTED_ASSET_NAMES.includes(baseAssetName);
|
|
51
|
-
const balanceChanges = await
|
|
23
|
+
const { balanceChanges } = await simulateTransactionV2({
|
|
24
|
+
transaction,
|
|
25
|
+
asset,
|
|
26
|
+
origin,
|
|
27
|
+
shouldCallPreviewApi: shouldSimulate,
|
|
28
|
+
});
|
|
52
29
|
const { txFee, txFeeDetails } = getTxFeeDetails(asset, transaction);
|
|
53
30
|
const displayInfo = getEthereumDisplayInfo(balanceChanges);
|
|
54
31
|
return {
|
package/lib/types.d.ts
CHANGED
|
@@ -1,7 +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 { Asset, IAnalyticsModule, IBlockchainMetadataModule,
|
|
4
|
+
import type { Asset, IAnalyticsModule, IBlockchainMetadataModule, EthereumFeeData, GetFeeDataParams } from '@exodus/web3-types';
|
|
5
5
|
/**
|
|
6
6
|
* EVM-compatible chains.
|
|
7
7
|
*/
|
|
@@ -37,6 +37,7 @@ export declare type EVMDeps = {
|
|
|
37
37
|
sendRawTransaction: (rawTransaction: string) => Promise<EthTransactionHash>;
|
|
38
38
|
getEstimatedGas: (transaction: EthTransaction) => Promise<string>;
|
|
39
39
|
getFeeData: () => Promise<FeeData>;
|
|
40
|
+
getOrigin: () => string;
|
|
40
41
|
getNonce: () => Promise<string>;
|
|
41
42
|
forwardRequest: (args: EthRequestArguments) => Promise<unknown>;
|
|
42
43
|
onEthWalletWatchAssetRequest?: (assetDetails: EthWalletWatchAsset) => Promise<boolean>;
|
|
@@ -44,4 +45,3 @@ export declare type EVMDeps = {
|
|
|
44
45
|
export declare type Dependencies = {
|
|
45
46
|
evms: EVMDeps[];
|
|
46
47
|
} & CommonDeps;
|
|
47
|
-
export { ApproveConnectionResponse };
|
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": "
|
|
4
|
+
"version": "5.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"module": "lib/index.js",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"@exodus/currency": "^2.1.2",
|
|
35
35
|
"@exodus/ethereum-api": "^6.0.0",
|
|
36
36
|
"@exodus/web3-constants": "^1.29.0",
|
|
37
|
-
"@exodus/web3-ethereum-utils": "^1.
|
|
38
|
-
"@exodus/web3-provider": "^2.
|
|
39
|
-
"@exodus/web3-rpc-handlers": "^1.
|
|
40
|
-
"@exodus/web3-utils": "^1.
|
|
37
|
+
"@exodus/web3-ethereum-utils": "^1.22.0",
|
|
38
|
+
"@exodus/web3-provider": "^2.29.0",
|
|
39
|
+
"@exodus/web3-rpc-handlers": "^1.4.0",
|
|
40
|
+
"@exodus/web3-utils": "^1.18.0",
|
|
41
41
|
"bn.js": "^5.2.0",
|
|
42
42
|
"eth-rpc-errors": "^4.0.3"
|
|
43
43
|
},
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
"@exodus/assets": "^8.0.72",
|
|
46
46
|
"@exodus/json-rpc": "^1.11.0",
|
|
47
47
|
"@exodus/schemasafe": "^1.0.0",
|
|
48
|
-
"@exodus/web3-types": "^1.
|
|
48
|
+
"@exodus/web3-types": "^1.27.0",
|
|
49
49
|
"@exodus/web3-validation": "^1.35.0",
|
|
50
50
|
"@wallet-standard/base": "^1.0.1"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"@exodus/assets": "^8.0.72"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "ce1e0287af1a5ee3d1f90b71dda277ca6f785825"
|
|
56
56
|
}
|