@aephia/atlas-kit 0.6.0-next.101 → 0.6.0-next.102

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.
Files changed (28) hide show
  1. package/dist/internal/planning/arrival-guards.d.ts +0 -1
  2. package/dist/internal/planning/arrival-guards.d.ts.map +1 -1
  3. package/dist/internal/planning/arrival-guards.js +0 -16
  4. package/dist/internal/planning/arrival-guards.js.map +1 -1
  5. package/dist/internal/planning/fleet-dock-funding-guard.d.ts +3 -3
  6. package/dist/internal/planning/fleet-dock-funding-guard.d.ts.map +1 -1
  7. package/dist/internal/planning/fleet-dock-funding-guard.js +76 -93
  8. package/dist/internal/planning/fleet-dock-funding-guard.js.map +1 -1
  9. package/dist/internal/planning/local-market-order.d.ts +4 -4
  10. package/dist/internal/planning/local-market-order.d.ts.map +1 -1
  11. package/dist/internal/planning/local-market-order.js +80 -108
  12. package/dist/internal/planning/local-market-order.js.map +1 -1
  13. package/dist/internal/planning/plan-fields.d.ts +59 -0
  14. package/dist/internal/planning/plan-fields.d.ts.map +1 -0
  15. package/dist/internal/planning/plan-fields.js +153 -0
  16. package/dist/internal/planning/plan-fields.js.map +1 -0
  17. package/dist/internal/planning/plan-guards.d.ts +4 -0
  18. package/dist/internal/planning/plan-guards.d.ts.map +1 -0
  19. package/dist/internal/planning/plan-guards.js +168 -0
  20. package/dist/internal/planning/plan-guards.js.map +1 -0
  21. package/dist/internal/planning/runtime-guards.d.ts +0 -2
  22. package/dist/internal/planning/runtime-guards.d.ts.map +1 -1
  23. package/dist/internal/planning/runtime-guards.js +0 -3
  24. package/dist/internal/planning/runtime-guards.js.map +1 -1
  25. package/dist/planning/index.d.ts.map +1 -1
  26. package/dist/planning/index.js +11 -961
  27. package/dist/planning/index.js.map +1 -1
  28. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import { validateCurrencyInstructions } from '../internal/planning/currency-cache-guard.js';
2
- import { normalizeFleetDockFundingGuard, dockFundingGuardToJSON, validateFleetDockFundingGuards, } from '../internal/planning/fleet-dock-funding-guard.js';
3
- import { normalizeLocalMarketOrderGuard, localMarketOrderGuardToJSON, validateLocalMarketOrderInstructions, } from '../internal/planning/local-market-order.js';
2
+ import { validateFleetDockFundingGuards, } from '../internal/planning/fleet-dock-funding-guard.js';
3
+ import { validateLocalMarketOrderInstructions, } from '../internal/planning/local-market-order.js';
4
4
  import { validateCrewTransferInstructions, } from '../internal/planning/fleet-crew-guard.js';
5
- import { validateCompletionInstructions, scanCompletionDiscriminators, } from '../internal/planning/scan-completion-guard.js';
5
+ import { validateCompletionInstructions, } from '../internal/planning/scan-completion-guard.js';
6
6
  import { validateOpenSignalInstructions } from '../internal/planning/open-signal-guard.js';
7
7
  import { validateDetectInstructions, } from '../internal/planning/scan-detect-guard.js';
8
8
  import { validateRespawnInstructions } from '../internal/planning/respawn-guards.js';
@@ -11,41 +11,24 @@ import { validateMovementXpInstructions } from '../internal/planning/movement-xp
11
11
  import { validateFleetDockingGuards } from '../internal/planning/fleet-docking-guard.js';
12
12
  import { validateStarbaseSystemInstructions, validateStarbaseSystemGuards, } from '../internal/planning/starbase-system-guard.js';
13
13
  import { validateCharacterRegistrationInstructions } from '../internal/planning/character-registration-guard.js';
14
- import { normalizeArrivalGuard, arrivalGuardToJSON, validateArrivalInstructions, } from '../internal/planning/arrival-guards.js';
15
- import { isRuntimeGuard, normalizeRuntimeGuard, runtimeGuardToJSON, validateRuntimeInstructions, } from '../internal/planning/runtime-guards.js';
16
- import { isTradeBuyGuard, isTradeSellGuard, isTradeMeterGuard, isFactionTradeGuard, } from '../internal/planning/faction-trade-guards.js';
17
- import { AccountRole, getBase64Decoder, getBase64Encoder, isAddress, isWritableRole, } from '@solana/kit';
14
+ import { validateArrivalInstructions, } from '../internal/planning/arrival-guards.js';
15
+ import { validateRuntimeInstructions, } from '../internal/planning/runtime-guards.js';
16
+ import { assertKeys, guardToWire, invalid, readAddress, readRecord, readString, } from '../internal/planning/plan-fields.js';
17
+ import { normalizePrecondition } from '../internal/planning/plan-guards.js';
18
+ import { isTradeBuyGuard, isTradeMeterGuard, isFactionTradeGuard, } from '../internal/planning/faction-trade-guards.js';
19
+ import { AccountRole, getBase64Decoder, getBase64Encoder, isWritableRole, } from '@solana/kit';
18
20
  import { InvalidActionInputError, SageSdkError } from '../client/errors.js';
19
21
  import { deepFreeze } from '../internal/immutable-tree.js';
20
22
  import { validateMiningStopInstructions } from '../internal/planning/mining-stop.js';
21
23
  import { validatePlanComposition } from './composition.js';
22
24
  import { isPlanInstance, registerPlanInstance } from './plan-instances.js';
23
25
  const BASE64_PATTERN = /^(?:[A-Za-z\d+/]{4})*(?:[A-Za-z\d+/]{2}==|[A-Za-z\d+/]{3}=)?$/u;
24
- const DATA_HASH_PATTERN = /^[\da-f]{64}$/u;
25
26
  const ACCOUNT_ROLES = new Set([
26
27
  AccountRole.READONLY,
27
28
  AccountRole.WRITABLE,
28
29
  AccountRole.READONLY_SIGNER,
29
30
  AccountRole.WRITABLE_SIGNER,
30
31
  ]);
