@hyperlane-xyz/registry 1.3.0 → 2.0.0

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 (101) hide show
  1. package/dist/chainAddresses.d.ts +23 -0
  2. package/dist/chainAddresses.js +23 -0
  3. package/dist/chainMetadata.js +83 -0
  4. package/dist/chains/arbitrum/metadata.js +6 -0
  5. package/dist/chains/arbitrum/metadata.json +6 -0
  6. package/dist/chains/arbitrum/metadata.yaml +2 -0
  7. package/dist/chains/blast/logo.svg +5 -1
  8. package/dist/chains/holesky/metadata.js +1 -0
  9. package/dist/chains/holesky/metadata.json +1 -0
  10. package/dist/chains/holesky/metadata.yaml +1 -0
  11. package/dist/chains/mantapacific/metadata.js +1 -0
  12. package/dist/chains/mantapacific/metadata.json +1 -0
  13. package/dist/chains/mantapacific/metadata.yaml +1 -0
  14. package/dist/chains/sketchpad/addresses.d.ts +23 -0
  15. package/dist/chains/sketchpad/addresses.js +23 -0
  16. package/dist/chains/sketchpad/addresses.json +23 -0
  17. package/dist/chains/sketchpad/addresses.yaml +21 -0
  18. package/dist/chains/sketchpad/index.d.ts +2 -0
  19. package/dist/chains/sketchpad/index.js +2 -0
  20. package/dist/chains/sketchpad/logo.svg +17 -0
  21. package/dist/chains/sketchpad/metadata.d.ts +2 -0
  22. package/dist/chains/sketchpad/metadata.js +27 -0
  23. package/dist/chains/sketchpad/metadata.json +27 -0
  24. package/dist/chains/sketchpad/metadata.yaml +19 -0
  25. package/dist/chains/stride/index.d.ts +1 -0
  26. package/dist/chains/stride/index.js +1 -0
  27. package/dist/chains/stride/logo.svg +4 -0
  28. package/dist/chains/stride/metadata.d.ts +2 -0
  29. package/dist/chains/stride/metadata.js +48 -0
  30. package/dist/chains/stride/metadata.json +48 -0
  31. package/dist/chains/stride/metadata.yaml +32 -0
  32. package/dist/consts.d.ts +2 -0
  33. package/dist/consts.js +2 -0
  34. package/dist/coreChainMetadata.js +7 -0
  35. package/dist/deployments/warp_routes/ECLIP/arbitrum-neutron-config.d.ts +48 -0
  36. package/dist/deployments/warp_routes/ECLIP/arbitrum-neutron-config.js +34 -0
  37. package/dist/deployments/warp_routes/ECLIP/arbitrum-neutron-config.json +34 -0
  38. package/dist/deployments/warp_routes/ECLIP/arbitrum-neutron-config.yaml.yaml +22 -0
  39. package/dist/deployments/warp_routes/ETH/ethereum-viction-config.d.ts +48 -0
  40. package/dist/deployments/warp_routes/ETH/ethereum-viction-config.js +32 -0
  41. package/dist/deployments/warp_routes/ETH/ethereum-viction-config.json +32 -0
  42. package/dist/deployments/warp_routes/ETH/ethereum-viction-config.yaml.yaml +20 -0
  43. package/dist/deployments/warp_routes/INJ/injective-inevm-config.d.ts +48 -0
  44. package/dist/deployments/warp_routes/INJ/injective-inevm-config.js +50 -0
  45. package/dist/deployments/warp_routes/INJ/injective-inevm-config.json +50 -0
  46. package/dist/deployments/warp_routes/INJ/injective-inevm-config.yaml.yaml +31 -0
  47. package/dist/deployments/warp_routes/TIA/arbitrum-neutron-config.d.ts +48 -0
  48. package/dist/deployments/warp_routes/TIA/arbitrum-neutron-config.js +43 -0
  49. package/dist/deployments/warp_routes/TIA/arbitrum-neutron-config.json +43 -0
  50. package/dist/deployments/warp_routes/TIA/arbitrum-neutron-config.yaml.yaml +27 -0
  51. package/dist/deployments/warp_routes/TIA/manta-neutron-config.d.ts +48 -0
  52. package/dist/deployments/warp_routes/TIA/manta-neutron-config.js +43 -0
  53. package/dist/deployments/warp_routes/TIA/manta-neutron-config.json +43 -0
  54. package/dist/deployments/warp_routes/TIA/manta-neutron-config.yaml.yaml +27 -0
  55. package/dist/deployments/warp_routes/TIA/stride-sketchpad-config.d.ts +48 -0
  56. package/dist/deployments/warp_routes/TIA/stride-sketchpad-config.js +49 -0
  57. package/dist/deployments/warp_routes/TIA/stride-sketchpad-config.json +49 -0
  58. package/dist/deployments/warp_routes/TIA/stride-sketchpad-config.yaml.yaml +31 -0
  59. package/dist/deployments/warp_routes/USDC/ethereum-ancient8-config.d.ts +48 -0
  60. package/dist/deployments/warp_routes/USDC/ethereum-ancient8-config.js +33 -0
  61. package/dist/deployments/warp_routes/USDC/ethereum-ancient8-config.json +33 -0
  62. package/dist/deployments/warp_routes/USDC/ethereum-ancient8-config.yaml.yaml +21 -0
  63. package/dist/deployments/warp_routes/USDC/ethereum-inevm-config.d.ts +48 -0
  64. package/dist/deployments/warp_routes/USDC/ethereum-inevm-config.js +33 -0
  65. package/dist/deployments/warp_routes/USDC/ethereum-inevm-config.json +33 -0
  66. package/dist/deployments/warp_routes/USDC/ethereum-inevm-config.yaml.yaml +21 -0
  67. package/dist/deployments/warp_routes/USDC/ethereum-viction-config.d.ts +48 -0
  68. package/dist/deployments/warp_routes/USDC/ethereum-viction-config.js +33 -0
  69. package/dist/deployments/warp_routes/USDC/ethereum-viction-config.json +33 -0
  70. package/dist/deployments/warp_routes/USDC/ethereum-viction-config.yaml.yaml +21 -0
  71. package/dist/deployments/warp_routes/USDT/ethereum-inevm-config.d.ts +48 -0
  72. package/dist/deployments/warp_routes/USDT/ethereum-inevm-config.js +33 -0
  73. package/dist/deployments/warp_routes/USDT/ethereum-inevm-config.json +33 -0
  74. package/dist/deployments/warp_routes/USDT/ethereum-inevm-config.yaml.yaml +21 -0
  75. package/dist/deployments/warp_routes/USDT/ethereum-viction-config.d.ts +48 -0
  76. package/dist/deployments/warp_routes/USDT/ethereum-viction-config.js +33 -0
  77. package/dist/deployments/warp_routes/USDT/ethereum-viction-config.json +33 -0
  78. package/dist/deployments/warp_routes/USDT/ethereum-viction-config.yaml.yaml +21 -0
  79. package/dist/index.d.ts +7 -2
  80. package/dist/index.js +7 -2
  81. package/dist/registry/BaseRegistry.d.ts +9 -13
  82. package/dist/registry/BaseRegistry.js +11 -3
  83. package/dist/registry/FileSystemRegistry.d.ts +6 -8
  84. package/dist/registry/FileSystemRegistry.js +38 -16
  85. package/dist/registry/GithubRegistry.d.ts +10 -13
  86. package/dist/registry/GithubRegistry.js +48 -15
  87. package/dist/registry/IRegistry.d.ts +18 -12
  88. package/dist/registry/MergedRegistry.d.ts +7 -12
  89. package/dist/registry/MergedRegistry.js +15 -2
  90. package/dist/registry/PartialRegistry.d.ts +9 -6
  91. package/dist/registry/PartialRegistry.js +19 -2
  92. package/dist/registry/SynchronousRegistry.d.ts +8 -17
  93. package/dist/registry/SynchronousRegistry.js +11 -0
  94. package/dist/registry/warp-utils.d.ts +31 -2
  95. package/dist/registry/warp-utils.js +56 -0
  96. package/dist/types.d.ts +6 -0
  97. package/dist/utils.d.ts +1 -0
  98. package/dist/utils.js +3 -0
  99. package/dist/warpRouteConfigs.d.ts +48 -0
  100. package/dist/warpRouteConfigs.js +418 -0
  101. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import type { Logger } from 'pino';
