-
Notifications
You must be signed in to change notification settings - Fork 215
/
attestation.js
130 lines (108 loc) · 3.67 KB
/
attestation.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// @ts-check
import { AmountMath } from '@agoric/ertp';
import { E } from '@agoric/eventual-send';
import { Far } from '@agoric/marshal';
import { makePromiseKit } from '@agoric/promise-kit';
import '../../../exported.js';
import { setupAttestation as setupReturnableAttestation } from './returnable/returnableNFT.js';
import { makeStoredTime } from './storedTime.js';
import { assertPrerequisites } from './prerequisites.js';
import { makeGetAttMaker } from './attMaker.js';
const { details: X } = assert;
/**
* @param {ContractFacet} zcf
* @param {Brand} underlyingBrand
* @param {string} returnableAttName
*/
export const makeAttestationFacets = async (
zcf,
underlyingBrand,
returnableAttName,
) => {
const authorityPromiseKit = makePromiseKit();
const { assetKind: underlyingAssetKind } = await E(
underlyingBrand,
).getDisplayInfo();
// AWAIT ///
const storedTime = makeStoredTime();
const empty = AmountMath.makeEmpty(underlyingBrand, underlyingAssetKind);
const returnableAttManager = await setupReturnableAttestation(
returnableAttName, // e.g. 'BldAttLoc'
empty,
zcf,
);
// AWAIT ///
/** @type {GetLiened} */
const getLiened = (address, currentTime, brand) => {
assert(
brand === underlyingBrand,
X`This contract can only make attestations for ${brand}`,
);
storedTime.updateTime(currentTime);
return returnableAttManager.getLienAmount(address);
};
// IMPORTANT: only expose this function to the owner of the address.
// This request *must* come from the owner of the address. Merely
// verifying that the address *could* add a lien is not sufficient.
// The owner must consent to adding a lien, and non-owners must not
// be able to initiate a lien for another account.
/**
* @param {string} address
* @param {Amount} amountToLien
*/
const makeAttestationsInternal = async (address, amountToLien) => {
amountToLien = AmountMath.coerce(underlyingBrand, amountToLien);
await assertPrerequisites(
authorityPromiseKit.promise,
storedTime,
getLiened,
underlyingBrand,
address,
amountToLien,
);
// AWAIT ///
const returnableAttPayment = returnableAttManager.addReturnableLien(
address,
amountToLien,
);
return harden(returnableAttPayment);
};
const publicFacet = Far('attestation publicFacet', {
makeReturnAttInvitation: returnableAttManager.makeReturnAttInvitation,
getIssuer: () => returnableAttManager.getIssuer(),
getBrand: () => returnableAttManager.getBrand(),
});
// IMPORTANT: The AttMaker should only be given to the owner of the
// address. Only the owner should be able to create attestations and
// the resulting liens on their underlying tokens.
/** @type {MakeAttMaker} */
const makeAttMaker = address => {
/** @type {AttMaker} */
return Far('attMaker', {
makeAttestation: amountToLien =>
makeAttestationsInternal(address, amountToLien),
makeReturnAttInvitation: returnableAttManager.makeReturnAttInvitation,
});
};
const getAttMaker = makeGetAttMaker(makeAttMaker);
// The authority is used to confirm that the underlying assets are escrowed appropriately.
const addAuthority = authority => authorityPromiseKit.resolve(authority);
const creatorFacet = Far('attestation creatorFacet', {
getLiened,
getAttMaker,
addAuthority,
});
return harden({ creatorFacet, publicFacet });
};
/**
* @param {ContractFacet} zcf
*/
const start = async zcf => {
const {
brands: { Underlying: underlyingBrand },
returnableAttName,
} = zcf.getTerms();
return makeAttestationFacets(zcf, underlyingBrand, returnableAttName);
};
harden(start);
export { start };