@agoric/orchestration 0.1.1-dev-df81dca.0 → 0.1.1-dev-be74a2b.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/orchestration",
3
- "version": "0.1.1-dev-df81dca.0+df81dca",
3
+ "version": "0.1.1-dev-be74a2b.0+be74a2b",
4
4
  "description": "Chain abstraction for Agoric's orchestration clients",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -100,5 +100,5 @@
100
100
  "typeCoverage": {
101
101
  "atLeast": 97.7
102
102
  },
103
- "gitHead": "df81dcaf96c8e7f3e8aeb74f63e8bca9cd31d007"
103
+ "gitHead": "be74a2bc3be6c03203f4fe76e9e287f49271ef76"
104
104
  }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @import {Remote, Vow} from '@agoric/vow';
3
+ * @import {Zone} from '@agoric/zone';
4
+ * @import {OrchestrationPowers, OrchestrationTools} from '../utils/start-helper.js';
5
+ * @import {CosmosChainInfo, Denom, DenomDetail, OrchestrationAccount} from '@agoric/orchestration';
6
+ */
7
+ export const SingleNatAmountRecord: import("@endo/patterns").Matcher;
8
+ export function contract(zcf: ZCF, privateArgs: OrchestrationPowers & {
9
+ assetInfo?: [Denom, DenomDetail & {
10
+ brandKey?: string;
11
+ }][];
12
+ chainInfo?: Record<string, CosmosChainInfo>;
13
+ marshaller: Marshaller;
14
+ storageNode: Remote<StorageNode>;
15
+ }, zone: Zone, { chainHub, orchestrate, vowTools, zoeTools }: OrchestrationTools): Promise<{
16
+ publicFacet: import("@endo/exo").Guarded<{
17
+ makeSwapInvitation(): Promise<globalThis.Invitation<Vow<string>, import("./swap-anything.flows.js").SwapInfo>>;
18
+ }>;
19
+ creatorFacet: import("@endo/exo").Guarded<{
20
+ registerChain(chainName: string, chainInfo: import("@agoric/orchestration").ChainInfo, ibcConnectionInfo?: import("@agoric/orchestration").IBCConnectionInfo): Promise<void>;
21
+ registerAsset(denom: Denom, detail: DenomDetail): Promise<void>;
22
+ }>;
23
+ }>;
24
+ export const start: (zcf: globalThis.ZCF<Record<string, unknown>>, privateArgs: OrchestrationPowers & {
25
+ assetInfo?: [Denom, DenomDetail & {
26
+ brandKey?: string;
27
+ }][];
28
+ chainInfo?: Record<string, CosmosChainInfo>;
29
+ marshaller: Marshaller;
30
+ storageNode: Remote<StorageNode>;
31
+ }, baggage: Baggage) => Promise<{
32
+ publicFacet: import("@endo/exo").Guarded<{
33
+ makeSwapInvitation(): Promise<globalThis.Invitation<Vow<string>, import("./swap-anything.flows.js").SwapInfo>>;
34
+ }>;
35
+ creatorFacet: import("@endo/exo").Guarded<{
36
+ registerChain(chainName: string, chainInfo: import("@agoric/orchestration").ChainInfo, ibcConnectionInfo?: import("@agoric/orchestration").IBCConnectionInfo): Promise<void>;
37
+ registerAsset(denom: Denom, detail: DenomDetail): Promise<void>;
38
+ }>;
39
+ }>;
40
+ import type { OrchestrationPowers } from '../utils/start-helper.js';
41
+ import type { Denom } from '@agoric/orchestration';
42
+ import type { DenomDetail } from '@agoric/orchestration';
43
+ import type { CosmosChainInfo } from '@agoric/orchestration';
44
+ import type { Remote } from '@agoric/vow';
45
+ import type { Zone } from '@agoric/zone';
46
+ import type { OrchestrationTools } from '../utils/start-helper.js';
47
+ import type { Vow } from '@agoric/vow';
48
+ //# sourceMappingURL=swap-anything.contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swap-anything.contract.d.ts","sourceRoot":"","sources":["swap-anything.contract.js"],"names":[],"mappings":"AAcA;;;;;GAKG;AAEH,qEAGE;AAmBK,8BAVI,GAAG,eACH,mBAAmB,GAAG;IAC5B,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC5C,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,OAAO,WAAW,CAAC,CAAC;CAClC,QACO,IAAI,iDACJ,kBAAkB;;;;;;;;GA6I5B;AAGD;gBAtJiB,CAAC,KAAK,EAAE,WAAW,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE;gBAC9C,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;gBAC/B,UAAU;iBACT,OAAO,WAAW,CAAC;;;;;;;;;GAmJ0C;yCAxKrB,0BAA0B;2BACR,uBAAuB;iCAAvB,uBAAuB;qCAAvB,uBAAuB;4BAHrE,aAAa;0BACpB,cAAc;wCACqB,0BAA0B;yBAFtD,aAAa"}
@@ -0,0 +1,187 @@
1
+ import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
2
+ import { makeTracer } from '@agoric/internal';
3
+ import { E } from '@endo/far';
4
+ import { M } from '@endo/patterns';
5
+ import { decodeAddressHook } from '@agoric/cosmic-proto/address-hooks.js';
6
+ import { prepareChainHubAdmin } from '../exos/chain-hub-admin.js';
7
+ import { withOrchestration } from '../utils/start-helper.js';
8
+ import * as sharedFlows from './shared.flows.js';
9
+ import { swapAnythingViaHook, swapIt } from './swap-anything.flows.js';
10
+ import { AnyNatAmountShape } from '../typeGuards.js';
11
+ import { registerChainsAndAssets } from '../utils/chain-hub-helper.js';
12
+
13
+ const trace = makeTracer('SwapAnything.Contract');
14
+ const interfaceTODO = undefined;
15
+ /**
16
+ * @import {Remote, Vow} from '@agoric/vow';
17
+ * @import {Zone} from '@agoric/zone';
18
+ * @import {OrchestrationPowers, OrchestrationTools} from '../utils/start-helper.js';
19
+ * @import {CosmosChainInfo, Denom, DenomDetail, OrchestrationAccount} from '@agoric/orchestration';
20
+ */
21
+
22
+ export const SingleNatAmountRecord = M.and(
23
+ M.recordOf(M.string(), AnyNatAmountShape, { numPropertiesLimit: 1 }),
24
+ M.not(harden({})),
25
+ );
26
+ harden(SingleNatAmountRecord);
27
+
28
+ /**
29
+ * Swap assets that are currently in an ERTP purse against another cosmos asset
30
+ * by using an Osmosis pool then have the swap output routed to any address
31
+ *
32
+ * Orchestration contract to be wrapped by withOrchestration for Zoe
33
+ *
34
+ * @param {ZCF} zcf
35
+ * @param {OrchestrationPowers & {
36
+ * assetInfo?: [Denom, DenomDetail & { brandKey?: string }][];
37
+ * chainInfo?: Record<string, CosmosChainInfo>;
38
+ * marshaller: Marshaller;
39
+ * storageNode: Remote<StorageNode>;
40
+ * }} privateArgs
41
+ * @param {Zone} zone
42
+ * @param {OrchestrationTools} tools
43
+ */
44
+ export const contract = async (
45
+ zcf,
46
+ privateArgs,
47
+ zone,
48
+ { chainHub, orchestrate, vowTools, zoeTools },
49
+ ) => {
50
+ const creatorFacet = prepareChainHubAdmin(zone, chainHub);
51
+
52
+ /**
53
+ * @type {OrchestrationAccount<{ chainId: 'agoric' }>} ;
54
+ */
55
+ let sharedLocalAccount;
56
+
57
+ // UNTIL https://github.com/Agoric/agoric-sdk/issues/9066
58
+ const logNode = E(privateArgs.storageNode).makeChildNode('log');
59
+ /** @type {(msg: string) => Vow<void>} */
60
+ const log = (msg, level = 'info') =>
61
+ vowTools.watch(E(logNode).setValue(JSON.stringify({ msg, level })));
62
+
63
+ const makeLocalAccount = orchestrate(
64
+ 'makeLocalAccount',
65
+ {},
66
+ sharedFlows.makeLocalAccount,
67
+ );
68
+
69
+ registerChainsAndAssets(
70
+ chainHub,
71
+ zcf.getTerms().brands,
72
+ privateArgs.chainInfo,
73
+ privateArgs.assetInfo,
74
+ );
75
+
76
+ /**
77
+ * @type {any} sharedLocalAccountP expects a Promise but this is a vow UNTIL
78
+ * https://github.com/Agoric/agoric-sdk/issues/9822
79
+ */
80
+ const sharedLocalAccountP = zone.makeOnce('localAccount', () =>
81
+ makeLocalAccount(),
82
+ );
83
+
84
+ const swapAnythingOffer = orchestrate(
85
+ 'swapAnything',
86
+ { chainHub, sharedLocalAccountP, log, zoeTools },
87
+ swapIt,
88
+ );
89
+
90
+ const swapAnythingAddressHook = orchestrate(
91
+ 'swapAnythingViaHook',
92
+ {
93
+ chainHub,
94
+ sharedLocalAccountP,
95
+ log,
96
+ },
97
+ swapAnythingViaHook,
98
+ );
99
+
100
+ const tap = zone.makeOnce('tapPosition', _key => {
101
+ console.log('making tap');
102
+ return zone.exo('tap', interfaceTODO, {
103
+ /**
104
+ * @param {import('@agoric/vats').VTransferIBCEvent} event
105
+ */
106
+ async receiveUpcall(event) {
107
+ await null;
108
+ trace('receiveUpcall', event);
109
+
110
+ if (event.event !== 'writeAcknowledgement') return;
111
+ trace('Moving on...');
112
+
113
+ const {
114
+ amount,
115
+ extra: { receiver: origReceiver },
116
+ } = await vowTools.when(
117
+ E(sharedLocalAccount).parseInboundTransfer(event.packet),
118
+ );
119
+
120
+ const { baseAddress, query } = decodeAddressHook(origReceiver);
121
+
122
+ /**
123
+ * @type {{
124
+ * destAddr: string;
125
+ * receiverAddr: string;
126
+ * outDenom: string;
127
+ * }}
128
+ */
129
+ // @ts-expect-error
130
+ const { destAddr, receiverAddr, outDenom } = query;
131
+
132
+ trace({
133
+ baseAddress,
134
+ destAddr,
135
+ receiverAddr,
136
+ outDenom,
137
+ });
138
+
139
+ if (!receiverAddr || !destAddr || !outDenom) return;
140
+ // Invoke the flow to perform swap and end up at the final destination.
141
+ return swapAnythingAddressHook(amount, {
142
+ destAddr,
143
+ receiverAddr,
144
+ outDenom, // swapOutDenom
145
+ onFailedDelivery: 'do_nothing',
146
+ slippage: {
147
+ slippagePercentage: '20',
148
+ windowSeconds: 10,
149
+ },
150
+ });
151
+ },
152
+ });
153
+ });
154
+
155
+ void vowTools.when(sharedLocalAccountP, async lca => {
156
+ sharedLocalAccount = lca;
157
+ await sharedLocalAccount.monitorTransfers(tap);
158
+ const encoded = await E(privateArgs.marshaller).toCapData({
159
+ sharedLocalAccount: sharedLocalAccount.getAddress(),
160
+ });
161
+ void E(privateArgs.storageNode).setValue(JSON.stringify(encoded));
162
+ trace('Localchain account information published', encoded);
163
+ });
164
+
165
+ const publicFacet = zone.exo(
166
+ 'Swap Anything PF',
167
+ M.interface('Swap Anything PF', {
168
+ makeSwapInvitation: M.callWhen().returns(InvitationShape),
169
+ }),
170
+ {
171
+ makeSwapInvitation() {
172
+ return zcf.makeInvitation(
173
+ swapAnythingOffer,
174
+ 'swap',
175
+ undefined,
176
+ M.splitRecord({ give: SingleNatAmountRecord }),
177
+ );
178
+ },
179
+ },
180
+ );
181
+
182
+ return { publicFacet, creatorFacet };
183
+ };
184
+ harden(contract);
185
+
186
+ export const start = withOrchestration(contract, { publishAccountInfo: true });
187
+ harden(start);
@@ -0,0 +1,32 @@
1
+ export function swapIt(orch: Orchestrator, { chainHub, sharedLocalAccountP, log, zoeTools: { localTransfer, withdrawToSeat }, }: {
2
+ chainHub: GuestInterface<ChainHub>;
3
+ sharedLocalAccountP: Promise<GuestInterface<LocalOrchestrationAccountKit["holder"]>>;
4
+ zoeTools: GuestInterface<ZoeTools>;
5
+ log: GuestOf<(msg: string, level?: string) => Vow<void>>;
6
+ }, seat: ZCFSeat, offerArgs: SwapInfo): Promise<string>;
7
+ export function swapAnythingViaHook(_orch: Orchestrator, { chainHub, sharedLocalAccountP }: {
8
+ chainHub: GuestInterface<ChainHub>;
9
+ sharedLocalAccountP: Promise<GuestInterface<LocalOrchestrationAccountKit["holder"]>>;
10
+ }, { denom, value }: DenomAmount, memoArgs: SwapInfo): Promise<void>;
11
+ export type SwapInfo = {
12
+ destAddr: string;
13
+ receiverAddr: string;
14
+ outDenom: Denom;
15
+ slippage: {
16
+ slippagePercentage: string;
17
+ windowSeconds: number;
18
+ };
19
+ onFailedDelivery: string;
20
+ nextMemo?: string;
21
+ };
22
+ import type { Orchestrator } from '../types.js';
23
+ import type { ChainHub } from '../types.js';
24
+ import type { GuestInterface } from '@agoric/async-flow';
25
+ import type { LocalOrchestrationAccountKit } from '../exos/local-orchestration-account.js';
26
+ import type { ZoeTools } from '../utils/zoe-tools.js';
27
+ import type { Vow } from '@agoric/vow';
28
+ import type { GuestOf } from '@agoric/async-flow';
29
+ import type { ZCFSeat } from '@agoric/zoe';
30
+ import type { DenomAmount } from '../types.js';
31
+ import type { Denom } from '@agoric/orchestration';
32
+ //# sourceMappingURL=swap-anything.flows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swap-anything.flows.d.ts","sourceRoot":"","sources":["swap-anything.flows.js"],"names":[],"mappings":"AA8EO,6BAXI,YAAY,wFAEpB;IAAsC,QAAQ,EAAtC,eAAe,QAAQ,CAAC;IAC6C,mBAAmB,EAAxF,OAAO,CAAC,eAAe,4BAA4B,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjC,QAAQ,EAAtC,eAAe,QAAQ,CAAC;IACiC,GAAG,EAA5D,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC;CAC3D,QAAQ,OAAO,aACP,QAAQ,mBAwFlB;AAYM,2CAPI,YAAY,qCAEpB;IAAsC,QAAQ,EAAtC,eAAe,QAAQ,CAAC;IAC6C,mBAAmB,EAAxF,OAAO,CAAC,eAAe,4BAA4B,CAAC,QAAQ,CAAC,CAAC,CAAC;CACvE,oBAAQ,WAAW,YACX,QAAQ,iBAgDlB;uBAnNY;IACR,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC;IAChB,QAAQ,EAAE;QAAE,kBAAkB,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;kCAQsF,aAAa;8BAAb,aAAa;oCAN7D,oBAAoB;kDAIf,wCAAwC;8BAC5D,uBAAuB;yBAF5B,aAAa;6BAHO,oBAAoB;6BAEpC,aAAa;iCAImD,aAAa;2BAL/E,uBAAuB"}
@@ -0,0 +1,222 @@
1
+ import { NonNullish, makeTracer } from '@agoric/internal';
2
+ import { makeError, q } from '@endo/errors';
3
+ import { M, mustMatch } from '@endo/patterns';
4
+
5
+ const trace = makeTracer('SwapAnything.Flow');
6
+
7
+ const { entries } = Object;
8
+
9
+ /**
10
+ * @typedef {{
11
+ * destAddr: string;
12
+ * receiverAddr: string;
13
+ * outDenom: Denom;
14
+ * slippage: { slippagePercentage: string; windowSeconds: number };
15
+ * onFailedDelivery: string;
16
+ * nextMemo?: string;
17
+ * }} SwapInfo
18
+ *
19
+ * @import {GuestInterface, GuestOf} from '@agoric/async-flow';
20
+ * @import {Denom} from '@agoric/orchestration';
21
+ * @import {ZCFSeat} from '@agoric/zoe';
22
+ * @import {Vow} from '@agoric/vow';
23
+ * @import {LocalOrchestrationAccountKit} from '../exos/local-orchestration-account.js';
24
+ * @import {ZoeTools} from '../utils/zoe-tools.js';
25
+ * @import {Orchestrator, OrchestrationFlow, ChainHub, CosmosChainInfo, DenomAmount} from '../types.js';
26
+ */
27
+
28
+ const denomForBrand = async (orch, brand) => {
29
+ const agoric = await orch.getChain('agoric');
30
+ const assets = await agoric.getVBankAssetInfo();
31
+ const { denom } = NonNullish(
32
+ assets.find(a => a.brand === brand),
33
+ `${brand} not registered in ChainHub`,
34
+ );
35
+ return denom;
36
+ };
37
+
38
+ /**
39
+ * @param {SwapInfo} swapInfo
40
+ * @returns {string}
41
+ */
42
+ const buildXCSMemo = swapInfo => {
43
+ const memo = {
44
+ wasm: {
45
+ contract: swapInfo.destAddr,
46
+ msg: {
47
+ osmosis_swap: {
48
+ output_denom: swapInfo.outDenom,
49
+ slippage: {
50
+ twap: {
51
+ window_seconds: swapInfo.slippage.windowSeconds,
52
+ slippage_percentage: swapInfo.slippage.slippagePercentage,
53
+ },
54
+ },
55
+ receiver: swapInfo.receiverAddr,
56
+ on_failed_delivery: swapInfo.onFailedDelivery,
57
+ nextMemo: swapInfo.nextMemo,
58
+ },
59
+ },
60
+ },
61
+ };
62
+
63
+ return JSON.stringify(memo);
64
+ };
65
+
66
+ /**
67
+ * @satisfies {OrchestrationFlow}
68
+ * @param {Orchestrator} orch
69
+ * @param {object} ctx
70
+ * @param {GuestInterface<ChainHub>} ctx.chainHub
71
+ * @param {Promise<GuestInterface<LocalOrchestrationAccountKit['holder']>>} ctx.sharedLocalAccountP
72
+ * @param {GuestInterface<ZoeTools>} ctx.zoeTools
73
+ * @param {GuestOf<(msg: string, level?: string) => Vow<void>>} ctx.log
74
+ * @param {ZCFSeat} seat
75
+ * @param {SwapInfo} offerArgs
76
+ */
77
+
78
+ // Ref: https://github.com/osmosis-labs/osmosis/tree/main/cosmwasm/contracts/crosschain-swaps#via-ibc
79
+ export const swapIt = async (
80
+ orch,
81
+ {
82
+ chainHub,
83
+ sharedLocalAccountP,
84
+ log,
85
+ zoeTools: { localTransfer, withdrawToSeat },
86
+ },
87
+ seat,
88
+ offerArgs,
89
+ ) => {
90
+ mustMatch(
91
+ offerArgs,
92
+ M.splitRecord(
93
+ {
94
+ destAddr: M.string(),
95
+ receiverAddr: M.string(),
96
+ outDenom: M.string(),
97
+ onFailedDelivery: M.string(),
98
+ slippage: { slippagePercentage: M.string(), windowSeconds: M.number() },
99
+ },
100
+ { nextMemo: M.string() },
101
+ ),
102
+ );
103
+ void log('Begin swapIt');
104
+
105
+ const { receiverAddr, destAddr } = offerArgs;
106
+ // NOTE the proposal shape ensures that the `give` is a single asset
107
+ const { give } = seat.getProposal();
108
+ const [[_kw, amt]] = entries(give);
109
+ trace(`sending {${amt.value}} from osmosis to ${receiverAddr}`);
110
+ const denom = await denomForBrand(orch, amt.brand);
111
+
112
+ /**
113
+ * @type {any} XXX methods returning vows
114
+ * https://github.com/Agoric/agoric-sdk/issues/9822
115
+ */
116
+ const sharedLocalAccount = await sharedLocalAccountP;
117
+
118
+ /**
119
+ * Helper function to recover if IBC Transfer fails
120
+ *
121
+ * @param {Error} e
122
+ */
123
+ const recoverFailedTransfer = async e => {
124
+ await withdrawToSeat(sharedLocalAccount, seat, give);
125
+ const errorMsg = `IBC Transfer failed ${q(e)}`;
126
+ trace(`ERROR: ${errorMsg}`);
127
+ void log(errorMsg, 'error');
128
+ seat.fail(errorMsg);
129
+ throw makeError(errorMsg);
130
+ };
131
+
132
+ const [_a, osmosisChainInfo, _connection] =
133
+ await chainHub.getChainsAndConnection('agoric', 'osmosis');
134
+
135
+ trace(`got info for chain: osmosis ${osmosisChainInfo}`);
136
+ trace(osmosisChainInfo);
137
+
138
+ await localTransfer(seat, sharedLocalAccount, give);
139
+ trace(`completed transfer to localAccount`);
140
+
141
+ try {
142
+ const memo = buildXCSMemo(offerArgs);
143
+ trace(memo);
144
+ void log(`sending transfer with ${q(memo)}`);
145
+
146
+ await sharedLocalAccount.transfer(
147
+ {
148
+ value: destAddr,
149
+ encoding: 'bech32',
150
+ chainId: /** @type {CosmosChainInfo} */ (osmosisChainInfo).chainId,
151
+ },
152
+ { denom, value: amt.value },
153
+ { memo },
154
+ );
155
+ trace(`completed transfer to ${destAddr}`);
156
+ } catch (e) {
157
+ void log(`transfer error ${q(e)}`, 'error');
158
+ return recoverFailedTransfer(e);
159
+ }
160
+
161
+ seat.exit();
162
+ return 'transfer complete, seat exited';
163
+ };
164
+ harden(swapIt);
165
+
166
+ /**
167
+ * @satisfies {OrchestrationFlow}
168
+ * @param {Orchestrator} _orch
169
+ * @param {object} ctx
170
+ * @param {GuestInterface<ChainHub>} ctx.chainHub
171
+ * @param {Promise<GuestInterface<LocalOrchestrationAccountKit['holder']>>} ctx.sharedLocalAccountP
172
+ * @param {DenomAmount} transferInfo
173
+ * @param {SwapInfo} memoArgs
174
+ */
175
+ export const swapAnythingViaHook = async (
176
+ _orch,
177
+ { chainHub, sharedLocalAccountP },
178
+ { denom, value },
179
+ memoArgs,
180
+ ) => {
181
+ mustMatch(
182
+ memoArgs,
183
+ M.splitRecord(
184
+ {
185
+ destAddr: M.string(),
186
+ receiverAddr: M.string(),
187
+ outDenom: M.string(),
188
+ onFailedDelivery: M.string(),
189
+ slippage: { slippagePercentage: M.string(), windowSeconds: M.number() },
190
+ },
191
+ { nextMemo: M.string() },
192
+ ),
193
+ );
194
+
195
+ const { receiverAddr, destAddr } = memoArgs;
196
+ trace(`sending {${value}} from osmosis to ${receiverAddr}`);
197
+
198
+ /**
199
+ * @type {any} XXX methods returning vows
200
+ * https://github.com/Agoric/agoric-sdk/issues/9822
201
+ */
202
+ const sharedLocalAccount = await sharedLocalAccountP;
203
+
204
+ const [_a, osmosisChainInfo, _connection] =
205
+ await chainHub.getChainsAndConnection('agoric', 'osmosis');
206
+
207
+ trace(`got info for chain: osmosis ${osmosisChainInfo}`);
208
+ trace(osmosisChainInfo);
209
+
210
+ const memo = buildXCSMemo(memoArgs);
211
+
212
+ await sharedLocalAccount.transfer(
213
+ {
214
+ value: destAddr,
215
+ encoding: 'bech32',
216
+ chainId: /** @type {CosmosChainInfo} */ (osmosisChainInfo).chainId,
217
+ },
218
+ { denom, value },
219
+ { memo },
220
+ );
221
+ };
222
+ harden(swapAnythingViaHook);
@@ -1 +1 @@
1
- {"version":3,"file":"ibc-packet.d.ts","sourceRoot":"","sources":["ibc-packet.js"],"names":[],"mappings":"AAMA,4CAA6C,MAAM,CAAC;AAsB7C,gDAHI,GAAG,GACD,OAAO,CAgCnB;AAOM,+CAHI,OAAO,mBAAmB,EAAE,IAAI,8BAChC,QAAQ,GAAG;IAAE,eAAe,EAAE,eAAe,CAAA;CAAE,IA0GhD,GAAG,MAFA,UAAU;eAtFH,iBAAiB,CAAC,WAAW,CAAC;;;;;QAU1C;;;;;WAKG;0BAJQ,IACV,SAAa,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAC,CAC9D,QACO,aAAa;;;;;;QAYxB;;;;;;;;;;;;;;;;WAgBG;oCAbQ,CACV,SACA,WACA,UAAkB,2CAA2C,CAAC,CACvD,CACF,CACF,OACO;YACN,IAAI,EAAE,aAAa,CAAC;YACpB,KAAK,EAAE,IACX,SAAe,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAC,CAC9D,CAAC;SACH;;;;;;;;GA+CK;IA9ET;;;;;OAKG;sBAJQ,IACV,SAAa,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAC,CAC9D,QACO,aAAa;;;;GA2E/B;AAaM,yCAHI,OAAO,mBAAmB,EAAE,IAAI,YAChC,QAAQ,IAqC6D,CAAC,SAAjE,SAAS,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAE,sFACjE,OAAO,UACP,IAAI,CAAC,CAAC,QACN,aAAa;;;EAmBzB;AAQM,sCAHI,OAAO,mBAAmB,EAAE,IAAI,YAChC,QAAQ;;mBArKC,iBAAiB,CAAC,WAAW,CAAC;;;;QAU1C;;;;;WAKG;0BAJQ,IACV,SAAa,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAC,CAC9D,QACO,aAAa;;;;;sBA2HgD,CAAC,SAAjE,SAAS,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAE,sFACjE,OAAO,UACP,IAAI,CAAC,CAAC,QACN,aAAa;;;;EAkCzB;8BAba,UAAU,CAAC,OAAO,kBAAkB,CAAC;6BAvOpB,gBAAgB;8BAEf,aAAa;8BACP,cAAc;yBADpB,aAAa;mCAGb,mBAAmB;uCADf,gCAAgC;+BAHlB,sBAAsB;gCAAtB,sBAAsB;8BAAtB,sBAAsB"}
1
+ {"version":3,"file":"ibc-packet.d.ts","sourceRoot":"","sources":["ibc-packet.js"],"names":[],"mappings":"AAMA,4CAA6C,MAAM,CAAC;AAsB7C,gDAHI,GAAG,GACD,OAAO,CAgCnB;AAOM,+CAHI,OAAO,mBAAmB,EAAE,IAAI,8BAChC,QAAQ,GAAG;IAAE,eAAe,EAAE,eAAe,CAAA;CAAE,IA2HhD,GAAG,MAFA,UAAU;eAvGH,iBAAiB,CAAC,WAAW,CAAC;;;;;QAU1C;;;;;WAKG;0BAJQ,IACV,SAAa,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAC,CAC9D,QACO,aAAa;;;;;;QAYxB;;;;;;;;;;;;;;;;WAgBG;oCAbQ,CACV,SACA,WACA,UAAkB,2CAA2C,CAAC,CACvD,CACF,CACF,OACO;YACN,IAAI,EAAE,aAAa,CAAC;YACpB,KAAK,EAAE,IACX,SAAe,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAC,CAC9D,CAAC;SACH;;;;;;;;GAgEK;IA/FT;;;;;OAKG;sBAJQ,IACV,SAAa,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAC,CAC9D,QACO,aAAa;;;;GA4F/B;AAaM,yCAHI,OAAO,mBAAmB,EAAE,IAAI,YAChC,QAAQ,IAqC6D,CAAC,SAAjE,SAAS,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAE,sFACjE,OAAO,UACP,IAAI,CAAC,CAAC,QACN,aAAa;;;EAmBzB;AAQM,sCAHI,OAAO,mBAAmB,EAAE,IAAI,YAChC,QAAQ;;mBAtLC,iBAAiB,CAAC,WAAW,CAAC;;;;QAU1C;;;;;WAKG;0BAJQ,IACV,SAAa,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAC,CAC9D,QACO,aAAa;;;;;sBA4IgD,CAAC,SAAjE,SAAS,uBAAuB,CAAC,GAAG,SAAS,eAAe,CAAE,sFACjE,OAAO,UACP,IAAI,CAAC,CAAC,QACN,aAAa;;;;EAkCzB;8BAba,UAAU,CAAC,OAAO,kBAAkB,CAAC;6BAxPpB,gBAAgB;8BAEf,aAAa;8BACP,cAAc;yBADpB,aAAa;mCAGb,mBAAmB;uCADf,gCAAgC;+BAHlB,sBAAsB;gCAAtB,sBAAsB;8BAAtB,sBAAsB"}
@@ -157,8 +157,25 @@ export const prepareIBCTransferSender = (zone, { watch, makeIBCReplyKit }) => {
157
157
  const { result, error } = obj;
158
158
  error === undefined || Fail`ICS20-1 transfer error ${error}`;
159
159
  result ?? Fail`Missing result in ICS20-1 transfer ack ${obj}`;
160
- result === ICS20_TRANSFER_SUCCESS_RESULT ||
161
- Fail`ICS20-1 transfer unsuccessful with ack result ${result}`;
160
+ if (result === ICS20_TRANSFER_SUCCESS_RESULT) {
161
+ return; // OK, transfer was successful, nothing to do
162
+ }
163
+
164
+ // Function to safely base64-decode and parse JSON
165
+ const decodeAndParse = b64 => {
166
+ try {
167
+ return JSON.parse(atob(b64));
168
+ } catch {
169
+ Fail`Decoding of base64-encoded ack obj object failed: ${JSON.stringify(b64)}`;
170
+ }
171
+ };
172
+
173
+ const outerDecoded = decodeAndParse(result);
174
+ const ibcAck =
175
+ outerDecoded?.ibc_ack && decodeAndParse(outerDecoded.ibc_ack);
176
+
177
+ ibcAck?.result === ICS20_TRANSFER_SUCCESS_RESULT ||
178
+ Fail`ICS20-1 transfer unsuccessful with ack result: ${outerDecoded}`;
162
179
  },
