@agoric/deploy-script-support 0.10.4-other-dev-8f8782b.0 → 0.10.4-other-dev-fbe72e7.0.fbe72e7

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.
@@ -1,4 +1,5 @@
1
1
  // @ts-check
2
+ import { Fail } from '@endo/errors';
2
3
  import { deeplyFulfilledObject } from '@agoric/internal';
3
4
  import fs from 'fs';
4
5
  import { createRequire } from 'module';
@@ -11,21 +12,45 @@ import {
11
12
  } from './coreProposalBehavior.js';
12
13
 
13
14
  /**
14
- * @typedef {string | { module: string, entrypoint: string, args?: Array<unknown> }} ConfigProposal
15
+ * @typedef {string | {module: string, entrypoint?: string, args?: Array<unknown>}} ConfigProposal
15
16
  */
16
17
 
17
- const { details: X, Fail } = assert;
18
+ /**
19
+ * @typedef {{steps: ConfigProposal[][]}} SequentialCoreProposals
20
+ * @typedef {ConfigProposal[] | SequentialCoreProposals} CoreProposals
21
+ */
18
22
 
19
23
  const req = createRequire(import.meta.url);
20
24
 
25
+ /**
26
+ * @param {...(CoreProposals | undefined | null)} args
27
+ * @returns {SequentialCoreProposals}
28
+ */
29
+ export const mergeCoreProposals = (...args) => {
30
+ /** @type {ConfigProposal[][]} */
31
+ const steps = [];
32
+ for (const coreProposal of args) {
33
+ if (!coreProposal) {
34
+ continue;
35
+ }
36
+ if ('steps' in coreProposal) {
37
+ steps.push(...coreProposal.steps);
38
+ } else {
39
+ steps.push(coreProposal);
40
+ }
41
+ }
42
+ return harden({ steps });
43
+ };
44
+ harden(mergeCoreProposals);
45
+
21
46
  /**
22
47
  * @param {(ModuleSpecifier | FilePath)[]} paths
23
48
  * @typedef {string} ModuleSpecifier
24
49
  * @typedef {string} FilePath
25
50
  */
