-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathpostal-service.contract.js
93 lines (80 loc) · 2.55 KB
/
postal-service.contract.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// @ts-check
import { E, Far } from '@endo/far';
import { M, mustMatch } from '@endo/patterns';
import { withdrawFromSeat } from '@agoric/zoe/src/contractSupport/zoeHelpers.js';
import { IssuerShape } from '@agoric/ertp/src/typeGuards.js';
/**
* @import {ContractMeta} from './@types/zoe-contract-facet.js';
* @import {ERef} from '@endo/far';
* @import {DepositFacet, Payment, Issuer} from '@agoric/ertp/src/types.js';
* @import {NameHub} from '@agoric/vats';
*/
const { keys, values } = Object;
/** @type {ContractMeta} */
export const meta = harden({
customTermsShape: { namesByAddress: M.remotable('namesByAddress') },
});
harden(meta);
// compatibility with an earlier contract metadata API
export const { customTermsShape } = meta;
harden(customTermsShape);
/**
* @typedef {object} PostalSvcTerms
* @property {NameHub} namesByAddress
*/
/** @param {ZCF<PostalSvcTerms>} zcf */
export const start = zcf => {
const { namesByAddress } = zcf.getTerms();
mustMatch(namesByAddress, M.remotable('namesByAddress'));
let issuerNumber = 1;
/**
* @param {string} addr
* @returns {ERef<DepositFacet>}
*/
const getDepositFacet = addr => {
assert.typeof(addr, 'string');
return E(namesByAddress).lookup(addr, 'depositFacet');
};
/**
* @param {string} addr
* @param {Payment} pmt
*/
const sendTo = (addr, pmt) => E(getDepositFacet(addr)).receive(pmt);
/**
* @param {string} recipient
* @param {Issuer[]} issuers
*/
const makeSendInvitation = (recipient, issuers) => {
assert.typeof(recipient, 'string');
mustMatch(issuers, M.arrayOf(IssuerShape));
for (const i of issuers) {
if (!Object.values(zcf.getTerms().issuers).includes(i)) {
zcf.saveIssuer(i, `Issuer${(issuerNumber += 1)}`);
}
}
/** @type {OfferHandler} */
const handleSend = async seat => {
const { give } = seat.getProposal();
const depositFacet = await getDepositFacet(recipient);
const payouts = await withdrawFromSeat(zcf, seat, give);
// XXX partial failure? return payments?
await Promise.all(
values(payouts).map(pmtP =>
E.when(pmtP, pmt => E(depositFacet).receive(pmt)),
),
);
seat.exit();
return `sent ${keys(payouts).join(', ')}`;
};
return zcf.makeInvitation(handleSend, 'send');
};
const publicFacet = Far('postalSvc', {
lookup: (...path) => E(namesByAddress).lookup(...path),
getDepositFacet,
sendTo,
makeSendInvitation,
});
return { publicFacet };
};
harden(start);
/** @typedef { typeof start } PostalServiceFn */