31
- function invalid(field, value, acceptedRange) {
32
- throw new InvalidActionInputError(field, value, acceptedRange, 'Correct this Plan field and recreate or hydrate the Plan before retrying.');
33
- }
34
- function readRecord(value, field) {
35
- if (value === null || typeof value !== 'object' || Array.isArray(value)) {
36
- return invalid(field, value, 'a plain object');
37
- }
38
- return value;
39
- }
40
- function assertKeys(value, field, required, optional = []) {
41
- const keys = Object.keys(value);
42
- const accepted = new Set([...required, ...optional]);
43
- const missing = required.find((key) => !Object.hasOwn(value, key));
44
- const unexpected = keys.find((key) => !accepted.has(key));
45
- if (missing !== undefined || unexpected !== undefined) {
46
- invalid(field, missing === undefined ? unexpected : `missing ${missing}`, `exactly the fields ${[...required, ...optional].join(', ')}`);
47
- }
48
- }
49
32
  function readArray(value, field) {
50
33
  if (!Array.isArray(value)) {
51
34
  return invalid(field, value, 'an ordered array');
@@ -59,29 +42,16 @@ function readArray(value, field) {
59
42
  }
60
43
  return normalized;
61
44
  }
62
- function readString(value, field) {
63
- return typeof value === 'string' ? value : invalid(field, value, 'a string');
64
- }
65
45
  function readToken(value, field) {
66
46
  return typeof value === 'string' && value.length > 0
67
47
  ? value
68
48
  : invalid(field, value, 'a non-empty string');
69
49
  }
70
- function readAddress(value, field) {
71
- return typeof value === 'string' && isAddress(value)
72
- ? value
73
- : invalid(field, value, 'a valid base58 Solana address');
74
- }
75
50
  function readRole(value, field) {
76
51
  return typeof value === 'number' && ACCOUNT_ROLES.has(value)
77
52
  ? value
78
53
  : invalid(field, value, 'an AccountRole integer from 0 through 3');
79
54
  }
80
- function readDataHash(value, field) {
81
- return typeof value === 'string' && DATA_HASH_PATTERN.test(value)
82
- ? value
83
- : invalid(field, value, 'a lowercase 64-character SHA-256 hex digest');
84
- }
85
55
  function decodeBase64(value, field) {
86
56
  if (typeof value !== 'string' || !BASE64_PATTERN.test(value)) {
87
57
  return invalid(field, value, 'canonical base64-encoded instruction bytes');
@@ -175,764 +145,6 @@ function normalizeSemanticFact(value, field) {
175
145
  }
176
146
  return invalid(`${field}.kind`, semantic.kind, 'one of exclusive, requires, invalidates, or transition');
177
147
  }
178
- function normalizePrecondition(value, field) {
179
- const precondition = readRecord(value, field);
180
- if (precondition.kind === 'fleet-arrival')
181
- return normalizeArrivalGuard(precondition, field);
182
- if (isRuntimeGuard(precondition))
183
- return normalizeRuntimeGuard(precondition, field);
184
- if (precondition.kind === 'character-registration') {
185
- assertKeys(precondition, field, [
186
- 'kind',
187
- 'address',
188
- 'game',
189
- 'profile',
190
- 'profileDataHash',
191
- 'funder',
192
- 'xpBudget',
193
- 'xpBudgetConfig',
194
- 'maximumFunderDebit',
195
- 'characterSize',
196
- 'initializationHash',
197
- 'characterLamports',
198
- 'budgetLamports',
199
- 'describes',
200
- ]);
201
- if (typeof precondition.characterSize !== 'number' ||
202
- !Number.isSafeInteger(precondition.characterSize) ||
203
- precondition.characterSize < 423)
204
- invalid(`${field}.characterSize`, precondition.characterSize, 'a qualified Character allocation of at least 423 bytes');
205
- for (const key of ['characterLamports', 'budgetLamports'])
206
- if (typeof precondition[key] !== 'bigint' || precondition[key] < 0n)
207
- invalid(`${field}.${key}`, precondition[key], 'a nonnegative bigint');
208
- const maximumFunderDebit = precondition.maximumFunderDebit;
209
- if (typeof maximumFunderDebit !== 'bigint' || maximumFunderDebit < 0n)
210
- invalid(`${field}.maximumFunderDebit`, maximumFunderDebit, 'a nonnegative bigint');
211
- return Object.freeze({
212
- kind: 'character-registration',
213
- address: readAddress(precondition.address, `${field}.address`),
214
- game: readAddress(precondition.game, `${field}.game`),
215
- profile: readAddress(precondition.profile, `${field}.profile`),
216
- profileDataHash: readDataHash(precondition.profileDataHash, `${field}.profileDataHash`),
217
- funder: readAddress(precondition.funder, `${field}.funder`),
218
- xpBudget: readAddress(precondition.xpBudget, `${field}.xpBudget`),
219
- xpBudgetConfig: readAddress(precondition.xpBudgetConfig, `${field}.xpBudgetConfig`),
220
- maximumFunderDebit,
221
- characterLamports: precondition.characterLamports,
222
- budgetLamports: precondition.budgetLamports,
223
- characterSize: precondition.characterSize,
224
- initializationHash: readDataHash(precondition.initializationHash, `${field}.initializationHash`),
225
- describes: readString(precondition.describes, `${field}.describes`),
226
- });
227
- }
228
- if (precondition.kind === 'ship-import-funding') {
229
- assertKeys(precondition, field, [
230
- 'kind',
231
- 'address',
232
- 'game',
233
- 'profile',
234
- 'system',
235
- 'shipId',
236
- 'maximumProfileDebit',
237
- 'describes',
238
- ]);
239
- const shipId = precondition.shipId;
240
- if (typeof shipId !== 'number' ||
241
- !Number.isInteger(shipId) ||
242
- shipId < 0 ||
243
- shipId > 65535)
244
- invalid(`${field}.shipId`, shipId, 'an unsigned u16 ship configuration ID');
245
- const maximumProfileDebit = precondition.maximumProfileDebit;
246
- if (typeof maximumProfileDebit !== 'bigint' || maximumProfileDebit < 0n)
247
- invalid(`${field}.maximumProfileDebit`, maximumProfileDebit, 'a nonnegative bigint');
248
- return Object.freeze({
249
- kind: 'ship-import-funding',
250
- address: readAddress(precondition.address, `${field}.address`),
251
- game: readAddress(precondition.game, `${field}.game`),
252
- profile: readAddress(precondition.profile, `${field}.profile`),
253
- system: readAddress(precondition.system, `${field}.system`),
254
- shipId,
255
- maximumProfileDebit,
256
- describes: readString(precondition.describes, `${field}.describes`),
257
- });
258
- }
259
- if (precondition.kind === 'fleet-attack') {
260
- assertKeys(precondition, field, [
261
- 'kind',
262
- 'address',
263
- 'defender',
264
- 'game',
265
- 'profile',
266
- 'defenderProfile',
267
- 'instructionKey',
268
- 'describes',
269
- ]);
270
- return Object.freeze({
271
- kind: 'fleet-attack',
272
- address: readAddress(precondition.address, `${field}.address`),
273
- defender: readAddress(precondition.defender, `${field}.defender`),
274
- game: readAddress(precondition.game, `${field}.game`),
275
- profile: readAddress(precondition.profile, `${field}.profile`),
276
- defenderProfile: readAddress(precondition.defenderProfile, `${field}.defenderProfile`),
277
- instructionKey: readString(precondition.instructionKey, `${field}.instructionKey`),
278
- describes: readString(precondition.describes, `${field}.describes`),
279
- });
280
- }
281
- if (precondition.kind === 'currency-cache') {
282
- assertKeys(precondition, field, ['kind', 'address', 'game', 'describes']);
283
- return Object.freeze({
284
- kind: 'currency-cache',
285
- address: readAddress(precondition.address, `${field}.address`),
286
- game: readAddress(precondition.game, `${field}.game`),
287
- describes: readString(precondition.describes, `${field}.describes`),
288
- });
289
- }
290
- if (precondition.kind === 'movement-character') {
291
- assertKeys(precondition, field, [
292
- 'kind',
293
- 'address',
294
- 'game',
295
- 'profile',
296
- 'stateHash',
297
- 'describes',
298
- ]);
299
- return Object.freeze({
300
- kind: 'movement-character',
301
- address: readAddress(precondition.address, `${field}.address`),
302
- game: readAddress(precondition.game, `${field}.game`),
303
- profile: readAddress(precondition.profile, `${field}.profile`),
304
- stateHash: readDataHash(precondition.stateHash, `${field}.stateHash`),
305
- describes: readString(precondition.describes, `${field}.describes`),
306
- });
307
- }
308
- if (precondition.kind === 'fleet-docking-policy') {
309
- assertKeys(precondition, field, [
310
- 'kind',
311
- 'address',
312
- 'game',
313
- 'system',
314
- 'ownership',
315
- 'describes',
316
- ]);
317
- return Object.freeze({
318
- kind: 'fleet-docking-policy',
319
- address: readAddress(precondition.address, `${field}.address`),
320
- game: readAddress(precondition.game, `${field}.game`),
321
- system: readAddress(precondition.system, `${field}.system`),
322
- ownership: readAddress(precondition.ownership, `${field}.ownership`),
323
- describes: readString(precondition.describes, `${field}.describes`),
324
- });
325
- }
326
- if (precondition.kind === 'starbase-system') {
327
- assertKeys(precondition, field, ['kind', 'address', 'game', 'starbaseSequenceId', 'describes'], ['requireCss']);
328
- if (precondition.requireCss !== undefined &&
329
- precondition.requireCss !== true)
330
- invalid(`${field}.requireCss`, precondition.requireCss, 'true when CSS access is required, otherwise omitted');
331
- const sequence = precondition.starbaseSequenceId;
332
- if (typeof sequence !== 'bigint' ||
333
- sequence < 0n ||
334
- sequence > 18446744073709551615n)
335
- invalid(`${field}.starbaseSequenceId`, sequence, 'an unsigned u64 Starbase sequence');
336
- return Object.freeze({
337
- kind: 'starbase-system',
338
- address: readAddress(precondition.address, `${field}.address`),
339
- game: readAddress(precondition.game, `${field}.game`),
340
- starbaseSequenceId: sequence,
341
- ...(precondition.requireCss === undefined
342
- ? {}
343
- : { requireCss: true }),
344
- describes: readString(precondition.describes, `${field}.describes`),
345
- });
346
- }
347
- if (precondition.kind === 'fleet-mining') {
348
- assertKeys(precondition, field, [
349
- 'kind',
350
- 'address',
351
- 'game',
352
- 'profile',
353
- 'asteroid',
354
- 'describes',
355
- ]);
356
- return Object.freeze({
357
- kind: 'fleet-mining',
358
- address: readAddress(precondition.address, `${field}.address`),
359
- game: readAddress(precondition.game, `${field}.game`),
360
- profile: readAddress(precondition.profile, `${field}.profile`),
361
- asteroid: readAddress(precondition.asteroid, `${field}.asteroid`),
362
- describes: readString(precondition.describes, `${field}.describes`),
363
- });
364
- }
365
- if (isFactionTradeGuard(precondition)) {
366
- const kind = precondition.kind;
367
- assertKeys(precondition, field, [
368
- 'kind',
369
- 'address',
370
- 'game',
371
- 'factionId',
372
- 'describes',
373
- 'schemaVersion',
374
- ...(isTradeBuyGuard(precondition)
375
- ? ['cargoId', 'floorRaw']
376
- : isTradeSellGuard(precondition)
377
- ? ['atlasOutCapPerEpochRaw', 'epochLengthSeconds']
378
- : []),
379
- ]);
380
- const unsigned = (key, max = 65535) => {
381
- const n = precondition[key];
382
- if (typeof n !== 'number' || !Number.isInteger(n) || n < 0 || n > max)
383
- invalid(`${field}.${key}`, n, `an unsigned ${max === 255 ? 'u8' : 'u16'} integer`);
384
- return n;
385
- };
386
- const integer = (key, signed = false) => {
387
- const n = precondition[key];
388
- const min = signed ? -(1n << 63n) : 0n;
389
- const max = signed ? (1n << 63n) - 1n : (1n << 64n) - 1n;
390
- if (typeof n !== 'bigint' || n < min || n > max)
391
- invalid(`${field}.${key}`, n, signed ? 'an i64 bigint' : 'a u64 bigint');
392
- return n;
393
- };
394
- const common = {
395
- address: readAddress(precondition.address, `${field}.address`),
396
- game: readAddress(precondition.game, `${field}.game`),
397
- factionId: unsigned('factionId'),
398
- schemaVersion: unsigned('schemaVersion', 255),
399
- describes: readString(precondition.describes, `${field}.describes`),
400
- };
401
- if (isTradeBuyGuard(precondition))
402
- return Object.freeze({
403
- kind,
404
- ...common,
405
- cargoId: unsigned('cargoId'),
406
- floorRaw: integer('floorRaw'),
407
- });
408
- if (isTradeSellGuard(precondition))
409
- return Object.freeze({
410
- kind,
411
- ...common,
412
- atlasOutCapPerEpochRaw: integer('atlasOutCapPerEpochRaw'),
413
- epochLengthSeconds: integer('epochLengthSeconds', true),
414
- });
415
- return Object.freeze({ kind, ...common });
416
- }
417
- if (precondition.kind === 'fleet-add-ship') {
418
- assertKeys(precondition, field, [
419
- 'kind',
420
- 'address',
421
- 'game',
422
- 'profile',
423
- 'authority',
424
- 'system',
425
- 'shipId',
426
- 'amount',
427
- 'keyIndex',
428
- 'configHash',
429
- 'maximumProfileDebit',
430
- 'describes',
431
- ]);
432
- const keyIndex = precondition.keyIndex;
433
- if (typeof keyIndex !== 'number' ||
434
- !Number.isInteger(keyIndex) ||
435
- keyIndex < 0 ||
436
- keyIndex > 65535)
437
- invalid(`${field}.keyIndex`, keyIndex, 'an integer from 0 through 65535');
438
- const shipId = precondition.shipId;
439
- if (typeof shipId !== 'number' ||
440
- !Number.isInteger(shipId) ||
441
- shipId < 0 ||
442
- shipId > 65535)
443
- invalid(`${field}.shipId`, shipId, 'a u16 ship configuration ID');
444
- const amount = precondition.amount;
445
- if (typeof amount !== 'bigint' || amount < 1n || amount > 255n)
446
- invalid(`${field}.amount`, amount, 'a whole ship quantity from 1n through 255n');
447
- const maximumProfileDebit = precondition.maximumProfileDebit;
448
- if (typeof maximumProfileDebit !== 'bigint' || maximumProfileDebit < 0n)
449
- invalid(`${field}.maximumProfileDebit`, maximumProfileDebit, 'a nonnegative bigint');
450
- return Object.freeze({
451
- kind: 'fleet-add-ship',
452
- address: readAddress(precondition.address, `${field}.address`),
453
- game: readAddress(precondition.game, `${field}.game`),
454
- profile: readAddress(precondition.profile, `${field}.profile`),
455
- authority: readAddress(precondition.authority, `${field}.authority`),
456
- system: readAddress(precondition.system, `${field}.system`),
457
- keyIndex,
458
- shipId,
459
- amount,
460
- maximumProfileDebit,
461
- configHash: readDataHash(precondition.configHash, `${field}.configHash`),
462
- describes: readString(precondition.describes, `${field}.describes`),
463
- });
464
- }
465
- if (precondition.kind === 'scan-completion') {
466
- const addresses = [
467
- 'address',
468
- 'game',
469
- 'signal',
470
- 'profile',
471
- 'character',
472
- 'authority',
473
- 'policy',
474
- 'loot',
475
- 'xpBudget',
476
- 'xpConfig',
477
- ];
478
- assertKeys(precondition, field, [
479
- 'kind',
480
- 'operation',
481
- ...addresses,
482
- 'keyIndex',
483
- 'status',
484
- 'expectedSequence',
485
- 'configHash',
486
- 'describes',
487
- ]);
488
- if (typeof precondition.operation !== 'string' ||
489
- !Object.hasOwn(scanCompletionDiscriminators, precondition.operation))
490
- invalid(field, precondition.operation, 'a supported scan lifecycle operation');
491
- const keyIndex = precondition.keyIndex, status = precondition.status, sequence = precondition.expectedSequence;
492
- if (typeof keyIndex !== 'number' ||
493
- !Number.isInteger(keyIndex) ||
494
- keyIndex < 0 ||
495
- keyIndex > 65535)
496
- invalid(field, keyIndex, 'a u16 key index');
497
- if (typeof status !== 'number' ||
498
- !Number.isInteger(status) ||
499
- status < 1 ||
500
- status > 6)
501
- invalid(field, status, 'a current nonempty signal state');
502
- if (typeof sequence !== 'bigint' ||
503
- sequence < 0n ||
504
- sequence > 18446744073709551615n)
505
- invalid(field, sequence, 'a u64 sequence');
506
- const parsed = Object.fromEntries(addresses.map((k) => [k, readAddress(precondition[k], `${field}.${k}`)]));
507
- return Object.freeze({
508
- kind: 'scan-completion',
509
- operation: precondition.operation,
510
- ...parsed,
511
- keyIndex,
512
- status,
513
- expectedSequence: sequence,
514
- configHash: readDataHash(precondition.configHash, field),
515
- describes: readString(precondition.describes, field),
516
- });
517
- }
518
- if (precondition.kind === 'scan-detect') {
519
- assertKeys(precondition, field, [
520
- 'kind',
521
- 'address',
522
- 'game',
523
- 'profile',
524
- 'authority',
525
- 'character',
526
- 'signal',
527
- 'pattern',
528
- 'policy',
529
- 'loot',
530
- 'tracker',
531
- 'keyIndex',
532
- 'patternId',
533
- 'focus',
534
- 'expectedSequence',
535
- 'policyRevision',
536
- 'profileRevision',
537
- 'configHash',
538
- 'describes',
539
- ]);
540
- const numbers = {};
541
- for (const [key, max] of [
542
- ['keyIndex', 65535],
543
- ['patternId', 65535],
544
- ['focus', 4],
545
- ['policyRevision', 4294967295],
546
- ['profileRevision', 4294967295],
547
- ]) {
548
- const value = precondition[key];
549
- if (typeof value !== 'number' ||
550
- !Number.isInteger(value) ||
551
- value < 0 ||
552
- value > max)
553
- invalid(`${field}.${key}`, value, `an integer from zero through ${max}`);
554
- numbers[key] = value;
555
- }
556
- const sequence = precondition.expectedSequence;
557
- if (typeof sequence !== 'bigint' ||
558
- sequence < 0n ||
559
- sequence > 18446744073709551615n)
560
- invalid(`${field}.expectedSequence`, sequence, 'a u64 bigint');
561
- return Object.freeze({
562
- kind: 'scan-detect',
563
- address: readAddress(precondition.address, field),
564
- game: readAddress(precondition.game, field),
565
- profile: readAddress(precondition.profile, field),
566
- authority: readAddress(precondition.authority, field),
567
- character: readAddress(precondition.character, field),
568
- signal: readAddress(precondition.signal, field),
569
- pattern: readAddress(precondition.pattern, field),
570
- policy: readAddress(precondition.policy, field),
571
- loot: readAddress(precondition.loot, field),
572
- tracker: readAddress(precondition.tracker, field),
573
- keyIndex: numbers.keyIndex,
574
- patternId: numbers.patternId,
575
- focus: numbers.focus,
576
- policyRevision: numbers.policyRevision,
577
- profileRevision: numbers.profileRevision,
578
- expectedSequence: sequence,
579
- configHash: readDataHash(precondition.configHash, field),
580
- describes: readString(precondition.describes, field),
581
- });
582
- }
583
- if (precondition.kind === 'fleet-crew-transfer') {
584
- assertKeys(precondition, field, [
585
- 'kind',
586
- 'direction',
587
- 'address',
588
- 'game',
589
- 'profile',
590
- 'authority',
591
- 'system',
592
- 'starbasePlayer',
593
- 'keyIndex',
594
- 'count',
595
- 'systemSequenceId',
596
- 'describes',
597
- ]);
598
- for (const key of ['count', 'keyIndex']) {
599
- const n = precondition[key];
600
- if (typeof n !== 'number' ||
601
- !Number.isInteger(n) ||
602
- n < (key === 'count' ? 1 : 0) ||
603
- n > 65535)
604
- invalid(field, n, 'a positive u16 count and u16 key index');
605
- }
606
- const direction = precondition.direction, sequence = precondition.systemSequenceId;
607
- if (direction !== 'load' && direction !== 'unload')
608
- invalid(field, direction, 'load or unload');
609
- if (typeof sequence !== 'bigint' ||
610
- sequence < 0n ||
611
- sequence > (1n << 64n) - 1n)
612
- invalid(field, sequence, 'a u64 System generation');
613
- return Object.freeze({
614
- kind: 'fleet-crew-transfer',
615
- direction,
616
- address: readAddress(precondition.address, field),
617
- game: readAddress(precondition.game, field),
618
- profile: readAddress(precondition.profile, field),
619
- authority: readAddress(precondition.authority, field),
620
- system: readAddress(precondition.system, field),
621
- starbasePlayer: readAddress(precondition.starbasePlayer, field),
622
- count: precondition.count,
623
- keyIndex: precondition.keyIndex,
624
- systemSequenceId: sequence,
625
- describes: readString(precondition.describes, field),
626
- });
627
- }
628
- if (precondition.kind === 'fleet-respawn') {
629
- assertKeys(precondition, field, [
630
- 'kind',
631
- 'address',
632
- 'game',
633
- 'profile',
634
- 'authority',
635
- 'system',
636
- 'keyIndex',
637
- 'phase',
638
- 'fleetHash',
639
- 'maximumRecoveryFee',
640
- 'maximumProfileDebit',
641
- 'describes',
642
- ]);
643
- const keyIndex = precondition.keyIndex;
644
- if (typeof keyIndex !== 'number' ||
645
- !Number.isInteger(keyIndex) ||
646
- keyIndex < 0 ||
647
- keyIndex > 65535)
648
- invalid(`${field}.keyIndex`, keyIndex, 'a u16 key index');
649
- const phase = precondition.phase;
650
- if (phase !== 'start' && phase !== 'complete')
651
- invalid(`${field}.phase`, phase, 'start or complete');
652
- const maximumRecoveryFee = precondition.maximumRecoveryFee, maximumProfileDebit = precondition.maximumProfileDebit;
653
- for (const value of [maximumRecoveryFee, maximumProfileDebit])
654
- if (typeof value !== 'bigint' || value < 0n || value > (1n << 64n) - 1n)
655
- invalid(field, value, 'a nonnegative u64 funding ceiling');
656
- return Object.freeze({
657
- kind: 'fleet-respawn',
658
- address: readAddress(precondition.address, field),
659
- game: readAddress(precondition.game, field),
660
- profile: readAddress(precondition.profile, field),
661
- authority: readAddress(precondition.authority, field),
662
- system: readAddress(precondition.system, field),
663
- keyIndex,
664
- phase,
665
- fleetHash: readDataHash(precondition.fleetHash, field),
666
- maximumRecoveryFee: maximumRecoveryFee,
667
- maximumProfileDebit: maximumProfileDebit,
668
- describes: readString(precondition.describes, field),
669
- });
670
- }
671
- if (precondition.kind === 'fleet-dock-funding')
672
- return normalizeFleetDockFundingGuard(precondition);
673
- if (precondition.kind === 'local-market-order')
674
- return normalizeLocalMarketOrderGuard(precondition);
675
- if (precondition.kind === 'scan-signal-open') {
676
- assertKeys(precondition, field, [
677
- 'kind',
678
- 'address',
679
- 'game',
680
- 'fleet',
681
- 'profile',
682
- 'authority',
683
- 'character',
684
- 'keyIndex',
685
- 'authorityHash',
686
- 'maximumProfileDebit',
687
- 'describes',
688
- ]);
689
- const keyIndex = precondition.keyIndex;
690
- if (typeof keyIndex !== 'number' ||
691
- !Number.isInteger(keyIndex) ||
692
- keyIndex < 0 ||
693
- keyIndex > 65535)
694
- invalid(field, keyIndex, 'a u16 key index');
695
- const maximumProfileDebit = precondition.maximumProfileDebit;
696
- if (typeof maximumProfileDebit !== 'bigint' ||
697
- maximumProfileDebit < 0n ||
698
- maximumProfileDebit > 0xffffffffffffffffn)
699
- invalid(field, maximumProfileDebit, 'a nonnegative u64 funding ceiling');
700
- return Object.freeze({
701
- kind: 'scan-signal-open',
702
- authorityHash: readDataHash(precondition.authorityHash, field),
703
- address: readAddress(precondition.address, field),
704
- game: readAddress(precondition.game, field),
705
- fleet: readAddress(precondition.fleet, field),
706
- profile: readAddress(precondition.profile, field),
707
- authority: readAddress(precondition.authority, field),
708
- character: readAddress(precondition.character, field),
709
- keyIndex,
710
- maximumProfileDebit,
711
- describes: readString(precondition.describes, field),
712
- });
713
- }
714
- if (precondition.kind === 'fleet-create') {
715
- assertKeys(precondition, field, [
716
- 'kind',
717
- 'address',
718
- 'game',
719
- 'profile',
720
- 'authority',
721
- 'system',
722
- 'keyIndex',
723
- 'label',
724
- 'maximumProfileDebit',
725
- 'describes',
726
- ]);
727
- const keyIndex = precondition.keyIndex;
728
- if (typeof keyIndex !== 'number' ||
729
- !Number.isSafeInteger(keyIndex) ||
730
- keyIndex < 0 ||
731
- keyIndex > 65_535)
732
- invalid(`${field}.keyIndex`, keyIndex, 'an integer from 0 through 65535');
733
- const label = readString(precondition.label, `${field}.label`);
734
- const bytes = new TextEncoder().encode(label);
735
- if (label.trim().length === 0 ||
736
- label.includes('\0') ||
737
- bytes.length > 64 ||
738
- new TextDecoder('utf-8', { ignoreBOM: true }).decode(bytes) !== label)
739
- invalid(`${field}.label`, label, 'a nonblank, NUL-free Unicode label of at most 64 UTF-8 bytes');
740
- const maximumProfileDebit = precondition.maximumProfileDebit;
741
- if (typeof maximumProfileDebit !== 'bigint' || maximumProfileDebit < 0n)
742
- invalid(`${field}.maximumProfileDebit`, maximumProfileDebit, 'a nonnegative bigint');
743
- return Object.freeze({
744
- kind: 'fleet-create',
745
- address: readAddress(precondition.address, `${field}.address`),
746
- game: readAddress(precondition.game, `${field}.game`),
747
- profile: readAddress(precondition.profile, `${field}.profile`),
748
- authority: readAddress(precondition.authority, `${field}.authority`),
749
- system: readAddress(precondition.system, `${field}.system`),
750
- keyIndex,
751
- label,
752
- maximumProfileDebit,
753
- describes: readString(precondition.describes, `${field}.describes`),
754
- });
755
- }
756
- if (precondition.kind === 'system-account-or-absent') {
757
- assertKeys(precondition, field, ['kind', 'address', 'describes']);
758
- return Object.freeze({
759
- kind: 'system-account-or-absent',
760
- address: readAddress(precondition.address, `${field}.address`),
761
- describes: readString(precondition.describes, `${field}.describes`),
762
- });
763
- }
764
- if (precondition.kind === 'recipe-state') {
765
- assertKeys(precondition, field, [
766
- 'kind',
767
- 'address',
768
- 'configHash',
769
- 'requiredUses',
770
- 'describes',
771
- ]);
772
- const requiredUses = precondition.requiredUses;
773
- if (typeof requiredUses !== 'bigint' ||
774
- requiredUses < 0n ||
775
- requiredUses > (1n << 64n) - 1n)
776
- invalid(`${field}.requiredUses`, requiredUses, 'an unsigned u64 bigint');
777
- const configHash = readDataHash(precondition.configHash, `${field}.configHash`);
778
- return Object.freeze({
779
- kind: 'recipe-state',
780
- address: readAddress(precondition.address, `${field}.address`),
781
- configHash,
782
- requiredUses,
783
- describes: readString(precondition.describes, `${field}.describes`),
784
- });
785
- }
786
- if (precondition.kind === 'token-mint') {
787
- assertKeys(precondition, field, [
788
- 'kind',
789
- 'address',
790
- 'decimals',
791
- 'describes',
792
- ]);
793
- const decimals = precondition.decimals;
794
- if (typeof decimals !== 'number' ||
795
- !Number.isInteger(decimals) ||
796
- decimals < 0 ||
797
- decimals > 255)
798
- invalid(`${field}.decimals`, decimals, 'an unsigned u8 mint decimals value');
799
- return Object.freeze({
800
- kind: 'token-mint',
801
- address: readAddress(precondition.address, `${field}.address`),
802
- decimals,
803
- describes: readString(precondition.describes, `${field}.describes`),
804
- });
805
- }
806
- if (precondition.kind === 'game-ship-config') {
807
- assertKeys(precondition, field, [
808
- 'kind',
809
- 'address',
810
- 'shipId',
811
- 'configHash',
812
- 'describes',
813
- ]);
814
- const id = precondition.shipId;
815
- if (typeof id !== 'number' || !Number.isInteger(id) || id < 0 || id > 65535)
816
- invalid(`${field}.shipId`, id, 'a u16 ship configuration ID');
817
- return Object.freeze({
818
- kind: 'game-ship-config',
819
- address: readAddress(precondition.address, `${field}.address`),
820
- shipId: id,
821
- configHash: readDataHash(precondition.configHash, `${field}.configHash`),
822
- describes: readString(precondition.describes, `${field}.describes`),
823
- });
824
- }
825
- if (precondition.kind === 'game-account') {
826
- assertKeys(precondition, field, ['kind', 'address', 'describes']);
827
- return Object.freeze({
828
- kind: 'game-account',
829
- address: readAddress(precondition.address, `${field}.address`),
830
- describes: readString(precondition.describes, `${field}.describes`),
831
- });
832
- }
833
- if (['game-cargo-bytes-config', 'token-account', 'cargo-cache'].includes(String(precondition.kind))) {
834
- const base = {
835
- address: readAddress(precondition.address, `${field}.address`),
836
- describes: readString(precondition.describes, `${field}.describes`),
837
- };
838
- if (precondition.kind === 'token-account') {
839
- assertKeys(precondition, field, [
840
- 'kind',
841
- 'address',
842
- 'mint',
843
- 'owner',
844
- 'minimumBalance',
845
- 'describes',
846
- ]);
847
- const amount = precondition.minimumBalance;
848
- if (typeof amount !== 'bigint' ||
849
- amount < 0n ||
850
- amount > (1n << 64n) - 1n)
851
- invalid(`${field}.minimumBalance`, amount, 'an unsigned u64 bigint');
852
- return Object.freeze({
853
- ...base,
854
- kind: 'token-account',
855
- mint: readAddress(precondition.mint, `${field}.mint`),
856
- owner: readAddress(precondition.owner, `${field}.owner`),
857
- minimumBalance: amount,
858
- });
859
- }
860
- if (precondition.kind === 'game-cargo-bytes-config') {
861
- assertKeys(precondition, field, [
862
- 'kind',
863
- 'address',
864
- 'cargoId',
865
- 'configHash',
866
- 'describes',
867
- ]);
868
- const id = precondition.cargoId;
869
- if (typeof id !== 'number' ||
870
- !Number.isInteger(id) ||
871
- id < 0 ||
872
- id > 65535)
873
- invalid(`${field}.cargoId`, id, 'a u16 cargo ID');
874
- return Object.freeze({
875
- ...base,
876
- kind: precondition.kind,
877
- cargoId: id,
878
- configHash: readDataHash(precondition.configHash, `${field}.configHash`),
879
- });
880
- }
881
- assertKeys(precondition, field, [
882
- 'kind',
883
- 'address',
884
- 'game',
885
- 'bump',
886
- 'describes',
887
- ]);
888
- const bump = precondition.bump;
889
- if (typeof bump !== 'number' ||
890
- !Number.isInteger(bump) ||
891
- bump < 0 ||
892
- bump > 255)
893
- invalid(`${field}.bump`, bump, 'a u8 PDA bump');
894
- return Object.freeze({
895
- ...base,
896
- kind: 'cargo-cache',
897
- game: readAddress(precondition.game, `${field}.game`),
898
- bump,
899
- });
900
- }
901
- if (precondition.kind === 'token-account-or-absent') {
902
- assertKeys(precondition, field, [
903
- 'kind',
904
- 'address',
905
- 'mint',
906
- 'owner',
907
- 'describes',
908
- ]);
909
- return Object.freeze({
910
- kind: 'token-account-or-absent',
911
- address: readAddress(precondition.address, `${field}.address`),
912
- mint: readAddress(precondition.mint, `${field}.mint`),
913
- owner: readAddress(precondition.owner, `${field}.owner`),
914
- describes: readString(precondition.describes, `${field}.describes`),
915
- });
916
- }
917
- if (precondition.kind === 'account-absent') {
918
- assertKeys(precondition, field, ['kind', 'address', 'describes']);
919
- return Object.freeze({
920
- kind: 'account-absent',
921
- address: readAddress(precondition.address, `${field}.address`),
922
- describes: readString(precondition.describes, `${field}.describes`),
923
- });
924
- }
925
- if (precondition.kind !== 'account-state') {
926
- invalid(`${field}.kind`, precondition.kind, 'a supported current Plan guard; recreate the Plan using the current capability planner');
927
- }
928
- assertKeys(precondition, field, ['kind', 'address', 'dataHash', 'describes']);
929
- return Object.freeze({
930
- kind: 'account-state',
931
- address: readAddress(precondition.address, `${field}.address`),
932
- dataHash: readDataHash(precondition.dataHash, `${field}.dataHash`),
933
- describes: readString(precondition.describes, `${field}.describes`),
934
- });
935
- }
936
148
  function getAffected(steps) {
937
149
  return uniqueAddresses(steps.flatMap((step) => (step.instruction.accounts ?? [])
938
150
  .filter((account) => isWritableRole(account.role))
@@ -973,64 +185,7 @@ function planToJSON(plan) {
973
185
  : {}),
974
186
  signers: [...step.signers],
975
187
  })),
976
- preconditions: plan.preconditions.map((guard) => {
977
- if (guard.kind === 'recipe-state')
978
- return { ...guard, requiredUses: String(guard.requiredUses) };
979
- if (guard.kind === 'scan-detect' || guard.kind === 'scan-completion')
980
- return { ...guard, expectedSequence: String(guard.expectedSequence) };
981
- if (guard.kind === 'fleet-dock-funding')
982
- return dockFundingGuardToJSON(guard);
983
- if (guard.kind === 'fleet-arrival')
984
- return arrivalGuardToJSON(guard);
985
- if (guard.kind === 'fleet-crew-transfer')
986
- return { ...guard, systemSequenceId: String(guard.systemSequenceId) };
987
- if (guard.kind === 'fleet-respawn')
988
- return {
989
- ...guard,
990
- maximumRecoveryFee: String(guard.maximumRecoveryFee),
991
- maximumProfileDebit: String(guard.maximumProfileDebit),
992
- };
993
- if (isRuntimeGuard(guard))
994
- return runtimeGuardToJSON(guard);
995
- if (isTradeBuyGuard(guard))
996
- return { ...guard, floorRaw: String(guard.floorRaw) };
997
- if (isTradeSellGuard(guard))
998
- return {
999
- ...guard,
1000
- atlasOutCapPerEpochRaw: String(guard.atlasOutCapPerEpochRaw),
1001
- epochLengthSeconds: String(guard.epochLengthSeconds),
1002
- };
1003
- if (guard.kind === 'fleet-add-ship')
1004
- return {
1005
- ...guard,
1006
- amount: String(guard.amount),
1007
- maximumProfileDebit: String(guard.maximumProfileDebit),
1008
- };
1009
- if (guard.kind === 'character-registration')
1010
- return {
1011
- ...guard,
1012
- maximumFunderDebit: String(guard.maximumFunderDebit),
1013
- characterLamports: String(guard.characterLamports),
1014
- budgetLamports: String(guard.budgetLamports),
1015
- };
1016
- if (guard.kind === 'scan-signal-open' ||
1017
- guard.kind === 'fleet-create' ||
1018
- guard.kind === 'ship-import-funding')
1019
- return {
1020
- ...guard,
1021
- maximumProfileDebit: String(guard.maximumProfileDebit),
1022
- };
1023
- if (guard.kind === 'starbase-system')
1024
- return {
1025
- ...guard,
1026
- starbaseSequenceId: String(guard.starbaseSequenceId),
1027
- };
1028
- if (guard.kind === 'local-market-order')
1029
- return localMarketOrderGuardToJSON(guard);
1030
- if (guard.kind === 'token-account')
1031
- return { ...guard, minimumBalance: String(guard.minimumBalance) };
1032
- return { ...guard };
1033
- }),
188
+ preconditions: plan.preconditions.map(guardToWire),
1034
189
  });
