@agoric/vats 0.15.2-dev-00cccfc.0 → 0.15.2-dev-e2e36cc.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/vats",
3
- "version": "0.15.2-dev-00cccfc.0+00cccfc",
3
+ "version": "0.15.2-dev-e2e36cc.0+e2e36cc",
4
4
  "description": "Agoric's Vat library",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -22,19 +22,19 @@
22
22
  "author": "Agoric",
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@agoric/assert": "0.6.1-dev-00cccfc.0+00cccfc",
26
- "@agoric/cosmic-proto": "0.4.1-dev-00cccfc.0+00cccfc",
27
- "@agoric/ertp": "0.16.3-dev-00cccfc.0+00cccfc",
28
- "@agoric/governance": "0.10.4-dev-00cccfc.0+00cccfc",
29
- "@agoric/internal": "0.3.3-dev-00cccfc.0+00cccfc",
30
- "@agoric/network": "0.1.1-dev-00cccfc.0+00cccfc",
31
- "@agoric/notifier": "0.6.3-dev-00cccfc.0+00cccfc",
32
- "@agoric/store": "0.9.3-dev-00cccfc.0+00cccfc",
33
- "@agoric/swingset-vat": "0.32.3-dev-00cccfc.0+00cccfc",
34
- "@agoric/time": "0.3.3-dev-00cccfc.0+00cccfc",
35
- "@agoric/vat-data": "0.5.3-dev-00cccfc.0+00cccfc",
36
- "@agoric/zoe": "0.26.3-dev-00cccfc.0+00cccfc",
37
- "@agoric/zone": "0.2.3-dev-00cccfc.0+00cccfc",
25
+ "@agoric/assert": "0.6.1-dev-e2e36cc.0+e2e36cc",
26
+ "@agoric/cosmic-proto": "0.4.1-dev-e2e36cc.0+e2e36cc",
27
+ "@agoric/ertp": "0.16.3-dev-e2e36cc.0+e2e36cc",
28
+ "@agoric/governance": "0.10.4-dev-e2e36cc.0+e2e36cc",
29
+ "@agoric/internal": "0.3.3-dev-e2e36cc.0+e2e36cc",
30
+ "@agoric/network": "0.1.1-dev-e2e36cc.0+e2e36cc",
31
+ "@agoric/notifier": "0.6.3-dev-e2e36cc.0+e2e36cc",
32
+ "@agoric/store": "0.9.3-dev-e2e36cc.0+e2e36cc",
33
+ "@agoric/swingset-vat": "0.32.3-dev-e2e36cc.0+e2e36cc",
34
+ "@agoric/time": "0.3.3-dev-e2e36cc.0+e2e36cc",
35
+ "@agoric/vat-data": "0.5.3-dev-e2e36cc.0+e2e36cc",
36
+ "@agoric/zoe": "0.26.3-dev-e2e36cc.0+e2e36cc",
37
+ "@agoric/zone": "0.2.3-dev-e2e36cc.0+e2e36cc",
38
38
  "@endo/far": "^1.1.1",
39
39
  "@endo/import-bundle": "^1.1.1",
40
40
  "@endo/marshal": "^1.4.1",
@@ -45,7 +45,7 @@
45
45
  "jessie.js": "^0.3.4"
46
46
  },
47
47
  "devDependencies": {
48
- "@agoric/swingset-liveslots": "0.10.3-dev-00cccfc.0+00cccfc",
48
+ "@agoric/swingset-liveslots": "0.10.3-dev-e2e36cc.0+e2e36cc",
49
49
  "@endo/bundle-source": "^3.2.2",
50
50
  "@endo/init": "^1.1.1",
51
51
  "ava": "^5.3.0",
@@ -76,7 +76,7 @@
76
76
  "workerThreads": false
77
77
  },
78
78
  "typeCoverage": {
79
- "atLeast": 89.58
79
+ "atLeast": 91.5
80
80
  },
81
- "gitHead": "00cccfc6fad7465b6dc611d2c861b32f07fdeaea"
81
+ "gitHead": "e2e36cc1e1c015fc517a179019184fdc81f3e809"
82
82
  }
