@avalabs/evm-module 0.0.13 → 0.0.16
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 +32 -8
- package/CHANGELOG.md +27 -0
- package/dist/index.cjs +29 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -6
- package/dist/index.d.ts +10 -6
- package/dist/index.js +27 -8
- package/dist/index.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +16 -9
- package/src/contracts/openzeppelin/ERC1155.ts +440 -0
- package/src/contracts/openzeppelin/ERC20.ts +330 -0
- package/src/contracts/openzeppelin/ERC721.ts +420 -0
- package/src/contracts/openzeppelin/common.ts +131 -0
- package/src/contracts/openzeppelin/factories/ERC1155__factory.ts +388 -0
- package/src/contracts/openzeppelin/factories/ERC20__factory.ts +353 -0
- package/src/contracts/openzeppelin/factories/ERC721__factory.ts +413 -0
- package/src/contracts/openzeppelin/factories/index.ts +6 -0
- package/src/contracts/openzeppelin/index.ts +10 -0
- package/src/handlers/eth-send-transaction/eth-send-transaction.test.ts +3 -3
- package/src/handlers/eth-send-transaction/eth-send-transaction.ts +4 -4
- package/src/handlers/eth-sign/eth-sign.test.ts +217 -0
- package/src/handlers/eth-sign/eth-sign.ts +137 -0
- package/src/handlers/eth-sign/schemas/eth-sign-typed-data.ts +65 -0
- package/src/handlers/eth-sign/schemas/eth-sign.ts +9 -0
- package/src/handlers/eth-sign/schemas/parse-request-params/fixture.ts +47 -0
- package/src/handlers/eth-sign/schemas/parse-request-params/parse-request-params.test.ts +284 -0
- package/src/handlers/eth-sign/schemas/parse-request-params/parse-request-params.ts +94 -0
- package/src/handlers/eth-sign/schemas/parse-request-params.ts +90 -0
- package/src/handlers/eth-sign/schemas/personal-sign.ts +12 -0
- package/src/handlers/eth-sign/schemas/shared.ts +5 -0
- package/src/handlers/eth-sign/utils/beautify-message/beautify-message.test.ts +29 -0
- package/src/handlers/eth-sign/utils/beautify-message/beautify-message.ts +134 -0
- package/src/handlers/eth-sign/utils/is-typed-data-valid.ts +26 -0
- package/src/handlers/eth-sign/utils/typeguards.ts +10 -0
- package/src/handlers/get-balances/evm-balance-service/get-erc20-balances.test.ts +78 -0
- package/src/handlers/get-balances/evm-balance-service/get-erc20-balances.ts +85 -0
- package/src/handlers/get-balances/evm-balance-service/get-native-token-balances.test.ts +102 -0
- package/src/handlers/get-balances/evm-balance-service/get-native-token-balances.ts +54 -0
- package/src/handlers/get-balances/get-balances.test.ts +252 -0
- package/src/handlers/get-balances/get-balances.ts +109 -0
- package/src/handlers/get-balances/glacier-balance-service/get-erc20-balances.test.ts +76 -0
- package/src/handlers/get-balances/glacier-balance-service/get-erc20-balances.ts +107 -0
- package/src/handlers/get-balances/glacier-balance-service/get-native-token-balances.test.ts +61 -0
- package/src/handlers/get-balances/glacier-balance-service/get-native-token-balances.ts +46 -0
- package/src/handlers/get-network-fee/get-network-fee.test.ts +0 -1
- package/src/handlers/get-network-fee/get-network-fee.ts +0 -1
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-transaction-from-glacier.test.ts +72 -59
- package/src/handlers/get-transaction-history/converters/evm-transaction-converter/get-transactions-from-glacier.ts +4 -11
- package/src/handlers/get-transaction-history/get-transaction-history.test.ts +7 -2
- package/src/handlers/get-transaction-history/get-transaction-history.ts +13 -3
- package/src/index.ts +1 -0
- package/src/module.ts +29 -7
- package/src/services/glacier-service/glacier-service.ts +259 -0
- package/tsconfig.json +7 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { BN } from 'bn.js';
|
|
2
|
+
import { getErc20Balances } from './get-erc20-balances';
|
|
3
|
+
import type { EvmGlacierService } from '../../../services/glacier-service/glacier-service';
|
|
4
|
+
|
|
5
|
+
describe('get-erc20-balances', () => {
|
|
6
|
+
it('should return erc20 token balances', async () => {
|
|
7
|
+
const mockGlacierService: EvmGlacierService = {
|
|
8
|
+
...expect.any(Object),
|
|
9
|
+
listErc20Balances: jest.fn().mockResolvedValue({
|
|
10
|
+
erc20TokenBalances: [
|
|
11
|
+
{
|
|
12
|
+
address: '0x123',
|
|
13
|
+
name: 'Ethereum',
|
|
14
|
+
symbol: 'ETH',
|
|
15
|
+
decimals: 18,
|
|
16
|
+
logoUri: 'https://example.com/logo.png',
|
|
17
|
+
ercType: 'ERC20',
|
|
18
|
+
price: {
|
|
19
|
+
currency: 'USD',
|
|
20
|
+
value: 1000,
|
|
21
|
+
},
|
|
22
|
+
chainId: '123',
|
|
23
|
+
balance: '1000000000000000000',
|
|
24
|
+
balanceValue: {
|
|
25
|
+
currency: 'USD',
|
|
26
|
+
value: 1000,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
const balance = getErc20Balances({
|
|
33
|
+
glacierService: mockGlacierService,
|
|
34
|
+
currency: 'USD',
|
|
35
|
+
chainId: 123,
|
|
36
|
+
address: '0x123',
|
|
37
|
+
customTokens: [],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(balance).resolves.toEqual({
|
|
41
|
+
'0x123': {
|
|
42
|
+
chainId: 123,
|
|
43
|
+
address: '0x123',
|
|
44
|
+
name: 'Ethereum',
|
|
45
|
+
symbol: 'ETH',
|
|
46
|
+
decimals: 18,
|
|
47
|
+
logoUri: 'https://example.com/logo.png',
|
|
48
|
+
balance: new BN('1000000000000000000'),
|
|
49
|
+
balanceCurrencyDisplayValue: '1000',
|
|
50
|
+
balanceDisplayValue: '1',
|
|
51
|
+
balanceInCurrency: 1000,
|
|
52
|
+
priceInCurrency: 1000,
|
|
53
|
+
contractType: 'ERC-20',
|
|
54
|
+
type: 'ERC20',
|
|
55
|
+
change24: 0,
|
|
56
|
+
marketCap: 0,
|
|
57
|
+
vol24: 0,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should return native token object without balance data', async () => {
|
|
63
|
+
const mockGlacierService: EvmGlacierService = {
|
|
64
|
+
...expect.any(Object),
|
|
65
|
+
listErc20Balances: jest.fn().mockRejectedValue(new Error('Failed to get erc20 balance')),
|
|
66
|
+
};
|
|
67
|
+
const balance = getErc20Balances({
|
|
68
|
+
glacierService: mockGlacierService,
|
|
69
|
+
currency: 'USD',
|
|
70
|
+
chainId: 123,
|
|
71
|
+
address: '0x123',
|
|
72
|
+
customTokens: [],
|
|
73
|
+
});
|
|
74
|
+
expect(balance).rejects.toEqual(new Error('Failed to get erc20 balance'));
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { balanceToDisplayValue, bnToBig } from '@avalabs/utils-sdk';
|
|
2
|
+
import {
|
|
3
|
+
TokenType,
|
|
4
|
+
type TokenWithBalanceERC20,
|
|
5
|
+
type NetworkContractToken,
|
|
6
|
+
type TokenWithBalance,
|
|
7
|
+
} from '@avalabs/vm-module-types';
|
|
8
|
+
import { CurrencyCode, Erc20TokenBalance } from '@avalabs/glacier-sdk';
|
|
9
|
+
import BN from 'bn.js';
|
|
10
|
+
import type { EvmGlacierService } from '../../../services/glacier-service/glacier-service';
|
|
11
|
+
|
|
12
|
+
export const getErc20Balances = async ({
|
|
13
|
+
glacierService,
|
|
14
|
+
currency,
|
|
15
|
+
chainId,
|
|
16
|
+
address,
|
|
17
|
+
customTokens,
|
|
18
|
+
}: {
|
|
19
|
+
glacierService: EvmGlacierService;
|
|
20
|
+
address: string;
|
|
21
|
+
currency: string;
|
|
22
|
+
chainId: number;
|
|
23
|
+
customTokens: NetworkContractToken[];
|
|
24
|
+
}): Promise<Record<string, TokenWithBalance>> => {
|
|
25
|
+
const tokensWithBalance: TokenWithBalanceERC20[] = [];
|
|
26
|
+
/**
|
|
27
|
+
* Load all pages to make sure we have all the tokens with balances
|
|
28
|
+
*/
|
|
29
|
+
let nextPageToken: string | undefined;
|
|
30
|
+
do {
|
|
31
|
+
const response = await glacierService.listErc20Balances({
|
|
32
|
+
chainId: chainId.toString(),
|
|
33
|
+
address,
|
|
34
|
+
currency: currency.toLocaleLowerCase() as CurrencyCode,
|
|
35
|
+
// glacier has a cap on page size of 100
|
|
36
|
+
pageSize: 100,
|
|
37
|
+
pageToken: nextPageToken,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
tokensWithBalance.push(...convertErc20ToTokenWithBalance(response.erc20TokenBalances, Number(chainId)));
|
|
41
|
+
nextPageToken = response.nextPageToken;
|
|
42
|
+
} while (nextPageToken);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Glacier doesnt return tokens without balances so we need to polyfill that list
|
|
46
|
+
* from our own list of tokens. We just set the balance to 0, these zero balance
|
|
47
|
+
* tokens are only used for swap, bridge and tx parsing.
|
|
48
|
+
*/
|
|
49
|
+
return [
|
|
50
|
+
...convertNetworkTokenToTokenWithBalance(customTokens),
|
|
51
|
+
...tokensWithBalance, // this needs to be second in the list so it overwrites its zero balance counterpart if there is one
|
|
52
|
+
].reduce(
|
|
53
|
+
(acc, token) => {
|
|
54
|
+
return { ...acc, [token.address.toLowerCase()]: token };
|
|
55
|
+
},
|
|
56
|
+
{} as Record<string, TokenWithBalance>,
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const convertNetworkTokenToTokenWithBalance = (tokens: NetworkContractToken[]): TokenWithBalanceERC20[] => {
|
|
61
|
+
return tokens.map((token) => {
|
|
62
|
+
return {
|
|
63
|
+
...token,
|
|
64
|
+
type: TokenType.ERC20,
|
|
65
|
+
balance: new BN(0),
|
|
66
|
+
balanceInCurrency: 0,
|
|
67
|
+
balanceDisplayValue: '0',
|
|
68
|
+
balanceCurrencyDisplayValue: '0',
|
|
69
|
+
priceInCurrency: 0,
|
|
70
|
+
marketCap: 0,
|
|
71
|
+
change24: 0,
|
|
72
|
+
vol24: 0,
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const convertErc20ToTokenWithBalance = (
|
|
78
|
+
tokenBalances: Erc20TokenBalance[],
|
|
79
|
+
chainId: number,
|
|
80
|
+
): TokenWithBalanceERC20[] => {
|
|
81
|
+
return tokenBalances.map((token: Erc20TokenBalance): TokenWithBalanceERC20 => {
|
|
82
|
+
const balance = new BN(token.balance);
|
|
83
|
+
const balanceDisplayValue = balanceToDisplayValue(balance, token.decimals);
|
|
84
|
+
const balanceCurrencyDisplayValue = token.balanceValue?.value.toString() ?? '0';
|
|
85
|
+
const priceInCurrency = token.price?.value ?? 0;
|
|
86
|
+
const balanceInCurrency = bnToBig(balance, token.decimals).mul(priceInCurrency).toNumber();
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
chainId,
|
|
90
|
+
address: token.address,
|
|
91
|
+
name: token.name,
|
|
92
|
+
symbol: token.symbol,
|
|
93
|
+
decimals: token.decimals,
|
|
94
|
+
logoUri: token.logoUri,
|
|
95
|
+
balance,
|
|
96
|
+
balanceCurrencyDisplayValue,
|
|
97
|
+
balanceDisplayValue,
|
|
98
|
+
balanceInCurrency,
|
|
99
|
+
priceInCurrency,
|
|
100
|
+
contractType: 'ERC-20',
|
|
101
|
+
type: TokenType.ERC20,
|
|
102
|
+
change24: 0,
|
|
103
|
+
marketCap: 0,
|
|
104
|
+
vol24: 0,
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BN } from 'bn.js';
|
|
2
|
+
import { getNativeTokenBalances } from './get-native-token-balances';
|
|
3
|
+
import type { EvmGlacierService } from '../../../services/glacier-service/glacier-service';
|
|
4
|
+
|
|
5
|
+
describe('get-native-token-balances', () => {
|
|
6
|
+
it('should return native token balances', async () => {
|
|
7
|
+
const mockGlacierService: EvmGlacierService = {
|
|
8
|
+
...expect.any(Object),
|
|
9
|
+
getNativeBalance: jest.fn().mockResolvedValue({
|
|
10
|
+
nativeTokenBalance: {
|
|
11
|
+
balance: new BN('1000000000000000000'),
|
|
12
|
+
decimals: 18,
|
|
13
|
+
name: 'Ethereum',
|
|
14
|
+
symbol: 'ETH',
|
|
15
|
+
price: {
|
|
16
|
+
value: 1000,
|
|
17
|
+
},
|
|
18
|
+
logoUri: 'https://example.com/logo.png',
|
|
19
|
+
},
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const balance = getNativeTokenBalances({
|
|
24
|
+
address: '0x123',
|
|
25
|
+
currency: 'USD',
|
|
26
|
+
chainId: 123,
|
|
27
|
+
glacierService: mockGlacierService,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect(balance).resolves.toEqual({
|
|
31
|
+
name: 'Ethereum',
|
|
32
|
+
symbol: 'ETH',
|
|
33
|
+
decimals: 18,
|
|
34
|
+
type: 'NATIVE',
|
|
35
|
+
logoUri: 'https://example.com/logo.png',
|
|
36
|
+
balance: new BN('1000000000000000000'),
|
|
37
|
+
balanceDisplayValue: '1',
|
|
38
|
+
balanceInCurrency: 1000,
|
|
39
|
+
balanceCurrencyDisplayValue: '1000.00',
|
|
40
|
+
priceInCurrency: 1000,
|
|
41
|
+
marketCap: 0,
|
|
42
|
+
vol24: 0,
|
|
43
|
+
change24: 0,
|
|
44
|
+
coingeckoId: '',
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should return native token object without balance data', async () => {
|
|
49
|
+
const mockGlacierService: EvmGlacierService = {
|
|
50
|
+
...expect.any(Object),
|
|
51
|
+
getNativeBalance: jest.fn().mockRejectedValue(new Error('Failed to get native balance')),
|
|
52
|
+
};
|
|
53
|
+
const balance = getNativeTokenBalances({
|
|
54
|
+
address: '0x123',
|
|
55
|
+
currency: 'USD',
|
|
56
|
+
chainId: 123,
|
|
57
|
+
glacierService: mockGlacierService,
|
|
58
|
+
});
|
|
59
|
+
expect(balance).rejects.toEqual(new Error('Failed to get native balance'));
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { CurrencyCode } from '@avalabs/glacier-sdk';
|
|
2
|
+
import { TokenType, type NetworkTokenWithBalance } from '@avalabs/vm-module-types';
|
|
3
|
+
import { balanceToDisplayValue, bnToBig } from '@avalabs/utils-sdk';
|
|
4
|
+
import { BN } from 'bn.js';
|
|
5
|
+
import type { EvmGlacierService } from '../../../services/glacier-service/glacier-service';
|
|
6
|
+
|
|
7
|
+
export const getNativeTokenBalances = async ({
|
|
8
|
+
address,
|
|
9
|
+
currency,
|
|
10
|
+
chainId,
|
|
11
|
+
glacierService,
|
|
12
|
+
}: {
|
|
13
|
+
chainId: number;
|
|
14
|
+
address: string;
|
|
15
|
+
currency: string;
|
|
16
|
+
glacierService: EvmGlacierService;
|
|
17
|
+
}): Promise<NetworkTokenWithBalance> => {
|
|
18
|
+
const nativeBalance = await glacierService.getNativeBalance({
|
|
19
|
+
chainId: chainId.toString(),
|
|
20
|
+
address,
|
|
21
|
+
currency: currency.toLocaleLowerCase() as CurrencyCode,
|
|
22
|
+
});
|
|
23
|
+
const nativeTokenBalance = nativeBalance.nativeTokenBalance;
|
|
24
|
+
const balance = new BN(nativeTokenBalance.balance);
|
|
25
|
+
const balanceDisplayValue = balanceToDisplayValue(balance, nativeTokenBalance.decimals);
|
|
26
|
+
const priceInCurrency = nativeTokenBalance.price?.value ?? 0;
|
|
27
|
+
const balanceInCurrency = bnToBig(balance, nativeTokenBalance.decimals).mul(priceInCurrency).toNumber();
|
|
28
|
+
const balanceCurrencyDisplayValue = balanceInCurrency.toFixed(2);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
name: nativeTokenBalance.name,
|
|
32
|
+
symbol: nativeTokenBalance.symbol,
|
|
33
|
+
decimals: nativeTokenBalance.decimals,
|
|
34
|
+
type: TokenType.NATIVE,
|
|
35
|
+
logoUri: nativeTokenBalance.logoUri,
|
|
36
|
+
balance,
|
|
37
|
+
balanceDisplayValue,
|
|
38
|
+
balanceInCurrency,
|
|
39
|
+
balanceCurrencyDisplayValue,
|
|
40
|
+
priceInCurrency,
|
|
41
|
+
marketCap: 0,
|
|
42
|
+
vol24: 0,
|
|
43
|
+
change24: 0,
|
|
44
|
+
coingeckoId: '',
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -2,7 +2,6 @@ import { getNetworkFee } from './get-network-fee';
|
|
|
2
2
|
import { FeeData, JsonRpcProvider } from 'ethers';
|
|
3
3
|
|
|
4
4
|
const params = {
|
|
5
|
-
glacierApiUrl: 'https://glacier-api.avax.network',
|
|
6
5
|
chainId: 1,
|
|
7
6
|
chainName: 'Ethereum Mainnet',
|
|
8
7
|
rpcUrl: 'https://mainnet.infura.io/v3/1234567890',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ListTransactionDetailsResponse } from '@avalabs/glacier-sdk';
|
|
2
2
|
import { getTransactionsFromGlacier } from './get-transactions-from-glacier';
|
|
3
|
+
import { EvmGlacierService } from '../../../../services/glacier-service/glacier-service';
|
|
3
4
|
|
|
4
5
|
const mockListTransactionDetailsResponse: ListTransactionDetailsResponse = {
|
|
5
6
|
nextPageToken: 'nextPageToken',
|
|
@@ -29,43 +30,16 @@ const mockListTransactionDetailsResponse: ListTransactionDetailsResponse = {
|
|
|
29
30
|
],
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
const mockListTransactions = jest.fn();
|
|
33
|
-
jest.mock('@avalabs/glacier-sdk', () => ({
|
|
34
|
-
Glacier: jest.fn(() => ({
|
|
35
|
-
evmTransactions: {
|
|
36
|
-
listTransactions: mockListTransactions,
|
|
37
|
-
},
|
|
38
|
-
})),
|
|
39
|
-
}));
|
|
40
|
-
|
|
41
33
|
describe('get-transactions-from-glacier', () => {
|
|
42
34
|
beforeEach(() => {
|
|
43
35
|
jest.clearAllMocks();
|
|
44
36
|
});
|
|
45
|
-
|
|
46
|
-
it('should have returned error with missing glacier api url', async () => {
|
|
47
|
-
try {
|
|
48
|
-
await getTransactionsFromGlacier({
|
|
49
|
-
networkToken: {
|
|
50
|
-
name: 'networkToken',
|
|
51
|
-
symbol: 'networkToken',
|
|
52
|
-
decimals: 1,
|
|
53
|
-
description: 'description',
|
|
54
|
-
logoUri: 'logoUri',
|
|
55
|
-
},
|
|
56
|
-
explorerUrl: 'explorerUrl',
|
|
57
|
-
chainId: 1,
|
|
58
|
-
address: 'address',
|
|
59
|
-
nextPageToken: 'nextPageToken',
|
|
60
|
-
offset: 1,
|
|
61
|
-
glacierApiUrl: 'glacierApiUrl',
|
|
62
|
-
});
|
|
63
|
-
} catch (error) {
|
|
64
|
-
expect(error).toEqual(new Error('Glacier API URL is required'));
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
37
|
it('should have returned empty response when listTransaction failed', async () => {
|
|
68
|
-
|
|
38
|
+
const mockGlacierService: EvmGlacierService = {
|
|
39
|
+
...expect.any(Object),
|
|
40
|
+
listTransactions: jest.fn().mockRejectedValue(new Error('failed to list transactions')),
|
|
41
|
+
isHealthy: jest.fn().mockReturnValue(true),
|
|
42
|
+
};
|
|
69
43
|
const result = await getTransactionsFromGlacier({
|
|
70
44
|
networkToken: {
|
|
71
45
|
name: 'networkToken',
|
|
@@ -79,7 +53,7 @@ describe('get-transactions-from-glacier', () => {
|
|
|
79
53
|
address: 'address',
|
|
80
54
|
nextPageToken: 'nextPageToken',
|
|
81
55
|
offset: 1,
|
|
82
|
-
|
|
56
|
+
glacierService: mockGlacierService,
|
|
83
57
|
});
|
|
84
58
|
expect(result).toEqual({
|
|
85
59
|
transactions: [],
|
|
@@ -87,18 +61,22 @@ describe('get-transactions-from-glacier', () => {
|
|
|
87
61
|
});
|
|
88
62
|
});
|
|
89
63
|
it('should have returned filtered response with no transaction status of 0', async () => {
|
|
90
|
-
|
|
91
|
-
...
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
...mockListTransactionDetailsResponse.transactions[0]
|
|
97
|
-
|
|
64
|
+
const mockGlacierService: EvmGlacierService = {
|
|
65
|
+
...expect.any(Object),
|
|
66
|
+
listTransactions: jest.fn().mockResolvedValue({
|
|
67
|
+
...mockListTransactionDetailsResponse,
|
|
68
|
+
transactions: [
|
|
69
|
+
{
|
|
70
|
+
...mockListTransactionDetailsResponse.transactions[0],
|
|
71
|
+
nativeTransaction: {
|
|
72
|
+
...mockListTransactionDetailsResponse.transactions[0]?.nativeTransaction,
|
|
73
|
+
txStatus: '0',
|
|
74
|
+
},
|
|
98
75
|
},
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
76
|
+
],
|
|
77
|
+
}),
|
|
78
|
+
isHealthy: jest.fn().mockReturnValue(true),
|
|
79
|
+
};
|
|
102
80
|
const result = await getTransactionsFromGlacier({
|
|
103
81
|
networkToken: {
|
|
104
82
|
name: 'networkToken',
|
|
@@ -112,7 +90,7 @@ describe('get-transactions-from-glacier', () => {
|
|
|
112
90
|
address: 'address',
|
|
113
91
|
nextPageToken: 'nextPageToken',
|
|
114
92
|
offset: 1,
|
|
115
|
-
|
|
93
|
+
glacierService: mockGlacierService,
|
|
116
94
|
});
|
|
117
95
|
expect(result).toEqual({
|
|
118
96
|
transactions: [],
|
|
@@ -120,18 +98,22 @@ describe('get-transactions-from-glacier', () => {
|
|
|
120
98
|
});
|
|
121
99
|
});
|
|
122
100
|
it('should have returned filtered response without transaction with amount 0', async () => {
|
|
123
|
-
|
|
124
|
-
...
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
...mockListTransactionDetailsResponse.transactions[0]
|
|
130
|
-
|
|
101
|
+
const mockGlacierService: EvmGlacierService = {
|
|
102
|
+
...expect.any(Object),
|
|
103
|
+
listTransactions: jest.fn().mockResolvedValue({
|
|
104
|
+
...mockListTransactionDetailsResponse,
|
|
105
|
+
transactions: [
|
|
106
|
+
{
|
|
107
|
+
...mockListTransactionDetailsResponse.transactions[0],
|
|
108
|
+
nativeTransaction: {
|
|
109
|
+
...mockListTransactionDetailsResponse.transactions[0]?.nativeTransaction,
|
|
110
|
+
txStatus: '0',
|
|
111
|
+
},
|
|
131
112
|
},
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
113
|
+
],
|
|
114
|
+
}),
|
|
115
|
+
isHealthy: jest.fn().mockReturnValue(true),
|
|
116
|
+
};
|
|
135
117
|
const result = await getTransactionsFromGlacier({
|
|
136
118
|
networkToken: {
|
|
137
119
|
name: 'networkToken',
|
|
@@ -145,7 +127,7 @@ describe('get-transactions-from-glacier', () => {
|
|
|
145
127
|
address: 'address',
|
|
146
128
|
nextPageToken: 'nextPageToken',
|
|
147
129
|
offset: 1,
|
|
148
|
-
|
|
130
|
+
glacierService: mockGlacierService,
|
|
149
131
|
});
|
|
150
132
|
expect(result).toEqual({
|
|
151
133
|
transactions: [],
|
|
@@ -154,7 +136,11 @@ describe('get-transactions-from-glacier', () => {
|
|
|
154
136
|
});
|
|
155
137
|
|
|
156
138
|
it('should have returned response', async () => {
|
|
157
|
-
|
|
139
|
+
const mockGlacierService: EvmGlacierService = {
|
|
140
|
+
...expect.any(Object),
|
|
141
|
+
listTransactions: jest.fn().mockResolvedValue(mockListTransactionDetailsResponse),
|
|
142
|
+
isHealthy: jest.fn().mockReturnValue(true),
|
|
143
|
+
};
|
|
158
144
|
const result = await getTransactionsFromGlacier({
|
|
159
145
|
networkToken: {
|
|
160
146
|
name: 'networkToken',
|
|
@@ -168,7 +154,7 @@ describe('get-transactions-from-glacier', () => {
|
|
|
168
154
|
address: 'address',
|
|
169
155
|
nextPageToken: 'nextPageToken',
|
|
170
156
|
offset: 1,
|
|
171
|
-
|
|
157
|
+
glacierService: mockGlacierService,
|
|
172
158
|
});
|
|
173
159
|
expect(result).toEqual({
|
|
174
160
|
transactions: [
|
|
@@ -206,4 +192,31 @@ describe('get-transactions-from-glacier', () => {
|
|
|
206
192
|
nextPageToken: 'nextPageToken',
|
|
207
193
|
});
|
|
208
194
|
});
|
|
195
|
+
|
|
196
|
+
it('should have returned empty response', async () => {
|
|
197
|
+
const mockGlacierService: EvmGlacierService = {
|
|
198
|
+
...expect.any(Object),
|
|
199
|
+
listTransactions: jest.fn(),
|
|
200
|
+
isHealthy: jest.fn().mockReturnValue(false),
|
|
201
|
+
};
|
|
202
|
+
const result = await getTransactionsFromGlacier({
|
|
203
|
+
networkToken: {
|
|
204
|
+
name: 'networkToken',
|
|
205
|
+
symbol: 'networkToken',
|
|
206
|
+
decimals: 1,
|
|
207
|
+
description: 'description',
|
|
208
|
+
logoUri: 'logoUri',
|
|
209
|
+
},
|
|
210
|
+
explorerUrl: 'explorerUrl',
|
|
211
|
+
chainId: 1,
|
|
212
|
+
address: 'address',
|
|
213
|
+
nextPageToken: 'nextPageToken',
|
|
214
|
+
offset: 1,
|
|
215
|
+
glacierService: mockGlacierService,
|
|
216
|
+
});
|
|
217
|
+
expect(result).toEqual({
|
|
218
|
+
transactions: [],
|
|
219
|
+
nextPageToken: '',
|
|
220
|
+
});
|
|
221
|
+
});
|
|
209
222
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { NetworkToken, TransactionHistoryResponse } from '@avalabs/vm-module-types';
|
|
2
|
-
import { Glacier } from '@avalabs/glacier-sdk';
|
|
3
|
-
import { rpcErrors } from '@metamask/rpc-errors';
|
|
4
2
|
import { convertTransaction } from './convert-transaction';
|
|
3
|
+
import type { EvmGlacierService } from '../../../../services/glacier-service/glacier-service';
|
|
5
4
|
|
|
6
5
|
export const getTransactionsFromGlacier = async ({
|
|
7
6
|
chainId,
|
|
@@ -10,7 +9,7 @@ export const getTransactionsFromGlacier = async ({
|
|
|
10
9
|
address,
|
|
11
10
|
nextPageToken,
|
|
12
11
|
offset,
|
|
13
|
-
|
|
12
|
+
glacierService,
|
|
14
13
|
}: {
|
|
15
14
|
chainId: number;
|
|
16
15
|
explorerUrl: string;
|
|
@@ -18,16 +17,10 @@ export const getTransactionsFromGlacier = async ({
|
|
|
18
17
|
address: string;
|
|
19
18
|
nextPageToken?: string;
|
|
20
19
|
offset?: number;
|
|
21
|
-
|
|
20
|
+
glacierService: EvmGlacierService;
|
|
22
21
|
}): Promise<TransactionHistoryResponse> => {
|
|
23
|
-
if (!glacierApiUrl) {
|
|
24
|
-
throw rpcErrors.invalidParams('Glacier API URL is required');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const glacierSdk = new Glacier({ BASE: glacierApiUrl });
|
|
28
|
-
|
|
29
22
|
try {
|
|
30
|
-
const response = await
|
|
23
|
+
const response = await glacierService.listTransactions({
|
|
31
24
|
chainId: chainId.toString(),
|
|
32
25
|
address,
|
|
33
26
|
pageToken: nextPageToken,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getTransactionHistory } from './get-transaction-history';
|
|
2
2
|
import { getTransactionFromEtherscan } from './converters/etherscan-transaction-converter/get-transaction-from-etherscan';
|
|
3
3
|
import { getTransactionsFromGlacier } from './converters/evm-transaction-converter/get-transactions-from-glacier';
|
|
4
|
+
import type { EvmGlacierService } from '../../services/glacier-service/glacier-service';
|
|
4
5
|
|
|
5
6
|
jest.mock('./converters/evm-transaction-converter/get-transactions-from-glacier', () => ({
|
|
6
7
|
getTransactionsFromGlacier: jest.fn(),
|
|
@@ -13,7 +14,7 @@ jest.mock('./converters/etherscan-transaction-converter/get-transaction-from-eth
|
|
|
13
14
|
describe('get-transaction-history', () => {
|
|
14
15
|
it('should have called getTransactionFromEtherscan', async () => {
|
|
15
16
|
await getTransactionHistory({
|
|
16
|
-
|
|
17
|
+
glacierService: {} as EvmGlacierService,
|
|
17
18
|
chainId: 1,
|
|
18
19
|
isTestnet: false,
|
|
19
20
|
networkToken: {
|
|
@@ -31,8 +32,12 @@ describe('get-transaction-history', () => {
|
|
|
31
32
|
expect(getTransactionFromEtherscan).toHaveBeenCalled();
|
|
32
33
|
});
|
|
33
34
|
it('should have called getTransactionsFromGlacier', async () => {
|
|
35
|
+
const mockGlacierService: EvmGlacierService = {
|
|
36
|
+
...expect.any(Object),
|
|
37
|
+
isHealthy: jest.fn().mockReturnValue(true),
|
|
38
|
+
};
|
|
34
39
|
await getTransactionHistory({
|
|
35
|
-
|
|
40
|
+
glacierService: mockGlacierService,
|
|
36
41
|
chainId: 41334,
|
|
37
42
|
isTestnet: false,
|
|
38
43
|
networkToken: {
|
|
@@ -2,6 +2,7 @@ import { getTransactionFromEtherscan } from './converters/etherscan-transaction-
|
|
|
2
2
|
import { isEthereumChainId } from './utils/is-ethereum-chain-id';
|
|
3
3
|
import type { NetworkToken, TransactionHistoryResponse } from '@avalabs/vm-module-types';
|
|
4
4
|
import { getTransactionsFromGlacier } from './converters/evm-transaction-converter/get-transactions-from-glacier';
|
|
5
|
+
import type { EvmGlacierService } from '../../services/glacier-service/glacier-service';
|
|
5
6
|
|
|
6
7
|
export const getTransactionHistory = async ({
|
|
7
8
|
chainId,
|
|
@@ -11,7 +12,7 @@ export const getTransactionHistory = async ({
|
|
|
11
12
|
address,
|
|
12
13
|
nextPageToken,
|
|
13
14
|
offset,
|
|
14
|
-
|
|
15
|
+
glacierService,
|
|
15
16
|
}: {
|
|
16
17
|
chainId: number;
|
|
17
18
|
isTestnet?: boolean;
|
|
@@ -20,7 +21,7 @@ export const getTransactionHistory = async ({
|
|
|
20
21
|
address: string;
|
|
21
22
|
nextPageToken?: string;
|
|
22
23
|
offset?: number;
|
|
23
|
-
|
|
24
|
+
glacierService: EvmGlacierService;
|
|
24
25
|
}): Promise<TransactionHistoryResponse> => {
|
|
25
26
|
if (isEthereumChainId(chainId)) {
|
|
26
27
|
return getTransactionFromEtherscan({
|
|
@@ -33,6 +34,15 @@ export const getTransactionHistory = async ({
|
|
|
33
34
|
offset,
|
|
34
35
|
});
|
|
35
36
|
}
|
|
37
|
+
|
|
38
|
+
const isHealthy = glacierService.isHealthy();
|
|
39
|
+
if (!isHealthy) {
|
|
40
|
+
return {
|
|
41
|
+
transactions: [],
|
|
42
|
+
nextPageToken: '',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
36
46
|
return getTransactionsFromGlacier({
|
|
37
47
|
networkToken,
|
|
38
48
|
explorerUrl,
|
|
@@ -40,6 +50,6 @@ export const getTransactionHistory = async ({
|
|
|
40
50
|
address,
|
|
41
51
|
nextPageToken,
|
|
42
52
|
offset,
|
|
43
|
-
|
|
53
|
+
glacierService,
|
|
44
54
|
});
|
|
45
55
|
};
|
package/src/index.ts
CHANGED