@agoric/deploy-script-support 0.10.4-u13.0 → 0.10.4-u14.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/CHANGELOG.md +12 -0
- package/package.json +9 -9
- package/src/coreProposalBehavior.js +104 -60
- package/src/endo-pieces-contract.js +3 -0
- package/src/externalTypes.js +9 -10
- package/src/extract-proposal.js +232 -154
- package/src/getBundlerMaker.js +4 -0
- package/src/offer.js +2 -2
- package/src/writeCoreProposal.js +76 -14
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
### [0.10.4-u14.0](https://github.com/Agoric/agoric-sdk/compare/@agoric/deploy-script-support@0.10.4-u13.0...@agoric/deploy-script-support@0.10.4-u14.0) (2024-02-27)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **deploy-script-support:** generalize `extractCoreProposalBundles` ([5de1e93](https://github.com/Agoric/agoric-sdk/commit/5de1e93747146a4c9cd4e3d3d77a0f43033c72fb))
|
|
12
|
+
* **deploy-script-support:** Write out bundle file names in machine readable file ([2a68ca1](https://github.com/Agoric/agoric-sdk/commit/2a68ca148f637ca88c553b75834496ac6ebea841))
|
|
13
|
+
* **extract-proposal:** organize proposals into steps ([eaa6b4f](https://github.com/Agoric/agoric-sdk/commit/eaa6b4fdc5c8ce5c377ac8ed2b88971f78641536))
|
|
14
|
+
* better diagnostic for bad proposal ([19725e5](https://github.com/Agoric/agoric-sdk/commit/19725e5a132056a314d90975fffbb89053de8829))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
6
18
|
### [0.10.4-u13.0](https://github.com/Agoric/agoric-sdk/compare/@agoric/deploy-script-support@0.10.4-u12.0...@agoric/deploy-script-support@0.10.4-u13.0) (2023-12-07)
|
|
7
19
|
|
|
8
20
|
**Note:** Version bump only for package @agoric/deploy-script-support
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/deploy-script-support",
|
|
3
|
-
"version": "0.10.4-
|
|
3
|
+
"version": "0.10.4-u14.0",
|
|
4
4
|
"description": "Helpers and other support for writing deploy scripts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/helpers.js",
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"homepage": "https://github.com/Agoric/agoric-sdk#readme",
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@agoric/assert": "^0.6.1-u11wf.0",
|
|
38
|
-
"@agoric/ertp": "^0.16.3-
|
|
39
|
-
"@agoric/import-manager": "^0.3.12-
|
|
40
|
-
"@agoric/internal": "^0.4.0-
|
|
41
|
-
"@agoric/notifier": "^0.6.3-
|
|
42
|
-
"@agoric/store": "^0.9.3-
|
|
43
|
-
"@agoric/zoe": "^0.26.3-
|
|
38
|
+
"@agoric/ertp": "^0.16.3-u14.0",
|
|
39
|
+
"@agoric/import-manager": "^0.3.12-u14.0",
|
|
40
|
+
"@agoric/internal": "^0.4.0-u14.0",
|
|
41
|
+
"@agoric/notifier": "^0.6.3-u14.0",
|
|
42
|
+
"@agoric/store": "^0.9.3-u14.0",
|
|
43
|
+
"@agoric/zoe": "^0.26.3-u14.0",
|
|
44
44
|
"@endo/base64": "0.2.31",
|
|
45
45
|
"@endo/bundle-source": "2.5.2-upstream-rollup",
|
|
46
46
|
"@endo/far": "0.2.18",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@endo/zip": "0.2.31"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@agoric/vats": "^0.15.2-
|
|
53
|
+
"@agoric/vats": "^0.15.2-u14.0",
|
|
54
54
|
"@endo/init": "0.5.56",
|
|
55
55
|
"ava": "^5.2.0",
|
|
56
56
|
"import-meta-resolve": "^2.2.1"
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"publishConfig": {
|
|
69
69
|
"access": "public"
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "b3a6f3374cb3bddab39fc6d6f426429cae6c29c6"
|
|
72
72
|
}
|
|
@@ -8,7 +8,20 @@ const t = 'makeCoreProposalBehavior';
|
|
|
8
8
|
* @typedef {*} BootstrapPowers
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {import('./externalTypes.js').ManifestBundleRef} ManifestBundleRef
|
|
13
|
+
* @typedef {[methodName: string, ...args: unknown[]]} FlatMethargs
|
|
14
|
+
* @typedef {Record<string, Record<string, unknown>>} Manifest
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* These permits are expected to be the minimum powers required by the
|
|
19
|
+
* `coreProposalBehavior` function returned from `makeCoreProposalBehavior`.
|
|
20
|
+
* They are merged with all of the manifest getter's permits to produce the
|
|
21
|
+
* total permits needed by the resulting core proposal (such as might be---and
|
|
22
|
+
* generally are---written into a *-permit.json file).
|
|
23
|
+
* @see {@link ./writeCoreProposal.js}
|
|
24
|
+
*/
|
|
12
25
|
export const permits = {
|
|
13
26
|
consume: { agoricNamesAdmin: t, vatAdminSvc: t, zoe: t },
|
|
14
27
|
evaluateBundleCap: t,
|
|
@@ -23,22 +36,22 @@ export const permits = {
|
|
|
23
36
|
* for catching bugs. Thus, this maker must not reference any other modules or
|
|
24
37
|
* definitions.
|
|
25
38
|
*
|
|
26
|
-
* @param {object}
|
|
27
|
-
* @param {
|
|
28
|
-
* @param {
|
|
29
|
-
* @param {
|
|
30
|
-
* @param {typeof import('@endo/far').E}
|
|
31
|
-
* @param {(...args: unknown[]) => void} [
|
|
32
|
-
* @param {(ref:
|
|
39
|
+
* @param {object} inputs
|
|
40
|
+
* @param {ManifestBundleRef} inputs.manifestBundleRef
|
|
41
|
+
* @param {FlatMethargs} inputs.getManifestCall
|
|
42
|
+
* @param {Manifest} [inputs.customManifest]
|
|
43
|
+
* @param {typeof import('@endo/far').E} inputs.E
|
|
44
|
+
* @param {(...args: unknown[]) => void} [inputs.log]
|
|
45
|
+
* @param {(ref: import('./externalTypes.js').ManifestBundleRef) => Promise<import('@agoric/zoe/src/zoeService/utils.js').Installation<unknown>>} [inputs.customRestoreRef]
|
|
33
46
|
* @returns {(vatPowers: unknown) => Promise<unknown>}
|
|
34
47
|
*/
|
|
35
48
|
export const makeCoreProposalBehavior = ({
|
|
36
49
|
manifestBundleRef,
|
|
37
|
-
getManifestCall,
|
|
38
|
-
|
|
50
|
+
getManifestCall: [manifestGetterName, ...manifestGetterArgs],
|
|
51
|
+
customManifest,
|
|
39
52
|
E,
|
|
40
53
|
log = console.info,
|
|
41
|
-
|
|
54
|
+
customRestoreRef,
|
|
42
55
|
}) => {
|
|
43
56
|
const { entries, fromEntries } = Object;
|
|
44
57
|
|
|
@@ -56,10 +69,32 @@ export const makeCoreProposalBehavior = ({
|
|
|
56
69
|
return fromEntries(ents);
|
|
57
70
|
};
|
|
58
71
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
const makeRestoreRef = (vatAdminSvc, zoe) => {
|
|
73
|
+
/** @type {(ref: import('./externalTypes.js').ManifestBundleRef) => Promise<Installation<unknown>>} */
|
|
74
|
+
const defaultRestoreRef = async bundleRef => {
|
|
75
|
+
// extract-proposal.js creates these records, and bundleName is
|
|
76
|
+
// the optional name under which the bundle was installed into
|
|
77
|
+
// config.bundles
|
|
78
|
+
const bundleIdP =
|
|
79
|
+
'bundleName' in bundleRef
|
|
80
|
+
? E(vatAdminSvc).getBundleIDByName(bundleRef.bundleName)
|
|
81
|
+
: bundleRef.bundleID;
|
|
82
|
+
const bundleID = await bundleIdP;
|
|
83
|
+
const label = bundleID.slice(0, 8);
|
|
84
|
+
return E(zoe).installBundleID(bundleID, label);
|
|
85
|
+
};
|
|
86
|
+
return defaultRestoreRef;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/** @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers */
|
|
90
|
+
const coreProposalBehavior = async powers => {
|
|
91
|
+
// NOTE: `powers` is expected to match or be a superset of the above `permits` export,
|
|
92
|
+
// which should therefore be kept in sync with this deconstruction code.
|
|
93
|
+
// HOWEVER, do note that this function is invoked with at least the *union* of powers
|
|
94
|
+
// required by individual moduleBehaviors declared by the manifest getter, which is
|
|
95
|
+
// necessary so it can use `runModuleBehaviors` to provide the appropriate subset to
|
|
96
|
+
// each one (see ./writeCoreProposal.js).
|
|
97
|
+
// Handle `powers` with the requisite care.
|
|
63
98
|
const {
|
|
64
99
|
consume: { vatAdminSvc, zoe, agoricNamesAdmin },
|
|
65
100
|
evaluateBundleCap,
|
|
@@ -67,49 +102,45 @@ export const makeCoreProposalBehavior = ({
|
|
|
67
102
|
modules: {
|
|
68
103
|
utils: { runModuleBehaviors },
|
|
69
104
|
},
|
|
70
|
-
} =
|
|
71
|
-
const [exportedGetManifest, ...manifestArgs] = getManifestCall;
|
|
72
|
-
|
|
73
|
-
const defaultRestoreRef = async ref => {
|
|
74
|
-
// extract-proposal.js creates these records, and bundleName is
|
|
75
|
-
// the name under which the bundle was installed into
|
|
76
|
-
// config.bundles
|
|
77
|
-
const p = ref.bundleName
|
|
78
|
-
? E(vatAdminSvc).getBundleIDByName(ref.bundleName)
|
|
79
|
-
: ref.bundleID;
|
|
80
|
-
const bundleID = await p;
|
|
81
|
-
const label = bundleID.slice(0, 8);
|
|
82
|
-
return E(zoe).installBundleID(bundleID, label);
|
|
83
|
-
};
|
|
84
|
-
const restoreRef = overrideRestoreRef || defaultRestoreRef;
|
|
105
|
+
} = powers;
|
|
85
106
|
|
|
86
107
|
// Get the on-chain installation containing the manifest and behaviors.
|
|
87
|
-
|
|
108
|
+
log('evaluateBundleCap', {
|
|
88
109
|
manifestBundleRef,
|
|
89
|
-
|
|
110
|
+
manifestGetterName,
|
|
90
111
|
vatAdminSvc,
|
|
91
112
|
});
|
|
92
113
|
let bcapP;
|
|
93
114
|
if ('bundleName' in manifestBundleRef) {
|
|
94
115
|
bcapP = E(vatAdminSvc).getNamedBundleCap(manifestBundleRef.bundleName);
|
|
95
|
-
} else {
|
|
116
|
+
} else if ('bundleID' in manifestBundleRef) {
|
|
96
117
|
bcapP = E(vatAdminSvc).getBundleCap(manifestBundleRef.bundleID);
|
|
118
|
+
} else {
|
|
119
|
+
const keys = Reflect.ownKeys(manifestBundleRef).map(key =>
|
|
120
|
+
typeof key === 'string' ? JSON.stringify(key) : String(key),
|
|
121
|
+
);
|
|
122
|
+
const keysStr = `[${keys.join(', ')}]`;
|
|
123
|
+
throw Error(
|
|
124
|
+
`bundleRef must have own bundleName or bundleID, missing in ${keysStr}`,
|
|
125
|
+
);
|
|
97
126
|
}
|
|
98
127
|
const bundleCap = await bcapP;
|
|
99
128
|
|
|
100
|
-
const
|
|
129
|
+
const proposalNS = await evaluateBundleCap(bundleCap);
|
|
101
130
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
131
|
+
// Get the manifest and its metadata.
|
|
132
|
+
log('execute', {
|
|
133
|
+
manifestGetterName,
|
|
134
|
+
bundleExports: Object.keys(proposalNS),
|
|
105
135
|
});
|
|
136
|
+
const restoreRef = customRestoreRef || makeRestoreRef(vatAdminSvc, zoe);
|
|
106
137
|
const {
|
|
107
138
|
manifest,
|
|
108
139
|
options: rawOptions,
|
|
109
140
|
installations: rawInstallations,
|
|
110
|
-
} = await
|
|
141
|
+
} = await proposalNS[manifestGetterName](
|
|
111
142
|
harden({ restoreRef }),
|
|
112
|
-
...
|
|
143
|
+
...manifestGetterArgs,
|
|
113
144
|
);
|
|
114
145
|
|
|
115
146
|
// Await references in the options or installations.
|
|
@@ -117,20 +148,24 @@ export const makeCoreProposalBehavior = ({
|
|
|
117
148
|
[rawOptions, rawInstallations].map(shallowlyFulfilled),
|
|
118
149
|
);
|
|
119
150
|
|
|
120
|
-
// Publish the installations for
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
151
|
+
// Publish the installations for our dependencies.
|
|
152
|
+
const installationEntries = entries(installations || {});
|
|
153
|
+
if (installationEntries.length > 0) {
|
|
154
|
+
const installAdmin = E(agoricNamesAdmin).lookupAdmin('installation');
|
|
155
|
+
await Promise.all(
|
|
156
|
+
installationEntries.map(([key, value]) => {
|
|
157
|
+
produceInstallations[key].resolve(value);
|
|
158
|
+
return E(installAdmin).update(key, value);
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
161
|
+
}
|
|
128
162
|
|
|
129
|
-
// Evaluate the manifest
|
|
163
|
+
// Evaluate the manifest.
|
|
130
164
|
return runModuleBehaviors({
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
165
|
+
// Remember that `powers` may be arbitrarily broad.
|
|
166
|
+
allPowers: powers,
|
|
167
|
+
behaviors: proposalNS,
|
|
168
|
+
manifest: customManifest || manifest,
|
|
134
169
|
makeConfig: (name, _permit) => {
|
|
135
170
|
log('coreProposal:', name);
|
|
136
171
|
return { options };
|
|
@@ -138,22 +173,31 @@ export const makeCoreProposalBehavior = ({
|
|
|
138
173
|
});
|
|
139
174
|
};
|
|
140
175
|
|
|
141
|
-
|
|
142
|
-
return behavior;
|
|
176
|
+
return coreProposalBehavior;
|
|
143
177
|
};
|
|
144
178
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
179
|
+
/**
|
|
180
|
+
* @param {object} inputs
|
|
181
|
+
* @param {Array<{ ref: ManifestBundleRef, call: FlatMethargs, customManifest?: Manifest }>} inputs.metadataRecords
|
|
182
|
+
* @param {typeof import('@endo/far').E} inputs.E
|
|
183
|
+
*/
|
|
184
|
+
export const makeEnactCoreProposalsFromBundleRef = ({ metadataRecords, E }) => {
|
|
185
|
+
/**
|
|
186
|
+
* @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers
|
|
187
|
+
* @returns {Promise<void>}
|
|
188
|
+
*/
|
|
189
|
+
const enactCoreProposals = async powers => {
|
|
148
190
|
await Promise.all(
|
|
149
|
-
|
|
150
|
-
const
|
|
191
|
+
metadataRecords.map(async ({ ref, call, customManifest }) => {
|
|
192
|
+
const coreProposalBehavior = makeCoreProposalBehavior({
|
|
151
193
|
manifestBundleRef: ref,
|
|
152
194
|
getManifestCall: call,
|
|
153
|
-
|
|
195
|
+
customManifest,
|
|
154
196
|
E,
|
|
155
197
|
});
|
|
156
|
-
return
|
|
198
|
+
return coreProposalBehavior(powers);
|
|
157
199
|
}),
|
|
158
200
|
);
|
|
159
201
|
};
|
|
202
|
+
return enactCoreProposals;
|
|
203
|
+
};
|
package/src/externalTypes.js
CHANGED
|
@@ -16,30 +16,29 @@ export {};
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* @typedef
|
|
20
|
-
* @property {string} [bundleName]
|
|
19
|
+
* @typedef {{fileName?: string} & ({ bundleName: string } | { bundleID: string}) } ManifestBundleRef
|
|
21
20
|
*/
|
|
22
21
|
|
|
23
22
|
/**
|
|
24
23
|
* @callback PublishBundleRef
|
|
25
|
-
* @param {ERef<
|
|
26
|
-
* @returns {Promise<
|
|
24
|
+
* @param {ERef<ManifestBundleRef>} bundle
|
|
25
|
+
* @returns {Promise<ManifestBundleRef>}
|
|
27
26
|
*/
|
|
28
27
|
|
|
29
28
|
/**
|
|
30
|
-
* @callback
|
|
29
|
+
* @callback InstallEntrypoint
|
|
31
30
|
* @param {string} srcSpec
|
|
32
|
-
* @param {string} bundlePath
|
|
33
|
-
* @param {
|
|
34
|
-
* @returns {
|
|
31
|
+
* @param {string} [bundlePath]
|
|
32
|
+
* @param {unknown} [opts]
|
|
33
|
+
* @returns {Promise<ManifestBundleRef>}
|
|
35
34
|
*/
|
|
36
35
|
|
|
37
36
|
/**
|
|
38
37
|
* @callback ProposalBuilder
|
|
39
38
|
* @param {{
|
|
40
39
|
* publishRef: PublishBundleRef,
|
|
41
|
-
* install:
|
|
42
|
-
* wrapInstall?: <T>(f: T) => T }
|
|
40
|
+
* install: InstallEntrypoint,
|
|
41
|
+
* wrapInstall?: <T extends InstallEntrypoint>(f: T) => T }
|
|
43
42
|
* } powers
|
|
44
43
|
* @param {...any} args
|
|
45
44
|
* @returns {Promise<ProposalResult>}
|
package/src/extract-proposal.js
CHANGED
|
@@ -11,21 +11,47 @@ import {
|
|
|
11
11
|
} from './coreProposalBehavior.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* @typedef {string | {
|
|
14
|
+
* @typedef {string | {module: string, entrypoint?: string, args?: Array<unknown>}} ConfigProposal
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {{steps: ConfigProposal[][]}} SequentialCoreProposals
|
|
19
|
+
* @typedef {ConfigProposal[] | SequentialCoreProposals} CoreProposals
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const { Fail } = assert;
|
|
18
23
|
|
|
19
24
|
const req = createRequire(import.meta.url);
|
|
20
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @param {...(CoreProposals | undefined | null)} args
|
|
28
|
+
* @returns {SequentialCoreProposals}
|
|
29
|
+
*/
|
|
30
|
+
export const mergeCoreProposals = (...args) => {
|
|
31
|
+
/** @type {ConfigProposal[][]} */
|
|
32
|
+
const steps = [];
|
|
33
|
+
for (const coreProposal of args) {
|
|
34
|
+
if (!coreProposal) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if ('steps' in coreProposal) {
|
|
38
|
+
steps.push(...coreProposal.steps);
|
|
39
|
+
} else {
|
|
40
|
+
steps.push(coreProposal);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return harden({ steps });
|
|
44
|
+
};
|
|
45
|
+
harden(mergeCoreProposals);
|
|
46
|
+
|
|
21
47
|
/**
|
|
22
48
|
* @param {(ModuleSpecifier | FilePath)[]} paths
|
|
23
49
|
* @typedef {string} ModuleSpecifier
|
|
24
50
|
* @typedef {string} FilePath
|
|
25
51
|
*/
|
|
26
52
|
const pathResolve = (...paths) => {
|
|
27
|
-
const fileName = paths.pop();
|
|
28
|
-
|
|
53
|
+
const fileName = /** @type {string} */ (paths.pop());
|
|
54
|
+
fileName || Fail`base name required`;
|
|
29
55
|
try {
|
|
30
56
|
return req.resolve(fileName, {
|
|
31
57
|
paths,
|
|
@@ -40,6 +66,19 @@ const findModule = (initDir, srcSpec) =>
|
|
|
40
66
|
? pathResolve(initDir, srcSpec)
|
|
41
67
|
: req.resolve(srcSpec);
|
|
42
68
|
|
|
69
|
+
/**
|
|
70
|
+
* @param {{ bundleID?: string, bundleName?: string }} handle - mutated then hardened
|
|
71
|
+
* @param {string} sourceSpec - the specifier of a module to load
|
|
72
|
+
* @param {string} key - the key of the proposal
|
|
73
|
+
* @param {string} piece - the piece of the proposal
|
|
74
|
+
* @returns {Promise<[string, any]>}
|
|
75
|
+
*/
|
|
76
|
+
const namedHandleToBundleSpec = async (handle, sourceSpec, key, piece) => {
|
|
77
|
+
handle.bundleName = `coreProposal${String(key)}_${piece}`;
|
|
78
|
+
harden(handle);
|
|
79
|
+
return harden([handle.bundleName, { sourceSpec }]);
|
|
80
|
+
};
|
|
81
|
+
|
|
43
82
|
/**
|
|
44
83
|
* Format core proposals to be run at bootstrap:
|
|
45
84
|
* SwingSet `bundles` configuration
|
|
@@ -51,188 +90,227 @@ const findModule = (initDir, srcSpec) =>
|
|
|
51
90
|
* but for sim-chain and such, they can be declared statically in
|
|
52
91
|
* the chain configuration, in which case they are run at bootstrap.
|
|
53
92
|
*
|
|
54
|
-
* @param {
|
|
93
|
+
* @param {CoreProposals} coreProposals - governance
|
|
55
94
|
* proposals to run at chain bootstrap for scenarios such as sim-chain.
|
|
56
95
|
* @param {FilePath} [dirname]
|
|
57
|
-
* @param {
|
|
58
|
-
* @param {
|
|
96
|
+
* @param {object} [opts]
|
|
97
|
+
* @param {typeof makeEnactCoreProposalsFromBundleRef} [opts.makeEnactCoreProposals]
|
|
98
|
+
* @param {(key: PropertyKey) => PropertyKey} [opts.getSequenceForProposal]
|
|
99
|
+
* @param {typeof namedHandleToBundleSpec} [opts.handleToBundleSpec]
|
|
59
100
|
*/
|
|
60
101
|
export const extractCoreProposalBundles = async (
|
|
61
102
|
coreProposals,
|
|
62
103
|
dirname = '.',
|
|
63
|
-
|
|
64
|
-
getSequenceForProposal,
|
|
104
|
+
opts,
|
|
65
105
|
) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
getSequenceForProposal =
|
|
69
|
-
|
|
106
|
+
const {
|
|
107
|
+
makeEnactCoreProposals = makeEnactCoreProposalsFromBundleRef,
|
|
108
|
+
getSequenceForProposal = key => key,
|
|
109
|
+
handleToBundleSpec = namedHandleToBundleSpec,
|
|
110
|
+
} = opts || {};
|
|
70
111
|
|
|
71
112
|
dirname = pathResolve(dirname);
|
|
72
113
|
dirname = await fs.promises
|
|
73
114
|
.stat(dirname)
|
|
74
115
|
.then(stbuf => (stbuf.isDirectory() ? dirname : path.dirname(dirname)));
|
|
75
116
|
|
|
76
|
-
/** @type {Map<{ bundleName?: string }, { source: string, bundle?: string }>} */
|
|
117
|
+
/** @type {Map<{ bundleID?: string, bundleName?: string }, { source: string, bundle?: string }>} */
|
|
77
118
|
const bundleHandleToAbsolutePaths = new Map();
|
|
78
119
|
|
|
120
|
+
const proposalSteps =
|
|
121
|
+
'steps' in coreProposals ? coreProposals.steps : [coreProposals];
|
|
79
122
|
const bundleToSource = new Map();
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
);
|
|
123
|
+
const extractedSteps = await Promise.all(
|
|
124
|
+
proposalSteps.map((proposalStep, i) =>
|
|
125
|
+
Promise.all(
|
|
126
|
+
proposalStep.map(async (coreProposal, j) => {
|
|
127
|
+
const key = `${i}.${j}`;
|
|
128
|
+
// console.debug(`Parsing core proposal:`, coreProposal);
|
|
129
|
+
|
|
130
|
+
/** @type {string} */
|
|
131
|
+
let entrypoint;
|
|
132
|
+
/** @type {unknown[]} */
|
|
133
|
+
let args;
|
|
134
|
+
/** @type {string} */
|
|
135
|
+
let module;
|
|
136
|
+
if (typeof coreProposal === 'string') {
|
|
137
|
+
module = coreProposal;
|
|
138
|
+
entrypoint = 'defaultProposalBuilder';
|
|
139
|
+
args = [];
|
|
125
140
|
} else {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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;
|
|
141
|
+
({
|
|
142
|
+
module,
|
|
143
|
+
entrypoint = 'defaultProposalBuilder',
|
|
144
|
+
args = [],
|
|
145
|
+
} = coreProposal);
|
|
150
146
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
147
|
+
|
|
148
|
+
typeof module === 'string' ||
|
|
149
|
+
Fail`coreProposal module ${module} must be string`;
|
|
150
|
+
typeof entrypoint === 'string' ||
|
|
151
|
+
Fail`coreProposal entrypoint ${entrypoint} must be string`;
|
|
152
|
+
Array.isArray(args) || Fail`coreProposal args ${args} must be array`;
|
|
153
|
+
|
|
154
|
+
const thisProposalBundleHandles = new Set();
|
|
155
|
+
assert(getSequenceForProposal);
|
|
156
|
+
const thisProposalSequence = getSequenceForProposal(key);
|
|
157
|
+
const initPath = findModule(dirname, module);
|
|
158
|
+
const initDir = path.dirname(initPath);
|
|
159
|
+
/** @type {Record<string, import('./externalTypes.js').ProposalBuilder>} */
|
|
160
|
+
const ns = await import(initPath);
|
|
161
|
+
const install = (srcSpec, bundlePath) => {
|
|
162
|
+
const absoluteSrc = findModule(initDir, srcSpec);
|
|
163
|
+
const bundleHandle = {};
|
|
164
|
+
const absolutePaths = { source: absoluteSrc };
|
|
165
|
+
if (bundlePath) {
|
|
166
|
+
const absoluteBundle = pathResolve(initDir, bundlePath);
|
|
167
|
+
absolutePaths.bundle = absoluteBundle;
|
|
168
|
+
const oldSource = bundleToSource.get(absoluteBundle);
|
|
169
|
+
if (oldSource) {
|
|
170
|
+
oldSource === absoluteSrc ||
|
|
171
|
+
Fail`${bundlePath} already installed from ${oldSource}, now ${absoluteSrc}`;
|
|
172
|
+
} else {
|
|
173
|
+
bundleToSource.set(absoluteBundle, absoluteSrc);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Don't harden the bundleHandle since we need to set the bundleName on
|
|
177
|
+
// its unique identity later.
|
|
178
|
+
thisProposalBundleHandles.add(bundleHandle);
|
|
179
|
+
bundleHandleToAbsolutePaths.set(
|
|
180
|
+
bundleHandle,
|
|
181
|
+
harden(absolutePaths),
|
|
182
|
+
);
|
|
183
|
+
return bundleHandle;
|
|
184
|
+
};
|
|
185
|
+
/** @type {import('./externalTypes.js').PublishBundleRef} */
|
|
186
|
+
const publishRef = async handleP => {
|
|
187
|
+
const handle = await handleP;
|
|
188
|
+
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 */
|
|
189
|
+
// @ts-ignore xxx types
|
|
190
|
+
bundleHandleToAbsolutePaths.has(handle) ||
|
|
191
|
+
Fail`${handle} not in installed bundles`;
|
|
192
|
+
return handle;
|
|
193
|
+
};
|
|
194
|
+
const proposal = await ns[entrypoint](
|
|
195
|
+
{
|
|
196
|
+
publishRef,
|
|
197
|
+
// @ts-expect-error not statically verified to return a full obj
|
|
198
|
+
install,
|
|
199
|
+
},
|
|
200
|
+
...args,
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
// Add the proposal bundle handles in sorted order.
|
|
204
|
+
const bundleSpecEntries = await Promise.all(
|
|
205
|
+
[...thisProposalBundleHandles.keys()]
|
|
206
|
+
.map(handle => [handle, bundleHandleToAbsolutePaths.get(handle)])
|
|
207
|
+
.sort(([_hnda, { source: a }], [_hndb, { source: b }]) => {
|
|
208
|
+
if (a < b) {
|
|
209
|
+
return -1;
|
|
210
|
+
}
|
|
211
|
+
if (a > b) {
|
|
212
|
+
return 1;
|
|
213
|
+
}
|
|
214
|
+
return 0;
|
|
215
|
+
})
|
|
216
|
+
.map(async ([handle, absolutePaths], k) => {
|
|
217
|
+
// Transform the bundle handle identity into a bundleName reference.
|
|
218
|
+
const specEntry = await handleToBundleSpec(
|
|
219
|
+
handle,
|
|
220
|
+
absolutePaths.source,
|
|
221
|
+
thisProposalSequence,
|
|
222
|
+
String(k),
|
|
223
|
+
);
|
|
224
|
+
harden(handle);
|
|
225
|
+
return specEntry;
|
|
226
|
+
}),
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
// Now that we've assigned all the bundleNames and hardened the
|
|
230
|
+
// handles, we can extract the behavior bundle.
|
|
231
|
+
const { sourceSpec, getManifestCall } = await deeplyFulfilledObject(
|
|
232
|
+
harden(proposal),
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
const proposalSource = pathResolve(initDir, sourceSpec);
|
|
236
|
+
const proposalNS = await import(proposalSource);
|
|
237
|
+
const [manifestGetterName, ...manifestGetterArgs] = getManifestCall;
|
|
238
|
+
manifestGetterName in proposalNS ||
|
|
239
|
+
Fail`proposal ${proposalSource} missing export ${manifestGetterName}`;
|
|
240
|
+
const { manifest: customManifest } = await proposalNS[
|
|
241
|
+
manifestGetterName
|
|
242
|
+
](harden({ restoreRef: () => null }), ...manifestGetterArgs);
|
|
243
|
+
|
|
244
|
+
const behaviorBundleHandle = {};
|
|
245
|
+
const specEntry = await handleToBundleSpec(
|
|
246
|
+
behaviorBundleHandle,
|
|
247
|
+
proposalSource,
|
|
248
|
+
thisProposalSequence,
|
|
249
|
+
'proposalNS',
|
|
250
|
+
);
|
|
251
|
+
bundleSpecEntries.unshift(specEntry);
|
|
252
|
+
|
|
253
|
+
bundleHandleToAbsolutePaths.set(
|
|
254
|
+
behaviorBundleHandle,
|
|
255
|
+
harden({
|
|
256
|
+
source: proposalSource,
|
|
257
|
+
}),
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
return /** @type {const} */ ([
|
|
261
|
+
key,
|
|
262
|
+
{
|
|
263
|
+
ref: behaviorBundleHandle,
|
|
264
|
+
call: getManifestCall,
|
|
265
|
+
customManifest,
|
|
266
|
+
bundleSpecs: bundleSpecEntries,
|
|
267
|
+
},
|
|
268
|
+
]);
|
|
269
|
+
}),
|
|
270
|
+
),
|
|
271
|
+
),
|
|
205
272
|
);
|
|
206
273
|
|
|
207
274
|
// Extract all the bundle specs in already-sorted order.
|
|
208
275
|
const bundles = Object.fromEntries(
|
|
209
|
-
|
|
276
|
+
extractedSteps.flatMap(step =>
|
|
277
|
+
step.flatMap(([_key, { bundleSpecs }]) => bundleSpecs),
|
|
278
|
+
),
|
|
210
279
|
);
|
|
211
280
|
harden(bundles);
|
|
212
281
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
282
|
+
const codeSteps = extractedSteps.map(extractedStep => {
|
|
283
|
+
// Extract the manifest references and calls.
|
|
284
|
+
const metadataRecords = extractedStep.map(([_key, extractedSpec]) => {
|
|
285
|
+
const { ref, call, customManifest } = extractedSpec;
|
|
286
|
+
return { ref, call, customManifest };
|
|
287
|
+
});
|
|
288
|
+
harden(metadataRecords);
|
|
220
289
|
|
|
221
|
-
|
|
222
|
-
// This is generated by @agoric/
|
|
290
|
+
const code = `\
|
|
291
|
+
// This is generated by @agoric/deploy-script-support/src/extract-proposal.js - DO NOT EDIT
|
|
223
292
|
/* eslint-disable */
|
|
224
293
|
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
const makeCoreProposalBehavior = ${makeCoreProposalBehavior};
|
|
294
|
+
const metadataRecords = harden(${stringify(metadataRecords, true)});
|
|
228
295
|
|
|
229
|
-
|
|
296
|
+
// Make an enactCoreProposals function and "export" it by way of script completion value.
|
|
297
|
+
// It is constructed by an IIFE to ensure the absence of global bindings for
|
|
298
|
+
// makeCoreProposalBehavior and makeEnactCoreProposals (the latter referencing the former),
|
|
299
|
+
// which may not be necessary but preserves behavior pre-dating
|
|
300
|
+
// https://github.com/Agoric/agoric-sdk/pull/8712 .
|
|
301
|
+
const enactCoreProposals = ((
|
|
302
|
+
makeCoreProposalBehavior = ${makeCoreProposalBehavior},
|
|
303
|
+
makeEnactCoreProposals = ${makeEnactCoreProposals},
|
|
304
|
+
) => makeEnactCoreProposals({ metadataRecords, E }))();
|
|
305
|
+
enactCoreProposals;
|
|
230
306
|
`;
|
|
307
|
+
return defangAndTrim(code);
|
|
308
|
+
});
|
|
231
309
|
|
|
232
310
|
// console.debug('created bundles from proposals:', coreProposals, bundles);
|
|
233
|
-
return {
|
|
311
|
+
return harden({
|
|
234
312
|
bundles,
|
|
235
|
-
|
|
313
|
+
codeSteps,
|
|
236
314
|
bundleHandleToAbsolutePaths,
|
|
237
|
-
};
|
|
315
|
+
});
|
|
238
316
|
};
|
package/src/getBundlerMaker.js
CHANGED
|
@@ -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/offer.js
CHANGED
|
@@ -19,7 +19,7 @@ import { AmountMath } from '@agoric/ertp/src/amountMath.js';
|
|
|
19
19
|
* @param {ERef<any>} walletAdmin - an internal type of the
|
|
20
20
|
* wallet, not defined here
|
|
21
21
|
* @param {ERef<ZoeService>} zoe
|
|
22
|
-
* @param {ERef<Purse
|
|
22
|
+
* @param {ERef<Purse<'set'>>} zoeInvitationPurse
|
|
23
23
|
*/
|
|
24
24
|
export const makeOfferAndFindInvitationAmount = (
|
|
25
25
|
walletAdmin,
|
|
@@ -28,7 +28,7 @@ export const makeOfferAndFindInvitationAmount = (
|
|
|
28
28
|
) => {
|
|
29
29
|
/**
|
|
30
30
|
* @param {Record<string, any>} invitationDetailsCriteria
|
|
31
|
-
* @returns {Promise<Amount
|
|
31
|
+
* @returns {Promise<Amount<'set'>>} invitationAmount
|
|
32
32
|
*/
|
|
33
33
|
const findInvitationAmount = async invitationDetailsCriteria => {
|
|
34
34
|
const invitationAmount = await E(zoeInvitationPurse).getCurrentAmount();
|
package/src/writeCoreProposal.js
CHANGED
|
@@ -7,6 +7,25 @@ import { createBundles } from '@agoric/internal/src/node/createBundles.js';
|
|
|
7
7
|
import { defangAndTrim, mergePermits, stringify } from './code-gen.js';
|
|
8
8
|
import { makeCoreProposalBehavior, permits } from './coreProposalBehavior.js';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @callback WriteCoreProposal
|
|
12
|
+
* @param {string} filePrefix
|
|
13
|
+
* @param {import('./externalTypes.js').ProposalBuilder} proposalBuilder
|
|
14
|
+
* @returns {Promise<void>}
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param {*} homeP
|
|
20
|
+
* @param {*} endowments
|
|
21
|
+
* @param {{
|
|
22
|
+
* getBundlerMaker: () => Promise<import('./getBundlerMaker.js').BundleMaker>,
|
|
23
|
+
* getBundleSpec: (...args: *) => Promise<import('./externalTypes.js').ManifestBundleRef>,
|
|
24
|
+
* log?: typeof console.log,
|
|
25
|
+
* writeFile?: typeof fs.promises.writeFile
|
|
26
|
+
* }} io
|
|
27
|
+
* @returns {WriteCoreProposal}
|
|
28
|
+
*/
|
|
10
29
|
export const makeWriteCoreProposal = (
|
|
11
30
|
homeP,
|
|
12
31
|
endowments,
|
|
@@ -20,6 +39,7 @@ export const makeWriteCoreProposal = (
|
|
|
20
39
|
const { bundleSource, pathResolve } = endowments;
|
|
21
40
|
|
|
22
41
|
let bundlerCache;
|
|
42
|
+
/** @returns {import('./getBundlerMaker.js').Bundler} */
|
|
23
43
|
const getBundler = () => {
|
|
24
44
|
if (!bundlerCache) {
|
|
25
45
|
bundlerCache = E(getBundlerMaker()).makeBundler({
|
|
@@ -32,15 +52,15 @@ export const makeWriteCoreProposal = (
|
|
|
32
52
|
const mergeProposalPermit = async (proposal, additionalPermits) => {
|
|
33
53
|
const {
|
|
34
54
|
sourceSpec,
|
|
35
|
-
getManifestCall: [
|
|
55
|
+
getManifestCall: [manifestGetterName, ...manifestGetterArgs],
|
|
36
56
|
} = proposal;
|
|
37
57
|
|
|
38
|
-
const
|
|
58
|
+
const proposalNS = await import(pathResolve(sourceSpec));
|
|
39
59
|
|
|
40
60
|
// We only care about the manifest, not any restoreRef calls.
|
|
41
|
-
const { manifest } = await
|
|
42
|
-
{ restoreRef: x => `restoreRef:${x}` },
|
|
43
|
-
...
|
|
61
|
+
const { manifest } = await proposalNS[manifestGetterName](
|
|
62
|
+
harden({ restoreRef: x => `restoreRef:${x}` }),
|
|
63
|
+
...manifestGetterArgs,
|
|
44
64
|
);
|
|
45
65
|
|
|
46
66
|
const mergedPermits = mergePermits(manifest);
|
|
@@ -50,8 +70,18 @@ export const makeWriteCoreProposal = (
|
|
|
50
70
|
};
|
|
51
71
|
};
|
|
52
72
|
|
|
53
|
-
let mutex =
|
|
73
|
+
let mutex =
|
|
74
|
+
/** @type {Promise<import('./externalTypes.js').ManifestBundleRef | undefined>} */ (
|
|
75
|
+
Promise.resolve()
|
|
76
|
+
);
|
|
77
|
+
/** @type {WriteCoreProposal} */
|
|
54
78
|
const writeCoreProposal = async (filePrefix, proposalBuilder) => {
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @param {string} entrypoint
|
|
82
|
+
* @param {string} [bundlePath]
|
|
83
|
+
* @returns {Promise<NodeModule>}
|
|
84
|
+
*/
|
|
55
85
|
const getBundle = async (entrypoint, bundlePath) => {
|
|
56
86
|
if (!bundlePath) {
|
|
57
87
|
return bundleSource(pathResolve(entrypoint));
|
|
@@ -62,20 +92,36 @@ export const makeWriteCoreProposal = (
|
|
|
62
92
|
return ns.default;
|
|
63
93
|
};
|
|
64
94
|
|
|
65
|
-
|
|
95
|
+
const bundles = [];
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Install an entrypoint.
|
|
99
|
+
*
|
|
100
|
+
* @param {string} entrypoint
|
|
101
|
+
* @param {string} [bundlePath]
|
|
102
|
+
* @param {unknown} [opts]
|
|
103
|
+
* @returns {Promise<import('./externalTypes.js').ManifestBundleRef>}
|
|
104
|
+
*/
|
|
66
105
|
const install = async (entrypoint, bundlePath, opts) => {
|
|
67
106
|
const bundle = getBundle(entrypoint, bundlePath);
|
|
68
107
|
|
|
69
108
|
// Serialise the installations.
|
|
70
|
-
mutex = E.when(mutex, () => {
|
|
109
|
+
mutex = E.when(mutex, async () => {
|
|
71
110
|
// console.log('installing', { filePrefix, entrypoint, bundlePath });
|
|
72
|
-
|
|
111
|
+
const spec = await getBundleSpec(bundle, getBundler, opts);
|
|
112
|
+
bundles.push({
|
|
113
|
+
entrypoint,
|
|
114
|
+
...spec,
|
|
115
|
+
});
|
|
116
|
+
return spec;
|
|
73
117
|
});
|
|
118
|
+
// @ts-expect-error xxx mutex type narrowing
|
|
74
119
|
return mutex;
|
|
75
120
|
};
|
|
76
121
|
|
|
77
122
|
// Await a reference then publish to the board.
|
|
78
123
|
const cmds = [];
|
|
124
|
+
/** @param {Promise<import('./externalTypes.js').ManifestBundleRef>} refP */
|
|
79
125
|
const publishRef = async refP => {
|
|
80
126
|
const { fileName, ...ref } = await refP;
|
|
81
127
|
if (fileName) {
|
|
@@ -93,7 +139,7 @@ export const makeWriteCoreProposal = (
|
|
|
93
139
|
// console.log('created', { filePrefix, sourceSpec, getManifestCall });
|
|
94
140
|
|
|
95
141
|
// Extract the top-level permit.
|
|
96
|
-
const { permits: proposalPermit, manifest:
|
|
142
|
+
const { permits: proposalPermit, manifest: customManifest } =
|
|
97
143
|
await mergeProposalPermit(proposal, permits);
|
|
98
144
|
|
|
99
145
|
// Get an install
|
|
@@ -106,10 +152,14 @@ export const makeWriteCoreProposal = (
|
|
|
106
152
|
|
|
107
153
|
const manifestBundleRef = ${stringify(manifestBundleRef)};
|
|
108
154
|
const getManifestCall = harden(${stringify(getManifestCall, true)});
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
// Make
|
|
112
|
-
|
|
155
|
+
const customManifest = ${stringify(customManifest, true)};
|
|
156
|
+
|
|
157
|
+
// Make a behavior function and "export" it by way of script completion value.
|
|
158
|
+
// It is constructed by an anonymous invocation to ensure the absence of a global binding
|
|
159
|
+
// for makeCoreProposalBehavior, which may not be necessary but preserves behavior pre-dating
|
|
160
|
+
// https://github.com/Agoric/agoric-sdk/pull/8712 .
|
|
161
|
+
const behavior = (${makeCoreProposalBehavior})({ manifestBundleRef, getManifestCall, customManifest, E });
|
|
162
|
+
behavior;
|
|
113
163
|
`;
|
|
114
164
|
|
|
115
165
|
const trimmed = defangAndTrim(code);
|
|
@@ -125,6 +175,18 @@ const overrideManifest = ${stringify(overrideManifest, true)};
|
|
|
125
175
|
log(`creating ${proposalJsFile}`);
|
|
126
176
|
await writeFile(proposalJsFile, trimmed);
|
|
127
177
|
|
|
178
|
+
const plan = {
|
|
179
|
+
name: filePrefix,
|
|
180
|
+
script: proposalJsFile,
|
|
181
|
+
permit: proposalPermitJsonFile,
|
|
182
|
+
bundles,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
await writeFile(
|
|
186
|
+
`${filePrefix}-plan.json`,
|
|
187
|
+
`${JSON.stringify(plan, null, 2)}\n`,
|
|
188
|
+
);
|
|
189
|
+
|
|
128
190
|
log(`\
|
|
129
191
|
You can now run a governance submission command like:
|
|
130
192
|
agd tx gov submit-proposal swingset-core-eval ${proposalPermitJsonFile} ${proposalJsFile} \\
|