@crediolabs/policy-builder-cli 0.1.7 → 0.1.8

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.
@@ -14,6 +14,7 @@
14
14
  // [--oracle-max-staleness <s>] [--oracle-max-deviation <bps>]
15
15
  // [--window-seconds <n>] [--valid-until <ledger>]
16
16
  // [--limit-amount <i128str>] [--invocation-limit <n>]
17
+ // [--recipient <C...|G...>]...
17
18
  // [--json] [--quiet] [--out <path>]
18
19
  //
19
20
  // The router is hand-rolled (no commander / yargs dep). It splits argv into
@@ -73,6 +74,7 @@ Usage:
73
74
  [--oracle-max-staleness <s>] [--oracle-max-deviation <bps>]
74
75
  [--window-seconds <n>] [--valid-until <ledger>]
75
76
  [--limit-amount <i128str>] [--invocation-limit <n>]
77
+ [--recipient <C...|G...>]...
76
78
  [--json] [--quiet] [--out <path>]
77
79
 
78
80
  Flags:
@@ -108,6 +110,10 @@ Flags:
108
110
  from --responses
109
111
  --invocation-limit per-field override of userResponses.invocationLimit;
110
112
  overrides the same field from --responses
113
+ --recipient swap-recipient allowlist entry (C... contract or
114
+ G... wallet) for a SoroSwap swap; REPEATABLE. Absent,
115
+ the recorded recipient is pinned by default; supplying
116
+ --recipient REPLACES that pin with the given set
111
117
  `);
112
118
  }
113
119
  await main();
@@ -1,3 +1,3 @@
1
- import type { ProposedPolicy } from '@crediolabs/policy-synth';
1
+ import { type ProposedPolicy } from '@crediolabs/policy-synth';
2
2
  import { type CliFlags } from '../output.ts';
3
3
  export declare function runSynthesizeCommand(argv: ReadonlyArray<string>, flags: CliFlags): Promise<ProposedPolicy>;
@@ -14,6 +14,7 @@
14
14
  // Oracle params (--oracle-max-staleness, --oracle-max-deviation) are part of
15
15
  // the interpreter opt-in and are rejected without --smart-account; tighten-only
16
16
  // bounds are validated by the core.
17
+ import { isStellarAddress } from '@crediolabs/policy-synth';
17
18
  import { runSynthesizePolicy } from '@crediolabs/policy-synth/run';
18
19
  import { CliError, formatToolResponse, parsePairs, readJsonFile } from "../output.js";
19
20
  // Positive-int flags and i128 amount strings share the same wire shape: a
@@ -91,6 +92,26 @@ export async function runSynthesizeCommand(argv, flags) {
91
92
  if (pairs['invocation-limit'] !== undefined) {
92
93
  userResponses.invocationLimit = parsePositiveInt(pairs['invocation-limit'], '--invocation-limit');
93
94
  }
95
+ // --recipient <C...|G...> is REPEATABLE (parsePairs collapses duplicate keys,
96
+ // so it is collected straight from argv). Each value builds the swap-recipient
97
+ // allowlist; supplying it REPLACES the default pin to the recorded recipient.
98
+ const recipients = collectRepeated(argv, 'recipient');
99
+ if (recipients.length > 0) {
100
+ for (const r of recipients) {
101
+ // Same validator the run-layer schema applies (SDK StrKey underneath) - a
102
+ // swap recipient may be a G... wallet or a C... contract. Shared rather
103
+ // than re-inlined so the CLI and the schema cannot drift apart.
104
+ if (!isStellarAddress(r)) {
105
+ throw new CliError({
106
+ code: 'CLI_MISSING_ARG',
107
+ message: `synthesize: --recipient "${r}" is not a valid Stellar address (expected a G... wallet or C... contract)`,
108
+ severity: 'error',
109
+ retryable: false,
110
+ });
111
+ }
112
+ }
113
+ userResponses.swapRecipientAllowlist = recipients;
114
+ }
94
115
  if (Object.keys(userResponses).length > 0) {
95
116
  args.userResponses = userResponses;
96
117
  }
@@ -234,6 +255,29 @@ function parsePositiveInt(raw, flagName) {
234
255
  }
235
256
  return n;
236
257
  }
258
+ /** Collect ALL values for a repeatable `--<name> <value>` / `--<name>=<value>`
259
+ * flag from argv, in order. Unlike `parsePairs` (which keeps only the last
260
+ * occurrence of a key), this preserves every occurrence so a flag like
261
+ * `--recipient` can be supplied multiple times to build an allowlist. A
262
+ * trailing `--<name>` with no value (or another flag next) is skipped. */
263
+ function collectRepeated(argv, name) {
264
+ const out = [];
265
+ const eqPrefix = `--${name}=`;
266
+ for (let i = 0; i < argv.length; i++) {
267
+ const a = argv[i];
268
+ if (a === `--${name}`) {
269
+ const next = argv[i + 1];
270
+ if (next !== undefined && !next.startsWith('--')) {
271
+ out.push(next);
272
+ i++;
273
+ }
274
+ }
275
+ else if (a?.startsWith(eqPrefix)) {
276
+ out.push(a.slice(eqPrefix.length));
277
+ }
278
+ }
279
+ return out;
280
+ }
237
281
  /** Parse an i128 decimal string (positive, base 10). The synth gate, not the
238
282
  * CLI, decides what to do with negatives - real recordings carry positive
239
283
  * amounts on the wire for `limitAmount`. */
@@ -1,3 +1,3 @@
1
- import type { ProposedPolicy } from '@crediolabs/policy-synth';
1
+ import { type ProposedPolicy } from '@crediolabs/policy-synth';
2
2
  import { type CliFlags } from '../output.ts';
3
3
  export declare function runSynthesizeCommand(argv: ReadonlyArray<string>, flags: CliFlags): Promise<ProposedPolicy>;
@@ -17,6 +17,7 @@
17
17
  // bounds are validated by the core.
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.runSynthesizeCommand = runSynthesizeCommand;
20
+ const policy_synth_1 = require("@crediolabs/policy-synth");
20
21
  const run_1 = require("@crediolabs/policy-synth/run");
21
22
  const output_ts_1 = require("../output.js");
22
23
  // Positive-int flags and i128 amount strings share the same wire shape: a
@@ -94,6 +95,26 @@ async function runSynthesizeCommand(argv, flags) {
94
95
  if (pairs['invocation-limit'] !== undefined) {
95
96
  userResponses.invocationLimit = parsePositiveInt(pairs['invocation-limit'], '--invocation-limit');
96
97
  }
98
+ // --recipient <C...|G...> is REPEATABLE (parsePairs collapses duplicate keys,
99
+ // so it is collected straight from argv). Each value builds the swap-recipient
100
+ // allowlist; supplying it REPLACES the default pin to the recorded recipient.
101
+ const recipients = collectRepeated(argv, 'recipient');
102
+ if (recipients.length > 0) {
103
+ for (const r of recipients) {
104
+ // Same validator the run-layer schema applies (SDK StrKey underneath) - a
105
+ // swap recipient may be a G... wallet or a C... contract. Shared rather
106
+ // than re-inlined so the CLI and the schema cannot drift apart.
107
+ if (!(0, policy_synth_1.isStellarAddress)(r)) {
108
+ throw new output_ts_1.CliError({
109
+ code: 'CLI_MISSING_ARG',
110
+ message: `synthesize: --recipient "${r}" is not a valid Stellar address (expected a G... wallet or C... contract)`,
111
+ severity: 'error',
112
+ retryable: false,
113
+ });
114
+ }
115
+ }
116
+ userResponses.swapRecipientAllowlist = recipients;
117
+ }
97
118
  if (Object.keys(userResponses).length > 0) {
98
119
  args.userResponses = userResponses;
99
120
  }
@@ -237,6 +258,29 @@ function parsePositiveInt(raw, flagName) {
237
258
  }
238
259
  return n;
239
260
  }
261
+ /** Collect ALL values for a repeatable `--<name> <value>` / `--<name>=<value>`
262
+ * flag from argv, in order. Unlike `parsePairs` (which keeps only the last
263
+ * occurrence of a key), this preserves every occurrence so a flag like
264
+ * `--recipient` can be supplied multiple times to build an allowlist. A
265
+ * trailing `--<name>` with no value (or another flag next) is skipped. */
266
+ function collectRepeated(argv, name) {
267
+ const out = [];
268
+ const eqPrefix = `--${name}=`;
269
+ for (let i = 0; i < argv.length; i++) {
270
+ const a = argv[i];
271
+ if (a === `--${name}`) {
272
+ const next = argv[i + 1];
273
+ if (next !== undefined && !next.startsWith('--')) {
274
+ out.push(next);
275
+ i++;
276
+ }
277
+ }
278
+ else if (a?.startsWith(eqPrefix)) {
279
+ out.push(a.slice(eqPrefix.length));
280
+ }
281
+ }
282
+ return out;
283
+ }
240
284
  /** Parse an i128 decimal string (positive, base 10). The synth gate, not the
241
285
  * CLI, decides what to do with negatives - real recordings carry positive
242
286
  * amounts on the wire for `limitAmount`. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crediolabs/policy-builder-cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "license": "MIT",
5
5
  "description": "CLI wrapper around the OZ policy-synth core (record + synthesize) for solo-dev and CI workflows.",
6
6
  "type": "module",
@@ -63,7 +63,7 @@
63
63
  "prepack": "bun run build"
64
64
  },
65
65
  "dependencies": {
66
- "@crediolabs/policy-synth": "0.1.5",
66
+ "@crediolabs/policy-synth": "0.1.6",
67
67
  "zod": "3.25.76"
68
68
  },
69
69
  "devDependencies": {
@@ -15,7 +15,7 @@
15
15
  // the interpreter opt-in and are rejected without --smart-account; tighten-only
16
16
  // bounds are validated by the core.
17
17
 
18
- import type { ProposedPolicy } from '@crediolabs/policy-synth'
18
+ import { isStellarAddress, type ProposedPolicy } from '@crediolabs/policy-synth'
19
19
  import { runSynthesizePolicy } from '@crediolabs/policy-synth/run'
20
20
  import { CliError, type CliFlags, formatToolResponse, parsePairs, readJsonFile } from '../output.ts'
21
21
 
@@ -110,6 +110,26 @@ export async function runSynthesizeCommand(
110
110
  '--invocation-limit'
111
111
  )
112
112
  }
113
+ // --recipient <C...|G...> is REPEATABLE (parsePairs collapses duplicate keys,
114
+ // so it is collected straight from argv). Each value builds the swap-recipient
115
+ // allowlist; supplying it REPLACES the default pin to the recorded recipient.
116
+ const recipients = collectRepeated(argv, 'recipient')
117
+ if (recipients.length > 0) {
118
+ for (const r of recipients) {
119
+ // Same validator the run-layer schema applies (SDK StrKey underneath) - a
120
+ // swap recipient may be a G... wallet or a C... contract. Shared rather
121
+ // than re-inlined so the CLI and the schema cannot drift apart.
122
+ if (!isStellarAddress(r)) {
123
+ throw new CliError({
124
+ code: 'CLI_MISSING_ARG',
125
+ message: `synthesize: --recipient "${r}" is not a valid Stellar address (expected a G... wallet or C... contract)`,
126
+ severity: 'error',
127
+ retryable: false,
128
+ })
129
+ }
130
+ }
131
+ userResponses.swapRecipientAllowlist = recipients
132
+ }
113
133
  if (Object.keys(userResponses).length > 0) {
114
134
  args.userResponses = userResponses
115
135
  }
@@ -269,6 +289,29 @@ function parsePositiveInt(raw: string, flagName: string): number {
269
289
  return n
270
290
  }
271
291
 
292
+ /** Collect ALL values for a repeatable `--<name> <value>` / `--<name>=<value>`
293
+ * flag from argv, in order. Unlike `parsePairs` (which keeps only the last
294
+ * occurrence of a key), this preserves every occurrence so a flag like
295
+ * `--recipient` can be supplied multiple times to build an allowlist. A
296
+ * trailing `--<name>` with no value (or another flag next) is skipped. */
297
+ function collectRepeated(argv: ReadonlyArray<string>, name: string): string[] {
298
+ const out: string[] = []
299
+ const eqPrefix = `--${name}=`
300
+ for (let i = 0; i < argv.length; i++) {
301
+ const a = argv[i]
302
+ if (a === `--${name}`) {
303
+ const next = argv[i + 1]
304
+ if (next !== undefined && !next.startsWith('--')) {
305
+ out.push(next)
306
+ i++
307
+ }
308
+ } else if (a?.startsWith(eqPrefix)) {
309
+ out.push(a.slice(eqPrefix.length))
310
+ }
311
+ }
312
+ return out
313
+ }
314
+
272
315
  /** Parse an i128 decimal string (positive, base 10). The synth gate, not the
273
316
  * CLI, decides what to do with negatives - real recordings carry positive
274
317
  * amounts on the wire for `limitAmount`. */