/ contract / test / test-poolFactory.js
test-poolFactory.js
  1  // @ts-check
  2  
  3  /* eslint-disable import/order -- https://github.com/endojs/endo/issues/1235 */
  4  import { test } from './prepare-test-env-ava.js';
  5  import path from 'path';
  6  
  7  import bundleSource from '@endo/bundle-source';
  8  
  9  import { E } from '@endo/eventual-send';
 10  import { makeFakeVatAdmin } from '@agoric/zoe/tools/fakeVatAdmin.js';
 11  import { makeZoeKit } from '@agoric/zoe';
 12  import { AmountMath, AssetKind, makeIssuerKit } from '@agoric/ertp';
 13  import { makeStore } from '@agoric/store';
 14  import { makeRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
 15  import { makeSubscription, makeSubscriptionKit } from '@agoric/notifier';
 16  import {
 17    handleError,
 18    handleSetIssuerError
 19  } from '../src/shared/utils/offers.js';
 20  
 21  const filename = new URL(import.meta.url).pathname;
 22  const dirname = path.dirname(filename);
 23  
 24  const contractPath = `${dirname}/../src/poolFactory.js`;
 25  
 26  const setupTestMints = () => {
 27    const dollarKit = makeIssuerKit('dollar');
 28    const {
 29      brand: dollarBrand,
 30      issuer: dollarIssuer,
 31      mint: dollarMint
 32    } = dollarKit;
 33    const euroKit = makeIssuerKit('euro');
 34    const { brand: euroBrand, issuer: euroIssuer, mint: euroMint } = euroKit;
 35    const dollars = x => AmountMath.make(dollarBrand, x);
 36    const euros = x => AmountMath.make(euroBrand, x);
 37    const {
 38      brand: atomBrand,
 39      issuer: atomIssuer,
 40      mint: atomMint
 41    } = makeIssuerKit('atom');
 42    const atoms = x => AmountMath.make(atomBrand, x);
 43    return {
 44      atomBrand,
 45      atomIssuer,
 46      atomMint,
 47      atoms,
 48      dollarKit,
 49      dollarBrand,
 50      dollarIssuer,
 51      dollarMint,
 52      dollars,
 53      euroKit,
 54      euroBrand,
 55      euroIssuer,
 56      euroMint,
 57      euros
 58    };
 59  };
 60  
 61  const setupContract = async contract => {
 62    const { zoeService } = makeZoeKit(makeFakeVatAdmin().admin);
 63    const feePurse = E(zoeService).makeFeePurse();
 64    const zoe = E(zoeService).bindDefaultFeePurse(feePurse);
 65    const bundle = await bundleSource(contract);
 66  
 67    // install the contract
 68    const installation = E(zoe).install(bundle);
 69  
 70    const contractInstance = await E(zoe).startInstance(installation);
 71  
 72    return {
 73      installation,
 74      zoe,
 75      bundle,
 76      feePurse,
 77      zoeService,
 78      contractInstance
 79    };
 80  };
 81  
 82  const {
 83    dollarIssuer,
 84    dollarBrand,
 85    dollars,
 86    dollarMint,
 87    euroIssuer,
 88    euroBrand,
 89    euros,
 90    euroMint,
 91    atomIssuer,
 92    atomBrand,
 93    atoms,
 94    atomMint
 95  } = setupTestMints();
 96  
 97  test('poolFactory - deployInitialCollateral:: given incorrect issuerKeywordRecord', async t => {
 98    const { contractInstance } = await setupContract(contractPath);
 99  
100    const { creatorFacet } = contractInstance;
101  
102    const incorrectIssuerKeywordRecord = {
103      Atoms: atomIssuer,
104      Dollars: dollarIssuer,
105      Euros: euroBrand
106    };
107    const deployInitialCollateralInvitation = await E(
108      creatorFacet
109    ).makeDeployInitialCollateralInvitation(incorrectIssuerKeywordRecord);
110  
111    const mockSaveIssuerError = TypeError(
112      'target has no method "getBrand", has []'
113    );
114  
115    t.deepEqual(
116      deployInitialCollateralInvitation,
117      handleSetIssuerError(mockSaveIssuerError),
118      'should gracefully handle the error.'
119    );
120  });
121  
122  test('poolFactory - deployInitialCollateral:: multiple issuerKeywords', async t => {
123    const { contractInstance, zoe } = await setupContract(contractPath);
124  
125    const { creatorFacet, publicFacet } = contractInstance;
126  
127    const issuerKeywordRecord = {
128      Atoms: atomIssuer,
129      Dollars: dollarIssuer,
130      Euros: euroIssuer
131    };
132  
133    const initialDollars = 10000n;
134    const initialEuros = 50000n;
135    const initialAtoms = 15000n;
136    const deployInitialCollateralProposal = harden({
137      give: {
138        Atoms: atoms(initialAtoms),
139        Dollars: dollars(initialDollars),
140        Euros: euros(initialEuros)
141      }
142    });
143  
144    const marketManagerFacet = await E(
145      creatorFacet
146    ).makeDeployInitialCollateralInvitation(issuerKeywordRecord);
147    t.true(!marketManagerFacet === false, 'marketManagerFacet should exit.');
148  
149    const store = marketManagerFacet.getStore();
150  
151    t.deepEqual(store.get('Atoms').issuer, atomIssuer);
152  });
153  
154  test('poolFactory - deployInitialCollateral:: setting up marekts', async t => {
155    const { contractInstance, zoe } = await setupContract(contractPath);
156  
157    const { creatorFacet, publicFacet } = contractInstance;
158  
159    const issuerKeywordRecord = {
160      Atoms: atomIssuer,
161      Dollars: dollarIssuer
162    };
163  
164    const initialDollars = 10000n;
165    const initialEuros = 50000n;
166    const initialAtoms = 15000n;
167  
168    const deployInitialCollateralPayments = {
169      Atoms: atomMint.mintPayment(atoms(initialAtoms))
170    };
171  
172    const debtIssuers = await E(publicFacet).getIssuers();
173  
174    const getLength = ({ length }) => length;
175  
176    t.deepEqual(
177      debtIssuers,
178      2,
179      'debtIssuers array should expose the correct issuers'
180    );
181    const [LiAtomsIssuer, LiDollarsIssuer] = debtIssuers;
182  
183    t.truthy(
184      await LiAtomsIssuer.getBrand(),
185      'should expose a reference to the LiAtoms Issuer'
186    );
187    t.truthy(
188      LiDollarsIssuer.getBrand(),
189      'should expose a reference to the LiDollars Issuer'
190    );
191  
192    const liAtoms = x => AmountMath.make(LiAtomsIssuer.getBrand(), x);
193    const liDollars = x => AmountMath.make(LiDollarsIssuer.getBrand(), x);
194    const marketManagerFacet = await E(
195      creatorFacet
196    ).makeDeployInitialCollateralInvitation(issuerKeywordRecord);
197  
198    const setupMarketFn = await E(marketManagerFacet).setMarketParams();
199    t.truthy(marketManagerFacet.setMarketParams);
200    const dollarsInterestState = {
201      uOptimal: 80,
202      slope1: 4,
203      slope2: 60
204    };
205    const deployCollateralInvitation = setupMarketFn(
206      'Dollars',
207      dollarsInterestState,
208      makeSubscriptionKit()
209    );
210  
211    const deployDollarsSeat = await E(zoe).offer(
212      await E(marketManagerFacet).deployInitialCollateral(),
213      deployDollarsProposal,
214      { Dollars: dollarMint.mintPayment(dollars(initialDollars)) }
215    );
216  
217    const deployDollarsProposal = harden({
218      give: {
219        Dollars: dollars(initialDollars)
220      },
221      want: {
222        LiDollars: liDollars(initialDollars)
223      }
224    });
225    t.deepEqual(await setParamsResult, {});
226  });
227  
228  // test('poolFactory - deployInitialCollateral:: given correct issuerKeywordRecord', async t => {
229  //   const { contractInstance, zoe } = await setupContract(contractPath);
230  
231  //   const { creatorFacet, publicFacet } = contractInstance;
232  
233  //   const issuerKeywordRecord = {
234  //     Atoms: atomIssuer,
235  //     Dollars: dollarIssuer
236  //   };
237  
238  //   const initialDollars = 10000n;
239  //   const initialEuros = 50000n;
240  //   const initialAtoms = 15000n;
241  
242  //   const deployInitialCollateralPayments = {
243  //     Atoms: atomMint.mintPayment(atoms(initialAtoms))
244  //   };
245  
246  //   const marketManagerFacet = await E(
247  //     creatorFacet
248  //   ).makeDeployInitialCollateralInvitation(issuerKeywordRecord);
249  
250  //   const debtIssuers = await E(publicFacet).getIssuers();
251  
252  //   const getLength = ({ length }) => length;
253  
254  //   t.deepEqual(
255  //     getLength(debtIssuers),
256  //     2,
257  //     'debtIssuers array should expose the correct issuers'
258  //   );
259  //   const [LiAtomsIssuer, LiDollarsIssuer] = debtIssuers;
260  
261  //   t.truthy(
262  //     await LiAtomsIssuer.getBrand(),
263  //     'should expose a reference to the LiAtoms Issuer'
264  //   );
265  //   t.truthy(
266  //     LiDollarsIssuer.getBrand(),
267  //     'should expose a reference to the LiDollars Issuer'
268  //   );
269  
270  //   const liAtoms = x => AmountMath.make(LiAtomsIssuer.getBrand(), x);
271  //   const liDollars = x => AmountMath.make(LiDollarsIssuer.getBrand(), x);
272  
273  //   const deployInitialCollateralProposal = harden({
274  //     give: {
275  //       Atoms: atoms(initialAtoms)
276  //     },
277  //     want: {
278  //       LiAtoms: liAtoms(initialAtoms)
279  //     }
280  //   });
281  //   /**
282  //    * @type {Invitation}
283  //    */
284  //   const deployInitialCollateralInvitation = await E(
285  //     marketManagerFacet
286  //   ).deployInitialCollateral();
287  
288  //   /**
289  //    * @type {UserSeat}
290  //    */
291  
292  //   const deployCollateralSeat = await E(zoe).offer(
293  //     deployInitialCollateralInvitation,
294  //     deployInitialCollateralProposal,
295  //     deployInitialCollateralPayments
296  //   );
297  
298  //   const deployCollateralOfferResult =
299  //     await deployCollateralSeat.getOfferResult();
300  //   const setupTestMarketParams =
301  //     await deployCollateralOfferResult.setMarketParams();
302  //   console.log({ deployCollateralOfferResult });
303  //   const dollarsInterestState = {
304  //     uOptimal: 80,
305  //     slope1: 4,
306  //     slope2: 60
307  //   };
308  //   const setParamsResult = setupTestMarketParams(
309  //     'Dollars',
310  //     dollarsInterestState,
311  //     makeSubscriptionKit()
312  //   );
313  
314  //   t.truthy(
315  //     deployCollateralOfferResult.getStore,
316  //     'deployCollateralOfferResult should expose getStore'
317  //   );
318  
319  //   const poolCollateralTypes = await deployCollateralOfferResult.getStore();
320  
321  //   t.deepEqual(
322  //     poolCollateralTypes.get('Atoms').totalSupply,
323  //     atoms(initialAtoms),
324  //     'should return the correct value'
325  //   );
326  
327  //   t.deepEqual(
328  //     poolCollateralTypes.get('Atoms').issuer,
329  //     atomIssuer,
330  //     'should return the atom issuer type'
331  //   );
332  
333  //   t.deepEqual(
334  //     poolCollateralTypes.get('Dollars').totalSupply,
335  //     dollars(0n),
336  //     'should return the correct value'
337  //   );
338  
339  //   t.deepEqual(
340  //     poolCollateralTypes.get('Dollars').issuer,
341  //     dollarIssuer,
342  //     'should return the Dollar issuer type'
343  //   );
344  
345  //   const getLiAtomsAmount = payment => LiAtomsIssuer.getAmountOf(payment);
346  //   const getLiDollarsAmount = payment => LiDollarsIssuer.getAmountOf(payment);
347  
348  //   const liAtomsPayment = deployCollateralSeat.getPayout('LiAtoms');
349  
350  //   t.deepEqual(
351  //     await getLiAtomsAmount(liAtomsPayment),
352  //     liAtoms(initialAtoms),
353  //     'should pay out all expected tokens to the depositer'
354  //   );
355  
356  //   t.deepEqual(await getLiAtomsAmount(liAtomsPayment), liAtoms(initialAtoms));
357  
358  //   const deployDollarsProposal = harden({
359  //     give: {
360  //       Dollars: dollars(initialDollars)
361  //     },
362  //     want: {
363  //       LiDollars: liDollars(initialDollars)
364  //     }
365  //   });
366  
367  //   /**
368  //    * @type {UserSeat}
369  //    */
370  
371  //   const deployDollarsSeat = await E(zoe).offer(
372  //     await E(marketManagerFacet).deployInitialCollateral(),
373  //     deployDollarsProposal,
374  //     { Dollars: dollarMint.mintPayment(dollars(initialDollars)) }
375  //   );
376  
377  //   await deployCollateralSeat.getOfferResult();
378  //   const liDollarsPayment = deployDollarsSeat.getPayout('LiDollars');
379  
380  //   t.deepEqual(
381  //     await getLiDollarsAmount(liDollarsPayment),
382  //     liDollars(initialDollars),
383  //     'should pay out all expected tokens to the depositer'
384  //   );
385  
386  //   // Investigate: THESE TESTS GET STALE.
387  //   // We should be able to use the same .poolCollateralTypes store every time.
388  //   // This test is working, but we should be able to use the .getStore() returned in the initial offerResult L#231
389  
390  //   t.deepEqual(
391  //     await poolCollateralTypes.get('Dollars').totalSupply,
392  //     dollars(initialDollars)
393  //   );
394  
395  //   const additionalAtoms = 5000n;
396  
397  //   const deployMoreAtomsSeat = await E(zoe).offer(
398  //     await E(marketManagerFacet).deployInitialCollateral(),
399  //     harden({
400  //       give: {
401  //         Atoms: atoms(additionalAtoms)
402  //       },
403  //       want: {
404  //         LiAtoms: liAtoms(additionalAtoms)
405  //       }
406  //     }),
407  //     { Atoms: atomMint.mintPayment(atoms(additionalAtoms)) }
408  //   );
409  
410  //   await deployMoreAtomsSeat.getOfferResult();
411  //   const liAtomsPaymentTwo = deployMoreAtomsSeat.getPayout('LiAtoms');
412  
413  //   t.deepEqual(
414  //     await getLiAtomsAmount(liAtomsPaymentTwo),
415  //     liAtoms(additionalAtoms),
416  //     'Payment amount should contain the correct amount of LiAtoms'
417  //   );
418  
419  //   t.deepEqual(
420  //     await poolCollateralTypes.get('Atoms').totalSupply,
421  //     atoms(initialAtoms + additionalAtoms),
422  //     'poolCollateralTypes store should update the totalSupply of Dollars to equal the updated value.'
423  //   );
424  
425  //   const additionalDollars = 1250000n;
426  
427  //   const deployMoreDollarsSeat = await E(zoe).offer(
428  //     await E(marketManagerFacet).deployInitialCollateral(),
429  //     harden({
430  //       give: {
431  //         Dollars: dollars(additionalDollars)
432  //       },
433  //       want: {
434  //         LiDollars: liDollars(additionalDollars)
435  //       }
436  //     }),
437  //     { Dollars: dollarMint.mintPayment(dollars(additionalDollars)) }
438  //   );
439  
440  //   const liDollarsPaymentTwo = deployMoreDollarsSeat.getPayout('LiDollars');
441  
442  //   t.deepEqual(
443  //     await getLiDollarsAmount(liDollarsPaymentTwo),
444  //     liDollars(additionalDollars),
445  //     'Payment amount should contain the correct amount of LiDollars'
446  //   );
447  
448  //   t.deepEqual(
449  //     await poolCollateralTypes.get('Dollars').totalSupply,
450  //     dollars(initialDollars + additionalDollars),
451  //     'poolCollateralTypes store should update the totalSupply of Dollars to equal the updated value.'
452  //   );
453  // });