@avalabs/evm-module 0.0.11 → 0.0.13

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.
Files changed (33) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/.turbo/turbo-test.log +36 -5
  4. package/CHANGELOG.md +21 -0
  5. package/dist/index.cjs +7 -4
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +30 -12
  8. package/dist/index.d.ts +30 -12
  9. package/dist/index.js +6 -4
  10. package/dist/index.js.map +1 -1
  11. package/package.json +5 -3
  12. package/src/env.ts +25 -0
  13. package/src/handlers/eth-send-transaction/eth-send-transaction.test.ts +333 -0
  14. package/src/handlers/eth-send-transaction/eth-send-transaction.ts +170 -0
  15. package/src/handlers/eth-send-transaction/schema.test.ts +240 -0
  16. package/src/handlers/eth-send-transaction/schema.ts +20 -0
  17. package/src/handlers/get-network-fee/get-network-fee.test.ts +2 -1
  18. package/src/handlers/get-network-fee/get-network-fee.ts +10 -11
  19. package/src/handlers/get-tokens/get-tokens.ts +2 -1
  20. package/src/handlers/get-transaction-history/converters/etherscan-transaction-converter/get-transaction-from-etherscan.ts +11 -3
  21. package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-transaction-from-glacier.test.ts +1 -5
  22. package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-transactions-from-glacier.ts +12 -3
  23. package/src/handlers/get-transaction-history/get-transaction-history.test.ts +2 -0
  24. package/src/handlers/get-transaction-history/get-transaction-history.ts +11 -3
  25. package/src/index.ts +2 -72
  26. package/src/module.ts +95 -0
  27. package/src/types.ts +13 -0
  28. package/src/utils/estimate-gas-limit.ts +27 -0
  29. package/src/utils/get-chain-id.ts +12 -0
  30. package/src/utils/get-nonce.ts +11 -0
  31. package/src/utils/get-provider.ts +18 -23
  32. package/tsconfig.json +1 -5
  33. /package/{src/manifest.json → manifest.json} +0 -0
