@avalabs/evm-module 0.0.10 → 0.0.12
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/.turbo/turbo-build.log +10 -10
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +36 -5
- package/CHANGELOG.md +19 -0
- package/dist/index.cjs +7 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -12
- package/dist/index.d.ts +30 -12
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/src/env.ts +25 -0
- package/src/handlers/eth-send-transaction/eth-send-transaction.test.ts +333 -0
- package/src/handlers/eth-send-transaction/eth-send-transaction.ts +170 -0
- package/src/handlers/eth-send-transaction/schema.test.ts +240 -0
- package/src/handlers/eth-send-transaction/schema.ts +20 -0
- package/src/handlers/get-network-fee/get-network-fee.test.ts +1 -1
- package/src/handlers/get-network-fee/get-network-fee.ts +9 -11
- package/src/handlers/get-tokens/get-tokens.ts +2 -1
- package/src/handlers/get-transaction-history/converters/etherscan-transaction-converter/get-transaction-from-etherscan.ts +11 -3
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-sender-info.ts +2 -2
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-transaction-from-glacier.test.ts +1 -5
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-transactions-from-glacier.ts +12 -3
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-tx-type.ts +9 -5
- package/src/handlers/get-transaction-history/get-transaction-history.test.ts +2 -0
- package/src/handlers/get-transaction-history/get-transaction-history.ts +11 -3
- package/src/index.ts +2 -72
- package/src/module.ts +95 -0
- package/src/types.ts +13 -0
- package/src/utils/estimate-gas-limit.ts +27 -0
- package/src/utils/get-chain-id.ts +12 -0
- package/src/utils/get-nonce.ts +11 -0
- package/src/utils/get-provider.ts +18 -23
- package/tsconfig.json +1 -5
|
@@ -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
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
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
|
-
}:
|
|
22
|
+
}: {
|
|
23
|
+
chainId: number;
|
|
24
|
+
chainName: string;
|
|
25
|
+
rpcUrl: string;
|
|
27
26
|
glacierApiUrl: string;
|
|
28
|
-
|
|
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
|
|
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;
|
|
@@ -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
|
|
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 {
|
|
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
|
-
}:
|
|
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
|
package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-sender-info.ts
CHANGED
|
@@ -23,8 +23,8 @@ export const getSenderInfo = (
|
|
|
23
23
|
to = erc721Transfers[0].to.address;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
const isOutgoing = isNativeSend || (isTransfer && from === address);
|
|
27
|
-
const isIncoming = isNativeReceive || (isTransfer && to === address);
|
|
26
|
+
const isOutgoing = isNativeSend || (isTransfer && from.toLowerCase() === address.toLowerCase());
|
|
27
|
+
const isIncoming = isNativeReceive || (isTransfer && to.toLowerCase() === address.toLowerCase());
|
|
28
28
|
|
|
29
29
|
const isSender = from === address;
|
|
30
30
|
|
|
@@ -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 {
|
|
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
|
-
}:
|
|
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
|
|
24
|
+
throw rpcErrors.invalidParams('Glacier API URL is required');
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
const glacierSdk = new Glacier({ BASE: glacierApiUrl });
|
package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-tx-type.ts
CHANGED
|
@@ -4,23 +4,27 @@ import startCase from 'lodash.startcase';
|
|
|
4
4
|
|
|
5
5
|
export const getTxType = (
|
|
6
6
|
{ nativeTransaction, erc20Transfers, erc721Transfers }: TransactionDetails,
|
|
7
|
-
|
|
7
|
+
userAddress: string,
|
|
8
8
|
tokens: TxToken[],
|
|
9
9
|
): TransactionType => {
|
|
10
10
|
const nativeOnly = !erc20Transfers && !erc721Transfers;
|
|
11
11
|
const method = parseRawMethod(nativeTransaction.method?.methodName);
|
|
12
12
|
|
|
13
|
+
const address = userAddress.toLowerCase();
|
|
14
|
+
|
|
13
15
|
const isSwap = method.toLowerCase().includes('swap');
|
|
14
|
-
const isNativeSend = nativeOnly && nativeTransaction.from.address === address;
|
|
15
|
-
const isNativeReceive = nativeOnly && nativeTransaction.to.address === address;
|
|
16
|
+
const isNativeSend = nativeOnly && nativeTransaction.from.address.toLowerCase() === address;
|
|
17
|
+
const isNativeReceive = nativeOnly && nativeTransaction.to.address.toLowerCase() === address;
|
|
16
18
|
const isNFTPurchase = method === 'Market Buy Orders With Eth' || method === 'Buy NFT';
|
|
17
19
|
const isApprove = method === 'Approve';
|
|
18
20
|
const isTransfer = method.toLowerCase().includes('transfer');
|
|
19
21
|
const isAirdrop = method.toLowerCase().includes('airdrop');
|
|
20
22
|
const isUnwrap = method.toLowerCase().includes('unwrap');
|
|
21
23
|
const isFillOrder = method === 'Fill Order';
|
|
22
|
-
const isNFTSend =
|
|
23
|
-
|
|
24
|
+
const isNFTSend =
|
|
25
|
+
isTransfer && !!tokens[0] && isNFT(tokens[0].type) && tokens[0].from?.address.toLowerCase() === address;
|
|
26
|
+
const isNFTReceive =
|
|
27
|
+
isTransfer && !!tokens[0] && isNFT(tokens[0].type) && tokens[0].to?.address.toLowerCase() === address;
|
|
24
28
|
|
|
25
29
|
if (isSwap) return TransactionType.SWAP;
|
|
26
30
|
if (isNativeSend) return TransactionType.SEND;
|
|
@@ -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 {
|
|
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
|
-
}:
|
|
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
|
-
|
|
2
|
-
|
|
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';
|