@avalabs/evm-module 0.0.0-workspaces-20240716185307 → 0.0.2
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 +3 -49
- package/CHANGELOG.md +0 -98
- package/dist/index.cjs +2 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -39
- package/dist/index.d.ts +3 -39
- package/dist/index.js +2 -17
- package/dist/index.js.map +1 -1
- package/package.json +6 -30
- package/src/index.ts +22 -2
- package/{manifest.json → src/manifest.json} +1 -1
- package/tsconfig.json +1 -2
- package/src/contracts/openzeppelin/ERC1155.ts +0 -440
- package/src/contracts/openzeppelin/ERC20.ts +0 -330
- package/src/contracts/openzeppelin/ERC721.ts +0 -420
- package/src/contracts/openzeppelin/common.ts +0 -131
- package/src/contracts/openzeppelin/factories/ERC1155__factory.ts +0 -388
- package/src/contracts/openzeppelin/factories/ERC20__factory.ts +0 -353
- package/src/contracts/openzeppelin/factories/ERC721__factory.ts +0 -413
- package/src/contracts/openzeppelin/factories/index.ts +0 -6
- package/src/contracts/openzeppelin/index.ts +0 -10
- package/src/handlers/eth-send-transaction/eth-send-transaction.test.ts +0 -350
- package/src/handlers/eth-send-transaction/eth-send-transaction.ts +0 -183
- package/src/handlers/eth-send-transaction/schema.test.ts +0 -240
- package/src/handlers/eth-send-transaction/schema.ts +0 -20
- package/src/handlers/get-balances/evm-balance-service/get-erc20-balances.test.ts +0 -78
- package/src/handlers/get-balances/evm-balance-service/get-erc20-balances.ts +0 -87
- package/src/handlers/get-balances/evm-balance-service/get-native-token-balances.test.ts +0 -102
- package/src/handlers/get-balances/evm-balance-service/get-native-token-balances.ts +0 -54
- package/src/handlers/get-balances/get-balances.test.ts +0 -250
- package/src/handlers/get-balances/get-balances.ts +0 -107
- package/src/handlers/get-balances/glacier-balance-service/get-erc20-balances.test.ts +0 -76
- package/src/handlers/get-balances/glacier-balance-service/get-erc20-balances.ts +0 -110
- package/src/handlers/get-balances/glacier-balance-service/get-native-token-balances.test.ts +0 -61
- package/src/handlers/get-balances/glacier-balance-service/get-native-token-balances.ts +0 -46
- package/src/handlers/get-network-fee/get-network-fee.test.ts +0 -43
- package/src/handlers/get-network-fee/get-network-fee.ts +0 -59
- package/src/handlers/get-tokens/get-tokens.test.ts +0 -100
- package/src/handlers/get-tokens/get-tokens.ts +0 -18
- package/src/handlers/get-transaction-history/converters/etherscan-transaction-converter/convert-transaction-erc20.ts +0 -51
- package/src/handlers/get-transaction-history/converters/etherscan-transaction-converter/convert-transaction-normal.ts +0 -58
- package/src/handlers/get-transaction-history/converters/etherscan-transaction-converter/get-transaction-from-etherscan.test.ts +0 -116
- package/src/handlers/get-transaction-history/converters/etherscan-transaction-converter/get-transaction-from-etherscan.ts +0 -73
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/convert-transaction.ts +0 -47
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-nft-metadata.ts +0 -35
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-sender-info.ts +0 -38
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-tokens.ts +0 -107
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-transaction-from-glacier.test.ts +0 -191
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-transactions-from-glacier.ts +0 -62
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-tx-type.ts +0 -52
- package/src/handlers/get-transaction-history/get-transaction-history.test.ts +0 -53
- package/src/handlers/get-transaction-history/get-transaction-history.ts +0 -46
- package/src/handlers/get-transaction-history/utils/get-explorer-address-by-network.ts +0 -7
- package/src/handlers/get-transaction-history/utils/get-small-image-for-nft.ts +0 -16
- package/src/handlers/get-transaction-history/utils/ipfs-resolver-with-fallback.ts +0 -18
- package/src/handlers/get-transaction-history/utils/is-ethereum-chain-id.ts +0 -15
- package/src/handlers/get-transaction-history/utils/resolve.ts +0 -7
- package/src/module.ts +0 -105
- package/src/types.ts +0 -16
- package/src/utils/estimate-gas-limit.ts +0 -27
- package/src/utils/get-chain-id.ts +0 -12
- package/src/utils/get-nonce.ts +0 -11
- package/src/utils/get-provider.ts +0 -46
- package/src/utils/parse-erc20-transaction-type.ts +0 -21
- package/src/utils/transaction-simulation.ts +0 -227
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { NetworkFees } from '@avalabs/vm-module-types';
|
|
2
|
-
import { getProvider } from '../../utils/get-provider';
|
|
3
|
-
import { rpcErrors } from '@metamask/rpc-errors';
|
|
4
|
-
|
|
5
|
-
const DEFAULT_PRESETS = {
|
|
6
|
-
LOW: 1n,
|
|
7
|
-
MEDIUM: 4n,
|
|
8
|
-
HIGH: 6n,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const BASE_PRIORITY_FEE_WEI = 500000000n; //0.5 GWei
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Returns {@link NetworkFees} based on {@link DEFAULT_PRESETS} multipliers.
|
|
15
|
-
* @throws Error if provider does not support eip-1559
|
|
16
|
-
*/
|
|
17
|
-
export async function getNetworkFee({
|
|
18
|
-
chainId,
|
|
19
|
-
chainName,
|
|
20
|
-
rpcUrl,
|
|
21
|
-
multiContractAddress,
|
|
22
|
-
}: {
|
|
23
|
-
chainId: number;
|
|
24
|
-
chainName: string;
|
|
25
|
-
rpcUrl: string;
|
|
26
|
-
multiContractAddress?: string;
|
|
27
|
-
}): Promise<NetworkFees> {
|
|
28
|
-
const provider = getProvider({
|
|
29
|
-
chainId,
|
|
30
|
-
chainName,
|
|
31
|
-
rpcUrl,
|
|
32
|
-
multiContractAddress,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
const { maxFeePerGas: maxFeePerGasInWei } = await provider.getFeeData();
|
|
36
|
-
if (!maxFeePerGasInWei) {
|
|
37
|
-
throw rpcErrors.internal('Pre-EIP-1559 networks are not supported');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const lowMaxTip = BASE_PRIORITY_FEE_WEI * DEFAULT_PRESETS.LOW;
|
|
41
|
-
const mediumMaxTip = BASE_PRIORITY_FEE_WEI * DEFAULT_PRESETS.MEDIUM;
|
|
42
|
-
const highMaxTip = BASE_PRIORITY_FEE_WEI * DEFAULT_PRESETS.HIGH;
|
|
43
|
-
return {
|
|
44
|
-
baseFee: maxFeePerGasInWei,
|
|
45
|
-
low: {
|
|
46
|
-
maxFeePerGas: maxFeePerGasInWei + lowMaxTip,
|
|
47
|
-
maxPriorityFeePerGas: lowMaxTip,
|
|
48
|
-
},
|
|
49
|
-
medium: {
|
|
50
|
-
maxFeePerGas: maxFeePerGasInWei + mediumMaxTip,
|
|
51
|
-
maxPriorityFeePerGas: mediumMaxTip,
|
|
52
|
-
},
|
|
53
|
-
high: {
|
|
54
|
-
maxFeePerGas: maxFeePerGasInWei + highMaxTip,
|
|
55
|
-
maxPriorityFeePerGas: highMaxTip,
|
|
56
|
-
},
|
|
57
|
-
isFixedFee: false,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { getTokens } from './get-tokens';
|
|
2
|
-
|
|
3
|
-
const PROXY_API_URL = 'https://proxy-api.avax.network';
|
|
4
|
-
|
|
5
|
-
global.fetch = jest.fn();
|
|
6
|
-
|
|
7
|
-
describe('get-tokens', () => {
|
|
8
|
-
beforeAll(() => {
|
|
9
|
-
jest.clearAllMocks();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('should return an empty array if chain id is not for a valid network', async () => {
|
|
13
|
-
(global.fetch as jest.Mock).mockResolvedValueOnce({
|
|
14
|
-
ok: true,
|
|
15
|
-
json: async () => [],
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const result = await getTokens({ chainId: 0, proxyApiUrl: PROXY_API_URL });
|
|
19
|
-
|
|
20
|
-
expect(result).toEqual([]);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should return correct contract tokens for Avalanche C-Chain', async () => {
|
|
24
|
-
(global.fetch as jest.Mock).mockResolvedValueOnce({
|
|
25
|
-
ok: true,
|
|
26
|
-
json: async () => [
|
|
27
|
-
{
|
|
28
|
-
address: '0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7',
|
|
29
|
-
name: 'Wrapped AVAX',
|
|
30
|
-
symbol: 'WAVAX',
|
|
31
|
-
contractType: 'ERC-20',
|
|
32
|
-
chainId: 43114,
|
|
33
|
-
decimals: 18,
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
|
|
37
|
-
name: 'USD Coin',
|
|
38
|
-
symbol: 'USDC',
|
|
39
|
-
contractType: 'ERC-20',
|
|
40
|
-
chainId: 43114,
|
|
41
|
-
decimals: 6,
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const result = await getTokens({ chainId: 43114, proxyApiUrl: PROXY_API_URL });
|
|
47
|
-
|
|
48
|
-
expect(result.length).toBeGreaterThan(0);
|
|
49
|
-
expect(result.find((token) => token.symbol === 'WAVAX')).toBeDefined();
|
|
50
|
-
expect(result.find((token) => token.symbol === 'USDC')).toBeDefined();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should return correct contract tokens for Ethereum', async () => {
|
|
54
|
-
(global.fetch as jest.Mock).mockResolvedValueOnce({
|
|
55
|
-
ok: true,
|
|
56
|
-
json: async () => [
|
|
57
|
-
{
|
|
58
|
-
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
|
59
|
-
name: 'Tether USD',
|
|
60
|
-
symbol: 'USDT',
|
|
61
|
-
contractType: 'ERC-20',
|
|
62
|
-
chainId: 1,
|
|
63
|
-
decimals: 6,
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
67
|
-
name: 'USDCoin',
|
|
68
|
-
symbol: 'USDC',
|
|
69
|
-
contractType: 'ERC-20',
|
|
70
|
-
chainId: 1,
|
|
71
|
-
decimals: 6,
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
address: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599',
|
|
75
|
-
name: 'Wrapped BTC',
|
|
76
|
-
symbol: 'WBTC',
|
|
77
|
-
contractType: 'ERC-20',
|
|
78
|
-
chainId: 1,
|
|
79
|
-
decimals: 8,
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
address: '0x514910771AF9Ca656af840dff83E8264EcF986CA',
|
|
83
|
-
name: 'ChainLink Token',
|
|
84
|
-
symbol: 'LINK',
|
|
85
|
-
contractType: 'ERC-20',
|
|
86
|
-
chainId: 1,
|
|
87
|
-
decimals: 18,
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const result = await getTokens({ chainId: 1, proxyApiUrl: PROXY_API_URL });
|
|
93
|
-
|
|
94
|
-
expect(result.length).toBeGreaterThan(0);
|
|
95
|
-
expect(result.find((token) => token.symbol === 'USDT')).toBeDefined();
|
|
96
|
-
expect(result.find((token) => token.symbol === 'USDC')).toBeDefined();
|
|
97
|
-
expect(result.find((token) => token.symbol === 'WBTC')).toBeDefined();
|
|
98
|
-
expect(result.find((token) => token.symbol === 'LINK')).toBeDefined();
|
|
99
|
-
});
|
|
100
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { NetworkContractToken } from '@avalabs/vm-module-types';
|
|
2
|
-
import { rpcErrors } from '@metamask/rpc-errors';
|
|
3
|
-
|
|
4
|
-
export async function getTokens({
|
|
5
|
-
chainId,
|
|
6
|
-
proxyApiUrl,
|
|
7
|
-
}: {
|
|
8
|
-
chainId: number;
|
|
9
|
-
proxyApiUrl: string;
|
|
10
|
-
}): Promise<NetworkContractToken[]> {
|
|
11
|
-
const response = await fetch(`${proxyApiUrl}/tokens?evmChainId=${chainId}`);
|
|
12
|
-
|
|
13
|
-
if (!response.ok) {
|
|
14
|
-
throw rpcErrors.internal(`Failed to fetch tokens for chainId ${chainId}`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return response.json();
|
|
18
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { Erc20Tx } from '@avalabs/etherscan-sdk';
|
|
2
|
-
import { TokenType, TransactionType, type Transaction } from '@avalabs/vm-module-types';
|
|
3
|
-
import { balanceToDisplayValue } from '@avalabs/utils-sdk';
|
|
4
|
-
import { getExplorerAddressByNetwork } from '../../utils/get-explorer-address-by-network';
|
|
5
|
-
import { BN } from 'bn.js';
|
|
6
|
-
|
|
7
|
-
export function convertTransactionERC20({
|
|
8
|
-
tx,
|
|
9
|
-
address,
|
|
10
|
-
explorerUrl,
|
|
11
|
-
chainId,
|
|
12
|
-
}: {
|
|
13
|
-
tx: Erc20Tx;
|
|
14
|
-
address: string;
|
|
15
|
-
chainId: number;
|
|
16
|
-
explorerUrl: string;
|
|
17
|
-
}): Transaction {
|
|
18
|
-
const isSender = tx.from.toLowerCase() === address.toLowerCase();
|
|
19
|
-
const timestamp = parseInt(tx.timeStamp) * 1000;
|
|
20
|
-
const decimals = parseInt(tx.tokenDecimal);
|
|
21
|
-
const amountBN = new BN(tx.value);
|
|
22
|
-
const amountDisplayValue = balanceToDisplayValue(amountBN, decimals);
|
|
23
|
-
const { from, to, gasPrice, gasUsed, hash, tokenDecimal, tokenName, tokenSymbol } = tx;
|
|
24
|
-
const txType = isSender ? TransactionType.SEND : TransactionType.RECEIVE;
|
|
25
|
-
const explorerLink = getExplorerAddressByNetwork(explorerUrl, hash);
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
isIncoming: !isSender,
|
|
29
|
-
isOutgoing: isSender,
|
|
30
|
-
isContractCall: false,
|
|
31
|
-
timestamp,
|
|
32
|
-
hash,
|
|
33
|
-
isSender,
|
|
34
|
-
from,
|
|
35
|
-
to,
|
|
36
|
-
tokens: [
|
|
37
|
-
{
|
|
38
|
-
decimal: tokenDecimal,
|
|
39
|
-
name: tokenName,
|
|
40
|
-
symbol: tokenSymbol,
|
|
41
|
-
type: TokenType.ERC20,
|
|
42
|
-
amount: amountDisplayValue,
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
gasUsed,
|
|
46
|
-
gasPrice,
|
|
47
|
-
chainId: chainId.toString(),
|
|
48
|
-
txType,
|
|
49
|
-
explorerLink,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { NormalTx } from '@avalabs/etherscan-sdk';
|
|
2
|
-
import { TokenType, TransactionType, type NetworkToken, type Transaction } from '@avalabs/vm-module-types';
|
|
3
|
-
import { balanceToDisplayValue } from '@avalabs/utils-sdk';
|
|
4
|
-
import { BN } from 'bn.js';
|
|
5
|
-
import { getExplorerAddressByNetwork } from '../../utils/get-explorer-address-by-network';
|
|
6
|
-
|
|
7
|
-
export const convertTransactionNormal = ({
|
|
8
|
-
tx,
|
|
9
|
-
networkToken,
|
|
10
|
-
chainId,
|
|
11
|
-
explorerUrl,
|
|
12
|
-
address,
|
|
13
|
-
}: {
|
|
14
|
-
tx: NormalTx;
|
|
15
|
-
networkToken: NetworkToken;
|
|
16
|
-
chainId: number;
|
|
17
|
-
explorerUrl: string;
|
|
18
|
-
address: string;
|
|
19
|
-
}): Transaction => {
|
|
20
|
-
const isSender = tx.from.toLowerCase() === address.toLowerCase();
|
|
21
|
-
const timestamp = parseInt(tx.timeStamp) * 1000;
|
|
22
|
-
const decimals = networkToken.decimals;
|
|
23
|
-
const amountBN = new BN(tx.value);
|
|
24
|
-
const amountDisplayValue = balanceToDisplayValue(amountBN, decimals);
|
|
25
|
-
const txType = isSender ? TransactionType.SEND : TransactionType.RECEIVE;
|
|
26
|
-
|
|
27
|
-
const { from, to, gasPrice, gasUsed, hash } = tx;
|
|
28
|
-
const explorerLink = getExplorerAddressByNetwork(explorerUrl, hash);
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
isIncoming: !isSender,
|
|
32
|
-
isOutgoing: isSender,
|
|
33
|
-
isContractCall: isContractCall(tx),
|
|
34
|
-
timestamp,
|
|
35
|
-
hash,
|
|
36
|
-
isSender,
|
|
37
|
-
from,
|
|
38
|
-
to,
|
|
39
|
-
tokens: [
|
|
40
|
-
{
|
|
41
|
-
decimal: decimals.toString(),
|
|
42
|
-
name: networkToken.name,
|
|
43
|
-
symbol: networkToken.symbol,
|
|
44
|
-
amount: amountDisplayValue,
|
|
45
|
-
type: TokenType.NATIVE,
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
gasUsed,
|
|
49
|
-
gasPrice,
|
|
50
|
-
chainId: chainId.toString(),
|
|
51
|
-
txType,
|
|
52
|
-
explorerLink,
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
function isContractCall(tx: NormalTx): boolean {
|
|
57
|
-
return tx.input !== '0x';
|
|
58
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { TokenType } from '@avalabs/vm-module-types';
|
|
2
|
-
import { getTransactionFromEtherscan } from './get-transaction-from-etherscan';
|
|
3
|
-
import type { Erc20Tx, NormalTx } from '@avalabs/etherscan-sdk';
|
|
4
|
-
|
|
5
|
-
const mockNormalTxs: NormalTx[] = [
|
|
6
|
-
{
|
|
7
|
-
blockNumber: 'blockNumber',
|
|
8
|
-
timeStamp: 'timeStamp',
|
|
9
|
-
hash: 'normalTxHash',
|
|
10
|
-
nonce: 'nonce',
|
|
11
|
-
blockHash: 'blockHash',
|
|
12
|
-
transactionIndex: 'transactionIndex',
|
|
13
|
-
from: 'from',
|
|
14
|
-
to: 'to',
|
|
15
|
-
value: '1',
|
|
16
|
-
gas: '1',
|
|
17
|
-
gasPrice: '1',
|
|
18
|
-
isError: 'isError',
|
|
19
|
-
txreceipt_status: 'txreceipt_status',
|
|
20
|
-
input: 'input',
|
|
21
|
-
contractAddress: 'contractAddress',
|
|
22
|
-
cumulativeGasUsed: '1',
|
|
23
|
-
gasUsed: '1',
|
|
24
|
-
confirmations: 'confirmations',
|
|
25
|
-
},
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
const mockErc20Txs: Erc20Tx[] = [
|
|
29
|
-
{
|
|
30
|
-
blockNumber: 'blockNumber',
|
|
31
|
-
timeStamp: 'timeStamp',
|
|
32
|
-
hash: 'erc20Hash',
|
|
33
|
-
nonce: 'nonce',
|
|
34
|
-
blockHash: 'blockHash',
|
|
35
|
-
from: 'from',
|
|
36
|
-
contractAddress: 'contractAddress',
|
|
37
|
-
to: 'to',
|
|
38
|
-
value: '1',
|
|
39
|
-
tokenName: 'tokenName',
|
|
40
|
-
tokenSymbol: 'tokenSymbol',
|
|
41
|
-
tokenDecimal: '1',
|
|
42
|
-
transactionIndex: 'transactionIndex',
|
|
43
|
-
gas: '1',
|
|
44
|
-
gasPrice: '1',
|
|
45
|
-
input: 'input',
|
|
46
|
-
cumulativeGasUsed: '1',
|
|
47
|
-
gasUsed: '1',
|
|
48
|
-
confirmations: 'confirmations',
|
|
49
|
-
},
|
|
50
|
-
];
|
|
51
|
-
// const mockTransactions = jest.fn();
|
|
52
|
-
jest.mock('@avalabs/etherscan-sdk', () => ({
|
|
53
|
-
getNormalTxs: () => mockNormalTxs,
|
|
54
|
-
getErc20Txs: () => mockErc20Txs,
|
|
55
|
-
}));
|
|
56
|
-
|
|
57
|
-
describe('get-transaction-from-etherscan', () => {
|
|
58
|
-
it('should have returned 1 normal transaction and 1 erc20 transaction', async () => {
|
|
59
|
-
const result = await getTransactionFromEtherscan({
|
|
60
|
-
isTestnet: false,
|
|
61
|
-
chainId: 1,
|
|
62
|
-
networkToken: {
|
|
63
|
-
name: 'networkToken',
|
|
64
|
-
symbol: 'networkToken',
|
|
65
|
-
decimals: 1,
|
|
66
|
-
description: 'description',
|
|
67
|
-
logoUri: 'logoUri',
|
|
68
|
-
},
|
|
69
|
-
explorerUrl: 'explorerUrl',
|
|
70
|
-
address: 'address',
|
|
71
|
-
nextPageToken: '',
|
|
72
|
-
offset: 1,
|
|
73
|
-
});
|
|
74
|
-
expect(result.transactions.length).toEqual(2);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should have returned 1 normal if nextPageToken contains only normal', async () => {
|
|
78
|
-
const result = await getTransactionFromEtherscan({
|
|
79
|
-
isTestnet: false,
|
|
80
|
-
chainId: 1,
|
|
81
|
-
networkToken: {
|
|
82
|
-
name: 'networkToken',
|
|
83
|
-
symbol: 'networkToken',
|
|
84
|
-
decimals: 1,
|
|
85
|
-
description: 'description',
|
|
86
|
-
logoUri: 'logoUri',
|
|
87
|
-
},
|
|
88
|
-
explorerUrl: 'explorerUrl',
|
|
89
|
-
address: 'address',
|
|
90
|
-
nextPageToken: JSON.stringify({ page: 1, queries: ['normal'] }),
|
|
91
|
-
offset: 1,
|
|
92
|
-
});
|
|
93
|
-
expect(result.transactions.length).toEqual(1);
|
|
94
|
-
expect(result.transactions[0]?.tokens[0]?.type).toEqual(TokenType.NATIVE);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('should have returned 1 erc20 if nextPageToken contains only erc20', async () => {
|
|
98
|
-
const result = await getTransactionFromEtherscan({
|
|
99
|
-
isTestnet: false,
|
|
100
|
-
chainId: 1,
|
|
101
|
-
networkToken: {
|
|
102
|
-
name: 'networkToken',
|
|
103
|
-
symbol: 'networkToken',
|
|
104
|
-
decimals: 1,
|
|
105
|
-
description: 'description',
|
|
106
|
-
logoUri: 'logoUri',
|
|
107
|
-
},
|
|
108
|
-
explorerUrl: 'explorerUrl',
|
|
109
|
-
address: 'address',
|
|
110
|
-
nextPageToken: JSON.stringify({ page: 1, queries: ['erc20'] }),
|
|
111
|
-
offset: 1,
|
|
112
|
-
});
|
|
113
|
-
expect(result.transactions.length).toEqual(1);
|
|
114
|
-
expect(result.transactions[0]?.tokens[0]?.type).toEqual(TokenType.ERC20);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { convertTransactionNormal } from './convert-transaction-normal';
|
|
2
|
-
import { convertTransactionERC20 } from './convert-transaction-erc20';
|
|
3
|
-
import type { NetworkToken, TransactionHistoryResponse } from '@avalabs/vm-module-types';
|
|
4
|
-
import { getErc20Txs, getNormalTxs } from '@avalabs/etherscan-sdk';
|
|
5
|
-
|
|
6
|
-
interface EtherscanPagination {
|
|
7
|
-
queries: ('normal' | 'erc20')[];
|
|
8
|
-
page?: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const getTransactionFromEtherscan = async ({
|
|
12
|
-
isTestnet,
|
|
13
|
-
networkToken,
|
|
14
|
-
explorerUrl,
|
|
15
|
-
chainId,
|
|
16
|
-
address,
|
|
17
|
-
nextPageToken,
|
|
18
|
-
offset,
|
|
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> => {
|
|
28
|
-
/*
|
|
29
|
-
Using JSON for nextPageToken because this function is managing both the Normal
|
|
30
|
-
and ERC20 queries. It encodes the current page and the queries that should be
|
|
31
|
-
run. For example, if 'normal' has no more records to fetch then it will be
|
|
32
|
-
excluded from the list and the JSON will be something like:
|
|
33
|
-
{ page: 3, queries: ['erc20'] }
|
|
34
|
-
*/
|
|
35
|
-
const parsedPageToken = nextPageToken ? (JSON.parse(nextPageToken) as EtherscanPagination) : undefined;
|
|
36
|
-
const page = parsedPageToken?.page || 1;
|
|
37
|
-
const queries = parsedPageToken?.queries || ['normal', 'erc20'];
|
|
38
|
-
|
|
39
|
-
const normalHist = (queries.includes('normal') ? await getNormalTxs(address, !isTestnet, { page, offset }) : []).map(
|
|
40
|
-
(tx) => convertTransactionNormal({ tx, chainId, networkToken, explorerUrl, address }),
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
const erc20Hist = (
|
|
44
|
-
queries.includes('erc20')
|
|
45
|
-
? await getErc20Txs(address, !isTestnet, undefined, {
|
|
46
|
-
page,
|
|
47
|
-
offset,
|
|
48
|
-
})
|
|
49
|
-
: []
|
|
50
|
-
).map((tx) =>
|
|
51
|
-
convertTransactionERC20({
|
|
52
|
-
tx,
|
|
53
|
-
address,
|
|
54
|
-
explorerUrl,
|
|
55
|
-
chainId,
|
|
56
|
-
}),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
// Filter erc20 transactions from normal tx list
|
|
60
|
-
const erc20TxHashes = erc20Hist.map((tx) => tx.hash);
|
|
61
|
-
const filteredNormalTxs = normalHist.filter((tx) => {
|
|
62
|
-
return !erc20TxHashes.includes(tx.hash);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const next: EtherscanPagination = { queries: [], page: page + 1 };
|
|
66
|
-
if (normalHist.length) next.queries.push('normal');
|
|
67
|
-
if (erc20Hist.length) next.queries.push('erc20');
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
transactions: [...filteredNormalTxs, ...erc20Hist],
|
|
71
|
-
nextPageToken: next.queries.length ? JSON.stringify(next) : '', // stop pagination
|
|
72
|
-
};
|
|
73
|
-
};
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { Transaction, NetworkToken } from '@avalabs/vm-module-types';
|
|
2
|
-
import { getTxType } from './get-tx-type';
|
|
3
|
-
import { getSenderInfo } from './get-sender-info';
|
|
4
|
-
import { getTokens } from './get-tokens';
|
|
5
|
-
import { getExplorerAddressByNetwork } from '../../utils/get-explorer-address-by-network';
|
|
6
|
-
import type { TransactionDetails } from '@avalabs/glacier-sdk';
|
|
7
|
-
import { NonContractCallTypes } from '../../../../types';
|
|
8
|
-
|
|
9
|
-
type ConvertTransactionParams = {
|
|
10
|
-
transactions: TransactionDetails;
|
|
11
|
-
explorerUrl: string;
|
|
12
|
-
networkToken: NetworkToken;
|
|
13
|
-
chainId: number;
|
|
14
|
-
address: string;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const convertTransaction = async ({
|
|
18
|
-
transactions,
|
|
19
|
-
explorerUrl,
|
|
20
|
-
networkToken,
|
|
21
|
-
chainId,
|
|
22
|
-
address,
|
|
23
|
-
}: ConvertTransactionParams): Promise<Transaction> => {
|
|
24
|
-
const tokens = await getTokens(transactions, networkToken);
|
|
25
|
-
const txType = getTxType(transactions, address, tokens);
|
|
26
|
-
const { isOutgoing, isIncoming, isSender, from, to } = getSenderInfo(txType, transactions, address);
|
|
27
|
-
const { blockTimestamp, txHash: hash, gasPrice, gasUsed } = transactions.nativeTransaction;
|
|
28
|
-
const explorerLink = getExplorerAddressByNetwork(explorerUrl, hash);
|
|
29
|
-
const isContractCall = !NonContractCallTypes.includes(txType);
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
isContractCall,
|
|
33
|
-
isIncoming,
|
|
34
|
-
isOutgoing,
|
|
35
|
-
isSender,
|
|
36
|
-
timestamp: blockTimestamp * 1000, // s to ms
|
|
37
|
-
hash,
|
|
38
|
-
from,
|
|
39
|
-
to,
|
|
40
|
-
tokens,
|
|
41
|
-
gasPrice,
|
|
42
|
-
gasUsed,
|
|
43
|
-
chainId: chainId.toString(),
|
|
44
|
-
txType,
|
|
45
|
-
explorerLink,
|
|
46
|
-
};
|
|
47
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { ipfsResolverWithFallback } from '../../utils/ipfs-resolver-with-fallback';
|
|
2
|
-
|
|
3
|
-
interface NftMetadata {
|
|
4
|
-
attributes?: string;
|
|
5
|
-
name?: string;
|
|
6
|
-
image?: string;
|
|
7
|
-
description?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async function fetchWithTimeout(uri: string, timeout = 5000) {
|
|
11
|
-
const controller = new AbortController();
|
|
12
|
-
setTimeout(() => controller.abort(), timeout);
|
|
13
|
-
|
|
14
|
-
return fetch(uri, { signal: controller.signal });
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function getNftMetadata(tokenUri: string) {
|
|
18
|
-
let data: NftMetadata = {};
|
|
19
|
-
if (!tokenUri) {
|
|
20
|
-
return {};
|
|
21
|
-
} else if (tokenUri.startsWith('data:application/json;base64,')) {
|
|
22
|
-
const value = tokenUri.substring(29);
|
|
23
|
-
try {
|
|
24
|
-
const json = Buffer.from(value, 'base64').toString();
|
|
25
|
-
data = JSON.parse(json);
|
|
26
|
-
} catch {
|
|
27
|
-
data = {};
|
|
28
|
-
}
|
|
29
|
-
} else {
|
|
30
|
-
data = await fetchWithTimeout(ipfsResolverWithFallback(tokenUri))
|
|
31
|
-
.then((r) => r.json())
|
|
32
|
-
.catch(() => ({}));
|
|
33
|
-
}
|
|
34
|
-
return data;
|
|
35
|
-
}
|
package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-sender-info.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { TransactionDetails } from '@avalabs/glacier-sdk';
|
|
2
|
-
import { TransactionType } from '@avalabs/vm-module-types';
|
|
3
|
-
|
|
4
|
-
export const getSenderInfo = (
|
|
5
|
-
txType: TransactionType,
|
|
6
|
-
{ nativeTransaction, erc20Transfers, erc721Transfers }: TransactionDetails,
|
|
7
|
-
address: string,
|
|
8
|
-
): { isOutgoing: boolean; isIncoming: boolean; isSender: boolean; from: string; to: string } => {
|
|
9
|
-
const isTransfer = txType === TransactionType.TRANSFER;
|
|
10
|
-
const isNativeSend = txType === TransactionType.SEND;
|
|
11
|
-
const isNativeReceive = txType === TransactionType.RECEIVE;
|
|
12
|
-
let from = nativeTransaction?.from?.address;
|
|
13
|
-
let to = nativeTransaction?.to?.address;
|
|
14
|
-
|
|
15
|
-
// Until multi tokens transaction is supported in UI, using from and to of the only token is helpful for UI
|
|
16
|
-
if (isTransfer && erc20Transfers && erc20Transfers[0]) {
|
|
17
|
-
from = erc20Transfers[0].from.address;
|
|
18
|
-
to = erc20Transfers[0].to.address;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (isTransfer && erc721Transfers && erc721Transfers[0]) {
|
|
22
|
-
from = erc721Transfers[0].from.address;
|
|
23
|
-
to = erc721Transfers[0].to.address;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const isOutgoing = isNativeSend || (isTransfer && from.toLowerCase() === address.toLowerCase());
|
|
27
|
-
const isIncoming = isNativeReceive || (isTransfer && to.toLowerCase() === address.toLowerCase());
|
|
28
|
-
|
|
29
|
-
const isSender = from === address;
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
isOutgoing,
|
|
33
|
-
isIncoming,
|
|
34
|
-
isSender,
|
|
35
|
-
from,
|
|
36
|
-
to,
|
|
37
|
-
};
|
|
38
|
-
};
|