@@ -0,0 +1,240 @@
1
+ import { parseRequestParams } from './schema';
2
+ import { z } from 'zod';
3
+
4
+ it('should return success for valid params', () => {
5
+ const paramsList = [
6
+ [
7
+ {
8
+ from: '0x1234567890123456789012345678901234567890',
9
+ to: '0x1234567890123456789012345678901234567890',
10
+ data: '0xdata',
11
+ value: '0xvalue',
12
+ gas: '0x5208',
13
+ gasPrice: '0x5208',
14
+ maxFeePerGas: '0x5208',
15
+ maxPriorityFeePerGas: '0x5208',
16
+ nonce: '12',
17
+ chainId: '1',
18
+ },
19
+ ],
20
+ [
21
+ {
22
+ from: '0x1234567890123456789012345678901234567890',
23
+ to: '0x1234567890123456789012345678901234567890',
24
+ value: '0xvalue',
25
+ gas: '0x5208',
26
+ gasPrice: '0x5208',
27
+ maxFeePerGas: '0x5208',
28
+ maxPriorityFeePerGas: '0x5208',
29
+ nonce: '12',
30
+ chainId: '1',
31
+ },
32
+ ],
33
+ [
34
+ {
35
+ from: '0x1234567890123456789012345678901234567890',
36
+ to: '0x1234567890123456789012345678901234567890',
37
+ gas: '0x5208',
38
+ gasPrice: '0x5208',
39
+ maxFeePerGas: '0x5208',
40
+ maxPriorityFeePerGas: '0x5208',
41
+ nonce: '12',
42
+ chainId: '1',
43
+ },
44
+ ],
45
+ [
46
+ {
47
+ from: '0x1234567890123456789012345678901234567890',
48
+ to: '0x1234567890123456789012345678901234567890',
49
+ gas: '0x5208',
50
+ gasPrice: '0x5208',
51
+ nonce: '12',
52
+ chainId: '1',
53
+ },
54
+ ],
55
+ [
56
+ {
57
+ from: '0x1234567890123456789012345678901234567890',
58
+ to: '0x1234567890123456789012345678901234567890',
59
+ },
60
+ ],
61
+ ];
62
+
63
+ for (const params of paramsList) {
64
+ const result = parseRequestParams(params);
65
+
66
+ expect(result.success).toBe(true);
67
+ expect(result.data).toEqual(params);
68
+ }
69
+ });
70
+
71
+ it('should return error for invalid params', () => {
72
+ const paramsList = [
73
+ // missing "from"
74
+ [
75
+ {
76
+ to: '0x1234567890123456789012345678901234567890',
77
+ data: '0xdata',
78
+ value: '0xvalue',
79
+ gas: '0x5208',
80
+ gasPrice: '0x5208',
81
+ maxFeePerGas: '0x5208',
82
+ maxPriorityFeePerGas: '0x5208',
83
+ nonce: '12',
84
+ chainId: '1',
85
+ },
86
+ ],
87
+ // invalid "from"
88
+ [
89
+ {
90
+ from: '0x123',
91
+ to: '0x1234567890123456789012345678901234567890',
92
+ data: '0xdata',
93
+ value: '0xvalue',
94
+ gas: '0x5208',
95
+ gasPrice: '0x5208',
96
+ maxFeePerGas: '0x5208',
97
+ maxPriorityFeePerGas: '0x5208',
98
+ nonce: '12',
99
+ chainId: '1',
100
+ },
101
+ ],
102
+ // missing "to"
103
+ [
104
+ {
105
+ from: '0x1234567890123456789012345678901234567890',
106
+ data: '0xdata',
107
+ value: '0xvalue',
108
+ gas: '0x5208',
109
+ gasPrice: '0x5208',
110
+ maxFeePerGas: '0x5208',
111
+ maxPriorityFeePerGas: '0x5208',
112
+ nonce: '12',
113
+ chainId: '1',
114
+ },
115
+ ],
116
+ // invalid "to"
117
+ [
118
+ {
119
+ from: '0x1234567890123456789012345678901234567890',
120
+ to: '0x123',
121
+ data: '0xdata',
122
+ value: '0xvalue',
123
+ gas: '0x5208',
124
+ gasPrice: '0x5208',
125
+ maxFeePerGas: '0x5208',
126
+ maxPriorityFeePerGas: '0x5208',
127
+ nonce: '12',
128
+ chainId: '1',
129
+ },
130
+ ],
131
+ // non-hex "value"
132
+ [
133
+ {
134
+ from: '0x1234567890123456789012345678901234567890',
135
+ to: '0x1234567890123456789012345678901234567890',
136
+ data: '0xdata',
137
+ value: 'value',
138
+ gas: '0x5208',
139
+ gasPrice: '0x5208',
140
+ maxFeePerGas: '0x5208',
141
+ maxPriorityFeePerGas: '0x5208',
142
+ nonce: '12',
143
+ chainId: '1',
144
+ },
145
+ ],
146
+ // non-hex "gas"
147
+ [
148
+ {
149
+ from: '0x1234567890123456789012345678901234567890',
150
+ to: '0x1234567890123456789012345678901234567890',
151
+ data: '0xdata',
152
+ value: '0x5208',
153
+ gas: 'gas',
154
+ gasPrice: '0x5208',
155
+ maxFeePerGas: '0x5208',
156
+ maxPriorityFeePerGas: '0x5208',
157
+ nonce: '12',
158
+ chainId: '1',
159
+ },
160
+ ],
161
+ // non-hex "gasPrice"
162
+ [
163
+ {
164
+ from: '0x1234567890123456789012345678901234567890',
165
+ to: '0x1234567890123456789012345678901234567890',
166
+ data: '0xdata',
167
+ value: '0x5208',
168
+ gas: '0x5208',
169
+ gasPrice: 'gasPrice',
170
+ maxFeePerGas: '0x5208',
171
+ maxPriorityFeePerGas: '0x5208',
172
+ nonce: '12',
173
+ chainId: '1',
174
+ },
175
+ ],
176
+ // non-hex "maxFeePerGas"
177
+ [
178
+ {
179
+ from: '0x1234567890123456789012345678901234567890',
180
+ to: '0x1234567890123456789012345678901234567890',
181
+ data: '0xdata',
182
+ value: '0x5208',
183
+ gas: '0x5208',
184
+ gasPrice: '0x5208',
185
+ maxFeePerGas: 'maxFeePerGas',
186
+ maxPriorityFeePerGas: '0x5208',
187
+ nonce: '12',
188
+ chainId: '1',
189
+ },
190
+ ],
191
+ // non-hex "maxPriorityFeePerGas"
192
+ [
193
+ {
194
+ from: '0x1234567890123456789012345678901234567890',
195
+ to: '0x1234567890123456789012345678901234567890',
196
+ data: '0xdata',
197
+ value: '0x5208',
198
+ gas: '0x5208',
199
+ gasPrice: '0x5208',
200
+ maxFeePerGas: '0x5208',
201
+ maxPriorityFeePerGas: 'maxPriorityFeePerGas',
202
+ nonce: '12',
203
+ chainId: '1',
204
+ },
205
+ ],
206
+ // multiple transactions
207
+ [
208
+ {
209
+ from: '0x1234567890123456789012345678901234567890',
210
+ to: '0x1234567890123456789012345678901234567890',
211
+ data: '0xdata',
212
+ value: '0xvalue',
213
+ gas: '0x5208',
214
+ gasPrice: '0x5208',
215
+ maxFeePerGas: '0x5208',
216
+ maxPriorityFeePerGas: '0x5208',
217
+ nonce: '12',
218
+ chainId: '1',
219
+ },
220
+ {
221
+ from: '0x1234567890123456789012345678901234567890',
222
+ to: '0x1234567890123456789012345678901234567890',
223
+ data: '0xdata',
224
+ value: '0xvalue',
225
+ gas: '0x5208',
226
+ gasPrice: '0x5208',
227
+ maxFeePerGas: '0x5208',
228
+ maxPriorityFeePerGas: '0x5208',
229
+ nonce: '12',
230
+ chainId: '1',
231
+ },
232
+ ],
233
+ ];
234
+
235
+ for (const params of paramsList) {
236
+ const result = parseRequestParams([params]);
237
+ expect(result.success).toBe(false);
238
+ expect(result.error).toBeInstanceOf(z.ZodError);
239
+ }
240
+ });
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+
3
+ const transactionSchema = z.object({
4
+ from: z.string().length(42),
5
+ to: z.string().length(42),
6
+ data: z.string().optional(),
7
+ value: z.string().startsWith('0x').optional(),
8
+ gas: z.string().startsWith('0x').optional(),
9
+ gasPrice: z.string().startsWith('0x').optional(),
10
+ maxFeePerGas: z.string().startsWith('0x').optional(),
11
+ maxPriorityFeePerGas: z.string().startsWith('0x').optional(),
12
+ nonce: z.string().optional(),
13
+ chainId: z.string().optional(),
14
+ });
15
+
16
+ const paramsSchema = z.array(transactionSchema).length(1);
17
+
18
+ export const parseRequestParams = (params: unknown) => {
19
+ return paramsSchema.safeParse(params);
20
+ };
@@ -3,7 +3,7 @@ import { FeeData, JsonRpcProvider } from 'ethers';
3
3
 
