@avalabs/bridge-unified 2.1.0 → 2.1.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/LICENSE +9 -0
- package/README.md +40 -24
- package/dist/index.cjs +8 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -36
- package/dist/index.d.ts +11 -36
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/.turbo/turbo-build.log +0 -22
- package/.turbo/turbo-lint.log +0 -4
- package/.turbo/turbo-test.log +0 -26
- package/CHANGELOG.md +0 -31
- package/jest.config.js +0 -9
- package/src/bridges/cctp/__mocks__/asset.mock.ts +0 -15
- package/src/bridges/cctp/__mocks__/bridge-transfer.mock.ts +0 -48
- package/src/bridges/cctp/__mocks__/chain.mocks.ts +0 -33
- package/src/bridges/cctp/__mocks__/config.mock.ts +0 -45
- package/src/bridges/cctp/abis/erc20.ts +0 -117
- package/src/bridges/cctp/abis/message-transmitter.ts +0 -318
- package/src/bridges/cctp/abis/token-router.ts +0 -843
- package/src/bridges/cctp/factory.test.ts +0 -73
- package/src/bridges/cctp/factory.ts +0 -36
- package/src/bridges/cctp/handlers/estimate-gas.test.ts +0 -110
- package/src/bridges/cctp/handlers/estimate-gas.ts +0 -58
- package/src/bridges/cctp/handlers/get-assets.test.ts +0 -47
- package/src/bridges/cctp/handlers/get-assets.ts +0 -27
- package/src/bridges/cctp/handlers/get-fees.test.ts +0 -61
- package/src/bridges/cctp/handlers/get-fees.ts +0 -26
- package/src/bridges/cctp/handlers/track-transfer.test.ts +0 -779
- package/src/bridges/cctp/handlers/track-transfer.ts +0 -365
- package/src/bridges/cctp/handlers/transfer-asset.test.ts +0 -429
- package/src/bridges/cctp/handlers/transfer-asset.ts +0 -179
- package/src/bridges/cctp/index.ts +0 -1
- package/src/bridges/cctp/types/chain.ts +0 -9
- package/src/bridges/cctp/types/config.ts +0 -20
- package/src/bridges/cctp/utils/build-tx.ts +0 -30
- package/src/bridges/cctp/utils/config.test.ts +0 -49
- package/src/bridges/cctp/utils/config.ts +0 -36
- package/src/bridges/cctp/utils/transfer-data.test.ts +0 -83
- package/src/bridges/cctp/utils/transfer-data.ts +0 -48
- package/src/errors/bridge-error.ts +0 -11
- package/src/errors/bridge-initialization-error.ts +0 -9
- package/src/errors/bridge-unavailable-error.ts +0 -9
- package/src/errors/index.ts +0 -4
- package/src/errors/invalid-params-error.ts +0 -9
- package/src/index.ts +0 -3
- package/src/types/asset.ts +0 -26
- package/src/types/bridge.ts +0 -64
- package/src/types/chain.ts +0 -10
- package/src/types/config.ts +0 -10
- package/src/types/environment.ts +0 -4
- package/src/types/error.ts +0 -19
- package/src/types/index.ts +0 -9
- package/src/types/provider.ts +0 -12
- package/src/types/signer.ts +0 -18
- package/src/types/transfer.ts +0 -35
- package/src/unified-bridge-service.test.ts +0 -209
- package/src/unified-bridge-service.ts +0 -97
- package/src/utils/bridge-types.test.ts +0 -103
- package/src/utils/bridge-types.ts +0 -32
- package/src/utils/caip2.test.ts +0 -44
- package/src/utils/caip2.ts +0 -41
- package/src/utils/client.test.ts +0 -97
- package/src/utils/client.ts +0 -44
- package/src/utils/ensure-config.test.ts +0 -43
- package/src/utils/ensure-config.ts +0 -12
- package/src/utils/index.ts +0 -2
- package/src/utils/network-fee.test.ts +0 -24
- package/src/utils/network-fee.ts +0 -6
- package/src/utils/retry-promise.test.ts +0 -115
- package/src/utils/retry-promise.ts +0 -72
- package/src/utils/wait.test.ts +0 -33
- package/src/utils/wait.ts +0 -4
- package/tsconfig.jest.json +0 -7
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -4
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BridgeType,
|
|
3
|
-
type BridgeService,
|
|
4
|
-
type FeeParams,
|
|
5
|
-
type TransferParams,
|
|
6
|
-
type TrackingParams,
|
|
7
|
-
} from '../../types/bridge';
|
|
8
|
-
import { Environment } from '../../types/environment';
|
|
9
|
-
import { ensureHasConfig } from '../../utils/ensure-config';
|
|
10
|
-
import { CCTP_CONFIG } from './__mocks__/config.mock';
|
|
11
|
-
import { cctpBridgeFactory } from './factory';
|
|
12
|
-
import { getAssets } from './handlers/get-assets';
|
|
13
|
-
import { getFees } from './handlers/get-fees';
|
|
14
|
-
import { trackTransfer } from './handlers/track-transfer';
|
|
15
|
-
import { transferAsset } from './handlers/transfer-asset';
|
|
16
|
-
import { getConfig } from './utils/config';
|
|
17
|
-
|
|
18
|
-
jest.mock('./utils/config');
|
|
19
|
-
jest.mock('../../utils/ensure-config');
|
|
20
|
-
jest.mock('./handlers/get-assets');
|
|
21
|
-
jest.mock('./handlers/get-fees');
|
|
22
|
-
jest.mock('./handlers/transfer-asset');
|
|
23
|
-
jest.mock('./handlers/track-transfer');
|
|
24
|
-
|
|
25
|
-
describe('CCTP factory', () => {
|
|
26
|
-
let service: BridgeService;
|
|
27
|
-
const environment = Environment.TEST;
|
|
28
|
-
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
jest.resetAllMocks();
|
|
31
|
-
service = cctpBridgeFactory(environment);
|
|
32
|
-
(getConfig as jest.Mock).mockResolvedValue(CCTP_CONFIG);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('contains the correct properties', async () => {
|
|
36
|
-
expect(service.type).toEqual(BridgeType.CCTP);
|
|
37
|
-
expect(service.config).toBeNull();
|
|
38
|
-
|
|
39
|
-
await service.updateConfig();
|
|
40
|
-
expect(getConfig).toHaveBeenCalledWith(environment);
|
|
41
|
-
expect(service.config).toStrictEqual(CCTP_CONFIG);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
describe('handlers', () => {
|
|
45
|
-
it('calls ensureHasConfig correctly', async () => {
|
|
46
|
-
await service.ensureHasConfig();
|
|
47
|
-
expect(ensureHasConfig).toHaveBeenCalledWith(service);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('calls ensureHasConfig correctly', async () => {
|
|
51
|
-
await service.getAssets();
|
|
52
|
-
expect(getAssets).toHaveBeenCalledWith(service);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('calls getFees correctly', async () => {
|
|
56
|
-
const feeParams = { foo: 'bar' } as unknown as FeeParams;
|
|
57
|
-
await service.getFees(feeParams);
|
|
58
|
-
expect(getFees).toHaveBeenCalledWith(service, feeParams);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('calls transferAsset correctly', async () => {
|
|
62
|
-
const transferAssetParams = { foo: 'bar' } as unknown as TransferParams;
|
|
63
|
-
await service.transferAsset(transferAssetParams);
|
|
64
|
-
expect(transferAsset).toHaveBeenCalledWith(service, transferAssetParams, environment);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('calls trackTransfer correctly', () => {
|
|
68
|
-
const trackTransferParams = { foo: 'bar' } as unknown as TrackingParams;
|
|
69
|
-
service.trackTransfer(trackTransferParams);
|
|
70
|
-
expect(trackTransfer).toHaveBeenCalledWith(service, trackTransferParams);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { type BridgeServiceFactory, BridgeType } from '../../types/bridge';
|
|
2
|
-
import { getConfig } from './utils/config';
|
|
3
|
-
import { getAssets } from './handlers/get-assets';
|
|
4
|
-
import { getFees } from './handlers/get-fees';
|
|
5
|
-
import { transferAsset } from './handlers/transfer-asset';
|
|
6
|
-
import { ensureHasConfig } from '../../utils/ensure-config';
|
|
7
|
-
import { trackTransfer } from './handlers/track-transfer';
|
|
8
|
-
import { estimateGas } from './handlers/estimate-gas';
|
|
9
|
-
|
|
10
|
-
export const cctpBridgeFactory: BridgeServiceFactory = (environment) => {
|
|
11
|
-
return {
|
|
12
|
-
type: BridgeType.CCTP,
|
|
13
|
-
config: null,
|
|
14
|
-
updateConfig: async function () {
|
|
15
|
-
this.config = await getConfig(environment);
|
|
16
|
-
},
|
|
17
|
-
ensureHasConfig: async function () {
|
|
18
|
-
return ensureHasConfig(this);
|
|
19
|
-
},
|
|
20
|
-
estimateGas: function (params) {
|
|
21
|
-
return estimateGas(this, params);
|
|
22
|
-
},
|
|
23
|
-
getAssets: async function () {
|
|
24
|
-
return getAssets(this);
|
|
25
|
-
},
|
|
26
|
-
getFees: async function (params) {
|
|
27
|
-
return getFees(this, params);
|
|
28
|
-
},
|
|
29
|
-
transferAsset: async function (params) {
|
|
30
|
-
return transferAsset(this, params, environment);
|
|
31
|
-
},
|
|
32
|
-
trackTransfer: function (params) {
|
|
33
|
-
return trackTransfer(this, params);
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
};
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { getClientForChain } from '../../../utils/client';
|
|
2
|
-
import { BridgeType, type BridgeService, type TransferParams } from '../../../types';
|
|
3
|
-
|
|
4
|
-
import { CCTP_CONFIG } from '../__mocks__/config.mock';
|
|
5
|
-
import { BRIDGE_ASSET } from '../__mocks__/asset.mock';
|
|
6
|
-
import { SOURCE_CHAIN, TARGET_CHAIN } from '../__mocks__/chain.mocks';
|
|
7
|
-
|
|
8
|
-
import { estimateGas } from './estimate-gas';
|
|
9
|
-
import { isAddress } from 'viem';
|
|
10
|
-
|
|
11
|
-
jest.mock('viem');
|
|
12
|
-
jest.mock('../../../utils/client');
|
|
13
|
-
|
|
14
|
-
describe('CCTP estimateGas', () => {
|
|
15
|
-
const sourceProviderMock = {
|
|
16
|
-
request: jest.fn(),
|
|
17
|
-
};
|
|
18
|
-
const targetProviderMock = {
|
|
19
|
-
request: jest.fn(),
|
|
20
|
-
};
|
|
21
|
-
const bridgeMock = {
|
|
22
|
-
type: BridgeType.CCTP,
|
|
23
|
-
config: CCTP_CONFIG,
|
|
24
|
-
ensureHasConfig: jest.fn(),
|
|
25
|
-
estimateGas: jest.fn(),
|
|
26
|
-
} as unknown as BridgeService;
|
|
27
|
-
|
|
28
|
-
const getTransferParams = (props?: Partial<TransferParams>) =>
|
|
29
|
-
({
|
|
30
|
-
asset: BRIDGE_ASSET,
|
|
31
|
-
amount: 1_000_000,
|
|
32
|
-
fromAddress: '0x787',
|
|
33
|
-
sourceChain: SOURCE_CHAIN,
|
|
34
|
-
targetChain: TARGET_CHAIN,
|
|
35
|
-
sourceProvider: sourceProviderMock,
|
|
36
|
-
targetProvider: targetProviderMock,
|
|
37
|
-
...(props ?? {}),
|
|
38
|
-
}) as TransferParams;
|
|
39
|
-
|
|
40
|
-
const clientMock = {
|
|
41
|
-
readContract: jest.fn(),
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
beforeEach(() => {
|
|
45
|
-
jest.resetAllMocks();
|
|
46
|
-
(getClientForChain as jest.Mock).mockReturnValue(clientMock);
|
|
47
|
-
jest.mocked(isAddress).mockReturnValue(true);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('calls ensureHasConfig', async () => {
|
|
51
|
-
const error = new Error('error');
|
|
52
|
-
const params = getTransferParams();
|
|
53
|
-
(bridgeMock.ensureHasConfig as jest.Mock).mockRejectedValueOnce(error);
|
|
54
|
-
await expect(estimateGas(bridgeMock, params)).rejects.toThrow(error);
|
|
55
|
-
|
|
56
|
-
expect(bridgeMock.ensureHasConfig).toHaveBeenCalled();
|
|
57
|
-
expect(getClientForChain).not.toHaveBeenCalled();
|
|
58
|
-
expect(clientMock.readContract).not.toHaveBeenCalled();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('when allowance approval is required', () => {
|
|
62
|
-
beforeEach(() => {
|
|
63
|
-
clientMock.readContract.mockResolvedValue(0);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe('when onboarding', () => {
|
|
67
|
-
const params = getTransferParams();
|
|
68
|
-
|
|
69
|
-
it('returns the sum of approval and transfer gas estimates', async () => {
|
|
70
|
-
expect(await estimateGas(bridgeMock, params)).toEqual(235_000n);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
describe('when offboarding', () => {
|
|
75
|
-
const params = getTransferParams({
|
|
76
|
-
sourceChain: TARGET_CHAIN,
|
|
77
|
-
targetChain: SOURCE_CHAIN,
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('returns the sum of approval and transfer gas estimates', async () => {
|
|
81
|
-
expect(await estimateGas(bridgeMock, params)).toEqual(275_000n);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
describe('when allowance approval is NOT required', () => {
|
|
87
|
-
beforeEach(() => {
|
|
88
|
-
clientMock.readContract.mockResolvedValue(2_000_000n);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
describe('when onboarding', () => {
|
|
92
|
-
const params = getTransferParams();
|
|
93
|
-
|
|
94
|
-
it('returns the gas estimate for transfer tx alone', async () => {
|
|
95
|
-
expect(await estimateGas(bridgeMock, params)).toEqual(175_000n);
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
describe('when offboarding', () => {
|
|
100
|
-
const params = getTransferParams({
|
|
101
|
-
sourceChain: TARGET_CHAIN,
|
|
102
|
-
targetChain: SOURCE_CHAIN,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('returns the gas estimate for transfer tx alone', async () => {
|
|
106
|
-
expect(await estimateGas(bridgeMock, params)).toEqual(215_000n);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { isAddress } from 'viem';
|
|
2
|
-
|
|
3
|
-
import { InvalidParamsError } from '../../../errors';
|
|
4
|
-
import { getClientForChain } from '../../../utils/client';
|
|
5
|
-
import { ErrorReason, type BridgeService, type TransferParams } from '../../../types';
|
|
6
|
-
|
|
7
|
-
import { ERC20_ABI } from '../abis/erc20';
|
|
8
|
-
import { getTransferData } from '../utils/transfer-data';
|
|
9
|
-
import { ChainDomain } from '../types/chain';
|
|
10
|
-
|
|
11
|
-
const ETH_APPROVAL_TX_GAS_ESTIMATE = 60_000n; // 55.5k gas on average (+/- 200 units)
|
|
12
|
-
const ETH_TRANSFER_TX_GAS_ESTIMATE = 175_000n; // 161.5k gas on average (+/- 200 units)
|
|
13
|
-
const AVAX_APPROVAL_TX_GAS_ESTIMATE = 60_000n; // 55.5k gas on average (+/- 200 units)
|
|
14
|
-
const AVAX_TRANSFER_TX_GAS_ESTIMATE = 215_000n; // 203k gas on average (+/- 200 units)
|
|
15
|
-
/**
|
|
16
|
-
* The CCTP bridging consists of up to two transactions:
|
|
17
|
-
*
|
|
18
|
-
* 1. Token spend approval (technically optional, but realistically performed basically every time)
|
|
19
|
-
* 2. Token transfer (required)
|
|
20
|
-
*
|
|
21
|
-
* Since the 2nd one needs the first transaction to be complete, calling .estimateGas() is not possible.
|
|
22
|
-
* The RPC call raises an error since it cannot execute the transfer transaction locally without
|
|
23
|
-
* the allowance being set. For that reason, we're using hard-coded estimates here, with small buffers added.
|
|
24
|
-
*
|
|
25
|
-
* NOTE: These estimates are only supposed to be used to approximate the network fees in the UI.
|
|
26
|
-
* DO NOT use them as `gasLimit` prop on the transactions!
|
|
27
|
-
*/
|
|
28
|
-
export async function estimateGas(bridge: BridgeService, params: TransferParams): Promise<bigint> {
|
|
29
|
-
await bridge.ensureHasConfig();
|
|
30
|
-
|
|
31
|
-
const { sourceChain, targetChain, asset, amount, fromAddress, toAddress: maybeToAddress, sourceProvider } = params;
|
|
32
|
-
const toAddress = maybeToAddress ?? fromAddress;
|
|
33
|
-
|
|
34
|
-
if (!isAddress(fromAddress) || !isAddress(toAddress)) {
|
|
35
|
-
throw new InvalidParamsError(ErrorReason.INCORRECT_ADDRESS_PROVIDED);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const { sourceChainData, burnToken } = getTransferData({ sourceChain, targetChain, asset, amount }, bridge.config!);
|
|
39
|
-
|
|
40
|
-
const client = getClientForChain({ chain: sourceChain, provider: sourceProvider });
|
|
41
|
-
|
|
42
|
-
const allowance = await client.readContract({
|
|
43
|
-
address: burnToken.address,
|
|
44
|
-
abi: ERC20_ABI,
|
|
45
|
-
functionName: 'allowance',
|
|
46
|
-
args: [fromAddress, sourceChainData.tokenRouterAddress],
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const isOffboarding = sourceChainData.domain === ChainDomain.Avalanche;
|
|
50
|
-
|
|
51
|
-
if (allowance >= amount) {
|
|
52
|
-
return isOffboarding ? AVAX_TRANSFER_TX_GAS_ESTIMATE : ETH_TRANSFER_TX_GAS_ESTIMATE;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return isOffboarding
|
|
56
|
-
? AVAX_APPROVAL_TX_GAS_ESTIMATE + AVAX_TRANSFER_TX_GAS_ESTIMATE
|
|
57
|
-
: ETH_APPROVAL_TX_GAS_ESTIMATE + ETH_TRANSFER_TX_GAS_ESTIMATE;
|
|
58
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { TokenType, type BridgeService, BridgeType } from '../../../types';
|
|
2
|
-
import { SOURCE_CHAIN, TARGET_CHAIN } from '../__mocks__/chain.mocks';
|
|
3
|
-
import { CCTP_CONFIG, SOURCE_TOKEN_ADDRESS, TARGET_TOKEN_ADDRESS } from '../__mocks__/config.mock';
|
|
4
|
-
import { getAssets } from './get-assets';
|
|
5
|
-
|
|
6
|
-
describe('CCTP getAssets', () => {
|
|
7
|
-
const bridgeMock = {
|
|
8
|
-
ensureHasConfig: jest.fn(),
|
|
9
|
-
config: CCTP_CONFIG,
|
|
10
|
-
} as unknown as BridgeService;
|
|
11
|
-
|
|
12
|
-
it('calls ensureHasConfig', async () => {
|
|
13
|
-
await getAssets(bridgeMock);
|
|
14
|
-
expect(bridgeMock.ensureHasConfig).toHaveBeenCalled();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('returns the correct assets', async () => {
|
|
18
|
-
const assets = await getAssets(bridgeMock);
|
|
19
|
-
|
|
20
|
-
expect(assets).toStrictEqual({
|
|
21
|
-
[SOURCE_CHAIN.chainId]: [
|
|
22
|
-
{
|
|
23
|
-
address: SOURCE_TOKEN_ADDRESS,
|
|
24
|
-
name: 'USD Coin',
|
|
25
|
-
symbol: 'USDC',
|
|
26
|
-
decimals: 6,
|
|
27
|
-
type: TokenType.ERC20,
|
|
28
|
-
destinations: {
|
|
29
|
-
[TARGET_CHAIN.chainId]: [BridgeType.CCTP],
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
],
|
|
33
|
-
[TARGET_CHAIN.chainId]: [
|
|
34
|
-
{
|
|
35
|
-
address: TARGET_TOKEN_ADDRESS,
|
|
36
|
-
name: 'USD Coin',
|
|
37
|
-
symbol: 'USDC',
|
|
38
|
-
decimals: 6,
|
|
39
|
-
type: TokenType.ERC20,
|
|
40
|
-
destinations: {
|
|
41
|
-
[SOURCE_CHAIN.chainId]: [BridgeType.CCTP],
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { TokenType, type BridgeService, type ChainAssetMap, type DestinationInfo, BridgeType } from '../../../types';
|
|
2
|
-
|
|
3
|
-
export async function getAssets(bridge: BridgeService) {
|
|
4
|
-
await bridge.ensureHasConfig();
|
|
5
|
-
|
|
6
|
-
const chainIds = bridge.config!.map((chainData) => chainData.chainId);
|
|
7
|
-
|
|
8
|
-
return bridge.config!.reduce<ChainAssetMap>((assets, chainData) => {
|
|
9
|
-
assets[chainData.chainId] = chainData.tokens.map((asset) => ({
|
|
10
|
-
...asset,
|
|
11
|
-
type: TokenType.ERC20,
|
|
12
|
-
destinations: chainIds.reduce<DestinationInfo>((destinations, chainId) => {
|
|
13
|
-
if (chainData.chainId !== chainId) {
|
|
14
|
-
if (!destinations[chainId]) {
|
|
15
|
-
destinations[chainId] = [];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
destinations[chainId]?.push(BridgeType.CCTP);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return destinations;
|
|
22
|
-
}, {}),
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
return assets;
|
|
26
|
-
}, {});
|
|
27
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type { BridgeService, FeeParams } from '../../../types';
|
|
2
|
-
import { getClientForChain } from '../../../utils/client';
|
|
3
|
-
import { BRIDGE_ASSET } from '../__mocks__/asset.mock';
|
|
4
|
-
import { SOURCE_CHAIN, TARGET_CHAIN } from '../__mocks__/chain.mocks';
|
|
5
|
-
import { CCTP_CONFIG, SOURCE_ROUTER_ADDRESS } from '../__mocks__/config.mock';
|
|
6
|
-
import { TOKEN_ROUTER_ABI } from '../abis/token-router';
|
|
7
|
-
import { getFees } from './get-fees';
|
|
8
|
-
|
|
9
|
-
jest.mock('../../../utils/client');
|
|
10
|
-
|
|
11
|
-
describe('CCTP getFees', () => {
|
|
12
|
-
const feeParams = {
|
|
13
|
-
sourceChain: SOURCE_CHAIN,
|
|
14
|
-
targetChain: TARGET_CHAIN,
|
|
15
|
-
asset: BRIDGE_ASSET,
|
|
16
|
-
amount: 1_000_000,
|
|
17
|
-
} as unknown as FeeParams;
|
|
18
|
-
|
|
19
|
-
const bridgeMock = {
|
|
20
|
-
ensureHasConfig: jest.fn(),
|
|
21
|
-
config: CCTP_CONFIG,
|
|
22
|
-
} as unknown as BridgeService;
|
|
23
|
-
|
|
24
|
-
const clientMock = {
|
|
25
|
-
readContract: jest.fn(),
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
jest.resetAllMocks();
|
|
30
|
-
(getClientForChain as jest.Mock).mockReturnValue(clientMock);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('calls ensureHasConfig', async () => {
|
|
34
|
-
const error = new Error('error');
|
|
35
|
-
(bridgeMock.ensureHasConfig as jest.Mock).mockRejectedValueOnce(error);
|
|
36
|
-
await expect(getFees(bridgeMock, feeParams)).rejects.toThrow(error);
|
|
37
|
-
|
|
38
|
-
expect(bridgeMock.ensureHasConfig).toHaveBeenCalled();
|
|
39
|
-
expect(getClientForChain).not.toHaveBeenCalled();
|
|
40
|
-
expect(clientMock.readContract).not.toHaveBeenCalled();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('returns the fee correctly', async () => {
|
|
44
|
-
const feeAmount = 2_000_000;
|
|
45
|
-
clientMock.readContract.mockResolvedValueOnce(feeAmount);
|
|
46
|
-
|
|
47
|
-
const fees = await getFees(bridgeMock, feeParams);
|
|
48
|
-
|
|
49
|
-
expect(fees).toStrictEqual({
|
|
50
|
-
[BRIDGE_ASSET.address!]: feeAmount,
|
|
51
|
-
});
|
|
52
|
-
expect(bridgeMock.ensureHasConfig).toHaveBeenCalled();
|
|
53
|
-
expect(getClientForChain).toHaveBeenCalledWith({ chain: feeParams.sourceChain, provider: undefined });
|
|
54
|
-
expect(clientMock.readContract).toHaveBeenCalledWith({
|
|
55
|
-
address: SOURCE_ROUTER_ADDRESS,
|
|
56
|
-
abi: TOKEN_ROUTER_ABI,
|
|
57
|
-
functionName: 'calculateFee',
|
|
58
|
-
args: [feeParams.amount, 1],
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { AssetFeeMap, BridgeService, FeeParams } from '../../../types';
|
|
2
|
-
import { getClientForChain } from '../../../utils/client';
|
|
3
|
-
import { TOKEN_ROUTER_ABI } from '../abis/token-router';
|
|
4
|
-
import { getTransferData } from '../utils/transfer-data';
|
|
5
|
-
|
|
6
|
-
export async function getFees(bridge: BridgeService, params: FeeParams) {
|
|
7
|
-
await bridge.ensureHasConfig();
|
|
8
|
-
|
|
9
|
-
const { sourceChain, targetChain, asset, amount, provider } = params;
|
|
10
|
-
const { sourceChainData, targetChainData, burnToken } = getTransferData(
|
|
11
|
-
{ sourceChain, targetChain, asset, amount },
|
|
12
|
-
bridge.config!,
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
const client = getClientForChain({ chain: sourceChain, provider });
|
|
16
|
-
const feeAmount = await client.readContract({
|
|
17
|
-
address: sourceChainData.tokenRouterAddress,
|
|
18
|
-
abi: TOKEN_ROUTER_ABI,
|
|
19
|
-
functionName: 'calculateFee',
|
|
20
|
-
args: [amount, targetChainData.domain],
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
[burnToken.address]: feeAmount,
|
|
25
|
-
} as AssetFeeMap;
|
|
26
|
-
}
|