@agoric/deploy-script-support 0.11.0 → 0.11.1-upgrade-23-dev-bd79330.0.bd79330

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.
@@ -0,0 +1,386 @@
1
+ /**
2
+ * @file contract-control: install, upgrade, terminate, reset chain-storage,
3
+ * for a contract in a branch of agoricNames / chain-storage.
4
+ */
5
+
6
+ import { makeTracer } from '@agoric/internal/src/debug.js';
7
+ import { Fail, q } from '@endo/errors';
8
+ import { E, passStyleOf } from '@endo/far';
9
+ import { M, objectMap } from '@endo/patterns';
10
+
11
+ const trace = makeTracer('CCtrl');
12
+
13
+ /**
14
+ * @import {Zone} from '@agoric/base-zone';
15
+ * @import {ContractStartFunction, StartResult} from '@agoric/zoe/src/zoeService/utils.js';
16
+ * @import {Installation, Instance, IssuerKeywordRecord, ZoeService} from '@agoric/zoe';
17
+ * @import {Remote} from '@agoric/internal';
18
+ * @import {StorageNode} from '@agoric/internal/src/lib-chainStorage.js';
19
+ * @import {Board, NameHubKit} from '@agoric/vats';
20
+ * @import {ERef} from '@agoric/vow';
21
+ * @import {StartedInstanceKitWithLabel, StartUpgradable} from '@agoric/vats/src/core/types.js';
22
+ * @import {StartedInstanceKit} from '@agoric/vats/src/core/types.js';
23
+ */
24
+
25
+ /**
26
+ * @typedef {<SF extends ContractStartFunction>(instance: Instance<SF>, privateArgs: Parameters<SF>[1]) => void} UpdatePrivateArgs
27
+ */
28
+
29
+ const IssuerShape = M.remotable('Issuer');
30
+ const InstallationShape = M.remotable('Installation');
31
+ const PublicParts = harden({
32
+ label: M.string(),
33
+ instance: M.remotable('Instance'),
34
+ publicFacet: M.remotable('publicFacet'),
35
+ });
36
+ const BundleIdShape = M.string();
37
+ const VatUpgradeResultsShape = M.splitRecord({ incarnationNumber: M.number() });
38
+ const IssuersShape = M.recordOf(M.string(), IssuerShape);
39
+ const PrivateArgsOverridesShape = M.record();
40
+
41
+ const iface = M.interface('ContractControl', {
42
+ install: M.callWhen(M.string()).returns({
43
+ boardId: M.string(),
44
+ installation: InstallationShape,
45
+ }),
46
+ start: M.callWhen(
47
+ M.splitRecord(
48
+ { installation: InstallationShape },
49
+ {
50
+ issuers: IssuersShape,
51
+ privateArgsOverrides: PrivateArgsOverridesShape,
52
+ },
53
+ {}, // Refuse unsupported options
54
+ ),
55
+ ).returns(PublicParts),
56
+ installAndStart: M.callWhen(
57
+ M.splitRecord(
58
+ { bundleId: BundleIdShape },
59
+ {
60
+ issuers: IssuersShape,
61
+ privateArgsOverrides: PrivateArgsOverridesShape,
62
+ },
63
+ {}, // Refuse unsupported options
64
+ ),
65
+ ).returns(PublicParts),
66
+ getPublicFacet: M.call().returns(M.remotable('publicFacet')),
67
+ getCreatorFacet: M.call().returns(M.remotable('creatorFacet')),
68
+ upgrade: M.callWhen(
69
+ M.or(
70
+ BundleIdShape, // Backward compat with old signature
71
+ M.splitRecord(
72
+ { bundleId: BundleIdShape },
73
+ {
74
+ privateArgsOverrides: PrivateArgsOverridesShape,
75
+ },
76
+ {}, // Refuse unsupported options
77
+ ),
78
+ ),
79
+ ).returns(VatUpgradeResultsShape),
80
+ terminate: M.callWhen()
81
+ .optional(
82
+ M.splitRecord(
83
+ {},
84
+ { message: M.string(), target: M.string(), revoke: M.boolean() },
85
+ {}, // Refuse unsupported options
86
+ ),
87
+ )
88
+ .returns(),
89
+ pruneChainStorage: M.callWhen(
90
+ M.recordOf(M.string(), M.arrayOf(M.string())),
91
+ ).returns(M.number()),
92
+ revoke: M.call().returns(),
93
+ });
94
+
95
+ /**
96
+ * @param {Zone} zone
97
+ * @param {{
98
+ * agoricNamesAdmin: ERef<NameHubKit['nameAdmin']>,
99
+ * board: ERef<Board>,
100
+ * zoe: ERef<ZoeService>,
101
+ * startUpgradable: ERef<StartUpgradable>,
102
+ * updatePrivateArgs: ERef<UpdatePrivateArgs>
103
+ * }} svcs
104
+ */
105
+ export const prepareContractControl = (zone, svcs) => {
106
+ /** @template {ContractStartFunction} SF */
107
+ const makeMaker = () =>
108
+ zone.exoClass(
109
+ 'ContractControl',
110
+ iface,
111
+ /**
112
+ * Install by bundleId and publish to (the board and) agoricNames,
113
+ * replacing anything that was there before.
114
+ *
115
+ * Former installations can be reached from the board.
116
+ *
117
+ * @param {ContractControlOpts} initial
118
+ */
119
+ initial => ({
120
+ initialPrivateArgs:
121
+ initial.initialPrivateArgs || initial.kit?.privateArgs,
122
+ kit: undefined,
123
+ ...initial,
124
+ revoked: false,
125
+ }),
126
+ {
127
+ /** @param {string} bundleId */
128
+ async install(bundleId) {
129
+ const { name, revoked } = this.state;
130
+ trace(name, 'install', bundleId);
131
+ !revoked || Fail`revoked`;
132
+ const { zoe, board, agoricNamesAdmin } = svcs;
133
+ const installation = await E(zoe).installBundleID(bundleId);
134
+ const installationAdmin =
135
+ E(agoricNamesAdmin).lookupAdmin('installation');
136
+ await E(installationAdmin).update(name, installation);
137
+ const boardId = await E(board).getId(installation);
138
+ trace(name, 'installed', { bundleId, installation, boardId });
139
+ return { boardId, installation };
140
+ },
141
+
142
+ /**
143
+ * Start the contract; publish the instance to (the board and) agoricNames.
144
+ *
145
+ * @throws if already running
146
+ * @param {object} opts
147
+ * @param {Installation<SF>} opts.installation
148
+ * @param {IssuerKeywordRecord} [opts.issuers]
149
+ * @param {Partial<Parameters<SF>[1]>} [opts.privateArgsOverrides]
150
+ */
151
+ async start({ installation, issuers, privateArgsOverrides }) {
152
+ const { name, storageNode, revoked, initialPrivateArgs } = this.state;
153
+ !revoked || Fail`revoked`;
154
+ !this.state.kit || Fail`${name} already started`;
155
+ const { startUpgradable, board } = svcs;
156
+ const installationId = await E(board).getId(installation);
157
+ trace(name, 'startUpgradable', { installation, installationId });
158
+ const privateArgs = harden({
159
+ ...initialPrivateArgs,
160
+ storageNode,
161
+ ...privateArgsOverrides,
162
+ });
163
+ const kit = await E(startUpgradable)({
164
+ label: name,
165
+ installation,
166
+ issuerKeywordRecord: issuers,
167
+ // terms: customTerms,
168
+ privateArgs,
169
+ });
170
+ /** @type {StartedInstanceKitWithLabel<SF>} */
171
+ const fullKit = harden({ ...kit, privateArgs });
172
+ trace(name, 'started', objectMap(fullKit, passStyleOf));
173
+ this.state.kit = fullKit;
174
+
175
+ const { agoricNamesAdmin } = svcs;
176
+ const instanceAdmin = E(agoricNamesAdmin).lookupAdmin('instance');
177
+ await E(instanceAdmin).update(name, kit.instance);
178
+ const boardId = await E(board).getId(kit.instance);
179
+ trace(name, 'published', { boardId, installationId });
180
+
181
+ return harden({
182
+ label: name,
183
+ instance: kit.instance,
184
+ publicFacet: kit.publicFacet,
185
+ });
186
+ },
187
+
188
+ /**
189
+ * @param {object} opts
190
+ * @param {string} opts.bundleId
191
+ * @param {IssuerKeywordRecord} [opts.issuers]
192
+ * @param {Partial<Parameters<SF>[1]>} [opts.privateArgsOverrides]
193
+ */
194
+ async installAndStart({ bundleId, issuers, privateArgsOverrides }) {
195
+ trace(this.state.name, 'installAndStart');
196
+ !this.state.revoked || Fail`revoked`;
197
+ const { self } = this;
198
+ const { installation } = await self.install(bundleId);
199
+ return self.start({
200
+ installation,
201
+ issuers,
202
+ privateArgsOverrides,
203
+ });
204
+ },
205
+
206
+ /** @returns {StartResult<SF>['publicFacet']} */
207
+ getPublicFacet() {
208
+ const { name, revoked, kit } = this.state;
209
+ trace(name, 'getPublicFacet');
210
+ !revoked || Fail`revoked`;
211
+ if (!kit) throw Fail`${q(name)}: no StartedInstanceKit`;
212
+ return kit.publicFacet;
213
+ },
214
+
215
+ /** @returns {StartResult<SF>['creatorFacet']} */
216
+ getCreatorFacet() {
217
+ const { name, revoked, kit } = this.state;
218
+ trace(name, 'getCreatorFacet');
219
+ !revoked || Fail`revoked`;
220
+ if (!kit) throw Fail`${q(name)}: no StartedInstanceKit`;
221
+ return kit.creatorFacet;
222
+ },
223
+
224
+ /** @param {string | {bundleId: string; privateArgsOverrides?: Partial<Parameters<SF>[1]>; }} opts */
225
+ async upgrade(opts) {
226
+ if (typeof opts === 'string') opts = { bundleId: opts };
227
+ const { bundleId, privateArgsOverrides = {} } = opts;
228
+
229
+ const { updatePrivateArgs } = svcs;
230
+
231
+ const { name, revoked, kit, initialPrivateArgs } = this.state;
232
+ trace(name, 'upgrade', bundleId);
233
+ !revoked || Fail`revoked`;
234
+ if (!kit) throw Fail`${q(name)}: no StartedInstanceKit`;
235
+ const { privateArgs: previousPrivateArgs } = kit;
236
+ const privateArgs = {
237
+ ...initialPrivateArgs,
238
+ ...previousPrivateArgs,
239
+ ...privateArgsOverrides,
240
+ };
241
+ const result = await E(kit.adminFacet).upgradeContract(
242
+ bundleId,
243
+ privateArgs,
244
+ );
245
+ const newKit = harden({ ...kit, privateArgs });
246
+ trace(name, 'upgrade result', result);
247
+ this.state.kit = newKit;
248
+ await E(updatePrivateArgs)(kit.instance, privateArgs);
249
+ return result;
250
+ },
251
+
252
+ /**
253
+ * @param {object} opts
254
+ * @param {string} [opts.target] boardId to confirm is current
255
+ * @param {string} [opts.message] for termination error
256
+ * @param {boolean} [opts.revoke] neuter this object
257
+ */
258
+ async terminate(opts = {}) {
259
+ const { name, kit, revoked } = this.state;
260
+ trace(name, 'terminate', kit?.adminFacet, opts);
261
+ !revoked || Fail`revoked`;
262
+ const { target, message = 'terminated', revoke } = opts;
263
+ if (!kit) {
264
+ if (revoke) {
265
+ trace(name, 'revoked');
266
+ this.state.revoked = true;
267
+ return;
268
+ }
269
+ throw Fail`${q(name)}: no StartedInstanceKit`;
270
+ }
271
+
272
+ await null;
273
+ if (target) {
274
+ const current = await E(svcs.board).getId(kit.instance);
275
+ assert.equal(current, target);
276
+ }
277
+
278
+ try {
279
+ await E(kit.adminFacet).terminateContract(harden(Error(message)));
280
+ } catch (err) {
281
+ console.error('terminateContract failed; forgetting kit', err);
282
+ }
283
+ this.state.kit = undefined;
284
+ if (revoke) {
285
+ trace(name, 'revoked');
286
+ this.state.revoked = true;
287
+ }
288
+ const { agoricNamesAdmin } = svcs;
289
+ const instanceAdmin = E(agoricNamesAdmin).lookupAdmin('instance');
290
+ await E(instanceAdmin).delete(name);
291
+ },
292
+
293
+ /** @param {Record<string, string[]>} parentToChildren */
294
+ async pruneChainStorage(parentToChildren) {
295
+ const { name, storageNode, revoked } = this.state;
296
+ trace(
297
+ name,
298
+ 'pruneChainStorage',
299
+ Object.keys(parentToChildren).length,
300
+ );
301
+ !revoked || Fail`revoked`;
302
+
303
+ /** @param {string[]} path */
304
+ const makePathNode = path => {
305
+ /** @type {Promise<Remote<StorageNode>>} */
306
+ let node = Promise.resolve(storageNode);
307
+ for (const segment of path) {
308
+ node = E(node).makeChildNode(segment);
309
+ }
310
+ return node;
311
+ };
312
+
313
+ const prefix = await E(storageNode).getPath();
314
+ for (const parent of Object.keys(parentToChildren)) {
315
+ parent.startsWith(prefix) ||
316
+ Fail`${parent} must start with ${prefix}`;
317
+ }
318
+
319
+ let qty = 0;
320
+ for (const [parent, children] of Object.entries(parentToChildren)) {
321
+ trace(name, 'pruning', parent, children);
322
+ const suffix = parent.slice(prefix.length + '.'.length);
323
+ const segments = suffix ? suffix.split('.') : [];
324
+ const parentNode = makePathNode(segments);
325
+ // on failure, trace rather than aborting the whole job
326
+ await Promise.allSettled(
327
+ children.map(async k => {
328
+ await null;
329
+ try {
330
+ await E(
331
+ E(parentNode).makeChildNode(k, { sequence: false }),
332
+ ).setValue('');
333
+ qty += 1;
334
+ } catch (err) {
335
+ trace('rejected:', parent, k, err);
336
+ }
337
+ }),
338
+ );
339
+ }
340
+ trace('done');
341
+ return qty;
342
+ },
343
+
344
+ revoke() {
345
+ const { name, kit, revoked } = this.state;
346
+ trace(name, 'revoke', kit?.adminFacet);
347
+ !revoked || Fail`revoked`;
348
+
349
+ trace(name, 'revoked');
350
+ this.state.revoked = true;
351
+ },
352
+ },
353
+ );
354
+
355
+ /**
356
+ * @template {ContractStartFunction} [SF=ContractStartFunction]
357
+ * @typedef {ReturnType<ReturnType<typeof makeMaker<SF>>>} ContractControl
358
+ */
359
+
360
+ /** @type {<SF extends ContractStartFunction>(initial: ContractControlOpts<SF>) => ContractControl<SF>} */
361
+ const makeContractControl = makeMaker();
362
+
363
+ return makeContractControl;
364
+ };
365
+ harden(prepareContractControl);
366
+
367
+ /**
368
+ * @template {ContractStartFunction} [SF=ContractStartFunction]
369
+ * @typedef {object} ContractControlOpts
370
+ * @property {string} name contractName
371
+ * @property {Remote<StorageNode>} storageNode
372
+ * @property {StartedInstanceKit<SF> & { privateArgs?: Parameters<SF>[1] }} [kit]
373
+ * @property {Partial<Parameters<SF>[1]>} [initialPrivateArgs]
374
+ */
375
+
376
+ /** @typedef {ReturnType<typeof prepareContractControl>} MakeContractControl */
377
+
378
+ // Hack to allow extracting the generic result of MakeContractControl
379
+ // See https://github.com/microsoft/TypeScript/issues/62524
380
+
381
+ const maker = /** @type {MakeContractControl} */ (
382
+ /** @type {unknown} */ (undefined)
383
+ );
384
+ harden(maker);
385
+
386
+ /** @template {ContractStartFunction} [SF=ContractStartFunction] @typedef {ReturnType<typeof maker<SF>>} ContractControl */
@@ -0,0 +1,138 @@
1
+ /** @file core eval to deliver control of a contract to a smartWallet */
2
+
3
+ import { makeTracer } from '@agoric/internal/src/debug.js';
4
+ import { makeHeapZone } from '@agoric/zone';
5
+ import { Fail } from '@endo/errors';
6
+ import { E } from '@endo/eventual-send';
7
+ import { YMAX_CONTROL_WALLET_KEY } from '@agoric/portfolio-api/src/portfolio-constants.js';
8
+ import { prepareContractControl } from './contract-control.contract.js';
9
+
10
+ /**
11
+ * @import {ContractStartFunction} from '@agoric/zoe/src/zoeService/utils.js';
12
+ * @import {ChainStoragePresent} from './chain-info.core.js'
13
+ * @import {PostalServiceBoot} from './postal-service.core.js';
14
+ * @import {AttenuatedDepositPowers} from './attenuated-deposit.core.js';
15
+ * @import {ContractControlOpts, ContractControl, UpdatePrivateArgs} from './contract-control.contract.js';
16
+ * @import {PromiseSpaceOf} from '@agoric/vats/src/core/types.js';
17
+ * @import {BootstrapPowers} from '@agoric/vats/src/core/types.js';
18
+ */
19
+
20
+ /**
21
+ * @template {ContractStartFunction} SF
22
+ * @typedef {Omit<ContractControlOpts<SF>, 'storageNode'> & {controlAddress: string}} ContractControlDeliverOpts
23
+ */
24
+
25
+ /**
26
+ * @typedef {<SF extends ContractStartFunction>(opts: ContractControlDeliverOpts<SF>) => Promise<{delivered: Promise<void>, contractControl: ContractControl<SF>}>} DeliverContractControl
27
+ */
28
+
29
+ /**
30
+ * @typedef {PromiseSpaceOf<{ deliverContractControl: DeliverContractControl}>} ContractControlPowers
31
+ */
32
+
33
+ /**
34
+ * @param {BootstrapPowers &
35
+ * ChainStoragePresent &
36
+ * PostalServiceBoot &
37
+ * ContractControlPowers &
38
+ * AttenuatedDepositPowers
39
+ * } permitted
40
+ */
41
+ export const produceDeliverContractControl = async permitted => {
42
+ permitted.produce.deliverContractControl.reset();
43
+ await null;
44
+
45
+ const { consume } = permitted;
46
+
47
+ const { chainStorage, getDepositFacet, zoe } = consume;
48
+
49
+ const instancePrivateArgs = await consume.instancePrivateArgs;
50
+
51
+ const postalSvcPub = E.when(
52
+ permitted.instance.consume.postalService,
53
+ instance => E(zoe).getPublicFacet(instance),
54
+ );
55
+
56
+ /** @type {UpdatePrivateArgs} */
57
+ const updatePrivateArgs = (instance, privateArgs) => {
58
+ if (!instancePrivateArgs.has(instance)) {
59
+ Fail`instance doesn't have privateArgs`;
60
+ }
61
+ instancePrivateArgs.set(instance, privateArgs);
62
+ };
63
+
64
+ // Use a heap zone to avoid entanglement with old liveslots
65
+ const zone = makeHeapZone();
66
+ const makeContractControl = prepareContractControl(zone, {
67
+ agoricNamesAdmin: await consume.agoricNamesAdmin,
68
+ board: await consume.board,
69
+ startUpgradable: await consume.startUpgradable,
70
+ updatePrivateArgs,
71
+ zoe: await zoe,
72
+ });
73
+
74
+ /** @type {DeliverContractControl} */
75
+ const deliverContractControl = async ({
76
+ name: contractName,
77
+ controlAddress,
78
+ ...opts
79
+ }) => {
80
+ await null;
81
+
82
+ const trace = makeTracer(`CCtrlCore-${contractName}`);
83
+
84
+ trace('creating contract control and delivering to', controlAddress);
85
+
86
+ const contractControl = makeContractControl({
87
+ name: contractName,
88
+ storageNode: await E(chainStorage).makeChildNode(contractName),
89
+ ...opts,
90
+ });
91
+
92
+ trace('reserving', controlAddress);
93
+ // This can block if the wallet is not provisioned
94
+ await E(getDepositFacet)(controlAddress);
95
+
96
+ trace(`delivering control`, controlAddress, contractControl);
97
+ // don't block on the recipient's offer
98
+ const delivered = E.when(
99
+ E(postalSvcPub).deliverPrize(
100
+ controlAddress,
101
+ contractControl,
102
+ YMAX_CONTROL_WALLET_KEY,
103
+ ),
104
+ () => trace('control received'),
105
+ );
106
+
107
+ return harden({ delivered, contractControl });
108
+ };
109
+ harden(deliverContractControl);
110
+
111
+ permitted.produce.deliverContractControl.resolve(deliverContractControl);
112
+ };
113
+
114
+ export const getManifestForDeliverContractControl = () => ({
115
+ manifest: {
116
+ [produceDeliverContractControl.name]: {
117
+ consume: {
118
+ agoricNamesAdmin: true,
119
+ board: true,
120
+ chainStorage: true,
121
+ getDepositFacet: true,
122
+ instancePrivateArgs: true,
123
+ startUpgradable: true,
124
+ zoe: true,
125
+ },
126
+ produce: {
127
+ deliverContractControl: true,
128
+ },
129
+ instance: {
130
+ consume: { postalService: true },
131
+ // provide: true,
132
+ },
133
+ installation: {
134
+ // provide: true,
135
+ },
136
+ },
137
+ },
138
+ });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @import { CoreEvalBuilder, DeployScriptFunction } from '@agoric/deploy-script-support/src/externalTypes.js';
3
+ */
4
+
5
+ import { makeHelpers } from '../helpers.js';
6
+ import { getManifestForGetUpgradeKit } from './get-upgrade-kit.core.js';
7
+
8
+ const sourceSpec =
9
+ '@agoric/deploy-script-support/src/control/get-upgrade-kit.core.js';
10
+
11
+ /**
12
+ * @satisfies {CoreEvalBuilder}
13
+ */
14
+ const defaultProposalBuilder = async () => {
15
+ return harden({
16
+ sourceSpec,
17
+ getManifestCall: [getManifestForGetUpgradeKit.name],
18
+ });
19
+ };
20
+
21
+ /** @type {DeployScriptFunction} */
22
+ const build = async (homeP, endowments) => {
23
+ const { writeCoreEval } = await makeHelpers(homeP, endowments);
24
+
25
+ await writeCoreEval('eval-get-upgrade-kit', () => defaultProposalBuilder());
26
+ };
27
+
28
+ export default build;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @file Get a contract upgrade kit by name.
3
+ */
4
+
5
+ import { E } from '@endo/eventual-send';
6
+
7
+ /**
8
+ * @import {ContractStartFunction, Instance} from '@agoric/zoe/src/zoeService/utils.js';
9
+ * @import {StartedInstanceKit, StartedInstanceKitWithLabel} from '@agoric/vats/src/core/types.js';
10
+ * @import {PromiseSpaceOf} from '@agoric/vats/src/core/types.js';
11
+ * @import {BootstrapPowers} from '@agoric/vats/src/core/types.js';
12
+ */
13
+
14
+ const trace = (...args) => console.log('---- GetUpgradeKit', ...args);
15
+
16
+ /**
17
+ * Similar to StartedInstanceKit, but with label and optional privateArgs
18
+ * managed by ContractControl.
19
+ *
20
+ * @template {ContractStartFunction} SF
21
+ * @typedef {StartedInstanceKit<SF> & {
22
+ * label: string;
23
+ * privateArgs?: Parameters<SF>[1];
24
+ * }} UpgradeKit
25
+ */
26
+
27
+ /**
28
+ * `getUpgradeKit` is a power allowing to retrieve a contract upgrade kit by
29
+ * the contract's name, without giving full access to the underlying stores.
30
+ *
31
+ * @typedef {PromiseSpaceOf<{
32
+ * getUpgradeKit: <SF extends ContractStartFunction>(name: string) => Promise<StartedInstanceKitWithLabel<SF>>
33
+ * }>} GetUpgradeKitPowers
34
+ */
35
+
36
+ /**
37
+ * @param {BootstrapPowers & GetUpgradeKitPowers} powers
38
+ */
39
+ export const produceGetUpgradeKit = async powers => {
40
+ powers.produce.getUpgradeKit.reset();
41
+ const { consume } = powers;
42
+
43
+ const agoricNames = await consume.agoricNames;
44
+ const contractKits = await consume.contractKits;
45
+ const instancePrivateArgs = await consume.instancePrivateArgs;
46
+
47
+ /**
48
+ * @template {ContractStartFunction} SF
49
+ * @param {string} name
50
+ * @returns {Promise<StartedInstanceKitWithLabel<SF>>}
51
+ */
52
+ const getUpgradeKit = async name => {
53
+ trace('getting instance for', name);
54
+ /** @type {Instance<SF>} */
55
+ const instance = await E(agoricNames).lookup('instance', name);
56
+
57
+ trace('getting contract kit for', name);
58
+ const kit = /** @type {UpgradeKit<SF>} */ (contractKits.get(instance));
59
+
60
+ trace('getting privateArgs for', name);
61
+ const privateArgs = instancePrivateArgs.has(instance)
62
+ ? /** @type {Parameters<SF>[1]} */ (instancePrivateArgs.get(instance))
63
+ : undefined;
64
+
65
+ return { ...kit, privateArgs };
66
+ };
67
+ harden(getUpgradeKit);
68
+
69
+ powers.produce.getUpgradeKit.resolve(getUpgradeKit);
70
+ };
71
+
72
+ export const getManifestForGetUpgradeKit = () => ({
73
+ manifest: {
74
+ [produceGetUpgradeKit.name]: {
75
+ consume: {
76
+ agoricNames: true,
77
+ contractKits: true,
78
+ instancePrivateArgs: true,
79
+ },
80
+ produce: { getUpgradeKit: true },
81
+ },
82
+ },
83
+ });
@@ -0,0 +1,59 @@
1
+ import { E } from '@endo/eventual-send';
2
+ import { passStyleOf } from '@endo/pass-style';
3
+ import { objectMap } from '@endo/patterns';
4
+ import { makeTracer } from '@agoric/internal/src/debug.js';
5
+
6
+ const contractName = 'postalService';
7
+
8
+ const trace = makeTracer('CCtrlCore');
9
+
10
+ /**
11
+ * @import {Installation} from '@agoric/zoe';
12
+ * @import {Instance} from '@agoric/zoe';
13
+ * @import {PromiseSpaceOf} from '@agoric/vats/src/core/types.js';
14
+ * @import {BootstrapPowers} from '@agoric/vats/src/core/types.js';
15
+ * @import {start} from '@aglocal/portfolio-deploy/src/control/postal-service.contract.js';
16
+ */
17
+ /**
18
+ * @typedef {typeof start} PostalServiceStartFn
19
+ *
20
+ * @typedef {{
21
+ * installation: PromiseSpaceOf<{ postalService: Installation<PostalServiceStartFn>}>;
22
+ * instance: PromiseSpaceOf<{ postalService: Instance<PostalServiceStartFn>}>;
23
+ * }} PostalServiceBoot
24
+ */
25
+
26
+ /** @param {BootstrapPowers & PostalServiceBoot} permitted */
27
+ export const deployPostalService = async permitted => {
28
+ permitted.instance.produce.postalService.reset();
29
+ const { startUpgradable, namesByAddress } = permitted.consume;
30
+ const { postalService: installationP } = permitted.installation.consume;
31
+ trace('await: installation.postalService');
32
+ const installation = await installationP;
33
+ trace('await: namesByAddress');
34
+ const privateArgs = harden({
35
+ namesByAddress: await namesByAddress,
36
+ });
37
+ trace('await: startUpgradable(...)');
38
+ const kit = await E(startUpgradable)({
39
+ label: contractName,
40
+ installation,
41
+ privateArgs,
42
+ });
43
+ trace('kit', objectMap(kit, passStyleOf));
44
+ permitted.instance.produce.postalService.resolve(kit.instance);
45
+ };
46
+
47
+ export const getManifestForPostalService = (
48
+ { restoreRef },
49
+ { installKeys },
50
+ ) => ({
51
+ manifest: {
52
+ [deployPostalService.name]: {
53
+ consume: { startUpgradable: true, namesByAddress: true },
54
+ installation: { consume: { postalService: true } },
55
+ instance: { produce: { postalService: true } },
56
+ },
57
+ },
58
+ installations: { postalService: restoreRef(installKeys.postalService) },
59
+ });