package/src/ibc.d.ts CHANGED
@@ -1,43 +1,61 @@
1
- export function prepareIBCConnectionHandler(zone: Zone): (args_0?: any, args_1?: any) => import("@endo/exo").Guarded<{
2
- onOpen(conn: any, localAddr: any, remoteAddr: any, _handler: any): Promise<void>;
3
- /**
4
- * @param {Connection} _conn
5
- * @param {Bytes} packetBytes
6
- * @param {ConnectionHandler} _handler
7
- * @param {object} root0
8
- * @param {bigint} [root0.relativeTimeoutNs]
9
- * @returns {PromiseVow<Bytes>} Acknowledgement data
10
- */
11
- onReceive(_conn: Connection, packetBytes: Bytes, _handler: ConnectionHandler, { relativeTimeoutNs }?: {
12
- relativeTimeoutNs?: bigint | undefined;
13
- }): PromiseVow<Bytes>;
14
- onClose(_conn: any, _reason: any, _handler: any): Promise<void>;
1
+ export function prepareIBCConnectionHandler(zone: Zone): (args_0: {
2
+ protocolUtils: any;
3
+ channelKeyToConnP: MapStore<string, import('@agoric/vow').Remote<Connection>>;
4
+ channelKeyToSeqAck: MapStore<string, MapStore<number, import('@agoric/vow').VowKit<Bytes>>>;
5
+ }, args_1: {
6
+ channelID: `channel-${number}`;
7
+ portID: string;
8
+ rChannelID: `channel-${number}`;
9
+ rPortID: string;
10
+ order: 'ORDERED' | 'UNORDERED';
11
+ }) => import("@endo/exo").Guarded<{
12
+ /** @type {Required<ConnectionHandler>['onOpen']} */
13
+ onOpen(connection: globalThis.Remote<Connection>, localAddr: string, remoteAddr: string, c: globalThis.Remote<ConnectionHandler>): PromiseVow<void>;
14
+ /** @type {Required<ConnectionHandler>['onReceive']} */
15
+ onReceive(connection: globalThis.Remote<Connection>, ack: string, c: globalThis.Remote<ConnectionHandler>, opts?: Record<string, any> | undefined): PromiseVow<string>;
16
+ /** @type {Required<ConnectionHandler>['onClose']} */
17
+ onClose(connection: globalThis.Remote<Connection>, reason?: any, c?: globalThis.Remote<ConnectionHandler> | undefined): PromiseVow<void>;
15
18
  }>;
16
19
  export function prepareIBCProtocol(zone: Zone, powers: {
17
20
  when: <T, TResult1 = import("@agoric/vow").Unwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: import("@agoric/vow").Unwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
18
- watch: <T_1 = any, TResult1_1 = T_1, TResult2_1 = T_1>(specimenP: import("@agoric/vow").ERef<T_1 | import("@agoric/vow").Vow<T_1>>, watcher?: import("@agoric/vow").Watcher<T_1, TResult1_1, TResult2_1> | undefined, watcherContext?: unknown) => import("@agoric/vow").Vow<TResult1_1 | TResult2_1>;
21
+ watch: <T_1 = unknown, TResult1_1 = T_1, TResult2_1 = T_1, C = unknown>(specimenP: import("@agoric/vow").ERef<T_1 | import("@agoric/vow").Vow<T_1>>, watcher?: import("@agoric/vow").Watcher<T_1, TResult1_1, TResult2_1, any> | undefined, watcherContext?: C | undefined) => import("@agoric/vow").Vow<TResult1_1 | TResult2_1>;
19
22
  makeVowKit: <T_2>() => VowKit<T_2>;
20
23
  allVows: (vows: any) => import("@agoric/vow").Vow<any>;
21
- }): (ibcdev: any) => {
24
+ }): (ibcdev: {
25
+ downcall: (method: string, args: object) => Promise<any>;
26
+ }) => {
22
27
  protocolHandler: ProtocolHandler;
23
28
  bridgeHandler: BridgeHandler;
24
29
  } | {
25
30
  protocolHandler: import("@endo/exo").Guarded<{
26
- onCreate(impl: any, _protocolHandler: any): Promise<void>;
27
- onInstantiate(): Promise<string>;
28
- generatePortID(_localAddr: any, _protocolHandler: any): Promise<string>;
29
- onBind(port: any, localAddr: any, _protocolHandler: any): Promise<any>;
30
- onConnect(port: any, localAddr: any, remoteAddr: any, _chandler: any, _protocolHandler: any): Promise<import("@agoric/vow").Vow<any>>;
31
- onListen(_port: any, localAddr: any, _listenHandler: any): Promise<void>;
32
- onListenRemove(_port: any, localAddr: any, _listenHandler: any): Promise<void>;
33
- onRevoke(_port: any, localAddr: any, _protocolHandler: any): Promise<void>;
31
+ /** @type {Required<ProtocolHandler>['onCreate']} */
32
+ onCreate(protocol: globalThis.Remote<ProtocolImpl>, p: globalThis.Remote<ProtocolHandler>): PromiseVow<void>;
33
+ /** @type {Required<ProtocolHandler>['onInstantiate']} */
34
+ onInstantiate(port: globalThis.Remote<Port>, localAddr: string, remote: string, p: globalThis.Remote<ProtocolHandler>): PromiseVow<string>;
35
+ /** @type {Required<ProtocolHandler>['generatePortID']} */
36
+ generatePortID(localAddr: string, p: globalThis.Remote<ProtocolHandler>): PromiseVow<string>;
37
+ /** @type {Required<ProtocolHandler>['onBind']} */
38
+ onBind(port: globalThis.Remote<Port>, localAddr: string, p: globalThis.Remote<ProtocolHandler>): PromiseVow<void>;
39
+ /** @type {Required<ProtocolHandler>['onConnect']} */
40
+ onConnect(port: globalThis.Remote<Port>, localAddr: string, remote: string, c: globalThis.Remote<ConnectionHandler>, p: globalThis.Remote<ProtocolHandler>): PromiseVow<AttemptDescription>;
41
+ /** @type {Required<ProtocolHandler>['onListen']} */
42
+ onListen(port: globalThis.Remote<Port>, localAddr: string, listenHandler: globalThis.Remote<ListenHandler>, p: globalThis.Remote<ProtocolHandler>): PromiseVow<void>;
43
+ /** @type {Required<ProtocolHandler>['onListenRemove']} */
44
+ onListenRemove(port: globalThis.Remote<Port>, localAddr: string, listenHandler: globalThis.Remote<ListenHandler>, p: globalThis.Remote<ProtocolHandler>): PromiseVow<void>;
45
+ /** @type {Required<ProtocolHandler>['onRevoke']} */
46
+ onRevoke(port: globalThis.Remote<Port>, localAddr: string, p: globalThis.Remote<ProtocolHandler>): PromiseVow<void>;
34
47
  }>;
35
48
  bridgeHandler: import("@endo/exo").Guarded<{
36
- fromBridge(obj: any): Promise<import("@agoric/vow").Vow<any> | undefined>;
49
+ /** @param {IBCEvent<IBCBridgeEvent>} obj */
50
+ fromBridge(obj: IBCEvent<IBCBridgeEvent>): Promise<import("@agoric/vow").Vow<any> | undefined>;
37
51
  }>;
38
52
  };
39
53
  export function prepareCallbacks(zone: Zone): (dibcBridgeManager: ScopedBridgeManager) => import("@endo/exo").Guarded<{
40
- downcall(method: any, obj: any): Promise<any>;
54
+ /**
55
+ * @param {string} method
56
+ * @param {any} obj
57
+ */
58
+ downcall(method: string, obj: any): Promise<any>;
41
59
  }>;