26
51
  const pathResolve = (...paths) => {
27
- const fileName = paths.pop();
28
- assert(fileName, '>=1 paths required');
52
+ const fileName = /** @type {string} */ (paths.pop());
53
+ fileName || Fail`base name required`;
29
54
  try {
30
55
  return req.resolve(fileName, {
31
56
  paths,
@@ -40,6 +65,19 @@ const findModule = (initDir, srcSpec) =>
40
65
  ? pathResolve(initDir, srcSpec)
41
66
  : req.resolve(srcSpec);
42
67
 
68
+ /**
69
+ * @param {{ bundleID?: string, bundleName?: string }} handle - mutated then hardened
70
+ * @param {string} sourceSpec - the specifier of a module to load
71
+ * @param {string} key - the key of the proposal
72
+ * @param {string} piece - the piece of the proposal
73
+ * @returns {Promise<[string, any]>}
74
+ */
75
+ const namedHandleToBundleSpec = async (handle, sourceSpec, key, piece) => {
76
+ handle.bundleName = `coreProposal${String(key)}_${piece}`;
77
+ harden(handle);
78
+ return harden([handle.bundleName, { sourceSpec }]);
79
+ };
80
+
43
81
  /**
44
82
  * Format core proposals to be run at bootstrap:
45
83
  * SwingSet `bundles` configuration
@@ -51,188 +89,225 @@ const findModule = (initDir, srcSpec) =>
51
89
  * but for sim-chain and such, they can be declared statically in
52
90
  * the chain configuration, in which case they are run at bootstrap.
53
91
  *
54
- * @param {ConfigProposal[]} coreProposals - governance
92
+ * @param {CoreProposals} coreProposals - governance
55
93
  * proposals to run at chain bootstrap for scenarios such as sim-chain.
56
94
  * @param {FilePath} [dirname]
57
- * @param {typeof makeEnactCoreProposalsFromBundleRef} [makeEnactCoreProposals]
58
- * @param {(i: number) => number} [getSequenceForProposal]
95
+ * @param {object} [opts]
96
+ * @param {typeof makeEnactCoreProposalsFromBundleRef} [opts.makeEnactCoreProposals]
97
+ * @param {(key: PropertyKey) => PropertyKey} [opts.getSequenceForProposal]
98
+ * @param {typeof namedHandleToBundleSpec} [opts.handleToBundleSpec]
59
99
  */
60
100
  export const extractCoreProposalBundles = async (
61
101
  coreProposals,
62
102
  dirname = '.',
63
- makeEnactCoreProposals = makeEnactCoreProposalsFromBundleRef,
64
- getSequenceForProposal,
103
+ opts,
65
104
  ) => {
66
- if (!getSequenceForProposal) {
67
- // Deterministic proposal numbers.
68
- getSequenceForProposal = i => i;
69
- }
105
+ const {
106
+ makeEnactCoreProposals = makeEnactCoreProposalsFromBundleRef,
107
+ getSequenceForProposal = key => key,
108
+ handleToBundleSpec = namedHandleToBundleSpec,
109
+ } = opts || {};
70
110
 
71
111
  dirname = pathResolve(dirname);
72
112
  dirname = await fs.promises
73
113
  .stat(dirname)
74
114
  .then(stbuf => (stbuf.isDirectory() ? dirname : path.dirname(dirname)));
75
115
 
76
- /** @type {Map<{ bundleName?: string }, { source: string, bundle?: string }>} */
116
+ /** @type {Map<{ bundleID?: string, bundleName?: string }, { source: string, bundle?: string }>} */
77
117
  const bundleHandleToAbsolutePaths = new Map();
78
118
 
119
+ const proposalSteps =
120
+ 'steps' in coreProposals ? coreProposals.steps : [coreProposals];
79
121
  const bundleToSource = new Map();
80
- const extracted = await Promise.all(
81
- coreProposals.map(async (coreProposal, i) => {
82
- // console.debug(`Parsing core proposal:`, coreProposal);
83
-
84
- /** @type {string} */
85
- let entrypoint;
86
- /** @type {unknown[]} */
87
- let args;
88
- /** @type {string} */
89
- let module;
90
- if (typeof coreProposal === 'string') {
91
- module = coreProposal;
92
- entrypoint = 'defaultProposalBuilder';
93
- args = [];
94
- } else {
95
- ({ module, entrypoint, args = [] } = coreProposal);
96
- }
97
-
98
- typeof module === 'string' ||
99
- Fail`coreProposal module ${module} must be string`;
100
- typeof entrypoint === 'string' ||
101
- Fail`coreProposal entrypoint ${entrypoint} must be string`;
102
- Array.isArray(args) || Fail`coreProposal args ${args} must be array`;
103
-
104
- const thisProposalBundleHandles = new Set();
105
- assert(getSequenceForProposal);
106
- const thisProposalSequence = getSequenceForProposal(i);
107
- const initPath = findModule(dirname, module);
108
- const initDir = path.dirname(initPath);
109
- /** @type {Record<string, import('./externalTypes.js').ProposalBuilder>} */
110
- const ns = await import(initPath);
111
- const install = (srcSpec, bundlePath) => {
112
- const absoluteSrc = findModule(initDir, srcSpec);
113
- const bundleHandle = {};
114
- const absolutePaths = { source: absoluteSrc };
115
- if (bundlePath) {
116
- const absoluteBundle = pathResolve(initDir, bundlePath);
117
- absolutePaths.bundle = absoluteBundle;
118
- const oldSource = bundleToSource.get(absoluteBundle);
119
- if (oldSource) {
120
- assert.equal(
121
- oldSource,
122
- absoluteSrc,
123
- X`${bundlePath} already installed from ${oldSource}, now ${absoluteSrc}`,
124
- );
122
+ const extractedSteps = await Promise.all(
123
+ proposalSteps.map((proposalStep, i) =>
124
+ Promise.all(
125
+ proposalStep.map(async (coreProposal, j) => {
126
+ const key = `${i}.${j}`;
127
+ // console.debug(`Parsing core proposal:`, coreProposal);
128
+
129
+ /** @type {string} */
130
+ let entrypoint;
131
+ /** @type {unknown[]} */
132
+ let args;
133
+ /** @type {string} */
134
+ let module;
135
+ if (typeof coreProposal === 'string') {
136
+ module = coreProposal;
137
+ entrypoint = 'defaultProposalBuilder';
138
+ args = [];
125
139
  } else {
126
- bundleToSource.set(absoluteBundle, absoluteSrc);
140
+ ({
141
+ module,
142
+ entrypoint = 'defaultProposalBuilder',
143
+ args = [],
144
+ } = coreProposal);
127
145
  }
128
- }
129
- // Don't harden the bundleHandle since we need to set the bundleName on
130
- // its unique identity later.
131
- thisProposalBundleHandles.add(bundleHandle);
132
- bundleHandleToAbsolutePaths.set(bundleHandle, harden(absolutePaths));
133
- return bundleHandle;
134
- };
135
- /** @type {import('./externalTypes.js').PublishBundleRef} */
136
- const publishRef = async handleP => {
137
- const handle = await handleP;
138
- bundleHandleToAbsolutePaths.has(handle) ||
139
- Fail`${handle} not in installed bundles`;
140
- return handle;
141
- };
142
- const proposal = await ns[entrypoint]({ publishRef, install }, ...args);
143
-
144
- // Add the proposal bundle handles in sorted order.
145
- const bundleSpecEntries = [...thisProposalBundleHandles.keys()]
146
- .map(handle => [handle, bundleHandleToAbsolutePaths.get(handle)])
147
- .sort(([_hnda, { source: a }], [_hndb, { source: b }]) => {
148
- if (a < b) {
149
- return -1;
150
- }
151
- if (a > b) {
152
- return 1;
153
- }
154
- return 0;
155
- })
156
- .map(([handle, absolutePaths], j) => {
157
- // Transform the bundle handle identity into a bundleName reference.
158
- handle.bundleName = `coreProposal${thisProposalSequence}_${j}`;
159
- harden(handle);
160
-
161
- /** @type {[string, { sourceSpec: string }]} */
162
- const specEntry = [
163
- handle.bundleName,
164
- { sourceSpec: absolutePaths.source },
165
- ];
166
- return specEntry;
167
- });
168
-
169
- // Now that we've assigned all the bundleNames and hardened the
170
- // handles, we can extract the behavior bundle.
171
- const { sourceSpec, getManifestCall } = await deeplyFulfilledObject(
172
- harden(proposal),
173
- );
174
-
175
- const behaviorSource = pathResolve(initDir, sourceSpec);
176
- const behaviors = await import(behaviorSource);
177
- const [exportedGetManifest, ...manifestArgs] = getManifestCall;
178
- const { manifest: overrideManifest } = await behaviors[
179
- exportedGetManifest
180
- ](harden({ restoreRef: () => null }), ...manifestArgs);
181
-
182
- const behaviorBundleHandle = harden({
183
- bundleName: `coreProposal${thisProposalSequence}_behaviors`,
184
- });
185
- const behaviorAbsolutePaths = harden({
186
- source: behaviorSource,
187
- });
188
- bundleHandleToAbsolutePaths.set(
189
- behaviorBundleHandle,
190
- behaviorAbsolutePaths,
191
- );
192
-
193
- bundleSpecEntries.unshift([
194
- behaviorBundleHandle.bundleName,
195
- { sourceSpec: behaviorAbsolutePaths.source },
196
- ]);
197
-
198
- return harden({
199
- ref: behaviorBundleHandle,
200
- call: getManifestCall,
201
- overrideManifest,
202
- bundleSpecs: bundleSpecEntries,
203
- });
204
- }),
146
+
147
+ typeof module === 'string' ||
148
+ Fail`coreProposal module ${module} must be string`;
149
+ typeof entrypoint === 'string' ||
150
+ Fail`coreProposal entrypoint ${entrypoint} must be string`;
151
+ Array.isArray(args) || Fail`coreProposal args ${args} must be array`;
152
+
153
+ const thisProposalBundleHandles = new Set();
154
+ assert(getSequenceForProposal);
155
+ const thisProposalSequence = getSequenceForProposal(key);
156
+ const initPath = findModule(dirname, module);
157
+ const initDir = path.dirname(initPath);
158
+ /** @type {Record<string, import('./externalTypes.js').CoreEvalBuilder>} */
159
+ const ns = await import(initPath);
160
+ const install = (srcSpec, bundlePath) => {
161
+ const absoluteSrc = findModule(initDir, srcSpec);
162
+ const bundleHandle = {};
163
+ const absolutePaths = { source: absoluteSrc };
164
+ if (bundlePath) {
165
+ const absoluteBundle = pathResolve(initDir, bundlePath);
166
+ absolutePaths.bundle = absoluteBundle;
167
+ const oldSource = bundleToSource.get(absoluteBundle);
168
+ if (oldSource) {
169
+ oldSource === absoluteSrc ||
170
+ Fail`${bundlePath} already installed from ${oldSource}, now ${absoluteSrc}`;
171
+ } else {
172
+ bundleToSource.set(absoluteBundle, absoluteSrc);
173
+ }
174
+ }
175
+ // Don't harden the bundleHandle since we need to set the bundleName on
176
+ // its unique identity later.
177
+ thisProposalBundleHandles.add(bundleHandle);
178
+ bundleHandleToAbsolutePaths.set(
179
+ bundleHandle,
180
+ harden(absolutePaths),
181
+ );
182
+ return bundleHandle;
183
+ };
184
+ /** @type {import('./externalTypes.js').PublishBundleRef} */
185
+ const publishRef = async handleP => {
186
+ const handle = await handleP;
187
+ bundleHandleToAbsolutePaths.has(handle) ||
188
+ Fail`${handle} not in installed bundles`;
189
+ return handle;
190
+ };
191
+ const proposal = await ns[entrypoint](
192
+ {
193
+ publishRef,
194
+ // @ts-expect-error not statically verified to return a full obj
195
+ install,
196
+ },
197
+ ...args,
198
+ );
199
+
200
+ // Add the proposal bundle handles in sorted order.
201
+ const bundleSpecEntries = await Promise.all(
202
+ [...thisProposalBundleHandles.keys()]
203
+ .map(handle => [handle, bundleHandleToAbsolutePaths.get(handle)])
204
+ .sort(([_hnda, { source: a }], [_hndb, { source: b }]) => {
205
+ if (a < b) {
206
+ return -1;
207
+ }
208
+ if (a > b) {
209
+ return 1;
210
+ }
211
+ return 0;
212
+ })
213
+ .map(async ([handle, absolutePaths], k) => {
214
+ // Transform the bundle handle identity into a bundleName reference.
215
+ const specEntry = await handleToBundleSpec(
216
+ handle,
217
+ absolutePaths.source,
218
+ thisProposalSequence,
219
+ String(k),
220
+ );
221
+ harden(handle);
222
+ return specEntry;
223
+ }),
224
+ );
225
+
226
+ // Now that we've assigned all the bundleNames and hardened the
227
+ // handles, we can extract the behavior bundle.
228
+ const { sourceSpec, getManifestCall } = await deeplyFulfilledObject(
229
+ harden(proposal),
230
+ );
231
+
232
+ const proposalSource = pathResolve(initDir, sourceSpec);
233
+ const proposalNS = await import(proposalSource);
234
+ const [manifestGetterName, ...manifestGetterArgs] = getManifestCall;
235
+ manifestGetterName in proposalNS ||
236
+ Fail`proposal ${proposalSource} missing export ${manifestGetterName}`;
237
+ const { manifest: customManifest } = await proposalNS[
238
+ manifestGetterName
239
+ ](harden({ restoreRef: () => null }), ...manifestGetterArgs);
240
+
241
+ const behaviorBundleHandle = {};
242
+ const specEntry = await handleToBundleSpec(
243
+ behaviorBundleHandle,
244
+ proposalSource,
245
+ thisProposalSequence,
246
+ 'proposalNS',
247
+ );
248
+ bundleSpecEntries.unshift(specEntry);
249
+
250
+ bundleHandleToAbsolutePaths.set(
251
+ behaviorBundleHandle,
252
+ harden({
253
+ source: proposalSource,
254
+ }),
255
+ );
256
+
257
+ return /** @type {const} */ ([
258
+ key,
259
+ {
260
+ ref: behaviorBundleHandle,
261
+ call: getManifestCall,
262
+ customManifest,
263
+ bundleSpecs: bundleSpecEntries,
264
+ },
265
+ ]);
266
+ }),
267
+ ),
268
+ ),
205
269
  );
206
270
 
207
271
  // Extract all the bundle specs in already-sorted order.
208
272
  const bundles = Object.fromEntries(
209
- extracted.flatMap(({ bundleSpecs }) => bundleSpecs),
273
+ extractedSteps.flatMap(step =>
274
+ step.flatMap(([_key, { bundleSpecs }]) => bundleSpecs),
275
+ ),
210
276
  );
211
277
  harden(bundles);
212
278
 
213
- // Extract the manifest references and calls.
214
- const makeCPArgs = extracted.map(({ ref, call, overrideManifest }) => ({
215
- ref,
216
- call,
217
- overrideManifest,
218
- }));
219
- harden(makeCPArgs);
279
+ const codeSteps = extractedSteps.map(extractedStep => {
280
+ // Extract the manifest references and calls.
281
+ const metadataRecords = extractedStep.map(([_key, extractedSpec]) => {
282
+ const { ref, call, customManifest } = extractedSpec;
283
+ return { ref, call, customManifest };
284
+ });
285
+ harden(metadataRecords);
220
286
 
221
- const code = `\
222
- // This is generated by @agoric/cosmic-swingset/src/extract-proposal.js - DO NOT EDIT
287
+ const code = `\
288
+ // This is generated by @agoric/deploy-script-support/src/extract-proposal.js - DO NOT EDIT
223
289
  /* eslint-disable */
224
290
 
225
- const makeCoreProposalArgs = harden(${stringify(makeCPArgs, true)});
226
-
227
- const makeCoreProposalBehavior = ${makeCoreProposalBehavior};
291
+ const metadataRecords = harden(${stringify(metadataRecords, true)});
228
292
 
229
- (${makeEnactCoreProposals})({ makeCoreProposalArgs, E });
293
+ // Make an enactCoreProposals function and "export" it by way of script completion value.
294
+ // It is constructed by an IIFE to ensure the absence of global bindings for
295
+ // makeCoreProposalBehavior and makeEnactCoreProposals (the latter referencing the former),
296
+ // which may not be necessary but preserves behavior pre-dating
297
+ // https://github.com/Agoric/agoric-sdk/pull/8712 .
298
+ const enactCoreProposals = ((
299
+ makeCoreProposalBehavior = ${makeCoreProposalBehavior},
300
+ makeEnactCoreProposals = ${makeEnactCoreProposals},
301
+ ) => makeEnactCoreProposals({ metadataRecords, E }))();
302
+ enactCoreProposals;
230
303
  `;
304
+ return defangAndTrim(code);
305
+ });
231
306
 
232
307
  // console.debug('created bundles from proposals:', coreProposals, bundles);
233
- return {
308
+ return harden({
234
309
  bundles,
235
- code: defangAndTrim(code),
310
+ codeSteps,
236
311
  bundleHandleToAbsolutePaths,
237
- };
312
+ });
238
313
  };
@@ -13,6 +13,9 @@
13
13
  import { E } from '@endo/far';
14
14
  import url from 'url';
15
15
 
16
+ /** @typedef {ReturnType<import('./endo-pieces-contract.js')['start']>['publicFacet']} BundleMaker */
17
+ /** @typedef {ReturnType<BundleMaker['makeBundler']>} Bundler */
18
+
16
19
  export const makeGetBundlerMaker =
17
20
  (homeP, { lookup, bundleSource }) =>
18
21
  async ({
@@ -20,6 +23,7 @@ export const makeGetBundlerMaker =
20
23
  log = console.log,
21
24
  } = {}) => {
22
25
  const { board: optionalBoard, zoe, scratch } = await homeP;
26
+ /** @type {() => Promise<BundleMaker>} */
23
27
  const lookupOrCreate = async () => {
24
28
  // Locate the bundler maker if any already exists at the given path.
25
29
  let bundlerMaker = await lookup(JSON.parse(BUNDLER_MAKER_LOOKUP));
package/src/helpers.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // @ts-check
2
- import '@agoric/zoe/exported.js';
2
+
3
+ /// <reference path="../../zoe/exported.js" />
4
+
3
5
  import { E } from '@endo/far';
4
6
  import bundleSource from '@endo/bundle-source';
5
7
 
@@ -15,9 +17,10 @@ import { makeSaveIssuer } from './saveIssuer.js';
15
17
  import { makeGetBundlerMaker } from './getBundlerMaker.js';
16
18
  import { assertOfferResult } from './assertOfferResult.js';
17
19
  import { installInPieces } from './installInPieces.js';
18
- import { makeWriteCoreProposal } from './writeCoreProposal.js';
20
+ import { makeWriteCoreEval } from './writeCoreEvalParts.js';
19
21
 
20
22
  export * from '@agoric/internal/src/node/createBundles.js';
23
+ export { parseScriptArgs } from './parseCoreEvalArgs.js';
21
24
 
22
25
  // These are also hard-coded in lib-wallet.js.
23
26
  // TODO: Add methods to the wallet to access these without hard-coding
@@ -50,6 +53,10 @@ const makeLazyObject = sourceObject => {
50
53
  return /** @type {T} */ (lazyObject);
51
54
  };
52
55
 
56
+ /**
57
+ * @param {Promise<import('./externalTypes.js').CommonHome | import('./externalTypes.js').AgSoloHome>} homePromise
58
+ * @param {import('./externalTypes.js').DeployScriptEndownments} endowments
59
+ */
53
60
  export const makeHelpers = async (homePromise, endowments) => {
54
61
  // Endowments provided via `agoric run` or `agoric deploy`.
55
62
  const {
@@ -82,6 +89,7 @@ export const makeHelpers = async (homePromise, endowments) => {
82
89
  return E(deps.walletAdmin).getIssuerManager();
83
90
  },
84
91
  get offerAndFind() {
92
+ assert('wallet' in deps.home, 'expected AgSolo home');
85
93
  return makeOfferAndFindInvitationAmount(
86
94
  deps.walletAdmin,
87
95
  deps.home.zoe,
@@ -89,6 +97,7 @@ export const makeHelpers = async (homePromise, endowments) => {
89
97
  );
90
98
  },
91
99
  get walletAdmin() {
100
+ assert('wallet' in deps.home, 'expected AgSolo home');
92
101
  return E(deps.home.wallet).getAdminFacet();
93
102
  },
94
103
  get zoeInvitationPurse() {
@@ -108,6 +117,7 @@ export const makeHelpers = async (homePromise, endowments) => {
108
117
  return deps.offerAndFind.findInvitationAmount;
109
118
  },
110
119
  get install() {
120
+ assert('wallet' in deps.home, 'expected AgSolo home');
111
121
  return makeInstall(
112
122
  bundleSource,
113
123
  deps.home.zoe,
@@ -125,6 +135,7 @@ export const makeHelpers = async (homePromise, endowments) => {
125
135
  return makeSaveIssuer(deps.walletAdmin, deps.issuerManager);
126
136
  },
127
137
  get startInstance() {
138
+ assert('wallet' in deps.home, 'expected AgSolo home');
128
139
  return makeStartInstance(
129
140
  deps.issuerManager,
130
141
  deps.instanceManager,
@@ -135,8 +146,16 @@ export const makeHelpers = async (homePromise, endowments) => {
135
146
  get getBundlerMaker() {
136
147
  return makeGetBundlerMaker(homePromise, { bundleSource, lookup });
137
148
  },
149
+ /** @returns {import('./writeCoreEvalParts.js').WriteCoreEval} */
150
+ get writeCoreEval() {
151
+ return makeWriteCoreEval(homePromise, endowments, {
152
+ getBundleSpec: deps.cacheAndGetBundleSpec,
153
+ getBundlerMaker: helpers.getBundlerMaker,
154
+ });
155
+ },
156
+ /** @deprecated use writeCoreEval */
138
157
  get writeCoreProposal() {
139
- return makeWriteCoreProposal(homePromise, endowments, {
158
+ return makeWriteCoreEval(homePromise, endowments, {
140
159
  getBundleSpec: deps.cacheAndGetBundleSpec,
141
160
  getBundlerMaker: helpers.getBundlerMaker,
142
161
  });
package/src/install.js CHANGED
@@ -3,20 +3,11 @@ import './externalTypes.js';
3
3
 
4
4
  import { E } from '@endo/far';
5
5
 
6
- /** @typedef {import('@agoric/deploy-script-support/src/externalTypes').Petname} Petname */
7
-
8
- /**
9
- * @callback BundleSource
10
- * @param {string} startFilename - the filepath to start the bundling from
11
- * @param {ModuleFormat | BundleOptions} [moduleFormat]
12
- * @param {object} [powers]
13
- * @param {ReadFn} [powers.read]
14
- * @param {CanonicalFn} [powers.canonical]
15
- */
6
+ /** @import {Petname} from '@agoric/deploy-script-support/src/externalTypes.js' */
16
7
 
17
8
  // XXX board is Board but specifying that leads to type errors with imports which aren't worth fixing right now
18
9
  /**
19
- * @param {BundleSource} bundleSource
10
+ * @param {typeof import('@endo/bundle-source')['default']} bundleSource
20
11
  * @param {ERef<ZoeService>} zoe
21
12
  * @param {ERef<import('./startInstance.js').InstallationManager>} installationManager
22
13
  * @param {ERef<any>} board
package/src/offer.js CHANGED
@@ -1,10 +1,14 @@
1
1
  // @ts-check
2
+ import { assert } from '@endo/errors';
2
3
  import { E } from '@endo/far';
3
- import { assert } from '@agoric/assert';
4
4
  // Avoid pulling in too many dependencies like notifiers
5
5
  import { AmountMath } from '@agoric/ertp/src/amountMath.js';
6
6
 
7
- /** @typedef {import('@agoric/deploy-script-support/src/externalTypes').Petname} Petname */
7
+ /**
8
+ * @import {Petname} from '@agoric/deploy-script-support/src/externalTypes.js';
9
+ * @import {Amount, Brand, Issuer, Payment, Purse} from '@agoric/ertp';
10
+ * @import {InvitationDetails, Keyword, Proposal} from '@agoric/zoe';
11
+ */
8
12
 
9
13
  /**
10
14
  * @typedef {object} OfferHelperConfig
@@ -19,7 +23,7 @@ import { AmountMath } from '@agoric/ertp/src/amountMath.js';
19
23
  * @param {ERef<any>} walletAdmin - an internal type of the
20
24
  * wallet, not defined here
21
25
  * @param {ERef<ZoeService>} zoe
22
- * @param {ERef<Purse>} zoeInvitationPurse
26
+ * @param {ERef<Purse<'set', InvitationDetails>>} zoeInvitationPurse
23
27
  */
24
28
  export const makeOfferAndFindInvitationAmount = (
25
29
  walletAdmin,
@@ -28,7 +32,7 @@ export const makeOfferAndFindInvitationAmount = (
28
32
  ) => {
29
33
  /**
30
34
  * @param {Record<string, any>} invitationDetailsCriteria
31
- * @returns {Promise<Amount>} invitationAmount
35
+ * @returns {Promise<InvitationAmount>} invitationAmount
32
36
  */
33
37
  const findInvitationAmount = async invitationDetailsCriteria => {
34
38
  const invitationAmount = await E(zoeInvitationPurse).getCurrentAmount();
@@ -114,9 +118,8 @@ export const makeOfferAndFindInvitationAmount = (
114
118
  } = config;
115
119
 
116
120
  const invitationToUse = getInvitation(invitation, partialInvitationDetails);
117
- const invitationDetails = await E(zoe).getInvitationDetails(
118
- invitationToUse,
119
- );
121
+ const invitationDetails =
122
+ await E(zoe).getInvitationDetails(invitationToUse);
120
123
  const payments = withdrawPayments(proposal, paymentsWithPursePetnames);
121
124
 
122
125
  const seat = E(zoe).offer(invitationToUse, proposal, payments);
@@ -0,0 +1,36 @@
1
+ /**
2
+ * To customize proposals for multiple environments, we pass the "variant"
3
+ * identifier in scriptArgs. The variant must match a knownVariant.
4
+ *
5
+ * @param {import('./externalTypes.js').DeployScriptEndownments} endowments
6
+ * @param {string} name a name to use in error messages or Usage suggestions.
7
+ * @param {string[]} knownVariants
8
+ */
9
+ export const parseScriptArgs = async (endowments, name, knownVariants) => {
10
+ const { scriptArgs } = endowments;
11
+ // const variantOrConfig = scriptArgs?.[0];
12
+ const variantOrConfig =
13
+ scriptArgs && scriptArgs.length > 0 ? scriptArgs : undefined;
14
+
15
+ console.log(`${name}`, variantOrConfig);
16
+
17
+ const Usage = `agoric run ${name}.js ${[...knownVariants, '<json-config>'].join(' | ')}`;
18
+ const opts = {};
19
+
20
+ if (typeof variantOrConfig === 'string') {
21
+ if (variantOrConfig[0] === '{') {
22
+ try {
23
+ opts.config = JSON.parse(variantOrConfig);
24
+ } catch (err) {
25
+ throw Error(`Failed to parse config argument ${variantOrConfig}`);
26
+ }
27
+ } else {
28
+ opts.variant = variantOrConfig;
29
+ }
30
+ } else {
31
+ console.error(Usage);
32
+ throw Error(Usage);
33
+ }
34
+
35
+ return opts;
36
+ };