@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.
Files changed (77) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +40 -24
  3. package/dist/index.cjs +8 -7
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +11 -36
  6. package/dist/index.d.ts +11 -36
  7. package/dist/index.js +3 -3
  8. package/dist/index.js.map +1 -1
  9. package/package.json +6 -2
  10. package/.turbo/turbo-build.log +0 -22
  11. package/.turbo/turbo-lint.log +0 -4
  12. package/.turbo/turbo-test.log +0 -26
  13. package/CHANGELOG.md +0 -31
  14. package/jest.config.js +0 -9
  15. package/src/bridges/cctp/__mocks__/asset.mock.ts +0 -15
  16. package/src/bridges/cctp/__mocks__/bridge-transfer.mock.ts +0 -48
  17. package/src/bridges/cctp/__mocks__/chain.mocks.ts +0 -33
  18. package/src/bridges/cctp/__mocks__/config.mock.ts +0 -45
  19. package/src/bridges/cctp/abis/erc20.ts +0 -117
  20. package/src/bridges/cctp/abis/message-transmitter.ts +0 -318
  21. package/src/bridges/cctp/abis/token-router.ts +0 -843
  22. package/src/bridges/cctp/factory.test.ts +0 -73
  23. package/src/bridges/cctp/factory.ts +0 -36
  24. package/src/bridges/cctp/handlers/estimate-gas.test.ts +0 -110
  25. package/src/bridges/cctp/handlers/estimate-gas.ts +0 -58
  26. package/src/bridges/cctp/handlers/get-assets.test.ts +0 -47
  27. package/src/bridges/cctp/handlers/get-assets.ts +0 -27
  28. package/src/bridges/cctp/handlers/get-fees.test.ts +0 -61
  29. package/src/bridges/cctp/handlers/get-fees.ts +0 -26
  30. package/src/bridges/cctp/handlers/track-transfer.test.ts +0 -779
  31. package/src/bridges/cctp/handlers/track-transfer.ts +0 -365
  32. package/src/bridges/cctp/handlers/transfer-asset.test.ts +0 -429
  33. package/src/bridges/cctp/handlers/transfer-asset.ts +0 -179
  34. package/src/bridges/cctp/index.ts +0 -1
  35. package/src/bridges/cctp/types/chain.ts +0 -9
  36. package/src/bridges/cctp/types/config.ts +0 -20
  37. package/src/bridges/cctp/utils/build-tx.ts +0 -30
  38. package/src/bridges/cctp/utils/config.test.ts +0 -49
  39. package/src/bridges/cctp/utils/config.ts +0 -36
  40. package/src/bridges/cctp/utils/transfer-data.test.ts +0 -83
  41. package/src/bridges/cctp/utils/transfer-data.ts +0 -48
  42. package/src/errors/bridge-error.ts +0 -11
  43. package/src/errors/bridge-initialization-error.ts +0 -9
  44. package/src/errors/bridge-unavailable-error.ts +0 -9
  45. package/src/errors/index.ts +0 -4
  46. package/src/errors/invalid-params-error.ts +0 -9
  47. package/src/index.ts +0 -3
  48. package/src/types/asset.ts +0 -26
  49. package/src/types/bridge.ts +0 -64
  50. package/src/types/chain.ts +0 -10
  51. package/src/types/config.ts +0 -10
  52. package/src/types/environment.ts +0 -4
  53. package/src/types/error.ts +0 -19
  54. package/src/types/index.ts +0 -9
  55. package/src/types/provider.ts +0 -12
  56. package/src/types/signer.ts +0 -18
  57. package/src/types/transfer.ts +0 -35
  58. package/src/unified-bridge-service.test.ts +0 -209
  59. package/src/unified-bridge-service.ts +0 -97
  60. package/src/utils/bridge-types.test.ts +0 -103
  61. package/src/utils/bridge-types.ts +0 -32
  62. package/src/utils/caip2.test.ts +0 -44
  63. package/src/utils/caip2.ts +0 -41
  64. package/src/utils/client.test.ts +0 -97
  65. package/src/utils/client.ts +0 -44
  66. package/src/utils/ensure-config.test.ts +0 -43
  67. package/src/utils/ensure-config.ts +0 -12
  68. package/src/utils/index.ts +0 -2
  69. package/src/utils/network-fee.test.ts +0 -24
  70. package/src/utils/network-fee.ts +0 -6
  71. package/src/utils/retry-promise.test.ts +0 -115
  72. package/src/utils/retry-promise.ts +0 -72
  73. package/src/utils/wait.test.ts +0 -33
  74. package/src/utils/wait.ts +0 -4
  75. package/tsconfig.jest.json +0 -7
  76. package/tsconfig.json +0 -9
  77. package/tsup.config.ts +0 -4