42
60
  export type OnConnectP = {
43
61
  vow: import("@agoric/vow").Vow<AttemptDescription>;
@@ -53,6 +71,8 @@ export type Outbound = Omit<ConnectingInfo, "counterparty" | "channelID" | "coun
53
71
  import type { Zone } from '@agoric/base-zone';
54
72
  import type { VowKit } from '@agoric/vow';
55
73
  import type { BridgeHandler } from './types.js';
74
+ import type { IBCBridgeEvent } from './types.js';
75
+ import type { IBCEvent } from './types.js';
56
76
  import type { ScopedBridgeManager } from './types.js';
57
77
  import type { VowResolver } from '@agoric/vow';
58
78
  import type { ConnectingInfo } from './types.js';
package/src/ibc.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ibc.d.ts","sourceRoot":"","sources":["ibc.js"],"names":[],"mappings":"AAqCO;;IA8CD;;;;;;;OAOG;qBANQ,UAAU,eACV,KAAK,YACL,iBAAiB;QAEF,iBAAiB;QAC9B,WAAW,KAAK,CAAC;;GA8CnC;AAMM;;;;;;qBAcmB,eAAe;;;;;;;;;;;;;;;;EAumBxC;AAKM;;GAiBN;;;;;;eA1vBe,QAAQ;gBACP,UAAU;kBACR;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;;0BAbf,mBAAmB;4BACc,aAAa;mCAFqH,YAAY;yCAAZ,YAAY;iCAE9I,aAAa;oCAFqH,YAAY"}
1
+ {"version":3,"file":"ibc.d.ts","sourceRoot":"","sources":["ibc.js"],"names":[],"mappings":"AA6CO;mBAciB,GAAG;uBACC,SACvB,MAAY,EACZ,OAAa,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CACzC;wBACmB,SACxB,MAAY,EACZ,SAAe,MAAM,EAAE,OAAO,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CACtD;;;YAIO,MAAM;;aAEL,MAAM;WACR,SAAS,GAAG,WAAW;;IAuBjC,oDAAoD;;IAepD,uDAAuD;;IAoBvD,qDAAqD;;GA0B1D;AAMM;;;;;;cAOS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,QAAQ,GAAG,CAAC;;qBAOpC,eAAe;;;;QAoDjC,oDAAoD;;QAKpD,yDAAyD;;QAKzD,0DAA0D;;QAK1D,kDAAkD;;QAalD,qDAAqD;;QAiDrD,oDAAoD;;QAIpD,0DAA0D;;QAI1D,oDAAoD;;;;QAgBpD,4CAA4C;;;EAudnD;AAIM;IAOD;;;OAGG;qBAFQ,MAAM,OACN,GAAG;GAYnB;;;;;;eArxBe,QAAQ;gBACP,UAAU;kBACR;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;;0BAbf,mBAAmB;4BACc,aAAa;mCAFqI,YAAY;oCAAZ,YAAY;8BAAZ,YAAY;yCAAZ,YAAY;iCAE9J,aAAa;oCAFqI,YAAY"}
package/src/ibc.js CHANGED
@@ -7,6 +7,14 @@ import { dataToBase64, base64ToBytes } from '@agoric/network';
7
7
 
8
8
  import '@agoric/store/exported.js';
9
9
  import '@agoric/network/exported.js';
10
+ import {
11
+ localAddrToPortID,
12
+ decodeRemoteIbcAddress,
13
+ encodeLocalIbcAddress,
14
+ encodeRemoteIbcAddress,
15
+ } from '../tools/ibc-utils.js';
16
+
17
+ /** @import {LocalIbcAddress, RemoteIbcAddress} from '../tools/ibc-utils.js' */
10
18
 
11
19
  // CAVEAT: IBC acks cannot be empty, as the Cosmos IAVL tree cannot represent
12
20
  // empty acknowledgements as distinct from unacknowledged packets.
@@ -16,14 +24,14 @@ const DEFAULT_ACKNOWLEDGEMENT = '\x00';
16
24
  const DEFAULT_PACKET_TIMEOUT_NS = 60n * 60n * 1_000_000_000n;
17
25
 
18
26
  /**
19
- * @import {BridgeHandler, ScopedBridgeManager, ConnectingInfo, IBCChannelID, IBCChannelOrdering, IBCEvent, IBCPacket, IBCPortID, IBCDowncall, IBCDowncallPacket, IBCDowncallMethod} from './types.js';
27
+ * @import {BridgeHandler, ScopedBridgeManager, ConnectingInfo, IBCChannelID, IBCChannelOrdering, IBCEvent, IBCPacket, IBCPortID, IBCDowncallPacket, IBCDowncallMethod, IBCDowncall, IBCBridgeEvent} from './types.js';
20
28
  * @import {Zone} from '@agoric/base-zone';
21
29
  * @import {Remote, VowKit, VowResolver, VowTools} from '@agoric/vow';
22
30
  */
23
31
 
32
+ /** @typedef {VowKit<AttemptDescription>} OnConnectP */
33
+
24
34
  /**
25
- * @typedef {VowKit<AttemptDescription>} OnConnectP
26
- *
27
35
  * @typedef {Omit<
28
36
  * ConnectingInfo,
29
37
  * 'counterparty' | 'channelID' | 'counterpartyVersion'
@@ -47,6 +55,26 @@ export const prepareIBCConnectionHandler = zone => {
47
55
  const makeIBCConnectionHandler = zone.exoClass(
48
56
  'IBCConnectionHandler',
49
57
  undefined,
58
+ /**
59
+ * @param {{
60
+ * protocolUtils: any;
61
+ * channelKeyToConnP: MapStore<
62
+ * string,
63
+ * import('@agoric/vow').Remote<Connection>
64
+ * >;
65
+ * channelKeyToSeqAck: MapStore<
66
+ * string,
67
+ * MapStore<number, import('@agoric/vow').VowKit<Bytes>>
68
+ * >;
69
+ * }} param0
70
+ * @param {{
71
+ * channelID: IBCChannelID;
72
+ * portID: string;
73
+ * rChannelID: IBCChannelID;
74
+ * rPortID: string;
75
+ * order: 'ORDERED' | 'UNORDERED';
76
+ * }} param1
77
+ */
50
78
  (
51
79
  { protocolUtils, channelKeyToConnP, channelKeyToSeqAck },
52
80
  { channelID, portID, rChannelID, rPortID, order },
@@ -67,6 +95,7 @@ export const prepareIBCConnectionHandler = zone => {
67
95
  };
68
96
  },
69
97
  {
98
+ /** @type {Required<ConnectionHandler>['onOpen']} */
70
99
  async onOpen(conn, localAddr, remoteAddr, _handler) {
71
100
  const { channelID, portID, channelKeyToConnP } = this.state;
72
101
 
@@ -81,14 +110,7 @@ export const prepareIBCConnectionHandler = zone => {
81
110
 
82
111
  channelKeyToConnP.init(channelKey, conn);
83
112
  },
84
- /**
85
- * @param {Connection} _conn
86
- * @param {Bytes} packetBytes
87
- * @param {ConnectionHandler} _handler
88
- * @param {object} root0
89
- * @param {bigint} [root0.relativeTimeoutNs]
90
- * @returns {PromiseVow<Bytes>} Acknowledgement data
91
- */
113
+ /** @type {Required<ConnectionHandler>['onReceive']} */
92
114
  async onReceive(
93
115
  _conn,
94
116
  packetBytes,
@@ -108,7 +130,8 @@ export const prepareIBCConnectionHandler = zone => {
108
130
  };
109
131
  return protocolUtils.ibcSendPacket(packet, relativeTimeoutNs);
110
132
  },
111
- async onClose(_conn, _reason, _handler) {
133
+ /** @type {Required<ConnectionHandler>['onClose']} */
134
+ async onClose() {
112
135
  const { portID, channelID } = this.state;
113
136
  const { protocolUtils, channelKeyToSeqAck } = this.state;
114
137
 
@@ -166,12 +189,11 @@ export const prepareIBCProtocol = (zone, powers) => {
166
189
  /**
167
190
  * Create a handler for the IBC protocol, both from the network and from the
168
191
  * bridge.
169
- *
170
- * @param {IBCDevice} ibcdev
171
192
  */
172
193
  const makeIBCProtocolKit = zone.exoClassKit(
173
194
  'IBCProtocolHandler',
174
195
  undefined,
196
+ /** @param {IBCDevice} ibcdev */
175
197
  ibcdev => {
176
198
  /** @type {MapStore<string, Remote<Connection>>} */
177
199
  const channelKeyToConnP = detached.mapStore('channelKeyToConnP');
@@ -206,73 +228,46 @@ export const prepareIBCProtocol = (zone, powers) => {
206
228
  },
207
229
  {
208
230
  protocolHandler: {
209
- async onCreate(impl, _protocolHandler) {
231
+ /** @type {Required<ProtocolHandler>['onCreate']} */
232
+ async onCreate(impl) {
210
233
  console.debug('IBC onCreate');
211
234
  this.state.protocolImpl = impl;
212
235
  },
236
+ /** @type {Required<ProtocolHandler>['onInstantiate']} */
213
237
  async onInstantiate() {
214
238
  // The IBC channel is not known until after handshake.
215
239
  return '';
216
240
  },
217
- async generatePortID(_localAddr, _protocolHandler) {
241
+ /** @type {Required<ProtocolHandler>['generatePortID']} */
242
+ async generatePortID() {
218
243
  this.state.lastPortID += 1n;
219
244
  return `port-${this.state.lastPortID}`;
220
245
  },
221
- async onBind(port, localAddr, _protocolHandler) {
246
+ /** @type {Required<ProtocolHandler>['onBind']} */
247
+ async onBind(_port, localAddr) {
222
248
  const { util } = this.facets;
223
249
  const { portToPendingConns } = this.state;
224
250
 
225
- const portID = util.localAddrToPortID(localAddr);
251
+ // @ts-expect-error may not be LocalIbcAddress
252
+ const portID = localAddrToPortID(localAddr);
226
253
  portToPendingConns.init(portID, detached.setStore('pendingConns'));
227
254
  const packet = {
228
255
  source_port: portID,
229
256
  };
230
257
  return util.downcall('bindPort', { packet });
231
258
  },
232
- async onConnect(
233
- port,
234
- localAddr,
235
- remoteAddr,
236
- _chandler,
237
- _protocolHandler,
238
- ) {
259
+ /** @type {Required<ProtocolHandler>['onConnect']} */
260
+ async onConnect(_port, localAddr, remoteAddr) {
239
261
  const { util } = this.facets;
240
262
  const { portToPendingConns, srcPortToOutbounds } = this.state;
241
263
 
242
264
  console.debug('IBC onConnect', localAddr, remoteAddr);
243
- const portID = util.localAddrToPortID(localAddr);
265
+ // @ts-expect-error may not be LocalIbcAddress
266
+ const portID = localAddrToPortID(localAddr);
244
267
  const pendingConns = portToPendingConns.get(portID);
245
268
 
246
- const match = remoteAddr.match(
247
- /^(\/ibc-hop\/[^/]+)*\/ibc-port\/([^/]+)\/(ordered|unordered)\/([^/]+)$/s,
248
- );
249
- if (!match) {
250
- throw TypeError(
251
- `Remote address ${remoteAddr} must be '(/ibc-hop/CONNECTION)*/ibc-port/PORT/(ordered|unordered)/VERSION'`,
252
- );
253
- }
254
-
255
- const hops = [];
256
- let h = match[1];
257
- while (h) {
258
- const m = h.match(/^\/ibc-hop\/([^/]+)/);
259
- if (!m) {
260
- throw Error(
261
- `internal: ${JSON.stringify(
262
- h,
263
- )} did not begin with "/ibc-hop/XXX"`,
264
- );
265
- }
266
- h = h.substr(m[0].length);
267
- hops.push(m[1]);
268
- }
269
-
270
- // Generate a circuit.
271
- /** @type {IBCPortID} */
272
- const rPortID = match[2];
273
- /** @type {IBCChannelOrdering} */
274
- const order = match[3] === 'ordered' ? 'ORDERED' : 'UNORDERED';
275
- const version = match[4];
269
+ const { rPortID, hops, order, version } =
270
+ decodeRemoteIbcAddress(remoteAddr);
276
271
 
277
272
  const kit = makeVowKit();
278
273
 
@@ -310,18 +305,20 @@ export const prepareIBCProtocol = (zone, powers) => {
310
305
 
311
306
  return kit.vow;
312
307
  },
313
- async onListen(_port, localAddr, _listenHandler) {
308
+ /** @type {Required<ProtocolHandler>['onListen']} */
309
+ async onListen(_port, localAddr) {
314
310
  console.debug('IBC onListen', localAddr);
315
311
  },
316
- async onListenRemove(_port, localAddr, _listenHandler) {
312
+ /** @type {Required<ProtocolHandler>['onListenRemove']} */
313
+ async onListenRemove(_port, localAddr) {
317
314
  console.debug('IBC onListenRemove', localAddr);
318
315
  },
319
- async onRevoke(_port, localAddr, _protocolHandler) {
320
- const { util } = this.facets;
316
+ /** @type {Required<ProtocolHandler>['onRevoke']} */
317
+ async onRevoke(_port, localAddr) {
321
318
  const { portToPendingConns } = this.state;
322
-
323
319
  console.debug('IBC onRevoke', localAddr);
324
- const portID = util.localAddrToPortID(localAddr);
320
+ // @ts-expect-error may not be LocalIbcAddress
321
+ const portID = localAddrToPortID(localAddr);
325
322
 
326
323
  const pendingConns = portToPendingConns.get(portID);
327
324
  portToPendingConns.delete(portID);
@@ -332,6 +329,7 @@ export const prepareIBCProtocol = (zone, powers) => {
332
329
  },
333
330
  },
334
331
  bridgeHandler: {
332
+ /** @param {IBCEvent<IBCBridgeEvent>} obj */
335
333
  async fromBridge(obj) {
336
334
  const {
337
335
  protocolImpl,
@@ -348,7 +346,6 @@ export const prepareIBCProtocol = (zone, powers) => {
348
346
  await null;
349
347
  switch (obj.event) {
350
348
  case 'channelOpenInit': {
351
- /** @type {IBCEvent<'channelOpenInit'>} */
352
349
  const {
353
350
  channelID,
354
351
  portID,
@@ -357,7 +354,7 @@ export const prepareIBCProtocol = (zone, powers) => {
357
354
  order,
358
355
  version,
359
356
  asyncVersions,
360
- } = obj;
357
+ } = /** @type {IBCEvent<'channelOpenInit'>} */ (obj);
361
358
  if (!asyncVersions) {
362
359
  // Synchronous versions have already been negotiated.
363
360
  break;
@@ -381,7 +378,6 @@ export const prepareIBCProtocol = (zone, powers) => {
381
378
  }
382
379
  case 'channelOpenTry': {
383
380
  // They're (more or less politely) asking if we are listening, so make an attempt.
384
- /** @type {IBCEvent<'channelOpenTry'>} */
385
381
  const {
386
382
  portID,
387
383
  counterparty: { port_id: rPortID, channel_id: rChannelID },
@@ -389,11 +385,16 @@ export const prepareIBCProtocol = (zone, powers) => {
389
385
  order,
390
386
  version,
391
387
  counterpartyVersion: rVersion,
392
- } = obj;
388
+ } = /** @type {IBCEvent<'channelOpenTry'>} */ (obj);
393
389
 
394
- const localAddr = `/ibc-port/${portID}/${order.toLowerCase()}/${version}`;
395
- const ibcHops = hops.map(hop => `/ibc-hop/${hop}`).join('/');
396
- const remoteAddr = `${ibcHops}/ibc-port/${rPortID}/${order.toLowerCase()}/${rVersion}/ibc-channel/${rChannelID}`;
390
+ const localAddr = encodeLocalIbcAddress(portID, order, version);
391
+ const remoteAddr = encodeRemoteIbcAddress(
392
+ hops,
393
+ rPortID,
394
+ order,
395
+ rVersion,
396
+ rChannelID,
397
+ );
397
398
 
398
399
  // See if we allow an inbound attempt for this address pair (without
399
400
  // rejecting).
@@ -420,14 +421,14 @@ export const prepareIBCProtocol = (zone, powers) => {
420
421
 
421
422
  case 'channelOpenAck': {
422
423
  // Complete the pending outbound connection.
423
- /** @type {IBCEvent<'channelOpenAck'>} */
424
424
  const {
425
425
  portID,
426
426
  channelID,
427
427
  counterparty: { port_id: rPortID, channel_id: rChannelID },
428
428
  counterpartyVersion: rVersion,
429
429
  connectionHops: rHops,
430
- } = obj;
430
+ } = /** @type {IBCEvent<'channelOpenAck'>} */ (obj);
431
+
431
432
  const outbounds = this.state.srcPortToOutbounds.has(portID)
432
433
  ? [...this.state.srcPortToOutbounds.get(portID)]
433
434
  : [];
@@ -460,8 +461,13 @@ export const prepareIBCProtocol = (zone, powers) => {
460
461
  }
461
462
 
462
463
  // Finish the outbound connection.
463
- const ibcHops = rHops.map(hop => `/ibc-hop/${hop}`).join('/');
464
- const remoteAddress = `${ibcHops}/ibc-port/${rPortID}/${chanInfo.order.toLowerCase()}/${rVersion}/ibc-channel/${rChannelID}`;
464
+ const remoteAddress = encodeRemoteIbcAddress(
465
+ rHops,
466
+ rPortID,
467
+ chanInfo.order,
468
+ rVersion,
469
+ rChannelID,
470
+ );
465
471
  const localAddress = `${localAddr}/${chanInfo.order.toLowerCase()}/${rVersion}/ibc-channel/${channelID}`;
466
472
  const rchandler = makeIBCConnectionHandler(
467
473
  {
@@ -486,8 +492,9 @@ export const prepareIBCProtocol = (zone, powers) => {
486
492
  }
487
493
 
488
494
  case 'channelOpenConfirm': {
489
- /** @type {IBCEvent<'channelOpenConfirm'>} */
490
- const { portID, channelID } = obj;
495
+ const { portID, channelID } =
496
+ /** @type {IBCEvent<'channelOpenConfirm'>} */ (obj);
497
+
491
498
  const channelKey = `${channelID}:${portID}`;
492
499
  channelKeyToAttempt.has(channelKey) ||
493
500
  Fail`${channelKey}: did not expect channelOpenConfirm`;
@@ -525,8 +532,7 @@ export const prepareIBCProtocol = (zone, powers) => {
525
532
  }
526
533
 
527
534
  case 'receivePacket': {
528
- /** @type {IBCEvent<'receivePacket'>} */
529
- const { packet } = obj;
535
+ const { packet } = /** @type {IBCEvent<'receivePacket'>} */ (obj);
530
536
  const {
531
537
  data: data64,
532
538
  destination_port: portID,
@@ -542,26 +548,30 @@ export const prepareIBCProtocol = (zone, powers) => {
542
548
  }
543
549
 
544
550
  case 'acknowledgementPacket': {
545
- /** @type {IBCEvent<'acknowledgementPacket'>} */
546
- const { packet, acknowledgement } = obj;
551
+ const { packet, acknowledgement } =
552
+ /** @type {IBCEvent<'acknowledgementPacket'>} */ (obj);
547
553
  const {
548
554
  sequence,
549
555
  source_channel: channelID,
550
556
  source_port: portID,
551
557
  } = packet;
558
+ if (sequence === undefined)
559
+ throw TypeError('acknowledgementPacket without sequence');
552
560
  const ackKit = util.findAckKit(channelID, portID, sequence);
553
561
  ackKit.resolver.resolve(base64ToBytes(acknowledgement));
554
562
  break;
555
563
  }
556
564
 
557
565
  case 'timeoutPacket': {
558
- /** @type {IBCEvent<'timeoutPacket'>} */
559
- const { packet } = obj;
566
+ const { packet } = /** @type {IBCEvent<'timeoutPacket'>} */ (obj);
560
567
  const {
561
568
  sequence,
562
569
  source_channel: channelID,
563
570
  source_port: portID,
564
571
  } = packet;
572
+ if (sequence === undefined)
573
+ throw TypeError('timeoutPacket without sequence');
574
+
565
575
  const ackKit = util.findAckKit(channelID, portID, sequence);
566
576
  ackKit.resolver.reject(Error(`Packet timed out`));
567
577
  break;
@@ -569,7 +579,9 @@ export const prepareIBCProtocol = (zone, powers) => {
569
579
 
570
580
  case 'channelCloseInit':
571
581
  case 'channelCloseConfirm': {
572
- const { portID, channelID } = obj;
582
+ const { portID, channelID } =
583
+ // could be either but that complicates line wrapping
584
+ /** @type {IBCEvent<'channelCloseInit'>} */ (obj);
573
585
  const channelKey = `${channelID}:${portID}`;
574
586
  if (channelKeyToConnP.has(channelKey)) {
575
587
  const conn = channelKeyToConnP.get(channelKey);
@@ -580,8 +592,8 @@ export const prepareIBCProtocol = (zone, powers) => {
580
592
  }
581
593
 
582
594
  case 'sendPacket': {
583
- /** @type {IBCEvent<'sendPacket'>} */
584
- const { packet, relativeTimeoutNs } = obj;
595
+ const { packet, relativeTimeoutNs } =
596
+ /** @type {IBCEvent<'sendPacket'>} */ (obj);
585
597
  util.ibcSendPacket(packet, relativeTimeoutNs).then(
586
598
  ack => console.info('Manual packet', packet, 'acked:', ack),
587
599
  e => console.warn('Manual packet', packet, 'failed:', e),
@@ -633,17 +645,12 @@ export const prepareIBCProtocol = (zone, powers) => {
633
645
  const { vow } = util.findAckKit(channelID, portID, sequence);
634
646
  return vow;
635
647
  },
636
- /** @param {string} localAddr */
637
- localAddrToPortID(localAddr) {
638
- const m = localAddr.match(/^\/ibc-port\/([-a-zA-Z0-9._+#[\]<>]+)$/);
639
- if (!m) {
640
- throw TypeError(
641
- `Invalid port specification ${localAddr}; expected "/ibc-port/PORT"`,
642
- );
643
- }
644
- return m[1];
645
- },
646
648
 
649
+ /**
650
+ * @param {IBCChannelID} channelID
651
+ * @param {IBCPortID} portID
652
+ * @param {number} sequence
653
+ */
647
654
  findAckKit(channelID, portID, sequence) {
648
655
  const { channelKeyToSeqAck } = this.state;
649
656
  const channelKey = `${channelID}:${portID}`;
@@ -657,6 +664,10 @@ export const prepareIBCProtocol = (zone, powers) => {
657
664
  },
658
665
  },
659
666
  ackWatcher: {
667
+ /**
668
+ * @param {string} ack
669
+ * @param {{ packet: any }} watcherContext
670
+ */
660
671
  onFulfilled(ack, watcherContext) {
661
672
  const { packet } = watcherContext;
662
673
 
@@ -674,6 +685,21 @@ export const prepareIBCProtocol = (zone, powers) => {
674
685
  },
675
686
  },
676
687
  protocolImplAttemptWatcher: {
688
+ /**
689
+ * @param {string} attemptedLocal
690
+ * @param {{
691
+ * channelID: IBCChannelID;
692
+ * portID: string;
693
+ * attempt: any;
694
+ * obj: any;
695
+ * asyncVersions: any;
696
+ * rPortID: string;
697
+ * rChannelID: IBCChannelID;
698
+ * order: IBCChannelOrdering;
699
+ * hops: any;
700
+ * version: string;
701
+ * }} watcherContext
702
+ */
677
703
  onFulfilled(attemptedLocal, watcherContext) {
678
704
  const {
679
705
  channelID,
@@ -736,6 +762,10 @@ export const prepareIBCProtocol = (zone, powers) => {
736
762
  },
737
763
  },
738
764
  protocolImplInboundWatcher: {
765
+ /**
766
+ * @param {any} attempt
767
+ * @param {Record<string, any>} watchContext
768
+ */
739
769
  onFulfilled(attempt, watchContext) {
740
770
  const { obj } = watchContext;
741
771
 
@@ -754,11 +784,13 @@ export const prepareIBCProtocol = (zone, powers) => {
754
784
  },
755
785
  );
756
786
 
787
+ /** @param {IBCDevice} ibcdev */
757
788
  const makeIBCProtocolHandlerKit = ibcdev => {
758
789
  const { protocolHandler, bridgeHandler } = makeIBCProtocolKit(ibcdev);
759
790
  return harden({ protocolHandler, bridgeHandler });
760
791
  };
761
792
 
793
+ /** @param {IBCDevice} ibcdev */
762
794
  const provideIBCProtocolHandlerKit = ibcdev => {
763
795
  if (ibcdevToKit.has(ibcdev)) {
764
796
  return ibcdevToKit.get(ibcdev);
@@ -769,7 +801,6 @@ export const prepareIBCProtocol = (zone, powers) => {
769
801
  };
770
802
  return provideIBCProtocolHandlerKit;
771
803
  };
772
-
773
804
  harden(prepareIBCProtocol);
774
805
 
775
806
  /** @param {Zone} zone */
@@ -780,6 +811,10 @@ export const prepareCallbacks = zone => {
780
811
  /** @param {ScopedBridgeManager} dibcBridgeManager */
781
812
  dibcBridgeManager => ({ dibcBridgeManager }),
782
813
  {
814
+ /**
815
+ * @param {string} method
816
+ * @param {any} obj
817
+ */
783
818
  downcall(method, obj) {
784
819
  const { dibcBridgeManager } = this.state;
785
820
  return E(dibcBridgeManager).toBridge({
package/src/types.d.ts CHANGED
@@ -167,8 +167,8 @@ type IBCPacketEvents = {
167
167
  timeoutPacket: {
168
168
  packet: IBCPacket;
169
169
  };
170
- channelCloseInit: {}; // TODO update
171
- channelCloseConfirm: {}; // TODO update
170
+ channelCloseInit: ConnectingInfo; // TODO update
171
+ channelCloseConfirm: ConnectingInfo; // TODO update
172
172
  sendPacket: { relativeTimeoutNs: bigint; packet: IBCPacket };
173
173
  };
174
174
 
package/src/vat-ibc.d.ts CHANGED
@@ -4,21 +4,21 @@ export function buildRootObject(_vatPowers: any, _args: any, baggage: any): {
4
4
  bridgeHandler: import("./types.js").BridgeHandler;
5
5
  } | {
6
6
  protocolHandler: import("@endo/exo").Guarded<{
7
- onCreate(impl: any, _protocolHandler: any): Promise<void>;
8
- onInstantiate(): Promise<string>;
9
- generatePortID(_localAddr: any, _protocolHandler: any): Promise<string>;
10
- onBind(port: any, localAddr: any, _protocolHandler: any): Promise<any>;
11
- onConnect(port: any, localAddr: any, remoteAddr: any, _chandler: any, _protocolHandler: any): Promise<import("@agoric/vow").Vow<any>>;
12
- onListen(_port: any, localAddr: any, _listenHandler: any): Promise<void>;
13
- onListenRemove(_port: any, localAddr: any, _listenHandler: any): Promise<void>;
14
- onRevoke(_port: any, localAddr: any, _protocolHandler: any): Promise<void>;
7
+ onCreate(protocol: Remote<ProtocolImpl>, p: Remote<ProtocolHandler>): PromiseVow<void>;
8
+ onInstantiate(port: Remote<Port>, localAddr: string, remote: string, p: Remote<ProtocolHandler>): PromiseVow<string>;
9
+ generatePortID(localAddr: string, p: Remote<ProtocolHandler>): PromiseVow<string>;
10
+ onBind(port: Remote<Port>, localAddr: string, p: Remote<ProtocolHandler>): PromiseVow<void>;
11
+ onConnect(port: Remote<Port>, localAddr: string, remote: string, c: Remote<ConnectionHandler>, p: Remote<ProtocolHandler>): PromiseVow<AttemptDescription>;
12
+ onListen(port: Remote<Port>, localAddr: string, listenHandler: Remote<ListenHandler>, p: Remote<ProtocolHandler>): PromiseVow<void>;
13
+ onListenRemove(port: Remote<Port>, localAddr: string, listenHandler: Remote<ListenHandler>, p: Remote<ProtocolHandler>): PromiseVow<void>;
14
+ onRevoke(port: Remote<Port>, localAddr: string, p: Remote<ProtocolHandler>): PromiseVow<void>;
15
15
  }>;
16
16
  bridgeHandler: import("@endo/exo").Guarded<{
17
- fromBridge(obj: any): Promise<import("@agoric/vow").Vow<any> | undefined>;
17
+ fromBridge(obj: import("./types.js").IBCEvent<import("./types.js").IBCBridgeEvent>): Promise<import("@agoric/vow").Vow<any> | undefined>;
18
18
  }>;
19
19
  };
20
20
  makeCallbacks: (dibcBridgeManager: import("./types.js").ScopedBridgeManager) => import("@endo/exo").Guarded<{
21
- downcall(method: any, obj: any): Promise<any>;
21
+ downcall(method: string, obj: any): Promise<any>;
22
22
  }>;
23
23
  } & import("@endo/eventual-send").RemotableBrand<{}, {
24
24
  createHandlers: (callbacks: any) => {
@@ -26,21 +26,21 @@ export function buildRootObject(_vatPowers: any, _args: any, baggage: any): {
26
26
  bridgeHandler: import("./types.js").BridgeHandler;
27
27
  } | {
28
28
  protocolHandler: import("@endo/exo").Guarded<{
29
- onCreate(impl: any, _protocolHandler: any): Promise<void>;
30
- onInstantiate(): Promise<string>;
31
- generatePortID(_localAddr: any, _protocolHandler: any): Promise<string>;
32
- onBind(port: any, localAddr: any, _protocolHandler: any): Promise<any>;
33
- onConnect(port: any, localAddr: any, remoteAddr: any, _chandler: any, _protocolHandler: any): Promise<import("@agoric/vow").Vow<any>>;
34
- onListen(_port: any, localAddr: any, _listenHandler: any): Promise<void>;
35
- onListenRemove(_port: any, localAddr: any, _listenHandler: any): Promise<void>;
36
- onRevoke(_port: any, localAddr: any, _protocolHandler: any): Promise<void>;
29
+ onCreate(protocol: Remote<ProtocolImpl>, p: Remote<ProtocolHandler>): PromiseVow<void>;
30
+ onInstantiate(port: Remote<Port>, localAddr: string, remote: string, p: Remote<ProtocolHandler>): PromiseVow<string>;
31
+ generatePortID(localAddr: string, p: Remote<ProtocolHandler>): PromiseVow<string>;
32
+ onBind(port: Remote<Port>, localAddr: string, p: Remote<ProtocolHandler>): PromiseVow<void>;
33
+ onConnect(port: Remote<Port>, localAddr: string, remote: string, c: Remote<ConnectionHandler>, p: Remote<ProtocolHandler>): PromiseVow<AttemptDescription>;
34
+ onListen(port: Remote<Port>, localAddr: string, listenHandler: Remote<ListenHandler>, p: Remote<ProtocolHandler>): PromiseVow<void>;
35
+ onListenRemove(port: Remote<Port>, localAddr: string, listenHandler: Remote<ListenHandler>, p: Remote<ProtocolHandler>): PromiseVow<void>;
36
+ onRevoke(port: Remote<Port>, localAddr: string, p: Remote<ProtocolHandler>): PromiseVow<void>;
37
37
  }>;
38
38
  bridgeHandler: import("@endo/exo").Guarded<{
39
- fromBridge(obj: any): Promise<import("@agoric/vow").Vow<any> | undefined>;
39
+ fromBridge(obj: import("./types.js").IBCEvent<import("./types.js").IBCBridgeEvent>): Promise<import("@agoric/vow").Vow<any> | undefined>;
40
40
  }>;
41
41
  };
42
42
  makeCallbacks: (dibcBridgeManager: import("./types.js").ScopedBridgeManager) => import("@endo/exo").Guarded<{
43
- downcall(method: any, obj: any): Promise<any>;
43
+ downcall(method: string, obj: any): Promise<any>;
44
44
  }>;
45
45
  }>;
46
46
  //# sourceMappingURL=vat-ibc.d.ts.map
@@ -0,0 +1,15 @@
1
+ export const REMOTE_ADDR_RE: RegExp;
2
+ /** @typedef {`/${string}ibc-port/${string}/${'ordered' | 'unordered'}/${string}`} RemoteIbcAddress */
3
+ export const LOCAL_ADDR_RE: RegExp;
4
+ export function decodeRemoteIbcAddress(remoteAddr: string): {
5
+ rPortID: string;
6
+ hops: `connection-${number}`[];
7
+ order: import("../src/types.js").IBCChannelOrdering;
8
+ version: string;
9
+ };
10
+ export function localAddrToPortID(localAddr: LocalIbcAddress): string;
11
+ export function encodeRemoteIbcAddress(hops: string[], rPortID: string, order: 'ordered' | 'unordered' | 'ORDERED' | 'UNORDERED', rVersion: string, rChannelID: string): RemoteIbcAddress;
12
+ export function encodeLocalIbcAddress(portID: string, order: 'ordered' | 'unordered' | 'ORDERED' | 'UNORDERED', version: string): string;
13
+ export type RemoteIbcAddress = `/${string}ibc-port/${string}/${'ordered' | 'unordered'}/${string}`;
14
+ export type LocalIbcAddress = `/ibc-port/${string}`;
15
+ //# sourceMappingURL=ibc-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ibc-utils.d.ts","sourceRoot":"","sources":["ibc-utils.js"],"names":[],"mappings":"AAAA,oCAC8G;AAE9G,sGAAsG;AAEtG,mCAA+E;AAIxE,mDADK,MAAM;;;;;EA8BjB;AAOM,6CAHI,eAAe,GACb,MAAM,CAWlB;AAWM,6CAPI,MAAM,EAAE,WACR,MAAM,SACN,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,YACjD,MAAM,cACN,MAAM,GACJ,gBAAgB,CAa5B;AAQM,8CAJI,MAAM,SACN,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,WACjD,MAAM,UAIhB;+BAnFa,IAAI,MAAM,YAAY,MAAM,IAAI,SAAS,GAAG,WAAW,IAAI,MAAM,EAAE;8BAGnE,aAAa,MAAM,EAAE"}
@@ -0,0 +1,89 @@
1
+ export const REMOTE_ADDR_RE =
2
+ /^(?<hops>\/ibc-hop\/[^/]+)*\/ibc-port\/(?<portID>[^/]+)\/(?<order>ordered|unordered)\/(?<version>[^/]+)$/s;
3
+ harden(REMOTE_ADDR_RE);
4
+ /** @typedef {`/${string}ibc-port/${string}/${'ordered' | 'unordered'}/${string}`} RemoteIbcAddress */
5
+
6
+ export const LOCAL_ADDR_RE = /^\/ibc-port\/(?<portID>[-a-zA-Z0-9._+#[\]<>]+)$/;
7
+ /** @typedef {`/ibc-port/${string}`} LocalIbcAddress */
8
+
9
+ /** @param {string} remoteAddr */
10
+ export const decodeRemoteIbcAddress = remoteAddr => {
11
+ const match = remoteAddr.match(REMOTE_ADDR_RE);
12
+ // .groups is to inform TS https://github.com/microsoft/TypeScript/issues/32098
13
+ if (!(match && match.groups)) {
14
+ throw TypeError(
15
+ `Remote address ${remoteAddr} must be '(/ibc-hop/CONNECTION)*/ibc-port/PORT/(ordered|unordered)/VERSION'`,
16
+ );
17
+ }
18
+
19
+ /** @type {import('../src/types.js').IBCConnectionID[]} */
20
+ const hops = [];
21
+
22
+ let h = match.groups.hops;
23
+ while (h) {
24
+ const m = h.match(/^\/ibc-hop\/(?<hop>[^/]+)/);
25
+ if (!m) {
26
+ throw Error(
27
+ `internal: ${JSON.stringify(h)} did not begin with "/ibc-hop/XXX"`,
28
+ );
29
+ }
30
+ h = h.substr(m[0].length);
31
+ // @ts-expect-error unchecked cast
32
+ hops.push(m.groups.hop);
33
+ }
34
+ // Generate a circuit.
35
+ const { portID: rPortID, version } = match.groups;
36
+ /** @type {import('../src/types.js').IBCChannelOrdering} */
37
+ const order = match.groups.order === 'ordered' ? 'ORDERED' : 'UNORDERED';
38
+ return { rPortID, hops, order, version };
39
+ };
40
+ harden(decodeRemoteIbcAddress);
41
+
42
+ /**
43
+ * @param {LocalIbcAddress} localAddr
44
+ * @returns {string}
45
+ */
46
+ export const localAddrToPortID = localAddr => {
47
+ const m = localAddr.match(LOCAL_ADDR_RE);
48
+ // .groups is to inform TS https://github.com/microsoft/TypeScript/issues/32098
49
+ if (!(m && m.groups)) {
50
+ throw TypeError(
51
+ `Invalid port specification ${localAddr}; expected "/ibc-port/PORT"`,
52
+ );
53
+ }
54
+ return m.groups.portID;
55
+ };
56
+ harden(localAddrToPortID);
57
+
58
+ /**
59
+ * @param {string[]} hops
60
+ * @param {string} rPortID
61
+ * @param {'ordered' | 'unordered' | 'ORDERED' | 'UNORDERED'} order
62
+ * @param {string} rVersion
63
+ * @param {string} rChannelID
64
+ * @returns {RemoteIbcAddress}
65
+ */
66
+ export const encodeRemoteIbcAddress = (
67
+ hops,
68
+ rPortID,
69
+ order,
70
+ rVersion,
71
+ rChannelID,
72
+ ) => {
73
+ const ibcHops = hops.map(hop => `/ibc-hop/${hop}`).join('/');
74
+ return /** @type {RemoteIbcAddress} */ (
75
+ `${ibcHops}/ibc-port/${rPortID}/${order.toLowerCase()}/${rVersion}/ibc-channel/${rChannelID}`
76
+ );
77
+ };
78
+ harden(encodeRemoteIbcAddress);
79
+
80
+ /**
81
+ * @param {string} portID
82
+ * @param {'ordered' | 'unordered' | 'ORDERED' | 'UNORDERED'} order
83
+ * @param {string} version
84
+ */
85
+ export const encodeLocalIbcAddress = (portID, order, version) => {
86
+ return `/ibc-port/${portID}/${order.toLowerCase()}/${version}`;
87
+ };
88
+
89
+ harden(encodeLocalIbcAddress);