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
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/* eslint-disable func-names */
|
|
3
|
+
/* eslint-env node */
|
|
4
|
+
import {
|
|
5
|
+
fetchEnvNetworkConfig,
|
|
6
|
+
makeAgoricNames,
|
|
7
|
+
makeVstorageKit,
|
|
8
|
+
} from '@agoric/client-utils';
|
|
9
|
+
import { execFileSync as execFileSyncAmbient } from 'child_process';
|
|
10
|
+
import { Command, CommanderError } from 'commander';
|
|
11
|
+
import { normalizeAddressWithOptions, pollBlocks } from '../lib/chain.js';
|
|
12
|
+
import {
|
|
13
|
+
findContinuingIds,
|
|
14
|
+
getCurrent,
|
|
15
|
+
getLastUpdate,
|
|
16
|
+
outputActionAndHint,
|
|
17
|
+
sendAction,
|
|
18
|
+
} from '../lib/wallet.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
|
|
22
|
+
* @import {AgoricNamesRemotes} from '@agoric/vats/tools/board-utils.js';
|
|
23
|
+
* @import {CurrentWalletRecord} from '@agoric/smart-wallet/src/smartWallet.js';
|
|
24
|
+
* @import {VstorageKit} from '@agoric/client-utils';
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const collectValues = (val, memo) => {
|
|
28
|
+
memo.push(val);
|
|
29
|
+
return memo;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const defaultKeyring = process.env.AGORIC_KEYRING_BACKEND || 'test';
|
|
33
|
+
|
|
34
|
+
const networkConfig = await fetchEnvNetworkConfig({ env: process.env, fetch });
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {import('anylogger').Logger} _logger
|
|
38
|
+
* @param {{
|
|
39
|
+
* env?: Record<string, string|undefined>,
|
|
40
|
+
* fetch?: typeof window.fetch,
|
|
41
|
+
* stdout?: Pick<import('stream').Writable, 'write'>,
|
|
42
|
+
* stderr?: Pick<import('stream').Writable, 'write'>,
|
|
43
|
+
* execFileSync?: typeof execFileSyncAmbient,
|
|
44
|
+
* delay?: (ms: number) => Promise<void>,
|
|
45
|
+
* }} [io]
|
|
46
|
+
*/
|
|
47
|
+
export const makeGovCommand = (_logger, io = {}) => {
|
|
48
|
+
const {
|
|
49
|
+
// Allow caller to provide access explicitly, but
|
|
50
|
+
// default to conventional ambient IO facilities.
|
|
51
|
+
stdout = process.stdout,
|
|
52
|
+
stderr = process.stderr,
|
|
53
|
+
fetch = global.fetch,
|
|
54
|
+
execFileSync = execFileSyncAmbient,
|
|
55
|
+
delay = ms => new Promise(resolve => setTimeout(resolve, ms)),
|
|
56
|
+
} = io;
|
|
57
|
+
|
|
58
|
+
const cmd = new Command('gov').description('Electoral governance commands');
|
|
59
|
+
// backwards compatibility with less general "ec" command. To make this work
|
|
60
|
+
// the new CLI options default to the values used for Economic Committee
|
|
61
|
+
cmd.alias('ec');
|
|
62
|
+
cmd.option(
|
|
63
|
+
'--keyring-backend <os|file|test>',
|
|
64
|
+
`keyring's backend (os|file|test) (default "${defaultKeyring}")`,
|
|
65
|
+
defaultKeyring,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
/** @param {string} literalOrName */
|
|
69
|
+
const normalizeAddress = literalOrName =>
|
|
70
|
+
normalizeAddressWithOptions(literalOrName, {
|
|
71
|
+
// FIXME does not observe keyring-backend option, which isn't available during arg parsing
|
|
72
|
+
keyringBackend: defaultKeyring,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
/** @type {(info: unknown, indent?: unknown) => boolean } */
|
|
76
|
+
const show = (info, indent) =>
|
|
77
|
+
stdout.write(`${JSON.stringify(info, null, indent ? 2 : undefined)}\n`);
|
|
78
|
+
|
|
79
|
+
const abortIfSeen = (instanceName, found) => {
|
|
80
|
+
const done = found.filter(it => it.instanceName === instanceName);
|
|
81
|
+
if (done.length > 0) {
|
|
82
|
+
console.warn(`invitation to ${instanceName} already accepted`, done);
|
|
83
|
+
// CommanderError is a class constructor, and so
|
|
84
|
+
// must be invoked with `new`.
|
|
85
|
+
throw new CommanderError(1, 'EALREADY', `already accepted`);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Make an offer from agoricNames, wallet status; sign and broadcast it,
|
|
91
|
+
* given a sendFrom address; else print it.
|
|
92
|
+
*
|
|
93
|
+
* @param {{
|
|
94
|
+
* toOffer: (agoricNames: AgoricNamesRemotes, current: CurrentWalletRecord | undefined) => OfferSpec,
|
|
95
|
+
* sendFrom?: string | undefined,
|
|
96
|
+
* keyringBackend: string,
|
|
97
|
+
* instanceName?: string,
|
|
98
|
+
* }} detail
|
|
99
|
+
* @param {VstorageKit} [vsk]
|
|
100
|
+
*/
|
|
101
|
+
const processOffer = async function (
|
|
102
|
+
{ toOffer, sendFrom, keyringBackend },
|
|
103
|
+
vsk,
|
|
104
|
+
) {
|
|
105
|
+
await null;
|
|
106
|
+
vsk ||= makeVstorageKit({ fetch }, networkConfig);
|
|
107
|
+
const { readPublished } = vsk;
|
|
108
|
+
const agoricNames = await makeAgoricNames(vsk.fromBoard, vsk.vstorage);
|
|
109
|
+
|
|
110
|
+
assert(keyringBackend, 'missing keyring-backend option');
|
|
111
|
+
|
|
112
|
+
let current;
|
|
113
|
+
if (sendFrom) {
|
|
114
|
+
current = await getCurrent(sendFrom, { readPublished });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const offer = toOffer(agoricNames, current);
|
|
118
|
+
if (!sendFrom) {
|
|
119
|
+
outputActionAndHint(
|
|
120
|
+
{ method: 'executeOffer', offer },
|
|
121
|
+
{ stdout, stderr },
|
|
122
|
+
);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const result = await sendAction(
|
|
127
|
+
{ method: 'executeOffer', offer },
|
|
128
|
+
{
|
|
129
|
+
keyring: { backend: keyringBackend },
|
|
130
|
+
from: sendFrom,
|
|
131
|
+
verbose: false,
|
|
132
|
+
...networkConfig,
|
|
133
|
+
execFileSync,
|
|
134
|
+
stdout,
|
|
135
|
+
delay,
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
assert(result); // not dry-run
|
|
139
|
+
const { timestamp, txhash, height } = result;
|
|
140
|
+
console.error('wallet action is broadcast:');
|
|
141
|
+
show({ timestamp, height, offerId: offer.id, txhash });
|
|
142
|
+
const checkInWallet = async blockInfo => {
|
|
143
|
+
const [state, update] = await Promise.all([
|
|
144
|
+
getCurrent(sendFrom, { readPublished }),
|
|
145
|
+
getLastUpdate(sendFrom, { readPublished }),
|
|
146
|
+
readPublished(`wallet.${sendFrom}`),
|
|
147
|
+
]);
|
|
148
|
+
if (update.updated === 'offerStatus' && update.status.id === offer.id) {
|
|
149
|
+
return blockInfo;
|
|
150
|
+
}
|
|
151
|
+
const info = await findContinuingIds(state, agoricNames);
|
|
152
|
+
const done = info.filter(it => it.offerId === offer.id);
|
|
153
|
+
if (!(done.length > 0)) throw Error('retry');
|
|
154
|
+
return blockInfo;
|
|
155
|
+
};
|
|
156
|
+
const blockInfo = await pollBlocks({
|
|
157
|
+
retryMessage: 'offer not yet in block',
|
|
158
|
+
...networkConfig,
|
|
159
|
+
execFileSync,
|
|
160
|
+
delay,
|
|
161
|
+
})(checkInWallet);
|
|
162
|
+
console.error('offer accepted in block');
|
|
163
|
+
show(blockInfo);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
cmd
|
|
167
|
+
.command('committee')
|
|
168
|
+
.description('accept invitation to join a committee')
|
|
169
|
+
.requiredOption(
|
|
170
|
+
'--name <string>',
|
|
171
|
+
'Committee instance name',
|
|
172
|
+
String,
|
|
173
|
+
'economicCommittee',
|
|
174
|
+
)
|
|
175
|
+
.option('--voter <number>', 'Voter number', Number, 0)
|
|
176
|
+
.option(
|
|
177
|
+
'--offerId <string>',
|
|
178
|
+
'Offer id',
|
|
179
|
+
String,
|
|
180
|
+
`gov-committee-${Date.now()}`,
|
|
181
|
+
)
|
|
182
|
+
.option(
|
|
183
|
+
'--send-from <name-or-address>',
|
|
184
|
+
'Send from address',
|
|
185
|
+
normalizeAddress,
|
|
186
|
+
)
|
|
187
|
+
.action(async function (opts, options) {
|
|
188
|
+
const { name: instanceName } = opts;
|
|
189
|
+
|
|
190
|
+
/** @type {Parameters<typeof processOffer>[0]['toOffer']} */
|
|
191
|
+
const toOffer = (agoricNames, current) => {
|
|
192
|
+
const instance = agoricNames.instance[instanceName];
|
|
193
|
+
assert(instance, `missing ${instanceName}`);
|
|
194
|
+
|
|
195
|
+
if (current) {
|
|
196
|
+
const found = findContinuingIds(current, agoricNames);
|
|
197
|
+
abortIfSeen(instanceName, found);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
id: opts.offerId,
|
|
202
|
+
invitationSpec: {
|
|
203
|
+
source: 'purse',
|
|
204
|
+
instance,
|
|
205
|
+
description: `Voter${opts.voter}`,
|
|
206
|
+
},
|
|
207
|
+
proposal: {},
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
await processOffer({
|
|
212
|
+
toOffer,
|
|
213
|
+
instanceName,
|
|
214
|
+
sendFrom: opts.sendFrom,
|
|
215
|
+
keyringBackend: options.optsWithGlobals().keyringBackend,
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
cmd
|
|
220
|
+
.command('charter')
|
|
221
|
+
.description('accept the charter invitation')
|
|
222
|
+
.requiredOption(
|
|
223
|
+
'--name <string>',
|
|
224
|
+
'Charter instance name',
|
|
225
|
+
'economicCommitteeCharter',
|
|
226
|
+
)
|
|
227
|
+
.option('--offerId <string>', 'Offer id', String, `charter-${Date.now()}`)
|
|
228
|
+
.option(
|
|
229
|
+
'--send-from <name-or-address>',
|
|
230
|
+
'Send from address',
|
|
231
|
+
normalizeAddress,
|
|
232
|
+
)
|
|
233
|
+
.action(async function (opts, options) {
|
|
234
|
+
const { name: instanceName } = opts;
|
|
235
|
+
|
|
236
|
+
/** @type {Parameters<typeof processOffer>[0]['toOffer']} */
|
|
237
|
+
const toOffer = (agoricNames, current) => {
|
|
238
|
+
const instance = agoricNames.instance[instanceName];
|
|
239
|
+
assert(instance, `missing ${instanceName}`);
|
|
240
|
+
|
|
241
|
+
if (current) {
|
|
242
|
+
const found = findContinuingIds(current, agoricNames);
|
|
243
|
+
abortIfSeen(instanceName, found);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
id: opts.offerId,
|
|
248
|
+
invitationSpec: {
|
|
249
|
+
source: 'purse',
|
|
250
|
+
instance,
|
|
251
|
+
description: 'charter member invitation',
|
|
252
|
+
},
|
|
253
|
+
proposal: {},
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
await processOffer({
|
|
258
|
+
toOffer,
|
|
259
|
+
instanceName,
|
|
260
|
+
sendFrom: opts.sendFrom,
|
|
261
|
+
keyringBackend: options.optsWithGlobals().keyringBackend,
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
cmd
|
|
266
|
+
.command('find-continuing-id')
|
|
267
|
+
.description('print id of specified voting continuing invitation')
|
|
268
|
+
.requiredOption(
|
|
269
|
+
'--from <name-or-address>',
|
|
270
|
+
'from address',
|
|
271
|
+
normalizeAddress,
|
|
272
|
+
)
|
|
273
|
+
.requiredOption('--for <string>', 'description of the invitation')
|
|
274
|
+
.action(async opts => {
|
|
275
|
+
const { readPublished, ...vsk } = makeVstorageKit(
|
|
276
|
+
{ fetch },
|
|
277
|
+
networkConfig,
|
|
278
|
+
);
|
|
279
|
+
const agoricNames = await makeAgoricNames(vsk.fromBoard, vsk.vstorage);
|
|
280
|
+
const current = await getCurrent(opts.from, { readPublished });
|
|
281
|
+
|
|
282
|
+
const known = findContinuingIds(current, agoricNames);
|
|
283
|
+
if (!known) {
|
|
284
|
+
console.error('No continuing ids found');
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const match = known.find(r => r.description === opts.for);
|
|
288
|
+
if (!match) {
|
|
289
|
+
console.error(`No match found for '${opts.for}'`);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
console.log(match.offerId);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
cmd
|
|
297
|
+
.command('find-continuing-ids')
|
|
298
|
+
.description('print records of voting continuing invitations')
|
|
299
|
+
.requiredOption(
|
|
300
|
+
'--from <name-or-address>',
|
|
301
|
+
'from address',
|
|
302
|
+
normalizeAddress,
|
|
303
|
+
)
|
|
304
|
+
.action(async opts => {
|
|
305
|
+
const { readPublished, ...vsk } = makeVstorageKit(
|
|
306
|
+
{ fetch },
|
|
307
|
+
networkConfig,
|
|
308
|
+
);
|
|
309
|
+
const agoricNames = await makeAgoricNames(vsk.fromBoard, vsk.vstorage);
|
|
310
|
+
const current = await getCurrent(opts.from, { readPublished });
|
|
311
|
+
|
|
312
|
+
const found = findContinuingIds(current, agoricNames);
|
|
313
|
+
for (const it of found) {
|
|
314
|
+
show({ ...it, address: opts.from });
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
cmd
|
|
319
|
+
.command('vote')
|
|
320
|
+
.description('vote on latest question')
|
|
321
|
+
.requiredOption(
|
|
322
|
+
'--instance <string>',
|
|
323
|
+
'Committee name under agoricNames.instances',
|
|
324
|
+
String,
|
|
325
|
+
'economicCommittee',
|
|
326
|
+
)
|
|
327
|
+
.requiredOption(
|
|
328
|
+
'--pathname <string>',
|
|
329
|
+
'Committee name under published.committees',
|
|
330
|
+
String,
|
|
331
|
+
'Economic_Committee',
|
|
332
|
+
)
|
|
333
|
+
.option('--offerId <number>', 'Offer id', String, `gov-vote-${Date.now()}`)
|
|
334
|
+
.requiredOption(
|
|
335
|
+
'--forPosition <number>',
|
|
336
|
+
'index of one position to vote for (within the question description.positions); ',
|
|
337
|
+
Number,
|
|
338
|
+
)
|
|
339
|
+
.requiredOption(
|
|
340
|
+
'--send-from <name-or-address>',
|
|
341
|
+
'Send from address',
|
|
342
|
+
normalizeAddress,
|
|
343
|
+
)
|
|
344
|
+
.action(async function (opts, options) {
|
|
345
|
+
const vsk = makeVstorageKit({ fetch }, networkConfig);
|
|
346
|
+
const { readPublished } = vsk;
|
|
347
|
+
|
|
348
|
+
const questionDesc = await readPublished(
|
|
349
|
+
`committees.${opts.pathname}.latestQuestion`,
|
|
350
|
+
).catch(err => {
|
|
351
|
+
// CommanderError is a class constructor, and so
|
|
352
|
+
// must be invoked with `new`.
|
|
353
|
+
throw new CommanderError(1, 'VSTORAGE_FAILURE', err.message);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// TODO support multiple position arguments
|
|
357
|
+
const chosenPositions = [questionDesc.positions[opts.forPosition]];
|
|
358
|
+
assert(chosenPositions, `undefined position index ${opts.forPosition}`);
|
|
359
|
+
|
|
360
|
+
/** @type {Parameters<typeof processOffer>[0]['toOffer']} */
|
|
361
|
+
const toOffer = (agoricNames, current) => {
|
|
362
|
+
const cont = current ? findContinuingIds(current, agoricNames) : [];
|
|
363
|
+
const votingRight = cont.find(it => it.instanceName === opts.instance);
|
|
364
|
+
if (!votingRight) {
|
|
365
|
+
console.debug('continuing ids', cont, 'for', current);
|
|
366
|
+
// CommanderError is a class constructor, and so
|
|
367
|
+
// must be invoked with `new`.
|
|
368
|
+
throw new CommanderError(
|
|
369
|
+
1,
|
|
370
|
+
'NO_INVITATION',
|
|
371
|
+
'first, try: agops ec committee ...',
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
return {
|
|
375
|
+
id: opts.offerId,
|
|
376
|
+
invitationSpec: {
|
|
377
|
+
source: 'continuing',
|
|
378
|
+
previousOffer: votingRight.offerId,
|
|
379
|
+
invitationMakerName: 'makeVoteInvitation',
|
|
380
|
+
// (positionList, questionHandle)
|
|
381
|
+
invitationArgs: harden([
|
|
382
|
+
chosenPositions,
|
|
383
|
+
questionDesc.questionHandle,
|
|
384
|
+
]),
|
|
385
|
+
},
|
|
386
|
+
proposal: {},
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
await processOffer(
|
|
391
|
+
{
|
|
392
|
+
toOffer,
|
|
393
|
+
sendFrom: opts.sendFrom,
|
|
394
|
+
keyringBackend: options.optsWithGlobals().keyringBackend,
|
|
395
|
+
},
|
|
396
|
+
vsk,
|
|
397
|
+
);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
cmd
|
|
401
|
+
.command('proposePauseOffers')
|
|
402
|
+
.description('propose a vote to pause offers')
|
|
403
|
+
.option(
|
|
404
|
+
'--send-from <name-or-address>',
|
|
405
|
+
'Send from address',
|
|
406
|
+
normalizeAddress,
|
|
407
|
+
)
|
|
408
|
+
.option(
|
|
409
|
+
'--offerId <string>',
|
|
410
|
+
'Offer id',
|
|
411
|
+
String,
|
|
412
|
+
`proposePauseOffers-${Date.now()}`,
|
|
413
|
+
)
|
|
414
|
+
.requiredOption(
|
|
415
|
+
'--instance <string>',
|
|
416
|
+
'name of governed instance in agoricNames',
|
|
417
|
+
)
|
|
418
|
+
.requiredOption(
|
|
419
|
+
'--substring <string>',
|
|
420
|
+
'an offer string to pause (can be repeated)',
|
|
421
|
+
collectValues,
|
|
422
|
+
[],
|
|
423
|
+
)
|
|
424
|
+
.option(
|
|
425
|
+
'--deadline <minutes>',
|
|
426
|
+
'minutes from now to close the vote',
|
|
427
|
+
Number,
|
|
428
|
+
1,
|
|
429
|
+
)
|
|
430
|
+
.action(async function (opts, options) {
|
|
431
|
+
const { instance: instanceName } = opts;
|
|
432
|
+
|
|
433
|
+
/** @type {Parameters<typeof processOffer>[0]['toOffer']} */
|
|
434
|
+
const toOffer = (agoricNames, current) => {
|
|
435
|
+
const instance = agoricNames.instance[instanceName];
|
|
436
|
+
assert(instance, `missing ${instanceName}`);
|
|
437
|
+
assert(current, 'missing current wallet');
|
|
438
|
+
|
|
439
|
+
const known = findContinuingIds(current, agoricNames);
|
|
440
|
+
|
|
441
|
+
assert(known, 'could not find committee acceptance offer id');
|
|
442
|
+
|
|
443
|
+
// TODO magic string
|
|
444
|
+
const match = known.find(
|
|
445
|
+
r => r.description === 'charter member invitation',
|
|
446
|
+
);
|
|
447
|
+
assert(match, 'no offer found for charter member invitation');
|
|
448
|
+
|
|
449
|
+
return {
|
|
450
|
+
id: opts.offerId,
|
|
451
|
+
invitationSpec: {
|
|
452
|
+
source: 'continuing',
|
|
453
|
+
previousOffer: match.offerId,
|
|
454
|
+
invitationMakerName: 'VoteOnPauseOffers',
|
|
455
|
+
// ( instance, strings list, timer deadline seconds )
|
|
456
|
+
invitationArgs: harden([
|
|
457
|
+
instance,
|
|
458
|
+
opts.substring,
|
|
459
|
+
BigInt(opts.deadline * 60 + Math.round(Date.now() / 1000)),
|
|
460
|
+
]),
|
|
461
|
+
},
|
|
462
|
+
proposal: {},
|
|
463
|
+
};
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
await processOffer({
|
|
467
|
+
toOffer,
|
|
468
|
+
instanceName,
|
|
469
|
+
sendFrom: opts.sendFrom,
|
|
470
|
+
keyringBackend: options.optsWithGlobals().keyringBackend,
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
return cmd;
|
|
475
|
+
};
|