@@ -1,209 +0,0 @@
1
- import { BridgeUnavailableError } from './errors';
2
- import {
3
- Environment,
4
- type BridgeService,
5
- type BridgeType,
6
- type FeeParams,
7
- type TransferParams,
8
- type TrackingParams,
9
- type BridgeAsset,
10
- } from './types';
11
- import { createUnifiedBridgeService } from './unified-bridge-service';
12
- import { getBridgeForTransfer, getEnabledBridgeServices } from './utils';
13
-
14
- jest.mock('./utils');
15
-
16
- const getBridgeMock = () => ({
17
- updateConfig: jest.fn(),
18
- getAssets: jest.fn(),
19
- getFees: jest.fn(),
20
- transferAsset: jest.fn(),
21
- trackTransfer: jest.fn(),
22
- });
23
-
24
- describe('unified-bridge-service', () => {
25
- const environment = Environment.TEST;
26
- const [bridge1, bridge2, bridge3] = [getBridgeMock(), getBridgeMock(), getBridgeMock()];
27
- const enabledBridges = new Map([
28
- ['bridge1', bridge1],
29
- ['bridge2', bridge2],
30
- ['bridge3', bridge3],
31
- ]) as unknown as Map<BridgeType, BridgeService>;
32
-
33
- beforeEach(() => {
34
- jest.resetAllMocks();
35
- jest.restoreAllMocks();
36
- jest.mocked(getEnabledBridgeServices).mockReturnValue(enabledBridges);
37
- jest
38
- .mocked(getBridgeForTransfer)
39
- .mockReturnValue({ type: 'bridge2' as unknown as BridgeType, bridge: bridge2 as unknown as BridgeService });
40
- });
41
-
42
- it('creates a new unified service correctly', () => {
43
- const service = createUnifiedBridgeService({ environment });
44
-
45
- expect(getEnabledBridgeServices).toHaveBeenCalledWith(environment, undefined);
46
- expect(service).toStrictEqual({
47
- environment,
48
- bridges: enabledBridges,
49
- init: expect.any(Function),
50
- updateConfigs: expect.any(Function),
51
- estimateGas: expect.any(Function),
52
- getAssets: expect.any(Function),
53
- getFees: expect.any(Function),
54
- transferAsset: expect.any(Function),
55
- trackTransfer: expect.any(Function),
56
- canTransferAsset: expect.any(Function),
57
- });
58
- });
59
-
60
- it('initializes the service correctly', async () => {
61
- const service = createUnifiedBridgeService({ environment });
62
-
63
- await expect(service.init()).resolves.toBeUndefined();
64
- expect(bridge1.updateConfig).toHaveBeenCalled();
65
- expect(bridge2.updateConfig).toHaveBeenCalled();
66
- expect(bridge3.updateConfig).toHaveBeenCalled();
67
- });
68
-
69
- it('attempts to update bridge configs correctly', async () => {
70
- bridge2.updateConfig.mockRejectedValueOnce(new Error('some error'));
71
- const service = createUnifiedBridgeService({ environment });
72
-
73
- await expect(service.updateConfigs()).resolves.toBeUndefined();
74
- expect(bridge1.updateConfig).toHaveBeenCalled();
75
- expect(bridge2.updateConfig).toHaveBeenCalled();
76
- expect(bridge3.updateConfig).toHaveBeenCalled();
77
- });
78
-
79
- it('returns the aggregated asset list correctly', async () => {
80
- bridge1.getAssets.mockResolvedValueOnce({
81
- 'eip155:1': [
82
- { symbol: 'TOK1', destinations: { 'eip155:2': ['bridge1'] } },
83
- { symbol: 'TOK2', destinations: { 'eip155:2': ['bridge1'] } },
84
- ],
85
- });
86
- bridge2.getAssets.mockResolvedValueOnce({
87
- 'eip155:1': [
88
- { symbol: 'TOK1', destinations: { 'eip155:2': ['bridge2'] } },
89
- { symbol: 'TOK3', destinations: { 'eip155:3': ['bridge2'] } },
90
- ],
91
- 'eip155:2': [
92
- { symbol: 'TOK4', destinations: { 'eip155:1': ['bridge2'] } },
93
- { symbol: 'TOK5', destinations: { 'eip155:3': ['bridge2'] } },
94
- ],
95
- });
96
- bridge3.getAssets.mockResolvedValueOnce({
97
- 'eip155:1': [{ symbol: 'TOK1', destinations: { 'eip155:3': ['bridge3'] } }],
98
- 'eip155:3': [{ symbol: 'TOK6', destinations: { 'eip155:1': ['bridge3'] } }],
99
- });
100
-
101
- const service = createUnifiedBridgeService({ environment });
102
- const assets = await service.getAssets();
103
-
104
- expect(assets).toStrictEqual({
105
- 'eip155:1': [
106
- { symbol: 'TOK1', destinations: { 'eip155:2': ['bridge1', 'bridge2'], 'eip155:3': ['bridge3'] } },
107
- { symbol: 'TOK2', destinations: { 'eip155:2': ['bridge1'] } },
108
- { symbol: 'TOK3', destinations: { 'eip155:3': ['bridge2'] } },
109
- ],
110
- 'eip155:2': [
111
- { symbol: 'TOK4', destinations: { 'eip155:1': ['bridge2'] } },
112
- { symbol: 'TOK5', destinations: { 'eip155:3': ['bridge2'] } },
113
- ],
114
- 'eip155:3': [{ symbol: 'TOK6', destinations: { 'eip155:1': ['bridge3'] } }],
115
- });
116
- expect(bridge1.getAssets).toHaveBeenCalled();
117
- expect(bridge2.getAssets).toHaveBeenCalled();
118
- expect(bridge3.getAssets).toHaveBeenCalled();
119
- });
120
-
121
- it('returns the fee of the correct bridge', async () => {
122
- const fee = 2000n;
123
- const feeParams = {
124
- asset: { symbol: 'TOK1' },
125
- targetChain: { chainId: 'eip155:1' },
126
- } as unknown as FeeParams;
127
-
128
- bridge2.getFees.mockResolvedValueOnce(fee);
129
-
130
- const service = createUnifiedBridgeService({ environment });
131
- const result = await service.getFees(feeParams);
132
-
133
- expect(result).toBe(fee);
134
- expect(getBridgeForTransfer).toHaveBeenCalledWith(enabledBridges, feeParams.asset, feeParams.targetChain.chainId);
135
- expect(bridge1.getFees).not.toHaveBeenCalled();
136
- expect(bridge2.getFees).toHaveBeenCalledWith(feeParams);
137
- expect(bridge3.getFees).not.toHaveBeenCalled();
138
- });
139
-
140
- it('starts a transfer using the correct bridge', async () => {
141
- const transferParams = {
142
- asset: { symbol: 'TOK1' },
143
- targetChain: { chainId: 'eip155:1' },
144
- } as unknown as TransferParams;
145
- const bridgeTransfer = { type: 'bridge2' };
146
-
147
- bridge2.transferAsset.mockResolvedValueOnce(bridgeTransfer);
148
-
149
- const service = createUnifiedBridgeService({ environment });
150
- const result = await service.transferAsset(transferParams);
151
-
152
- expect(result).toStrictEqual(bridgeTransfer);
153
- expect(getBridgeForTransfer).toHaveBeenCalledWith(
154
- enabledBridges,
155
- transferParams.asset,
156
- transferParams.targetChain.chainId,
157
- );
158
- expect(bridge1.transferAsset).not.toHaveBeenCalled();
159
- expect(bridge2.transferAsset).toHaveBeenCalledWith(transferParams);
160
- expect(bridge3.transferAsset).not.toHaveBeenCalled();
161
- });
162
-
163
- it('throws if there is no enabled bridge for transfer tracking', () => {
164
- const trackingParams = {
165
- bridgeTransfer: {
166
- type: 'not-enabled-bridge',
167
- },
168
- } as unknown as TrackingParams;
169
-
170
- const service = createUnifiedBridgeService({ environment });
171
- expect(() => service.trackTransfer(trackingParams)).toThrow(BridgeUnavailableError);
172
- expect(bridge1.trackTransfer).not.toHaveBeenCalled();
173
- expect(bridge2.trackTransfer).not.toHaveBeenCalled();
174
- expect(bridge3.trackTransfer).not.toHaveBeenCalled();
175
- });
176
-
177
- it('tracks a transfer using the correct bridge', () => {
178
- const trackingParams = {
179
- bridgeTransfer: {
180
- type: 'bridge2',
181
- },
182
- } as unknown as TrackingParams;
183
- const trackingResult = {
184
- cancel: jest.fn(),
185
- };
186
-
187
- bridge2.trackTransfer.mockReturnValueOnce(trackingResult);
188
-
189
- const service = createUnifiedBridgeService({ environment });
190
- const result = service.trackTransfer(trackingParams);
191
-
192
- expect(result).toStrictEqual(trackingResult);
193
- expect(bridge1.trackTransfer).not.toHaveBeenCalled();
194
- expect(bridge2.trackTransfer).toHaveBeenCalledWith(trackingParams);
195
- expect(bridge3.trackTransfer).not.toHaveBeenCalled();
196
- });
197
-
198
- it('can tell whether it can transfer an asset to target chain ahead of time', () => {
199
- const service = createUnifiedBridgeService({ environment });
200
-
201
- expect(service.canTransferAsset({ symbol: 'TOK1' } as unknown as BridgeAsset, 'eip155:1')).toBe(true);
202
-
203
- jest.mocked(getBridgeForTransfer).mockImplementationOnce(() => {
204
- throw new BridgeUnavailableError();
205
- });
206
-
207
- expect(service.canTransferAsset({ symbol: 'TOK1' } as unknown as BridgeAsset, 'eip155:2')).toBe(false);
208
- });
209
- });
@@ -1,97 +0,0 @@
1
- import type { FeeParams, TrackingParams, TransferParams } from './types/bridge';
2
- import type { BridgeServiceConfig } from './types/config';
3
- import { getBridgeForTransfer, getEnabledBridgeServices } from './utils';
4
- import type { BridgeAsset, ChainAssetMap } from './types';
5
- import { isArray, mergeWith } from 'lodash';
6
- import { BridgeUnavailableError } from './errors';
7
-
8
- export const createUnifiedBridgeService = ({ environment, disabledBridgeTypes }: BridgeServiceConfig) => {
9
- const enabledBridgeServices = getEnabledBridgeServices(environment, disabledBridgeTypes);
10
-
11
- const updateConfigs = async () => {
12
- await Promise.allSettled(
13
- Array.from(enabledBridgeServices).map(([, bridgeService]) => bridgeService.updateConfig()),
14
- );
15
- };
16
-
17
- const init = async () => {
18
- await updateConfigs();
19
- };
20
-
21
- const getAssets = async () => {
22
- const assets = await Promise.all(Array.from(enabledBridgeServices).map(([, bridge]) => bridge.getAssets()));
23
- return assets.reduce<ChainAssetMap>((aggregatedAssets, chainAssetMap) => {
24
- for (const [chainId, bridgeAssets] of Object.entries(chainAssetMap)) {
25
- const existingAssets = aggregatedAssets[chainId];
26
-
27
- if (existingAssets) {
28
- for (const bridgeAsset of bridgeAssets) {
29
- const index = existingAssets.findIndex(({ symbol }) => symbol === bridgeAsset.symbol);
30
-
31
- if (index === -1) {
32
- existingAssets.push(bridgeAsset);
33
- } else {
34
- mergeWith(existingAssets[index], bridgeAsset, (objValue, srcValue) => {
35
- if (isArray(objValue)) {
36
- return [...new Set(objValue.concat(srcValue))];
37
- }
38
- });
39
- }
40
- }
41
- } else {
42
- aggregatedAssets[chainId] = bridgeAssets;
43
- }
44
- }
45
-
46
- return aggregatedAssets;
47
- }, {});
48
- };
49
-
50
- const getFees = async (params: FeeParams) => {
51
- const { bridge } = getBridgeForTransfer(enabledBridgeServices, params.asset, params.targetChain.chainId);
52
- return bridge.getFees(params);
53
- };
54
-
55
- const transferAsset = async (params: TransferParams) => {
56
- const { bridge } = getBridgeForTransfer(enabledBridgeServices, params.asset, params.targetChain.chainId);
57
- return bridge.transferAsset(params);
58
- };
59
-
60
- const canTransferAsset = (asset: BridgeAsset, targetChainId: string) => {
61
- try {
62
- getBridgeForTransfer(enabledBridgeServices, asset, targetChainId);
63
- return true;
64
- } catch {
65
- return false;
66
- }
67
- };
68
-
69
- const trackTransfer = (params: TrackingParams) => {
70
- const bridge = enabledBridgeServices.get(params.bridgeTransfer.type);
71
-
72
- if (!bridge) {
73
- throw new BridgeUnavailableError();
74
- }
75
-
76
- return bridge.trackTransfer(params);
77
- };
78
-
79
- const estimateGas = async (params: TransferParams) => {
80
- const { bridge } = getBridgeForTransfer(enabledBridgeServices, params.asset, params.targetChain.chainId);
81
-
82
- return bridge.estimateGas(params);
83
- };
84
-
85
- return {
86
- environment,
87
- bridges: enabledBridgeServices,
88
- init,
89
- updateConfigs,
90
- getAssets,
91
- getFees,
92
- estimateGas,
93
- canTransferAsset,
94
- transferAsset,
95
- trackTransfer,
96
- };
97
- };
@@ -1,103 +0,0 @@
1
- import { BridgeUnavailableError } from '../errors';
2
- import {
3
- Environment,
4
- type BridgeType,
5
- type BridgeServiceFactory,
6
- type BridgeService,
7
- type BridgeAsset,
8
- } from '../types';
9
- import * as bridgeTypes from './bridge-types';
10
-
11
- const getBridgeMock = () => ({
12
- updateConfig: jest.fn(),
13
- getAssets: jest.fn(),
14
- getFees: jest.fn(),
15
- transferAsset: jest.fn(),
16
- trackTransfer: jest.fn(),
17
- });
18
-
19
- describe('bridge-types', () => {
20
- const environment = Environment.TEST;
21
-
22
- beforeEach(() => {
23
- jest.resetAllMocks();
24
- });
25
-
26
- describe('getEnabledBridgeServices', () => {
27
- let realSupportedBridges: Map<BridgeType, BridgeServiceFactory>;
28
-
29
- const [bridge1, bridge2, bridge3] = [jest.fn(), jest.fn(), jest.fn()];
30
- const enabledBridges = new Map([
31
- ['bridge1', bridge1],
32
- ['bridge2', bridge2],
33
- ['bridge3', bridge3],
34
- ]) as unknown as Map<BridgeType, BridgeServiceFactory>;
35
-
36
- beforeAll(() => {
37
- realSupportedBridges = bridgeTypes.supportedBridges;
38
-
39
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
40
- // @ts-ignore
41
- bridgeTypes.supportedBridges = enabledBridges;
42
- });
43
-
44
- afterAll(() => {
45
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
46
- // @ts-ignore
47
- bridgeTypes.supportedBridges = realSupportedBridges;
48
- });
49
-
50
- beforeEach(() => {
51
- bridge1.mockReturnValueOnce({ type: 'bridge1' });
52
- bridge2.mockReturnValueOnce({ type: 'bridge2' });
53
- bridge3.mockReturnValueOnce({ type: 'bridge3' });
54
- });
55
-
56
- it('returns all of the supported bridges correctly', () => {
57
- const bridges = bridgeTypes.getEnabledBridgeServices(environment);
58
- expect(bridges).toStrictEqual(
59
- new Map([
60
- ['bridge1', { type: 'bridge1' }],
61
- ['bridge2', { type: 'bridge2' }],
62
- ['bridge3', { type: 'bridge3' }],
63
- ]),
64
- );
65
- });
66
-
67
- it('returns all of the enabled bridges correctly', () => {
68
- const bridges = bridgeTypes.getEnabledBridgeServices(environment, ['bridge2' as unknown as BridgeType]);
69
- expect(bridges).toStrictEqual(
70
- new Map([
71
- ['bridge1', { type: 'bridge1' }],
72
- ['bridge3', { type: 'bridge3' }],
73
- ]),
74
- );
75
- });
76
- });
77
-
78
- describe('getBridgeForTransfer', () => {
79
- const [bridge1, bridge2, bridge3] = [getBridgeMock(), getBridgeMock(), getBridgeMock()];
80
- const enabledBridges = new Map([
81
- ['bridge1', bridge1],
82
- ['bridge2', bridge2],
83
- ['bridge3', bridge3],
84
- ]) as unknown as Map<BridgeType, BridgeService>;
85
- const asset = {
86
- destinations: {
87
- 'eip155:2': ['bridge1', 'bridge3'],
88
- },
89
- } as unknown as BridgeAsset;
90
-
91
- it('throws if no enabled bridge found', () => {
92
- expect(() => bridgeTypes.getBridgeForTransfer(enabledBridges, asset, 'eip155:1')).toThrow(BridgeUnavailableError);
93
- });
94
-
95
- it('returns the correct bridge for the transfer', () => {
96
- const result = bridgeTypes.getBridgeForTransfer(enabledBridges, asset, 'eip155:2');
97
- expect(result).toStrictEqual({
98
- type: 'bridge1',
99
- bridge: bridge1,
100
- });
101
- });
102
- });
103
- });
@@ -1,32 +0,0 @@
1
- import { cctpBridgeFactory } from '../bridges/cctp/factory';
2
- import { BridgeUnavailableError } from '../errors';
3
- import type { BridgeAsset } from '../types/asset';
4
- import { type BridgeService, BridgeType } from '../types/bridge';
5
- import { Environment } from '../types/environment';
6
-
7
- export const supportedBridges = new Map([[BridgeType.CCTP, cctpBridgeFactory]]);
8
-
9
- export const getEnabledBridgeServices = (environment: Environment, disabledBridgeTypes?: BridgeType[]) => {
10
- return new Map(
11
- [...supportedBridges]
12
- .filter(([bridgeType]) => !disabledBridgeTypes?.includes(bridgeType))
13
- .map(([bridgeType, factory]) => [bridgeType, factory(environment)]),
14
- );
15
- };
16
-
17
- export const getBridgeForTransfer = (
18
- enabledBridgeServices: Map<BridgeType, BridgeService>,
19
- asset: BridgeAsset,
20
- targetChainId: string,
21
- ) => {
22
- const bridgeType = asset.destinations[targetChainId]?.find((bridgeType) => enabledBridgeServices.has(bridgeType));
23
-
24
- if (!bridgeType) {
25
- throw new BridgeUnavailableError();
26
- }
27
-
28
- return {
29
- type: bridgeType,
30
- bridge: enabledBridgeServices.get(bridgeType)!,
31
- };
32
- };
@@ -1,44 +0,0 @@
1
- import caip2 from './caip2';
2
-
3
- describe('caip2', () => {
4
- describe('toJSON', () => {
5
- it.each(['', '1.', '1:', ':2'])('throws when the identifier is invalid', (identifier) => {
6
- expect(() => caip2.toJSON(identifier)).toThrow('Invalid identifier provided.');
7
- });
8
-
9
- it.each(['1:2', 'toolongnamespace:2', '!:2'])('throws when the namespace is invalid', (identifier) => {
10
- expect(() => caip2.toJSON(identifier)).toThrow('Invalid namespace provided.');
11
- });
12
-
13
- it.each(['eip155:!', 'eip155:toolong-2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM'])(
14
- 'throws when the reference is invalid',
15
- (identifier) => {
16
- expect(() => caip2.toJSON(identifier)).toThrow('Invalid reference provided.');
17
- },
18
- );
19
-
20
- it.each([
21
- {
22
- identifier: 'eip155:1',
23
- expected: { namespace: 'eip155', reference: '1' },
24
- },
25
- {
26
- identifier: 'bip122:000000000019d6689c085ae165831e93',
27
- expected: { namespace: 'bip122', reference: '000000000019d6689c085ae165831e93' },
28
- },
29
- {
30
- identifier: 'ava:2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM',
31
- expected: { namespace: 'ava', reference: '2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM' },
32
- },
33
- ])('returns the correct caip2 object', ({ identifier, expected }) => {
34
- expect(caip2.toJSON(identifier)).toStrictEqual(expected);
35
- });
36
- });
37
-
38
- it('returns the correct identifier', () => {
39
- const namespace = 'eip155';
40
- const reference = '1';
41
-
42
- expect(caip2.toString({ namespace, reference })).toBe('eip155:1');
43
- });
44
- });
@@ -1,41 +0,0 @@
1
- // ref: https://chainagnostic.org/CAIPs/caip-2
2
-
3
- export type Caip2ChainId = {
4
- namespace: string;
5
- reference: string;
6
- };
7
-
8
- const namespacePattern = '^[-a-z0-9]{3,8}$';
9
- // the standard allows up to 32 characters for the reference part, but we have to set it to 50 so it accepts our cb58 encoded chain IDs
10
- const referencePattern = '^[-_a-zA-Z0-9]{1,50}$';
11
- const delimeter = ':';
12
-
13
- const toJSON = (identifier: string): Caip2ChainId => {
14
- const [namespace, reference] = identifier.split(delimeter);
15
-
16
- if (!namespace || !reference) {
17
- throw new Error('Invalid identifier provided.');
18
- }
19
-
20
- if (!new RegExp(namespacePattern).test(namespace)) {
21
- throw new Error('Invalid namespace provided.');
22
- }
23
-
24
- if (!new RegExp(referencePattern).test(reference)) {
25
- throw new Error('Invalid reference provided.');
26
- }
27
-
28
- return {
29
- namespace,
30
- reference,
31
- };
32
- };
33
-
34
- const toString = ({ namespace, reference }: Caip2ChainId) => {
35
- return `${namespace}${delimeter}${reference}`;
36
- };
37
-
38
- export default {
39
- toJSON,
40
- toString,
41
- };
@@ -1,97 +0,0 @@
1
- import {
2
- custom,
3
- http,
4
- type CustomTransport,
5
- type HttpTransport,
6
- createWalletClient,
7
- type WalletClient,
8
- publicActions,
9
- } from 'viem';
10
- import { TokenType, type Chain, type Provider } from '../types';
11
- import { getClientForChain } from './client';
12
-
13
- jest.mock('viem');
14
-
15
- const chainMock: Chain = {
16
- chainId: 'eip155:1',
17
- chainName: 'test chain',
18
- networkToken: {
19
- decimals: 18,
20
- symbol: 'TEST',
21
- name: 'Test Token',
22
- type: TokenType.NATIVE,
23
- },
24
- rpcUrl: 'http://test.com',
25
- utilityAddresses: {
26
- multicall: '0x1',
27
- },
28
- };
29
-
30
- const chainInfo = {
31
- id: 1,
32
- name: chainMock.chainName,
33
- nativeCurrency: {
34
- decimals: chainMock.networkToken.decimals,
35
- symbol: chainMock.networkToken.symbol,
36
- name: chainMock.networkToken.name,
37
- },
38
- network: chainMock.chainName,
39
- rpcUrls: {
40
- default: {
41
- http: [chainMock.rpcUrl],
42
- },
43
- public: {
44
- http: [chainMock.rpcUrl],
45
- },
46
- },
47
- ...(chainMock.utilityAddresses?.multicall && {
48
- contracts: {
49
- multicall3: {
50
- address: chainMock.utilityAddresses.multicall,
51
- },
52
- },
53
- }),
54
- };
55
-
56
- describe('client', () => {
57
- const transportMock = { type: 'transport' };
58
- const walletClientMock = { type: 'client', extend: jest.fn() };
59
- const extendedWalletClientMock = { ...walletClientMock, extended: true };
60
-
61
- beforeEach(() => {
62
- jest.resetAllMocks();
63
-
64
- walletClientMock.extend.mockReturnValueOnce(extendedWalletClientMock);
65
-
66
- jest.mocked(http).mockReturnValueOnce(transportMock as unknown as HttpTransport);
67
- jest.mocked(custom).mockReturnValueOnce(transportMock as unknown as CustomTransport);
68
- jest.mocked(createWalletClient).mockReturnValueOnce(walletClientMock as unknown as WalletClient);
69
- });
70
-
71
- it('returns the client correctly without predefined provider', () => {
72
- const client = getClientForChain({ chain: chainMock });
73
- expect(client).toStrictEqual(extendedWalletClientMock);
74
-
75
- expect(custom).not.toHaveBeenCalled();
76
- expect(http).toHaveBeenCalledWith(chainMock.rpcUrl, { batch: true, retryCount: 0 });
77
- expect(createWalletClient).toHaveBeenCalledWith({
78
- chain: chainInfo,
79
- transport: transportMock,
80
- });
81
- expect(walletClientMock.extend).toHaveBeenCalledWith(publicActions);
82
- });
83
-
84
- it('returns the client correctly with a predefined provider', () => {
85
- const providerMock = { type: 'provider' } as unknown as Provider;
86
- const client = getClientForChain({ chain: chainMock, provider: providerMock });
87
- expect(client).toStrictEqual(extendedWalletClientMock);
88
-
89
- expect(http).not.toHaveBeenCalled();
90
- expect(custom).toHaveBeenCalledWith(providerMock);
91
- expect(createWalletClient).toHaveBeenCalledWith({
92
- chain: chainInfo,
93
- transport: transportMock,
94
- });
95
- expect(walletClientMock.extend).toHaveBeenCalledWith(publicActions);
96
- });
97
- });
@@ -1,44 +0,0 @@
1
- import { createWalletClient, publicActions, custom, http } from 'viem';
2
- import type { Chain } from '../types/chain';
3
- import type { Provider } from '../types';
4
- import caip2 from './caip2';
5
-
6
- const _getChain = (chain: Chain) => {
7
- const { reference: chainId } = caip2.toJSON(chain.chainId);
8
-
9
- return {
10
- id: Number(chainId),
11
- name: chain.chainName,
12
- nativeCurrency: {
13
- decimals: chain.networkToken.decimals,
14
- symbol: chain.networkToken.symbol,
15
- name: chain.networkToken.name,
16
- },
17
- network: chain.chainName,
18
- rpcUrls: {
19
- default: {
20
- http: [chain.rpcUrl],
21
- },
22
- public: {
23
- http: [chain.rpcUrl],
24
- },
25
- },
26
- ...(chain.utilityAddresses?.multicall && {
27
- contracts: {
28
- multicall3: {
29
- address: chain.utilityAddresses.multicall,
30
- },
31
- },
32
- }),
33
- };
34
- };
35
-
36
- export const getClientForChain = ({ chain, provider }: { chain: Chain; provider?: Provider }) => {
37
- const chainInfo = _getChain(chain);
38
- const transport = provider ? custom(provider) : http(chain.rpcUrl, { batch: true, retryCount: 0 });
39
-
40
- return createWalletClient({
41
- chain: chainInfo,
42
- transport,
43
- }).extend(publicActions);
44
- };