163
180
  },
164
181
  },
@@ -0,0 +1,133 @@
1
+ import {
2
+ deeplyFulfilledObject,
3
+ makeTracer,
4
+ NonNullish,
5
+ } from '@agoric/internal';
6
+ import { E } from '@endo/far';
7
+
8
+ /// <reference types="@agoric/vats/src/core/types-ambient"/>
9
+
10
+ /**
11
+ * @import {Installation} from '@agoric/zoe/src/zoeService/utils.js';
12
+ * @import {CosmosChainInfo, Denom, DenomDetail} from '@agoric/orchestration';
13
+ * @import {start as StartFn} from '@agoric/orchestration/src/examples/swap-anything.contract.js';
14
+ */
15
+
16
+ const trace = makeTracer('StartSA', true);
17
+
18
+ /**
19
+ * @param {BootstrapPowers & {
20
+ * installation: {
21
+ * consume: {
22
+ * swapAnything: Installation<StartFn>;
23
+ * };
24
+ * };
25
+ * instance: {
26
+ * produce: {
27
+ * swapAnything: Producer<Instance>;
28
+ * };
29
+ * };
30
+ * issuer: {
31
+ * consume: {
32
+ * BLD: Issuer<'nat'>;
33
+ * IST: Issuer<'nat'>;
34
+ * };
35
+ * };
36
+ * }} powers
37
+ * @param {{
38
+ * options: {
39
+ * chainInfo: Record<string, CosmosChainInfo>;
40
+ * assetInfo: [Denom, DenomDetail & { brandKey?: string }][];
41
+ * };
42
+ * }} config
43
+ */
44
+ export const startSwapAnything = async (
45
+ {
46
+ consume: {
47
+ agoricNames,
48
+ board,
49
+ chainStorage,
50
+ chainTimerService,
51
+ cosmosInterchainService,
52
+ localchain,
53
+ startUpgradable,
54
+ },
55
+ installation: {
56
+ consume: { swapAnything },
57
+ },
58
+ instance: {
59
+ produce: { swapAnything: produceInstance },
60
+ },
61
+ issuer: {
62
+ consume: { BLD, IST },
63
+ },
64
+ },
65
+ { options: { chainInfo, assetInfo } },
66
+ ) => {
67
+ trace(startSwapAnything.name);
68
+
69
+ const marshaller = await E(board).getReadonlyMarshaller();
70
+
71
+ const privateArgs = await deeplyFulfilledObject(
72
+ harden({
73
+ agoricNames,
74
+ localchain,
75
+ marshaller,
76
+ orchestrationService: cosmosInterchainService,
77
+ storageNode: E(NonNullish(await chainStorage)).makeChildNode(
78
+ 'swap-anything',
79
+ ),
80
+ timerService: chainTimerService,
81
+ chainInfo,
82
+ assetInfo,
83
+ }),
84
+ );
85
+
86
+ const issuerKeywordRecord = harden({
87
+ BLD: await BLD,
88
+ IST: await IST,
89
+ });
90
+ trace('issuerKeywordRecord', issuerKeywordRecord);
91
+
92
+ const { instance } = await E(startUpgradable)({
93
+ label: 'swap-anything',
94
+ installation: swapAnything,
95
+ issuerKeywordRecord,
96
+ privateArgs,
97
+ });
98
+ produceInstance.resolve(instance);
99
+ trace('done');
100
+ };
101
+ harden(startSwapAnything);
102
+
103
+ export const getManifest = ({ restoreRef }, { installationRef, options }) => {
104
+ return {
105
+ manifest: {
106
+ [startSwapAnything.name]: {
107
+ consume: {
108
+ agoricNames: true,
109
+ board: true,
110
+ chainStorage: true,
111
+ chainTimerService: true,
112
+ cosmosInterchainService: true,
113
+ localchain: true,
114
+
115
+ startUpgradable: true,
116
+ },
117
+ installation: {
118
+ consume: { swapAnything: true },
119
+ },
120
+ instance: {
121
+ produce: { swapAnything: true },
122
+ },
123
+ issuer: {
124
+ consume: { BLD: true, IST: true },
125
+ },
126
+ },
127
+ },
128
+ installations: {
129
+ swapAnything: restoreRef(installationRef),
130
+ },
131
+ options,
132
+ };
133
+ };