@agoric/orchestration 0.1.1-dev-44f473e.0 → 0.1.1-dev-2fa8100.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-tests.d.ts","sourceRoot":"","sources":["contract-tests.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,292 @@
1
+ import type { MsgTransfer } from '@agoric/cosmic-proto/ibc/applications/transfer/v1/tx.js';
2
+ import { VTRANSFER_IBC_EVENT } from '@agoric/internal/src/action-types.js';
3
+ import {
4
+ defaultSerializer,
5
+ makeFakeStorageKit,
6
+ } from '@agoric/internal/src/storage-test-utils.js';
7
+ import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js';
8
+ import { setupFakeNetwork } from '@agoric/orchestration/test/network-fakes.js';
9
+ import { buildVTransferEvent } from '@agoric/orchestration/tools/ibc-mocks.js';
10
+ import {
11
+ makeNameHubKit,
12
+ type IBCChannelID,
13
+ type VTransferIBCEvent,
14
+ } from '@agoric/vats';
15
+ import { prepareBridgeTargetModule } from '@agoric/vats/src/bridge-target.js';
16
+ import { makeWellKnownSpaces } from '@agoric/vats/src/core/utils.js';
17
+ import { prepareLocalChainTools } from '@agoric/vats/src/localchain.js';
18
+ import { prepareTransferTools } from '@agoric/vats/src/transfer.js';
19
+ import { makeFakeBankManagerKit } from '@agoric/vats/tools/bank-utils.js';
20
+ import { makeFakeBoard } from '@agoric/vats/tools/board-utils.js';
21
+ import {
22
+ makeFakeLocalchainBridge,
23
+ makeFakeTransferBridge,
24
+ } from '@agoric/vats/tools/fake-bridge.js';
25
+ import { prepareSwingsetVowTools } from '@agoric/vow/vat.js';
26
+ import { buildZoeManualTimer } from '@agoric/zoe/tools/manualTimer.js';
27
+ import { makeHeapZone } from '@agoric/zone';
28
+ import { E } from '@endo/far';
29
+ import { objectMap } from '@endo/patterns';
30
+ import type { ExecutionContext } from 'ava';
31
+ import { withChainCapabilities, type Bech32Address } from '../index.js';
32
+ import cctpChainInfo from '../src/cctp-chain-info.js';
33
+ import { registerKnownChains } from '../src/chain-info.js';
34
+ import { makeChainHub } from '../src/exos/chain-hub.js';
35
+ import { prepareCosmosInterchainService } from '../src/exos/cosmos-interchain-service.js';
36
+ import fetchedChainInfo from '../src/fetched-chain-info.js';
37
+ import { makeTestAddress } from './make-test-address.js';
38
+
39
+ export const ROOT_STORAGE_PATH = 'orchtest'; // Orchetration Contract Test
40
+
41
+ /**
42
+ * Common setup for contract tests, without any specific asset configuration.
43
+ */
44
+ export const setupOrchestrationTest = async ({
45
+ log,
46
+ }: {
47
+ log: ExecutionContext<any>['log'];
48
+ }) => {
49
+ // The common setup cannot support a durable zone because many of the fakes are not durable.
50
+ // They were made before we had durable kinds (and thus don't take a zone or baggage).
51
+ // To test durability in unit tests, test a particular entity with `relaxDurabilityRules: false`.
52
+ // To test durability integrating multiple vats, use a RunUtils/bootstrap test.
53
+ const rootZone = makeHeapZone();
54
+
55
+ const { nameHub: agoricNames, nameAdmin: agoricNamesAdmin } =
56
+ makeNameHubKit();
57
+
58
+ const bankBridgeMessages = [] as any[];
59
+ const { bankManager, pourPayment } = await makeFakeBankManagerKit({
60
+ onToBridge: obj => bankBridgeMessages.push(obj),
61
+ });
62
+ // XXX real bankManager does this. fake should too?
63
+ // TODO https://github.com/Agoric/agoric-sdk/issues/9966
64
+ await makeWellKnownSpaces(agoricNamesAdmin, log, ['vbankAsset']);
65
+
66
+ const vowTools = prepareSwingsetVowTools(rootZone.subZone('vows'));
67
+
68
+ const transferBridge = makeFakeTransferBridge(rootZone);
69
+ const { makeBridgeTargetKit } = prepareBridgeTargetModule(
70
+ rootZone.subZone('bridge'),
71
+ );
72
+ const { makeTransferMiddlewareKit } = prepareTransferTools(
73
+ rootZone.subZone('transfer'),
74
+ vowTools,
75
+ );
76
+
77
+ const { finisher, interceptorFactory, transferMiddleware } =
78
+ makeTransferMiddlewareKit();
79
+ const bridgeTargetKit = makeBridgeTargetKit(
80
+ transferBridge,
81
+ VTRANSFER_IBC_EVENT,
82
+ interceptorFactory,
83
+ );
84
+ finisher.useRegistry(bridgeTargetKit.targetRegistry);
85
+ await E(transferBridge).initHandler(bridgeTargetKit.bridgeHandler);
86
+
87
+ const localBridgeLog: { obj: any; result: any }[] = [];
88
+ const localchainBridge = makeFakeLocalchainBridge(
89
+ rootZone,
90
+ (obj, result) => localBridgeLog.push({ obj, result }),
91
+ makeTestAddress,
92
+ );
93
+ /** @returns {ReadonlyArray<any>} the input messages sent to the localchain bridge */
94
+ const inspectLocalBridge = () =>
95
+ harden(localBridgeLog.map(entry => entry.obj));
96
+
97
+ const localchain = prepareLocalChainTools(
98
+ rootZone.subZone('localchain'),
99
+ vowTools,
100
+ ).makeLocalChain({
101
+ bankManager,
102
+ system: localchainBridge,
103
+ transfer: transferMiddleware,
104
+ });
105
+ const timer = buildZoeManualTimer(log);
106
+ const marshaller = makeFakeBoard().getPublishingMarshaller();
107
+ const storage = makeFakeStorageKit(ROOT_STORAGE_PATH);
108
+
109
+ const { portAllocator, setupIBCProtocol, ibcBridge } = setupFakeNetwork(
110
+ rootZone.subZone('network'),
111
+ { vowTools },
112
+ );
113
+ await setupIBCProtocol();
114
+
115
+ const makeCosmosInterchainService = prepareCosmosInterchainService(
116
+ rootZone.subZone('orchestration'),
117
+ vowTools,
118
+ );
119
+ const cosmosInterchainService = makeCosmosInterchainService({
120
+ portAllocator,
121
+ });
122
+
123
+ await registerKnownChains(agoricNamesAdmin, () => {});
124
+
125
+ /**
126
+ * Find the Nth outgoing MsgTransfer and its sequence number from the localchain bridge log.
127
+ * @param index 0-based index from the start, or negative index from the end.
128
+ * @returns The MsgTransfer message and its sequence number.
129
+ * @throws If index is out of bounds or sequence is not found in the log result.
130
+ */
131
+ const outgoingTransferAt = (index: number) => {
132
+ const transferMessagesInfo: { message: MsgTransfer; sequence: bigint }[] =
133
+ [];
134
+ const isRelevant = ({ obj, result }) =>
135
+ obj.type === 'VLOCALCHAIN_EXECUTE_TX' &&
136
+ obj.messages &&
137
+ Array.isArray(result);
138
+ for (const { obj, result } of localBridgeLog.filter(isRelevant)) {
139
+ // `obj.messages` and `result` are paired arrays.
140
+ for (let i = 0; i < obj.messages.length; i += 1) {
141
+ const message = obj.messages[i];
142
+ if (message['@type'] === '/ibc.applications.transfer.v1.MsgTransfer') {
143
+ const messageResult = result[i];
144
+ try {
145
+ const sequence = BigInt(messageResult.sequence);
146
+ transferMessagesInfo.push({ message, sequence });
147
+ } catch (cause) {
148
+ throw new Error(
149
+ `Sequence not found in result for MsgTransfer: ${JSON.stringify(message)}`,
150
+ { cause },
151
+ );
152
+ }
153
+ }
154
+ }
155
+ }
156
+ const transferMessageInfo = transferMessagesInfo.at(index);
157
+ if (!transferMessageInfo) {
158
+ throw new Error(
159
+ `Index ${index} out of bounds for ${transferMessagesInfo.length} outgoing transfers.`,
160
+ );
161
+ }
162
+ return transferMessageInfo;
163
+ };
164
+
165
+ /**
166
+ * Simulate an inbound VTransferIBCEvent message to the vtransfer bridge for a specific transfer.
167
+ *
168
+ * @param event The type of IBC event ('acknowledgementPacket' or 'timeoutPacket').
169
+ * @param query Index of the outgoing transfer (e.g., -1 for the last one) or the `{ message: MsgTransfer, sequence: bigint }` object itself.
170
+ * @param acknowledgementError Optional error string for acknowledgementPacket events.
171
+ *
172
+ * @example
173
+ * ```js
174
+ * // send ack for the last transfer
175
+ * await transmitVTransferEvent('acknowledgementPacket', -1);
176
+ * // send ack error for the first transfer
177
+ * await transmitVTransferEvent('acknowledgementPacket', 0, 'simulated error');
178
+ * // send timeout for the second-to-last transfer
179
+ * await transmitVTransferEvent('timeoutPacket', -2);
180
+ * ```
181
+ */
182
+ const transmitVTransferEvent = async (
183
+ event: VTransferIBCEvent['event'],
184
+ query: number | { message: MsgTransfer; sequence: bigint },
185
+ acknowledgementError?: string,
186
+ ) => {
187
+ // let the promise for the transfer start (if any)
188
+ await eventLoopIteration();
189
+
190
+ const transferInfo =
191
+ typeof query === 'number' ? outgoingTransferAt(query) : query;
192
+
193
+ const { message: msg, sequence } = transferInfo;
194
+
195
+ const base = {
196
+ receiver: msg.receiver as Bech32Address,
197
+ sender: msg.sender as Bech32Address,
198
+ target: msg.sender as Bech32Address, // target is usually the sender for outgoing transfers
199
+ sourceChannel: msg.sourceChannel as IBCChannelID,
200
+ sequence, // Use sequence from transferInfo
201
+ amount: BigInt(msg.token.amount),
202
+ denom: msg.token.denom,
203
+ memo: msg.memo,
204
+ };
205
+
206
+ await E(transferBridge).fromBridge(
207
+ buildVTransferEvent(
208
+ event === 'timeoutPacket'
209
+ ? { event, ...base }
210
+ : { event, ...base, acknowledgementError },
211
+ ),
212
+ );
213
+ // let the bridge handler finish
214
+ await eventLoopIteration();
215
+ };
216
+
217
+ /** A chainHub for Exo tests, distinct from the one a contract makes within `withOrchestration` */
218
+ const chainHub = makeChainHub(
219
+ rootZone.subZone('chainHub'),
220
+ agoricNames,
221
+ vowTools,
222
+ );
223
+
224
+ const chainInfo = harden(() => {
225
+ const { agoric, osmosis, noble } = withChainCapabilities(fetchedChainInfo);
226
+ const { ethereum, solana } = objectMap(cctpChainInfo, v => ({
227
+ ...v,
228
+ // for backwards compatibility with `CosmosChainInfoShapeV1` which expects a `chainId`
229
+ chainId: `${v.namespace}:${v.reference}`,
230
+ }));
231
+ return {
232
+ agoric,
233
+ osmosis,
234
+ noble,
235
+ ethereum,
236
+ solana,
237
+ };
238
+ })();
239
+
240
+ return {
241
+ bootstrap: {
242
+ agoricNames,
243
+ agoricNamesAdmin,
244
+ bankManager,
245
+ timer,
246
+ localchain,
247
+ cosmosInterchainService,
248
+ storage: {
249
+ ...storage,
250
+ /**
251
+ * Read pure data (CapData that has no slots) from the storage path
252
+ */
253
+ getDeserialized(path: string): unknown[] {
254
+ return storage.getValues(path).map(defaultSerializer.parse);
255
+ },
256
+ },
257
+ },
258
+ mocks: {
259
+ ibcBridge,
260
+ transferBridge,
261
+ },
262
+ commonPrivateArgs: {
263
+ agoricNames,
264
+ localchain,
265
+ orchestrationService: cosmosInterchainService,
266
+ storageNode: storage.rootNode,
267
+ poolMetricsNode: storage.rootNode.makeChildNode('poolMetrics'),
268
+ marshaller,
269
+ timerService: timer,
270
+ chainInfo,
271
+ },
272
+ facadeServices: {
273
+ agoricNames,
274
+ /** A chainHub for Exo tests, distinct from the one a contract makes within `withOrchestration` */
275
+ chainHub,
276
+ localchain,
277
+ orchestrationService: cosmosInterchainService,
278
+ timerService: timer,
279
+ },
280
+ utils: {
281
+ contractZone: rootZone.subZone('contract'),
282
+ pourPayment,
283
+ inspectLocalBridge,
284
+ inspectDibcBridge: () => E(ibcBridge).inspectDibcBridge(),
285
+ inspectBankBridge: () => harden([...bankBridgeMessages]),
286
+ outgoingTransferAt,
287
+ rootZone,
288
+ transmitVTransferEvent,
289
+ vowTools,
290
+ },
291
+ };
292
+ };