1
+ import { NonNullish , makeTracer } from '@agoric/internal' ;
2
+ import { Fail , makeError , q } from '@endo/errors' ;
3
+ import { M , mustMatch } from '@endo/patterns' ;
4
+ import { RatioShape } from '@agoric/ertp' ;
5
+
6
+ const trace = makeTracer ( 'SwapAnything' ) ;
7
+
8
+ const { entries } = Object ;
9
+
1
10
/**
2
11
* @import {GuestInterface, GuestOf} from '@agoric/async-flow';
3
- * @import {Invitation, ZCF, ZCFSeat} from '@agoric/zoe';
12
+ * @import {Denom, DenomDetail} from '@agoric/orchestration';
13
+ * @import {ZCF, ZCFSeat} from '@agoric/zoe';
4
14
* @import {Brand} from '@agoric/ertp';
5
15
* @import {Vow} from '@agoric/vow';
6
16
* @import {LocalOrchestrationAccountKit} from '../exos/local-orchestration-account.js';
7
17
* @import {ZoeTools} from '../utils/zoe-tools.js';
8
- * @import {Orchestrator, OrchestrationFlow, LocalAccountMethods, ChainHub, ChainInfo} from '../types.js';
18
+ * @import {Orchestrator, OrchestrationFlow, ChainHub, ChainInfo} from '../types.js';
9
19
* @import {AccountIdArg} from '../orchestration-api.ts';
10
20
*/
11
21
22
+ const denomForBrand = async ( orch , brand ) => {
23
+ const agoric = await orch . getChain ( 'agoric' ) ;
24
+ const assets = await agoric . getVBankAssetInfo ( ) ;
25
+ const { denom } = NonNullish (
26
+ assets . find ( a => a . brand === brand ) ,
27
+ `${ brand } not registered in ChainHub` ,
28
+ ) ;
29
+ return denom ;
30
+ } ;
31
+
12
32
/**
13
33
* @satisfies {OrchestrationFlow }
14
34
* @param {Orchestrator } orch
15
35
* @param {object } ctx
16
36
* @param {GuestInterface<ChainHub> } ctx.chainHub
17
37
* @param {Promise<GuestInterface<LocalOrchestrationAccountKit['holder']>> } ctx.sharedLocalAccountP
18
- * @param {Promise<
19
- * GuestInterface<
20
- * import('../exos/cosmos-orchestration-account.js').CosmosOrchestrationAccountKit['holder']
21
- * >
22
- * >} ctx.nobleAccountP
23
38
* @param {GuestInterface<ZoeTools> } ctx.zoeTools
24
39
* @param {GuestOf<(msg: string) => Vow<void>> } ctx.log
25
- * @param {Brand } ctx.USDC
26
40
* @param {ZCFSeat } seat
27
41
* @param {{
28
- * destAddr: AccountIdArg;
29
- * destDenom: Denom;
30
- * slippage: { slippageRatio: Ratio; windowSeconds: Nat };
42
+ * destAddr: string;
43
+ * receiverAddr: string;
44
+ * outDenom: Denom;
45
+ * slippage: { slippageRatio: Ratio; windowSeconds: bigint };
31
46
* onFailedDelivery: string;
32
- * nextMemo: string;
47
+ * nextMemo? : string;
33
48
* }} offerArgs
34
49
*/
35
50
@@ -41,11 +56,92 @@ export const swapIt = async (
41
56
chainHub,
42
57
sharedLocalAccountP,
43
58
log,
44
- nobleAccountP,
45
- USDC ,
46
59
zoeTools : { localTransfer, withdrawToSeat } ,
47
60
} ,
48
61
seat ,
49
62
offerArgs ,
50
- ) => { } ;
63
+ ) => {
64
+ // offerArgs,
65
+ // harden({
66
+ // destAddr: M.string(),
67
+ // receiverAddr: M.string(),
68
+ // outDenom: M.string(),
69
+ // onFailedDelivery: M.string(),
70
+ // slippage: { slippageRatio: RatioShape, windowSeconds: M.bigint() },
71
+ // }),
72
+ // );
73
+ mustMatch (
74
+ offerArgs ,
75
+ M . splitRecord (
76
+ {
77
+ destAddr : M . string ( ) ,
78
+ receiverAddr : M . string ( ) ,
79
+ outDenom : M . string ( ) ,
80
+ onFailedDelivery : M . string ( ) ,
81
+ slippage : { slippageRatio : RatioShape , windowSeconds : M . bigint ( ) } ,
82
+ } ,
83
+ { nextMemo : M . or ( undefined , M . string ( ) ) } ,
84
+ ) ,
85
+ ) ;
86
+
87
+ trace ( 'HELLLOOOOO' ) ;
88
+
89
+ const { destAddr } = offerArgs ;
90
+ // NOTE the proposal shape ensures that the `give` is a single asset
91
+ const { give } = seat . getProposal ( ) ;
92
+ const [ [ _kw , amt ] ] = entries ( give ) ;
93
+ void log ( `sending {${ amt . value } } from osmosis to ${ destAddr } ` ) ;
94
+ const denom = await denomForBrand ( orch , amt . brand ) ;
95
+
96
+ /** @type {ChainInfo } */
97
+ const info = await chainHub . getChainInfo ( 'osmosis' ) ;
98
+
99
+ /**
100
+ * @type {any } XXX methods returning vows
101
+ * https://github.com/Agoric/agoric-sdk/issues/9822
102
+ */
103
+ const sharedLocalAccount = await sharedLocalAccountP ;
104
+
105
+ /**
106
+ * Helper function to recover if IBC Transfer fails
107
+ *
108
+ * @param {Error } e
109
+ */
110
+ const recoverFailedTransfer = async e => {
111
+ await withdrawToSeat ( sharedLocalAccount , seat , give ) ;
112
+ const errorMsg = `IBC Transfer failed ${ q ( e ) } ` ;
113
+ void log ( `ERROR: ${ errorMsg } ` ) ;
114
+ seat . fail ( errorMsg ) ;
115
+ throw makeError ( errorMsg ) ;
116
+ } ;
117
+
118
+ const { chainId } = info ;
119
+ assert ( typeof chainId === 'string' , 'bad chainId' ) ;
120
+
121
+ const [ _a , _o , connection ] = await chainHub . getChainsAndConnection (
122
+ 'agoric' ,
123
+ 'osmosis' ,
124
+ ) ;
125
+
126
+ connection . counterparty || Fail `No IBC connection to Osmosis` ;
127
+
128
+ void log ( `got info for chain: osmosis ${ chainId } ` ) ;
129
+
130
+ await localTransfer ( seat , sharedLocalAccount , give ) ;
131
+ void log ( `completed transfer to localAccount` ) ;
132
+
133
+ try {
134
+ await sharedLocalAccount . transfer (
135
+ { value : destAddr , encoding : 'bech32' , chainId } ,
136
+ { denom, value : amt . value } ,
137
+ // memo here
138
+ ) ;
139
+ void log ( `completed transfer to ${ destAddr } ` ) ;
140
+ } catch ( e ) {
141
+ return recoverFailedTransfer ( e ) ;
142
+ }
143
+
144
+ seat . exit ( ) ;
145
+ void log ( `transfer complete, seat exited` ) ;
146
+ } ;
51
147
harden ( swapIt ) ;
0 commit comments