@agoric/orchestration 0.2.0-upgrade-18-dev-aaebae4.0 → 0.2.0-upgrade-18-dev-bd8fd54.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 (116) hide show
  1. package/index.d.ts +3 -0
  2. package/index.js +3 -0
  3. package/package.json +30 -29
  4. package/src/chain-capabilities.d.ts +15 -0
  5. package/src/chain-capabilities.d.ts.map +1 -0
  6. package/src/chain-capabilities.js +60 -0
  7. package/src/chain-info.d.ts +33 -20
  8. package/src/chain-info.d.ts.map +1 -1
  9. package/src/cosmos-api.d.ts +96 -21
  10. package/src/cosmos-api.d.ts.map +1 -1
  11. package/src/cosmos-api.ts +115 -28
  12. package/src/examples/auto-stake-it.contract.d.ts +19 -2
  13. package/src/examples/auto-stake-it.contract.d.ts.map +1 -1
  14. package/src/examples/auto-stake-it.contract.js +13 -2
  15. package/src/examples/auto-stake-it.flows.d.ts +1 -1
  16. package/src/examples/basic-flows.contract.d.ts +16 -1
  17. package/src/examples/basic-flows.contract.d.ts.map +1 -1
  18. package/src/examples/basic-flows.contract.js +14 -3
  19. package/src/examples/basic-flows.flows.d.ts +1 -1
  20. package/src/examples/send-anywhere.contract.d.ts +28 -5
  21. package/src/examples/send-anywhere.contract.d.ts.map +1 -1
  22. package/src/examples/send-anywhere.contract.js +11 -0
  23. package/src/examples/stake-bld.contract.d.ts +2 -2
  24. package/src/examples/stake-ica.contract.d.ts +5 -0
  25. package/src/examples/stake-ica.contract.d.ts.map +1 -1
  26. package/src/examples/staking-combinations.contract.d.ts +2 -0
  27. package/src/examples/staking-combinations.contract.d.ts.map +1 -1
  28. package/src/examples/staking-combinations.contract.js +1 -2
  29. package/src/examples/staking-combinations.flows.d.ts +4 -2
  30. package/src/examples/staking-combinations.flows.d.ts.map +1 -1
  31. package/src/examples/staking-combinations.flows.js +9 -4
  32. package/src/examples/swap.contract.d.ts +18 -2
  33. package/src/examples/swap.contract.d.ts.map +1 -1
  34. package/src/examples/swap.contract.js +6 -0
  35. package/src/exos/README.md +5 -4
  36. package/src/exos/chain-hub-admin.d.ts.map +1 -1
  37. package/src/exos/chain-hub-admin.js +1 -2
  38. package/src/exos/chain-hub.d.ts +37 -25
  39. package/src/exos/chain-hub.d.ts.map +1 -1
  40. package/src/exos/chain-hub.js +203 -18
  41. package/src/exos/cosmos-interchain-service.d.ts +5 -5
  42. package/src/exos/cosmos-interchain-service.d.ts.map +1 -1
  43. package/src/exos/cosmos-interchain-service.js +3 -3
  44. package/src/exos/cosmos-orchestration-account.d.ts +7 -24
  45. package/src/exos/cosmos-orchestration-account.d.ts.map +1 -1
  46. package/src/exos/cosmos-orchestration-account.js +27 -14
  47. package/src/exos/ibc-packet.d.ts.map +1 -1
  48. package/src/exos/ica-account-kit.d.ts +1 -3
  49. package/src/exos/ica-account-kit.d.ts.map +1 -1
  50. package/src/exos/local-chain-facade.d.ts +4 -2
  51. package/src/exos/local-chain-facade.d.ts.map +1 -1
  52. package/src/exos/local-orchestration-account.d.ts +13 -50
  53. package/src/exos/local-orchestration-account.d.ts.map +1 -1
  54. package/src/exos/local-orchestration-account.js +50 -53
  55. package/src/exos/orchestrator.d.ts +5 -7
  56. package/src/exos/orchestrator.d.ts.map +1 -1
  57. package/src/exos/orchestrator.js +12 -6
  58. package/src/exos/packet-tools.d.ts +1 -6
  59. package/src/exos/packet-tools.d.ts.map +1 -1
  60. package/src/exos/packet-tools.js +8 -12
  61. package/src/exos/portfolio-holder-kit.d.ts +4 -4
  62. package/src/exos/portfolio-holder-kit.d.ts.map +1 -1
  63. package/src/exos/portfolio-holder-kit.js +1 -1
  64. package/src/exos/remote-chain-facade.d.ts +3 -8
  65. package/src/exos/remote-chain-facade.d.ts.map +1 -1
  66. package/src/exos/remote-chain-facade.js +0 -2
  67. package/src/facade.d.ts.map +1 -1
  68. package/src/facade.js +0 -1
  69. package/src/fetched-chain-info.d.ts +43 -18
  70. package/src/fetched-chain-info.js +31 -18
  71. package/src/orchestration-api.d.ts +8 -5
  72. package/src/orchestration-api.d.ts.map +1 -1
  73. package/src/orchestration-api.ts +15 -14
  74. package/src/proposals/start-auto-stake-it.d.ts +52 -0
  75. package/src/proposals/start-auto-stake-it.d.ts.map +1 -0
  76. package/src/proposals/start-auto-stake-it.js +108 -0
  77. package/src/proposals/start-basic-flows.d.ts +39 -6
  78. package/src/proposals/start-basic-flows.d.ts.map +1 -1
  79. package/src/proposals/start-basic-flows.js +60 -21
  80. package/src/proposals/start-send-anywhere.d.ts +105 -0
  81. package/src/proposals/start-send-anywhere.d.ts.map +1 -0
  82. package/src/proposals/start-send-anywhere.js +150 -0
  83. package/src/proposals/start-stakeAtom.d.ts +5 -0
  84. package/src/proposals/start-stakeAtom.d.ts.map +1 -1
  85. package/src/proposals/start-stakeBld.d.ts +2 -2
  86. package/src/proposals/start-stakeOsmo.d.ts +5 -0
  87. package/src/proposals/start-stakeOsmo.d.ts.map +1 -1
  88. package/src/typeGuards.d.ts +27 -4
  89. package/src/typeGuards.d.ts.map +1 -1
  90. package/src/typeGuards.js +103 -26
  91. package/src/types.d.ts +1 -0
  92. package/src/types.d.ts.map +1 -1
  93. package/src/types.ts +1 -0
  94. package/src/utils/address.d.ts +2 -1
  95. package/src/utils/address.d.ts.map +1 -1
  96. package/src/utils/address.js +18 -1
  97. package/src/utils/asset.d.ts +5 -0
  98. package/src/utils/asset.d.ts.map +1 -0
  99. package/src/utils/asset.js +33 -0
  100. package/src/utils/chain-hub-helper.d.ts +8 -0
  101. package/src/utils/chain-hub-helper.d.ts.map +1 -0
  102. package/src/utils/chain-hub-helper.js +60 -0
  103. package/src/utils/orchestrationAccount.js +2 -2
  104. package/src/utils/packet.d.ts +1 -1
  105. package/src/utils/packet.d.ts.map +1 -1
  106. package/src/utils/registry.d.ts +2 -0
  107. package/src/utils/registry.d.ts.map +1 -1
  108. package/src/utils/registry.js +3 -1
  109. package/src/utils/start-helper.d.ts +7 -4
  110. package/src/utils/start-helper.d.ts.map +1 -1
  111. package/src/utils/start-helper.js +6 -4
  112. package/src/utils/time.d.ts +1 -1
  113. package/src/utils/time.d.ts.map +1 -1
  114. package/src/vat-orchestration.d.ts +9 -9
  115. package/src/vat-orchestration.d.ts.map +1 -1
  116. package/src/vat-orchestration.js +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"staking-combinations.flows.d.ts","sourceRoot":"","sources":["staking-combinations.flows.js"],"names":[],"mappings":"AA4BO,kCATI,YAAY,OACZ;IACN,2BAA2B,EAAE,2BAA2B,CAAC;IACzD,wBAAwB,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,gBAAgB,CAAC;CAC9D,SACO,OAAO,iBACP;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GACnB,OAAO,CAAC,6BAA6B,CAAC,CAiBlD;AAcM,yCATI,YAAY,qCAEpB;IAA6E,mBAAmB,EAAxF,OAAO,CAAC,eAAe,4BAA4B,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjC,QAAQ,EAAtC,eAAe,QAAQ,CAAC;CAChC,WAAQ,eAAe,0BAA0B,CAAC,QAC1C,OAAO,aACP,sBAAsB,GACpB,OAAO,CAAC,IAAI,CAAC,CAgCzB;AAcM,4CATI,YAAY,OACZ,MAAM,WACN,eAAe,0BAA0B,CAAC,gCAC1C;IACN,WAAW,EAAE;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,SAAS,EAAE,sBAAsB,CAAA;KAAE,EAAE,CAAC;IACxE,WAAW,EAAE,YAAY,CAAC;CAC3B,GACS,OAAO,CAAC,IAAI,CAAC,CAYzB;kCA7G8I,aAAa;iDAG9G,sCAAsC;sCAF1B,mCAAmC;mDAInC,uBAAuB;kDAHlC,wCAAwC;oCAHtD,oBAAoB;8BAMK,uBAAuB;gDADpC,yCAAyC;4CAJyD,aAAa;+BAAb,aAAa;kCAAb,aAAa"}
