reader.js
1 /** 2 * @file shared functions used when operating with the reader monad. 3 */ 4 import { AmountMath } from '@agoric/ertp'; 5 import { Fn } from '../../data.types.js'; 6 import { 7 formatHeadOffer, 8 formatOfferSide, 9 handleBasicExchange 10 } from './utils/offers.js'; 11 import { actionTypes } from './state/index.js'; 12 13 const { ask } = Fn; 14 15 const initOrSet = 16 store => 17 ({ keyword, brand, value, ...rest }) => 18 !store.has(keyword) 19 ? store.init(keyword, { 20 value, 21 brand, 22 ...rest 23 }) 24 : store.set(keyword, { 25 totalSupply: store.get(keyword).totalSupply + value, 26 ...rest 27 }); 28 29 const runGetWantAmount = () => 30 ask.map(({ userSeat }) => formatHeadOffer(userSeat.getProposal().want)); 31 32 const runGetGiveAmounts = () => 33 ask.map(env => formatOfferSide(env.userSeat.getProposal().give)); 34 const runGetWantAmounts = () => 35 ask.map(env => formatOfferSide(env.userSeat.getProposal().want)); 36 37 const runGetGiveAmount = () => 38 ask.map(({ userSeat }) => formatHeadOffer(userSeat.getProposal().give)); 39 /** 40 * @description the resulting allocations held by an adminSeat following an exchange. 41 * @typedef {Object <Allocation, Allocation>} ResultAdminAllocations 42 */ 43 /** 44 * 45 * @function runIncrementAdmin 46 * @returns {ReturnType <ResultAdminAllocations>} the resulting allocations held by an adminSeat following an exchange. 47 */ 48 const runIncrementAdmin = () => 49 ask.map(({ userSeat, poolSeat }) => handleBasicExchange(poolSeat, userSeat)); 50 51 /** 52 * @function runReallocate 53 * @returns {ReturnType <Reallocate<UserSeat, ZCFSeat>>} 54 */ 55 const runReallocate = () => 56 ask.map(({ zcf, userSeat, poolSeat }) => zcf.reallocate(userSeat, poolSeat)); 57 58 /** 59 * @function runExitUserSeat 60 * @returns {void} succesfully exit will return void. 61 * @description exits the userSeat from an offer handler. 62 */ 63 const runExitUserSeat = () => ask.map(({ userSeat }) => userSeat.exit()); 64 65 const runGetIssuerRecord = () => 66 ask.map(state => ({ ...state, ...state.zcfMint.getIssuerRecord() })); 67 68 const runPublishMarketEvent = giveObject => 69 ask.map(env => 70 env[giveObject.keyword].marketPubisher.updateState({ 71 type: actionTypes.private.poolManager.SUPPLY, 72 payload: { ...giveObject, accountId: env.userStore.get('id').accountId } 73 }) 74 ); 75 76 const handleUpdateUserStore = 77 (userStore, accountId) => 78 ({ keyword, brand, value }) => 79 userStore.has(keyword) 80 ? userStore.set( 81 keyword, 82 harden({ 83 accountId, 84 supplied: AmountMath.add( 85 userStore.get(keyword).supplied, 86 AmountMath.make(brand, value) 87 ) 88 }) 89 ) 90 : userStore.init( 91 keyword, 92 harden({ 93 accountId, 94 supplied: AmountMath.make(brand, value) 95 }) 96 ); 97 98 const runUpdateUserStore = giveObject => 99 ask.map(({ userStore }) => 100 handleUpdateUserStore(userStore, userStore.get('id').accountId)(giveObject) 101 ); 102 103 const runRecordUserDeposit = () => runGetGiveAmount().chain(runUpdateUserStore); 104 105 const runRecordAdminDeposit = () => 106 runGetGiveAmount().chain(runPublishMarketEvent); 107 108 const mergeReader = inner => Fn(x => ({ ...x, ...inner })); 109 110 const runMintTokens = ({ currentMint, value, keyword }) => 111 Fn.ask.map(env => 112 currentMint.mint.mintGains( 113 { 114 [keyword]: currentMint.makeAmount(value) 115 }, 116 env.userSeat 117 ) 118 ); 119 120 /** 121 * Flow 122 * 1. exchange user allocation into poolSeat. 123 * 2. grab the userSeat "want" property from offer. 124 * 3. find debt token mint requested. 125 * 4. mint debt tokens directly to the userSeat (at this point, the poolSeat and userSeat both have their staged allocations) 126 */ 127 128 const runPrepareMint = ({ keyword, value }) => 129 Fn.ask.map(env => ({ 130 currentMint: env[keyword.slice(2)].mint.mintDetails, 131 value, 132 keyword 133 })); 134 135 const runHandleDebtTokenMint = () => 136 runIncrementAdmin() 137 .chain(runGetWantAmount) 138 .chain(runPrepareMint) 139 .chain(runMintTokens); 140 141 // userStore creation or find process - START 142 // ###################################### 143 const handleFindOrCreateUserId = (userStore, activeAccountsStore) => 144 !userStore.has('id') 145 ? userStore.init( 146 'id', 147 harden({ 148 accountId: activeAccountsStore 149 }) 150 ) 151 : userStore; 152 153 const runFindUserAccount = activeAccountsLength => 154 Fn.ask.map(env => 155 handleFindOrCreateUserId(env.userStore, activeAccountsLength) 156 ); 157 const runGetActiveAccountLength = Fn(env => env.activeAccountsStore.getSize()); 158 159 const runAccountStoreFns = runGetActiveAccountLength.chain(runFindUserAccount); 160 // ###################################### 161 // userStore creation or find process - END 162 163 export { 164 mergeReader, 165 initOrSet, 166 runAccountStoreFns, 167 runGetIssuerRecord, 168 runHandleDebtTokenMint, 169 runGetWantAmount, 170 runIncrementAdmin, 171 runReallocate, 172 runExitUserSeat, 173 runGetGiveAmount, 174 runGetGiveAmounts, 175 runGetWantAmounts, 176 runRecordAdminDeposit, 177 runRecordUserDeposit 178 };