1035
190
  }
1036
191
  /** Creates an inert branded Plan while deriving every aggregate field.
@@ -1127,111 +282,6 @@ export function planFromJSON(json) {
1127
282
  if (value.v !== 27) {
1128
283
  throw new InvalidActionInputError('planJson.v', value.v, 'the current Plan wire version 27', 'Recreate the Plan using the current capability planner; do not change its saved version or migrate its guards.');
1129
284
  }
1130
- value.preconditions = readArray(value.preconditions, 'planJson.preconditions').map((entry) => {
1131
- const guard = readRecord(entry, 'precondition');
1132
- if (guard.kind === 'recipe-state') {
1133
- if (typeof guard.requiredUses !== 'string' ||
1134
- !/^(0|[1-9][0-9]*)$/.test(guard.requiredUses))
1135
- invalid('requiredUses', guard.requiredUses, 'a canonical unsigned decimal string');
1136
- return { ...guard, requiredUses: BigInt(guard.requiredUses) };
1137
- }
1138
- if (guard.kind === 'fleet-dock-funding')
1139
- return normalizeFleetDockFundingGuard(guard, true);
1140
- if (guard.kind === 'local-market-order')
1141
- return normalizeLocalMarketOrderGuard(guard, true);
1142
- if (guard.kind === 'scan-detect' || guard.kind === 'scan-completion') {
1143
- if (typeof guard.expectedSequence !== 'string' ||
1144
- !/^(0|[1-9][0-9]*)$/.test(guard.expectedSequence))
1145
- invalid('expectedSequence', guard.expectedSequence, 'a canonical unsigned decimal string');
1146
- return { ...guard, expectedSequence: BigInt(guard.expectedSequence) };
1147
- }
1148
- if (guard.kind === 'fleet-arrival')
1149
- return normalizeArrivalGuard(guard, 'precondition', true);
1150
- if (isRuntimeGuard(guard))
1151
- return normalizeRuntimeGuard(guard, 'precondition', true);
1152
- if (isTradeBuyGuard(guard) || isTradeSellGuard(guard)) {
1153
- const keys = isTradeBuyGuard(guard)
1154
- ? ['floorRaw']
1155
- : ['atlasOutCapPerEpochRaw', 'epochLengthSeconds'];
1156
- const decoded = { ...guard };
1157
- for (const key of keys) {
1158
- const raw = guard[key];
1159
- const pattern = key === 'epochLengthSeconds'
1160
- ? /^(0|[1-9][0-9]*|-[1-9][0-9]*)$/
1161
- : /^(0|[1-9][0-9]*)$/;
1162
- if (typeof raw !== 'string' || !pattern.test(raw))
1163
- invalid(key, raw, 'a canonical decimal string');
1164
- decoded[key] = BigInt(raw);
1165
- }
1166
- return decoded;
1167
- }
1168
- if (guard.kind === 'fleet-add-ship') {
1169
- for (const field of ['amount', 'maximumProfileDebit'])
1170
- if (typeof guard[field] !== 'string' ||
1171
- !/^(0|[1-9][0-9]*)$/.test(guard[field]))
1172
- invalid(field, guard[field], 'a canonical unsigned decimal string');
1173
- return {
1174
- ...guard,
1175
- amount: BigInt(guard.amount),
1176
- maximumProfileDebit: BigInt(guard.maximumProfileDebit),
1177
- };
1178
- }
1179
- if (guard.kind === 'character-registration') {
1180
- for (const key of ['characterLamports', 'budgetLamports'])
1181
- if (typeof guard[key] !== 'string' ||
1182
- !/^(0|[1-9][0-9]*)$/.test(guard[key]))
1183
- invalid(key, guard[key], 'a canonical unsigned decimal string');
1184
- if (typeof guard.maximumFunderDebit !== 'string' ||
1185
- !/^(0|[1-9][0-9]*)$/.test(guard.maximumFunderDebit))
1186
- invalid('maximumFunderDebit', guard.maximumFunderDebit, 'a canonical unsigned decimal string');
1187
- return {
1188
- ...guard,
1189
- maximumFunderDebit: BigInt(guard.maximumFunderDebit),
1190
- characterLamports: BigInt(guard.characterLamports),
1191
- budgetLamports: BigInt(guard.budgetLamports),
1192
- };
1193
- }
1194
- if (guard.kind === 'fleet-crew-transfer') {
1195
- if (typeof guard.systemSequenceId !== 'string' ||
1196
- !/^(0|[1-9][0-9]*)$/.test(guard.systemSequenceId))
1197
- invalid('systemSequenceId', guard.systemSequenceId, 'a canonical unsigned decimal string');
1198
- return { ...guard, systemSequenceId: BigInt(guard.systemSequenceId) };
1199
- }
1200
- if (guard.kind === 'fleet-respawn') {
1201
- for (const key of ['maximumRecoveryFee', 'maximumProfileDebit'])
1202
- if (typeof guard[key] !== 'string' ||
1203
- !/^(0|[1-9][0-9]*)$/.test(guard[key]))
1204
- invalid(key, guard[key], 'a canonical unsigned decimal string');
1205
- return {
1206
- ...guard,
1207
- maximumRecoveryFee: BigInt(guard.maximumRecoveryFee),
1208
- maximumProfileDebit: BigInt(guard.maximumProfileDebit),
1209
- };
1210
- }
1211
- if (guard.kind === 'scan-signal-open' ||
1212
- guard.kind === 'fleet-create' ||
1213
- guard.kind === 'ship-import-funding') {
1214
- if (typeof guard.maximumProfileDebit !== 'string' ||
1215
- !/^(0|[1-9][0-9]*)$/.test(guard.maximumProfileDebit))
1216
- invalid('maximumProfileDebit', guard.maximumProfileDebit, 'a canonical unsigned decimal string');
1217
- return {
1218
- ...guard,
1219
- maximumProfileDebit: BigInt(guard.maximumProfileDebit),
1220
- };
1221
- }
1222
- if (guard.kind === 'starbase-system') {
1223
- if (typeof guard.starbaseSequenceId !== 'string' ||
1224
- !/^(0|[1-9][0-9]*)$/.test(guard.starbaseSequenceId))
1225
- invalid('starbaseSequenceId', guard.starbaseSequenceId, 'a canonical unsigned decimal string');
1226
- return { ...guard, starbaseSequenceId: BigInt(guard.starbaseSequenceId) };
1227
- }
1228
- if (guard.kind !== 'token-account')
1229
- return guard;
1230
- if (typeof guard.minimumBalance !== 'string' ||
1231
- !/^(0|[1-9][0-9]*)$/.test(guard.minimumBalance))
1232
- invalid('minimumBalance', guard.minimumBalance, 'a canonical unsigned decimal string');
1233
- return { ...guard, minimumBalance: BigInt(guard.minimumBalance) };
1234
- });
1235
285
  const steps = readArray(value.steps, 'planJson.steps').map((candidate, index) => {
1236
286
  const field = `planJson.steps[${String(index)}]`;
1237
287
  const step = readRecord(candidate, field);
@@ -1247,7 +297,7 @@ export function planFromJSON(json) {
1247
297
  signers: readArray(step.signers, `${field}.signers`).map((signer, signerIndex) => readAddress(signer, `${field}.signers[${String(signerIndex)}]`)),
1248
298
  };
1249
299
  });
1250
- const preconditions = readArray(value.preconditions, 'planJson.preconditions').map((candidate, index) => normalizePrecondition(candidate, `planJson.preconditions[${String(index)}]`));
300
+ const preconditions = readArray(value.preconditions, 'planJson.preconditions').map((candidate, index) => normalizePrecondition(candidate, `planJson.preconditions[${String(index)}]`, true));
1251
301
  const affected = readArray(value.affected, 'planJson.affected').map((candidate, index) => readAddress(candidate, `planJson.affected[${String(index)}]`));
1252
302
  const requiredSigners = readArray(value.requiredSigners, 'planJson.requiredSigners').map((candidate, index) => readAddress(candidate, `planJson.requiredSigners[${String(index)}]`));
1253
303
  const plan = createPlan({