Skip to content

Commit 9da7798

Browse files
committed
chore: unit test for happy path
Refs: #8863
1 parent 00dd441 commit 9da7798

File tree

2 files changed

+106
-63
lines changed

2 files changed

+106
-63
lines changed

packages/orchestration/src/examples/swap-anything.flows.js

+58-42
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
import { NonNullish, makeTracer } from '@agoric/internal';
22
import { Fail, makeError, q } from '@endo/errors';
33
import { M, mustMatch } from '@endo/patterns';
4-
import { RatioShape } from '@agoric/ertp';
54

65
const trace = makeTracer('SwapAnything');
76

87
const { entries } = Object;
98

109
/**
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+
*
1119
* @import {GuestInterface, GuestOf} from '@agoric/async-flow';
12-
* @import {Denom, DenomDetail} from '@agoric/orchestration';
13-
* @import {ZCF, ZCFSeat} from '@agoric/zoe';
14-
* @import {Brand} from '@agoric/ertp';
20+
* @import {Denom} from '@agoric/orchestration';
21+
* @import {ZCFSeat} from '@agoric/zoe';
1522
* @import {Vow} from '@agoric/vow';
1623
* @import {LocalOrchestrationAccountKit} from '../exos/local-orchestration-account.js';
1724
* @import {ZoeTools} from '../utils/zoe-tools.js';
18-
* @import {Orchestrator, OrchestrationFlow, ChainHub, ChainInfo} from '../types.js';
19-
* @import {AccountIdArg} from '../orchestration-api.ts';
25+
* @import {Orchestrator, OrchestrationFlow, ChainHub, ChainInfo, CosmosChainInfo} from '../types.js';
2026
*/
2127

