@agoric/zoe 0.26.3-dev-121b677.0 → 0.26.3-dev-d2ea4b4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/zoe",
3
- "version": "0.26.3-dev-121b677.0+121b677",
3
+ "version": "0.26.3-dev-d2ea4b4.0+d2ea4b4",
4
4
  "description": "Zoe: the Smart Contract Framework for Offer Enforcement",
5
5
  "type": "module",
6
6
  "main": "./src/zoeService/zoe.js",
@@ -43,17 +43,20 @@
43
43
  },
44
44
  "homepage": "https://github.com/Agoric/agoric-sdk#readme",
45
45
  "dependencies": {
46
- "@agoric/assert": "0.6.1-dev-121b677.0+121b677",
47
- "@agoric/ertp": "0.16.3-dev-121b677.0+121b677",
48
- "@agoric/internal": "0.3.3-dev-121b677.0+121b677",
49
- "@agoric/notifier": "0.6.3-dev-121b677.0+121b677",
50
- "@agoric/store": "0.9.3-dev-121b677.0+121b677",
51
- "@agoric/swingset-liveslots": "0.10.3-dev-121b677.0+121b677",
52
- "@agoric/swingset-vat": "0.32.3-dev-121b677.0+121b677",
53
- "@agoric/time": "0.3.3-dev-121b677.0+121b677",
54
- "@agoric/vat-data": "0.5.3-dev-121b677.0+121b677",
46
+ "@agoric/assert": "0.6.1-dev-d2ea4b4.0+d2ea4b4",
47
+ "@agoric/base-zone": "0.1.1-dev-d2ea4b4.0+d2ea4b4",
48
+ "@agoric/ertp": "0.16.3-dev-d2ea4b4.0+d2ea4b4",
49
+ "@agoric/internal": "0.3.3-dev-d2ea4b4.0+d2ea4b4",
50
+ "@agoric/notifier": "0.6.3-dev-d2ea4b4.0+d2ea4b4",
51
+ "@agoric/store": "0.9.3-dev-d2ea4b4.0+d2ea4b4",
52
+ "@agoric/swingset-liveslots": "0.10.3-dev-d2ea4b4.0+d2ea4b4",
53
+ "@agoric/swingset-vat": "0.32.3-dev-d2ea4b4.0+d2ea4b4",
54
+ "@agoric/time": "0.3.3-dev-d2ea4b4.0+d2ea4b4",
55
+ "@agoric/vat-data": "0.5.3-dev-d2ea4b4.0+d2ea4b4",
56
+ "@agoric/zone": "0.2.3-dev-d2ea4b4.0+d2ea4b4",
55
57
  "@endo/bundle-source": "^3.0.2",
56
58
  "@endo/captp": "^4.0.2",
59
+ "@endo/common": "^1.0.2",
57
60
  "@endo/eventual-send": "^1.1.0",
58
61
  "@endo/far": "^1.0.2",
59
62
  "@endo/import-bundle": "^1.0.2",
@@ -64,7 +67,7 @@
64
67
  "yargs-parser": "^21.1.1"
65
68
  },
66
69
  "devDependencies": {
67
- "@agoric/kmarshal": "0.1.1-dev-121b677.0+121b677",
70
+ "@agoric/kmarshal": "0.1.1-dev-d2ea4b4.0+d2ea4b4",
68
71
  "@endo/init": "^1.0.2",
69
72
  "ava": "^5.3.0",
70
73
  "c8": "^7.13.0",
@@ -137,5 +140,5 @@
137
140
  "typeCoverage": {
138
141
  "atLeast": 84.82
139
142
  },
140
- "gitHead": "121b67747aaa842adff618c610dbb0835d88cc33"
143
+ "gitHead": "d2ea4b46b9efa61e97eec8711830d9fdd741ca55"
141
144
  }
@@ -7,6 +7,14 @@ type IssuerOptionsRecord = import('@agoric/ertp').IssuerOptionsRecord;
7
7
  */
8
8
  type Completion = any;
9
9
  type ZCFMakeEmptySeatKit = (exit?: ExitRule | undefined) => ZcfSeatKit;
10
+
11
+ type MakeInvitation = <Result>(
12
+ offerHandler: OfferHandler<Result>,
13
+ description: string,
14
+ customDetails?: object,
15
+ proposalShape?: Pattern,
16
+ ) => Promise<Invitation<R, A>>;
17
+
10
18
  /**
11
19
  * Zoe Contract Facet
12
20
  *
@@ -54,12 +62,7 @@ type ZCF<CT extends unknown = Record<string, unknown>> = {
54
62
  * getting in the `customDetails`. `customDetails` will be
55
63
  * placed in the details of the invitation.
56
64
  */