4
4
  const params = {
5
5
  glacierApiUrl: 'https://glacier-api.avax.network',
6
- chainId: 'eip155:1',
6
+ chainId: 1,
7
7
  chainName: 'Ethereum Mainnet',
8
8
  rpcUrl: 'https://mainnet.infura.io/v3/1234567890',
9
9
  };
@@ -38,6 +38,7 @@ describe('get-network-fee', () => {
38
38
  maxFeePerGas: 4000000000n,
39
39
  maxPriorityFeePerGas: 3000000000n,
40
40
  },
41
+ isFixedFee: false,
41
42
  });
42
43
  });
43
44
  });
@@ -1,5 +1,6 @@
1
- import type { GetNetworkFeeParams, NetworkFees } from '@avalabs/vm-module-types';
1
+ import type { NetworkFees } from '@avalabs/vm-module-types';
2
2
  import { getProvider } from '../../utils/get-provider';
3
+ import { rpcErrors } from '@metamask/rpc-errors';
3
4
 
4
5
  const DEFAULT_PRESETS = {
5
6
  LOW: 1n,
@@ -11,33 +12,30 @@ const BASE_PRIORITY_FEE_WEI = 500000000n; //0.5 GWei
11
12
 
12
13
  /**
13
14
  * Returns {@link NetworkFees} based on {@link DEFAULT_PRESETS} multipliers.
14
- * @param glacierApiUrl
15
- * @param glacierApiKey
16
- * @params GetNetworkFeeParams
17
15
  * @throws Error if provider does not support eip-1559
18
16
  */
19
17
  export async function getNetworkFee({
20
- glacierApiUrl,
21
- glacierApiKey,
22
18
  chainId,
23
19
  chainName,
24
20
  rpcUrl,
25
21
  multiContractAddress,
26
- }: GetNetworkFeeParams & {
22
+ }: {
23
+ chainId: number;
24
+ chainName: string;
25
+ rpcUrl: string;
27
26
  glacierApiUrl: string;
28
- glacierApiKey?: string;
27
+ multiContractAddress?: string;
29
28
  }): Promise<NetworkFees> {
30
29
  const provider = getProvider({
31
- glacierApiUrl,
32
- glacierApiKey,
33
30
  chainId,
34
31
  chainName,
35
32
  rpcUrl,
36
33
  multiContractAddress,
37
34
  });
35
+
38
36
  const { maxFeePerGas: maxFeePerGasInWei } = await provider.getFeeData();
39
37
  if (!maxFeePerGasInWei) {
40
- throw new Error('Pre-EIP-1559 networks are not supported');
38
+ throw rpcErrors.internal('Pre-EIP-1559 networks are not supported');
41
39
  }
42
40
 
43
41
  const lowMaxTip = BASE_PRIORITY_FEE_WEI * DEFAULT_PRESETS.LOW;
@@ -57,5 +55,6 @@ export async function getNetworkFee({
57
55
  maxFeePerGas: maxFeePerGasInWei + highMaxTip,
58
56
  maxPriorityFeePerGas: highMaxTip,
59
57
  },
58
+ isFixedFee: false,
60
59
  };
61
60
  }
@@ -1,4 +1,5 @@
1
1
  import type { NetworkContractToken } from '@avalabs/vm-module-types';
2
+ import { rpcErrors } from '@metamask/rpc-errors';
2
3
 
3
4
  export async function getTokens({
4
5
  chainId,
@@ -10,7 +11,7 @@ export async function getTokens({
10
11
  const response = await fetch(`${proxyApiUrl}/tokens?evmChainId=${chainId}`);
11
12
 
12
13
  if (!response.ok) {
13
- throw new Error(`Failed to fetch tokens for chainId ${chainId}`);
14
+ throw rpcErrors.internal(`Failed to fetch tokens for chainId ${chainId}`);
14
15
  }
15
16
 
16
17
  return response.json();
@@ -1,6 +1,6 @@
1
1
  import { convertTransactionNormal } from './convert-transaction-normal';
2
2
  import { convertTransactionERC20 } from './convert-transaction-erc20';
3
- import type { GetTransactionHistory, TransactionHistoryResponse } from '@avalabs/vm-module-types';
3
+ import type { NetworkToken, TransactionHistoryResponse } from '@avalabs/vm-module-types';
4
4
  import { getErc20Txs, getNormalTxs } from '@avalabs/etherscan-sdk';
5
5
 
6
6
  interface EtherscanPagination {
@@ -10,13 +10,21 @@ interface EtherscanPagination {
10
10
 
11
11
  export const getTransactionFromEtherscan = async ({
12
12
  isTestnet,
13
- chainId,
14
13
  networkToken,
15
14
  explorerUrl,
15
+ chainId,
16
16
  address,
17
17
  nextPageToken,
18
18
  offset,
19
- }: GetTransactionHistory): Promise<TransactionHistoryResponse> => {
19
+ }: {
20
+ isTestnet?: boolean;
21
+ networkToken: NetworkToken;
22
+ explorerUrl: string;
23
+ chainId: number;
24
+ address: string;
25
+ nextPageToken?: string;
26
+ offset?: number;
27
+ }): Promise<TransactionHistoryResponse> => {
20
28
  /*
21
29
  Using JSON for nextPageToken because this function is managing both the Normal
22
30
  and ERC20 queries. It encodes the current page and the queries that should be
@@ -46,7 +46,6 @@ describe('get-transactions-from-glacier', () => {
46
46
  it('should have returned error with missing glacier api url', async () => {
47
47
  try {
48
48
  await getTransactionsFromGlacier({
49
- isTestnet: false,
50
49
  networkToken: {
51
50
  name: 'networkToken',
52
51
  symbol: 'networkToken',
@@ -59,6 +58,7 @@ describe('get-transactions-from-glacier', () => {
59
58
  address: 'address',
60
59
  nextPageToken: 'nextPageToken',
61
60
  offset: 1,
61
+ glacierApiUrl: 'glacierApiUrl',
62
62
  });
63
63
  } catch (error) {
64
64
  expect(error).toEqual(new Error('Glacier API URL is required'));
@@ -67,7 +67,6 @@ describe('get-transactions-from-glacier', () => {
67
67
  it('should have returned empty response when listTransaction failed', async () => {
68
68
  mockListTransactions.mockRejectedValue(new Error('failed to list transactions'));
69
69
  const result = await getTransactionsFromGlacier({
70
- isTestnet: false,
71
70
  networkToken: {
72
71
  name: 'networkToken',
73
72
  symbol: 'networkToken',
@@ -101,7 +100,6 @@ describe('get-transactions-from-glacier', () => {
101
100
  ],
102
101
  });
103
102
  const result = await getTransactionsFromGlacier({
104
- isTestnet: false,
105
103
  networkToken: {
106
104
  name: 'networkToken',
107
105
  symbol: 'networkToken',
@@ -135,7 +133,6 @@ describe('get-transactions-from-glacier', () => {
135
133
  ],
136
134
  });
137
135
  const result = await getTransactionsFromGlacier({
138
- isTestnet: false,
139
136
  networkToken: {
140
137
  name: 'networkToken',
141
138
  symbol: 'networkToken',
@@ -159,7 +156,6 @@ describe('get-transactions-from-glacier', () => {
159
156
  it('should have returned response', async () => {
160
157
  mockListTransactions.mockResolvedValue(mockListTransactionDetailsResponse);
161
158
  const result = await getTransactionsFromGlacier({
162
- isTestnet: false,
163
159
  networkToken: {
164
160
  name: 'networkToken',
165
161
  symbol: 'networkToken',
@@ -1,5 +1,6 @@
1
- import type { GetTransactionHistory, TransactionHistoryResponse } from '@avalabs/vm-module-types';
1
+ import type { NetworkToken, TransactionHistoryResponse } from '@avalabs/vm-module-types';
2
2
  import { Glacier } from '@avalabs/glacier-sdk';
3
+ import { rpcErrors } from '@metamask/rpc-errors';
3
4
  import { convertTransaction } from './convert-transaction';
4
5
 
5
6
  export const getTransactionsFromGlacier = async ({
@@ -10,9 +11,17 @@ export const getTransactionsFromGlacier = async ({
10
11
  nextPageToken,
11
12
  offset,
12
13
  glacierApiUrl,
13
- }: GetTransactionHistory): Promise<TransactionHistoryResponse> => {
14
+ }: {
15
+ chainId: number;
16
+ explorerUrl: string;
17
+ networkToken: NetworkToken;
18
+ address: string;
19
+ nextPageToken?: string;
20
+ offset?: number;
21
+ glacierApiUrl: string;
22
+ }): Promise<TransactionHistoryResponse> => {
14
23
  if (!glacierApiUrl) {
15
- throw new Error('Glacier API URL is required');
24
+ throw rpcErrors.invalidParams('Glacier API URL is required');
16
25
  }
17
26
 
18
27
  const glacierSdk = new Glacier({ BASE: glacierApiUrl });
@@ -13,6 +13,7 @@ jest.mock('./converters/etherscan-transaction-converter/get-transaction-from-eth
13
13
  describe('get-transaction-history', () => {
14
14
  it('should have called getTransactionFromEtherscan', async () => {
15
15
  await getTransactionHistory({
16
+ glacierApiUrl: 'glacierApiUrl',
16
17
  chainId: 1,
17
18
  isTestnet: false,
18
19
  networkToken: {
@@ -31,6 +32,7 @@ describe('get-transaction-history', () => {
31
32
  });
32
33
  it('should have called getTransactionsFromGlacier', async () => {
33
34
  await getTransactionHistory({
35
+ glacierApiUrl: 'glacierApiUrl',
34
36
  chainId: 41334,
35
37
  isTestnet: false,
36
38
  networkToken: {
@@ -1,6 +1,6 @@
1
1
  import { getTransactionFromEtherscan } from './converters/etherscan-transaction-converter/get-transaction-from-etherscan';
2
2
  import { isEthereumChainId } from './utils/is-ethereum-chain-id';
3
- import type { GetTransactionHistory, TransactionHistoryResponse } from '@avalabs/vm-module-types';
3
+ import type { NetworkToken, TransactionHistoryResponse } from '@avalabs/vm-module-types';
4
4
  import { getTransactionsFromGlacier } from './converters/evm-transaction-converter/get-transactions-from-glacier';
5
5
 
6
6
  export const getTransactionHistory = async ({
@@ -12,7 +12,16 @@ export const getTransactionHistory = async ({
12
12
  nextPageToken,
13
13
  offset,
14
14
  glacierApiUrl,
15
- }: GetTransactionHistory): Promise<TransactionHistoryResponse> => {
15
+ }: {
16
+ chainId: number;
17
+ isTestnet?: boolean;
18
+ networkToken: NetworkToken;
19
+ explorerUrl: string;
20
+ address: string;
21
+ nextPageToken?: string;
22
+ offset?: number;
23
+ glacierApiUrl: string;
24
+ }): Promise<TransactionHistoryResponse> => {
16
25
  if (isEthereumChainId(chainId)) {
17
26
  return getTransactionFromEtherscan({
18
27
  isTestnet,
@@ -25,7 +34,6 @@ export const getTransactionHistory = async ({
25
34
  });
26
35
  }
27
36
  return getTransactionsFromGlacier({
28
- isTestnet,
29
37
  networkToken,
30
38
  explorerUrl,
31
39
  chainId,
package/src/index.ts CHANGED
@@ -1,72 +1,2 @@
1
- import type {
2
- Module,
3
- Manifest,
4
- NetworkFees,
5
- GetTransactionHistory,
6
- RpcRequest,
7
- GetNetworkFeeParams,
8
- } from '@avalabs/vm-module-types';
9
- import { parseManifest } from '@avalabs/vm-module-types';
10
- import { getNetworkFee } from './handlers/get-network-fee/get-network-fee';
11
- import { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';
12
- import { getTokens } from './handlers/get-tokens/get-tokens';
13
- import ManifestJson from './manifest.json';
14
-
15
- export class EvmModule implements Module {
16
- #glacierApiUrl: string;
17
- #glacierApiKey?: string;
18
- #proxyApiUrl: string;
19
-
20
- constructor({
21
- glacierApiUrl,
22
- glacierApiKey,
23
- proxyApiUrl,
24
- }: {
25
- glacierApiUrl: string;
26
- glacierApiKey?: string;
27
- proxyApiUrl: string;
28
- }) {
29
- this.#glacierApiUrl = glacierApiUrl;
30
- this.#glacierApiKey = glacierApiKey;
31
- this.#proxyApiUrl = proxyApiUrl;
32
- }
33
- getAddress(): Promise<string> {
34
- return Promise.resolve('EVM address');
35
- }
36
-
37
- getBalances(): Promise<string> {
38
- return Promise.resolve('EVM balances');
39
- }
40
-
41
- getManifest(): Manifest | undefined {
42
- const result = parseManifest(ManifestJson);
43
- return result.success ? result.data : undefined;
44
- }
45
-
46
- getNetworkFee({ chainId, chainName, rpcUrl, multiContractAddress }: GetNetworkFeeParams): Promise<NetworkFees> {
47
- return getNetworkFee({
48
- glacierApiUrl: this.#glacierApiUrl,
49
- glacierApiKey: this.#glacierApiKey,
50
- chainId,
51
- chainName,
52
- rpcUrl,
53
- multiContractAddress,
54
- });
55
- }
56
-
57
- getTransactionHistory(params: GetTransactionHistory) {
58
- return getTransactionHistory({ ...params, glacierApiUrl: this.#glacierApiUrl });
59
- }
60
-
61
- getTokens(chainId: number) {
62
- return getTokens({ chainId, proxyApiUrl: this.#proxyApiUrl });
63
- }
64
-
65
- async onRpcRequest(request: RpcRequest) {
66
- // TODO implement the RPC request handler
67
- switch (request.method) {
68
- default:
69
- return { error: new Error(`Method ${request.method} not supported`) };
70
- }
71
- }
72
- }
1
+ export * from './module';
2
+ export * from './types';
package/src/module.ts ADDED
@@ -0,0 +1,95 @@
1
+ import type {
2
+ Module,
3
+ Manifest,
4
+ NetworkFees,
5
+ GetTransactionHistory,
6
+ RpcRequest,
7
+ Environment,
8
+ Network,
9
+ ApprovalController,
10
+ } from '@avalabs/vm-module-types';
11
+ import { rpcErrors } from '@metamask/rpc-errors';
12
+ import { RpcMethod, parseManifest } from '@avalabs/vm-module-types';
13
+ import { getTokens } from './handlers/get-tokens/get-tokens';
14
+ import { getNetworkFee } from './handlers/get-network-fee/get-network-fee';
15
+ import { getTransactionHistory } from './handlers/get-transaction-history/get-transaction-history';
16
+ import ManifestJson from '../manifest.json';
17
+ import { getEnv } from './env';
18
+ import { ethSendTransaction } from './handlers/eth-send-transaction/eth-send-transaction';
19
+
20
+ export class EvmModule implements Module {
21
+ #glacierApiUrl: string;
22
+ #proxyApiUrl: string;
23
+ #approvalController: ApprovalController;
24
+
25
+ constructor({
26
+ approvalController,
27
+ environment,
28
+ }: {
29
+ approvalController: ApprovalController;
30
+ environment: Environment;
31
+ }) {
32
+ const { glacierApiUrl, proxyApiUrl } = getEnv(environment);
33
+ this.#glacierApiUrl = glacierApiUrl;
34
+ this.#proxyApiUrl = proxyApiUrl;
35
+ this.#approvalController = approvalController;
36
+ }
37
+
38
+ getAddress(): Promise<string> {
39
+ return Promise.resolve('EVM address');
40
+ }
41
+
42
+ getBalances(): Promise<string> {
43
+ return Promise.resolve('EVM balances');
44
+ }
45
+
46
+ getManifest(): Manifest | undefined {
47
+ const result = parseManifest(ManifestJson);
48
+ return result.success ? result.data : undefined;
49
+ }
50
+
51
+ getNetworkFee(network: Network): Promise<NetworkFees> {
52
+ const { chainId, chainName, rpcUrl, utilityAddresses } = network;
53
+ return getNetworkFee({
54
+ chainId,
55
+ chainName,
56
+ rpcUrl,
57
+ multiContractAddress: utilityAddresses?.multicall,
58
+ glacierApiUrl: this.#glacierApiUrl,
59
+ });
60
+ }
61
+
62
+ getTransactionHistory(params: GetTransactionHistory) {
63
+ const { network, address, nextPageToken, offset } = params;
64
+ const { chainId, isTestnet, networkToken, explorerUrl = '' } = network;
65
+
66
+ return getTransactionHistory({
67
+ chainId,
68
+ isTestnet,
69
+ networkToken,
70
+ explorerUrl,
71
+ address,
72
+ nextPageToken,
73
+ offset,
74
+ glacierApiUrl: this.#glacierApiUrl,
75
+ });
76
+ }
77
+
78
+ getTokens(network: Network) {
79
+ const { chainId } = network;
80
+ return getTokens({ chainId, proxyApiUrl: this.#proxyApiUrl });
81
+ }
82
+
83
+ async onRpcRequest(request: RpcRequest, network: Network) {
84
+ switch (request.method) {
85
+ case RpcMethod.ETH_SEND_TRANSACTION:
86
+ return ethSendTransaction({
87
+ request,
88
+ network,
89
+ approvalController: this.#approvalController,
90
+ });
91
+ default:
92
+ return { error: rpcErrors.methodNotSupported(`Method ${request.method} not supported`) };
93
+ }
94
+ }
95
+ }
package/src/types.ts CHANGED
@@ -1,3 +1,16 @@
1
1
  import { TransactionType } from '@avalabs/vm-module-types';
2
2
 
3
3
  export const NonContractCallTypes = [TransactionType.SEND, TransactionType.RECEIVE, TransactionType.TRANSFER];
4
+
5
+ export type TransactionParams = {
6
+ from: string;
7
+ to: string;
8
+ data?: string;
9
+ value?: string;
10
+ gas?: string;
11
+ gasPrice?: string;
12
+ maxFeePerGas?: string;
13
+ maxPriorityFeePerGas?: string;
14
+ nonce?: string;
15
+ chainId?: string;
16
+ };