2228
const denomForBrand = async (orch, brand) => {
@@ -29,6 +35,34 @@ const denomForBrand = async (orch, brand) => {
2935
return denom;
3036
};
3137

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+
3266
/**
3367
* @satisfies {OrchestrationFlow}
3468
* @param {Orchestrator} orch
@@ -38,14 +72,7 @@ const denomForBrand = async (orch, brand) => {
3872
* @param {GuestInterface<ZoeTools>} ctx.zoeTools
3973
* @param {GuestOf<(msg: string) => Vow<void>>} ctx.log
4074
* @param {ZCFSeat} seat
41-
* @param {{
42-
* destAddr: string;
43-
* receiverAddr: string;
44-
* outDenom: Denom;
45-
* slippage: { slippageRatio: Ratio; windowSeconds: bigint };
46-
* onFailedDelivery: string;
47-
* nextMemo?: string;
48-
* }} offerArgs
75+
* @param {SwapInfo} offerArgs
4976
*/
5077

5178
// Given USDC, swap to desired token with slippage
@@ -61,15 +88,6 @@ export const swapIt = async (
6188
seat,
6289
offerArgs,
6390
) => {
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-
// );
7391
mustMatch(
7492
offerArgs,
7593
M.splitRecord(
@@ -78,24 +96,19 @@ export const swapIt = async (
7896
receiverAddr: M.string(),
7997
outDenom: M.string(),
8098
onFailedDelivery: M.string(),
81-
slippage: { slippageRatio: RatioShape, windowSeconds: M.bigint() },
99+
slippage: { slippagePercentage: M.string(), windowSeconds: M.number() },
82100
},
83-
{ nextMemo: M.or(undefined, M.string()) },
101+
{ nextMemo: M.string() },
84102
),
85103
);
86104

87-
trace('HELLLOOOOO');
88-
89-
const { destAddr } = offerArgs;
105+
const { receiverAddr, destAddr } = offerArgs;
90106
// NOTE the proposal shape ensures that the `give` is a single asset
91107
const { give } = seat.getProposal();
92108
const [[_kw, amt]] = entries(give);
93-
void log(`sending {${amt.value}} from osmosis to ${destAddr}`);
109+
void log(`sending {${amt.value}} from osmosis to ${receiverAddr}`);
94110
const denom = await denomForBrand(orch, amt.brand);
95111

96-
/** @type {ChainInfo} */
97-
const info = await chainHub.getChainInfo('osmosis');
98-
99112
/**
100113
* @type {any} XXX methods returning vows
101114
* https://github.com/Agoric/agoric-sdk/issues/9822
@@ -115,26 +128,29 @@ export const swapIt = async (
115128
throw makeError(errorMsg);
116129
};
117130

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-
);
131+
const [_a, osmosisChainInfo, connection] =
132+
await chainHub.getChainsAndConnection('agoric', 'osmosis');
125133

126134
connection.counterparty || Fail`No IBC connection to Osmosis`;
127135

128-
void log(`got info for chain: osmosis ${chainId}`);
136+
void log(`got info for chain: osmosis ${osmosisChainInfo}`);
137+
trace(osmosisChainInfo);
129138

130139
await localTransfer(seat, sharedLocalAccount, give);
131140
void log(`completed transfer to localAccount`);
132141

133142
try {
143+
const memo = buildXCSMemo(offerArgs);
144+
trace(memo);
145+
134146
await sharedLocalAccount.transfer(
135-
{ value: destAddr, encoding: 'bech32', chainId },
147+
{
148+
value: destAddr,
149+
encoding: 'bech32',
150+
chainId: /** @type {CosmosChainInfo} */ (osmosisChainInfo).chainId,
151+
},
136152
{ denom, value: amt.value },
137-
// memo here
153+
{ memo },
138154
);
139155
void log(`completed transfer to ${destAddr}`);
140156
} catch (e) {

packages/orchestration/test/examples/swap-anything.test.ts

+48-21
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js';
22
import { setUpZoeForTest } from '@agoric/zoe/tools/setup-zoe.js';
33
import { E } from '@endo/far';
4-
import { makeRatio } from '@agoric/ertp/src/ratio.js';
54
import * as contractExports from '../../src/examples/swap-anything.contract.js';
65
import { commonSetup } from '../supports.js';
76

87
const contractName = 'swap-anything';
98
type StartFn = typeof contractExports.start;
109

10+
const config = {
11+
xcsInformation: {
12+
// A message that we know to be working
13+
rawMsgNoNextMemo:
14+
'{"wasm":{"contract":"osmo17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9jfksztgw5uh69wac2pgs5yczr8","msg":{"osmosis_swap":{"output_denom":"uosmo","slippage":{"twap":{"window_seconds":10,"slippage_percentage":"20"}},"receiver":"agoric1elueec97as0uwavlxpmj75u5w7yq9dgphq47zx","on_failed_delivery":"do_nothing"}}}}',
15+
},
16+
};
17+
1118
const bootstrapOrchestration = async t => {
1219
t.log('bootstrap, orchestration core-eval');
1320
const {
1421
bootstrap,
1522
commonPrivateArgs,
1623
brands: { bld },
17-
utils: {
18-
inspectLocalBridge,
19-
pourPayment,
20-
transmitTransferAck,
21-
populateChainHub,
22-
},
24+
utils: { inspectLocalBridge, pourPayment, transmitTransferAck },
2325
} = await commonSetup(t);
2426
const vt = bootstrap.vowTools;
2527

@@ -34,8 +36,6 @@ const bootstrapOrchestration = async t => {
3436
contractName,
3537
);
3638

37-
populateChainHub();
38-
3939
const swapKit = await E(zoe).startInstance(
4040
installation,
4141
{ BLD: bld.issuer },
@@ -58,6 +58,38 @@ const bootstrapOrchestration = async t => {
5858
};
5959
};
6060

61+
const buildOfferArgs = rawMsg => {
62+
const {
63+
wasm: {
64+
contract,
65+
msg: {
66+
osmosis_swap: {
67+
receiver,
68+
output_denom: outDenom,
69+
slippage: {
70+
twap: {
71+
slippage_percentage: slippagePercentage,
72+
window_seconds: windowSeconds,
73+
},
74+
},
75+
76+
on_failed_delivery: onFailedDelivery,
77+
next_memo: nextMemo,
78+
},
79+
},
80+
},
81+
} = JSON.parse(rawMsg);
82+
83+
return {
84+
destAddr: contract,
85+
receiverAddr: receiver,
86+
outDenom,
87+
slippage: { slippagePercentage, windowSeconds },
88+
onFailedDelivery,
89+
nextMemo,
90+
};
91+
};
92+
6193
test('swap BLD for Osmo, receiver on Agoric', async t => {
6294
const {
6395
vt,
@@ -76,20 +108,13 @@ test('swap BLD for Osmo, receiver on Agoric', async t => {
76108

77109
const anAmt = bld.units(3.5);
78110
const Send = await pourPayment(anAmt);
111+
const offerArgs = buildOfferArgs(config.xcsInformation.rawMsgNoNextMemo);
112+
79113
const userSeat = await E(zoe).offer(
80114
inv,
81115
{ give: { Send: anAmt } },
82116
{ Send },
83-
{
84-
destAddr: 'hot1destAddr',
85-
receiverAddr: 'osmosis1xcsaddr',
86-
outDenom: 'uosmo',
87-
onFailedDelivery: 'doNothing',
88-
slippage: {
89-
slippageRatio: makeRatio(10n, bld.brand),
90-
windowSeconds: 10n,
91-
},
92-
},
117+
offerArgs,
93118
);
94119
await transmitTransferAck();
95120
await vt.when(E(userSeat).getOfferResult());
@@ -105,10 +130,12 @@ test('swap BLD for Osmo, receiver on Agoric', async t => {
105130
history.find(x => x.type === 'VLOCALCHAIN_EXECUTE_TX')?.messages?.[0],
106131
{
107132
'@type': '/ibc.applications.transfer.v1.MsgTransfer',
108-
receiver: 'hot1destAddr',
133+
receiver: offerArgs.destAddr, // XCS contract has to be the one receiving the IBC message
109134
sender: 'agoric1fakeLCAAddress',
110-
memo: '',
135+
memo: config.xcsInformation.rawMsgNoNextMemo,
111136
},
112137
'crosschain swap sent',
113138
);
114139
});
140+
141+
test.todo('should throw when Osmosis not connected');

0 commit comments

Comments
 (0)