poolDirector.js
1 /* eslint-disable no-shadow */ 2 /* eslint-disable no-use-before-define */ 3 import { makeSubscriptionKit } from '@agoric/notifier'; 4 import { M } from '@agoric/store'; 5 import { makeScalarBigMapStore as makeStore } from '@agoric/vat-data'; 6 import { saveAllIssuers } from '@agoric/zoe/src/contractSupport'; 7 import { Far } from '@endo/marshal'; 8 import { Fn } from '../data.types.js'; 9 import { runAddCollateralToPool } from './accounts'; 10 import { 11 makeMint, 12 poolManagerHelpers as helpers, 13 yieldMints 14 } from './shared/async'; 15 import { 16 createStore, 17 lensProp, 18 merge, 19 trace, 20 view 21 } from './shared/utils/general'; 22 import { createGiveShape } from './shared/utils/offers.js'; 23 import { 24 poolManagerReducer, 25 initPublicState, 26 onAddIssuer, 27 SET_MARKET_PARAMETERS 28 } from './shared/state'; 29 30 /** 31 * @type {ContractStartFn} 32 */ 33 const start = async (zcf, privateArgs) => { 34 const { brands } = await zcf.getTerms(); 35 36 const initialAdminState = { 37 poolSeat: await zcf.makeEmptySeatKit().zcfSeat, 38 mints: [], 39 metrics: {}, 40 activeAccountsStore: makeStore('poolManager - active accounts store'), 41 userStore: makeStore('poolManager - personal account store'), 42 zcf, 43 reallocate: zcf.reallocate 44 }; 45 const adminStore = createStore(poolManagerReducer, initialAdminState); 46 47 const runMakePoolManagerResult = store => seat => 48 runAddCollateralToPool 49 .chain(() => Fn(() => makePoolManagerResult(store))) 50 .run(merge(store.getState(), { userSeat: seat })); 51 52 const runHandleBorrow = () => { 53 // TG: need to (finish) implementation --- GOES IN ./accounts.js file 54 // 55 // existing code from removed contract.js file 56 // ############################################ 57 // const calculateMaxBorrowValue = (balances = []) => 58 // balances.reduceRight((acc, val) => acc + val.maxAllowed.value, 0n); 59 // const runValidateAccountBalances = runGetUsersLtv() 60 // .map(calculateMaxBorrowValue) 61 // .chain(runCheckCurrentLtv); 62 // const borrow = store => seat => 63 // runValidateAccountBalances 64 // .run(merge(contractAdminState, { userSeat: seat, userStore: store })) 65 // .fold(handleError('Error handling borrow.'), () => 66 // accountOfferResult(store) 67 // ); 68 }; 69 70 const runMakeAccountResult = adminStore => store => seat => 71 runAddCollateralToPool 72 .chain(() => Fn(env => accountOfferResult(env.userStore))) 73 .map(trace('after makeing accountOfferResult')) 74 .run( 75 merge(adminStore.getState(), { 76 userSeat: seat, 77 userStore: store 78 }) 79 ); 80 81 const publicState = initPublicState(); 82 83 const initializePoolConfiguration = 84 store => 85 async ( 86 marketKeyword, 87 marketIssuer, 88 interestRateState, 89 subscriptionKit = makeSubscriptionKit() 90 ) => { 91 const mints = store.getSlice('mints'); 92 93 store.dispatch({ 94 type: SET_MARKET_PARAMETERS, 95 payload: { 96 key: marketKeyword, 97 ...{ 98 ...interestRateState, 99 collateralIssuer: marketIssuer, 100 collateralBrand: marketIssuer.getBrand(), 101 marketPubisher: subscriptionKit.publication, 102 marketSubscription: subscriptionKit.subscription, 103 mint: view(lensProp(`Li${marketKeyword}`), mints) 104 } 105 } 106 }); 107 108 helpers.getSubscriber(marketKeyword, store); 109 return makePoolManagerResult(adminStore); 110 }; 111 112 /** 113 * @function accountOfferResult 114 * @param {AccountStore} store 115 * @returns {ERef<MakeAccountOfferHandler>} offerResult 116 */ 117 const accountOfferResult = store => 118 Far('accountHolderFacet', { 119 getStore: () => store, 120 makeAddCollateralInvitation: () => 121 zcf.makeInvitation( 122 // eslint-disable-next-line no-use-before-define 123 runMakeAccountResult(adminStore)(store), 124 'add collateral to your balanace' 125 ), 126 makeBorrowInvitation: () => 127 zcf.makeInvitation( 128 // eslint-disable-next-line no-use-before-define 129 runHandleBorrow(store), 130 'add collateral to your balanace' 131 ) 132 }); 133 134 const makePoolManagerResult = store => 135 Far('pool director facet', { 136 makeOpenAccountInvitation: () => 137 zcf.makeInvitation( 138 runMakeAccountResult(store)(makeStore('new user account')), 139 'mint a payment', 140 undefined, 141 M.splitRecord({ give: M.or(...createGiveShape(brands)) }) 142 ), 143 getAccountStore: () => store.getState().userStore, 144 getAdminState: () => store.getState(), 145 getStore: () => store, 146 getSlice: () => store.getSlice, 147 setInitialPoolConfiguration: initializePoolConfiguration(store), 148 deployInitialLiquidity: () => 149 zcf.makeInvitation( 150 runMakePoolManagerResult(store), 151 'deployInitialCollateral' 152 ), 153 makePoolManagerInvitation: async issuerKeywordRecord => { 154 await saveAllIssuers(zcf, issuerKeywordRecord); 155 156 const issuersState = Object.entries(issuerKeywordRecord).reduceRight( 157 (acc, [key, val]) => { 158 publicState.dispatch(onAddIssuer({ keyword: key, issuer: val })); 159 return publicState.getState().issuers; 160 }, 161 {} 162 ); 163 164 await yieldMints(adminStore, publicState)( 165 makeMint(zcf), 166 issuersState.map(x => `Li${x.keyword}`) 167 ); 168 169 return makePoolManagerResult(store); 170 } 171 }); 172 173 return harden({ 174 creatorFacet: makePoolManagerResult(adminStore), 175 publicFacet: Far('public facet', { 176 getPublicState: () => publicState.getState(), 177 getIssuers: () => publicState.getSlice('issuers') 178 }) 179 }); 180 }; 181 harden(start); 182 export { start };