test-contract.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 import '@agoric/zoe/exported.js'; 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 { makeZoeKitForTest } from '@agoric/zoe/tools/setup-zoe.js'; 12 import { AmountMath, makeIssuerKit } from '@agoric/ertp'; 13 import { 14 invertRatio, 15 makeRatio, 16 multiplyBy 17 } from '@agoric/zoe/src/contractSupport/ratio.js'; 18 19 // @ts-ignore 20 const filename = new URL(import.meta.url).pathname; 21 const dirname = path.dirname(filename); 22 23 const contractPath = `${dirname}/../src/accounts.js`; 24 const setupMints = () => { 25 const { 26 brand: osmoBrand, 27 issuer: osmoIssuer, 28 mint: osmoMint 29 } = makeIssuerKit('Osmos'); 30 const osmos = x => AmountMath.make(osmoBrand, x); 31 const { 32 brand: atomBrand, 33 issuer: atomIssuer, 34 mint: atomMint 35 } = makeIssuerKit('atom'); 36 const { 37 brand: usdBrand, 38 issuer: usdIssuer, 39 mint: usdMint 40 } = makeIssuerKit('usd'); 41 const atoms = x => AmountMath.make(atomBrand, x); 42 const usd = x => AmountMath.make(usdBrand, x); 43 return { 44 atomBrand, 45 atomIssuer, 46 atomMint, 47 atoms, 48 osmoBrand, 49 osmoIssuer, 50 osmoMint, 51 osmos, 52 usdBrand, 53 usdIssuer, 54 usdMint, 55 usd 56 }; 57 }; 58 59 const { 60 atomBrand, 61 atomIssuer, 62 atomMint, 63 atoms, 64 osmoBrand, 65 osmoIssuer, 66 osmoMint, 67 osmos, 68 usdBrand, 69 usdIssuer, 70 usdMint, 71 usd 72 } = setupMints(); 73 const maxAtomRatio = makeRatio(1n, atomBrand, 7n, usdBrand); 74 75 const maxOsmoRation = makeRatio(10n, osmoBrand, 4n, usdBrand); 76 const osmoInUSD = invertRatio(maxOsmoRation); 77 const atomInUSD = invertRatio(maxAtomRatio); 78 const setupContract = async (contract, issuerRecord, startProps) => { 79 const { zoeService: zoe } = makeZoeKitForTest(makeFakeVatAdmin().admin); 80 81 // pack the contract 82 const bundle = await bundleSource(contract); 83 84 // install the contract 85 const installation = E(zoe).install(bundle); 86 87 const { creatorFacet, publicFacet, instance } = await E(zoe).startInstance( 88 installation, 89 issuerRecord, 90 startProps 91 ); 92 93 const LiOsmoIssuer = E(publicFacet).getLiOsmosIssuer(); 94 const LiOsmoBrand = await E(LiOsmoIssuer).getBrand(); 95 const LiAtomsIssuer = E(publicFacet).getLiAtomsIssuer(); 96 const LiAtomsBrand = await E(LiAtomsIssuer).getBrand(); 97 const LiUSDIssuer = await E(publicFacet).getLiUSDIssuer(); 98 const LiUSDBrand = await E(LiUSDIssuer).getBrand(); 99 100 return { 101 zoe, 102 creatorFacet, 103 publicFacet, 104 instance, 105 defaultIssuers: { 106 LiOsmoIssuer, 107 LiAtomsIssuer, 108 LiUSDIssuer 109 }, 110 defaultDebtAmounts: { 111 liAtoms: x => AmountMath.make(LiAtomsBrand, x), 112 liOsmos: x => AmountMath.make(LiOsmoBrand, x), 113 liUSD: x => AmountMath.make(LiUSDBrand, x) 114 } 115 }; 116 }; 117 118 test('zoe - mint payments', async t => { 119 // Let's get the liUSDIssuer from the contract so we can evaluate 120 // what we get as our payout 121 const issuerRecord = { 122 Osmos: osmoIssuer, 123 Atoms: atomIssuer, 124 USD: usdIssuer 125 }; 126 const config = { 127 Ratios: { 128 Atoms: atomInUSD, 129 Osmos: osmoInUSD, 130 USD: makeRatio(1n, usdBrand) 131 } 132 }; 133 134 const { 135 zoe, 136 creatorFacet, 137 defaultIssuers: { LiOsmoIssuer, LiAtomsIssuer }, 138 defaultDebtAmounts 139 } = await setupContract(contractPath, issuerRecord, config); 140 const { liAtoms, liOsmos, liUSD } = defaultDebtAmounts; 141 const calculateMaxBorrow = amount => multiplyBy(amount, atomInUSD); 142 const calculateMaxBorrowOsmo = amount => multiplyBy(amount, osmoInUSD); 143 144 t.deepEqual(calculateMaxBorrow(atoms(10n)), usd(70n)); 145 t.deepEqual(calculateMaxBorrowOsmo(osmos(100n)), usd(40n)); 146 147 // Alice makes an invitation for Bob that will give him 1000 tokens 148 const invitation = E(creatorFacet).makeInvitation(); 149 150 // Bob makes an offer using the invitation 151 const seat = await E(zoe).offer( 152 invitation, 153 { 154 give: { Osmos: osmos(100n) }, 155 want: { LiOsmos: liOsmos(100n) } 156 }, 157 { Osmos: osmoMint.mintPayment(osmos(100n)) } 158 ); 159 160 t.deepEqual(await seat.hasExited(), true); 161 162 const paymentP = await seat.getPayout('LiOsmos'); 163 const tokenPayoutAmount = await E(LiOsmoIssuer).getAmountOf(paymentP); 164 t.deepEqual(tokenPayoutAmount, liOsmos(100n)); 165 166 /** 167 * @type {ERef<AccountOfferResult>} 168 */ 169 const seatOneResult = await E(seat).getOfferResult(); 170 171 t.truthy( 172 seatOneResult.getStore, 173 'openAccount should return a reference to getStore' 174 ); 175 t.truthy( 176 seatOneResult.makeAddCollateralInvitation, 177 'openAccount should return a reference to addCollateral' 178 ); 179 180 t.deepEqual(seatOneResult.getStore().get('Osmos').value, 100n); 181 // Let's get the LiOsmoIssuer from the contract so we can evaluate 182 // what we get as our payout 183 184 const store = await E(creatorFacet).getStore(); 185 // t.deepEqual(store.get('Osmos'), { brand, value: 100n }); 186 187 // Bob makes an offer using the invitation 188 const seatTwo = await E(zoe).offer( 189 E(creatorFacet).makeInvitation(), 190 { 191 give: { Atoms: atoms(200n) }, 192 want: { LiAtoms: liAtoms(200n) } 193 }, 194 { Atoms: atomMint.mintPayment(atoms(200n)) } 195 ); 196 const seatTwoPayment = await seatTwo.getPayout('LiAtoms'); 197 const seatTwoPaymentAmt = await E(LiAtomsIssuer).getAmountOf(seatTwoPayment); 198 199 /** 200 * @type {ERef<AccountOfferResult>} 201 */ 202 const seatTwoResult = await seatTwo.getOfferResult(); 203 204 t.deepEqual(seatTwoPaymentAmt, liAtoms(200n)); 205 t.deepEqual(store.get('Atoms').value, 200n); 206 t.deepEqual(store.get('Atoms').brand, atomBrand); 207 208 t.deepEqual(await seatTwo.hasExited(), true); 209 210 const addCollateralSeat = await E(zoe).offer( 211 E(seatOneResult).makeAddCollateralInvitation(), 212 { 213 give: { Osmos: osmos(900n) }, 214 want: { LiOsmos: liOsmos(900n) } 215 }, 216 { Osmos: osmoMint.mintPayment(osmos(900n)) } 217 ); 218 await addCollateralSeat.getOfferResult(); 219 await E(zoe).offer( 220 E(seatOneResult).makeAddCollateralInvitation(), 221 { 222 give: { USD: usd(1200n) }, 223 want: { LiUSD: liUSD(1200n) } 224 }, 225 { USD: usdMint.mintPayment(usd(1200n)) } 226 ); 227 await addCollateralSeat.getOfferResult(); 228 229 t.deepEqual(seatOneResult.getStore().get('USD').value, 1200n); 230 t.deepEqual(store.get('USD'), AmountMath.make(usdBrand, 1200n)); 231 232 t.deepEqual(seatOneResult.getStore().get('Osmos').value, 1000n); 233 t.deepEqual(store.get('Osmos').value, 1000n); 234 235 const addCollateralToSeatTwo = await E(zoe).offer( 236 E(seatTwoResult).makeAddCollateralInvitation(), 237 { 238 give: { Osmos: osmos(1200n) }, 239 want: { LiOsmos: liOsmos(1200n) } 240 }, 241 { Osmos: osmoMint.mintPayment(osmos(1200n)) } 242 ); 243 const addCollateralToSeatTwoPayment = await addCollateralToSeatTwo.getPayout( 244 'LiOsmos' 245 ); 246 const addCollateralToSeatTwoPaymentValue = await E(LiOsmoIssuer).getAmountOf( 247 addCollateralToSeatTwoPayment 248 ); 249 // seatTwo :: adding ATOM 250 await E(zoe).offer( 251 E(seatOneResult).makeAddCollateralInvitation(), 252 { 253 give: { Atoms: atoms(1000n) }, 254 want: { LiAtoms: liAtoms(1000n) } 255 }, 256 { Atoms: atomMint.mintPayment(atoms(1000n)) } 257 ); 258 t.deepEqual(addCollateralToSeatTwoPaymentValue, liOsmos(1200n)); 259 260 // borrow 261 const borrowFromSeatOne = await E(zoe).offer( 262 await E(seatOneResult).makeBorrowInvitation(), 263 { 264 want: { USD: AmountMath.make(usdBrand, 200n) } 265 } 266 ); 267 268 /** 269 * @type {ERef<AccountOfferResult>} 270 */ 271 const borrowResult = await E(borrowFromSeatOne).getOfferResult(); 272 273 t.deepEqual(!borrowResult.error === true, true); 274 275 // borrow 276 const borrowFromSeatTwo = await E(zoe).offer( 277 E(seatTwoResult).makeBorrowInvitation(), 278 { 279 want: { USD: AmountMath.make(usdBrand, 22200n) } 280 } 281 ); 282 283 /** 284 * @type {ERef<AccountOfferResult>} 285 */ 286 const borrowResultTwo = await E(borrowFromSeatTwo).getOfferResult(); 287 t.deepEqual(!borrowResultTwo.error === false, true); 288 });