1
+ {"version":3,"file":"staking-combinations.flows.d.ts","sourceRoot":"","sources":["staking-combinations.flows.js"],"names":[],"mappings":"AA4BO,kCATI,YAAY,OACZ;IACN,2BAA2B,EAAE,2BAA2B,CAAC;IACzD,wBAAwB,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,gBAAgB,CAAC;CAC9D,SACO,OAAO,iBACP;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GACnB,OAAO,CAAC,6BAA6B,CAAC,CAiBlD;AAeM,yCAVI,YAAY,+CAEpB;IAAsC,QAAQ,EAAtC,eAAe,QAAQ,CAAC;IAC6C,mBAAmB,EAAxF,OAAO,CAAC,eAAe,4BAA4B,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjC,QAAQ,EAAtC,eAAe,QAAQ,CAAC;CAChC,WAAQ,eAAe,0BAA0B,CAAC,QAC1C,OAAO,aACP,sBAAsB,GACpB,OAAO,CAAC,IAAI,CAAC,CAoCzB;AAcM,4CATI,YAAY,OACZ,MAAM,WACN,eAAe,0BAA0B,CAAC,gCAC1C;IACN,WAAW,EAAE;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,SAAS,EAAE,sBAAsB,CAAA;KAAE,EAAE,CAAC;IACxE,WAAW,EAAE,YAAY,CAAC;CAC3B,GACS,OAAO,CAAC,IAAI,CAAC,CAYzB;kCAlH6J,aAAa;iDAG7H,sCAAsC;sCAF1B,mCAAmC;mDAInC,uBAAuB;8BAL6E,aAAa;oCAD1I,oBAAoB;kDAGN,wCAAwC;8BAG7B,uBAAuB;gDADpC,yCAAyC;4CAJwE,aAAa;+BAAb,aAAa;kCAAb,aAAa"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @import {GuestInterface} from '@agoric/async-flow';
3
- * @import {Orchestrator, OrchestrationFlow, AmountArg, CosmosValidatorAddress, ChainAddress, LocalAccountMethods, OrchestrationAccountI} from '../types.js'
3
+ * @import {Orchestrator, OrchestrationFlow, AmountArg, CosmosValidatorAddress, ChainAddress, LocalAccountMethods, OrchestrationAccountCommon, ChainHub} from '../types.js'
4
4
  * @import {ContinuingOfferResult, InvitationMakers} from '@agoric/smart-wallet/src/types.js';
5
5
  * @import {LocalOrchestrationAccountKit} from '../exos/local-orchestration-account.js';
6
6
  * @import {MakeCombineInvitationMakers} from '../exos/combine-invitation-makers.js';
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import { mustMatch } from '@endo/patterns';
12
- import { makeError, q } from '@endo/errors';
12
+ import { Fail, makeError, q } from '@endo/errors';
13
13
  import { makeTracer } from '@agoric/internal';
14
14
  import { ChainAddressShape } from '../typeGuards.js';
15
15
 
@@ -48,6 +48,7 @@ harden(makeAccount);
48
48
  * @satisfies {OrchestrationFlow}
49
49
  * @param {Orchestrator} orch
50
50
  * @param {object} ctx
51
+ * @param {GuestInterface<ChainHub>} ctx.chainHub
51
52
  * @param {Promise<GuestInterface<LocalOrchestrationAccountKit['holder']>>} ctx.sharedLocalAccountP
52
53
  * @param {GuestInterface<ZoeTools>} ctx.zoeTools
53
54
  * @param {GuestInterface<CosmosOrchestrationAccount>} account
@@ -57,7 +58,7 @@ harden(makeAccount);
57
58
  */
58
59
  export const depositAndDelegate = async (
59
60
  orch,
60
- { sharedLocalAccountP, zoeTools },
61
+ { chainHub, sharedLocalAccountP, zoeTools },
61
62
  account,
62
63
  seat,
63
64
  validator,
@@ -84,7 +85,11 @@ export const depositAndDelegate = async (
84
85
  throw errMsg;
85
86
  }
86
87
  seat.exit();
87
- await account.delegate(validator, give.Stake);
88
+ const denom = chainHub.getDenom(give.Stake.brand);
89
+ if (!denom) throw Fail`unknown brand ${q(give.Stake.brand)}`;
90
+ // TODO #10449 amountToCoin accepts brands
91
+ const denomAmount = harden({ denom, value: give.Stake.value });
92
+ await account.delegate(validator, denomAmount);
88
93
  };
89
94
  harden(depositAndDelegate);
90
95
 
@@ -6,10 +6,11 @@
6
6
  * @import {NameHub} from '@agoric/vats';
7
7
  * @import {Zone} from '@agoric/zone';
8
8
  * @import {OrchestrationTools} from '../utils/start-helper.js';
9
+ * @import {CosmosChainInfo, Denom, DenomDetail} from '@agoric/orchestration';
9
10
  */
10
11
  /** @type {ContractMeta<typeof start>} */
11
12
  export const meta: ContractMeta<typeof start>;
12
- export function makeNatAmountShape(brand: Brand, min?: bigint | undefined): {
13
+ export function makeNatAmountShape(brand: Brand, min?: NatValue): {
13
14
  brand: globalThis.Brand;
14
15
  value: import("@endo/patterns").Matcher;
15
16
  };
@@ -20,11 +21,24 @@ export const start: (zcf: ZCF<Record<string, unknown>>, privateArgs: {
20
21
  storageNode: Remote<StorageNode>;
21
22
  timerService: Remote<TimerService>;
22
23
  marshaller: Marshaller;
24
+ chainInfo: Record<string, Readonly<{
25
+ bech32Prefix?: string;
26
+ chainId: string;
27
+ connections?: Record<string, import("@agoric/orchestration").IBCConnectionInfo>;
28
+ icqEnabled?: boolean;
29
+ pfmEnabled?: boolean;
30
+ stakingTokens?: Readonly<Array<{
31
+ denom: string;
32
+ }>>;
33
+ }>>;
34
+ assetInfo: [Denom, DenomDetail & {
35
+ brandKey?: string;
36
+ }][];
23
37
  }, baggage: import("@agoric/vat-data").Baggage) => Promise<{
24
38
  publicFacet: import("@endo/exo").Guarded<{
25
39
  makeSwapAndStakeInvitation(): Promise<Invitation<import("@agoric/vow").Vow<void>, {
26
40
  staked: Amount<"nat">;
27
- validator: import("../cosmos-api.js").CosmosValidatorAddress;
41
+ validator: import("@agoric/orchestration").CosmosValidatorAddress;
28
42
  }>>;
29
43
  }>;
30
44
  }>;
@@ -33,4 +47,6 @@ import type { Remote } from '@agoric/internal';
33
47
  import type { LocalChain } from '@agoric/vats/src/localchain.js';
34
48
  import type { CosmosInterchainService } from '../exos/exo-interfaces.js';
35
49
  import type { TimerService } from '@agoric/time';
50
+ import type { Denom } from '@agoric/orchestration';
51
+ import type { DenomDetail } from '@agoric/orchestration';
36
52
  //# sourceMappingURL=swap.contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"swap.contract.d.ts","sourceRoot":"","sources":["swap.contract.js"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AAEH,yCAAyC;AACzC,mBADW,YAAY,CAAC,OAAO,KAAK,CAAC,CAWnC;AASK,0CAHI,KAAK;;;EAIsC;AAgDtD;iBAxCkB,OAAO,OAAO,CAAC;gBAChB,OAAO,UAAU,CAAC;0BACR,OAAO,uBAAuB,CAAC;iBACxC,OAAO,WAAW,CAAC;kBAClB,OAAO,YAAY,CAAC;gBACtB,UAAU;;;;;;;;GAmCsB;6BA1EvB,cAAc;4BAFf,kBAAkB;gCADd,gCAAgC;6CAEnB,2BAA2B;kCAHtC,cAAc"}
1
+ {"version":3,"file":"swap.contract.d.ts","sourceRoot":"","sources":["swap.contract.js"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AAEH,yCAAyC;AACzC,mBADW,YAAY,CAAC,OAAO,KAAK,CAAC,CAanC;AASK,0CAHI,KAAK,QACL,QAAQ;;;EAGmC;AAkDtD;iBA1CkB,OAAO,OAAO,CAAC;gBAChB,OAAO,UAAU,CAAC;0BACR,OAAO,uBAAuB,CAAC;iBACxC,OAAO,WAAW,CAAC;kBAClB,OAAO,YAAY,CAAC;gBACtB,UAAU;;;;;;;;;;;eAEX,CAAC,KAAK,EAAE,WAAW,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE;;;;;;;;GAmCb;6BA/EvB,cAAc;4BAFf,kBAAkB;gCADd,gCAAgC;6CAEnB,2BAA2B;kCAHtC,cAAc;2BAOS,uBAAuB;iCAAvB,uBAAuB"}
@@ -3,6 +3,7 @@ import { TimerServiceShape } from '@agoric/time';
3
3
  import { M } from '@endo/patterns';
4
4
  import { withOrchestration } from '../utils/start-helper.js';
5
5
  import * as flows from './swap.flows.js';
6
+ import { CosmosChainInfoShape, DenomDetailShape } from '../typeGuards.js';
6
7
 
7
8
  /**
8
9
  * @import {TimerService} from '@agoric/time';
@@ -12,6 +13,7 @@ import * as flows from './swap.flows.js';
12
13
  * @import {NameHub} from '@agoric/vats';
13
14
  * @import {Zone} from '@agoric/zone';
14
15
  * @import {OrchestrationTools} from '../utils/start-helper.js';
16
+ * @import {CosmosChainInfo, Denom, DenomDetail} from '@agoric/orchestration';
15
17
  */
16
18
 
17
19
  /** @type {ContractMeta<typeof start>} */
@@ -23,6 +25,8 @@ export const meta = {
23
25
  storageNode: StorageNodeShape,
24
26
  marshaller: M.remotable('marshaller'),
25
27
  timerService: M.or(TimerServiceShape, null),
28
+ chainInfo: M.recordOf(M.string(), CosmosChainInfoShape),
29
+ assetInfo: M.arrayOf([M.string(), DenomDetailShape]),
26
30
  },
27
31
  upgradability: 'canUpgrade',
28
32
  };
@@ -49,6 +53,8 @@ harden(makeNatAmountShape);
49
53
  * storageNode: Remote<StorageNode>;
50
54
  * timerService: Remote<TimerService>;
51
55
  * marshaller: Marshaller;
56
+ * chainInfo: Record<string, CosmosChainInfo>;
57
+ * assetInfo: [Denom, DenomDetail & { brandKey?: string }][];
52
58
  * }} privateArgs
53
59
  * @param {Zone} zone
54
60
  * @param {OrchestrationTools} tools
@@ -1,6 +1,6 @@
1
1
  # Exo structure
2
2
 
3
- Last verified 2024-09-06
3
+ Last verified 2024-10-30
4
4
 
5
5
  ```mermaid
6
6
  classDiagram
@@ -52,9 +52,9 @@ classDiagram
52
52
 
53
53
  %% In other vats
54
54
  class Port {
55
- getLocalAddress()
56
55
  addListener()
57
56
  connect()
57
+ getLocalAddress()
58
58
  removeListener()
59
59
  revoke()
60
60
  }
@@ -76,9 +76,8 @@ classDiagram
76
76
  deposit()
77
77
  executeTx()
78
78
  getBalance()
79
- withdraw()
80
- executeTx()
81
79
  monitorTransfers()
80
+ withdraw()
82
81
  }
83
82
 
84
83
  %% In api consumer vats
@@ -113,12 +112,14 @@ classDiagram
113
112
  timer: Timer
114
113
  topicKit: RecorderKit<OrchestrationAccountNotification>
115
114
  asContinuingOffer()
115
+ deactivate()
116
116
  delegate()
117
117
  executeEncodedTx()
118
118
  getAddress()
119
119
  getBalance()
120
120
  getBalances()
121
121
  getPublicTopics()
122
+ reactivate()
122
123
  redelegate()
123
124
  send()
124
125
  sendAll()
@@ -1 +1 @@
1
- {"version":3,"file":"chain-hub-admin.d.ts","sourceRoot":"","sources":["chain-hub-admin.js"],"names":[],"mappings":"AAgCO,2CAHI,IAAI,YACJ,QAAQ;IAeb;;;;;;OAMG;6BAHQ,MAAM,aACN,eAAe,kBACf,iBAAiB;IAe5B;;;;;;;OAOG;yBAHQ,KAAK,UAEL,WAAW;GAU3B;4BAEa,UAAU,QAtDb,IAAI,YACJ,QAAQ;IAeb;;;;;;OAMG;6BAHQ,MAAM,aACN,eAAe,kBACf,iBAAiB;IAe5B;;;;;;;OAOG;yBAHQ,KAAK,UAEL,WAAW;GAYkB;0BA3EvB,cAAc;8BAEG,gBAAgB;qCADI,uBAAuB;uCAAvB,uBAAuB;2BAAvB,uBAAuB;iCAC3C,gBAAgB"}
1
+ {"version":3,"file":"chain-hub-admin.d.ts","sourceRoot":"","sources":["chain-hub-admin.js"],"names":[],"mappings":"AA+BO,2CAHI,IAAI,YACJ,QAAQ;IAeb;;;;;;OAMG;6BAHQ,MAAM,aACN,eAAe,kBACf,iBAAiB;IAe5B;;;;;;;OAOG;yBAHQ,KAAK,UAEL,WAAW;GAU3B;4BAEa,UAAU,QAtDb,IAAI,YACJ,QAAQ;IAeb;;;;;;OAMG;6BAHQ,MAAM,aACN,eAAe,kBACf,iBAAiB;IAe5B;;;;;;;OAOG;yBAHQ,KAAK,UAEL,WAAW;GAYkB;0BA3EvB,cAAc;8BAEG,gBAAgB;qCADI,uBAAuB;uCAAvB,uBAAuB;2BAAvB,uBAAuB;iCAC3C,gBAAgB"}
@@ -2,8 +2,7 @@
2
2
  /* eslint-disable no-restricted-syntax */
3
3
  import { heapVowE } from '@agoric/vow/vat.js';
4
4
  import { M } from '@endo/patterns';
5
- import { CosmosChainInfoShape } from '../typeGuards.js';
6
- import { DenomDetailShape } from './chain-hub.js';
5
+ import { CosmosChainInfoShape, DenomDetailShape } from '../typeGuards.js';
7
6
 
8
7
  /**
9
8
  * @import {Zone} from '@agoric/zone';
@@ -2,31 +2,13 @@
2
2
  * @import {NameHub} from '@agoric/vats';
3
3
  * @import {Vow, VowTools} from '@agoric/vow';
4
4
  * @import {Zone} from '@agoric/zone';
5
- * @import {CosmosAssetInfo, CosmosChainInfo, IBCConnectionInfo} from '../cosmos-api.js';
5
+ * @import {CosmosAssetInfo, CosmosChainInfo, ForwardInfo, IBCConnectionInfo, IBCMsgTransferOptions, TransferRoute, GoDuration} from '../cosmos-api.js';
6
6
  * @import {ChainInfo, KnownChains} from '../chain-info.js';
7
- * @import {Denom} from '../orchestration-api.js';
8
- * @import {Remote} from '@agoric/internal';
9
- * @import {TypedPattern} from '@agoric/internal';
7
+ * @import {ChainAddress, Denom, DenomAmount} from '../orchestration-api.js';
8
+ * @import {Remote, TypedPattern} from '@agoric/internal';
10
9
  */
11
- /**
12
- * If K matches a known chain, narrow the type from generic ChainInfo
13
- *
14
- * @template {string} K
15
- * @typedef {K extends keyof KnownChains
16
- * ? ChainInfo & Omit<KnownChains[K], 'connections'>
17
- * : ChainInfo} ActualChainInfo
18
- * @internal
19
- */
20
- /**
21
- * @typedef {object} DenomDetail
22
- * @property {string} baseName - name of issuing chain; e.g. cosmoshub
23
- * @property {Denom} baseDenom - e.g. uatom
24
- * @property {string} chainName - name of holding chain; e.g. agoric
25
- * @property {Brand<'nat'>} [brand] - vbank brand, if registered
26
- * @see {ChainHub} `registerAsset` method
27
- */
28
- /** @type {TypedPattern<DenomDetail>} */
29
- export const DenomDetailShape: TypedPattern<DenomDetail>;
10
+ /** receiver address value for ibc transfers that involve PFM */
11
+ export const PFM_RECEIVER: "pfm";
30
12
  export type HubName = (typeof HubName)[keyof typeof HubName];
31
13
  export namespace HubName {
32
14
  let Chain: "chain";
@@ -41,6 +23,8 @@ export const CONNECTIONS_KEY: "chainConnection";
41
23
  export const ASSETS_KEY: "chainAssets";
42
24
  export function connectionKey(chainId1: string, chainId2: string): string;
43
25
  export function normalizeConnectionInfo(primaryChainId: string, counterChainId: string, directed: IBCConnectionInfo): [string, IBCConnectionInfo];
26
+ /** @type {TypedPattern<TransferRoute>} */
27
+ export const TransferRouteShape: TypedPattern<TransferRoute>;
44
28
  export function makeChainHub(zone: Zone, agoricNames: Remote<NameHub>, vowTools: VowTools): import("@endo/exo").Guarded<{
45
29
  /**
46
30
  * Register a new chain. The name will override a name in well known chain
@@ -100,9 +84,10 @@ export function makeChainHub(zone: Zone, agoricNames: Remote<NameHub>, vowTools:
100
84
  * Retrieve holding, issuing chain names etc. for a denom.
101
85
  *
102
86
  * @param {Denom} denom
87
+ * @param {string} srcChainName - the chainName the denom is held on
103
88
  * @returns {DenomDetail | undefined}
104
89
  */
105
- getAsset(denom: Denom): DenomDetail | undefined;
90
+ getAsset(denom: Denom, srcChainName: string): DenomDetail | undefined;
106
91
  /**
107
92
  * Retrieve denom (string) for a Brand.
108
93
  *
@@ -110,6 +95,29 @@ export function makeChainHub(zone: Zone, agoricNames: Remote<NameHub>, vowTools:
110
95
  * @returns {Denom | undefined}
111
96
  */
112
97
  getDenom(brand: Brand): Denom | undefined;
98
+ /**
99
+ * @param {string} address bech32 address
100
+ * @returns {ChainAddress}
101
+ * @throws {Error} if chain info not found for bech32Prefix
102
+ */
103
+ makeChainAddress(address: string): ChainAddress;
104
+ /**
105
+ * Determine the transfer route for a destination and amount given the
106
+ * current holding chain.
107
+ *
108
+ * Does not account for routes with more than 1 intermediary hop - that is,
109
+ * it can't unwrap denoms that were incorrectly routed.
110
+ *
111
+ * XXX consider accepting AmountArg #10449
112
+ *
113
+ * @param {ChainAddress} destination
114
+ * @param {DenomAmount} denomAmount
115
+ * @param {string} srcChainName
116
+ * @param {IBCMsgTransferOptions['forwardOpts']} [forwardOpts]
117
+ * @returns {TransferRoute} single hop, multi hop
118
+ * @throws {Error} if unable to determine route
119
+ */
120
+ makeTransferRoute(destination: ChainAddress, denomAmount: DenomAmount, srcChainName: string, forwardOpts?: IBCMsgTransferOptions["forwardOpts"]): TransferRoute;
113
121
  }>;
114
122
  export function registerAssets(chainHub: ChainHub, name: string, assets: CosmosAssetInfo[]): void;
115
123
  /**
@@ -135,8 +143,9 @@ export type DenomDetail = {
135
143
  brand?: globalThis.Brand<"nat"> | undefined;
136
144
  };
137
145
  export type ChainHub = ReturnType<typeof makeChainHub>;
138
- import type { TypedPattern } from '@agoric/internal';
139
146
  import type { IBCConnectionInfo } from '../cosmos-api.js';
147
+ import type { TransferRoute } from '../cosmos-api.js';
148
+ import type { TypedPattern } from '@agoric/internal';
140
149
  import type { Zone } from '@agoric/zone';
141
150
  import type { NameHub } from '@agoric/vats';
142
151
  import type { Remote } from '@agoric/internal';
@@ -144,6 +153,9 @@ import type { VowTools } from '@agoric/vow';
144
153
  import type { CosmosChainInfo } from '../cosmos-api.js';
145
154
  import type { Vow } from '@agoric/vow';
146
155
  import type { Denom } from '../orchestration-api.js';
156
+ import type { ChainAddress } from '../orchestration-api.js';
157
+ import type { DenomAmount } from '../orchestration-api.js';
158
+ import type { IBCMsgTransferOptions } from '../cosmos-api.js';
147
159
  import type { CosmosAssetInfo } from '../cosmos-api.js';
148
160
  import type { KnownChains } from '../chain-info.js';
149
161
  import type { ChainInfo } from '../chain-info.js';
@@ -1 +1 @@
1
- {"version":3,"file":"chain-hub.d.ts","sourceRoot":"","sources":["chain-hub.js"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AAEH;;;;;;;;GAQG;AAEH;;;;;;;GAOG;AACH,wCAAwC;AACxC,+BADW,aAAa,WAAW,CAAC,CAIlC;sBAGQ,CAAC,OAAO,OAAO,EAAE,MAAM,OAAO,OAAO,CAAC;;;;;;AAYhD,oCAAoC;AACpC,gCAAuC;AACvC,8CAA8C;AAC9C,gDAAuD;AACvD,0CAA0C;AAC1C,uCAA8C;AAqBvC,wCAHI,MAAM,YACN,MAAM,UAUhB;AAoCM,wDALI,MAAM,kBACN,MAAM,YACN,iBAAiB,GACf,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAavC;AA2DM,mCAJI,IAAI,eACJ,OAAO,OAAO,CAAC,YACf,QAAQ;IA8Gf;;;;;;;;;;;OAWG;wBAFQ,MAAM,aACN,eAAe;IAK1B;;;;OAIG;iBAHmB,CAAC,SAAV,MAAQ,aACV,CAAC,GACC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;IAYpC;;;;OAIG;uCAHQ,MAAM,uBACN,MAAM,kBACN,iBAAiB;IAW5B;;;;OAIG;+BAHQ,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,WAC5B,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAC1B,IAAI,iBAAiB,CAAC;IAmBnC;;;;;;;;OAQG;2BAPmB,EAAE,SAAX,MAAQ,EACC,EAAE,SAAX,MAAQ,eACV,EAAE,eACF,EAAE,GACA,IACZ,CAAK,eAAe,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAC9D;IAOJ;;;;;;;OAOG;yBAHQ,KAAK,UAEL,WAAW;IAatB;;;;;OAKG;oBAFQ,KAAK,GACH,WAAW,GAAG,SAAS;IAQpC;;;;;OAKG;oBAFQ,KAAK,GACH,KAAK,GAAG,SAAS;GAWjC;AAUM,yCAJI,QAAQ,QACR,MAAM,UACN,eAAe,EAAE,QAe3B;;;;4BA/aqB,CAAC,SAAV,MAAQ,IACR,CAAC,SAAS,MAAM,WAAW,GACjC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,GAC/C,SAAS;;;;;cAMF,MAAM;;;;eACN,KAAK;;;;eACL,MAAM;;;;;;uBA8YN,UAAU,CAAC,OAAO,YAAY,CAAC;kCA/Zd,kBAAkB;uCAJqB,kBAAkB;0BADjE,cAAc;6BAFX,cAAc;4BAMf,kBAAkB;8BALX,aAAa;qCAEyB,kBAAkB;yBAFxD,aAAa;2BAIrB,yBAAyB;qCAFqB,kBAAkB;iCAC/C,kBAAkB;+BAAlB,kBAAkB"}
1
+ {"version":3,"file":"chain-hub.d.ts","sourceRoot":"","sources":["chain-hub.js"],"names":[],"mappings":"AAmBA;;;;;;;;GAQG;AAEH,gEAAgE;AAChE,2BAAkD,KAAK,CAAE;sBAsB/C,CAAC,OAAO,OAAO,EAAE,MAAM,OAAO,OAAO,CAAC;;;;;;AAYhD,oCAAoC;AACpC,gCAAuC;AACvC,8CAA8C;AAC9C,gDAAuD;AACvD,0CAA0C;AAC1C,uCAA8C;AAqBvC,wCAHI,MAAM,YACN,MAAM,UAUhB;AAoCM,wDALI,MAAM,kBACN,MAAM,YACN,iBAAiB,GACf,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAavC;AAwCD,0CAA0C;AAC1C,iCADW,aAAa,aAAa,CAAC,CAUpC;AAmCK,mCAJI,IAAI,eACJ,OAAO,OAAO,CAAC,YACf,QAAQ;IA2Hf;;;;;;;;;;;OAWG;wBAFQ,MAAM,aACN,eAAe;IAQ1B;;;;OAIG;iBAHmB,CAAC,SAAV,MAAQ,aACV,CAAC,GACC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;IAYpC;;;;OAIG;uCAHQ,MAAM,uBACN,MAAM,kBACN,iBAAiB;IAW5B;;;;OAIG;+BAHQ,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,WAC5B,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAC1B,IAAI,iBAAiB,CAAC;IAmBnC;;;;;;;;OAQG;2BAPmB,EAAE,SAAX,MAAQ,EACC,EAAE,SAAX,MAAQ,eACV,EAAE,eACF,EAAE,GACA,IACZ,CAAK,eAAe,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAC9D;IAOJ;;;;;;;OAOG;yBAHQ,KAAK,UAEL,WAAW;IAmBtB;;;;;;OAMG;oBAHQ,KAAK,gBACL,MAAM,GACJ,WAAW,GAAG,SAAS;IASpC;;;;;OAKG;oBAFQ,KAAK,GACH,KAAK,GAAG,SAAS;IAQ9B;;;;OAIG;8BAHQ,MAAM,GACJ,YAAY;IAgBzB;;;;;;;;;;;;;;;OAeG;mCANQ,YAAY,eACZ,WAAW,gBACX,MAAM,gBACN,qBAAqB,CAAC,aAAa,CAAC,GAClC,aAAa;GAmG7B;AAUM,yCAJI,QAAQ,QACR,MAAM,UACN,eAAe,EAAE,QAe3B;;;;4BA3lBqB,CAAC,SAAV,MAAQ,IACR,CAAC,SAAS,MAAM,WAAW,GACjC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,GAC/C,SAAS;;;;;cAMF,MAAM;;;;eACN,KAAK;;;;eACL,MAAM;;;;;;uBA0jBN,UAAU,CAAC,OAAO,YAAY,CAAC;uCAjlBwF,kBAAkB;mCAAlB,kBAAkB;kCAGhH,kBAAkB;0BAJlC,cAAc;6BAFX,cAAc;4BAMD,kBAAkB;8BALzB,aAAa;qCAEwF,kBAAkB;yBAFvH,aAAa;2BAIM,yBAAyB;kCAAzB,yBAAyB;iCAAzB,yBAAyB;2CAFyD,kBAAkB;qCAAlB,kBAAkB;iCAC9G,kBAAkB;+BAAlB,kBAAkB"}
@@ -4,19 +4,32 @@ import { M } from '@endo/patterns';
4
4
  import { BrandShape } from '@agoric/ertp/src/typeGuards.js';
5
5
 
6
6
  import { VowShape } from '@agoric/vow';
7
- import { CosmosChainInfoShape, IBCConnectionInfoShape } from '../typeGuards.js';
7
+ import {
8
+ ChainAddressShape,
9
+ CoinShape,
10
+ CosmosChainInfoShape,
11
+ DenomAmountShape,
12
+ DenomDetailShape,
13
+ ForwardInfoShape,
14
+ ForwardOptsShape,
15
+ IBCChannelIDShape,
16
+ IBCConnectionInfoShape,
17
+ } from '../typeGuards.js';
18
+ import { getBech32Prefix } from '../utils/address.js';
8
19
 
9
20
  /**
10
21
  * @import {NameHub} from '@agoric/vats';
11
22
  * @import {Vow, VowTools} from '@agoric/vow';
12
23
  * @import {Zone} from '@agoric/zone';
13
- * @import {CosmosAssetInfo, CosmosChainInfo, IBCConnectionInfo} from '../cosmos-api.js';
24
+ * @import {CosmosAssetInfo, CosmosChainInfo, ForwardInfo, IBCConnectionInfo, IBCMsgTransferOptions, TransferRoute, GoDuration} from '../cosmos-api.js';
14
25
  * @import {ChainInfo, KnownChains} from '../chain-info.js';
15
- * @import {Denom} from '../orchestration-api.js';
16
- * @import {Remote} from '@agoric/internal';
17
- * @import {TypedPattern} from '@agoric/internal';
26
+ * @import {ChainAddress, Denom, DenomAmount} from '../orchestration-api.js';
27
+ * @import {Remote, TypedPattern} from '@agoric/internal';
18
28
  */
19
29
 
30
+ /** receiver address value for ibc transfers that involve PFM */
31
+ export const PFM_RECEIVER = /** @type {const} */ ('pfm');
32
+
20
33
  /**
21
34
  * If K matches a known chain, narrow the type from generic ChainInfo
22
35
  *
@@ -35,11 +48,6 @@ import { CosmosChainInfoShape, IBCConnectionInfoShape } from '../typeGuards.js';
35
48
  * @property {Brand<'nat'>} [brand] - vbank brand, if registered
36
49
  * @see {ChainHub} `registerAsset` method
37
50
  */
38
- /** @type {TypedPattern<DenomDetail>} */
39
- export const DenomDetailShape = M.splitRecord(
40
- { chainName: M.string(), baseName: M.string(), baseDenom: M.string() },
41
- { brand: BrandShape },
42
- );
43
51
 
44
52
  /**
45
53
  * @enum {(typeof HubName)[keyof typeof HubName]}
@@ -98,7 +106,7 @@ export const connectionKey = (chainId1, chainId2) => {
98
106
  */
99
107
  const reverseConnInfo = connInfo => {
100
108
  const { transferChannel } = connInfo;
101
- return {
109
+ return harden({
102
110
  id: connInfo.counterparty.connection_id,
103
111
  client_id: connInfo.counterparty.client_id,
104
112
  counterparty: {
@@ -113,7 +121,7 @@ const reverseConnInfo = connInfo => {
113
121
  portId: transferChannel.counterPartyPortId,
114
122
  counterPartyPortId: transferChannel.portId,
115
123
  },
116
- };
124
+ });
117
125
  };
118
126
 
119
127
  /**
@@ -167,6 +175,26 @@ const ChainIdArgShape = M.or(
167
175
  ),
168
176
  );
169
177
 
178
+ // TODO #9324 determine timeout defaults
179
+ const DefaultPfmTimeoutOpts = harden(
180
+ /** @type {const} */ ({
181
+ retries: 3,
182
+ timeout: /** @type {const} */ ('10m'),
183
+ }),
184
+ );
185
+
186
+ /** @type {TypedPattern<TransferRoute>} */
187
+ export const TransferRouteShape = M.splitRecord(
188
+ {
189
+ sourcePort: M.string(),
190
+ sourceChannel: IBCChannelIDShape,
191
+ token: CoinShape,
192
+ receiver: M.string(),
193
+ },
194
+ { forwardInfo: ForwardInfoShape },
195
+ {},
196
+ );
197
+
170
198
  const ChainHubI = M.interface('ChainHub', {
171
199
  registerChain: M.call(M.string(), CosmosChainInfoShape).returns(),
172
200
  getChainInfo: M.call(M.string()).returns(VowShape),
@@ -178,8 +206,14 @@ const ChainHubI = M.interface('ChainHub', {
178
206
  getConnectionInfo: M.call(ChainIdArgShape, ChainIdArgShape).returns(VowShape),
179
207
  getChainsAndConnection: M.call(M.string(), M.string()).returns(VowShape),
180
208
  registerAsset: M.call(M.string(), DenomDetailShape).returns(),
181
- getAsset: M.call(M.string()).returns(M.or(DenomDetailShape, M.undefined())),
209
+ getAsset: M.call(M.string(), M.string()).returns(
210
+ M.or(DenomDetailShape, M.undefined()),
211
+ ),
182
212
  getDenom: M.call(BrandShape).returns(M.or(M.string(), M.undefined())),
213
+ makeChainAddress: M.call(M.string()).returns(ChainAddressShape),
214
+ makeTransferRoute: M.call(ChainAddressShape, DenomAmountShape, M.string())
215
+ .optional(ForwardOptsShape)
216
+ .returns(M.or(M.undefined(), TransferRouteShape)),
183
217
  });
184
218
 
185
219
  /**
@@ -216,6 +250,17 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
216
250
  keyShape: BrandShape,
217
251
  valueShape: M.string(),
218
252
  });
253
+ /** @type {MapStore<string, string>} */
254
+ const bech32PrefixToChainName = zone.mapStore('bech32PrefixToChainName', {
255
+ keyShape: M.string(),
256
+ valueShape: M.string(),
257
+ });
258
+
259
+ /**
260
+ * @param {Denom} denom - from perspective of the src/holding chain
261
+ * @param {DenomDetail['chainName']} srcChainName
262
+ */
263
+ const makeDenomKey = (denom, srcChainName) => `${srcChainName}:${denom}`;
219
264
 
220
265
  const lookupChainInfo = vowTools.retryable(
221
266
  zone,
@@ -230,6 +275,9 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
230
275
  // TODO consider makeAtomicProvider for vows
231
276
  if (!chainInfos.has(chainName)) {
232
277
  chainInfos.init(chainName, chainInfo);
278
+ if (chainInfo.bech32Prefix) {
279
+ bech32PrefixToChainName.init(chainInfo.bech32Prefix, chainName);
280
+ }
233
281
  }
234
282
  return chainInfo;
235
283
  } catch (e) {
@@ -269,7 +317,6 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
269
317
  },
270
318
  );
271
319
 
272
- /* eslint-disable no-use-before-define -- chainHub defined below */
273
320
  const lookupChainsAndConnection = vowTools.retryable(
274
321
  zone,
275
322
  'lookupChainsAndConnection',
@@ -316,6 +363,9 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
316
363
  */
317
364
  registerChain(name, chainInfo) {
318
365
  chainInfos.init(name, chainInfo);
366
+ if (chainInfo.bech32Prefix) {
367
+ bech32PrefixToChainName.init(chainInfo.bech32Prefix, name);
368
+ }
319
369
  },
320
370
  /**
321
371
  * @template {string} K
@@ -396,8 +446,14 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
396
446
  Fail`must register chain ${q(chainName)} first`;
397
447
  chainInfos.has(baseName) ||
398
448
  Fail`must register chain ${q(baseName)} first`;
399
- denomDetails.init(denom, detail);
449
+
450
+ const denomKey = makeDenomKey(denom, detail.chainName);
451
+ denomDetails.has(denomKey) &&
452
+ Fail`already registered ${q(denom)} on ${q(chainName)}`;
453
+ denomDetails.init(denomKey, detail);
400
454
  if (detail.brand) {
455
+ chainName === 'agoric' ||
456
+ Fail`brands only registerable for agoric-held assets`;
401
457
  brandDenoms.init(detail.brand, denom);
402
458
  }
403
459
  },
@@ -405,11 +461,13 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
405
461
  * Retrieve holding, issuing chain names etc. for a denom.
406
462
  *
407
463
  * @param {Denom} denom
464
+ * @param {string} srcChainName - the chainName the denom is held on
408
465
  * @returns {DenomDetail | undefined}
409
466
  */
410
- getAsset(denom) {
411
- if (denomDetails.has(denom)) {
412
- return denomDetails.get(denom);
467
+ getAsset(denom, srcChainName) {
468
+ const denomKey = makeDenomKey(denom, srcChainName);
469
+ if (denomDetails.has(denomKey)) {
470
+ return denomDetails.get(denomKey);
413
471
  }
414
472
  return undefined;
415
473
  },
@@ -425,6 +483,133 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
425
483
  }
426
484
  return undefined;
427
485
  },
486
+ /**
487
+ * @param {string} address bech32 address
488
+ * @returns {ChainAddress}
489
+ * @throws {Error} if chain info not found for bech32Prefix
490
+ */
491
+ makeChainAddress(address) {
492
+ const prefix = getBech32Prefix(address);
493
+ if (!bech32PrefixToChainName.has(prefix)) {
494
+ throw makeError(`Chain info not found for bech32Prefix ${q(prefix)}`);
495
+ }
496
+ const chainName = bech32PrefixToChainName.get(prefix);
497
+ const { chainId } = chainInfos.get(chainName);
498
+ return harden({
499
+ chainId,
500
+ value: address,
501
+ encoding: /** @type {const} */ ('bech32'),
502
+ });
503
+ },
504
+ /**
505
+ * Determine the transfer route for a destination and amount given the
506
+ * current holding chain.
507
+ *
508
+ * Does not account for routes with more than 1 intermediary hop - that is,
509
+ * it can't unwrap denoms that were incorrectly routed.
510
+ *
511
+ * XXX consider accepting AmountArg #10449
512
+ *
513
+ * @param {ChainAddress} destination
514
+ * @param {DenomAmount} denomAmount
515
+ * @param {string} srcChainName
516
+ * @param {IBCMsgTransferOptions['forwardOpts']} [forwardOpts]
517
+ * @returns {TransferRoute} single hop, multi hop
518
+ * @throws {Error} if unable to determine route
519
+ */
520
+ makeTransferRoute(destination, denomAmount, srcChainName, forwardOpts) {
521
+ chainInfos.has(srcChainName) ||
522
+ Fail`chain info not found for holding chain: ${q(srcChainName)}`;
523
+
524
+ const denomDetail = chainHub.getAsset(denomAmount.denom, srcChainName);
525
+ denomDetail ||
526
+ Fail`no denom detail for: ${q(denomAmount.denom)} on ${q(srcChainName)}. ensure it is registered in chainHub.`;
527
+
528
+ const { baseName, chainName } = /** @type {DenomDetail} */ (denomDetail);
529
+
530
+ // currently unreachable since assets are registered with holdingChainName
531
+ chainName === srcChainName ||
532
+ Fail`cannot transfer asset ${q(denomAmount.denom)}. held on ${q(chainName)} not ${q(srcChainName)}.`;
533
+
534
+ // currently unreachable since we can't register an asset before a chain
535
+ chainInfos.has(baseName) ||
536
+ Fail`chain info not found for issuing chain: ${q(baseName)}`;
537
+
538
+ const { chainId: baseChainId, pfmEnabled } = chainInfos.get(baseName);
539
+
540
+ const holdingChainId = chainInfos.get(srcChainName).chainId;
541
+
542
+ // asset is transferring to or from the issuing chain, return direct route
543
+ if (baseChainId === destination.chainId || baseName === srcChainName) {
544
+ // TODO use getConnectionInfo once its sync
545
+ const connKey = connectionKey(holdingChainId, destination.chainId);
546
+ connectionInfos.has(connKey) ||
547
+ Fail`no connection info found for ${holdingChainId}<->${destination.chainId}`;
548
+
549
+ const { transferChannel } = denormalizeConnectionInfo(
550
+ holdingChainId, // from chain (primary)
551
+ destination.chainId, // to chain (counterparty)
552
+ connectionInfos.get(connKey),
553
+ );
554
+ return harden({
555
+ sourcePort: transferChannel.portId,
556
+ sourceChannel: transferChannel.channelId,
557
+ token: {
558
+ amount: String(denomAmount.value),
559
+ denom: denomAmount.denom,
560
+ },
561
+ receiver: destination.value,
562
+ });
563
+ }
564
+
565
+ // asset is issued on a 3rd chain, attempt pfm route
566
+ pfmEnabled || Fail`pfm not enabled on issuing chain: ${q(baseName)}`;
567
+
568
+ // TODO use getConnectionInfo once its sync
569
+ const currToIssuerKey = connectionKey(holdingChainId, baseChainId);
570
+ connectionInfos.has(currToIssuerKey) ||
571
+ Fail`no connection info found for ${holdingChainId}<->${baseChainId}`;
572
+
573
+ const issuerToDestKey = connectionKey(baseChainId, destination.chainId);
574
+ connectionInfos.has(issuerToDestKey) ||
575
+ Fail`no connection info found for ${baseChainId}<->${destination.chainId}`;
576
+
577
+ const currToIssuer = denormalizeConnectionInfo(
578
+ holdingChainId,
579
+ baseChainId,
580
+ connectionInfos.get(currToIssuerKey),
581
+ );
582
+ const issuerToDest = denormalizeConnectionInfo(
583
+ baseChainId,
584
+ destination.chainId,
585
+ connectionInfos.get(issuerToDestKey),
586
+ );
587
+
588
+ /** @type {ForwardInfo} */
589
+ const forwardInfo = harden({
590
+ forward: {
591
+ receiver: destination.value,
592
+ port: issuerToDest.transferChannel.portId,
593
+ channel: issuerToDest.transferChannel.channelId,
594
+ ...DefaultPfmTimeoutOpts,
595
+ ...forwardOpts,
596
+ },
597
+ });
598
+ return harden({
599
+ sourcePort: currToIssuer.transferChannel.portId,
600
+ sourceChannel: currToIssuer.transferChannel.channelId,
601
+ token: {
602
+ amount: String(denomAmount.value),
603
+ denom: denomAmount.denom,
604
+ },
605
+ /**
606
+ * purposely using invalid bech32
607
+ * {@link https://github.com/cosmos/ibc-apps/blob/26f3ad8f58e4ffc7769c6766cb42b954181dc100/middleware/packet-forward-middleware/README.md#minimal-example---chain-forward-a-b-c}
608
+ */
609
+ receiver: forwardOpts?.intermediateRecipient?.value || PFM_RECEIVER,
610
+ forwardInfo,
611
+ });
612
+ },
428
613
  });
429
614
 
430
615
  return chainHub;