@exodus/web3-ethereum 10.7.0 → 11.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.
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { fetchGasLimit, getNonce as apiGetNonce, getServer, } from '@exodus/ethereum-api';
|
|
2
|
+
import { InvalidInputError } from '@exodus/web3-errors';
|
|
3
|
+
import { signMessage, signTypedData } from '@exodus/web3-ethereum-utils';
|
|
4
|
+
import { SignTypedDataVersion } from '@metamask/eth-sig-util';
|
|
2
5
|
import BN from 'bn.js';
|
|
6
|
+
async function getDefaultPurposeForLedger(asset) {
|
|
7
|
+
const purposes = await asset.api.getSupportedPurposes({
|
|
8
|
+
compatibilityMode: 'ledger',
|
|
9
|
+
});
|
|
10
|
+
return purposes[0];
|
|
11
|
+
}
|
|
3
12
|
const createEvmDepsFactory = ({ analytics, blockchainMetadata, }) => {
|
|
4
|
-
return ({ assetName, origin, getAsset, getAddress: _getAddress, getPrivateKey: _getPrivateKey, getFeeData: getFeeConfig, getCustomFeeRate, getActiveWalletAccount, simulateEthereumTransactions, }) => {
|
|
13
|
+
return ({ assetName, origin, getAsset, getAddress: _getAddress, getPrivateKey: _getPrivateKey, getFeeData: getFeeConfig, getCustomFeeRate, getActiveWalletAccount, simulateEthereumTransactions, getActiveWalletAccountData, transactionSigner, getLedgerDevice, }) => {
|
|
5
14
|
const asset = getAsset(assetName);
|
|
6
15
|
const server = getServer(asset);
|
|
7
16
|
const forwardRequest = async ({ method, params }) => {
|
|
@@ -107,6 +116,44 @@ const createEvmDepsFactory = ({ analytics, blockchainMetadata, }) => {
|
|
|
107
116
|
});
|
|
108
117
|
return true;
|
|
109
118
|
};
|
|
119
|
+
const messageSigner = {
|
|
120
|
+
signMessage: async ({ baseAssetName, walletAccount, message, }) => {
|
|
121
|
+
const { rawMessage, EIP712Message } = message;
|
|
122
|
+
if (walletAccount.source === 'exodus') {
|
|
123
|
+
const privateKey = await getPrivateKey();
|
|
124
|
+
if (rawMessage) {
|
|
125
|
+
return Buffer.from(signMessage(rawMessage.toString(), privateKey));
|
|
126
|
+
}
|
|
127
|
+
if (EIP712Message) {
|
|
128
|
+
const typedDataVersion = Array.isArray(EIP712Message)
|
|
129
|
+
? SignTypedDataVersion.V1
|
|
130
|
+
: SignTypedDataVersion.V4;
|
|
131
|
+
return Buffer.from(signTypedData(EIP712Message, privateKey, typedDataVersion));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else if (getLedgerDevice) {
|
|
135
|
+
const device = await getLedgerDevice();
|
|
136
|
+
const purpose = await getDefaultPurposeForLedger(asset);
|
|
137
|
+
const { derivationPath } = await getAsset(assetName).baseAsset.api.getKeyIdentifier({
|
|
138
|
+
compatibilityMode: 'ledger',
|
|
139
|
+
purpose,
|
|
140
|
+
accountIndex: 0,
|
|
141
|
+
chainIndex: 0,
|
|
142
|
+
addressIndex: 0,
|
|
143
|
+
});
|
|
144
|
+
const signedMessage = await device.signMessage({
|
|
145
|
+
assetName: baseAssetName,
|
|
146
|
+
derivationPath,
|
|
147
|
+
message: {
|
|
148
|
+
rawMessage,
|
|
149
|
+
EIP712Message,
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
return Buffer.from(signedMessage);
|
|
153
|
+
}
|
|
154
|
+
throw new InvalidInputError();
|
|
155
|
+
},
|
|
156
|
+
};
|
|
110
157
|
return {
|
|
111
158
|
chainId: 'undefined',
|
|
112
159
|
forwardRequest,
|
|
@@ -119,6 +166,9 @@ const createEvmDepsFactory = ({ analytics, blockchainMetadata, }) => {
|
|
|
119
166
|
getCustomFeeData,
|
|
120
167
|
onEthWalletWatchAssetRequest: trackWalletWatchAssetUse,
|
|
121
168
|
simulateEthereumTransactions,
|
|
169
|
+
transactionSigner,
|
|
170
|
+
messageSigner,
|
|
171
|
+
getActiveWalletAccountData,
|
|
122
172
|
};
|
|
123
173
|
};
|
|
124
174
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AssetNotSupportedError, InvalidInputError, UnauthorizedError, UserRejectedRequestError, } from '@exodus/web3-errors';
|
|
2
|
-
import { getTransactionId, signMessage, signTransaction, signTypedData, } from '@exodus/web3-ethereum-utils';
|
|
3
2
|
import { connect } from '@exodus/web3-rpc-handlers';
|
|
4
3
|
import { hexToBN } from '@exodus/web3-utils';
|
|
5
4
|
import { SignTypedDataVersion } from '@metamask/eth-sig-util';
|
|
@@ -62,7 +61,7 @@ const isValidGasLimitValue = (value) => {
|
|
|
62
61
|
return proposedGasLimit.lte(maximumBlockGasLimit);
|
|
63
62
|
};
|
|
64
63
|
export function exposeHandlers(rpc, deps) {
|
|
65
|
-
const { chainId, isTrusted, isAutoApproved, ensureTrusted, approveConnection, approveMessage, approveTransactions, forwardRequest, getAddress,
|
|
64
|
+
const { chainId, isTrusted, isAutoApproved, ensureTrusted, approveConnection, approveMessage, approveTransactions, forwardRequest, getAddress, getEstimatedGas, getCustomFeeData, getFeeData, getNonce, sendRawTransaction, simulateEthereumTransactions, scanDomains, onTransactionsSigned = () => { }, onEthWalletWatchAssetRequest = () => { }, isUnlocked = () => true, ensureUnlocked = async () => true, getAsset, getOrigin, getActiveWalletAccountData, transactionSigner, messageSigner, } = deps;
|
|
66
65
|
const network = `evm:${chainId}`;
|
|
67
66
|
async function assertTrusted() {
|
|
68
67
|
const trusted = await isTrusted();
|
|
@@ -142,26 +141,48 @@ export function exposeHandlers(rpc, deps) {
|
|
|
142
141
|
});
|
|
143
142
|
await approve(approveTransactions, network, simulatedChanges);
|
|
144
143
|
const modifiedTransaction = await applyCustomFeeRate(preparedTransaction);
|
|
145
|
-
const privateKey = await getPrivateKey();
|
|
146
|
-
const signedTransaction = signTransaction({ ...modifiedTransaction, chainId }, privateKey);
|
|
147
144
|
const isEIP1559Enabled = !!modifiedTransaction.maxFeePerGas;
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
const walletAccount = await getActiveWalletAccountData();
|
|
146
|
+
const { rawTx: signedTransaction, txId } = await transactionSigner.signTransaction({
|
|
147
|
+
baseAssetName: asset.baseAssetName,
|
|
148
|
+
walletAccount,
|
|
149
|
+
unsignedTx: {
|
|
150
|
+
txData: { transaction: { ...modifiedTransaction, chainId } },
|
|
151
|
+
txMeta: { eip1559Enabled: isEIP1559Enabled },
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
onTransactionsSigned(network, [txId]);
|
|
155
|
+
return `0x${Buffer.from(signedTransaction).toString('hex')}`;
|
|
151
156
|
}
|
|
152
157
|
async function approveAndSignMessage(message) {
|
|
153
158
|
await assertTrusted();
|
|
154
159
|
await approve(approveMessage, network, message);
|
|
155
|
-
const
|
|
156
|
-
|
|
160
|
+
const walletAccount = await getActiveWalletAccountData();
|
|
161
|
+
const asset = await getAsset(network);
|
|
162
|
+
const signedMessageBuffer = await messageSigner.signMessage({
|
|
163
|
+
walletAccount,
|
|
164
|
+
baseAssetName: asset.baseAssetName,
|
|
165
|
+
message: {
|
|
166
|
+
rawMessage: Buffer.from(message),
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
return signedMessageBuffer.toString();
|
|
157
170
|
}
|
|
158
171
|
async function approveAndSignTypedData(typedData) {
|
|
159
172
|
await assertTrusted();
|
|
160
173
|
const parsedTypedData = parseAndValidateTypedData(typedData, { chainId });
|
|
161
174
|
const message = typedDataToMessage(typedData, SignTypedDataVersion.V4);
|
|
162
175
|
await approve(approveMessage, network, message);
|
|
163
|
-
const
|
|
164
|
-
|
|
176
|
+
const walletAccount = await getActiveWalletAccountData();
|
|
177
|
+
const asset = await getAsset(network);
|
|
178
|
+
const signedMessageBuffer = await messageSigner.signMessage({
|
|
179
|
+
walletAccount,
|
|
180
|
+
baseAssetName: asset.baseAssetName,
|
|
181
|
+
message: {
|
|
182
|
+
EIP712Message: parsedTypedData,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
return signedMessageBuffer.toString();
|
|
165
186
|
}
|
|
166
187
|
function exposeEvmFunction(name,
|
|
167
188
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -203,8 +224,16 @@ export function exposeHandlers(rpc, deps) {
|
|
|
203
224
|
await assertTrusted();
|
|
204
225
|
const message = typedDataToMessage(typedData, SignTypedDataVersion.V1);
|
|
205
226
|
await approve(approveMessage, network, message);
|
|
206
|
-
const
|
|
207
|
-
|
|
227
|
+
const walletAccount = await getActiveWalletAccountData();
|
|
228
|
+
const asset = await getAsset(network);
|
|
229
|
+
const signedMessageBuffer = await messageSigner.signMessage({
|
|
230
|
+
walletAccount,
|
|
231
|
+
baseAssetName: asset.baseAssetName,
|
|
232
|
+
message: {
|
|
233
|
+
EIP712Message: typedData,
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
return signedMessageBuffer.toString();
|
|
208
237
|
});
|
|
209
238
|
exposeEvmFunction('eth_signTypedData_v3', async (account, typedData) => approveAndSignTypedData(typedData));
|
|
210
239
|
exposeEvmFunction('eth_signTypedData_v4', async (account, typedData) => approveAndSignTypedData(typedData));
|
|
@@ -15,6 +15,9 @@ const validateEVMDeps = (evm) => {
|
|
|
15
15
|
'getNonce',
|
|
16
16
|
'sendRawTransaction',
|
|
17
17
|
'simulateEthereumTransactions',
|
|
18
|
+
'getActiveWalletAccountData',
|
|
19
|
+
'transactionSigner',
|
|
20
|
+
'messageSigner',
|
|
18
21
|
];
|
|
19
22
|
const optionalKeys = ['onEthWalletWatchAssetRequest'];
|
|
20
23
|
validateDeps(evm, requiredKeys, optionalKeys);
|
package/lib/types.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import type { EthereumProvider } from './provider/index.js';
|
|
3
3
|
import type { EthAggregatedTransactionSimulationResult, EthSimulateTransactionParams, EthTransaction, EthTransactionHash, EthWalletWatchAsset } from '@exodus/web3-ethereum-utils';
|
|
4
|
+
import type { EthTransactionParams } from '@exodus/web3-ethereum-utils';
|
|
4
5
|
import type { WalletStandardCommonDeps } from '@exodus/web3-provider';
|
|
5
6
|
import type { CommonDeps } from '@exodus/web3-rpc-handlers';
|
|
6
|
-
import type { Asset,
|
|
7
|
+
import type { Asset, CreateSimulationServiceParams, EthereumFeeData, GetActiveWalletAccountData, GetFeeDataParams, GetLedgerDevice, IAnalyticsModule, IBlockchainMetadataModule, IMessageSignerModule, ITransactionSignerModule, NumberUnit } from '@exodus/web3-types';
|
|
8
|
+
import type { TypedDataV1 } from '@metamask/eth-sig-util';
|
|
9
|
+
import type { MessageTypes, TypedMessage } from '@metamask/eth-sig-util/sign-typed-data';
|
|
7
10
|
/**
|
|
8
11
|
* EVM-compatible chains.
|
|
9
12
|
*/
|
|
@@ -34,8 +37,12 @@ export interface CreateEvmDepsParams {
|
|
|
34
37
|
privateKey: Buffer;
|
|
35
38
|
}>;
|
|
36
39
|
simulateEthereumTransactions: SimulateTransactionsFn;
|
|
40
|
+
getActiveWalletAccountData: GetActiveWalletAccountData;
|
|
41
|
+
transactionSigner: EVMTransactionSignerModule;
|
|
42
|
+
getLedgerDevice?: GetLedgerDevice;
|
|
37
43
|
}
|
|
38
44
|
export declare type EVMFactory = (params: CreateEvmDepsParams) => EVMDeps;
|
|
45
|
+
export declare type EVMTransactionSignerModule = ITransactionSignerModule<EVMUnsignedTransaction>;
|
|
39
46
|
export declare type EVMDeps = {
|
|
40
47
|
chainId: string;
|
|
41
48
|
getAddress: () => Promise<string>;
|
|
@@ -47,7 +54,10 @@ export declare type EVMDeps = {
|
|
|
47
54
|
getCustomFeeData: () => Promise<FeeData | undefined>;
|
|
48
55
|
getNonce: () => Promise<string>;
|
|
49
56
|
forwardRequest: (args: EthRequestArguments) => Promise<unknown>;
|
|
57
|
+
transactionSigner: EVMTransactionSignerModule;
|
|
58
|
+
messageSigner: EVMMessageSigner;
|
|
50
59
|
onEthWalletWatchAssetRequest?: (assetDetails: EthWalletWatchAsset) => Promise<boolean>;
|
|
60
|
+
getActiveWalletAccountData: GetActiveWalletAccountData;
|
|
51
61
|
};
|
|
52
62
|
export declare type Dependencies = {
|
|
53
63
|
evms: EVMDeps[];
|
|
@@ -55,4 +65,17 @@ export declare type Dependencies = {
|
|
|
55
65
|
export interface WalletStandardDeps extends WalletStandardCommonDeps {
|
|
56
66
|
provider: EthereumProvider;
|
|
57
67
|
}
|
|
68
|
+
export interface EVMUnsignedTransaction {
|
|
69
|
+
txData: {
|
|
70
|
+
transaction: EthTransactionParams;
|
|
71
|
+
};
|
|
72
|
+
txMeta: {
|
|
73
|
+
eip1559Enabled: boolean;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export interface EVMMesage {
|
|
77
|
+
rawMessage?: Buffer;
|
|
78
|
+
EIP712Message?: TypedDataV1 | TypedMessage<MessageTypes>;
|
|
79
|
+
}
|
|
80
|
+
export declare type EVMMessageSigner = IMessageSignerModule<EVMMesage>;
|
|
58
81
|
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": "
|
|
4
|
+
"version": "11.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"module": "lib/index.js",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"@exodus/currency": "^2.1.2",
|
|
34
34
|
"@exodus/ethereum-api": "^6.3.33",
|
|
35
35
|
"@exodus/web3-constants": "^1.29.0",
|
|
36
|
-
"@exodus/web3-ethereum-utils": "^3.
|
|
37
|
-
"@exodus/web3-provider": "^3.
|
|
38
|
-
"@exodus/web3-rpc-handlers": "^2.
|
|
39
|
-
"@exodus/web3-utils": "^1.
|
|
36
|
+
"@exodus/web3-ethereum-utils": "^3.17.0",
|
|
37
|
+
"@exodus/web3-provider": "^3.8.0",
|
|
38
|
+
"@exodus/web3-rpc-handlers": "^2.14.0",
|
|
39
|
+
"@exodus/web3-utils": "^1.38.0",
|
|
40
40
|
"bn.js": "^5.2.0",
|
|
41
41
|
"eth-rpc-errors": "^4.0.3"
|
|
42
42
|
},
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
"@exodus/assets": "^8.0.95",
|
|
45
45
|
"@exodus/json-rpc": "^1.11.0",
|
|
46
46
|
"@exodus/schemasafe": "^1.0.0",
|
|
47
|
-
"@exodus/web3-types": "^1.
|
|
47
|
+
"@exodus/web3-types": "^1.44.0",
|
|
48
48
|
"@exodus/web3-validation": "^1.37.0",
|
|
49
49
|
"@wallet-standard/base": "^1.0.1"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@exodus/assets": "^8.0.95"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "273234a09070d3d7ce08d77cace39695fc27b2c8"
|
|
55
55
|
}
|