Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add depositToSeat, withdrawFromSeat #1680

Merged
merged 3 commits into from
Sep 10, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions packages/zoe/src/contractSupport/zoeHelpers.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// @ts-check
import '../../exported';

import { assert, details } from '@agoric/assert';
import { sameStructure } from '@agoric/same-structure';
import { E } from '@agoric/eventual-send';

import { MathKind } from '@agoric/ertp';
import { satisfiesWant } from '../contractFacet/offerSafety';
import { objectMap } from '../objArrayConversion';

import '../../exported';

export const defaultAcceptanceMsg = `The offer has been accepted. Once the contract has been completed, please check your payout`;

const getKeysSorted = obj =>
Expand Down Expand Up @@ -255,3 +255,69 @@ export const assertUsesNatMath = (zcf, brand) => {
details`issuer must use NAT amountMath`,
);
};

export const depositToSeatSuccessMsg = `Deposit and reallocation successful.`;

/**
* Deposit payments such that their amounts are reallocated to a seat.
* The `amounts` and `payments` records must have corresponding
* keywords.
*
* @param {ContractFacet} zcf
* @param {ZCFSeat} recipientSeat
* @param {AmountKeywordRecord} amounts
* @param {PaymentKeywordRecord} payments
* @returns {Promise<string>} `Deposit and reallocation successful.`
*/

export async function depositToSeat(zcf, recipientSeat, amounts, payments) {
assert(!recipientSeat.hasExited(), 'The recipientSeat cannot not be exited.');

// We will create a temporary offer to be able to escrow our payments
// with Zoe.
function reallocateAfterDeposit(tempSeat) {
// After the assets are deposited, reallocate them onto the recipient seat and
// exit the temporary seat. Note that the offerResult is the return value of this
// function, so this synchronous trade must happen before the
// offerResult resolves.
trade(
zcf,
{ seat: tempSeat, gains: {} },
{ seat: recipientSeat, gains: amounts },
);
tempSeat.exit();
return depositToSeatSuccessMsg;
}
const invitation = zcf.makeInvitation(
reallocateAfterDeposit,
'temporary seat for deposit',
);
const proposal = harden({ give: amounts });
harden(payments);
// To escrow the payment, we must get the Zoe Service facet and
// make an offer
const zoe = zcf.getZoeService();
const tempUserSeat = E(zoe).offer(invitation, proposal, payments);
// This will be a promise for the string: `Deposit and reallocation
// successful.` It will only fulfill after the assets have been
// successfully reallocated to the recipient seat.
return E(tempUserSeat).getOfferResult();
}

/**
* Withdraw payments from a seat. Note that withdrawing the amounts of
* the payments must not and cannot violate offer safety for the seat. The
* `amounts` and `payments` records must have corresponding keywords.
*
* @param {ContractFacet} zcf
* @param {ZCFSeat} seat
* @param {AmountKeywordRecord} amounts
* @returns {Promise<PaymentPKeywordRecord>}
*/
export async function withdrawFromSeat(zcf, seat, amounts) {
assert(!seat.hasExited(), 'The seat cannot be exited.');
const { zcfSeat: tempSeat, userSeat: tempUserSeatP } = zcf.makeEmptySeatKit();
trade(zcf, { seat: tempSeat, gains: amounts }, { seat, gains: {} });
tempSeat.exit();
return E(tempUserSeatP).getPayouts();
}