/ contract / src / poolDirector.js
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 };