agoric 0.21.2-other-dev-8f8782b.0 → 0.21.2-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.
- package/README.md +0 -73
- package/package.json +60 -43
- package/src/anylogger-agoric.js +31 -16
- package/src/bin-agops.js +8 -12
- package/src/chain-config.js +42 -16
- package/src/commands/auction.js +22 -19
- package/src/commands/gov.js +475 -0
- package/src/commands/inter.js +44 -62
- package/src/commands/oracle.js +144 -87
- package/src/commands/perf.js +20 -16
- package/src/commands/psm.js +29 -26
- package/src/commands/reserve.js +13 -6
- package/src/commands/test-upgrade.js +15 -8
- package/src/commands/vaults.js +31 -18
- package/src/commands/wallet.js +121 -48
- package/src/cosmos.js +3 -3
- package/src/deploy.js +10 -5
- package/src/entrypoint.js +2 -5
- package/src/follow.js +14 -10
- package/src/helpers.js +10 -5
- package/src/init.js +2 -9
- package/src/install.js +18 -25
- package/src/lib/bundles.js +102 -0
- package/src/lib/chain.js +71 -35
- package/src/lib/format.js +28 -34
- package/src/lib/index.js +7 -0
- package/src/lib/packageManager.js +24 -0
- package/src/lib/wallet.js +44 -144
- package/src/main-publish.js +2 -3
- package/src/main.js +95 -125
- package/src/open.js +8 -10
- package/src/publish.js +4 -9
- package/src/scripts.js +14 -32
- package/src/sdk-package-names.js +22 -9
- package/src/set-defaults.js +2 -1
- package/src/start.js +59 -68
- package/tools/getting-started.js +272 -0
- package/tools/resm-plugin/deploy.js +18 -0
- package/tools/resm-plugin/package.json +12 -0
- package/tools/resm-plugin/src/output.js +1 -0
- package/tools/resm-plugin/src/plugin.js +17 -0
- package/CHANGELOG.md +0 -1069
- package/src/commands/ec.js +0 -314
- package/src/lib/rpc.js +0 -272
package/src/entrypoint.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/* eslint-env node */
|
|
2
3
|
// @jessie-check
|
|
3
4
|
|
|
4
|
-
/* global process */
|
|
5
|
-
|
|
6
|
-
import '@endo/init/pre.js';
|
|
7
|
-
import 'esm';
|
|
8
|
-
import '@agoric/casting/node-fetch-shim.js';
|
|
9
5
|
import '@endo/init/legacy.js';
|
|
10
6
|
|
|
11
7
|
import path from 'path';
|
|
@@ -25,6 +21,7 @@ const log = anylogger('agoric');
|
|
|
25
21
|
const progname = path.basename(process.argv[1]);
|
|
26
22
|
|
|
27
23
|
const stdout = str => process.stdout.write(str);
|
|
24
|
+
/** @type {(...args: ConstructorParameters<typeof WebSocket>) => WebSocket} */
|
|
28
25
|
const makeWebSocket = (...args) => new WebSocket(...args);
|
|
29
26
|
|
|
30
27
|
const rawArgs = process.argv.slice(2);
|
package/src/follow.js
CHANGED
|
@@ -126,25 +126,29 @@ export default async function followerMain(progname, rawArgs, powers, opts) {
|
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
const leaderOptions = makeLeaderOptions({
|
|
130
|
-
sleep,
|
|
131
|
-
jitter,
|
|
132
|
-
log: verbose ? console.warn : () => undefined,
|
|
133
|
-
});
|
|
134
|
-
|
|
135
129
|
const [_cmd, ...specs] = rawArgs;
|
|
136
130
|
|
|
137
131
|
verbose && console.warn('Creating leader for', bootstrap);
|
|
138
|
-
const leader = makeLeader(
|
|
132
|
+
const leader = makeLeader(
|
|
133
|
+
bootstrap,
|
|
134
|
+
makeLeaderOptions({
|
|
135
|
+
sleep,
|
|
136
|
+
jitter,
|
|
137
|
+
log: verbose ? console.warn : () => undefined,
|
|
138
|
+
}),
|
|
139
|
+
);
|
|
139
140
|
const iterate = opts.lossy ? iterateLatest : iterateEach;
|
|
140
141
|
await Promise.all(
|
|
141
142
|
specs.map(async spec => {
|
|
142
143
|
verbose && console.warn('Following', spec);
|
|
143
144
|
const castingSpec = makeCastingSpec(spec);
|
|
144
145
|
const follower = makeFollower(castingSpec, leader, followerOptions);
|
|
145
|
-
for await (const
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
for await (const obj of iterate(follower)) {
|
|
147
|
+
if ('error' in obj) {
|
|
148
|
+
console.error('Error following:', obj.error);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const { value, blockHeight, currentBlockHeight } = obj;
|
|
148
152
|
const blockHeightPrefix = opts.blockHeight ? `${blockHeight}:` : '';
|
|
149
153
|
const currentBlockHeightPrefix = opts.currentBlockHeight
|
|
150
154
|
? `${currentBlockHeight}:`
|
package/src/helpers.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* eslint-env node */
|
|
2
2
|
// @ts-check
|
|
3
3
|
|
|
4
|
-
/** @
|
|
4
|
+
/** @import { ChildProcess } from 'child_process' */
|
|
5
|
+
|
|
6
|
+
// Backwards compatibility
|
|
7
|
+
export { fetchEnvNetworkConfig as getNetworkConfig } from '@agoric/client-utils';
|
|
5
8
|
|
|
6
9
|
export const getSDKBinaries = ({
|
|
7
10
|
jsPfx = '../..',
|
|
@@ -40,10 +43,12 @@ export const makePspawn = ({
|
|
|
40
43
|
*
|
|
41
44
|
* @param {string} cmd command name to run
|
|
42
45
|
* @param {Array<string>} cargs arguments to the command
|
|
43
|
-
* @param {object}
|
|
44
|
-
* @param {string
|
|
46
|
+
* @param {object} [opts]
|
|
47
|
+
* @param {string} [opts.cwd]
|
|
48
|
+
* @param {string | [string, string, string]} [opts.stdio] standard IO
|
|
45
49
|
* specification
|
|
46
|
-
* @param {Record<string, string | undefined>} [
|
|
50
|
+
* @param {Record<string, string | undefined>} [opts.env] environment
|
|
51
|
+
* @param {boolean} [opts.detached] whether the child process should be detached
|
|
47
52
|
* @returns {Promise<number> & { childProcess: ChildProcess }}} promise for
|
|
48
53
|
* exit status. The return result has a `childProcess` property to obtain
|
|
49
54
|
* control over the running process
|
package/src/init.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { makePspawn } from './helpers.js';
|
|
3
3
|
|
|
4
|
-
// Ambient types. Needed only for dev but this does a runtime import.
|
|
5
|
-
// https://github.com/Agoric/agoric-sdk/issues/6512
|
|
6
|
-
import '@endo/captp/src/types.js';
|
|
7
|
-
import '@agoric/swingset-vat/exported.js';
|
|
8
|
-
import '@agoric/swingset-vat/src/vats/network/types.js';
|
|
9
|
-
|
|
10
4
|
// Use either an absolute template URL, or find it relative to DAPP_URL_BASE.
|
|
11
5
|
const gitURL = (relativeOrAbsoluteURL, base) => {
|
|
12
6
|
const url = new URL(relativeOrAbsoluteURL, base);
|
|
@@ -40,9 +34,10 @@ export default async function initMain(_progname, rawArgs, priv, opts) {
|
|
|
40
34
|
dappBranch = ['-b', opts.dappBranch];
|
|
41
35
|
}
|
|
42
36
|
|
|
37
|
+
const shallow = ['--depth', '1', '--shallow-submodules'];
|
|
43
38
|
const exitStatus = await pspawn(
|
|
44
39
|
'git',
|
|
45
|
-
['clone', '--origin=upstream', dappURL, DIR, ...dappBranch],
|
|
40
|
+
['clone', '--origin=upstream', ...shallow, dappURL, DIR, ...dappBranch],
|
|
46
41
|
{
|
|
47
42
|
stdio: 'inherit',
|
|
48
43
|
},
|
|
@@ -60,7 +55,6 @@ export default async function initMain(_progname, rawArgs, priv, opts) {
|
|
|
60
55
|
const path = `${DIR}/${dir}package.json`;
|
|
61
56
|
log('rewriting ', path);
|
|
62
57
|
|
|
63
|
-
// eslint-disable-next-line no-await-in-loop
|
|
64
58
|
const contents = await fs.readFile(path, 'utf-8');
|
|
65
59
|
const pkg = JSON.parse(contents.replace(/@DIR@/g, DIR));
|
|
66
60
|
if (dir === '') {
|
|
@@ -74,7 +68,6 @@ export default async function initMain(_progname, rawArgs, priv, opts) {
|
|
|
74
68
|
pkg.name = `${DIR}${pkg.name.substr(topLevelName.length)}`;
|
|
75
69
|
const json = JSON.stringify(pkg, undefined, 2);
|
|
76
70
|
|
|
77
|
-
// eslint-disable-next-line no-await-in-loop
|
|
78
71
|
await fs.writeFile(path, json);
|
|
79
72
|
}
|
|
80
73
|
|
package/src/install.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* eslint-env node */
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
import { execFileSync } from 'child_process';
|
|
4
5
|
import { makePspawn } from './helpers.js';
|
|
5
6
|
import DEFAULT_SDK_PACKAGE_NAMES from './sdk-package-names.js';
|
|
7
|
+
import { listWorkspaces } from './lib/packageManager.js';
|
|
6
8
|
|
|
7
9
|
const REQUIRED_AGORIC_START_PACKAGES = [
|
|
8
10
|
'@agoric/solo',
|
|
9
11
|
'@agoric/cosmic-swingset',
|
|
10
12
|
];
|
|
11
13
|
|
|
12
|
-
const
|
|
13
|
-
const dirname = path.dirname(filename);
|
|
14
|
+
const dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
14
15
|
|
|
15
16
|
export default async function installMain(progname, rawArgs, powers, opts) {
|
|
16
17
|
const { anylogger, fs, spawn } = powers;
|
|
@@ -31,26 +32,16 @@ export default async function installMain(progname, rawArgs, powers, opts) {
|
|
|
31
32
|
const rimraf = file => pspawn('rm', ['-rf', file]);
|
|
32
33
|
|
|
33
34
|
async function getWorktreePackagePaths(cwd = '.', map = new Map()) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
cwd,
|
|
38
|
-
stdio: ['inherit', 'pipe', 'inherit'],
|
|
39
|
-
});
|
|
40
|
-
const stdout = [];
|
|
41
|
-
p.childProcess.stdout.on('data', out => stdout.push(out));
|
|
42
|
-
await p;
|
|
43
|
-
const d = JSON.parse(Buffer.concat(stdout).toString('utf-8'));
|
|
44
|
-
Object.entries(d).forEach(([name, { location }]) =>
|
|
45
|
-
map.set(name, path.resolve(cwd, location)),
|
|
46
|
-
);
|
|
35
|
+
for (const { name, location } of listWorkspaces({ execFileSync }, cwd)) {
|
|
36
|
+
map.set(name, path.resolve(cwd, location));
|
|
37
|
+
}
|
|
47
38
|
return map;
|
|
48
39
|
}
|
|
49
40
|
|
|
50
41
|
let subdirs;
|
|
51
42
|
const workTrees = ['.'];
|
|
52
43
|
let sdkWorktree;
|
|
53
|
-
/** @type {Map<string, string>} */
|
|
44
|
+
/** @type {Map<string, string | null>} */
|
|
54
45
|
const sdkPackageToPath = new Map();
|
|
55
46
|
const linkFolder = path.resolve(`_agstate/yarn-links`);
|
|
56
47
|
const linkFlags = [];
|
|
@@ -61,7 +52,6 @@ export default async function installMain(progname, rawArgs, powers, opts) {
|
|
|
61
52
|
const yarnInstallEachWorktree = async (phase, ...flags) => {
|
|
62
53
|
for await (const workTree of workTrees) {
|
|
63
54
|
log.info(`yarn install ${phase} in ${workTree}`);
|
|
64
|
-
// eslint-disable-next-line no-await-in-loop
|
|
65
55
|
const yarnInstall = await pspawn(
|
|
66
56
|
'yarn',
|
|
67
57
|
[...linkFlags, 'install', ...flags],
|
|
@@ -133,7 +123,6 @@ export default async function installMain(progname, rawArgs, powers, opts) {
|
|
|
133
123
|
// Ensure we update the package.json before exiting.
|
|
134
124
|
const updatePackageJson = async () => {
|
|
135
125
|
// Don't update on exit anymore.
|
|
136
|
-
// eslint-disable-next-line no-use-before-define
|
|
137
126
|
process.off('beforeExit', updatePackageJsonOnExit);
|
|
138
127
|
log.info(`updating ${pjson}`);
|
|
139
128
|
await fs.writeFile(
|
|
@@ -172,12 +161,9 @@ export default async function installMain(progname, rawArgs, powers, opts) {
|
|
|
172
161
|
.then(results => {
|
|
173
162
|
// After all have settled, throw any errors.
|
|
174
163
|
const failures = results.filter(
|
|
175
|
-
|
|
164
|
+
result => result.status !== 'fulfilled',
|
|
176
165
|
);
|
|
177
166
|
if (failures.length) {
|
|
178
|
-
if (typeof AggregateError !== 'function') {
|
|
179
|
-
throw failures[0].reason;
|
|
180
|
-
}
|
|
181
167
|
throw AggregateError(
|
|
182
168
|
failures.map(({ reason }) => reason),
|
|
183
169
|
'Failed to prune',
|
|
@@ -269,7 +255,9 @@ export default async function installMain(progname, rawArgs, powers, opts) {
|
|
|
269
255
|
};
|
|
270
256
|
await Promise.all(subdirs.map(removeNodeModulesSymlinks));
|
|
271
257
|
} else {
|
|
272
|
-
|
|
258
|
+
for (const name of DEFAULT_SDK_PACKAGE_NAMES) {
|
|
259
|
+
sdkPackageToPath.set(name, null);
|
|
260
|
+
}
|
|
273
261
|
}
|
|
274
262
|
|
|
275
263
|
if (forceSdkVersion !== undefined) {
|
|
@@ -287,7 +275,12 @@ export default async function installMain(progname, rawArgs, powers, opts) {
|
|
|
287
275
|
// Create symlinks to the SDK packages.
|
|
288
276
|
await Promise.all(
|
|
289
277
|
[...sdkPackageToPath.entries()].map(async ([pjName, dir]) => {
|
|
278
|
+
if (typeof dir !== 'string') {
|
|
279
|
+
throw Error(`unexpected incomplete package mapping: ${pjName}`);
|
|
280
|
+
}
|
|
281
|
+
|
|
290
282
|
const SUBOPTIMAL = false;
|
|
283
|
+
await null;
|
|
291
284
|
if (SUBOPTIMAL) {
|
|
292
285
|
// This use of yarn is noisy and slow.
|
|
293
286
|
await pspawn('yarn', [...linkFlags, 'unlink', pjName]);
|
|
@@ -303,7 +296,7 @@ export default async function installMain(progname, rawArgs, powers, opts) {
|
|
|
303
296
|
log('linking', linkName);
|
|
304
297
|
return fs
|
|
305
298
|
.mkdir(linkDir, { recursive: true })
|
|
306
|
-
.then(
|
|
299
|
+
.then(() => fs.symlink(path.relative(linkDir, dir), linkName));
|
|
307
300
|
}),
|
|
308
301
|
);
|
|
309
302
|
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/* eslint-env node */
|
|
3
|
+
|
|
4
|
+
import assert from 'node:assert/strict';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
|
|
8
|
+
import { ZipReader } from '@endo/zip';
|
|
9
|
+
|
|
10
|
+
/** @import {Bundle} from '@agoric/swingset-vat'; */
|
|
11
|
+
/** @import {CoreEvalPlan} from '@agoric/deploy-script-support/src/writeCoreEvalParts.js' */
|
|
12
|
+
|
|
13
|
+
// exported for testing
|
|
14
|
+
export const PACKAGE_NAME_RE = /^(?:@[^/]+\/)?[^/]+/;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {{ name: string, label: string, location: string, modules: Record<string, {compartment: string, module: string}>}} Compartment
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef CompartmentMap
|
|
22
|
+
* @property {string[]} tags
|
|
23
|
+
* @property {{compartment: string, module: string}} entry
|
|
24
|
+
* @property {Record<string, Compartment>} compartments
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** @param {Bundle} bundleObj*/
|
|
28
|
+
export const extractBundleInfo = async bundleObj => {
|
|
29
|
+
if (bundleObj.moduleFormat !== 'endoZipBase64') {
|
|
30
|
+
throw Error('only endoZipBase64 is supported');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const contents = Buffer.from(bundleObj.endoZipBase64, 'base64');
|
|
34
|
+
|
|
35
|
+
const zipReader = new ZipReader(contents);
|
|
36
|
+
const { files } = zipReader;
|
|
37
|
+
|
|
38
|
+
const cmapEntry = files.get('compartment-map.json');
|
|
39
|
+
/** @type {CompartmentMap} */
|
|
40
|
+
const compartmentMap = JSON.parse(Buffer.from(cmapEntry.content).toString());
|
|
41
|
+
|
|
42
|
+
// XXX mapIter better but requires SES
|
|
43
|
+
const fileSizes = Object.fromEntries(
|
|
44
|
+
Array.from(files.values()).map(f => [
|
|
45
|
+
f.name,
|
|
46
|
+
// bundle contents are not compressed
|
|
47
|
+
f.content.length,
|
|
48
|
+
]),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return { compartmentMap, fileSizes };
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// UNTIL https://github.com/endojs/endo/issues/1656
|
|
55
|
+
/** @param {string} bundleFilename */
|
|
56
|
+
export const statBundle = async bundleFilename => {
|
|
57
|
+
const bundle = fs.readFileSync(bundleFilename, 'utf8');
|
|
58
|
+
/** @type {Bundle} */
|
|
59
|
+
const bundleObj = JSON.parse(bundle);
|
|
60
|
+
console.log('\nBUNDLE', bundleObj.moduleFormat, bundleFilename);
|
|
61
|
+
|
|
62
|
+
const info = await extractBundleInfo(bundleObj);
|
|
63
|
+
assert(info, 'no bundle info');
|
|
64
|
+
|
|
65
|
+
/** @type {Record<string, number>} */
|
|
66
|
+
const byPackage = {};
|
|
67
|
+
let totalSize = 0;
|
|
68
|
+
for (const [filename, size] of Object.entries(info.fileSizes)) {
|
|
69
|
+
totalSize += size;
|
|
70
|
+
if (filename === 'compartment-map.json') {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const packageName = filename.match(PACKAGE_NAME_RE)?.[0];
|
|
74
|
+
assert(packageName, `invalid filename ${filename}`);
|
|
75
|
+
byPackage[packageName] ||= 0;
|
|
76
|
+
byPackage[packageName] += size;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log('Sum of file sizes in each package:');
|
|
80
|
+
console.table(byPackage);
|
|
81
|
+
|
|
82
|
+
console.log('total size:', totalSize);
|
|
83
|
+
console.log('\nTo explore the contents:\n');
|
|
84
|
+
console.log(
|
|
85
|
+
` DIR=$(mktemp -d); cat ${bundleFilename} | jq -r .endoZipBase64 | base64 -d | tar xC $DIR; open $DIR`,
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/** @param {string} path */
|
|
90
|
+
export const statPlans = async path => {
|
|
91
|
+
const files = await fs.promises.readdir(path);
|
|
92
|
+
const planfiles = files.filter(f => f.endsWith('plan.json'));
|
|
93
|
+
|
|
94
|
+
for (const planfile of planfiles) {
|
|
95
|
+
/** @type {CoreEvalPlan} */
|
|
96
|
+
const plan = JSON.parse(fs.readFileSync(join(path, planfile), 'utf8'));
|
|
97
|
+
console.log('\n**\nPLAN', plan.name);
|
|
98
|
+
for (const bundle of plan.bundles) {
|
|
99
|
+
await statBundle(bundle.fileName);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
package/src/lib/chain.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
/*
|
|
2
|
+
/* eslint-env node */
|
|
3
3
|
import { normalizeBech32 } from '@cosmjs/encoding';
|
|
4
4
|
import { execFileSync as execFileSyncAmbient } from 'child_process';
|
|
5
|
+
import { makeAgoricQueryClient } from '@agoric/client-utils';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @import {MinimalNetworkConfig} from '@agoric/client-utils';
|
|
9
|
+
* @import {Params, ParamsSDKType} from '@agoric/cosmic-proto/agoric/swingset/swingset.js';
|
|
10
|
+
*/
|
|
5
11
|
|
|
6
12
|
const agdBinary = 'agd';
|
|
7
13
|
|
|
@@ -34,10 +40,42 @@ export const normalizeAddressWithOptions = (
|
|
|
34
40
|
};
|
|
35
41
|
harden(normalizeAddressWithOptions);
|
|
36
42
|
|
|
43
|
+
/** @typedef {number | 'auto' | ['auto', adjustment?: number | undefined]} GasLimit */
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {GasLimit} limit
|
|
47
|
+
* @returns {string[]}
|
|
48
|
+
*/
|
|
49
|
+
const makeGasOpts = limit => {
|
|
50
|
+
if (Number.isFinite(limit) || limit === 'auto') {
|
|
51
|
+
return [`--gas=${limit}`];
|
|
52
|
+
}
|
|
53
|
+
if (Array.isArray(limit) && limit.length >= 1 && limit[0] === 'auto') {
|
|
54
|
+
const gasOpts = ['--gas=auto'];
|
|
55
|
+
if (limit.length > 1) {
|
|
56
|
+
const [adjustment, ...rest] = limit.slice(1);
|
|
57
|
+
const adjustmentIsValid =
|
|
58
|
+
adjustment === undefined ||
|
|
59
|
+
(Number.isFinite(adjustment) && Number(adjustment) > 0);
|
|
60
|
+
if (rest.length !== 0 || !adjustmentIsValid) {
|
|
61
|
+
throw Error('invalid gas input');
|
|
62
|
+
}
|
|
63
|
+
if (adjustment !== undefined) {
|
|
64
|
+
gasOpts.push(`--gas-adjustment=${adjustment}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return gasOpts;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
throw Error('invalid gas input');
|
|
71
|
+
};
|
|
72
|
+
|
|
37
73
|
/**
|
|
38
74
|
* @param {ReadonlyArray<string>} swingsetArgs
|
|
39
|
-
* @param {
|
|
75
|
+
* @param {MinimalNetworkConfig & {
|
|
40
76
|
* from: string,
|
|
77
|
+
* fees?: string,
|
|
78
|
+
* gas?: GasLimit,
|
|
41
79
|
* dryRun?: boolean,
|
|
42
80
|
* verbose?: boolean,
|
|
43
81
|
* keyring?: {home?: string, backend: string}
|
|
@@ -48,6 +86,8 @@ harden(normalizeAddressWithOptions);
|
|
|
48
86
|
export const execSwingsetTransaction = (swingsetArgs, opts) => {
|
|
49
87
|
const {
|
|
50
88
|
from,
|
|
89
|
+
fees,
|
|
90
|
+
gas = ['auto', 1.2],
|
|
51
91
|
dryRun = false,
|
|
52
92
|
verbose = true,
|
|
53
93
|
keyring = undefined,
|
|
@@ -60,9 +100,12 @@ export const execSwingsetTransaction = (swingsetArgs, opts) => {
|
|
|
60
100
|
const backendOpt = keyring?.backend
|
|
61
101
|
? [`--keyring-backend=${keyring.backend}`]
|
|
62
102
|
: [];
|
|
103
|
+
const feeOpt = fees ? ['--fees', fees] : [];
|
|
63
104
|
const cmd = [`--node=${rpcAddrs[0]}`, `--chain-id=${chainName}`].concat(
|
|
64
105
|
homeOpt,
|
|
65
106
|
backendOpt,
|
|
107
|
+
feeOpt,
|
|
108
|
+
makeGasOpts(gas),
|
|
66
109
|
[`--from=${from}`, 'tx', 'swingset'],
|
|
67
110
|
swingsetArgs,
|
|
68
111
|
);
|
|
@@ -74,31 +117,34 @@ export const execSwingsetTransaction = (swingsetArgs, opts) => {
|
|
|
74
117
|
stdout.write('\n');
|
|
75
118
|
} else {
|
|
76
119
|
const yesCmd = cmd.concat(['--yes']);
|
|
77
|
-
if (verbose) console.log('Executing ', yesCmd);
|
|
78
|
-
|
|
120
|
+
if (verbose) console.log('Executing ', agdBinary, yesCmd);
|
|
121
|
+
const out = execFileSync(agdBinary, yesCmd, { encoding: 'utf-8' });
|
|
122
|
+
|
|
123
|
+
// agd puts this diagnostic on stdout rather than stderr :-/
|
|
124
|
+
// "Default sign-mode 'direct' not supported by Ledger, using sign-mode 'amino-json'.
|
|
125
|
+
if (out.startsWith('Default sign-mode')) {
|
|
126
|
+
const stripDiagnostic = out.replace(/^Default[^\n]+\n/, '');
|
|
127
|
+
return stripDiagnostic;
|
|
128
|
+
}
|
|
129
|
+
return out;
|
|
79
130
|
}
|
|
80
131
|
};
|
|
81
132
|
harden(execSwingsetTransaction);
|
|
82
133
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
'--output',
|
|
93
|
-
'--json',
|
|
94
|
-
];
|
|
95
|
-
const buffer = execFileSync(agdBinary, cmd);
|
|
96
|
-
return JSON.parse(buffer.toString());
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
* @param {MinimalNetworkConfig} net
|
|
137
|
+
* @returns {Promise<Params>}
|
|
138
|
+
*/
|
|
139
|
+
export const fetchSwingsetParams = async net => {
|
|
140
|
+
const client = await makeAgoricQueryClient(net);
|
|
141
|
+
const { params } = await client.agoric.swingset.params();
|
|
142
|
+
return params;
|
|
97
143
|
};
|
|
98
144
|
harden(fetchSwingsetParams);
|
|
99
145
|
|
|
100
146
|
/**
|
|
101
|
-
* @param {
|
|
147
|
+
* @param {MinimalNetworkConfig & {
|
|
102
148
|
* execFileSync: typeof import('child_process').execFileSync,
|
|
103
149
|
* delay: (ms: number) => Promise<void>,
|
|
104
150
|
* period?: number,
|
|
@@ -117,12 +163,10 @@ export const pollBlocks = opts => async lookup => {
|
|
|
117
163
|
for (;;) {
|
|
118
164
|
const sTxt = execFileSync(agdBinary, ['status', ...nodeArgs]);
|
|
119
165
|
const status = JSON.parse(sTxt.toString());
|
|
120
|
-
const {
|
|
121
|
-
|
|
122
|
-
} = status;
|
|
166
|
+
const { latest_block_time: time, latest_block_height: height } =
|
|
167
|
+
status.sync_info || status.SyncInfo;
|
|
123
168
|
try {
|
|
124
169
|
// see await null above
|
|
125
|
-
// eslint-disable-next-line @jessie.js/no-nested-await, no-await-in-loop
|
|
126
170
|
const result = await lookup({ time, height });
|
|
127
171
|
return result;
|
|
128
172
|
} catch (_err) {
|
|
@@ -132,7 +176,6 @@ export const pollBlocks = opts => async lookup => {
|
|
|
132
176
|
height,
|
|
133
177
|
'retrying...',
|
|
134
178
|
);
|
|
135
|
-
// eslint-disable-next-line @jessie.js/no-nested-await, no-await-in-loop
|
|
136
179
|
await delay(period);
|
|
137
180
|
}
|
|
138
181
|
}
|
|
@@ -140,14 +183,14 @@ export const pollBlocks = opts => async lookup => {
|
|
|
140
183
|
|
|
141
184
|
/**
|
|
142
185
|
* @param {string} txhash
|
|
143
|
-
* @param {
|
|
186
|
+
* @param {MinimalNetworkConfig & {
|
|
144
187
|
* execFileSync: typeof import('child_process').execFileSync,
|
|
145
188
|
* delay: (ms: number) => Promise<void>,
|
|
146
189
|
* period?: number,
|
|
147
190
|
* }} opts
|
|
148
191
|
*/
|
|
149
192
|
export const pollTx = async (txhash, opts) => {
|
|
150
|
-
const { execFileSync, rpcAddrs
|
|
193
|
+
const { execFileSync, rpcAddrs } = opts;
|
|
151
194
|
|
|
152
195
|
const nodeArgs = [`--node=${rpcAddrs[0]}`];
|
|
153
196
|
const outJson = ['--output', 'json'];
|
|
@@ -155,15 +198,8 @@ export const pollTx = async (txhash, opts) => {
|
|
|
155
198
|
const lookup = async () => {
|
|
156
199
|
const out = execFileSync(
|
|
157
200
|
agdBinary,
|
|
158
|
-
[
|
|
159
|
-
|
|
160
|
-
'tx',
|
|
161
|
-
txhash,
|
|
162
|
-
`--chain-id=${chainName}`,
|
|
163
|
-
...nodeArgs,
|
|
164
|
-
...outJson,
|
|
165
|
-
],
|
|
166
|
-
{ stdio: ['ignore', 'pipe', 'ignore'] },
|
|
201
|
+
['query', 'tx', txhash, ...nodeArgs, ...outJson],
|
|
202
|
+
{ stdio: ['ignore', 'pipe', 'pipe'] },
|
|
167
203
|
);
|
|
168
204
|
// XXX this type is defined in a .proto file somewhere
|
|
169
205
|
/** @type {{ height: string, txhash: string, code: number, timestamp: string }} */
|
package/src/lib/format.js
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { Fail, q } from '@endo/errors';
|
|
2
2
|
import { makeBoardRemote } from '@agoric/vats/tools/board-utils.js';
|
|
3
|
-
// eslint-disable-next-line no-unused-vars -- typeof below
|
|
4
|
-
import { makeAgoricNames } from './rpc.js';
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
import '@agoric/ertp
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @import {Amount, Brand} from '@agoric/ertp'
|
|
6
|
+
* @import {AgoricNamesRemotes, BoardRemote, VBankAssetDetail} from '@agoric/vats/tools/board-utils.js';
|
|
7
|
+
*/
|
|
10
8
|
|
|
9
|
+
// TODO Move to packages/internal.
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
11
|
+
* Parses the input and returns either a finite number or NaN.
|
|
13
12
|
*
|
|
14
|
-
* @param {string}
|
|
15
|
-
* @returns {
|
|
13
|
+
* @param {string} input
|
|
14
|
+
* @returns {number}
|
|
16
15
|
*/
|
|
17
|
-
export const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
throw RangeError(`${b} is negative`);
|
|
21
|
-
}
|
|
22
|
-
return b;
|
|
16
|
+
export const parseFiniteNumber = input => {
|
|
17
|
+
const result = /[0-9]/.test(input || '') ? Number(input) : NaN;
|
|
18
|
+
return Number.isFinite(result) ? result : NaN;
|
|
23
19
|
};
|
|
24
20
|
|
|
25
21
|
/**
|
|
@@ -30,21 +26,18 @@ export const Natural = str => {
|
|
|
30
26
|
*/
|
|
31
27
|
export const bigintReplacer = (k, v) => (typeof v === 'bigint' ? `${v}` : v);
|
|
32
28
|
|
|
33
|
-
/** @type {
|
|
29
|
+
/** @type {Partial<VBankAssetDetail>} */
|
|
34
30
|
// eslint-disable-next-line no-unused-vars
|
|
35
31
|
const exampleAsset = {
|
|
36
|
-
// @ts-expect-error cast
|
|
37
32
|
brand: makeBoardRemote({ boardId: 'board0425', iface: 'Alleged: BLD brand' }),
|
|
38
33
|
displayInfo: { assetKind: 'nat', decimalPlaces: 6 },
|
|
39
|
-
// @ts-expect-error cast
|
|
40
34
|
issuer: makeBoardRemote({ boardId: null, iface: undefined }),
|
|
41
|
-
|
|
35
|
+
proposedName: 'Agoric staking token',
|
|
42
36
|
};
|
|
43
|
-
/** @typedef {import('@agoric/vats/tools/board-utils.js').VBankAssetDetail } AssetDescriptor */
|
|
44
37
|
|
|
45
38
|
/**
|
|
46
|
-
* @param {
|
|
47
|
-
* @returns {(a: Amount & { brand: BoardRemote }) => [string, number | any[]]}
|
|
39
|
+
* @param {VBankAssetDetail[]} assets
|
|
40
|
+
* @returns {(a: Amount & { brand: BoardRemote }) => [string | null, number | any[]]}
|
|
48
41
|
*/
|
|
49
42
|
export const makeAmountFormatter = assets => amt => {
|
|
50
43
|
const { brand, value } = amt;
|
|
@@ -60,7 +53,9 @@ export const makeAmountFormatter = assets => amt => {
|
|
|
60
53
|
return [issuerName, Number(value) / 10 ** decimalPlaces];
|
|
61
54
|
case 'set':
|
|
62
55
|
assert(Array.isArray(value));
|
|
56
|
+
// @ts-expect-error narrowed
|
|
63
57
|
if (value[0]?.handle?.iface?.includes('InvitationHandle')) {
|
|
58
|
+
// @ts-expect-error narrowed
|
|
64
59
|
return [issuerName, value.map(v => v.description)];
|
|
65
60
|
}
|
|
66
61
|
return [issuerName, value];
|
|
@@ -75,8 +70,6 @@ export const asPercent = ratio => {
|
|
|
75
70
|
return (100 * Number(numerator.value)) / Number(denominator.value);
|
|
76
71
|
};
|
|
77
72
|
|
|
78
|
-
const { Fail, quote: q } = assert;
|
|
79
|
-
|
|
80
73
|
const isObject = x => typeof x === 'object' && x !== null;
|
|
81
74
|
|
|
82
75
|
/**
|
|
@@ -94,8 +87,8 @@ export const asBoardRemote = x => {
|
|
|
94
87
|
/**
|
|
95
88
|
* Summarize the balances array as user-facing informative tuples
|
|
96
89
|
*
|
|
97
|
-
* @param {import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord['purses']} purses
|
|
98
|
-
* @param {
|
|
90
|
+
* @param {import('@agoric/smart-wallet/src/smartWallet.js').CurrentWalletRecord['purses']} purses
|
|
91
|
+
* @param {VBankAssetDetail[]} assets
|
|
99
92
|
*/
|
|
100
93
|
export const purseBalanceTuples = (purses, assets) => {
|
|
101
94
|
const fmt = makeAmountFormatter(assets);
|
|
@@ -107,14 +100,15 @@ export const purseBalanceTuples = (purses, assets) => {
|
|
|
107
100
|
*/
|
|
108
101
|
export const fmtRecordOfLines = record => {
|
|
109
102
|
const { stringify } = JSON;
|
|
103
|
+
/** @type {Array<[string, string[]]>} */
|
|
110
104
|
const groups = Object.entries(record).map(([key, items]) => [
|
|
111
105
|
key,
|
|
112
106
|
items.map(item => ` ${stringify(item)}`),
|
|
113
107
|
]);
|
|
114
|
-
const lineEntries = groups.map(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
);
|
|
108
|
+
const lineEntries = groups.map(([key, lines]) => {
|
|
109
|
+
const linesStr = lines.length === 0 ? `[]` : `[\n${lines.join(',\n')}\n ]`;
|
|
110
|
+
return ` ${stringify(key)}: ${linesStr}`;
|
|
111
|
+
});
|
|
118
112
|
return `{\n${lineEntries.join(',\n')}\n}`;
|
|
119
113
|
};
|
|
120
114
|
|
|
@@ -122,7 +116,7 @@ export const fmtRecordOfLines = record => {
|
|
|
122
116
|
* Summarize the offerStatuses of the state as user-facing informative tuples
|
|
123
117
|
*
|
|
124
118
|
* @param {import('@agoric/smart-wallet/src/utils.js').CoalescedWalletState} state
|
|
125
|
-
* @param {
|
|
119
|
+
* @param {AgoricNamesRemotes} agoricNames
|
|
126
120
|
*/
|
|
127
121
|
export const offerStatusTuples = (state, agoricNames) => {
|
|
128
122
|
const { offerStatuses } = state;
|
|
@@ -177,9 +171,9 @@ export const offerStatusTuples = (state, agoricNames) => {
|
|
|
177
171
|
};
|
|
178
172
|
|
|
179
173
|
/**
|
|
180
|
-
* @param {import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord} current
|
|
174
|
+
* @param {import('@agoric/smart-wallet/src/smartWallet.js').CurrentWalletRecord} current
|
|
181
175
|
* @param {ReturnType<import('@agoric/smart-wallet/src/utils.js').makeWalletStateCoalescer>['state']} coalesced
|
|
182
|
-
* @param {
|
|
176
|
+
* @param {AgoricNamesRemotes} agoricNames
|
|
183
177
|
*/
|
|
184
178
|
export const summarize = (current, coalesced, agoricNames) => {
|
|
185
179
|
return {
|