/ contract / test / services.js
services.js
  1  import { makeFakeMarshaller } from '@agoric/notifier/tools/testSupports.js';
  2  import { makeFakeVatAdmin } from '@agoric/zoe/tools/fakeVatAdmin.js';
  3  import { makeZoeKitForTest } from '@agoric/zoe/tools/setup-zoe.js';
  4  import bundleSource from '@endo/bundle-source';
  5  import { E } from '@endo/eventual-send';
  6  import buildManualTimer from '../src/tools/manualTimer.js';
  7  import { makeFakeStorageKit } from '@agoric/internal/src/storage-test-utils.js';
  8  import { Far } from '@endo/far';
  9  import path from 'path';
 10  import { AmountMath, makeIssuerKit } from '@agoric/ertp';
 11  import { ONE_DAY, ONE_HOUR } from '../src/shared/utils/time.js';
 12  import { metricsTracker } from './test-metrics.js';
 13  
 14  const makeKit = name => makeIssuerKit(name);
 15  
 16  const setupIssuers = (issuers = ['ATOM', 'IST', 'BLD', 'USDC']) =>
 17    issuers.map(makeKit);
 18  
 19  const issuers = setupIssuers();
 20  const makeAmounts =
 21    ({ brand }) =>
 22    (x = 0n) =>
 23      AmountMath.make(brand, x);
 24  const [atoms, ist, bld, usdc] = issuers.map(makeAmounts);
 25  const [atomKit, istKit, bldKit, USDCKit] = issuers;
 26  const callFacet =
 27    facet =>
 28    (method, args = {}) =>
 29      E(facet)[method](args);
 30  
 31  const facetMethods = {
 32    public: {
 33      GET_PUBLIC_TOPICS: 'getPublicTopics',
 34      SAVE_ISSUERS: 'saveIssuers',
 35      GET_ISSUERS: 'getIssuers',
 36      UNDERWRITE_LOAN: 'underwriteLoan',
 37      GET_FUNDED_LOANS: 'getFundedLoans'
 38    }
 39  };
 40  
 41  const setupContract = async () => {
 42    const filename = new URL(import.meta.url).pathname;
 43    const dirname = path.dirname(filename);
 44  
 45    const contractPath = `${dirname}/../src/p2pLendingMarket/p2p.js`;
 46  
 47    const { admin: fakeVatAdmin, vatAdminState } = makeFakeVatAdmin();
 48    const { zoeService: zoe } = makeZoeKitForTest(fakeVatAdmin);
 49  
 50    const p2pBundle = await bundleSource(contractPath);
 51    vatAdminState.installBundle('b1-p2p', p2pBundle);
 52  
 53    const timerService = buildManualTimer();
 54    const p2pInstallation = await E(zoe).installBundleID('b1-p2p');
 55    const contractInstance = await E(zoe).startInstance(
 56      p2pInstallation,
 57      undefined, // @todo - add issuers?
 58      harden({
 59        timerService
 60      }),
 61      // @ts-ignore
 62      harden({
 63        storageNode: makeFakeStorageKit('p2pMetrics').rootNode,
 64        marshaller: Far('marshaller', {
 65          ...makeFakeMarshaller()
 66        })
 67      })
 68    );
 69  
 70    return {
 71      zoe,
 72      contractInstance,
 73      fakeVatAdmin,
 74      vatAdminState,
 75      timerService
 76    };
 77  };
 78  
 79  const setupLoanStateTwo = async t => {
 80    const KEYWORDS = {
 81      IST: 'IST',
 82      ATOM: 'ATOM'
 83    };
 84  
 85    const LOAN_EXPIRY = 5n;
 86  
 87    const { IST: istKeyword, ATOM: atomKeyword } = KEYWORDS;
 88  
 89    const { contractInstance, zoe, timerService } = await setupContract();
 90  
 91    const zoeIssuer = await E(zoe).getInvitationIssuer();
 92  
 93    const callCreatorFacet = callFacet(contractInstance.creatorFacet);
 94    const callPublicFacet = callFacet(contractInstance.publicFacet);
 95  
 96    const {
 97      public: {
 98        GET_PUBLIC_TOPICS,
 99        GET_ISSUERS,
100        GET_FUNDED_LOANS,
101        SAVE_ISSUERS,
102        UNDERWRITE_LOAN
103      }
104    } = facetMethods;
105    const { metrics } = await callPublicFacet(GET_PUBLIC_TOPICS);
106    const tracker = await metricsTracker(t, contractInstance.publicFacet);
107    await callCreatorFacet(SAVE_ISSUERS, {
108      ATOM: atomKit.issuer,
109      IST: istKit.issuer,
110      BLD: bldKit.issuer,
111      USDC: USDCKit.issuer
112    });
113  
114    const getIssuers = () => callPublicFacet(GET_ISSUERS);
115    const getLength = ({ length }) => length;
116  
117    const aliceLoanTerms = {
118      collateralKey: 'ATOM',
119      collateralBrand: atomKit.brand,
120      debtKey: 'IST',
121      debtBrand: istKit.brand,
122      expiry: LOAN_EXPIRY,
123      loanToValue: 70n,
124      interestRate: 5n
125    };
126  
127    const aliceLoanInvitation = await callPublicFacet(
128      UNDERWRITE_LOAN,
129      aliceLoanTerms
130    );
131  
132    const aliceLoanDetails = await E(zoe).getInvitationDetails(
133      aliceLoanInvitation
134    );
135  
136    const firstLoanId = 'loan-0';
137  
138    const sevenThousandIST = ist(7000n);
139    const aliceLoanSeat = await E(zoe).offer(
140      aliceLoanInvitation,
141      {
142        give: { IST: sevenThousandIST },
143        want: {}
144      },
145      { IST: istKit.mint.mintPayment(sevenThousandIST) }
146    );
147  
148    await E(aliceLoanSeat).getOfferResult();
149  
150    const alicesSecondLoanInvitation = await callPublicFacet(
151      UNDERWRITE_LOAN,
152      harden({
153        ...aliceLoanTerms,
154        expiry: ONE_DAY
155      })
156    );
157    const aliceSecondLoanDetails = await E(zoe).getInvitationDetails(
158      alicesSecondLoanInvitation
159    );
160  
161    const aliceSecondLoanSeat = await E(zoe).offer(
162      alicesSecondLoanInvitation,
163      {
164        give: { IST: ist(7000n) },
165        want: {}
166      },
167      { IST: istKit.mint.mintPayment(ist(7000n)) }
168    );
169  
170    const [fundedLoan] = await callPublicFacet(GET_FUNDED_LOANS).then(res => {
171      return [...res.entries()].map(([key, value]) => {
172        return { key, value };
173      });
174    });
175    const borrowInvitation = fundedLoan.value.invitationMakers.makeFulfillLoan();
176  
177    const bobSeat = await E(zoe).offer(
178      borrowInvitation,
179      {
180        give: { ATOM: atoms(1000n) },
181        want: { IST: AmountMath.make(istKit.brand, 7000n) }
182      },
183      { ATOM: atomKit.mint.mintPayment(atoms(1000n)) }
184    );
185  
186    const borrowOfferResult = await E(bobSeat).getPayout('IST');
187  
188    const { loan: loanTopic } = fundedLoan.value.holder.getPublicTopics();
189  
190    const makeStoragePath = rootPath => childPath => `${rootPath}.${childPath}`;
191  
192    const loansStoragePath = makeStoragePath('p2pMetrics.loans');
193  
194    return {
195      callPublicFacet,
196      borrowInvitation,
197      facetMethods,
198      zoe,
199      contractInstance,
200      bobSeat,
201      aliceLoanSeat,
202      loansStoragePath,
203      tracker,
204      aliceSecondLoanSeat
205    };
206  };
207  
208  export { setupContract, setupLoanStateTwo, callFacet, facetMethods };