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 };