57
- makeInvitation: <Result>(
58
- offerHandler: OfferHandler<Result>,
59
- description: string,
60
- customDetails?: object,
61
- proposalShape?: Pattern,
62
- ) => Promise<Invitation<R, A>>;
65
+ makeInvitation: MakeInvitation;
63
66
  shutdown: (completion: Completion) => void;
64
67
  shutdownWithFailure: ShutdownWithFailure;
65
68
  getZoeService: () => ERef<ZoeService>;
@@ -54,6 +54,8 @@ export {
54
54
  } from './ratio.js';
55
55
 
56
56
  export * from './durability.js';
57
+ export * from './prepare-ownable.js';
58
+ export * from './prepare-revocable.js';
57
59
  export * from './priceAuthority.js';
58
60
  export * from './priceQuote.js';
59
61
  export * from './statistics.js';
@@ -0,0 +1,94 @@
1
+ import { M } from '@endo/patterns';
2
+ import { OfferHandlerI } from '../typeGuards.js';
3
+ import { prepareRevocableKit } from './prepare-revocable.js';
4
+
5
+ const TransferProposalShape = M.splitRecord({
6
+ give: {},
7
+ want: {},
8
+ exit: {
9
+ onDemand: null,
10
+ },
11
+ });
12
+
13
+ /**
14
+ * @typedef {object} OwnableOptions
15
+ * @property {string} [uInterfaceName]
16
+ * The `interfaceName` of the underlying interface guard.
17
+ * Defaults to the `uKindName`.
18
+ */
19
+
20
+ /**
21
+ * @template {any} [U=any]
22
+ * @param {import('@agoric/base-zone').Zone} zone
23
+ * @param {MakeInvitation} makeInvitation
24
+ * A function with the same behavior as `zcf.makeInvitation`.
25
+ * A contract will normally just extract it from its own zcf using the
26
+ * argument expression
27
+ * ```js
28
+ * (...args) => zcf.makeInvitation(...args)
29
+ * ```
30
+ * See ownable-counter.js for the canonical example.
31
+ * @param {string} uKindName
32
+ * The `kindName` of the underlying exo class
33
+ * @param {(string|symbol)[]} uMethodNames
34
+ * The method names of the underlying exo class that should be represented
35
+ * by transparently-forwarding methods of the wrapping ownable object.
36
+ * @param {OwnableOptions} [options]
37
+ * @returns {(underlying: U) => U}
38
+ */
39
+ export const prepareOwnable = (
40
+ zone,
41
+ makeInvitation,
42
+ uKindName,
43
+ uMethodNames,
44
+ options = {},
45
+ ) => {
46
+ const { uInterfaceName = uKindName } = options;
47
+ const makeRevocableKit = prepareRevocableKit(zone, uKindName, uMethodNames, {
48
+ uInterfaceName,
49
+ extraMethodGuards: {
50
+ makeTransferInvitation: M.call().returns(M.promise()),
51
+ },
52
+ extraMethods: {
53
+ makeTransferInvitation() {
54
+ const { underlying } = this.state;
55
+ const { revoker } = this.facets;
56
+ const customDetails = underlying.getInvitationCustomDetails();
57
+ // eslint-disable-next-line no-use-before-define
58
+ const transferHandler = makeTransferHandler(underlying);
59
+
60
+ const invitation = makeInvitation(
61
+ transferHandler,
62
+ 'transfer',
63
+ customDetails,
64
+ TransferProposalShape,
65
+ );
66
+ revoker.revoke();
67
+ return invitation;
68
+ },
69
+ },
70
+ });
71
+
72
+ const makeTransferHandler = zone.exoClass(
73
+ 'TransferHandler',
74
+ OfferHandlerI,
75
+ underlying => ({
76
+ underlying,
77
+ }),
78
+ {
79
+ handle(seat) {
80
+ const { underlying } = this.state;
81
+ const { revocable } = makeRevocableKit(underlying);
82
+ seat.exit();
83
+ return revocable;
84
+ },
85
+ },
86
+ );
87
+
88
+ const makeOwnable = underlying => {
89
+ const { revocable } = makeRevocableKit(underlying);
90
+ return revocable;
91
+ };
92
+ return harden(makeOwnable);
93
+ };
94
+ harden(prepareOwnable);
@@ -0,0 +1,137 @@
1
+ import { M } from '@endo/patterns';
2
+ import { fromUniqueEntries } from '@endo/common/from-unique-entries.js';
3
+
4
+ const { Fail, quote: q } = assert;
5
+
6
+ /**
7
+ * @typedef {object} Revoker
8
+ * @property {() => boolean} revoke
9
+ */
10
+
11
+ /**
12
+ * @template {any} [U=any]
13
+ * @typedef {object} RevocableKit
14
+ * @property {Revoker} revoker
15
+ * @property {U} revocable
16
+ * Forwards to the underlying exo object, until revoked
17
+ */
18
+
19
+ /**
20
+ * @template [U=any]
21
+ * @typedef {object} RevocableKitThis
22
+ * @property {RevocableKit<U>} facets
23
+ * @property {{ underlying: U }} state
24
+ */
25
+
26
+ /**
27
+ * @template {any} [U=any]
28
+ * @typedef {object} RevocableKitOptions
29
+ * @property {string} [uInterfaceName]
30
+ * The `interfaceName` of the underlying interface guard.
31
+ * Defaults to the `uKindName`.
32
+ * @property {Record<
33
+ * string|symbol,
34
+ * import('@endo/patterns').MethodGuard
35
+ * >} [extraMethodGuards]
36
+ * For guarding the `extraMethods`, if you include them below. These appear
37
+ * only on the synthesized interface guard for the revocable caretaker, and
38
+ * do not necessarily correspond to any method of the underlying.
39
+ * @property {Record<
40
+ * string|symbol,
41
+ * (this: RevocableKitThis<U>, ...args: any[]) => any
42
+ * >} [extraMethods]
43
+ * Extra methods adding behavior only to the revocable caretaker, and
44
+ * do not necessarily correspond to any methods of the underlying.
45
+ */
46
+
47
+ /**
48
+ * Make an exo class kit for wrapping an underlying exo class,
49
+ * where the wrapper is a revocable forwarder
50
+ *
51
+ * @template {any} [U=any]
52
+ * @param {import('@agoric/base-zone').Zone} zone
53
+ * @param {string} uKindName
54
+ * The `kindName` of the underlying exo class
55
+ * @param {(string|symbol)[]} uMethodNames
56
+ * The method names of the underlying exo class that should be represented
57
+ * by transparently-forwarding methods of the revocable caretaker.
58
+ * @param {RevocableKitOptions} [options]
59
+ * @returns {(underlying: U) => RevocableKit<U>}
60
+ */
61
+ export const prepareRevocableKit = (
62
+ zone,
63
+ uKindName,
64
+ uMethodNames,
65
+ options = {},
66
+ ) => {
67
+ const {
68
+ uInterfaceName = uKindName,
69
+ extraMethodGuards = undefined,
70
+ extraMethods = undefined,
71
+ } = options;
72
+ const RevocableIKit = harden({
73
+ revoker: M.interface(`${uInterfaceName}_revoker`, {
74
+ revoke: M.call().returns(M.boolean()),
75
+ }),
76
+ revocable: M.interface(
77
+ `${uInterfaceName}_revocable`,
78
+ {
79
+ ...extraMethodGuards,
80
+ },
81
+ {
82
+ defaultGuards: 'raw',
83
+ },
84
+ ),
85
+ });
86
+
87
+ const revocableKindName = `${uKindName}_caretaker`;
88
+
89
+ const makeRevocableKit = zone.exoClassKit(
90
+ revocableKindName,
91
+ RevocableIKit,
92
+ underlying => ({
93
+ underlying,
94
+ }),
95
+ {
96
+ revoker: {
97
+ revoke() {
98
+ const { state } = this;
99
+ if (state.underlying === undefined) {
100
+ return false;
101
+ }
102
+ state.underlying = undefined;
103
+ return true;
104
+ },
105
+ },
106
+ revocable: {
107
+ ...fromUniqueEntries(
108
+ uMethodNames.map(name => [
109
+ name,
110
+ {
111
+ // Use concise method syntax for exo methods
112
+ [name](...args) {
113
+ // @ts-expect-error normal exo-this typing confusion
114
+ const { underlying } = this.state;
115
+ underlying !== undefined ||
116
+ Fail`${q(revocableKindName)} revoked`;
117
+ return underlying[name](...args);
118
+ },
119
+ // @ts-expect-error using possible symbol as index type
120
+ }[name],
121
+ ]),
122
+ ),
123
+ ...extraMethods,
124
+ },
125
+ },
126
+ {
127
+ stateShape: {
128
+ underlying: M.opt(M.remotable('underlying')),
129
+ },
130
+ },
131
+ );
132
+
133
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
134
+ // @ts-ignore parameter confusion
135
+ return makeRevocableKit;
136
+ };
137
+ harden(prepareRevocableKit);