2
2
  import type { ChainMap, ChainMetadata, ChainName, WarpCoreConfig } from '@hyperlane-xyz/sdk';
3
- import { ChainAddresses } from '../types.js';
3
+ import { ChainAddresses, WarpRouteConfigMap } from '../types.js';
4
4
  import { BaseRegistry } from './BaseRegistry.js';
5
- import { RegistryType, type ChainFiles, type IRegistry, type RegistryContent } from './IRegistry.js';
5
+ import { ChainFiles, IRegistry, RegistryContent, RegistryType, UpdateChainParams, WarpRouteFilterParams } from './IRegistry.js';
6
6
  export interface GithubRegistryOptions {
7
7
  uri?: string;
8
8
  branch?: string;
@@ -21,26 +21,23 @@ export declare class GithubRegistry extends BaseRegistry implements IRegistry {
21
21
  readonly repoOwner: string;
22
22
  readonly repoName: string;
23
23
  constructor(options?: GithubRegistryOptions);
24
+ getUri(itemPath?: string): string;
24
25
  listRegistryContent(): Promise<RegistryContent>;
25
26
  getChains(): Promise<Array<ChainName>>;
26
27
  getMetadata(): Promise<ChainMap<ChainMetadata>>;
27
28
  getChainMetadata(chainName: ChainName): Promise<ChainMetadata | null>;
28
29
  getAddresses(): Promise<ChainMap<ChainAddresses>>;
29
30
  getChainAddresses(chainName: ChainName): Promise<ChainAddresses | null>;
30
- addChain(_chains: {
31
- chainName: ChainName;
32
- metadata?: ChainMetadata;
33
- addresses?: ChainAddresses;
34
- }): Promise<void>;
35
- updateChain(_chains: {
36
- chainName: ChainName;
37
- metadata?: ChainMetadata;
38
- addresses?: ChainAddresses;
39
- }): Promise<void>;
31
+ addChain(_chains: UpdateChainParams): Promise<void>;
32
+ updateChain(_chains: UpdateChainParams): Promise<void>;
40
33
  removeChain(_chains: ChainName): Promise<void>;
34
+ getWarpRoute(routeId: string): Promise<WarpCoreConfig | null>;
35
+ getWarpRoutes(filter?: WarpRouteFilterParams): Promise<WarpRouteConfigMap>;
41
36
  addWarpRoute(_config: WarpCoreConfig): Promise<void>;
42
37
  protected getRawContentUrl(path: string): string;
43
38
  protected fetchChainFiles<T>(fileName: keyof ChainFiles, chainNames?: ChainName[]): Promise<ChainMap<T>>;
44
- protected fetchSingleChainFile<T>(fileName: keyof ChainFiles, chainName: ChainName): Promise<T | null>;
39
+ protected fetchChainFile<T>(fileName: keyof ChainFiles, chainName: ChainName): Promise<T | null>;
40
+ protected fetchYamlFiles<T>(urls: string[]): Promise<T[]>;
41
+ protected fetchYamlFile<T>(url: string): Promise<T>;
45
42
  protected fetch(url: string): Promise<Response>;
46
43
  }
@@ -1,8 +1,9 @@
1
1
  import { parse as yamlParse } from 'yaml';
2
- import { DEFAULT_GITHUB_REGISTRY, GITHUB_FETCH_CONCURRENCY_LIMIT } from '../consts.js';
3
- import { concurrentMap } from '../utils.js';
4
- import { BaseRegistry, CHAIN_FILE_REGEX } from './BaseRegistry.js';
2
+ import { CHAIN_FILE_REGEX, DEFAULT_GITHUB_REGISTRY, GITHUB_FETCH_CONCURRENCY_LIMIT, WARP_ROUTE_CONFIG_FILE_REGEX, } from '../consts.js';
3
+ import { concurrentMap, stripLeadingSlash } from '../utils.js';
4
+ import { BaseRegistry } from './BaseRegistry.js';
5
5
  import { RegistryType, } from './IRegistry.js';
6
+ import { filterWarpRoutesIds, warpRouteConfigPathToId } from './warp-utils.js';
6
7
  /**
7
8
  * A registry that uses a github repository as its data source.
8
9
  * Reads are performed via the github API and github's raw content URLs.
@@ -24,6 +25,11 @@ export class GithubRegistry extends BaseRegistry {
24
25
  this.repoOwner = pathSegments.at(-2);
25
26
  this.repoName = pathSegments.at(-1);
26
27
  }
28
+ getUri(itemPath) {
29
+ if (!itemPath)
30
+ return super.getUri();
31
+ return this.getRawContentUrl(itemPath);
32
+ }
27
33
  async listRegistryContent() {
28
34
  if (this.listContentCache)
29
35
  return this.listContentCache;
@@ -35,6 +41,7 @@ export class GithubRegistry extends BaseRegistry {
35
41
  const tree = result.tree;
36
42
  const chainPath = this.getChainsPath();
37
43
  const chains = {};
44
+ const warpRoutes = {};
38
45
  for (const node of tree) {
39
46
  if (CHAIN_FILE_REGEX.test(node.path)) {
40
47
  const [_, chainName, fileName, extension] = node.path.match(CHAIN_FILE_REGEX);
@@ -42,9 +49,12 @@ export class GithubRegistry extends BaseRegistry {
42
49
  // @ts-ignore allow dynamic key assignment
43
50
  chains[chainName][fileName] = this.getRawContentUrl(`${chainPath}/${chainName}/${fileName}.${extension}`);
44
51
  }
45
- // TODO add handling for deployment artifact files here too
52
+ if (WARP_ROUTE_CONFIG_FILE_REGEX.test(node.path)) {
53
+ const routeId = warpRouteConfigPathToId(node.path);
54
+ warpRoutes[routeId] = this.getRawContentUrl(node.path);
55
+ }
46
56
  }
47
- return (this.listContentCache = { chains, deployments: {} });
57
+ return (this.listContentCache = { chains, deployments: { warpRoutes } });
48
58
  }
49
59
  async getChains() {
50
60
  const repoContents = await this.listRegistryContent();
@@ -60,7 +70,7 @@ export class GithubRegistry extends BaseRegistry {
60
70
  async getChainMetadata(chainName) {
61
71
  if (this.metadataCache?.[chainName])
62
72
  return this.metadataCache[chainName];
63
- const data = await this.fetchSingleChainFile('metadata', chainName);
73
+ const data = await this.fetchChainFile('metadata', chainName);
64
74
  if (!data)
65
75
  return null;
66
76
  this.metadataCache = { ...this.metadataCache, [chainName]: data };
@@ -76,7 +86,7 @@ export class GithubRegistry extends BaseRegistry {
76
86
  async getChainAddresses(chainName) {
77
87
  if (this.addressCache?.[chainName])
78
88
  return this.addressCache[chainName];
79
- const data = await this.fetchSingleChainFile('addresses', chainName);
89
+ const data = await this.fetchChainFile('addresses', chainName);
80
90
  if (!data)
81
91
  return null;
82
92
  this.addressCache = { ...this.addressCache, [chainName]: data };
@@ -91,10 +101,25 @@ export class GithubRegistry extends BaseRegistry {
91
101
  async removeChain(_chains) {
92
102
  throw new Error('TODO: Implement');
93
103
  }
104
+ async getWarpRoute(routeId) {
105
+ const repoContents = await this.listRegistryContent();
106
+ const routeConfigUrl = repoContents.deployments.warpRoutes[routeId];
107
+ if (!routeConfigUrl)
108
+ return null;
109
+ return this.fetchYamlFile(routeConfigUrl);
110
+ }
111
+ async getWarpRoutes(filter) {
112
+ const warpRoutes = (await this.listRegistryContent()).deployments.warpRoutes;
113
+ const { ids: routeIds, values: routeConfigUrls } = filterWarpRoutesIds(warpRoutes, filter);
114
+ const configs = await this.fetchYamlFiles(routeConfigUrls);
115
+ const idsWithConfigs = routeIds.map((id, i) => [id, configs[i]]);
116
+ return Object.fromEntries(idsWithConfigs);
117
+ }
94
118
  async addWarpRoute(_config) {
95
119
  throw new Error('TODO: Implement');
96
120
  }
97
121
  getRawContentUrl(path) {
122
+ path = stripLeadingSlash(path);
98
123
  return `https://raw.githubusercontent.com/${this.repoOwner}/${this.repoName}/${this.branch}/${path}`;
99
124
  }
100
125
  // Fetches all files of a particular type in parallel
@@ -108,17 +133,25 @@ export class GithubRegistry extends BaseRegistry {
108
133
  acc[chainName] = fileUrl;
109
134
  return acc;
110
135
  }, {});
111
- const results = await concurrentMap(GITHUB_FETCH_CONCURRENCY_LIMIT, Object.entries(fileUrls), async ([chainName, fileUrl]) => {
112
- const response = await this.fetch(fileUrl);
113
- const data = await response.text();
114
- return [chainName, yamlParse(data)];
115
- });
116
- return Object.fromEntries(results);
117
- }
118
- async fetchSingleChainFile(fileName, chainName) {
136
+ const results = await this.fetchYamlFiles(Object.values(fileUrls));
137
+ const chainNameWithResult = chainNames.map((chainName, i) => [
138
+ chainName,
139
+ results[i],
140
+ ]);
141
+ return Object.fromEntries(chainNameWithResult);
142
+ }
143
+ async fetchChainFile(fileName, chainName) {
119
144
  const results = await this.fetchChainFiles(fileName, [chainName]);
120
145
  return results[chainName] ?? null;
121
146
  }
147
+ fetchYamlFiles(urls) {
148
+ return concurrentMap(GITHUB_FETCH_CONCURRENCY_LIMIT, urls, (url) => this.fetchYamlFile(url));
149
+ }
150
+ async fetchYamlFile(url) {
151
+ const response = await this.fetch(url);
152
+ const data = await response.text();
153
+ return yamlParse(data);
154
+ }
122
155
  async fetch(url) {
123
156
  this.logger.debug(`Fetching from github: ${url}`);
124
157
  const response = await fetch(url);
@@ -1,5 +1,5 @@
1
1
  import type { ChainMap, ChainMetadata, ChainName, WarpCoreConfig } from '@hyperlane-xyz/sdk';
2
- import type { ChainAddresses, MaybePromise } from '../types.js';
2
+ import { ChainAddresses, MaybePromise, WarpRouteConfigMap, WarpRouteId } from '../types.js';
3
3
  export interface ChainFiles {
4
4
  metadata?: string;
5
5
  addresses?: string;
@@ -7,7 +7,18 @@ export interface ChainFiles {
7
7
  }
8
8
  export interface RegistryContent {
9
9
  chains: ChainMap<ChainFiles>;
10
- deployments: {};
10
+ deployments: {
11
+ warpRoutes: Record<WarpRouteId, string>;
12
+ };
13
+ }
14
+ export interface UpdateChainParams {
15
+ chainName: ChainName;
16
+ metadata?: ChainMetadata;
17
+ addresses?: ChainAddresses;
18
+ }
19
+ export interface WarpRouteFilterParams {
20
+ symbol?: string;
21
+ chainName?: ChainName;
11
22
  }
12
23
  export declare enum RegistryType {
13
24
  Github = "github",
@@ -18,6 +29,7 @@ export declare enum RegistryType {
18
29
  export interface IRegistry {
19
30
  type: RegistryType;
20
31
  uri: string;
32
+ getUri(itemPath?: string): string;
21
33
  listRegistryContent(): MaybePromise<RegistryContent>;
22
34
  getChains(): MaybePromise<Array<ChainName>>;
23
35
  getMetadata(): MaybePromise<ChainMap<ChainMetadata>>;
@@ -25,17 +37,11 @@ export interface IRegistry {
25
37
  getAddresses(): MaybePromise<ChainMap<ChainAddresses>>;
26
38
  getChainAddresses(chainName: ChainName): MaybePromise<ChainAddresses | null>;
27
39
  getChainLogoUri(chainName: ChainName): Promise<string | null>;
28
- addChain(chain: {
29
- chainName: ChainName;
30
- metadata?: ChainMetadata;
31
- addresses?: ChainAddresses;
32
- }): MaybePromise<void>;
33
- updateChain(chain: {
34
- chainName: ChainName;
35
- metadata?: ChainMetadata;
36
- addresses?: ChainAddresses;
37
- }): MaybePromise<void>;
40
+ addChain(chain: UpdateChainParams): MaybePromise<void>;
41
+ updateChain(chain: UpdateChainParams): MaybePromise<void>;
38
42
  removeChain(chain: ChainName): MaybePromise<void>;
43
+ getWarpRoute(routeId: string): MaybePromise<WarpCoreConfig | null>;
44
+ getWarpRoutes(filter?: WarpRouteFilterParams): MaybePromise<WarpRouteConfigMap>;
39
45
  addWarpRoute(config: WarpCoreConfig): MaybePromise<void>;
40
46
  merge(otherRegistry: IRegistry): IRegistry;
41
47
  }
@@ -1,7 +1,7 @@
1
1
  import type { Logger } from 'pino';
2
2
  import type { ChainMap, ChainMetadata, ChainName, WarpCoreConfig } from '@hyperlane-xyz/sdk';
3
- import { ChainAddresses } from '../types.js';
4
- import { IRegistry, RegistryContent, RegistryType } from './IRegistry.js';
3
+ import { ChainAddresses, WarpRouteConfigMap, WarpRouteId } from '../types.js';
4
+ import { IRegistry, RegistryContent, RegistryType, UpdateChainParams, WarpRouteFilterParams } from './IRegistry.js';
5
5
  export interface MergedRegistryOptions {
6
6
  registries: Array<IRegistry>;
7
7
  logger?: Logger;
@@ -18,6 +18,7 @@ export declare class MergedRegistry implements IRegistry {
18
18
  readonly registries: Array<IRegistry>;
19
19
  protected readonly logger: Logger;
20
20
  constructor({ registries, logger }: MergedRegistryOptions);
21
+ getUri(): string;
21
22
  listRegistryContent(): Promise<RegistryContent>;
22
23
  getChains(): Promise<Array<ChainName>>;
23
24
  getMetadata(): Promise<ChainMap<ChainMetadata>>;
@@ -25,17 +26,11 @@ export declare class MergedRegistry implements IRegistry {
25
26
  getAddresses(): Promise<ChainMap<ChainAddresses>>;
26
27
  getChainAddresses(chainName: ChainName): Promise<ChainAddresses | null>;
27
28
  getChainLogoUri(chainName: ChainName): Promise<string | null>;
28
- addChain(chain: {
29
- chainName: ChainName;
30
- metadata?: ChainMetadata;
31
- addresses?: ChainAddresses;
32
- }): Promise<void>;
33
- updateChain(chain: {
34
- chainName: ChainName;
35
- metadata?: ChainMetadata;
36
- addresses?: ChainAddresses;
37
- }): Promise<void>;
29
+ addChain(chain: UpdateChainParams): Promise<void>;
30
+ updateChain(chain: UpdateChainParams): Promise<void>;
38
31
  removeChain(chain: ChainName): Promise<void>;
32
+ getWarpRoute(id: WarpRouteId): Promise<WarpCoreConfig | null>;
33
+ getWarpRoutes(filter?: WarpRouteFilterParams): Promise<WarpRouteConfigMap>;
39
34
  addWarpRoute(config: WarpCoreConfig): Promise<void>;
40
35
  protected multiRegistryRead<R>(readFn: (registry: IRegistry) => Promise<R> | R): Promise<(Awaited<R> | Awaited<R>)[]>;
41
36
  protected multiRegistryWrite(writeFn: (registry: IRegistry) => Promise<void>, logMsg: string): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import { objMerge } from '../utils.js';
2
- import { RegistryType } from './IRegistry.js';
2
+ import { RegistryType, } from './IRegistry.js';
3
3
  /**
4
4
  * A registry that accepts multiple sub-registries.
5
5
  * Read methods are performed on all sub-registries and the results are merged.
@@ -18,11 +18,16 @@ export class MergedRegistry {
18
18
  // @ts-ignore
19
19
  this.logger = logger || console;
20
20
  }
21
+ getUri() {
22
+ throw new Error('getUri method not applicable to MergedRegistry');
23
+ }
21
24
  async listRegistryContent() {
22
25
  const results = await this.multiRegistryRead((r) => r.listRegistryContent());
23
26
  return results.reduce((acc, content) => objMerge(acc, content), {
24
27
  chains: {},
25
- deployments: {},
28
+ deployments: {
29
+ warpRoutes: {},
30
+ },
26
31
  });
27
32
  }
28
33
  async getChains() {
@@ -55,6 +60,14 @@ export class MergedRegistry {
55
60
  async removeChain(chain) {
56
61
  return this.multiRegistryWrite(async (registry) => await registry.removeChain(chain), `removing chain ${chain}`);
57
62
  }
63
+ async getWarpRoute(id) {
64
+ const results = await this.multiRegistryRead((r) => r.getWarpRoute(id));
65
+ return results.find((r) => !!r) || null;
66
+ }
67
+ async getWarpRoutes(filter) {
68
+ const results = await this.multiRegistryRead((r) => r.getWarpRoutes(filter));
69
+ return results.reduce((acc, content) => objMerge(acc, content), {});
70
+ }
58
71
  async addWarpRoute(config) {
59
72
  return this.multiRegistryWrite(async (registry) => await registry.addWarpRoute(config), 'adding warp route');
60
73
  }
@@ -1,6 +1,6 @@
1
1
  import type { Logger } from 'pino';
2
2
  import type { ChainMap, ChainMetadata, ChainName, WarpCoreConfig } from '@hyperlane-xyz/sdk';
3
- import { ChainAddresses } from '../types.js';
3
+ import { ChainAddresses, DeepPartial, WarpRouteId } from '../types.js';
4
4
  import { IRegistry, RegistryContent, RegistryType } from './IRegistry.js';
5
5
  import { SynchronousRegistry } from './SynchronousRegistry.js';
6
6
  /**
@@ -8,20 +8,23 @@ import { SynchronousRegistry } from './SynchronousRegistry.js';
8
8
  * Useful for merging with other registries force overrides of subsets of data.
9
9
  */
10
10
  export interface PartialRegistryOptions {
11
- chainMetadata?: ChainMap<Partial<ChainMetadata>>;
12
- chainAddresses?: ChainMap<Partial<ChainAddresses>>;
11
+ chainMetadata?: ChainMap<DeepPartial<ChainMetadata>>;
12
+ chainAddresses?: ChainMap<DeepPartial<ChainAddresses>>;
13
+ warpRoutes?: Array<DeepPartial<WarpCoreConfig>>;
13
14
  logger?: Logger;
14
15
  }
15
16
  export declare class PartialRegistry extends SynchronousRegistry implements IRegistry {
16
17
  readonly type = RegistryType.Partial;
17
- chainMetadata: ChainMap<Partial<ChainMetadata>>;
18
- chainAddresses: ChainMap<Partial<ChainAddresses>>;
19
- constructor({ chainMetadata, chainAddresses, logger }: PartialRegistryOptions);
18
+ chainMetadata: ChainMap<DeepPartial<ChainMetadata>>;
19
+ chainAddresses: ChainMap<DeepPartial<ChainAddresses>>;
20
+ warpRoutes: Array<DeepPartial<WarpCoreConfig>>;
21
+ constructor({ chainMetadata, chainAddresses, warpRoutes, logger }: PartialRegistryOptions);
20
22
  listRegistryContent(): RegistryContent;
21
23
  getMetadata(): ChainMap<ChainMetadata>;
22
24
  getAddresses(): ChainMap<ChainAddresses>;
23
25
  removeChain(chainName: ChainName): void;
24
26
  addWarpRoute(_config: WarpCoreConfig): void;
27
+ protected getWarpRoutesForIds(ids: WarpRouteId[]): WarpCoreConfig[];
25
28
  protected createOrUpdateChain(chain: {
26
29
  chainName: ChainName;
27
30
  metadata?: ChainMetadata;
@@ -1,14 +1,17 @@
1
1
  import { RegistryType } from './IRegistry.js';
2
2
  import { SynchronousRegistry } from './SynchronousRegistry.js';
3
+ import { warpRouteConfigToId } from './warp-utils.js';
3
4
  const PARTIAL_URI_PLACEHOLDER = '__partial_registry__';
4
5
  export class PartialRegistry extends SynchronousRegistry {
5
6
  type = RegistryType.Partial;
6
7
  chainMetadata;
7
8
  chainAddresses;
8
- constructor({ chainMetadata, chainAddresses, logger }) {
9
+ warpRoutes;
10
+ constructor({ chainMetadata, chainAddresses, warpRoutes, logger }) {
9
11
  super({ uri: PARTIAL_URI_PLACEHOLDER, logger });
10
12
  this.chainMetadata = chainMetadata || {};
11
13
  this.chainAddresses = chainAddresses || {};
14
+ this.warpRoutes = warpRoutes || [];
12
15
  }
13
16
  listRegistryContent() {
14
17
  const chains = {};
@@ -20,9 +23,17 @@ export class PartialRegistry extends SynchronousRegistry {
20
23
  chains[c] ||= {};
21
24
  chains[c].addresses = PARTIAL_URI_PLACEHOLDER;
22
25
  });
26
+ const warpRoutes = this.warpRoutes.reduce((acc, r) => {
27
+ // Cast is useful because this handles partials and safe because the fn validates data
28
+ const id = warpRouteConfigToId(r);
29
+ acc[id] = PARTIAL_URI_PLACEHOLDER;
30
+ return acc;
31
+ }, {});
23
32
  return {
24
33
  chains,
25
- deployments: {},
34
+ deployments: {
35
+ warpRoutes,
36
+ },
26
37
  };
27
38
  }
28
39
  getMetadata() {
@@ -41,6 +52,12 @@ export class PartialRegistry extends SynchronousRegistry {
41
52
  addWarpRoute(_config) {
42
53
  throw new Error('Method not implemented.');
43
54
  }
55
+ getWarpRoutesForIds(ids) {
56
+ return this.warpRoutes.filter((r) => {
57
+ const id = warpRouteConfigToId(r);
58
+ return ids.includes(id);
59
+ });
60
+ }
44
61
  createOrUpdateChain(chain) {
45
62
  if (chain.metadata)
46
63
  this.chainMetadata[chain.chainName] = chain.metadata;
@@ -1,7 +1,7 @@
1
1
  import type { ChainMap, ChainMetadata, ChainName, WarpCoreConfig } from '@hyperlane-xyz/sdk';
2
- import { ChainAddresses } from '../types.js';
2
+ import { ChainAddresses, WarpRouteConfigMap, WarpRouteId } from '../types.js';
3
3
  import { BaseRegistry } from './BaseRegistry.js';
4
- import { IRegistry, RegistryContent } from './IRegistry.js';
4
+ import { IRegistry, RegistryContent, UpdateChainParams, WarpRouteFilterParams } from './IRegistry.js';
5
5
  /**
6
6
  * Shared code for sync registries like the FileSystem and Partial registries.
7
7
  * This is required because of the inconsistent sync/async methods across registries.
@@ -14,21 +14,12 @@ export declare abstract class SynchronousRegistry extends BaseRegistry implement
14
14
  getChainMetadata(chainName: ChainName): ChainMetadata | null;
15
15
  abstract getAddresses(): ChainMap<ChainAddresses>;
16
16
  getChainAddresses(chainName: ChainName): ChainAddresses | null;
17
- addChain(chain: {
18
- chainName: ChainName;
19
- metadata?: ChainMetadata;
20
- addresses?: ChainAddresses;
21
- }): void;
22
- updateChain(chain: {
23
- chainName: ChainName;
24
- metadata?: ChainMetadata;
25
- addresses?: ChainAddresses;
26
- }): void;
17
+ addChain(chain: UpdateChainParams): void;
18
+ updateChain(chain: UpdateChainParams): void;
27
19
  removeChain(chainName: ChainName): void;
20
+ getWarpRoute(routeId: string): WarpCoreConfig | null;
21
+ getWarpRoutes(filter?: WarpRouteFilterParams): WarpRouteConfigMap;
28
22
  abstract addWarpRoute(config: WarpCoreConfig): void;
29
- protected abstract createOrUpdateChain(chain: {
30
- chainName: ChainName;
31
- metadata?: ChainMetadata;
32
- addresses?: ChainAddresses;
33
- }): void;
23
+ protected abstract createOrUpdateChain(chain: UpdateChainParams): void;
24
+ protected abstract getWarpRoutesForIds(ids: WarpRouteId[]): WarpCoreConfig[];
34
25
  }
@@ -1,4 +1,5 @@
1
1
  import { BaseRegistry } from './BaseRegistry.js';
2
+ import { filterWarpRoutesIds } from './warp-utils.js';
2
3
  /**
3
4
  * Shared code for sync registries like the FileSystem and Partial registries.
4
5
  * This is required because of the inconsistent sync/async methods across registries.
@@ -38,4 +39,14 @@ export class SynchronousRegistry extends BaseRegistry {
38
39
  if (this.addressCache?.[chainName])
39
40
  delete this.addressCache[chainName];
40
41
  }
42
+ getWarpRoute(routeId) {
43
+ return this.getWarpRoutesForIds([routeId])[0] || null;
44
+ }
45
+ getWarpRoutes(filter) {
46
+ const warpRoutes = this.listRegistryContent().deployments.warpRoutes;
47
+ const { ids: routeIds } = filterWarpRoutesIds(warpRoutes, filter);
48
+ const configs = this.getWarpRoutesForIds(routeIds);
49
+ const idsWithConfigs = routeIds.map((id, i) => [id, configs[i]]);
50
+ return Object.fromEntries(idsWithConfigs);
51
+ }
41
52
  }
@@ -1,3 +1,32 @@
1
- import type { ChainMap, WarpCoreConfig } from '@hyperlane-xyz/sdk';
2
- import { ChainAddresses } from '../types.js';
1
+ import type { ChainMap, ChainName, WarpCoreConfig } from '@hyperlane-xyz/sdk';
2
+ import { ChainAddresses, WarpRouteId } from '../types.js';
3
+ import { WarpRouteFilterParams } from './IRegistry.js';
4
+ /**
5
+ * Converts from a full warp config to a map of chain addresses.
6
+ */
3
7
  export declare function warpConfigToWarpAddresses(config: WarpCoreConfig): ChainMap<ChainAddresses>;
8
+ /**
9
+ * Gets a warp route ID from a warp route config path.
10
+ * @param configRelativePath A relative path in the deployments dir
11
+ * (e.g. `warp_routes/USDC/ethereum-arbitrum-config.yaml`)
12
+ */
13
+ export declare function warpRouteConfigPathToId(configRelativePath: string): WarpRouteId;
14
+ /**
15
+ * Gets a warp route ID from a warp route config.
16
+ * This uses the first symbol in the lift. Situations where a config contains multiple
17
+ * symbols are not officially supported yet.
18
+ */
19
+ export declare function warpRouteConfigToId(config: WarpCoreConfig): WarpRouteId;
20
+ export declare function createWarpRouteConfigId(tokenSymbol: string, chains: ChainName[]): WarpRouteId;
21
+ export declare function parseWarpRouteConfigId(routeId: WarpRouteId): {
22
+ tokenSymbol: string;
23
+ chainNames: ChainName[];
24
+ };
25
+ /**
26
+ * Filters a list of warp route IDs based on the provided filter params.
27
+ */
28
+ export declare function filterWarpRoutesIds<T>(idMap: Record<WarpRouteId, T>, filter?: WarpRouteFilterParams): {
29
+ ids: WarpRouteId[];
30
+ values: T[];
31
+ idMap: Record<WarpRouteId, T>;
32
+ };
@@ -1,3 +1,7 @@
1
+ import { WARP_ROUTE_CONFIG_FILE_REGEX } from '../consts.js';
2
+ /**
3
+ * Converts from a full warp config to a map of chain addresses.
4
+ */
1
5
  export function warpConfigToWarpAddresses(config) {
2
6
  return config.tokens.reduce((acc, token) => {
3
7
  const addressKey = getWarpAddressKey(token.standard);
@@ -20,3 +24,55 @@ function getWarpAddressKey(standard) {
20
24
  else
21
25
  return null;
22
26
  }
27
+ /**
28
+ * Gets a warp route ID from a warp route config path.
29
+ * @param configRelativePath A relative path in the deployments dir
30
+ * (e.g. `warp_routes/USDC/ethereum-arbitrum-config.yaml`)
31
+ */
32
+ export function warpRouteConfigPathToId(configRelativePath) {
33
+ const matches = configRelativePath.match(WARP_ROUTE_CONFIG_FILE_REGEX);
34
+ if (!matches || matches.length < 3)
35
+ throw new Error(`Invalid warp route config path: ${configRelativePath}`);
36
+ const [_, tokenSymbol, chains] = matches;
37
+ return createWarpRouteConfigId(tokenSymbol, chains.split('-'));
38
+ }
39
+ /**
40
+ * Gets a warp route ID from a warp route config.
41
+ * This uses the first symbol in the lift. Situations where a config contains multiple
42
+ * symbols are not officially supported yet.
43
+ */
44
+ export function warpRouteConfigToId(config) {
45
+ if (!config?.tokens?.length)
46
+ throw new Error('Cannot generate ID for empty warp config');
47
+ const tokenSymbol = config.tokens[0].symbol;
48
+ if (!tokenSymbol)
49
+ throw new Error('Cannot generate warp config ID without a token symbol');
50
+ const chains = config.tokens.map((token) => token.chainName);
51
+ return createWarpRouteConfigId(tokenSymbol, chains);
52
+ }
53
+ export function createWarpRouteConfigId(tokenSymbol, chains) {
54
+ const sortedChains = [...chains].sort();
55
+ return `${tokenSymbol}/${sortedChains.join('-')}`;
56
+ }
57
+ export function parseWarpRouteConfigId(routeId) {
58
+ const [tokenSymbol, chains] = routeId.split('/');
59
+ return { tokenSymbol, chainNames: chains.split('-') };
60
+ }
61
+ /**
62
+ * Filters a list of warp route IDs based on the provided filter params.
63
+ */
64
+ export function filterWarpRoutesIds(idMap, filter) {
65
+ const filterChainName = filter?.chainName?.toLowerCase();
66
+ const filterSymbol = filter?.symbol?.toLowerCase();
67
+ const filtered = Object.entries(idMap).filter(([routeId]) => {
68
+ const { tokenSymbol, chainNames } = parseWarpRouteConfigId(routeId);
69
+ if (filterSymbol && tokenSymbol.toLowerCase() !== filterSymbol)
70
+ return false;
71
+ if (filterChainName && !chainNames.includes(filterChainName))
72
+ return false;
73
+ return true;
74
+ });
75
+ const ids = filtered.map(([routeId]) => routeId);
76
+ const values = filtered.map(([, value]) => value);
77
+ return { ids, values, idMap: Object.fromEntries(filtered) };
78
+ }
package/dist/types.d.ts CHANGED
@@ -1,4 +1,10 @@
1
+ import type { WarpCoreConfig } from '@hyperlane-xyz/sdk';
1
2
  import { z } from 'zod';
2
3
  export type MaybePromise<T> = T | Promise<T> | PromiseLike<T>;
3
4
  export declare const ChainAddressesSchema: z.ZodRecord<z.ZodString, z.ZodString>;
4
5
  export type ChainAddresses = z.infer<typeof ChainAddressesSchema>;
6
+ export type WarpRouteId = string;
7
+ export type WarpRouteConfigMap = Record<WarpRouteId, WarpCoreConfig>;
8
+ export type DeepPartial<T> = T extends object ? {
9
+ [P in keyof T]?: DeepPartial<T[P]>;
10
+ } : T;
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export declare function toYamlString(data: any, prefix?: string): string;
2
+ export declare function stripLeadingSlash(path: string): string;
2
3
  export declare function concurrentMap<A, B>(concurrency: number, xs: A[], mapFn: (val: A, idx: number) => Promise<B>): Promise<B[]>;
3
4
  export declare function isObject(item: any): any;
4
5
  export declare function objMerge(a: Record<string, any>, b: Record<string, any>, max_depth?: number): any;
package/dist/utils.js CHANGED
@@ -3,6 +3,9 @@ export function toYamlString(data, prefix) {
3
3
  const yamlString = stringify(data);
4
4
  return prefix ? `${prefix}\n${yamlString}` : yamlString;
5
5
  }
6
+ export function stripLeadingSlash(path) {
7
+ return path.startsWith('/') || path.startsWith('\\') ? path.slice(1) : path;
8
+ }
6
9
  export async function concurrentMap(concurrency, xs, mapFn) {
7
10
  let res = [];
8
11
  for (let i = 0; i < xs.length; i += concurrency) {
@@ -0,0 +1,48 @@
1
+ export declare const warpRouteConfigs: Record<string, {
2
+ tokens: {
3
+ symbol: string;
4
+ name: string;
5
+ decimals: number;
6
+ chainName: string;
7
+ standard: import("@hyperlane-xyz/sdk").TokenStandard;
8
+ addressOrDenom: string | null;
9
+ collateralAddressOrDenom?: string | undefined;
10
+ igpTokenAddressOrDenom?: string | undefined;
11
+ logoURI?: string | undefined;
12
+ connections?: ({
13
+ token: string;
14
+ type?: import("@hyperlane-xyz/sdk").TokenConnectionType.Hyperlane | undefined;
15
+ } | {
16
+ type: import("@hyperlane-xyz/sdk").TokenConnectionType.Ibc;
17
+ token: string;
18
+ sourcePort: string;
19
+ sourceChannel: string;
20
+ } | {
21
+ type: import("@hyperlane-xyz/sdk").TokenConnectionType.IbcHyperlane;
22
+ token: string;
23
+ sourcePort: string;
24
+ sourceChannel: string;
25
+ intermediateChainName: string;
26
+ intermediateIbcDenom: string;
27
+ intermediateRouterAddress: string;
28
+ })[] | undefined;
29
+ }[];
30
+ options?: {
31
+ localFeeConstants?: {
32
+ amount: string | number | bigint;
33
+ origin: string;
34
+ destination: string;
35
+ addressOrDenom?: string | undefined;
36
+ }[] | undefined;
37
+ interchainFeeConstants?: {
38
+ amount: string | number | bigint;
39
+ origin: string;
40
+ destination: string;
41
+ addressOrDenom?: string | undefined;
42
+ }[] | undefined;
43
+ routeBlacklist?: {
44
+ origin: string;
45
+ destination: string;
46
+ }[] | undefined;
47
+ } | undefined;
48
+ }>;