@agoric/network 0.1.1-dev-91a9ad7.0.91a9ad7 → 0.1.1-dev-c35956d.0.c35956d

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/README.md CHANGED
@@ -48,7 +48,7 @@ You must also prepare a `ConnectionHandler` object to manage the connection you'
48
48
  Then you will call the `connect()` method on your local `Port`. This will return a `Promise` that will fire with a new `Connection` object, on which you can send data. Your `ConnectionHandler` will be notified about the new channel, and will receive inbound data from the other side.
49
49
 
50
50
  ```js
51
- import { encodeIbcEndpoint } from '@agoric/vats/tools/ibc-utils.js';
51
+ import { encodeIbcEndpoint } from '@agoric/network/ibc/utils.js';
52
52
  const remoteEndpoint = encodeIbcEndpoint({
53
53
  hops: [connectionID],
54
54
  portID,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/network",
3
- "version": "0.1.1-dev-91a9ad7.0.91a9ad7",
3
+ "version": "0.1.1-dev-c35956d.0.c35956d",
4
4
  "description": "Agoric's network protocol API",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -21,9 +21,9 @@
21
21
  "author": "Agoric",
22
22
  "license": "Apache-2.0",
23
23
  "dependencies": {
24
- "@agoric/internal": "0.3.3-dev-91a9ad7.0.91a9ad7",
25
- "@agoric/store": "0.9.3-dev-91a9ad7.0.91a9ad7",
26
- "@agoric/vat-data": "0.5.3-dev-91a9ad7.0.91a9ad7",
24
+ "@agoric/internal": "0.3.3-dev-c35956d.0.c35956d",
25
+ "@agoric/store": "0.9.3-dev-c35956d.0.c35956d",
26
+ "@agoric/vat-data": "0.5.3-dev-c35956d.0.c35956d",
27
27
  "@endo/base64": "^1.0.12",
28
28
  "@endo/errors": "^1.2.13",
29
29
  "@endo/far": "^1.1.14",
@@ -32,16 +32,19 @@
32
32
  "@endo/promise-kit": "^1.1.13"
33
33
  },
34
34
  "devDependencies": {
35
- "@agoric/swingset-liveslots": "0.10.3-dev-91a9ad7.0.91a9ad7",
36
- "@agoric/swingset-vat": "0.32.3-dev-91a9ad7.0.91a9ad7",
37
- "@agoric/vow": "0.1.1-dev-91a9ad7.0.91a9ad7",
38
- "@agoric/zone": "0.2.3-dev-91a9ad7.0.91a9ad7",
35
+ "@agoric/cosmic-proto": "0.4.1-dev-c35956d.0.c35956d",
36
+ "@agoric/swingset-liveslots": "0.10.3-dev-c35956d.0.c35956d",
37
+ "@agoric/swingset-vat": "0.32.3-dev-c35956d.0.c35956d",
38
+ "@agoric/vow": "0.1.1-dev-c35956d.0.c35956d",
39
+ "@agoric/zone": "0.2.3-dev-c35956d.0.c35956d",
39
40
  "@endo/bundle-source": "^4.1.2",
40
41
  "ava": "^6.4.1",
41
42
  "c8": "^10.1.3"
42
43
  },
43
44
  "exports": {
44
- ".": "./src/index.js"
45
+ ".": "./src/index.js",
46
+ "./ibc": "./src/ibc/index.js",
47
+ "./ibc/utils.js": "./src/ibc/utils.js"
45
48
  },
46
49
  "files": [
47
50
  "CHANGELOG.md",
@@ -67,5 +70,5 @@
67
70
  "typeCoverage": {
68
71
  "atLeast": 91.16
69
72
  },
70
- "gitHead": "91a9ad7ba5458194cd2e3f952738997cbcc55a38"
73
+ "gitHead": "c35956dcf414e6cc7f24db886cb647f36cb1eb90"
71
74
  }
@@ -0,0 +1,2 @@
1
+ export * from "./types.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export * from './types.js';
@@ -0,0 +1,36 @@
1
+ import type { State as IBCChannelState, Order } from '@agoric/cosmic-proto/ibc/core/channel/v1/channel.js';
2
+ import type { State as IBCConnectionState } from '@agoric/cosmic-proto/ibc/core/connection/v1/connection.js';
3
+ export type RemoteIbcAddress = `/${string}ibc-port/${string}/${'ordered' | 'unordered'}/${string}`;
4
+ export type LocalIbcAddress = `/ibc-port/${string}`;
5
+ export type IBCConnectionID = `connection-${number}`;
6
+ export type IBCChannelOrdering = 'ORDERED' | 'UNORDERED';
7
+ export type IBCPortID = string;
8
+ export type IBCChannelID = `channel-${number}`;
9
+ export interface IBCEndpoint {
10
+ hops: IBCConnectionID[];
11
+ portID: IBCPortID;
12
+ order?: IBCChannelOrdering;
13
+ version?: string;
14
+ channelID?: IBCChannelID;
15
+ }
16
+ export interface IBCTransferChannelInfo {
17
+ portId: string;
18
+ channelId: IBCChannelID;
19
+ counterPartyPortId: string;
20
+ counterPartyChannelId: IBCChannelID;
21
+ ordering: Order;
22
+ state: IBCChannelState;
23
+ version: string;
24
+ }
25
+ /** Represents an IBC Connection between two chains, which can contain multiple Channels. */
26
+ export interface IBCConnectionInfo {
27
+ id: IBCConnectionID;
28
+ client_id: string;
29
+ state: IBCConnectionState;
30
+ counterparty: {
31
+ client_id: string;
32
+ connection_id: IBCConnectionID;
33
+ };
34
+ transferChannel: IBCTransferChannelInfo;
35
+ }
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,IAAI,eAAe,EACxB,KAAK,EACN,MAAM,qDAAqD,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,IAAI,kBAAkB,EAAE,MAAM,2DAA2D,CAAC;AAE7G,MAAM,MAAM,gBAAgB,GAC1B,IAAI,MAAM,YAAY,MAAM,IAAI,SAAS,GAAG,WAAW,IAAI,MAAM,EAAE,CAAC;AACtE,MAAM,MAAM,eAAe,GAAG,aAAa,MAAM,EAAE,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG,cAAc,MAAM,EAAE,CAAC;AACrD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,WAAW,CAAC;AACzD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAC/B,MAAM,MAAM,YAAY,GAAG,WAAW,MAAM,EAAE,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,YAAY,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,YAAY,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,YAAY,CAAC;IACpC,QAAQ,EAAE,KAAK,CAAC;IAChB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,4FAA4F;AAC5F,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,eAAe,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,YAAY,EAAE;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,eAAe,CAAC;KAChC,CAAC;IACF,eAAe,EAAE,sBAAsB,CAAC;CACzC"}
@@ -0,0 +1,44 @@
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+ /** Represents an IBC Connection between two chains, which can contain multiple Channels. */
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @file Conversion from IBC endpoints to Agoric Network API Endpoints
3
+ * @summary Utilities for constructing and parsing Agoric Network API IBC addresses, which
4
+ * are used to identify IBC ports and channels in a Cosmos-participating
5
+ * blockchain.
6
+ *
7
+ * Agoric Network API addresses are roughly akin to Multiaddrs (@ref
8
+ * https://github.com/multiformats/js-multiaddr) but with a less rigid
9
+ * structure. Both share a similar textual representation, which is
10
+ * encapsulated protocols and values separated by slashes.
11
+ */
12
+ /**
13
+ * @import {Endpoint} from '../types.js';
14
+ * @import {
15
+ * IBCChannelID,
16
+ * IBCChannelOrdering,
17
+ * IBCConnectionID,
18
+ * IBCEndpoint,
19
+ * IBCPortID,
20
+ * LocalIbcAddress,
21
+ * RemoteIbcAddress,
22
+ * } from './types.js';
23
+ */
24
+ export const IBC_ADDR_RE: RegExp;
25
+ export const VALID_ORDERS: readonly ["ordered", "unordered", "ORDERED", "UNORDERED"];
26
+ export function encodeSlashes(raw: string): string;
27
+ export function decodeSlashes(encoded: string): string;
28
+ export function validateIbcAddress(addr: any): any;
29
+ export function decodeIbcHops(h: string): IBCConnectionID[];
30
+ export function decodeIbcEndpoint(addr: string): IBCEndpoint;
31
+ export function encodeIbcEndpoint({ hops, portID, order: rawOrder, version, channelID, }: {
32
+ hops?: string[] | undefined;
33
+ portID: string;
34
+ order: "ordered" | "unordered" | "ORDERED" | "UNORDERED";
35
+ version: string;
36
+ channelID?: string | undefined;
37
+ }): Endpoint;
38
+ /**
39
+ * @overload
40
+ * @param {string} remoteAddr
41
+ * @param {undefined | false} [returnMatch]
42
+ * @returns {boolean}
43
+ */
44
+ export function validateRemoteIbcAddress(remoteAddr: string, returnMatch?: undefined | false): boolean;
45
+ /**
46
+ * @overload
47
+ * @param {string} remoteAddr
48
+ * @param {true} returnMatch
49
+ * @returns {RegExpMatchArray}
50
+ */
51
+ export function validateRemoteIbcAddress(remoteAddr: string, returnMatch: true): RegExpMatchArray;
52
+ export function decodeRemoteIbcAddress(remoteAddr: string): {
53
+ rPortID: string;
54
+ order: IBCChannelOrdering;
55
+ version: string;
56
+ hops: `connection-${number}`[];
57
+ };
58
+ export function localAddrToPortID(localAddr: LocalIbcAddress): string;
59
+ export function encodeRemoteIbcAddress(hops: string[], portID: string, order: "ordered" | "unordered" | "ORDERED" | "UNORDERED", version: string, channelID?: string): RemoteIbcAddress;
60
+ export function encodeLocalIbcAddress(portID: string, order: "ordered" | "unordered" | "ORDERED" | "UNORDERED", version: string): string;
61
+ import type { IBCConnectionID } from './types.js';
62
+ import type { IBCEndpoint } from './types.js';
63
+ import type { Endpoint } from '../types.js';
64
+ import type { IBCChannelOrdering } from './types.js';
65
+ import type { LocalIbcAddress } from './types.js';
66
+ import type { RemoteIbcAddress } from './types.js';
67
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["utils.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;GAWG;AAEH,iCACsJ;AAGtJ,qFAKG;AAII,mCADK,MAAM,UAC8C;AAIzD,uCADK,MAAM,UACsD;AAGjE,mDASN;AAQM,iCAHI,MAAM,GACJ,eAAe,EAAE,CAsB7B;AAOM,wCAHI,MAAM,GACJ,WAAW,CAkBvB;AAYM,0FAPJ;IAAwB,IAAI;IACP,MAAM,EAAnB,MAAM;IACkD,KAAK,EAA7D,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW;IACpC,OAAO,EAApB,MAAM;IACQ,SAAS;CAC/B,GAAU,QAAQ,CAwCpB;;;;;;;AAIE,qDACQ,MAAM,gBACN,SAAS,GAAG,KAAK,GACf,OAAO,CACnB;;;;;;;AAEE,qDACQ,MAAM,eACN,IAAI,GACF,gBAAgB,CAC5B;AA0BM,mDADK,MAAM;;;;;EAYjB;AAOM,6CAHI,eAAe,GACb,MAAM,CAqBlB;AAWM,6CAPI,MAAM,EAAE,UACR,MAAM,SACN,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,WACjD,MAAM,cACN,MAAM,GACJ,gBAAgB,CAiB5B;AAQM,8CAJI,MAAM,SACN,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,WACjD,MAAM,UAIhB;qCAtPS,YAAY;iCAAZ,YAAY;8BATK,aAAa;wCAS9B,YAAY;qCAAZ,YAAY;sCAAZ,YAAY"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * @file Conversion from IBC endpoints to Agoric Network API Endpoints
3
+ * @summary Utilities for constructing and parsing Agoric Network API IBC addresses, which
4
+ * are used to identify IBC ports and channels in a Cosmos-participating
5
+ * blockchain.
6
+ *
7
+ * Agoric Network API addresses are roughly akin to Multiaddrs (@ref
8
+ * https://github.com/multiformats/js-multiaddr) but with a less rigid
9
+ * structure. Both share a similar textual representation, which is
10
+ * encapsulated protocols and values separated by slashes.
11
+ */
12
+
13
+ /**
14
+ * @import {Endpoint} from '../types.js';
15
+ * @import {
16
+ * IBCChannelID,
17
+ * IBCChannelOrdering,
18
+ * IBCConnectionID,
19
+ * IBCEndpoint,
20
+ * IBCPortID,
21
+ * LocalIbcAddress,
22
+ * RemoteIbcAddress,
23
+ * } from './types.js';
24
+ */
25
+
26
+ export const IBC_ADDR_RE =
27
+ /^(?<hops>\/ibc-hop\/[^/]+)*\/ibc-port\/(?<portID>[^/]+)(\/(?<order>ordered|unordered)\/(?<version>[^/]+)(\/ibc-channel\/(?<channelID>[^/]+))?)?$/s;
28
+ harden(IBC_ADDR_RE);
29
+
30
+ export const VALID_ORDERS = /** @type {const} */ ([
31
+ 'ordered',
32
+ 'unordered',
33
+ 'ORDERED',
34
+ 'UNORDERED',
35
+ ]);
36
+ harden(VALID_ORDERS);
37
+
38
+ /** @param {string} raw */
39
+ export const encodeSlashes = raw => raw.replaceAll('/', '\\x2f');
40
+ harden(encodeSlashes);
41
+
42
+ /** @param {string} encoded */
43
+ export const decodeSlashes = encoded => encoded.replaceAll('\\x2f', '/');
44
+ harden(decodeSlashes);
45
+
46
+ export const validateIbcAddress = addr => {
47
+ const match = addr.match(IBC_ADDR_RE);
48
+ // .groups is to inform TS
49
+ if (!(match && match.groups)) {
50
+ throw TypeError(
51
+ `IBC address ${addr} must be '(/ibc-hop/CONNECTION)*/ibc-port/PORT/(ordered|unordered)/VERSION(/ibc-channel/CHANNEL_ID)?'`,
52
+ );
53
+ }
54
+ return match;
55
+ };
56
+
57
+ /**
58
+ * Decode the /ibc-hop/CONNECTION segments of an IBC address.
59
+ *
60
+ * @param {string} h
61
+ * @returns {IBCConnectionID[]}
62
+ */
63
+ export const decodeIbcHops = h => {
64
+ /** @type {IBCConnectionID[]} */
65
+ const hops = [];
66
+
67
+ /** @type {string} */
68
+ while (h) {
69
+ const m = h.match(/^\/ibc-hop\/(?<hop>[^/]+)/);
70
+ if (!m || !m.groups) {
71
+ throw Error(
72
+ `internal: ${JSON.stringify(h)} did not begin with "/ibc-hop/XXX"`,
73
+ );
74
+ }
75
+ h = h.slice(m[0].length);
76
+
77
+ const hop = /** @type {IBCConnectionID} */ (m.groups.hop);
78
+ assert(typeof hop === 'string' && hop.startsWith('connection-'));
79
+ hops.push(hop);
80
+ }
81
+
82
+ return hops;
83
+ };
84
+ harden(decodeIbcHops);
85
+
86
+ /**
87
+ * @param {string} addr
88
+ * @returns {IBCEndpoint}
89
+ */
90
+ export const decodeIbcEndpoint = addr => {
91
+ const match = validateIbcAddress(addr);
92
+ if (!match.groups)
93
+ throw Error('Unexpected error, validateRemoteIbcAddress should throw.');
94
+
95
+ const hops = decodeIbcHops(match.groups.hops);
96
+
97
+ // Generate a circuit.
98
+ const { portID, version, channelID, order } = match.groups;
99
+ return {
100
+ hops,
101
+ portID,
102
+ ...(order && { order: order.toUpperCase() }),
103
+ ...(version && { version: decodeSlashes(version) }),
104
+ ...(channelID && { channelID }),
105
+ };
106
+ };
107
+ harden(decodeIbcEndpoint);
108
+
109
+ /**
110
+ * @param {object} spec
111
+ * @param {string[]} [spec.hops]
112
+ * @param {string} spec.portID
113
+ * @param {'ordered' | 'unordered' | 'ORDERED' | 'UNORDERED'} spec.order
114
+ * @param {string} spec.version
115
+ * @param {string} [spec.channelID]
116
+ * @returns {Endpoint}
117
+ */
118
+ export const encodeIbcEndpoint = ({
119
+ hops = [],
120
+ portID,
121
+ order: rawOrder,
122
+ version,
123
+ channelID,
124
+ }) => {
125
+ const isLegitString = str =>
126
+ typeof str === 'string' && str && !str.includes('/');
127
+ let addr = '';
128
+ assert(Array.isArray(hops), 'hops must be an array');
129
+ for (const hop of hops) {
130
+ assert(isLegitString(hop), `invalid hop ${hop}`);
131
+ addr += `/ibc-hop/${hop}`;
132
+ }
133
+ assert(isLegitString(portID), `invalid portID ${portID}`);
134
+ addr += `/ibc-port/${portID}`;
135
+
136
+ if (rawOrder !== undefined) {
137
+ assert(isLegitString(rawOrder), `invalid order ${rawOrder}`);
138
+
139
+ assert(
140
+ VALID_ORDERS.includes(rawOrder),
141
+ `invalid order ${rawOrder}; ${rawOrder} not found in ${JSON.stringify(VALID_ORDERS)}`,
142
+ );
143
+
144
+ const order = rawOrder.toLowerCase();
145
+
146
+ assert(typeof version === 'string' && version, 'missing version');
147
+ addr += `/${order}/${encodeSlashes(version)}`;
148
+
149
+ if (channelID !== undefined) {
150
+ assert(isLegitString(channelID), `invalid channelID ${channelID}`);
151
+ addr += `/ibc-channel/${channelID}`;
152
+ }
153
+ }
154
+
155
+ return addr;
156
+ };
157
+ harden(encodeIbcEndpoint);
158
+
159
+ /**
160
+ * @overload
161
+ * @param {string} remoteAddr
162
+ * @param {undefined | false} [returnMatch]
163
+ * @returns {boolean}
164
+ */
165
+ /**
166
+ * @overload
167
+ * @param {string} remoteAddr
168
+ * @param {true} returnMatch
169
+ * @returns {RegExpMatchArray}
170
+ */
171
+ /**
172
+ * Validates a remote IBC address format and returns true if the address is
173
+ * valid.
174
+ *
175
+ * @param {string} remoteAddr
176
+ * @param {boolean} [returnMatch]
177
+ */
178
+ export const validateRemoteIbcAddress = (remoteAddr, returnMatch = false) => {
179
+ const match = validateIbcAddress(remoteAddr);
180
+ // .groups is to inform TS https://github.com/microsoft/TypeScript/issues/32098
181
+ if (!(match && match.groups)) {
182
+ throw TypeError(
183
+ `Remote address ${remoteAddr} must be '(/ibc-hop/CONNECTION)*/ibc-port/PORT/(ordered|unordered)/VERSION'`,
184
+ );
185
+ }
186
+ if (match.groups.channelID) {
187
+ throw TypeError(
188
+ `Remote address ${remoteAddr} must not include channelID; found ${match.groups.channelID}`,
189
+ );
190
+ }
191
+ return returnMatch ? match : true;
192
+ };
193
+ harden(validateRemoteIbcAddress);
194
+
195
+ /** @param {string} remoteAddr */
196
+ export const decodeRemoteIbcAddress = remoteAddr => {
197
+ validateRemoteIbcAddress(remoteAddr);
198
+ const {
199
+ hops,
200
+ portID: rPortID,
201
+ order,
202
+ version,
203
+ } = decodeIbcEndpoint(remoteAddr);
204
+ assert(order !== undefined, 'missing order');
205
+ assert(version !== undefined, 'missing version');
206
+ return { rPortID, order, version, hops };
207
+ };
208
+ harden(decodeRemoteIbcAddress);
209
+
210
+ /**
211
+ * @param {LocalIbcAddress} localAddr
212
+ * @returns {string}
213
+ */
214
+ export const localAddrToPortID = localAddr => {
215
+ const m = localAddr.match(IBC_ADDR_RE);
216
+ // .groups is to inform TS https://github.com/microsoft/TypeScript/issues/32098
217
+ if (!(m && m.groups)) {
218
+ throw TypeError(
219
+ `Invalid port specification ${localAddr}; expected "/ibc-port/PORT"`,
220
+ );
221
+ }
222
+ for (const group of Object.keys(m.groups)) {
223
+ if (group === 'portID') {
224
+ continue;
225
+ }
226
+ if (m.groups[group] !== undefined) {
227
+ throw TypeError(
228
+ `Invalid port specification ${localAddr}; unexpected ${group}=${m.groups[group]}`,
229
+ );
230
+ }
231
+ }
232
+ return m.groups.portID;
233
+ };
234
+ harden(localAddrToPortID);
235
+
236
+ /**
237
+ * @param {string[]} hops
238
+ * @param {string} portID
239
+ * @param {'ordered' | 'unordered' | 'ORDERED' | 'UNORDERED'} order
240
+ * @param {string} version
241
+ * @param {string} [channelID]
242
+ * @returns {RemoteIbcAddress}
243
+ */
244
+ export const encodeRemoteIbcAddress = (
245
+ hops,
246
+ portID,
247
+ order,
248
+ version,
249
+ channelID,
250
+ ) => {
251
+ const ep = encodeIbcEndpoint({
252
+ hops,
253
+ portID,
254
+ order,
255
+ version,
256
+ ...(channelID && { channelID }),
257
+ });
258
+ return /** @type {RemoteIbcAddress} */ (ep);
259
+ };
260
+ harden(encodeRemoteIbcAddress);
261
+
262
+ /**
263
+ * @param {string} portID
264
+ * @param {'ordered' | 'unordered' | 'ORDERED' | 'UNORDERED'} order
265
+ * @param {string} version
266
+ */
267
+ export const encodeLocalIbcAddress = (portID, order, version) => {
268
+ return encodeIbcEndpoint({ portID, order, version });
269
+ };
270
+ harden(encodeLocalIbcAddress);